cadrumo.domain.modelos.ledger_filing_snapshot module

Immutable ledger snapshot backing a modelo filing revision.

A modelo calculation revision that reaches a verified or filed state carries a content-addressed snapshot of the ledger state it was computed from: a fingerprint over each contributing transaction’s tax-relevant facts plus an aggregate snapshot fingerprint. This is the audit + staleness layer that sits on top of the write-time blocking guard.

This module holds the pure records and the pure fingerprint diff. The Transaction-aware capture (which reads the live catalogue to produce row fingerprints) lives in the application aggregation layer so the domain stays free of the ledger-read dependency, per the hexagonal boundary.

class LedgerRowFingerprint(**data)[source]

Bases: BaseModel

Content fingerprint of one contributing ledger transaction.

Variables:
  • transaction_id – The contributor’s stable ledger transaction id.

  • fingerprint – SHA-256 hex over the transaction’s tax-relevant facts (the fields that can move a casilla), computed by the application capture helper.

Parameters:

data (Any)

transaction_id: TransactionId
fingerprint: SnapshotId
class LedgerFilingSnapshot(**data)[source]

Bases: BaseModel

Immutable snapshot of the ledger state behind one filing revision.

Empty rows is valid and expected for a non-ledger modelo (no contributing transactions); its snapshot_fingerprint is the digest of the empty contributor set, so every modelo carries a uniform, comparable snapshot regardless of whether it is ledger-fed.

Variables:
  • rows – Per-contributor fingerprints, sorted by transaction id.

  • snapshot_fingerprint – SHA-256 hex over the sorted (id, fingerprint) pairs; the content address of the whole ledger state.

  • captured_at – UTC timestamp the snapshot was taken.

  • fingerprint_field_set_version – Which set of tax facts the stored fingerprints cover. A stored hash is only comparable against a hash recomputed over the SAME fields, so this records which set was in force when the snapshot was sealed. It defaults to 1 so a snapshot written before the field set was versioned reads back as what it is, rather than being silently reinterpreted under a wider set and reported stale.

Parameters:

data (Any)

rows: tuple[LedgerRowFingerprint, ...]
snapshot_fingerprint: SnapshotId
captured_at: UtcInstant
fingerprint_field_set_version: int
class LedgerFilingStalenessVerdict(**data)[source]

Bases: BaseModel

Drift between a filed snapshot and the current ledger state.

Variables:
  • is_stale – True when any contributor changed or was removed.

  • changed – Contributor ids whose live fingerprint differs from the snapshot.

  • removed – Contributor ids absent from the live catalogue.

  • unchanged – Contributor ids whose live fingerprint matches the snapshot.

  • covers_current_fact_set – Whether the compared fingerprints span every tax fact this build knows can move a casilla. False means the comparison was sound but NARROWER than today’s: the snapshot was sealed under an older field set and was compared under that set, so unchanged means “unchanged in the facts that were being watched”, not “unchanged in every fact”. Deliberately separate from is_stale and non-blocking – a narrow comparison is not evidence of drift, and reporting it as drift would restate every historical filing at once.

Parameters:

data (Any)

is_stale: bool
changed: tuple[TransactionId, ...]
removed: tuple[TransactionId, ...]
unchanged: tuple[TransactionId, ...]
covers_current_fact_set: bool
snapshot_fingerprint(rows)[source]

Return the aggregate content address over sorted contributor fingerprints.

Return type:

TypeAliasType

Parameters:

rows (tuple[LedgerRowFingerprint, ...])

diff_ledger_fingerprints(snapshot, current_fingerprints)[source]

Compare a filed snapshot against live per-contributor fingerprints.

current_fingerprints maps each contributor’s transaction id to its freshly-recomputed fingerprint (a contributor missing from the mapping is treated as removed). Pure: no ledger read happens here.

Return type:

LedgerFilingStalenessVerdict

Returns:

The computed LedgerFilingStalenessVerdict detail.

Parameters:
class LedgerEvidenceRow(**data)[source]

Bases: BaseModel

Typed evidence projection of one contributing ledger transaction.

Where LedgerRowFingerprint records only the content hash (for staleness detection), this record carries the tax-relevant facts themselves, plus regulatory grounding and evidence references, so the fact basis can be reconstituted from the revision and rendered into a filing artefact. fingerprint binds this row to the matching LedgerRowFingerprint, so an evidence/fingerprint mismatch is detectable.

The field set deliberately mirrors the fingerprint’s rather than the transaction’s, so evidence and staleness always describe the same facts. The two therefore move together, and they did: recargo_amount, usage_ratio_id, deduction_fact_kind and the prorrata declarations were absent from both, so the exported evidence for a recargo-de-equivalencia purchase showed base and IVA with no surcharge. They are present in both now, under fingerprint field-set version 2 (see _FINGERPRINT_FIELDS_V2 in the application capture module).

A row bundled under version 1 carries them as None, which is honest rather than lossy: that capture genuinely did not record them, and fingerprint_field_set_version on the owning bundle says so.

Enum-valued facts are stored as their canonical string value (and dates as ISO-8601 strings) so the record roundtrips cleanly through the strict persistence boundary and the domain stays free of the ledger-read dependency; the application capture layer projects the typed Transaction into this primitive shape.

Parameters:

data (Any)

transaction_id: TransactionId
fingerprint: SnapshotId
booked_date: str
value_date: str | None
amount: Decimal
currency: IsoCurrencyCode
direction: str
business_classification: str
business_pct: Decimal | None
taxable_base: Decimal | None
iva_rate: Decimal | None
iva_amount: Decimal | None
recargo_amount: Decimal | None
iva_category: str | None
usage_ratio_id: str | None
deduction_fact_kind: str | None
art_104_tres_exclusion: str | None
input_classification: str | None
prorrata_sector_id: str | None
prorrata_reference: str | None
category_id: str | None
irpf_category: str | None
source_jurisdiction: CountryCodeAlpha2 | None
m210_official_tipo_renta_code: str | None
m210_gross_income_amount: Decimal | None
m210_applicable_rate: UnitProportion | None
m210_payer_mode: str | None
m210_payer_id: str | None
m210_asset_or_right_id: str | None
counterparty_country: CountryCodeAlpha2 | None
fx_rate: Decimal | None
value_in_eur: Decimal | None
lifecycle_state: str
counterparty: str | None
description: str
purchase_invoice_evidence_id: str | None
invoice_id: str | None
attachment_ids: tuple[str, ...]
legal_refs: tuple[LegalRefId, ...]
source_refs: tuple[SourceRefId, ...]
class ManualFactBasisEntry(**data)[source]

Bases: BaseModel

One operator-entered fact behind a revision that is not ledger-derived.

Manual casilla inputs and binding overrides have no contributing ledger row; they are nonetheless part of the fact basis a filing artefact must explain. casilla_id is the canonical registry casilla id and value is the rendered canonical string of the operator-entered value.

Parameters:

data (Any)

casilla_id: CasillaId
value: str
kind: str
note: str
legal_refs: tuple[LegalRefId, ...]
source_refs: tuple[SourceRefId, ...]
class LedgerFilingEvidence(**data)[source]

Bases: BaseModel

The bundled fact basis behind one ledger-derived filing revision.

Pegged to the revision’s LedgerFilingSnapshot via snapshot_fingerprint so evidence and the staleness fingerprint share one content address. Empty rows + empty manual_entries is valid for a non-ledger, non-manual revision; a ledger-derived revision MUST carry one LedgerEvidenceRow per fingerprint contributor (the application capture asserts the sets match, so no contributor is silently dropped from the evidence).

Parameters:

data (Any)

snapshot_fingerprint: SnapshotId
rows: tuple[LedgerEvidenceRow, ...]
manual_entries: tuple[ManualFactBasisEntry, ...]
captured_at: UtcInstant
fingerprint_field_set_version: int

Mirrors the paired snapshot’s field-set version. Carried here too because this record is what an audit reader renders, and the fact basis it shows is only as wide as the set that produced it.