cadrumo.application.modelo.revision_persistence module

Repository mutation helpers for modelo calculation and filing transitions.

The calculate path stores draft CalculationRevision rows with their provenance-bearing CasillaObservation entries, advances the parent WorkUnit pointer, and emits modelo.calculation.created through the BucketEventHistoryRepository catalogue. The event is a lightweight join record; full legal/source provenance remains on the persisted calculation revision’s observations, with has_provenance signalling that the join is grounded.

The filing path runs here only after its caller has passed readiness, workflow, and clean-state gates. It records the local/internal filing transition: create a current ModeloRecord, supersede any prior current filing for the work target, move calculation revisions into PRESENTADO states, and co-emit the TransactionRevisionParticipationIndex writes, cross-period observation projections, and Modelo 303 settlement prorrata register writeback. It never submits to AEAT and never turns the non-official app_filing carry projection into filing-grade external evidence.

See also

file_modelo_revision():

Orchestrates preconditions and result-disposition resolution before delegating successful mutations here.

import_external_filing_evidence():

Separate import boundary that creates current records with ExternalEvidence; this persistence helper deliberately creates local records without that payload.

persist_filed_revision_observation():

Projects filed casilla observations into non-official cross-period carry evidence.

ProrrataRegisterRepositoryProtocol:

Profile-scoped repository capability co-emitted for Modelo 303 settlement prorrata writeback.

ProrrataRegisterEntry:

Typed row updated with definitive percentage and annual volume inputs.

emit_modelo_bucket_event(*, repository, bucket_id, event_type, occurred_at, actor, object_type, object_id, payload)[source]

Emit one BucketEvent under the modelo payload contract.

Modelo’s narrow wrapper over emit_bucket_event(): it supplies _BUCKET_EVENT_PAYLOAD_VERSION so no modelo call site restates it, and adds nothing else. The shared derive-append-save sequence lives in the domain beside append_bucket_event(), because it composes only bucket domain types and every emitting domain needs it — keeping it here made this module a hub that peer application packages had to reach up into.

The returned event is the durable bucket-scoped audit pointer for the modelo mutation. Payloads stay compact and reference the owning calculation revision, filing record, or work unit instead of duplicating their catalogued state.

Return type:

BucketEvent

Parameters:
build_modelo_bucket_event(*, bucket_id, event_type, occurred_at, actor, object_type, object_id, payload)[source]

Derive one modelo BucketEvent without persisting it.

The non-saving counterpart of emit_modelo_bucket_event(), supplying the same _BUCKET_EVENT_PAYLOAD_VERSION so a co-committed event cannot declare a different payload contract than an emitted one. Pair it with domain.buckets.event_repository.bucket_event_history_write() to commit the event in the same unit of work as the catalogues it records.

Return type:

BucketEvent

Parameters:
persist_calculation_revision(*, work_unit_id, registry_snapshot_ref, work_unit, work_units, work_units_revision_id, input_values_by_casilla_id, binding_overrides, row_binding_values, row_source_identities, row_casilla_values, row_casilla_provenance, relation_overrides, casilla_values, source_transaction_ids, borrador_snapshot_id, bindings_sourced_from_borrador, observations, cleared_casilla_ids=(), unresolved_outcomes=(), source_provenance, source_issues=(), filing_instance_evidence=None, m303_regimen_simplificado_annual_summary_handoff=None, detail_rows, formula_count, actor, now, calculation_repository, work_unit_repository, bucket_event_repository, ledger_filing_snapshot=None, m210_official_tipo_renta_code=None, m210_gross_income_source_mode=None, additional_secure_object_writes_for_revision=None)[source]

Persist a freshly calculated draft revision and return the CalculationRevision.

Returns the existing duplicate when an identical revision is already persisted. The content-addressed revision id includes manual casilla inputs, binding/relation overrides, ledger source transactions, borrador provenance, detail rows, and calculated casilla values. The supplied CasillaObservation rows carry the legal and source provenance persisted with a new calculation revision.

The source_provenance tuple carries the resolver-level source-mesh trace (CalculationSourceRef rows projected from the calculation source mesh) so the persisted revision records which resolver mesh and which upstream source objects produced it. The tuple is required at every call site (including an explicit empty decision) and participates in derive_calculation_revision_id through an order-canonical identity payload.

ledger_filing_snapshot pins the ledger state the casilla values were computed FROM, for a ledger-derived draft. It is the anchor the verify-time drift gate compares against the live ledger, and it exists because the snapshot is otherwise captured only on a granted verify — leaving exactly the drafts that need guarding with nothing to compare. A granted verify overwrites it, alongside the evidence bundle, with the state it froze.

The emitted BucketEvent uses the revision id as object_id and includes a has_provenance payload flag plus a source_provenance_count and an order-independent source_provenance_trace_sha256 digest of the source-mesh trace. Audit readers can therefore use the event as a compact pointer back to the persisted CalculationRevision, and detect a source-connectivity change from the digest without decrypting the revision, instead of treating bucket history as the standalone provenance store.

The duplicate branch still advances or confirms the work-unit pointer under the SAME work_units_revision_id compare-and-swap guard the new-revision branch uses – it never falls back to an unguarded pointer save, and it still invokes additional_secure_object_writes_for_revision when supplied, so a caller relying on a co-committed side effect (a guarded edit’s result receipt, for instance) gets it on the duplicate path exactly as reliably as on the new-revision path.

additional_secure_object_writes_for_revision lets a caller land its own atomic writes (an edit-contract mutation-result receipt, most notably) in the SAME secure-object transaction as the revision, pointer, and bucket event this function already commits, without this function knowing anything about the caller’s payload shape. It is a FACTORY rather than a plain tuple because the content-addressed revision id (and, on the new-revision path only, the fresh bucket-event id) are not known until this function derives them – a receipt needs the revision id, so the caller cannot build its write before calling in. The factory receives the resolved calculation_revision_id and the fresh bucket-event id, or None for the latter on the duplicate-result path where no new event is emitted, and returns the writes to co-commit. None by default, so every existing caller’s write set is unchanged.

Return type:

CalculationRevision

Parameters:
require_filing_instance_evidence_for_work_unit(*, work_unit, revision)[source]

Return persisted evidence only when it is valid for the selected work unit.

Core types: CalculationRevision.

Return type:

FilingInstanceEvidence | None

Parameters:
prior_domiciliation_payload(election)[source]

Project the prior-domiciliation election onto its MODELO_FILED payload keys.

Every key is emitted in both branches, in one order, so the event payload shape never depends on whether an election was resolved. An absent election and an election with an absent baseline field are both recorded as the empty-string absence marker the payload contract already used.

Return type:

dict[str, str]

Parameters:

election (PriorDomiciliationElectionProjection | None)

persist_filed_revision(*, target, work_unit, work_units, notes, actor, now, calculation_repository, filing_repository, work_unit_repository, bucket_event_repository, calculation_observation_repository, iva_compensation_history_repository, participation_index_repository, prorrata_register_repository, operation, result_disposition=None, prior_domiciliation_election=None, taxpayer_nif=None, justificante_repository=None)[source]

Persist a verified-complete calculation revision and return a ModeloRecord.

The caller has already run verification/workflow/readiness gates. The target CalculationRevision is the verified-complete source revision that becomes PRESENTADO when this transition succeeds. The parent WorkUnit is advanced to the new current filing record after the calculation and filing catalogues are saved.

The filed revision’s observations are written to the pending-local observation layer in the same unit of work as MODELO_FILED, so later calculations can carry them through the previous_filing resolver. The record is stamped with NON-official app_filing and never satisfies the cross-period clean-state filing gate; use import_external_filing_evidence() when the current record must carry ExternalEvidence.

result_disposition is resolved once at the calculate/file boundary by resolve_modelo_result_disposition. Modelo 303 observation persistence retains that typed fact with app-filing provenance and derives carry only through the shared canonical ingress; it never inherits a boolean default.

For Modelo 303 settlement periods, the filed definitive prorrata percentage and annual volume inputs are also co-emitted to the profile ProrrataRegister through ProrrataRegisterRepositoryProtocol in the same secure-object save as the filing catalogue and filed calculation revision.

Return type:

ModeloRecord

Parameters:
supersede_prior_current_filing(prior_current, *, filing_catalogue, revisions, new_filing_id, now)

Supersede the prior current filing record and its PRESENTADO revision.

Marks prior_current SUPERSEDIDO (stamped with new_filing_id) and, when its calculation revision is still PRESENTADO, advances that revision to PRESENTADO_SUPERSEDIDO. A prior entry AEAT never confirmed was never presented, so it is also marked DESCARTADA. Returns the updated (filing_catalogue, revisions).

Return type:

tuple[ModeloRecordCatalogue, CalculationRevisionCatalogue]

Parameters: