Finanzen: Offen zeigt auch Ueberfaellige, Rechnungsliste laedt nach Zuordnen neu
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1feeb18c08
commit
24a3cc41ef
6 files changed
+149
-29
No files matched your search
@@ -25,6 +25,8 @@ const {
|
||||
aboStatus,
|
||||
INVOICE_FILTERS,
|
||||
DEFAULT_INVOICE_FILTER,
|
||||
invoiceFilterStatuses,
|
||||
mergeInvoiceLists,
|
||||
INVOICE_LIMITS,
|
||||
PENDING_ASSIGN_HINT,
|
||||
ageGroupCells,
|
||||
@@ -652,6 +654,40 @@ test('INVOICE_FILTERS: Reihenfolge Offen, Überfällig, Bezahlt, Entwürfe, Alle
|
||||
assert.equal(DEFAULT_INVOICE_FILTER, 'offen')
|
||||
})
|
||||
|
||||
test('invoiceFilterStatuses: „Offen“ ruft offen UND überfällig ab, die anderen genau ihren Status', () => {
|
||||
assert.deepEqual(invoiceFilterStatuses('offen'), ['offen', 'ueberfaellig'])
|
||||
assert.deepEqual(invoiceFilterStatuses('ueberfaellig'), ['ueberfaellig'])
|
||||
assert.deepEqual(invoiceFilterStatuses('bezahlt'), ['bezahlt'])
|
||||
assert.deepEqual(invoiceFilterStatuses('entwurf'), ['entwurf'])
|
||||
assert.deepEqual(invoiceFilterStatuses('alle'), ['alle'])
|
||||
assert.deepEqual(invoiceFilterStatuses('gibtsnicht'), ['alle'])
|
||||
assert.deepEqual(invoiceFilterStatuses(undefined), ['alle'])
|
||||
// die Liste des Filters lässt sich nicht von außen verändern
|
||||
invoiceFilterStatuses('offen').push('x')
|
||||
assert.deepEqual(invoiceFilterStatuses('offen'), ['offen', 'ueberfaellig'])
|
||||
for (const f of INVOICE_FILTERS) assert.deepEqual(invoiceFilterStatuses(f.key), f.statuses)
|
||||
})
|
||||
|
||||
test('mergeInvoiceLists: neueste zuerst, gleiche Tage in Listenreihenfolge, keine Doppelten', () => {
|
||||
const open = [
|
||||
{ id: 'a', createdDate: '2026-07-28', status: 'offen' },
|
||||
{ id: 'b', createdDate: '2026-09-15', status: 'offen' },
|
||||
]
|
||||
const overdue = [
|
||||
{ id: 'c', createdDate: '2026-09-01', status: 'ueberfaellig' },
|
||||
{ id: 'd', createdDate: '2026-09-15', status: 'ueberfaellig' },
|
||||
{ id: 'a', createdDate: '2026-07-28', status: 'offen' },
|
||||
]
|
||||
assert.deepEqual(mergeInvoiceLists([open, overdue]).map((i) => i.id), ['b', 'd', 'c', 'a'])
|
||||
assert.deepEqual(mergeInvoiceLists([overdue, open]).map((i) => i.id), ['d', 'b', 'c', 'a'])
|
||||
assert.deepEqual(mergeInvoiceLists([open]).map((i) => i.id), ['b', 'a'])
|
||||
assert.deepEqual(mergeInvoiceLists([undefined, null, [null, 5, { id: 'x', createdDate: '2026-01-01' }]]).map((i) => i.id), ['x'])
|
||||
assert.deepEqual(mergeInvoiceLists(undefined), [])
|
||||
const input = [open, overdue]
|
||||
mergeInvoiceLists(input)
|
||||
assert.deepEqual(open.map((i) => i.id), ['a', 'b'], 'Eingabelisten bleiben unverändert')
|
||||
})
|
||||
|
||||
test('ageGroupCells: vier Gruppen in fester Reihenfolge, fehlende zählen 0', () => {
|
||||
const cells = ageGroupCells([
|
||||
{ key: '1-30', anzahl: 2, summeCents: 12345 },
|
||||
@@ -1072,6 +1108,30 @@ test('assignModel: Vorschlag mit abweichendem Betrag ist nicht wählbar', () =>
|
||||
assert.equal(known.suggestions[0].disabled, true, 'auch wenn die Liste den Unterschied zeigt')
|
||||
})
|
||||
|
||||
test('assignModel: Vorschlag zu einer Rechnung, die in der frisch geladenen Liste fehlt, ist nicht wählbar', () => {
|
||||
const tx = TX({ amountCents: 5000, vorschlaege: [SUG_INV(), SUG_INV({ id: 'in_9', number: 'WK-0009' })] })
|
||||
const listed = [OPEN()] // in_1 steht darin, in_9 nicht mehr
|
||||
const loaded = assignModel(tx, { invoices: listed, invoicesLoaded: true })
|
||||
assert.equal(loaded.suggestions[0].disabled, false)
|
||||
assert.equal(loaded.suggestions[1].disabled, true)
|
||||
assert.equal(loaded.suggestions[1].disabledReason, 'Diese Rechnung ist nicht mehr offen.')
|
||||
assert.equal(loaded.suggestions[1].number, 'WK-0009')
|
||||
// Liste leer, aber frisch geladen: alle Rechnungsvorschläge sind weg
|
||||
const none = assignModel(tx, { invoices: [], invoicesLoaded: true })
|
||||
assert.deepEqual(none.suggestions.map((s) => s.disabled), [true, true])
|
||||
assert.ok(none.suggestions.every((s) => s.disabledReason === 'Diese Rechnung ist nicht mehr offen.'))
|
||||
// nicht (oder fehlerhaft) geladen: nichts sperren, der Server entscheidet
|
||||
for (const opts of [{ invoices: [] }, { invoices: [], invoicesLoaded: false }]) {
|
||||
assert.deepEqual(assignModel(tx, opts).suggestions.map((s) => s.disabled), [false, false])
|
||||
}
|
||||
// Auszahlungen hängen nicht an der Rechnungsliste
|
||||
const withPayout = TX({ amountCents: 5000, vorschlaege: [{ kind: 'payout', id: 'po_1', number: '', confidence: 'hoch', reason: 'x', amountDiffers: false }] })
|
||||
assert.equal(assignModel(withPayout, { invoices: [], invoicesLoaded: true }).suggestions[0].disabled, false)
|
||||
// eine Rechnung, die in der Liste steht, aber einen anderen Betrag hat, nennt weiter den Betrag
|
||||
const differs = assignModel(TX({ amountCents: 5000, vorschlaege: [SUG_INV()] }), { invoices: [OPEN({ remainingCents: 4000 })], invoicesLoaded: true })
|
||||
assert.match(differs.suggestions[0].disabledReason, /Betrag weicht ab/)
|
||||
})
|
||||
|
||||
test('assignModel: Ausgang bekommt Fixkosten (nur aktive) und Privat/Sonstiges, keine Rechnungen', () => {
|
||||
const tx = TX({ amountCents: -1000, vorschlaege: [SUG_INV()] })
|
||||
const m = assignModel(tx, {
|
||||
|
||||
Reference in new issue
Block a user