cadrumo.domain.calculations.registry.bindings module

Data binding helpers for registry-backed factual inputs.

This module owns the CasillaObservation envelope emitted by the formula runtime and the BindingDefinition helper surface that turns factual binding values into bound casilla inputs.

See also

domain.calculations.registry.formula_runtime

Runtime that emits typed observations and consumes resolved bound casilla inputs.

domain.calculations.registry.formula_initial_values

Initial-value assembler that calls the bound-casilla helpers here.

domain.calculations.registry.schema

Registry schema definitions for casillas, bindings, and revisions.

class CasillaObservationValueKind(*values)[source]

Bases: StrEnum

Whether an observed casilla value is a number or free text.

DECIMAL
TEXT
CasillaObservationValueKindValue

The same vocabulary for a strict model field.

alias of Literal[DECIMAL, TEXT]

class CasillaObservation(**data)[source]

Bases: BaseModel

One typed casilla observation emitted by the formula runtime.

Carries a CasillaId, final scalar value (numeric decimal.Decimal or validated text), required legal/source provenance, and optional formula lineage. When formula_id is set, the runtime computed this casilla and operand_refs / operand_values trace its inputs while operand_casilla_refs carries the casilla-id-only projection; when formula_id is None the casilla was supplied as input (manual / bound) and the trace fields are empty.

Used as the primary storage for RegistryCalculationResult; derived values and entries views project from it.

Parameters:

data (Any)

casilla_id: CasillaId
value_kind: CasillaObservationValueKindValue
value: Decimal | str
formula_id: FormulaId | None
op: str | None
operand_refs: tuple[str, ...]
operand_casilla_refs: tuple[CasillaId, ...]
operand_values: tuple[Decimal, ...]
legal_refs: tuple[LegalRefId, ...]
source_refs: tuple[SourceRefId, ...]
absent_by_design: bool
class RegistryModeloObservation(**data)[source]

Bases: BaseModel

Observed casilla values from a filed declaration.

Storage is observations: a typed tuple of CasillaObservation carrying full formula provenance. The casilla_values property provides a read-only mapping view for downstream consumers.

Parameters:

data (Any)

modelo: ModeloId
filing_period: Period | None
filing_year: FilingYear
period: RegistryPeriodCode

A registry coordinate, not necessarily a period a taxpayer files in: a non-filing modelo such as the censal 036 is addressed by its event (alta, modificacion, baja) rather than by a calendar period. The span-capable filing_period above stays None for those.

observations: tuple[CasillaObservation, ...]
property casilla_values: Mapping[CasillaId, Decimal]

casilla_id -> Decimal derived from typed observations.

Deliberately a plain @property and NOT a pydantic computed_field: the typed envelope (observations) is canonical storage. Exposing this derived view in JSON would round-trip self-incompatibly under extra='forbid' because the loader would refuse the duplicate field on the way back in.

Type:

Read-only mapping view

resolve_bound_casilla_binding_value(casilla, facts)[source]

Resolve equivalent binding facts for one casilla, rejecting disagreements.

A bound CasillaDefinition can declare reviewed alternate bindings when multiple registry source paths represent the same factual amount. Supplying two equivalent source values is legal only if they agree exactly; otherwise accepting either one would silently over- or under-declare the downstream calculation.

Return type:

tuple[Decimal | None, tuple[TypeAliasType, ...]]

Parameters:
resolve_available_bound_inputs_by_casilla_id(revision, binding_values)[source]

Project available binding values into input values keyed by bound casilla.id.

The ModeloRevision supplies the bound casilla-to-binding mapping; only values already present in binding_values are projected. Missing optional bindings are skipped rather than treated as registry errors, which lets calculate paths combine partial source mesh output with caller overrides before the engine runs.

Parameters:
Return type:

dict[TypeAliasType, Decimal]

Returns:

A dict keyed by CasillaId for every bound casilla whose binding value is currently available.

See also

resolve_bound_casilla_binding_value():

Per-casilla primitive this projection folds over, including its refusal of disagreeing equivalent alternate bindings.

class IvaCompensationAnnualPartitionRequirement(**data)[source]

Bases: BaseModel

One typed annual Modelo 303 compensation-partition projection.

The annual partition is a distinct FIFO resolution family, rather than a relation fold. Its bindings nevertheless share one source fact: four Modelo 303 state observations and the target revision’s declared treatment of that source. This projection is the only interpretation of the binding selectors consumers may use; it retains each target slot and the complete source/provenance contract without exposing raw selector mappings.

Parameters:

data (Any)

source_modelo: ModeloId
source_periods: tuple[str, ...]
source_casilla_ids: tuple[CasillaId, ...]
binding_ids: tuple[BindingId, ...]
last_period_amount_binding_id: BindingId | None
generated_not_in_last_amount_binding_id: BindingId | None
dependency_treatment: str
legal_refs: tuple[LegalRefId, ...]
source_refs: tuple[SourceRefId, ...]
iva_compensation_annual_partition_requirement(revision)[source]

Project the revision’s annual compensation-partition bindings once.

Returns None when the revision declares no partition bindings. When it does, every binding must name the same typed source selector and each of the two partition outputs may be targeted at most once. The source’s dependency treatment comes directly from the revision classification and stays empty only when that classification is absent; consumers must not reconstruct or default it.

Core types: ModeloRevision.

Return type:

IvaCompensationAnnualPartitionRequirement | None

Parameters:

revision (ModeloRevision)

binding_source_casilla_ids(binding)[source]

Return the typed source casilla ids the binding’s provider member declares.

The answer is read off the constructed provider member, not re-parsed from a dumped mapping: the union already narrowed the row to one class, so this is a structural match over the members that carry a source coordinate.

An empty tuple means the family declares no source casilla, which the registration states independently. A family whose registration says it names one and which no branch below handles is refused rather than silently answered with the empty tuple.

Raises:

RegistryValidationError – The provider’s registration declares a source casilla coordinate that no branch here narrows.

Return type:

tuple[TypeAliasType, ...]

Parameters:

binding (BindingDefinition)

binding_source_modelo(binding)[source]

Return the typed source modelo the binding’s provider member declares.

None means the family declares no source modelo. A family whose registration says it declares one and which no branch below handles is refused rather than silently answered with None.

Raises:

RegistryValidationError – The provider’s registration declares a source modelo coordinate that no branch here narrows.

Return type:

TypeAliasType | None

Parameters:

binding (BindingDefinition)

validate_binding_selector_shape(binding)[source]

Validate a binding against its provider kind’s single enrolled validator.

Dispatch is one join through the canonical enrollment authority: the provider member’s own discriminator selects its BindingProviderRegistration, whose validator is the family’s build-time gate. A kind with no registration cannot reach here – the registration table refuses to import unless it covers exactly the provider union, and the union refuses an unknown member at construction – so this function holds no opinion about membership.

A registration may enrol no validator at all. That is the stated answer for a family whose provider member is its own complete gate: the union built that member from the authored row, so there is nothing left to check and no diagnostic to earn.

Each family validator validates the provider shape (projected through the same normalised mapping the resolve-time helpers see, so the gate is never stricter than runtime) and lifts that family’s op/fact cross-invariants to build time. Failures accumulate as diagnostic strings rather than raising, preserving the underlying pydantic field error, so the snapshot-build gate collects every failure across a revision in one pass.

Return type:

list[str]

Parameters:

binding (BindingDefinition)