Finanzen: Stripe-Kunde vor der Rechnung auf die aktuellen Kundendaten bringen
Ein wiederverwendeter Stripe-Kunde (ueber das Abo oder die Metadaten gefunden) trug noch die alte E-Mail und Anschrift, die Stripe auf die Rechnung schreibt (Empfaengeranschrift, § 14 Abs. 4 Nr. 1 UStG). createProjectInvoice aktualisiert ihn jetzt nach getOrCreateStripeCustomer und vor dem ersten Rechnungsaufruf mit E-Mail, Name (Firma vor Name) und Anschrift (Land DE, wenn keine zweistellige Angabe). Scheitert das, entsteht keine Rechnung: 502 "Kundendaten konnten nicht an Stripe uebertragen werden." ohne invoiceId. Die Felder baut stripeCustomerFields fuer das Anlegen und das Aktualisieren gemeinsam. Der Stripe-Nachbau kennt POST /v1/customers/:id. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5ed4fbd188
commit
73811e0300
4 files changed
+142
-12
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import { createHash } from 'node:crypto'
|
||||
import { config } from '../../config.js'
|
||||
import { getStripe, getOrCreateStripeCustomer, subscriptionIdOfInvoice } from '../stripeBilling.js'
|
||||
import { getStripe, getOrCreateStripeCustomer, stripeCustomerFields, subscriptionIdOfInvoice } from '../stripeBilling.js'
|
||||
import { getDocument } from '../appwriteAdmin.js'
|
||||
import { addDays, berlinDate, daysBetween } from './dates.js'
|
||||
import { getSettings } from './settings.js'
|
||||
@@ -156,6 +156,26 @@ export class InvoiceError extends Error {
|
||||
|
||||
const httpError = (status, message) => new InvoiceError(status, message)
|
||||
|
||||
const CUSTOMER_SYNC_MESSAGE = 'Kundendaten konnten nicht an Stripe übertragen werden.'
|
||||
|
||||
/**
|
||||
* Den Stripe-Kunden auf den Stand der WOMS-Kundendaten bringen (E-Mail, Name, Anschrift), bevor eine Rechnung entsteht:
|
||||
* ein frueher angelegter oder ueber die Metadaten gefundener Stripe-Kunde traegt sonst noch die alte E-Mail und
|
||||
* Anschrift, und Stripe schreibt beides auf die Rechnung (Empfaengeranschrift, § 14 Abs. 4 Nr. 1 UStG). Scheitert
|
||||
* das, entsteht keine Rechnung: status 502 mit fester Meldung (die Ursache bleibt als cause fuers Protokoll).
|
||||
*/
|
||||
async function syncStripeCustomer(stripe, stripeCustomerId, customer) {
|
||||
const fields = stripeCustomerFields(customer)
|
||||
if (!fields.email && !fields.name && !fields.address) return
|
||||
try {
|
||||
await stripe.customers.update(stripeCustomerId, fields)
|
||||
} catch (cause) {
|
||||
const err = httpError(502, CUSTOMER_SYNC_MESSAGE)
|
||||
err.cause = cause
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
/** Rechnungsfuss: Kleinunternehmer-Hinweis, Bankdaten (falls gesetzt), Hinweis auf den Verwendungszweck. */
|
||||
export function invoiceFooter(bankDetailsText = '') {
|
||||
const bank = typeof bankDetailsText === 'string' ? bankDetailsText.trim() : ''
|
||||
@@ -278,7 +298,9 @@ function validateIdempotencyKey(key) {
|
||||
* settings.js). Mit senden=true wird sie sofort finalisiert und per E-Mail gesendet (offen), sonst bleibt sie ein
|
||||
* Entwurf. Fehler mit status 400 bei ungueltigen Eingaben (auch Summe ueber 99.999.999 Cent), einem Kunden, der noch
|
||||
* Lead/verloren ist, oder fehlender E-Mail-Adresse bei senden=true (alles vor dem ersten Stripe-Aufruf, ebenso ein
|
||||
* Fehler beim Lesen der Einstellungen). Scheitert nur das Senden nach dem Festschreiben: status 502 mit invoiceId und
|
||||
* Fehler beim Lesen der Einstellungen). Vor der Rechnung wird der Stripe-Kunde (auch ein schon bestehender) auf die
|
||||
* aktuellen WOMS-Kundendaten gebracht (E-Mail, Name, Anschrift); scheitert das: status 502 „Kundendaten konnten nicht
|
||||
* an Stripe übertragen werden.“ ohne invoiceId, es entsteht keine Rechnung. Scheitert nur das Senden nach dem Festschreiben: status 502 mit invoiceId und
|
||||
* invoiceNumber (die offene Rechnung bleibt, erneut senden mit sendInvoiceNow); ebenso, wenn die fertige Rechnung nicht
|
||||
* mehr gelesen werden kann (sie besteht dann trotzdem).
|
||||
*
|
||||
@@ -326,6 +348,8 @@ async function createInvoice({ customerId, lines, daysUntilDue, note, senden, ke
|
||||
const { bankDetailsText } = await getSettings()
|
||||
const stripe = getStripe()
|
||||
const stripeCustomerId = await getOrCreateStripeCustomer(customer)
|
||||
// Vor dem ersten Rechnungsaufruf: scheitert das, gibt es keine halbfertige Rechnung
|
||||
await syncStripeCustomer(stripe, stripeCustomerId, customer)
|
||||
let invoiceId = null
|
||||
try {
|
||||
const draft = await stripe.invoices.create(
|
||||
|
||||
Reference in new issue
Block a user