Source code for cadrumo.domain.calculations.registry.relation_prefill_bindings
"""The relation-prefill provider: one cross-filing fold declared in one place.A ``relation_prefill`` binding folds values filed on another modelo -- or on anearlier period of this one -- into a form slot of the target filing. Thedeclaration carries every axis of that fold: which modelo and casilla are read,what kind of dependency it is, and, through the shared closed temporal member,when the source was filed relative to the target."""from__future__importannotationsfromtypingimportLiteralfrompydanticimportBaseModel,Field,model_validatorfrom....core.aggregationimportBindingSourceKindfrom....core.casilla_idimportCasillaIdfrom....core.errors.hierarchyimportpydantic_validation_boundaryfrom....core.modelsimportSTRICT_FROZEN_CONFIGfrom.binding_temporalimport(BindingTemporalSelector,FiledCurrentPeriod,FilingYearOffset,FilingYearOffsetByTargetPeriod,SameFilingYearPeriods,temporal_max_year_delta,temporal_period_anchors,)from.errorsimportRegistryValidationErrorfrom.idsimportModeloIdfrom.relation_dependencyimportRelationDependencyRoleField,RelationKindField__all__=["RelationPrefillProvider"]
[docs]classRelationPrefillProvider(BaseModel):"""Strict validator for a ``relation_prefill`` binding declaration. The fold used to be split across two identified families: a binding that named the slot and a relation that named the source, the periods, the year alignment, and the aggregation. Every axis except :attr:`relation_kind` and :attr:`dependency_role` was declared on both sides, and the two could disagree. They are one declaration now. :attr:`temporal` is the shared closed member, so the source window is stated relative to the target filing context. An absolute source year is unspellable rather than merely rejected: no member of the union carries one, which is what keeps an inherited row from silently naming a year its successor edition does not file. Aggregation stays on the binding: it is a property of the value channel the slot yields, not of the source coordinate this provider names. """model_config=STRICT_FROZEN_CONFIGkind:Literal[BindingSourceKind.RELATION_PREFILL]=BindingSourceKind.RELATION_PREFILLrelation_kind:RelationKindFielddependency_role:RelationDependencyRoleFieldsource_modelo:ModeloIdtemporal:BindingTemporalSelectorsource_casilla_id:CasillaId|None=Field(default=None,min_length=1)source_casilla_ids:tuple[CasillaId,...]=()@propertydefmax_year_delta(self)->int|None:"""Return the absolute bound on anchor year deltas the member declares."""returntemporal_max_year_delta(self.temporal)
[docs]defrequired_period_anchors_for_target(self,target_period:str)->tuple[tuple[int,str],...]:"""Return source year-offset and period anchors for a target period. Each year offset is the TOTAL distance from the target filing year. An empty result means this provider names no source window for the target period at all, which is a scope-out and never a zero. """returntemporal_period_anchors(self.temporal,target_period=target_period)
@propertydefrequired_source_periods(self)->tuple[str,...]:"""Return the fixed source periods the temporal member names, if any. The members whose periods depend on the target period name none here; their windows come from :meth:`required_period_anchors_for_target`. """ifisinstance(self.temporal,SameFilingYearPeriods|FilingYearOffset|FilingYearOffsetByTargetPeriod):returnself.temporal.source_periodsifisinstance(self.temporal,FiledCurrentPeriod):return(self.temporal.source_period,)return()@propertydefdeclared_source_casilla_ids(self)->tuple[CasillaId,...]:"""Return the source casillas this provider reads, however they were declared."""ifself.source_casilla_idisnotNone:return(self.source_casilla_id,)returnself.source_casilla_ids@model_validator(mode="after")@pydantic_validation_boundarydef_validate_source_shape(self)->RelationPrefillProvider:ifself.source_casilla_idisnotNoneandself.source_casilla_ids:raiseRegistryValidationError("relation_prefill provider cannot declare both source_casilla_id and source_casilla_ids",)ifself.source_casilla_idisNoneandnotself.source_casilla_ids:raiseRegistryValidationError("relation_prefill provider must declare source_casilla_id or source_casilla_ids",)iflen(set(self.source_casilla_ids))!=len(self.source_casilla_ids):raiseRegistryValidationError("relation_prefill provider source_casilla_ids entries must be unique")returnself@model_validator(mode="after")@pydantic_validation_boundarydef_validate_dependency_role(self)->RelationPrefillProvider:"""Keep the annual-summary fold on the role that names it. An annual summary reads the periodic filings it summarises; declaring it under any other dependency role would misreport the fold to every consumer that classifies sources by role. """ifself.relation_kind=="annual_summary"andself.dependency_role!="periodic_to_annual_summary":raiseRegistryValidationError("annual_summary relation_prefill must use the periodic_to_annual_summary dependency role",context={"dependency_role":str(self.dependency_role)},)returnself