Add source identity to transactions so a feed can be re-imported safely
ci / lint-test (push) Successful in 51s
ci / lint-test (push) Successful in 51s
The CSV importer has no idempotency and structurally cannot have any: batchInsertCSVTransactions assigns row_index = MAX(row_index) + 1, and row_index is the fifth column of uq_transaction_identity, so the constraint is guaranteed a fresh value on every run. The same file imported twice produces two full sets of rows and nothing objects. Tolerable for the hand-driven bank CSV this was built for. Not tolerable for any recurring feed, whose windows overlap by design — and not cleanable afterwards, since every child of transactions is ON DELETE CASCADE, so a duplicate must be superseded rather than deleted (0023). ~$42k of re-imported statement rows already show how that goes. source_ref carries the provider's own key verbatim, enforced by a partial unique index rather than an application-side ON CONFLICT that a refactor can quietly drop. Found while evaluating Frollo (DECISIONS.md ING-11 in the smarthome repo). That feed is not being ingested — 88% of it duplicates existing statement coverage — but this gap is real independently of it.
This commit is contained in:
@@ -187,6 +187,9 @@ model transactions {
|
||||
superseded_by_id Int?
|
||||
principal_amount Decimal? @db.Decimal(12, 2)
|
||||
interest_amount Decimal? @db.Decimal(12, 2)
|
||||
source String? // feed this row came from, e.g. "frollo"; NULL = statement/manual (migration 0028)
|
||||
source_ref String? // the provider's own transaction id — idempotency key for re-imports
|
||||
source_account String? // account label as the source names it
|
||||
statement statements? @relation(fields: [statement_id], references: [id], onDelete: Cascade)
|
||||
reconciled_with transactions? @relation("reconciled", fields: [reconciled_with_id], references: [id], onDelete: SetNull)
|
||||
reconciled_by transactions[] @relation("reconciled")
|
||||
|
||||
Reference in New Issue
Block a user