Kontrolle: Steuernummer steht im Rechnungsfuss der Projektrechnungen

Die Steuernummer aus den Finanz-Einstellungen kommt als Zeile direkt nach dem
§ 19-Satz in den Fuss; ohne Wert bleibt der Fuss unveraendert.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-07 15:15:56 +00:00
1 parent aad0a8b807
commit d96d09f589
2 files changed
+21 -5

No files matched your search

+9 -5
View File
@@ -197,10 +197,14 @@ function assertAddressForSend(customer, totalCents) {
if (!complete && totalCents > SMALL_INVOICE_MAX_CENTS) throw httpError(409, ADDRESS_INCOMPLETE_MESSAGE)
}
/** Rechnungsfuss: Kleinunternehmer-Hinweis, Bankdaten (falls gesetzt), Hinweis auf den Verwendungszweck. */
export function invoiceFooter(bankDetailsText = '') {
/**
* Rechnungsfuss: Kleinunternehmer-Hinweis, Steuernummer (falls gesetzt, § 34a UStDV), Bankdaten (falls gesetzt), Hinweis
* auf den Verwendungszweck.
*/
export function invoiceFooter(bankDetailsText = '', steuernummer = '') {
const bank = typeof bankDetailsText === 'string' ? bankDetailsText.trim() : ''
return [config.stripe.invoiceFooter, bank, PAYMENT_REFERENCE_NOTE].filter(Boolean).join('\n')
const nummer = typeof steuernummer === 'string' ? steuernummer.trim() : ''
return [config.stripe.invoiceFooter, nummer ? `Steuernummer: ${nummer}` : '', bank, PAYMENT_REFERENCE_NOTE].filter(Boolean).join('\n')
}
const isWholeNumberBetween = (value, min, max) => Number.isInteger(value) && value >= min && value <= max
@@ -382,7 +386,7 @@ async function createInvoice({ eingabe, daysUntilDue, note, senden, key }) {
if (senden && !String(customer.email || '').trim()) throw httpError(400, NO_EMAIL_MESSAGE)
if (senden) assertAddressForSend(customer, entwurf.summeCents)
const { bankDetailsText } = await getSettings()
const { bankDetailsText, steuernummer } = await getSettings()
const stripe = getStripe()
const stripeCustomerId = await getOrCreateStripeCustomer(customer)
// Vor dem ersten Rechnungsaufruf: scheitert das, gibt es keine halbfertige Rechnung
@@ -397,7 +401,7 @@ async function createInvoice({ eingabe, daysUntilDue, note, senden, key }) {
auto_advance: false,
pending_invoice_items_behavior: 'exclude',
currency: 'eur',
footer: invoiceFooter(bankDetailsText),
footer: invoiceFooter(bankDetailsText, steuernummer),
description: note || undefined,
metadata: entwurf.metadata,
custom_fields: entwurf.customFields.length ? entwurf.customFields : undefined,
+12
View File
@@ -604,6 +604,18 @@ test('Rechnung: ohne Einstellungsdokument nur Kleinunternehmer-Hinweis und Verwe
assert.equal(aw.docs(SETTINGS()).size, 0)
})
test('Rechnung: mit gesetzter Steuernummer steht sie als Zeile direkt nach dem § 19-Satz im Rechnungsfuss, ohne Wert bleibt der Fuss unveraendert', async () => {
assert.equal((await patchSettings({ steuernummer: '123/456/78901', bankDetailsText: 'IBAN DE00 0000' })).status, 200)
await createProjectInvoice({ customerId: 'c1', items: ITEMS, createdBy: 'kenso@example.invalid' })
assert.equal(footerOfLastDraft(), `${config.stripe.invoiceFooter}\nSteuernummer: 123/456/78901\nIBAN DE00 0000\n${PAYMENT_NOTE}`)
// geloescht: wieder wie vorher
assert.equal((await patchSettings({ steuernummer: '', bankDetailsText: '' })).status, 200)
resetInvoiceCreateGuardForTests()
await createProjectInvoice({ customerId: 'c1', items: ITEMS, createdBy: 'kenso@example.invalid' })
assert.equal(footerOfLastDraft(), `${config.stripe.invoiceFooter}\n${PAYMENT_NOTE}`)
})
test('Rechnung: sind die Einstellungen nicht lesbar, scheitert sie vor jedem Stripe-Aufruf', async () => {
aw.failNext({ collection: SETTINGS(), method: 'GET', status: 500 })
await assert.rejects(createProjectInvoice({ customerId: 'c1', items: ITEMS, createdBy: 'k' }))