statements: derive account identity, fix the new-bank alert (0033)
ci / lint-test (push) Successful in 42s

account_number fragments exactly like bank_name did, from the same cause:
ANZ's Access Advantage arrived as both '4085-56264' (4 statements) and
'408556264' (1). uq_statement_identity keyed on it, so re-importing one
period under the other spelling evaded the duplicate check.

account_number_key is GENERATED ALWAYS — the number with separators
stripped — and the unique index moves onto it. Derived rather than
rewritten because the raw number is the readable one and some of it is
structure: Up stores '633-123 / 176540052', a BSB and an account number,
and flattening it would lose a distinction a human reads at a glance to
fix a machine problem. The Amex mask and case are preserved; 'X' records
which digits were redacted.

Not the cause of the documented 31-row / $42,040.68 ANZ duplication —
107/142/143 overlap on different end dates, which that index cannot catch
at any spelling.

Adds statement_identity_drift: one account under two bank names, or one
bank under two spellings of one number. Non-empty means fragmentation the
normaliser could not know about. Currently one row, the ANZ pair above,
now unified by key.

Also documents the N8N regression this series caused. Check Known Bank
compared the raw Gemini name against the canonical column before the
insert, so nothing ever matched and every Zip statement was tagged
pending and held for Slack approval — a stall, not just a noisy alert.
Fixed in workflow FysADdFwEtwONQl4 by comparing like with like through
normalize_bank_name(), passing currency so a genuinely new national
entity still alerts. Verified live: 12s after vs 30-53s before.
This commit is contained in:
2026-08-15 17:03:13 +10:00
parent c3b623052d
commit 2cfaf8e8c8
4 changed files with 151 additions and 15 deletions
+5
View File
@@ -135,6 +135,11 @@ model statements {
card_name String?
account_type String?
account_number String
/// GENERATED ALWAYS (migration 0033) — account_number with separators
/// stripped, so '4085-56264' and '408556264' are one account. Backs
/// uq_statement_identity. Read-only: never write to it, display
/// account_number instead.
account_number_key String?
billing_start_date DateTime? @db.Date
billing_end_date DateTime? @db.Date
total_amount_due Decimal? @db.Decimal(12, 2)