Source code for cadrumo.application.calculations.errors
"""Typed exception hierarchy for the calculations application layer.These exceptions are raised by previous-filing, binding-prefill, IVAcompensation, and encrypted observation-repository services at the applicationboundary. Every class inherits from :class:`~core.errors.hierarchy.CoreError`;validation failures use :class:`~core.errors.hierarchy.CoreValidationError` so CLIand API callers receive registry-backed envelopes instead of generic``ValueError`` or ``TypeError`` failures.Every refusal raised across this package carries a registered locale key plusmachine facts; no raise site authors an operator-facing sentence, so``str(exc)`` renders the key and the prose is resolved once, per locale, at thepresentation boundary.A narrow subset is additionally a *safety* disposition: the calculationobserved evidence whose contradiction cannot be resolved by choosing one side,because either choice silently changes a declared amount. Those raise sitesattach a :class:`~application.operator_actions.models.PreconditionVerdict` whose``no_recovery_outcome`` is :attr:`~core.operator_action_enums.NoRecoveryOutcome.SAFETY`, so the CLIboundary projects an explicit "there is deliberately no recovery here" insteadof manufacturing a retry that would re-derive the same contradiction.See Also: :mod:`application.calculations.binding_prefill`: Previous-filing binding readers that raise :exc:`BindingPrefillTypeError`. :mod:`application.calculations.iva_compensation_history`: Modelo 303 IVA compensation carry-forward readers that raise :exc:`IvaCompensationModeloError`. :mod:`application.calculations.observations_repository`: Encrypted observation storage that raises :exc:`ObservationKeyError` and :exc:`ObservationCasillaReferenceError`."""from__future__importannotationsfromcollections.abcimportMappingfromenumimportStrEnumfromtypingimportTYPE_CHECKINGfrom...core.errors.hierarchyimportCoreError,CoreValidationError,TerminalPreconditionErrorMixinfrom...core.operator_action_enumsimportActionEvidenceProvenance,NoRecoveryOutcomeifTYPE_CHECKING:from..operator_actions.modelsimportPreconditionVerdict_CalculationPreconditionErrorMixin=TerminalPreconditionErrorMixin[PreconditionVerdict]else:_CalculationPreconditionErrorMixin=TerminalPreconditionErrorMixin
[docs]classCalculationRefusalPrecondition(StrEnum):"""Closed failed-condition identities for calculation safety dispositions. Membership is deliberately narrow. A condition earns a place here only when the refusal reports two sources of the same declared amount that disagree, so no automatic remedy exists: resolving it means deciding which figure the taxpayer actually declared, which is an operator judgement made against AEAT's own record. An evidence-incomplete refusal an operator fixes by supplying better evidence is not a safety disposition and stays a plain typed refusal. """M303_CARRY_DISPOSITION_CONSISTENT="calculations.m303_carry.disposition_consistent"M303_CARRY_DERIVATION_CONSISTENT="calculations.m303_carry.derivation_consistent"M303_CARRY_MATCHES_REGISTRY_FORMULA="calculations.m303_carry.matches_registry_formula"
[docs]defcalculation_no_recovery_verdict(condition:CalculationRefusalPrecondition,*,facts:Mapping[str,str|int|bool],outcome:NoRecoveryOutcome=NoRecoveryOutcome.SAFETY,)->PreconditionVerdict:"""Return one explicitly non-actionable outcome for a calculation refusal. The facts name exactly what the two disagreeing sources reported; the closed outcome is what stops a downstream boundary from manufacturing a recovery command that would simply re-derive the same contradiction. No action is bound because none of these conditions has a safe automatic remedy. Args: condition: The calculation condition that failed. facts: Stable machine facts, never prose, describing the observation. outcome: The closed no-recovery reason. Defaults to :attr:`~core.operator_action_enums.NoRecoveryOutcome.SAFETY`. Returns: The :class:`~application.operator_actions.models.PreconditionVerdict` carrying the failed condition and its explicit no-recovery outcome. """from..operator_actions.preconditionsimportno_action_precondition_verdictreturnno_action_precondition_verdict(condition_id=condition.value,facts=facts,provenance=ActionEvidenceProvenance.RUNTIME_OBSERVATION,outcome=outcome,)
[docs]classIvaCompensationModeloError(CoreError):"""Raised when a non-Modelo 303 observation is passed to IVA compensation history. The IVA compensation carry-forward pipeline is exclusively sourced from Modelo 303 filed observations. Passing any other modelo to :func:`~application.calculations.iva_compensation_history.iva_compensation_state_from_observation_envelope` violates the calculation boundary contract. """
[docs]classBindingPrefillTypeError(CoreValidationError):"""Raised when a binding selector field carries an unexpected runtime type. Binding selectors flow through pydantic with a union value type, so static analysis loses the per-key shape. This error is raised by the selector narrowing helpers in :mod:`application.calculations.binding_prefill`. It protects :func:`~application.calculations.binding_prefill.resolve_bindings_from_local_store` from selector values that do not match the expected ``int | str`` or ``str | tuple[str, ...]`` shape. """
[docs]classObservationKeyError(CoreValidationError):"""Raised when an observation key component fails its repository contract. The repository key for a ``(modelo, filing_year, period)`` triple must satisfy :func:`~adapters.persistence.storage.path_safety.safe_repository_id` for string components and fall within the supported year range ``[2000, 2099]`` for the integer year component. The key builders in :mod:`application.calculations.observations_repository` raise this error instead of a bare :class:`ValueError` so failures propagate through the typed error registry and produce structured envelopes. """
[docs]classObservationCasillaReferenceError(CoreValidationError):"""Raised when a persisted filing observation names undeclared casillas. :class:`~application.calculations.observations_repository.CalculationObservationRepositoryProtocol` is the encrypted calculation-history substrate for cross-period and cross-modelo reads. It must not persist a :class:`~domain.calculations.registry.bindings.RegistryModeloObservation` whose casilla keys are only syntactically valid ``CasillaId`` strings; every key must be declared by the resolved :class:`~domain.calculations.registry.schema.RegistrySnapshot` for that modelo, year, and period via :func:`~domain.calculations.registry.casilla_membership.undeclared_casilla_ids`. """