"""Strict amendment domain records for :mod:`domain.filing`.Houses the immutable records that describe an AEAT amendment. The``amended_draft`` field on each amendment record holds the originating:class:`ModeloDraft` that the amendment modifies, keeping the draft'scasilla arithmetic and tax due values bound to the amendment foraudit purposes.Concrete variants are :class:`ModeloComplementaria` (LGT Art. 122.2)and :class:`ModeloSustitutiva` (LGT Art. 122.1), the:class:`CasillaChange` delta entries, and the :class:`AmendmentKind`enum. The orchestration use case:func:`application.filing.build_complementaria` lives at:mod:`application.filing._complementaria`; this module containsonly the typed shapes and the deterministic:func:`make_amendment_id` helper so the repository (also under:mod:`domain.filing`) can persist amendments without dependingon the application layer.Callers operate on the discriminated union ``ModeloComplementaria |ModeloSustitutiva``. There is no umbrella alias - pick the variantthat matches the LGT Art. 122 article you're filing under."""from__future__importannotationsfromdatetimeimportdatetimefromdecimalimportDecimalfromenumimportStrEnumfromtypingimportLiteralfrompydanticimportBaseModel,Fieldfrom...coreimportSTRICT_FROZEN_CONFIGas_STRICT_FROZENfrom...coreimportPeriodfrom...core.hashingimportcontent_hash_hexfrom..calculations.registryimportCasillaIdfrom._protocolsimportModeloInputsfrom._schemaimportModeloDrafttypeModeloCode=strtypeCasillaInputs=ModeloInputs"""Updated casilla inputs supplied to an amendment build.An amendment restates casilla values, so its input contract is thesame canonical :data:`domain.filing.ModeloInputs` mapping thefiling builder consumes."""
[docs]classAmendmentKind(StrEnum):"""Legally distinct amendment kinds supported by the engine."""COMPLEMENTARIA="complementaria"SUSTITUTIVA="sustitutiva"
[docs]classCasillaChange(BaseModel):"""One changed casilla in an amendment delta."""model_config=_STRICT_FROZENcasilla_id:CasillaIdold_value:Decimal|None=Nonenew_value:Decimalreason:str=Field(min_length=1)
typeCasillaDelta=tuple[CasillaChange,...]
[docs]classBaseAmendment(BaseModel):"""Shared shape across the two LGT Art. 122 amendment variants. Concrete subclasses fix the ``amendment_kind`` discriminator to a single :class:`AmendmentKind` literal so callers select the variant by class, not by enum value. """model_config=_STRICT_FROZENamendment_id:str=Field(min_length=1)submission_id:str=Field(min_length=1)original_csv:str=Field(min_length=1)original_model:ModeloCode=Field(min_length=1)original_period:Perioddelta:CasillaDelta=Field(min_length=1)amended_draft:ModeloDraftcreated_at:datetime
[docs]classModeloComplementaria(BaseAmendment):"""LGT Art. 122.2 complementaria: corrects an already-presented filing."""amendment_kind:Literal[AmendmentKind.COMPLEMENTARIA]=AmendmentKind.COMPLEMENTARIA
[docs]classModeloSustitutiva(BaseAmendment):"""LGT Art. 122.1 sustitutiva: replaces an already-presented filing in full."""amendment_kind:Literal[AmendmentKind.SUSTITUTIVA]=AmendmentKind.SUSTITUTIVA
[docs]defmake_amendment_id(*,submission_id:str,amendment_kind:AmendmentKind,delta:CasillaDelta,)->str:"""Compute a stable amendment identifier."""payload={"submission_id":submission_id,"amendment_kind":amendment_kind.value,"delta":[change.model_dump(mode="json")forchangeindelta],}returncontent_hash_hex(payload)[:16]