cadrumo.application.modelo.calculate_input module

Typed input bundle and validation for modelo work calculation.

This module converts CLI override tokens into a WorkCalculateInputBundle, resolves the active work unit’s ModeloRevision, and validates canonical CasillaId values, binding channels, relation ids, and shortcut-derived semantic-role casillas before the calculate service persists a CalculationRevision.

The application result pairs that persisted revision with its parent WorkUnit and any non-blocking CalculationSourceDiagnostic rows surfaced by bucket aggregation or post-calculation advisory collectors.

See also

cadrumo.entrypoints.cli._modelo_work_calculate_cli:

Parses the operator-facing modelo work calculate command and calls this module to build the input bundle.

cadrumo.application.modelo.calculation_actions.calculate_modelo_revision_from_bucket_aggregation_with_diagnostics():

Consumes the validated bundle and persists the draft calculation revision.

cadrumo.application.modelo.calculation_resolution:

Merges caller, backend, profile, relation, and borrador channels before registry-engine execution.

cadrumo.application.modelo.semantic_role_resolution.casilla_id_for_unique_revision_semantic_role():

Resolves shortcut inputs onto the unique casilla declared by a revision.

exception ModeloCalculateInputError(message=None, *, context=None, translated_message=None)[source]

Bases: ModeloError

Raised when operator-supplied modelo calculation inputs are invalid.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • translated_message (str | None)

Return type:

None

code
exception ModeloCalculateDetailRowsError(message=None, *, context=None, translated_message=None)[source]

Bases: ModeloCalculateInputError

Raised when detail rows violate modelo calculation preconditions.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • translated_message (str | None)

Return type:

None

code
exception ModeloCalculateDecimalInputError(message=None, *, context=None, translated_message=None)[source]

Bases: ModeloCalculateInputError

Raised when a calculation override value is not decimal-shaped.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • translated_message (str | None)

Return type:

None

code
exception ModeloCalculateTextInputError(message=None, *, context=None, translated_message=None)[source]

Bases: ModeloCalculateInputError

Raised when a --casilla override targets a text casilla with a value its type refuses.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • translated_message (str | None)

Return type:

None

code
exception ModeloCalculateCasillaInputError(message=None, *, context=None, translated_message=None)[source]

Bases: ModeloCalculateInputError

Raised when a casilla override cannot be resolved for the active revision.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • translated_message (str | None)

Return type:

None

code
exception ModeloCalculateBindingInputError(message=None, *, context=None, translated_message=None)[source]

Bases: ModeloCalculateInputError

Raised when a --binding override cannot be resolved for the active revision.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • translated_message (str | None)

Return type:

None

code
exception ModeloCalculateRelationInputError(message=None, *, context=None, translated_message=None)[source]

Bases: ModeloCalculateInputError

Raised when a --relation override cannot be resolved for the active revision.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • translated_message (str | None)

Return type:

None

code
exception ModeloCalculateShortcutInputError(message=None, *, context=None, translated_message=None)[source]

Bases: ModeloCalculateInputError

Raised when grouped calculation shortcut inputs are incomplete.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • translated_message (str | None)

Return type:

None

code
exception ModeloCalculateSemanticRoleError(message=None, *, context=None, translated_message=None)[source]

Bases: ModeloCalculateInputError

Raised when a registry revision lacks a semantic-role target required by a shortcut.

Parameters:
  • message (str | None)

  • context (Mapping[str, object] | None)

  • translated_message (str | None)

Return type:

None

code
class WorkCalculateInputBundle(casilla_inputs, text_casilla_inputs, m210_official_tipo_renta_code, binding_values, enum_binding_values, relation_values, detail_rows, borrador_snapshot_id, filing_instance_evidence=None, m210_gross_income_source_mode=M210GrossIncomeSourceMode.MANUAL, shortcut_diagnostics=())[source]

Bases: object

Application-facing input channels for one modelo work calculate run.

The bundle is the handoff from CLI parsing to application calculation. It separates manual casilla inputs, text casilla inputs, decimal binding overrides, enum binding overrides, relation values, typed detail rows, and the optional borrador snapshot id so each downstream channel keeps its registry-declared type. text_casilla_inputs carries operator-supplied text-scalar casilla values — every family whose registry_scalar_value_type() is "str", such as Modelo 210’s tipo_renta (text) and Modelo 303’s decl.periodo (period_code) — on a channel parallel to casilla_inputs: the registry engine’s calculate_registry_snapshot(text_inputs=...) reads it for categorical formula dispatch, and it rides into the persisted CalculationRevision input_values_by_casilla_id field so the verification layer’s required-casilla and casilla_equals_implies_nonzero predicate checks can see it. It is never folded into the Decimal casilla_values projection.

Parameters:
casilla_inputs: Mapping[TypeAliasType, Decimal]
text_casilla_inputs: Mapping[TypeAliasType, str]
m210_official_tipo_renta_code: str | None
binding_values: Mapping[TypeAliasType, Decimal]
enum_binding_values: Mapping[TypeAliasType, str]
relation_values: Mapping[TypeAliasType, Decimal]
detail_rows: tuple[Modelo184MemberRow | Modelo232VinculadaRow | Modelo349OperadorRow | Modelo349RectificacionRow | Modelo347ContraparteRow | Modelo210AgrupacionRentaRow, ...]
borrador_snapshot_id: str | None
filing_instance_evidence: FilingInstanceEvidence | None
m210_gross_income_source_mode: M210GrossIncomeSourceMode
shortcut_diagnostics: tuple[CalculationSourceDiagnostic, ...]

Non-blocking advisories raised while resolving shortcut inputs.

Carries the DT 12ª apartado-3 window diagnostics (apply_calculation_shortcut_inputs()) so the calculate service can fold them into its source_diagnostics / source_advisories channel. The shortcut path is the only site with the contingencia/rescate year facts, so the advisory originates here and rides the bundle to the operator surface.

classmethod build(*, casilla_inputs, binding_values, enum_binding_values, relation_values, detail_rows, borrador_snapshot_id, filing_instance_evidence=None, text_casilla_inputs=None, m210_official_tipo_renta_code=None, m210_gross_income_source_mode=M210GrossIncomeSourceMode.MANUAL, shortcut_diagnostics=())[source]

Freeze CLI-assembled mappings before crossing into calculation services.

Returns:

The frozen calculate input bundle.

Return type:

WorkCalculateInputBundle

Parameters:
optional_binding_values()[source]

Return decimal binding values using the calculation-service optional contract.

Return type:

Mapping[TypeAliasType, Decimal] | None

optional_enum_binding_values()[source]

Return enum binding values using the calculation-service optional contract.

Return type:

Mapping[TypeAliasType, str] | None

optional_relation_values()[source]

Return relation values using the calculation-service optional contract.

Return type:

Mapping[TypeAliasType, Decimal] | None

optional_text_casilla_inputs()[source]

Return text casilla inputs using the calculation-service optional contract.

Return type:

Mapping[TypeAliasType, str] | None

class Modelo202ModalitySummary(modality, reason)[source]

Bases: object

Application summary of the Modelo 202 Art. 40.2 / 40.3 modality.

The calculate CLI includes this advisory when the work unit is a Modelo 202 calculation so the operator can see which registry modality the profile selected and why.

Parameters:
modality: str
reason: str
class ModeloWorkCalculationServiceResult(revision, work_unit, modality=None, source_diagnostics=(), plazo_resolutions=())[source]

Bases: object

Application-owned result for one modelo work calculate command.

revision is the persisted CalculationRevision; work_unit is the parent WorkUnit loaded after persistence so renderers do not have to repeat the lookup. The optional advisory summaries are presentation data derived from registry applicability and authorization metadata.

source_diagnostics carries the NON-blocking CalculationSourceDiagnostic rows the source mesh and post-calculation advisory collectors raised. They include unresolved or deferred binding sources, unrouted ledger observations, and calculate-grade official-box / prior-payment / settlement advisories. The calculate verb succeeded and persisted the revision regardless; surfacing these rows keeps omitted or degraded source evidence operator-visible (no-silent-under-declaration). Each diagnostic’s message carries the evidence needed by the CLI renderer.

Parameters:
revision: CalculationRevision
work_unit: WorkUnit
modality: Modelo202ModalitySummary | None
source_diagnostics: tuple[CalculationSourceDiagnostic, ...]
plazo_resolutions: tuple[M210PlazoResolution, ...]
calculate_modelo_work_revision(*, work_unit_id, actor, inputs, ports, profile=None)[source]

Persist a draft calculation revision as a ModeloWorkCalculationServiceResult.

The function forwards the already validated WorkCalculateInputBundle into the bucket-aggregation calculation path, reloads the parent WorkUnit, and attaches any Modelo 202 modality, authorization, or non-blocking source diagnostics needed by the CLI payload. profile is the work profile the command already loaded; when omitted, the calculation loads it once. Every profile read below uses the profile the calculation checked.

See also

cadrumo.application.modelo.calculation_actions.calculate_modelo_revision_from_bucket_aggregation_with_diagnostics():

Runs source aggregation and persists the calculation revision.

cadrumo.entrypoints.cli._modelo_work_calculate_cli._run_work_calculate():

Calls this service and serialises the result for the operator.

Return type:

ModeloWorkCalculationServiceResult

Parameters:
build_work_calculate_input_bundle(*, work_unit_id, ports, casilla_overrides, binding_overrides, relation_overrides, detail_rows, borrador_snapshot_id, filing_instance_evidence=None, m210_gross_income_source_mode=M210GrossIncomeSourceMode.MANUAL, prestacion_inss_exenta=None, rescate_plan_pensiones_capital=None, rescate_plan_pensiones_aportaciones_pre_2007=None, rescate_plan_pensiones_aportaciones_totales=None, rescate_plan_pensiones_tipo=None, rescate_plan_pensiones_contingencia_year=None, rescate_plan_pensiones_rescate_year=None, sal_beneficio_neto=None, sal_reserva_dotada=None, sal_capital_social=None, autoconsumo_promotor_base=None, operation, profile=None)[source]

Build a WorkCalculateInputBundle from operator-supplied tokens.

The active work unit determines the ModeloRevision used for every validation step. --casilla values must be canonical casilla ids; printed numbers and ambiguous noncanonical references are refused. A --casilla key whose registry CasillaDefinition declares a text-scalar data_type — every family whose registry_scalar_value_type() is "str", so text (Modelo 210’s tipo_renta) alongside period_code, nif, iban and the rest — is routed onto the parallel text-casilla channel, canonicalised by that family’s own declared validator instead of being forced through the decimal parser; every other --casilla key keeps the existing decimal-only contract. Membership is derived from the type family rather than keyed on one literal member, so a string-family override can never be silently routed to the Decimal channel. --binding is routed by the registry-declared channel, so enum bindings stay as strings, decimal bindings are parsed as Decimal, and date-valued profile bindings are rejected with profile guidance. --relation values must match declared relation ids.

Detail rows are checked before engine dispatch, and shortcut flags are translated into semantic-role casilla values or backend-owned bindings by cadrumo.application.modelo.calculate_input.apply_calculation_shortcut_inputs(). profile is the work profile the command already loaded; when omitted, it is loaded where a profile-backed shortcut first needs it.

Return type:

WorkCalculateInputBundle

Parameters:
is_detail_casilla_override_key(key, *, operation)[source]

Return whether key names a reserved detail-row alias, not a scalar casilla.

Return type:

bool

Parameters:
modelo_202_modality_for_work_unit(work_unit)[source]

Return a Modelo202ModalitySummary for work_unit when applicable.

Non-Modelo-202 work units return None. For Modelo 202, the active profile projection is passed to the registry applicability helper so the calculate payload can disclose whether Art. 40.2 or Art. 40.3 was selected.

Return type:

Modelo202ModalitySummary | None

Parameters:

work_unit (WorkUnit)

modelo_202_modality_for_record(work_unit, record)[source]

Return the Modelo 202 modality summary for an already-loaded profile record.

Core types: UserProfileRecord.

Return type:

Modelo202ModalitySummary | None

Parameters:
apply_calculation_shortcut_inputs(*, work_unit, casilla_inputs, binding_values, fact_context, prestacion_inss_exenta=None, rescate_plan_pensiones_capital=None, rescate_plan_pensiones_aportaciones_pre_2007=None, rescate_plan_pensiones_aportaciones_totales=None, rescate_plan_pensiones_tipo=None, rescate_plan_pensiones_contingencia_year=None, rescate_plan_pensiones_rescate_year=None, sal_beneficio_neto=None, sal_reserva_dotada=None, sal_capital_social=None, autoconsumo_promotor_base=None, operation, profile=None)[source]

Apply backend-owned tax shortcut inputs for a calculation command.

The CLI may parse option strings into typed values, but legal-rule computations, semantic casilla routing, and special binding injection belong to the application layer. INSS maternity/paternity, maternity deduction, DT 12 pension-rescue reduction, and SAL reserve inputs resolve to unique semantic-role casillas. The Modelo 303 autoconsumo-promotor shortcut writes the backend-owned binding consumed by the registry engine.

The DT 12ª pension-rescate shortcut is fact-gated by the apartado-3 time window (LIRPF DT 12ª.4, added by Ley 26/2014). When the operator declares the contingencia year and the window predicate (dt12_regime_window_eligibility()) proves the window CLOSED, the 40% reducción injection is WITHHELD — the legally correct no-régimen result, since applying an out-of-window reducción would be a silent over-reduction (under-declaration of tax per no-silent-under-declaration). When the window is open the reducción injects as usual; when the contingencia year is absent the reducción injects with an unverified-window advisory. Every branch surfaces a non-blocking CalculationSourceDiagnostic; calculate never aborts on the window verdict.

Returns:

resolved casilla inputs, resolved decimal binding values, and the non-blocking DT 12ª window advisory diagnostics (empty when no pension rescate was supplied).

Return type:

A triple

Parameters:

See also

cadrumo.application.modelo.semantic_role_resolution.casilla_id_for_unique_revision_semantic_role():

Selects the unique semantic-role casilla for shortcut values.

decimal_binding_value(raw_value, binding)

Parse a --binding decimal value, teaching the accepted encoding on failure.

For a boolean-typed decimal-channel binding (the Modelo 100 estimación-directa modality flag), a non-numeric value such as false otherwise produces the opaque “is not a decimal” error. This raises an instructive refusal that names the accepted 0 / 1 encoding and what each value means, derived from the binding’s boolean selector rather than a per-form hardcoded table.

Conformance is judged by the same canonical grammar _decimal() applies, so a value whose numeric meaning is not what it appears (scientific notation, a leading +, a comma decimal) refuses here too instead of being silently coerced.

Return type:

Decimal

Parameters:
validated_binding_input_channel(key, revision, known_binding_ids, enum_channel_ids)

Return the registry-declared engine channel for a --binding override.

Routes the override by the binding’s declared input channel, not by parse success: a binding the revision’s formulas consume as a string enum key (enum_consumed_binding_ids) is an "enum" channel and its override is carried verbatim; every other declared binding is a "decimal" channel whose override the caller coerces with _decimal() (so a malformed numeric value REFUSES instead of silently reclassifying as an enum string). An unknown binding id refuses with the accepted set, per no-silent-under-declaration and the CLI-Choice-hint mandate.

Return type:

tuple[TypeAliasType, Literal['decimal', 'enum']]

Parameters: