Kontrolle: Anzahlung und Schlussrechnung nehmen das Zahlungsziel der AB
Ohne daysUntilDue gilt bei Anzahlung und Schluss auftrag.zahlungszielTage (Route und createProjectInvoice), sonst weiterhin 14 Tage; eine Angabe gilt vor der AB. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d96d09f589
commit
57d1ab82c6
4 files changed
+73
-6
No files matched your search
@@ -0,0 +1,52 @@
|
||||
// Schlusskontrolle (Z3.4): Korrekturen an Projektrechnungen zu Auftragsbestaetigungen
|
||||
import { test, after, beforeEach } from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { startAppwriteMock } from './support/appwriteMock.js'
|
||||
import { startFakeStripe } from './support/fakeStripe.js'
|
||||
import { schemaKeys } from './support/schema.js'
|
||||
import { useTestEnv } from './support/testEnv.js'
|
||||
import { AUFTRAEGE_DATETIMES } from '../server/services/auftraege/schema.js'
|
||||
|
||||
const aw = await startAppwriteMock({
|
||||
schema: { auftraege: schemaKeys('auftraege'), projektRechnungen: schemaKeys('projektRechnungen') },
|
||||
datetimes: AUFTRAEGE_DATETIMES,
|
||||
defaultLimit: 25,
|
||||
})
|
||||
const st = await startFakeStripe()
|
||||
useTestEnv({ appwriteUrl: aw.url, stripeUrl: st.url })
|
||||
const { config } = await import('../server/config.js')
|
||||
const { seedRechnungsDaten, legeAuftragAn, leereRechnungsDaten } = await import('./auftraegeRechnungenHilfe.js')
|
||||
const { createProjectInvoice, sendInvoiceNow, voidInvoice, deleteDraft, invalidateFinanceCache, resetInvoiceCreateGuardForTests } = await import('../server/services/finance/stripeFinance.js')
|
||||
const { getAuftrag, updateAuftrag } = await import('../server/services/auftraege/auftragStore.js')
|
||||
const { umhaengen } = await import('../server/services/auftraege/projektRechnungenStore.js')
|
||||
|
||||
after(() => Promise.all([aw.close(), st.close()]))
|
||||
seedRechnungsDaten(aw)
|
||||
config.auftraege.mode = 'on'
|
||||
beforeEach(async () => {
|
||||
await leereRechnungsDaten(aw, st)
|
||||
invalidateFinanceCache()
|
||||
resetInvoiceCreateGuardForTests()
|
||||
})
|
||||
|
||||
const letzterEntwurf = () => st.calls.filter((c) => c.method === 'POST' && c.path === '/v1/invoices').at(-1)
|
||||
const anzahlung = (ab, prozent, extra = {}) =>
|
||||
createProjectInvoice({ customerId: 'k1', art: 'anzahlung', auftragId: ab.id, projektId: 'p1', anzahlung: { prozent, bezeichnung: `Anzahlung ${prozent}` }, ...extra })
|
||||
const schluss = (ab, extra = {}) => createProjectInvoice({ customerId: 'k1', art: 'schluss', auftragId: ab.id, projektId: 'p1', ...extra })
|
||||
|
||||
test('Zahlungsziel: Anzahlung und Schluss ohne eigene Angabe nehmen das Zahlungsziel der AB, eine Angabe gilt vor der AB', async () => {
|
||||
const ab = await legeAuftragAn({ zahlungszielTage: 30 })
|
||||
await anzahlung(ab, 50, { senden: true })
|
||||
assert.equal(letzterEntwurf().body.days_until_due, '30')
|
||||
await schluss(ab)
|
||||
assert.equal(letzterEntwurf().body.days_until_due, '30')
|
||||
const ab2 = await legeAuftragAn({ zahlungszielTage: 30, projektId: 'p3' }, { nummer: 'AB-2026-0003', laufnummer: 3 })
|
||||
await createProjectInvoice({ customerId: 'k1', art: 'anzahlung', auftragId: ab2.id, projektId: 'p3', anzahlung: { prozent: 50 }, daysUntilDue: 7 })
|
||||
assert.equal(letzterEntwurf().body.days_until_due, '7')
|
||||
})
|
||||
|
||||
test('Zahlungsziel: ohne AB-Bezug (frei, festbetrag) bleibt es bei 14 Tagen', async () => {
|
||||
await legeAuftragAn({ zahlungszielTage: 30 })
|
||||
await createProjectInvoice({ customerId: 'k1', items: [{ description: 'Domain', quantity: 1, unitAmountCents: 1200 }] })
|
||||
assert.equal(letzterEntwurf().body.days_until_due, '14')
|
||||
})
|
||||
@@ -125,3 +125,14 @@ test('Rechte: ohne Anmeldung 401, Mitarbeiter ohne Admin-Label 403; GET /rechnun
|
||||
const felder = (r) => [r.art, r.projektId, r.projektName, r.auftragId, r.auftragNummer]
|
||||
assert.deepEqual(liste.map(felder).sort(), [['festbetrag', 'p1', 'Website anelia-wolf.com', '', ''], ['frei', '', '', '', '']])
|
||||
})
|
||||
|
||||
test('POST /rechnungen: Anzahlung ohne daysUntilDue nimmt das Zahlungsziel der AB, mit Angabe diese; freie Rechnung bleibt bei 14', async () => {
|
||||
const ab = await legeAuftragAn({ zahlungszielTage: 30 })
|
||||
const tage = () => st.calls.filter((c) => c.method === 'POST' && c.path === '/v1/invoices').at(-1).body.days_until_due
|
||||
assert.equal((await post(`${base}/rechnungen`, { customerId: 'k1', art: 'anzahlung', auftragId: ab.id, projektId: 'p1', anzahlung: { prozent: 20 } }, admin)).status, 200)
|
||||
assert.equal(tage(), '30')
|
||||
assert.equal((await post(`${base}/rechnungen`, { customerId: 'k1', art: 'anzahlung', auftragId: ab.id, projektId: 'p1', anzahlung: { prozent: 10 }, daysUntilDue: 7 }, admin)).status, 200)
|
||||
assert.equal(tage(), '7')
|
||||
assert.equal((await post(`${base}/rechnungen`, { customerId: 'k1', items: POSTEN }, admin)).status, 200)
|
||||
assert.equal(tage(), '14')
|
||||
})
|
||||
Reference in new issue
Block a user