fix(transactions): include 'overdue' in match-supplier-invoice CAS guard (#779)
SupplierInvoicePicker shows overdue invoices as payable candidates, but the CAS update in the match route omitted 'overdue' from its status whitelist. This caused the update to return 0 rows for any overdue invoice, committing a journal entry and then orphaning it before returning MATCH_SI_NOT_OPEN — making the match appear to fail due to a concurrent request. The v1 route already had this correct. Signed-off-by: Jonas Flodén <jonas@floden.nu>
This commit is contained in:
@@ -81,6 +81,7 @@ function enqueueHappyPath(opts: {
|
||||
exchange_rate?: number | null
|
||||
remaining_amount?: number
|
||||
paid_amount?: number
|
||||
status?: string
|
||||
}
|
||||
accountingMethod?: string
|
||||
}) {
|
||||
@@ -103,7 +104,7 @@ function enqueueHappyPath(opts: {
|
||||
id: SI_UUID,
|
||||
currency: opts.invoice.currency,
|
||||
exchange_rate: opts.invoice.exchange_rate ?? null,
|
||||
status: 'registered',
|
||||
status: opts.invoice.status ?? 'registered',
|
||||
remaining_amount: opts.invoice.remaining_amount ?? 225,
|
||||
paid_amount: opts.invoice.paid_amount ?? 0,
|
||||
supplier: { supplier_type: 'eu_business' },
|
||||
@@ -285,6 +286,18 @@ describe('POST /api/transactions/[id]/match-supplier-invoice — non-FX paths',
|
||||
expect(details.excess).toBe(1000)
|
||||
})
|
||||
|
||||
it('succeeds for an overdue invoice (status is a valid CAS target)', async () => {
|
||||
// Regression: CAS guard previously omitted 'overdue', so selecting an overdue
|
||||
// invoice from SupplierInvoicePicker would commit a JE, fail the update, orphan
|
||||
// the voucher, and return MATCH_SI_NOT_OPEN.
|
||||
enqueueHappyPath({
|
||||
transaction: { amount: -1000, currency: 'SEK' },
|
||||
invoice: { currency: 'SEK', remaining_amount: 1000, status: 'overdue' },
|
||||
})
|
||||
const res = await POST(makeReq(), createMockRouteParams({ id: TX_UUID }))
|
||||
expect(res.status).toBe(200)
|
||||
})
|
||||
|
||||
it('does NOT trigger overshoot guard on currency mismatch (FX path clamps to remaining)', async () => {
|
||||
// SEK transaction paying a EUR invoice. The currency-mismatch branch
|
||||
// collapses paymentAmountInvoiceCurrency to invoice.remaining_amount and
|
||||
|
||||
@@ -330,7 +330,7 @@ export const POST = withRouteContext(
|
||||
transaction_id: transactionId,
|
||||
})
|
||||
.eq('id', supplier_invoice_id)
|
||||
.in('status', ['registered', 'approved', 'partially_paid'])
|
||||
.in('status', ['registered', 'approved', 'partially_paid', 'overdue'])
|
||||
.select('id')
|
||||
|
||||
if (updateInvError) {
|
||||
|
||||
Reference in New Issue
Block a user