From ced6f1c65bf8e2fd2892d7fcd1cbb1a336384584 Mon Sep 17 00:00:00 2001 From: Mattsson <111893710+mattssonn@users.noreply.github.com> Date: Thu, 13 Aug 2026 23:35:14 +0200 Subject: [PATCH] fix(reconciliation): await the pre-existing matched/storno match-log writes (#1606) Final Swedish-review finding (approved by Emil): the six fire-and-forget logMatchEvent calls that predate this branch in the four match routes are now awaited, matching the rest of the PR and the DECISIONS claim that every audit write is awaited. logMatchEvent never throws; on serverless an unawaited promise can be frozen when the response returns, silently dropping the behandlingshistorik row (BFNAR 2013:2 kap 8). Co-authored-by: Claude Fable 5 --- app/api/transactions/[id]/match-invoice/route.ts | 4 ++-- app/api/transactions/[id]/match-supplier-invoice/route.ts | 2 +- .../[companyId]/transactions/[id]/match-invoice/route.ts | 4 ++-- .../transactions/[id]/match-supplier-invoice/route.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/api/transactions/[id]/match-invoice/route.ts b/app/api/transactions/[id]/match-invoice/route.ts index 7cbed208..4af3a3dd 100644 --- a/app/api/transactions/[id]/match-invoice/route.ts +++ b/app/api/transactions/[id]/match-invoice/route.ts @@ -365,7 +365,7 @@ export const POST = withRouteContext( txLog.warn('failed to clear journal_entry_id after storno', clearJeError) } - logMatchEvent(supabase, user.id, transactionId, 'storno_conflict_resolved', { + await logMatchEvent(supabase, user.id, transactionId, 'storno_conflict_resolved', { invoiceId: invoice_id, previousState: { journal_entry_id: transaction.journal_entry_id }, newState: { journal_entry_id: null }, @@ -776,7 +776,7 @@ export const POST = withRouteContext( }) } - logMatchEvent(supabase, user.id, transactionId, 'matched', { + await logMatchEvent(supabase, user.id, transactionId, 'matched', { invoiceId: invoice_id, matchConfidence: 1.0, matchMethod: 'manual_confirm', diff --git a/app/api/transactions/[id]/match-supplier-invoice/route.ts b/app/api/transactions/[id]/match-supplier-invoice/route.ts index 4b2a5bd1..934234e6 100644 --- a/app/api/transactions/[id]/match-supplier-invoice/route.ts +++ b/app/api/transactions/[id]/match-supplier-invoice/route.ts @@ -501,7 +501,7 @@ export const POST = withRouteContext( // it is already anchored, e.g. on the registration verifikat. await anchorSupplierInvoiceDocument(supabase, companyId, supplier_invoice_id) - logMatchEvent(supabase, user.id, transactionId, 'matched', { + await logMatchEvent(supabase, user.id, transactionId, 'matched', { supplierInvoiceId: supplier_invoice_id, matchConfidence: 1.0, matchMethod: 'manual_confirm', diff --git a/app/api/v1/companies/[companyId]/transactions/[id]/match-invoice/route.ts b/app/api/v1/companies/[companyId]/transactions/[id]/match-invoice/route.ts index 4b7d489d..9fa32f13 100644 --- a/app/api/v1/companies/[companyId]/transactions/[id]/match-invoice/route.ts +++ b/app/api/v1/companies/[companyId]/transactions/[id]/match-invoice/route.ts @@ -437,7 +437,7 @@ export const POST = withApiV1<{ params: Promise<{ companyId: string; id: string if (clearErr) { txLog.warn('failed to clear journal_entry_id after storno', clearErr) } - logMatchEvent(ctx.supabase, ctx.userId, txId, 'storno_conflict_resolved', { + await logMatchEvent(ctx.supabase, ctx.userId, txId, 'storno_conflict_resolved', { invoiceId: invoice_id, previousState: { journal_entry_id: transaction.journal_entry_id }, newState: { journal_entry_id: null }, @@ -808,7 +808,7 @@ export const POST = withApiV1<{ params: Promise<{ companyId: string; id: string }) } - logMatchEvent(ctx.supabase, ctx.userId, txId, 'matched', { + await logMatchEvent(ctx.supabase, ctx.userId, txId, 'matched', { invoiceId: invoice_id, matchConfidence: 1.0, matchMethod: 'manual_confirm', diff --git a/app/api/v1/companies/[companyId]/transactions/[id]/match-supplier-invoice/route.ts b/app/api/v1/companies/[companyId]/transactions/[id]/match-supplier-invoice/route.ts index 8b647ab9..38a4f150 100644 --- a/app/api/v1/companies/[companyId]/transactions/[id]/match-supplier-invoice/route.ts +++ b/app/api/v1/companies/[companyId]/transactions/[id]/match-supplier-invoice/route.ts @@ -581,7 +581,7 @@ export const POST = withApiV1<{ params: Promise<{ companyId: string; id: string // invoice. No-op when it is already anchored. Never throws. await anchorSupplierInvoiceDocument(ctx.supabase, ctx.companyId!, supplier_invoice_id) - logMatchEvent(ctx.supabase, ctx.userId, txId, 'matched', { + await logMatchEvent(ctx.supabase, ctx.userId, txId, 'matched', { supplierInvoiceId: supplier_invoice_id, matchConfidence: 1.0, matchMethod: 'manual_confirm',