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:
1 parent
aad0a8b807
commit
d96d09f589
2 files changed
+21
-5
No files matched your search
@@ -197,10 +197,14 @@ function assertAddressForSend(customer, totalCents) {
|
|||||||
if (!complete && totalCents > SMALL_INVOICE_MAX_CENTS) throw httpError(409, ADDRESS_INCOMPLETE_MESSAGE)
|
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() : ''
|
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
|
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 && !String(customer.email || '').trim()) throw httpError(400, NO_EMAIL_MESSAGE)
|
||||||
if (senden) assertAddressForSend(customer, entwurf.summeCents)
|
if (senden) assertAddressForSend(customer, entwurf.summeCents)
|
||||||
|
|
||||||
const { bankDetailsText } = await getSettings()
|
const { bankDetailsText, steuernummer } = await getSettings()
|
||||||
const stripe = getStripe()
|
const stripe = getStripe()
|
||||||
const stripeCustomerId = await getOrCreateStripeCustomer(customer)
|
const stripeCustomerId = await getOrCreateStripeCustomer(customer)
|
||||||
// Vor dem ersten Rechnungsaufruf: scheitert das, gibt es keine halbfertige Rechnung
|
// 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,
|
auto_advance: false,
|
||||||
pending_invoice_items_behavior: 'exclude',
|
pending_invoice_items_behavior: 'exclude',
|
||||||
currency: 'eur',
|
currency: 'eur',
|
||||||
footer: invoiceFooter(bankDetailsText),
|
footer: invoiceFooter(bankDetailsText, steuernummer),
|
||||||
description: note || undefined,
|
description: note || undefined,
|
||||||
metadata: entwurf.metadata,
|
metadata: entwurf.metadata,
|
||||||
custom_fields: entwurf.customFields.length ? entwurf.customFields : undefined,
|
custom_fields: entwurf.customFields.length ? entwurf.customFields : undefined,
|
||||||
|
|||||||
@@ -604,6 +604,18 @@ test('Rechnung: ohne Einstellungsdokument nur Kleinunternehmer-Hinweis und Verwe
|
|||||||
assert.equal(aw.docs(SETTINGS()).size, 0)
|
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 () => {
|
test('Rechnung: sind die Einstellungen nicht lesbar, scheitert sie vor jedem Stripe-Aufruf', async () => {
|
||||||
aw.failNext({ collection: SETTINGS(), method: 'GET', status: 500 })
|
aw.failNext({ collection: SETTINGS(), method: 'GET', status: 500 })
|
||||||
await assert.rejects(createProjectInvoice({ customerId: 'c1', items: ITEMS, createdBy: 'k' }))
|
await assert.rejects(createProjectInvoice({ customerId: 'c1', items: ITEMS, createdBy: 'k' }))
|
||||||
|
|||||||
Reference in new issue
Block a user