aeat.domain.modelos._calculation_revision module¶
One calculation attempt under a modelo work unit.
A work unit owns many calculation revisions. Each calculate
invocation produces a fresh, content-addressed
CalculationRevision. The work unit carries pointer fields
that disambiguate which revision is the most recent (current)
and which one is the filed answer (filed). Without those
pointers, multiple drafts under the same work unit have no canonical
selection — every consumer (year-aggregation, amendment delta,
forward-period carry-forward) needs to know which one is THE
revision. Formula provenance for every computed casilla is carried
through CasillaObservation entries in the typed observations
envelope.
Lifecycle states:
BORRADOR— newly calculated; mutable in the sense that re-runningcalculatecreates a new revision rather than editing this one. Multiple borradores can coexist.VERIFICADO_COMPLETO—verifyran cleanly: all required casillas resolved, zero blocking findings, source trace persisted. The revision is immutable from this point on; any recalculation produces a fresh borrador instead.PRESENTADO— paired with aModeloRecord. The revision is the currently-effective filed answer for its (bucket, modelo, year, period) tuple. Exactly one presentado revision per tuple at any time.PRESENTADO_SUPERSEDIDO— a later verified revision was filed against the same tuple. The revision and its filing record remain in the audit trail.DESCARTADO— operator abandoned the revision before filing.
Two CalculationRevisions can never share a calculation_revision_id;
the id is the SHA-256 of the inputs + binding overrides + computed
casilla values (plus the parent work_unit_id), so structurally
identical re-runs produce the same id and re-running calculate
with the same data is naturally idempotent.
- class CalculationRevisionState(*values)[source]¶
Bases:
StrEnumClosed enumeration of calculation-revision lifecycle states.
- BORRADOR¶
- VERIFICADO_COMPLETO¶
- PRESENTADO¶
- PRESENTADO_SUPERSEDIDO¶
- DESCARTADO¶
- class CalculationRevisionAmendmentKind(*values)[source]¶
Bases:
StrEnumClosed catalogue of amendment kinds a revision may carry.
Aligned with Spanish tax law’s legally-distinct amendment shapes:
COMPLEMENTARIA— corrective filing that adds to the prior filing’s tax due (LGT art. 122.2,ley-58-2003:art-122). Filed when the operator discovers an error that under-reported tax.SUSTITUTIVA— substitute filing that replaces the prior filing entirely (LGT art. 122.1). Used for material restatements.RECTIFICATIVA— autoliquidación rectificativa: the unified amendment mechanism established by LGT art. 120.4 (ley-58-2003:art-120, apartado 4) and developed by RD 117/2024 (which amended the Reglamento de gestión, RD 1065/2007). For the modelos whose tax-specific orden implements it (Modelo 303 from the 2023-y-siguientes revision onward), the rectificativa replaces BOTH the complementaria and the separate solicitud de rectificación: a single amended autoliquidación that may raise OR lower the resultado, carrying its own fichero-BOE indicator and, when it lowers the cuota to a refund, the operator’s devolución account.
- COMPLEMENTARIA¶
- SUSTITUTIVA¶
- RECTIFICATIVA¶
- derive_calculation_revision_id(*, work_unit_id, input_values_by_casilla_id, binding_overrides, row_binding_values=None, casilla_values, relation_overrides=None, source_transaction_ids=(), borrador_snapshot_id=None, bindings_sourced_from_borrador=(), detail_rows=())[source]¶
Return the deterministic SHA-256 id for a calculation attempt.
The id is content-addressed by the parent work unit plus the three payload mappings: input casilla values, scalar binding overrides, and computed casilla outputs. Row-indexed binding values are carried as their own nested map so repeating-record coordinates participate in identity without being flattened into synthetic binding ids. Two structurally identical re-runs produce the same id; the catalogue’s content-addressing invariant then makes a second
calculatecall idempotent (the existing revision is returned, no duplicate is persisted).detail_rowscarries typed row observations for informational modelos (M184, M232) that declare row-producer bindings. When rows are present they are serialised into the hash so structurally identical re-runs with the same rows produce the same id.- Return type:
- Parameters:
work_unit_id (str)
row_binding_values (Mapping[BindingId, Mapping[str, str]] | None)
borrador_snapshot_id (str | None)
bindings_sourced_from_borrador (Sequence[BindingId])
detail_rows (Sequence[Modelo184MemberRow | Modelo232VinculadaRow | Modelo349OperadorRow | Modelo349RectificacionRow | Modelo347ContraparteRow])
- class CalculationSourceRef(**data)[source]¶
Bases:
BaseModelOne resolver-level source-object trace persisted on a calculation revision.
The calculation source mesh (
aeat.application.aggregation) resolves each registry binding source through an enrolled resolver and produces a typedCalculationSourceProvenancerow per contributing source object. This is the DOMAIN-side, persistence-shaped projection of that provenance: it carries exactly the resolver→source-object→fingerprint trace that lets an audit reader reconstruct which resolver mesh and which upstream source objects produced a revision, and whether those objects have since drifted.It deliberately does NOT carry
legal_refs/source_refs— those are the per-casilla regulatory grounding already carried byCasillaObservationon the same revision; duplicating them here would fragment the grounding across two surfaces.- Variables:
source_kind – Free-form resolver source token (e.g.
collectible_invoice). Always the token the resolver declared for the contributing source.binding_source – The canonical
BindingSourceKindwhensource_kindnames a registry binding source;Nonefor advisory or non-binding provenance rows.source_ref – Stable reference to the contributing source object (e.g.
collectible_invoice:{invoice_id}).fingerprint – Data-dependent digest of the contributing source object when the resolver produced one;
Nonewhen the resolver emits a reference without a content digest.
- Parameters:
source_kind (str)
binding_source (BindingSourceKind | None)
source_ref (str)
fingerprint (str | None)
- source_kind: str¶
- binding_source: BindingSourceKind | None¶
- source_ref: str¶
- fingerprint: str | None¶
- class CalculationRevision(**data)[source]¶
Bases:
BaseModelOne calculation attempt attached to a work unit.
- Variables:
calculation_revision_id – Lowercase 64-char SHA-256 derived from the parent work_unit_id plus the inputs, overrides, and casilla outputs. Content-addressed: structurally identical re-runs produce the same id.
work_unit_id – Parent work unit id (also content-addressed).
state – Lifecycle state from
CalculationRevisionState.input_values_by_casilla_id – Mapping of canonical input casilla values captured at calculation time. The string values are decimal strings or short literals from the registry input contract.
binding_overrides – Mapping of operator-supplied binding overrides applied during this calculation. Empty when no binding overrides were used.
row_binding_values – Mapping of row-indexed binding values produced by source meshes for repeating export records. Kept separate from
binding_overridesso the row coordinate remains structured.relation_overrides – Mapping of relation values applied during this calculation. Kept separate from
binding_overridesso BindingId-keyed snapshots never carry RelationId keys.source_transaction_ids – Stable ledger transaction ids that contributed to this revision through bucket-local aggregation. Empty for calculations that did not consume ledger transactions.
casilla_values – Mapping of computed casilla values (decimal output). The values that would be exported to AEAT if this revision were filed.
created_at – UTC timestamp of revision creation.
updated_at – UTC timestamp of the most recent state transition. Equals
created_aton a fresh draft.verified_at – UTC timestamp at which the revision transitioned to
VERIFICADO_COMPLETO.Nonefor non-verified revisions.verified_by – Actor label captured at verification time.
Nonefor non-verified revisions.filed_at – UTC timestamp at which the revision was filed.
Nonefor non-filed revisions.filed_by – Actor label captured at filing time.
Nonefor non-filed revisions.superseded_at – UTC timestamp at which a later filed revision superseded this one.
Noneunlessstate is PRESENTADO_SUPERSEDIDO.discarded_at – UTC timestamp captured when the revision is moved to
DESCARTADO.Noneotherwise.discarded_by – Actor label captured when the revision is moved to
DESCARTADO.Noneotherwise.discard_reason – Audit reason captured when the revision is moved to
DESCARTADO.Noneotherwise.
- Parameters:
calculation_revision_id (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=64, max_length=64, pattern=^[0-9a-f]{64}$, ascii_only=None)])
work_unit_id (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=64, max_length=64, pattern=^[0-9a-f]{64}$, ascii_only=None)])
state (CalculationRevisionState)
source_transaction_ids (tuple[Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=64, max_length=64, pattern=^[0-9a-f]{64}$, ascii_only=None)], ...])
borrador_snapshot_id (str | None)
bindings_sourced_from_borrador (tuple[BindingId, ...])
observations (tuple[CasillaObservation, ...])
unresolved_outcomes (tuple[RegistryCalculationUnresolvedOutcome, ...])
ledger_filing_snapshot (LedgerFilingSnapshot | None)
ledger_filing_evidence (LedgerFilingEvidence | None)
source_provenance (tuple[CalculationSourceRef, ...])
detail_rows (tuple[Modelo184MemberRow | Modelo232VinculadaRow | Modelo349OperadorRow | Modelo349RectificacionRow | Modelo347ContraparteRow, ...])
created_at (datetime)
updated_at (datetime)
verified_at (datetime | None)
verified_by (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=64, pattern=None, ascii_only=None)] | None)
filed_at (datetime | None)
filed_by (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=64, pattern=None, ascii_only=None)] | None)
superseded_at (datetime | None)
discarded_at (datetime | None)
discarded_by (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=64, pattern=None, ascii_only=None)] | None)
discard_reason (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=500, pattern=None, ascii_only=None)] | None)
amendment_kind (CalculationRevisionAmendmentKind | None)
amends_filing_record_id (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=64, max_length=64, pattern=^[0-9a-f]{64}$, ascii_only=None)] | None)
amendment_reason (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=500, pattern=None, ascii_only=None)] | None)
- calculation_revision_id: CalculationRevisionId¶
- work_unit_id: WorkUnitId¶
- state: CalculationRevisionState¶
- input_values_by_casilla_id: Mapping[CasillaId, str]¶
- binding_overrides: Mapping[BindingId, str]¶
- row_binding_values: Mapping[BindingId, Mapping[str, str]]¶
- relation_overrides: Mapping[RelationId, str]¶
- source_transaction_ids: tuple[CalculationRevisionId, ...]¶
- borrador_snapshot_id: str | None¶
- bindings_sourced_from_borrador: tuple[BindingId, ...]¶
- casilla_values: Mapping[CasillaId, Decimal]¶
- observations: tuple[CasillaObservation, ...]¶
- unresolved_outcomes: tuple[RegistryCalculationUnresolvedOutcome, ...]¶
- ledger_filing_snapshot: LedgerFilingSnapshot | None¶
- ledger_filing_evidence: LedgerFilingEvidence | None¶
- source_provenance: tuple[CalculationSourceRef, ...]¶
- detail_rows: tuple[ModeloDetailRow, ...]¶
- created_at: datetime¶
- updated_at: datetime¶
- verified_at: datetime | None¶
- verified_by: ModeloActorLabel | None¶
- filed_at: datetime | None¶
- filed_by: ModeloActorLabel | None¶
- superseded_at: datetime | None¶
- discarded_at: datetime | None¶
- discarded_by: ModeloActorLabel | None¶
- discard_reason: _DiscardReason | None¶
- amendment_kind: CalculationRevisionAmendmentKind | None¶
- amends_filing_record_id: CalculationRevisionId | None¶
- amendment_reason: _DiscardReason | None¶
- class CalculationRevisionCatalogue(**data)[source]¶
Bases:
BaseModelImmutable catalogue of every calculation revision in storage.
- Parameters:
revisions (Mapping[str, CalculationRevision])
- revisions: Mapping[str, CalculationRevision]¶
- for_work_unit(work_unit_id)[source]¶
Return every revision attached to one work unit.
- Return type:
- Returns:
Tuple of
CalculationRevisionrecords for the given work unit.- Parameters:
work_unit_id (str)
- exception LedgerFilingCoverageError(message=None, *, context=None, suggestion=None, translated_message=None)[source]¶
Bases:
ModeloErrorRaised when a persisted revision’s snapshot and evidence contributor sets diverge.
A ledger-derived revision bundles a
ledger_filing_snapshot(the fingerprinted contributor set) and aledger_filing_evidence(the typed fact basis). The two are projected from the samesource_transaction_idsand MUST cover the same contributors. A divergence on read-back means a contributor row was silently dropped after persistence; this gate surfaces it on load rather than letting the filing artefact ship an unexplainable casilla.- Parameters:
- Return type:
None
- code: ClassVar[ErrorCode]¶
- assert_revision_snapshot_evidence_coverage(revision)[source]¶
Cross-check a loaded revision’s snapshot and evidence contributor coverage.
- Parameters:
revision (
CalculationRevision) – TheCalculationRevisionloaded from persistence.- Return type:
Post-roundtrip validator (per the modelo-export-evidence-parity discipline): when both
ledger_filing_snapshotandledger_filing_evidenceare present, theirrowscontributor (transaction_id) sets MUST be equal. A revision with neither (a non-ledger or borrador revision) passes trivially. RaisesLedgerFilingCoverageErrornaming the divergent contributors.