cadrumo.application.ledger.actions_import module

Ledger source import services for bucket-scoped transaction catalogues.

Provider rows arrive through the ParsedLedgerRowProtocol port. This module classifies them against a loaded TransactionCatalogue, persists imported Transaction instances, records LEDGER_TRANSACTION_IMPORTED bucket events, and returns LedgerImportOperationResult or LedgerSourceImportResult.

class LedgerProviderID(*values)[source]

Bases: StrEnum

Canonical provider ID strings accepted by the ledger import dispatch.

AUTO
CSV
OFX
QFX
XLSX
EXCEL
N26
PDF
PDF_N26
evaluate_import_rows(*, bucket_id, catalogue, parsed_rows, currency_normalizer=None, occurred_at=None)[source]

Classify every parsed row as imported / skipped / likely-duplicate.

Each ParsedLedgerRowProtocol carries the magnitude RawTransaction and the authoritative direction the provider derived from the source sign at the parse boundary; this classifier never re-derives flow from a sign. Deduplication keys on derive_import_fingerprint() - a direction- and currency-qualified identity that is stable across both later edits of a transaction and a re-export of the same movement in a different file format. The import/skip verdict itself comes from classify_import_row(), which the --verify diagnostics path consumes too, so the persisting path, the --dry-run preview and the verify report all agree on what a row is.

Core types: TransactionCatalogue.

Return type:

_ImportRowPlan

Parameters:
import_ledger_transactions(*, bucket_id, parsed_rows, ports, transaction_repository, bucket_event_repository, actor='operator', source_command='aeat app ledger import', occurred_at=None, currency_normalizer=None, catalogue=None)[source]

Import provider rows into one bucket catalogue and emit events.

Each ParsedLedgerRowProtocol carries the magnitude RawTransaction plus the authoritative direction the provider derived at the parse boundary, so the import path never re-derives flow from a sign.

catalogue is the bucket’s already-loaded catalogue when the caller read one to diagnose the source against; otherwise it is loaded here.

Returns a LedgerImportOperationResult summarising the imported, skipped, and likely-duplicate transactions.

Core types: TransactionCatalogue.

Return type:

LedgerImportOperationResult

Parameters:
import_ledger_source(command, *, ports, transaction_repository=None, bucket_event_repository=None, currency_normalizer=None)[source]

Validate, ingest, and optionally persist one ledger source file.

Returns a LedgerSourceImportResult.

Return type:

LedgerSourceImportResult

Parameters:
apply_fx_conversion(raw, currency_normalizer)

Return (fx_rate, value_in_eur, rate_source, rate_date_iso) for a raw row.

EUR-native rows and non-EUR rows with no normalizer / a missing rate yield all None, preserving the coupling invariant on Transaction.

Return type:

tuple[Decimal | None, Decimal | None, str | None, str | None]

Parameters:
aggregate_ledger_import_results(results)[source]

Fold the per-file results of a directory import into one result.

import_ledger_source() produces one result per file, so a directory import holds several and the operator is owed a single answer. Summing them is a statement about what an import IS – which counts add, which references concatenate, and which fields may not differ between files – so it belongs beside the function that produces them rather than beside the command that happens to call it more than once.

The invocation-wide fields are ASSERTED rather than assumed. dry_run, verify, period and bucket_id describe the invocation. Each source file has its own content-derived import_batch_id in persisted events; a folder with distinct batch ids has no single batch id to report.

Parameters:

results (Sequence[LedgerSourceImportResult]) – The per-file results, in the order the files were read.

Return type:

LedgerSourceImportResult

Returns:

One result whose counts are sums and whose reference tuples are the concatenation, in file order – including every file’s validation and source-verification report, which the fold previously dropped after the first.

Raises:

TransactionValidationError – If results is empty, or if the results disagree on a field that describes the invocation.

IMPORTABLE_SOURCE_EXTENSIONS: Final[frozenset[str]]

The file kinds this product can read as a bank statement. It is a statement about ingestion capability, not about one surface’s argument parsing, so a second frontend importing a folder selects exactly the same files.

plan_ledger_import_sources(path)[source]

Resolve one import target into the ordered files to read.

A file is itself; a directory is its importable children. The extension filter is what keeps a stray note or an exported PDF in the same folder from being handed to a statement parser, and refusing an empty directory matters because the alternative is an import that reports success having read nothing.

Order is scan_directory()’s deterministic sort. That is load-bearing rather than incidental: several files fold into one aggregated result, and a filesystem-dependent order would make the same folder import differently on two machines.

Parameters:

path (Path) – The file or directory the operator named.

Return type:

tuple[Path, ...]

Returns:

The files to import, in the order they will be read.

Raises:

TransactionValidationError – When path is a directory holding no importable file.