cadrumo.domain.calculations.registry.schema_base module

Shared base classes and aliases for registry schema models.

The SensitivityClassField alias coerces registry output_sensitivity tokens into SensitivityClass members before strict schema validation. RevisionReviewStatusField does the same for the per-revision governance stamp’s review_status token, and RegistryAuthorityGradeField for the per-revision authority_grade token.

coerce_enum_member(enum_cls)[source]

Return a scalar coercion hop for one enum-typed field.

The generated function is the identical shape as _coerce_sensitivity_class() and its siblings above – registry schema models validate under strict=True, which refuses a bare TOML string for an enum-typed field, so the loader boundary hydrates the typed member here. An unknown token still raises out of the enum constructor and surfaces as a registry load failure naming the offending value.

Factored out because the ledger binding-selector families (IVA, OSS/IOSS, retenciones) need this same coercion for several enum types each; hand- duplicating the four-line function per type is the drift risk this project’s architecture rules warn against, not the discipline they ask for.

Return type:

Callable[[object], object]

Parameters:

enum_cls (type)

coerce_enum_tuple(enum_cls)[source]

Return a tuple[enum_cls, ...] coercion hop, element-wise.

Same rationale and mechanism as coerce_enum_member(), applied to each element of an enum-typed tuple field rather than to a scalar field: strict mode refuses a bare string for an enum-typed tuple ELEMENT exactly as it refuses one for a scalar enum field, so each element is coerced independently and an unknown token still raises out of the enum constructor unchanged.

Return type:

Callable[[object], object]

Parameters:

enum_cls (type)

coerce_decimal_tuple(value)[source]

Coerce a tuple[Decimal, ...] field’s elements from TOML string/int tokens.

TOML has no native Decimal type; committed registry TOML stores a rate tuple as quoted decimal strings (e.g. ["0.21"]) to avoid float imprecision. Strict mode refuses that bare string for a Decimal-typed tuple element exactly as it refuses one for any other strict-typed element, so this is the same coercion-hop mechanism as coerce_enum_tuple(), targeting Decimal instead of an enum. An unparseable token still raises out of the Decimal constructor and surfaces as a registry load failure.

Return type:

object

Parameters:

value (object)

class ManifestOnlyMarker[source]

Bases: object

Annotated metadata pinning one field to the revision’s own manifest.

A revision compiles from its revision.toml manifest plus up to several hundred per-section fragment files, and the merge takes a scalar from whichever file declares it. A field marked here is refused inside a section fragment: it is a statement about the WHOLE revision, so it has to be readable in the one place a reviewer opens, not merged in from a file thousands deep in a fragment tree where the manifest still reads silent on it.

Manifest-only-ness is not derivable from a field’s annotation - the marked fields are a free-text attribution, a closed enum, a date and two id tuples, shapes a dozen unmarked fields on the same model share - so the enrolment has to be declared. Declaring it at the field rather than in a hand-kept list is the point: the list can be forgotten when a field is added, and it is the sole input to the loader’s placement refusal, so a forgotten entry silently reopens the laundering route the refusal exists to close.

MANIFEST_ONLY

The singleton marker attached to every manifest-only field declaration.

class GovernanceStampMarker[source]

Bases: ManifestOnlyMarker

Annotated metadata enrolling one field into the governance stamp.

Narrower than ManifestOnlyMarker, and a subclass of it rather than a sibling. Governance provenance and legal grounding are different subjects - one is a claim about who built and signed off a revision, the other is the law the revision stands on - and only the governance fields belong to the stamp vocabulary the conformance tooling reads and writes. What they share is the placement guarantee, and expressing that as a type relation rather than a second marker on the same fields is what keeps it: a governance field added tomorrow cannot be manifest-pinned by memory, because it already is one by construction.

GOVERNANCE_STAMP

The singleton marker attached to every governance-stamp field declaration.

class SchemaFamilyMarker[source]

Bases: object

Annotated metadata enrolling one field as a revision schema family.

A family is one of the revision’s declared content collections - its casillas, its formulas, its bindings, its export layouts. Coverage asks one question of each: is it populated, is it honestly not applicable, or is it empty for a reason nobody has recorded. The marker is what makes a field subject to that question.

Unrelated to ManifestOnlyMarker, and deliberately not a subclass of it. Placement asks WHERE a field may be written; enrolment asks WHETHER a field’s emptiness is a coverage claim. The two sets barely intersect: the manifest-only fields are scalars, and the families are collections. A marker hierarchy between them would assert a relationship that does not exist.

Family-ness IS derivable from the annotation - a family is exactly a tuple of a schema model - which is why the marker carries a completeness check rather than standing alone: schema_family_fields() reads the declarations, the check compares that against the shape-derived set, and a collection added without the marker reds. Marking alone would catch a rename and never an addition; deriving alone would enrol collections nobody meant as families. Requiring both is what makes the enrolment exhaustive AND deliberate.

SCHEMA_FAMILY

The singleton marker attached to every revision schema-family declaration.

class ChainFamilyMarker[source]

Bases: object

Annotated metadata enrolling one field as a chain-statement family.

A chain family holds authored statements about an identifier-keyed family’s inheritance chain across editions - retirements and replacements - rather than content of the revision itself. Its natural state is empty: an edition that withdraws nothing declares nothing. Emptiness is therefore resolved by construction and is never a coverage claim, which is why this marker is distinct from SchemaFamilyMarker and why coverage ignores it. The loader still discovers the section by shape, and the conformance check accepts either marker as deliberate enrolment.

CHAIN_FAMILY

The singleton marker attached to every chain-statement family declaration.

chain_family_fields(model)[source]

Return the names of model’s fields marked CHAIN_FAMILY.

Return type:

frozenset[str]

Parameters:

model (type[BaseModel])

manifest_only_fields(model)[source]

Return the names of model’s fields marked MANIFEST_ONLY.

Includes every field marked GOVERNANCE_STAMP, since the governance marker is a ManifestOnlyMarker. Reads the marker back out of pydantic’s retained Annotated metadata, so a field carrying either marker - including one added by a subclass - enrols itself without any second list being edited.

Return type:

frozenset[str]

Parameters:

model (type[BaseModel])

schema_family_fields(model)[source]

Return the names of model’s fields marked SCHEMA_FAMILY.

The declared enrolment. collection_shaped_fields computes the set this one is meant to equal; the gate that compares them is what stops a new collection shipping outside coverage.

Return type:

frozenset[str]

Parameters:

model (type[BaseModel])

is_schema_model_element(element)[source]

Return whether a tuple element type is a registry model or a closed union of them.

A family may be a plain model class or an Annotated discriminated union of model classes; both are collections of schema models for enrolment and loader purposes.

Return type:

bool

Parameters:

element (object)

collection_shaped_fields(model)[source]

Return the names of model’s tuple fields whose element is a schema model.

Return type:

frozenset[str]

Parameters:

model (type[BaseModel])

governance_stamp_fields(model)[source]

Return the names of model’s fields marked GOVERNANCE_STAMP.

The stamp vocabulary proper, narrower than manifest_only_fields(): a field pinned to the manifest for legal-grounding reasons is not part of the provenance claim and must not be written or read as one.

Return type:

frozenset[str]

Parameters:

model (type[BaseModel])

class CalculationClass(*values)[source]

Bases: StrEnum

What kind of declaration a modelo is, as an enforcement posture.

FILING

A self-assessment the taxpayer settles.

INFORMATIVE

An informative declaration carrying no liquidacion.

SUMMARY

A summary rolling up period filings without settling on its own.

ModeloFilingCapability

Discriminator for the calculation role of a ModeloDefinition.

  • filing: The modelo computes and submits filing-grade amounts. Most modelos fall into this class.

  • informative: The modelo collects and reports data but does not compute filing-grade amounts. Revisions must have empty formulas and empty relations; every casilla must be manual or informational. Modelo 232 is the canonical example.

  • summary: The modelo aggregates other modelos (e.g. 390 over 303) and may declare cross-model relations but is not a filing modelo.

alias of Literal[‘borrador’, ‘renta_ledger_default’]

sorted_unique_capabilities(value)[source]

Order declared modelo capabilities and refuse a repeated declaration.

A set-shaped container orders its members by hash, which varies between processes, so the same declaration would serialise and digest differently from one run to the next. Sorting on construction makes the declared order irrelevant to the stored value; rejecting duplicates keeps the tuple’s length a truthful count of what was declared.

Return type:

object

Parameters:

value (object)

DesignAuthority

Whether a bundled record design is a machine-readable authority or provenance.

authoritative is the default and the case for every design a revision may cite as an export-layout authority. provenance_only marks a design the corpus keeps as evidence but which the registry must never treat as a layout map: the raw BOE ordenes that carry a modelo’s design as an annex and so refuse to parse from wire position 1, and a superseded draft AEAT published alongside a definitive edition. The distinction has to be declared rather than inferred – parse failure alone cannot tell “this is provenance” from “this design is broken”, and neither can the absence of a record_design_epoch, which also covers designs whose selection window is merely not assigned yet.

alias of Literal[‘authoritative’, ‘provenance_only’]

class DateAxis(*values)[source]

Bases: StrEnum

Which date a registry value or bracket table is keyed to.

FILING_PERIOD

The period the declaration covers, rather than any single date.

DEVENGO_DATE

The accrual date the liability arises on.

TRANSACTION_DATE

The date the underlying transaction occurred.

INVOICE_DATE

The date the invoice was issued.

SUBMISSION_DATE

The date the declaration was submitted.

class ThresholdComparison(*values)[source]

Bases: StrEnum

How a dated value is compared when it is used as a threshold.

A provision can be redrafted so that only the COMPARISON changes: LIVA art. 103.Dos.2 read “exceda en un 20 por 100” until 2014 and “exceda en un 10 por ciento o mas” from 2015, and the added “o mas” moves the boundary case from excluded to included. A value alone cannot express that, so two redactions of one provision could not be two dated values while the operator lived in code.

EXCLUSIVE is the default because it is the semantics every shipped value is read with today, so declaring the field changes no existing meaning.

EXCLUSIVE

The threshold is met only when the compared amount is strictly beyond it.

INCLUSIVE

The threshold is met when the compared amount reaches it.

class EvidenceTier(*values)[source]

Bases: StrEnum

What kind of authority grounds a registry entity.

LEGAL_AUTHORITY

a BOE provision or the orden that approves a design.

Type:

The law itself

OFFICIAL_SOURCE_GUIDANCE

AEAT-published guidance, instructions or a form specification.

EXECUTABLE_PARITY_EVIDENCE

An artefact that can be executed and compared, such as a safe calculator.

LAYOUT_AUTHORITY

A published record design fixing field offsets, widths and order.

class CasillaSignConstraint(*values)[source]

Bases: StrEnum

Which side of zero a casilla’s computed value may fall on.

Declared by the registry and consumed unchanged by the spreadsheet surface that renders the same restriction as a cell validation rule. The two stated it separately before, so a member added here would have left the workbook accepting a value the engine rejects.

ANY

Unrestricted; the casilla admits either sign.

NON_NEGATIVE

Zero or positive. A negative computed value is a constraint violation.

NON_POSITIVE

Zero or negative, as for a casilla that only ever records a deduction.

CasillaSignConstraintValue

The same vocabulary where a coercing annotation may not be used.

A strict payload or operation surface refuses a bare enum for a raw token and forbids a customised core schema, so those fields take this literal over the members above rather than restating the tokens.

alias of Literal[ANY, NON_NEGATIVE, NON_POSITIVE]

REGISTRY_SOURCE_GROUNDING_TIERS: tuple[EvidenceTier, ...]

The tiers that ground a registry entity on AEAT-published MATERIAL, as distinct from the law itself and from executable parity artefacts. Three section validators require exactly this pair through require_any_source_tier. Derived from the vocabulary above rather than restated, so a tier added there cannot leave this narrowing silently measuring the old set.

class CorpusTier(*values)[source]

Bases: StrEnum

How much of a legal instrument the bundled corpus artefact carries.

FULL_CONSOLIDATED

The whole consolidated instrument, not a provision-suffixed extract.

PROVISION_EXCERPT

A single provision lifted from the instrument.

class PublishingAuthority(*values)[source]

Bases: StrEnum

Who published the instrument or artefact a registry row cites.

BOE

The Boletin Oficial del Estado, where Spanish law is promulgated.

AEAT

The Agencia Estatal de Administracion Tributaria.

EU

A European Union instrument.

AUTONOMOUS_COMMUNITY

An autonomous community exercising its own competence.

OTHER

A publisher outside the four named above, recorded rather than assumed.

class SettlementDirection(*values)[source]

Bases: StrEnum

Which way a declaration’s result settles between taxpayer and AEAT.

INGRESAR

the result is paid in.

Type:

The taxpayer owes

DEVOLVER

the result is refunded.

Type:

The AEAT owes

class RegistrySourceKind(*values)[source]

Bases: StrEnum

What kind of official artefact a source reference cites.

RECORD_DESIGN

A diseno de registro fixing field offsets, widths and order.

MANUAL_PDF

An AEAT manual published as PDF.

INSTRUCTIONS

Filing instructions accompanying a modelo.

FORM_SPEC

A published specification of the form’s own fields.

DICTIONARY

A data dictionary for an XML or structured submission.

XSD

An XML schema definition.

SUPPRESSION_NOTICE

A notice withdrawing or superseding a previously published artefact.

class CasillaDataType(*values)[source]

Bases: StrEnum

The scalar kind a casilla declares, and the root of every narrowing of it.

DECIMAL

A decimal quantity that is not money.

MONEY

A monetary amount, the default for a casilla.

INTEGER

A whole count.

RATIO

A proportion or rate expressed as a fraction.

TEXT

Free text the taxpayer or AEAT supplies.

BOOLEAN

A declared yes or no.

NIF

A Spanish tax identity number.

YEAR

A four-digit ejercicio.

PERIOD_CODE

A filing-period token.

COUNTRY_CODE

An ISO country code.

IBAN

An international bank account number.

NAME

A party name.

NIF_IVA

An intra-community NIF-IVA identifier.

CCAA_CODE

An autonomous-community code.

PROVINCE_CODE

A Spanish province code.

POSTAL_CODE

A Spanish postal code.

MUNICIPALITY_CODE

A municipality code.

BIC

A SWIFT business identifier code.

DATE

A calendar date.

NUMERIC_CASILLA_DATA_TYPES: Final[frozenset[CasillaDataType]]

Data types a formula may consume as a scalar operand.

A narrowing of CasillaDataType, held as members rather than as tokens so a member added or renamed cannot leave this set validating the old spelling. A StrEnum member hashes as its own string, so this set accepts a raw token and a member alike – verified against the live enum, not assumed.

Distinct from ZERO_PADDED_EXPORT_DATA_TYPES, which excludes RATIO: a ratio is a scalar a formula can read, and is not written as a zero-padded numeral.

ZERO_PADDED_EXPORT_DATA_TYPES: Final[frozenset[CasillaDataType]]

Data types written right-justified and zero-padded in a fixed-width export.

The narrower of the two numeric sets. Keeping both named, rather than one set with an exception at the ratio, is what stops a later reader assuming they are the same population.

CasillaDataTypeValue

The same vocabulary in the one form an operation public schema admits.

An operation model graph must not customise its Pydantic core schema, which the coercing field alias does, and a bare enum under strict validation refuses the plain token every caller sends. A literal over the enum’s own members satisfies both: it carries no core-schema hook and it still accepts the token. Rooted in the vocabulary above rather than restated, so a member added there reaches this form too.

alias of Literal[DECIMAL, MONEY, INTEGER, RATIO, TEXT, BOOLEAN, NIF, YEAR, PERIOD_CODE, COUNTRY_CODE, IBAN, NAME, NIF_IVA, CCAA_CODE, PROVINCE_CODE, POSTAL_CODE, MUNICIPALITY_CODE, BIC, DATE]

class RegistryModel(**data)[source]

Bases: BaseModel

Strict frozen base for registry schema objects.

Parameters:

data (Any)

class SourceCitation(**data)[source]

Bases: RegistryModel

A source reference paired with the exact text required to ground it.

source_ref: SourceRefId
required_text: SourceCitationText
filing_period_from_scope(filing_year, period)[source]

Return a core Period when the registry token is a real filing-period code.

An administrative registry token (Modelo 036 ALTA, Modelo 145 comunicacion) addresses a revision rather than naming a period, and the symbolic EVENT-N selector (Modelo 210) covers a set of event periods without being one, so neither has a filing period and both yield None. Every other token must build a Period; a malformed token or out-of-range year still raises.

Raises:

PeriodError – When a non-administrative token cannot build a period.

Return type:

Period | None

Parameters:
  • filing_year (int)

  • period (str)