cadrumo.application.transactions.import_classification module

The one verdict on what an imported row is: new, seen before, or a collision.

Two classifiers once answered this question and disagreed. The diagnostics path treated a fingerprint repeated WITHIN one file as a duplicate and counted it skipped; the persisting path deliberately imported both, reasoning that two identical same-day movements – a pair of matching retainers or subscriptions – are two genuine movements, and that dropping one silently under-declares. Since --verify ran the first and the actual import ran the second, the operator was warned about a row the import would happily persist, and the preview count was wrong in the direction that hides money.

The persisting path holds the reasoned position, so it is the one preserved here: under-declaration is the worse error, and an intra-batch repeat is surfaced as an ADVISORY the operator can review rather than a skip that removes the row.

The two intra-batch cases are NOT the same, which is the distinction the diagnostics path was missing entirely:

  • a repeated fingerprint is two rows describing movements that look alike; the provider synthesises a distinct row-index-bearing transaction id for each, so both persist, and both must;

  • a repeated transaction id is two rows resolving to the same catalogue key. The later would overwrite the earlier, so only one can persist and the count must say so.

See also

LedgerImportDiagnosticKind

The category an unimported verdict is reported under.

class ImportRowVerdict(*values)[source]

Bases: StrEnum

What one parsed row is, relative to the catalogue and the rest of its batch.

NEW

Not seen in the catalogue nor earlier in this batch. Imports.

DUPLICATE_OF_STORED

Its fingerprint is already in the catalogue – the same movement seen before.

A re-imported statement, or the same movement re-exported in another file format. Skipped: the fingerprint survives later edits, so this recognises the row even after the stored copy was amended.

REPEATED_IN_BATCH

An earlier row in this same file carries the same fingerprint. Still imports.

Two identical same-day movements are two movements. Reported as an advisory so the operator can rule out a genuine double-count in the source file, never dropped on their behalf.

COLLIDING_TRANSACTION_ID

An earlier row in this batch resolves to the same transaction id. Skipped.

The catalogue keys on that id, so the later row would overwrite the earlier one. Only one can persist and the count says one.

property imports: bool

Return whether a row with this verdict is persisted.

The single place the import/skip split is decided, so a caller counting skips and a caller building rows cannot drift apart.

classify_import_row(*, fingerprint, transaction_id, stored_fingerprints, batch_fingerprints, batch_transaction_ids)[source]

Return the verdict for one parsed row.

Pure: it reads the three sets and nothing else, so both the preview and the persisting path reach the same answer from the same inputs.

Parameters:
  • fingerprint (str) – The row’s stable import fingerprint, derived by the caller with the direction the provider read at the parse boundary.

  • transaction_id (str) – The row’s derived catalogue key.

  • stored_fingerprints (Set[str]) – Every fingerprint already in the catalogue.

  • batch_fingerprints (Set[str]) – Fingerprints of the rows classified so far in this batch, in document order.

  • batch_transaction_ids (Set[str]) – Transaction ids of the rows ACCEPTED so far in this batch.

Returns:

an already-stored fingerprint is a re-import whatever else the batch contains, and an id collision outranks a fingerprint repeat because it is the one that cannot persist.

Return type:

The verdict. Order matters