fix(reconciliation): exclude ignored transactions from the bank total and bridge whitespace-drifted duplicate descriptions (#1705)
Bank reconciliation counted ignored transactions in bank_transaction_total while excluding them from the unmatched count, so after the sanctioned duplicate cleanup (ignore one twin) the differens showed the ignored sum forever and is_reconciled was unreachable: observed live as a permanent 116 367 kr differens on a fully booked enskild firma (78 867 kr ignored reconnect duplicates + 37 500 kr genuinely unbooked). The ignore toast already promised 'försvinner från avstämningen'; now the engine keeps that promise. Ignored rows are surfaced separately (count + sum) in the status object, the UI card, and the v1 API, mirroring the IB pattern. The duplicates themselves came from a PSD2 reconnect: the new connection re-rendered identical transactions with drifted whitespace (CRLF vs space, and a DROPPED space), so the prefix-containment content bridge missed every twin. descriptionsBridge now strips all whitespace before comparing: char-filtering preserves existing prefix relations, and the compare stays confined to a (date, öre) bucket. Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Jakob Wennberg
Claude Fable 5
parent
6b9338f17e
commit
506d030bb1
@@ -18,8 +18,11 @@ import { getReconciliationStatus } from '@/lib/reconciliation/bank-reconciliatio
|
||||
// total_unmatched_amount, …) that the endpoint never returned; any client coded
|
||||
// against it read undefined for every field except difference.
|
||||
const StatusResponse = z.object({
|
||||
/** Sum of bank-feed transactions in the window (the bank side). */
|
||||
/** Sum of bank-feed transactions in the window (the bank side), excluding ignored rows. */
|
||||
bank_transaction_total: z.number(),
|
||||
/** Sum of ignored bank transactions in the window. Informational: not part of bank_transaction_total or difference. */
|
||||
ignored_transaction_total: z.number(),
|
||||
ignored_transaction_count: z.number().int(),
|
||||
/** Full ledger balance on the account incl. opening balance: matches the balance sheet. */
|
||||
gl_1930_balance: z.number(),
|
||||
/** Ledger movement excluding opening balance: what `difference` compares against. */
|
||||
@@ -50,11 +53,14 @@ registerEndpoint({
|
||||
'A non-zero difference is normal between sync runs (uncleared cheques, in-flight transfers). Investigate only if it persists across reconciliations.',
|
||||
'difference compares against gl_1930_period_movement (movement excl. opening balance), NOT gl_1930_balance. Do not display gl_1930_balance next to difference.',
|
||||
'is_reconciled means |difference| < 0.01 for the window, an aggregate check, not a per-transaction guarantee.',
|
||||
'Ignored transactions are excluded from bank_transaction_total and difference (they never get a ledger counterpart); their count and sum are reported separately.',
|
||||
],
|
||||
example: {
|
||||
response: {
|
||||
data: {
|
||||
bank_transaction_total: 48150,
|
||||
ignored_transaction_total: 0,
|
||||
ignored_transaction_count: 0,
|
||||
gl_1930_balance: 98150,
|
||||
gl_1930_period_movement: 48150,
|
||||
gl_1930_opening_balance: 50000,
|
||||
|
||||
Reference in New Issue
Block a user