cadrumo.domain.calculations.registry.schema_exports module¶
Export and fixed-width record schema models.
This module owns the wire-facing declaration models so casilla and relation surfaces remain independent of fixed-width rendering policy.
- class ExportLineEnding(*values)[source]¶
Bases:
StrEnumThe line terminator a fixed-width export record is written with.
- CRLF¶
- LF¶
- NONE¶
- class ExportRecordRepeat(*values)[source]¶
Bases:
StrEnumWhat a repeating export record iterates over.
- BINDING_ROWS¶
- PROJECTION_ROWS¶
- class RecordDiscriminatorRequirement(*values)[source]¶
Bases:
StrEnumWhether a discriminator field must be blank or filled.
- BLANK¶
- NON_BLANK¶
- class FilingEnvelopePrefixRole(*values)[source]¶
Bases:
StrEnumClosed roles an AEAT variable-envelope prefix declares, in source order.
ONE vocabulary for every modelo, because the designs share one grammar: the thirty-five bundled 328-byte envelopes all open with the
<T…>record identifier and an<AUX>block carrying the product identity between reserved spans. What differs between designs is which of these roles a given design prints and how wide each one is – both facts the declaration carries – not what the roles MEAN.Declared in this order deliberately: a declaration’s roles must appear as a subsequence of this tuple, so a design that omits a role stays admissible while one that reorders the grammar refuses.
COMPOSED_OPENING_TAGis the one genuine alternative rather than an omission. Some designs (Modelo 200, 100, 714) print the whole seventeen-byte<T200020250A0000>identifier as ONE source row instead of the six separate rows Modelo 303 prints, so the two spellings are mutually exclusive andFilingEnvelopeDefinitionrefuses a declaration carrying both.- COMPOSED_OPENING_TAG¶
- OPENING_TAG¶
- MODELO¶
- DISCRIMINANT¶
- FILING_YEAR¶
- PERIOD¶
- RECORD_TYPE¶
- AUX_OPENING_TAG¶
- PRE_PROGRAM_FILLER¶
- PROGRAM_IDENTIFIER¶
- BETWEEN_IDENTITIES_FILLER¶
- DEVELOPER_TAX_ID¶
- POST_DEVELOPER_FILLER¶
- AUX_CLOSING_TAG¶
- class FilingEnvelopeCloserDerivation(*values)[source]¶
Bases:
StrEnumClosed algorithms deriving a variable envelope’s closing identifier.
- RELATIVE_CLOSER_V1¶
- class FilingEnvelopeTotalDerivation(*values)[source]¶
Bases:
StrEnumClosed algorithms deriving a variable envelope’s declared total.
- EMITTED_BYTE_TOTAL_V1¶
- class FilingEnvelopePrefixFieldDeclaration(**data)[source]¶
Bases:
RegistryModelOne reviewed envelope prefix role and its exact emitted byte length.
- role: FilingEnvelopePrefixRoleValue¶
- length: int¶
- class FilingEnvelopeDefinition(**data)[source]¶
Bases:
RegistryModelStatic variable-envelope declaration carried by a generated layout.
This is a declaration of the envelope grammar, not an instance filing payload. Period, product identity values, body occurrences, bytes, totals, and digests are deliberately absent: the application filing boundary owns those facts when it renders an approved draft.
Modelo-agnostic BY CONSTRUCTION rather than by convention. Every fact that used to be a Modelo 303 constant in code – the
DP30300identity, the thirteen-slot prefix, the 328-byte extent – is declared data here, so the same type carries Modelo 200’s eight-slot composed-tag prefix and Modelo 309’s thirteen without a branch. The modelo itself is deliberately NOT a field: the layout is owned by exactly one revision of one modelo, and the render path reads that identity from the selected snapshot rather than letting a second, drift-capable spelling of it exist here.- schema_version: Literal[1]¶
- source_ref: SourceRefId¶
- source_sha256: ContentDigest¶
- record_identity: str¶
- prefix_fields: tuple[FilingEnvelopePrefixFieldDeclaration, ...]¶
- prefix_extent: int¶
- body_record_ids: tuple[RecordId, ...]¶
- product_identity_requirement: Literal['aeat-product-software-identity-v1']¶
- closer_derivation: FilingEnvelopeCloserDerivationValue¶
- total_derivation: FilingEnvelopeTotalDerivationValue¶
- AUXILIARY_ENVELOPE_HEADER_SCHEMA_VERSION: Final[Literal[1]]¶
Wire version of the auxiliary-envelope header declaration. Named rather than written as a bare default so the number has one home: a reader can find every site bound to this format, and a version bump cannot land on the model while a writer stamping the old number silently disagrees with it.
- class AuxiliaryEnvelopeHeaderDefinition(**data)[source]¶
Bases:
RegistryModelStatic total-less page-zero header declaration carried by a generated layout.
The fixed 328-byte header that opens a design whose records are fixed (Modelo 232’s
DR23200; Modelo 390’s page zero). It shares the filing envelope’s prefix grammar – the same thirteen roles in canonical order and the same emitted literals – and declares no body, closer or total: the layout’s records are the payload.A declaration, not an instance payload, for the same reason its envelope sibling is: period and product-identity values are filing-instance facts the application filing boundary owns at render time.
- schema_version: Literal[1]¶
- source_ref: SourceRefId¶
- source_sha256: ContentDigest¶
- record_identity: str¶
- prefix_fields: tuple[FilingEnvelopePrefixFieldDeclaration, ...]¶
- prefix_extent: int¶
- product_identity_requirement: Literal['aeat-product-software-identity-v1']¶
- class ProjectionEndpointDeclaration(**data)[source]¶
Bases:
RegistryModelRevision-owned admission and evidence for one typed filing endpoint.
The declaration is deliberately independent of a generated layout. It makes the semantic endpoint identity and its legal/source grounding an immutable revision fact before record-design coordinates are generated.
- id: ProjectionEndpointId¶
what it projects, never where.
Derived from the declaration’s own typed reference – the projection kind and the semantic axes of that reference – so the same endpoint carries the same identity in every edition that declares it, and the family inherits along a predecessor chain instead of being restated in full. The numbered casilla a reference resolves to is deliberately not part of it: that box is the edition’s address for the endpoint and renumbers between editions, while the endpoint does not.
- Type:
The endpoint’s edition-free identity
- projection_ref: FilingProjectionRef¶
- legal_refs: LegalRefs¶
- source_refs: SourceRefs¶
- class ExportFieldDefinition(**data)[source]¶
Bases:
RegistryModelDeclare one field’s position, value, and rendering constraints in an export.
- id: ExportFieldId¶
- offset: OneBasedExportOffset | None¶
- length: int | None¶
- kind: CasillaFieldKindValue¶
- casilla_id: CasillaId | None¶
- binding: BindingId | None¶
- literal: str | None¶
- producer_key: FilingProducerKey | None¶
- projection_ref: FilingProjectionRef | None¶
- draft_attribute: ExportDraftAttribute | None¶
- computed_key: ExportComputedKey | None¶
- data_type: ExportFieldDataType¶
- required: bool¶
- padding: ExportPaddingValue¶
- justification: ExportJustificationValue¶
- date_format: str | None¶
- decimals: int | None¶
- signed: bool¶
- sign_position: ExportSignPositionValue¶
- required_for: Literal['natural_person'] | None¶
A requirement the design states for one taxpayer legal form only.
Modelo 390 marks the sujeto pasivo nombre “OBLIGATORIO (persona fisica)”: required when the taxpayer is a natural person, and meaningless for an entity. A layout cannot know the filer, so the condition is carried here and evaluated at export against the filing’s own taxpayer.
- design_type: Literal['N', 'Num'] | None¶
The numeric type the official record design prints for this slot.
AEAT’s type vocabulary: “N: numerico con signo”, “Num: numerico sin signo”. Carried by generated layouts from the design row they derive from, so the sign is held to the design at the registry boundary rather than trusted: a field typed N must be signed and one typed Num must not be. A hand- authored layout has no design row to supply it and declares none.
- value_policy: ExportValuePolicyValue¶
- allowed_values: tuple[str, ...] | None¶
- legal_refs: LegalRefs¶
- source_refs: SourceRefs¶
- property endpoint_casilla_id: CasillaId | None¶
Return the exact numbered endpoint carried by this field, if any.
- validate_allowed_values()[source]¶
Constrain an exact reviewed semantic integer domain.
- Return type:
- validate_value_policy()[source]¶
Require each explicit policy to match its complete fixed-width shape.
- Return type:
- validate_decimals()[source]¶
Require an explicit scale on every decimal field.
AEAT fixed-width slots carry decimals implicitly: the diseño de registro declares them as “N enteros y M decimales” filling the whole slot, with no separator byte. The scale is not derivable from the length – Modelo 200 pairs length 9 with 2 decimals and length 7 with 4 – so it has to be declared per field, and a field that omits it cannot be rendered.
- Return type:
- class RecordDiscriminator(**data)[source]¶
Bases:
RegistryModelRecord-shape discriminator for record types that share literal prefixes.
A record’s literal-prefix matcher cannot tell two records apart when they share their leading literal fields (AEAT models several Tipo-2 record sub-shapes that all start with the same record-type literal). The discriminator declares a contiguous byte range whose populated-or-blank pattern uniquely identifies this record subtype, letting the parser pick the correct record while reading binding-row sequences.
- offset: OneBasedExportOffset¶
- length: int¶
- requires: RecordDiscriminatorRequirementField¶
- class ExportRecordDefinition(**data)[source]¶
Bases:
RegistryModelDeclare one record type and its ordered field authority in an export layout.
- id: RecordId¶
- record_type: str¶
- order: NonNegativeInt¶
- encoding: ExportEncodingValue¶
- line_ending: ExportLineEndingField¶
- required: bool¶
- repeat: ExportRecordRepeatField | None¶
- binding_record: str | None¶
- row_field_casilla_ids: Annotated[Mapping[str, CasillaId], FROZEN_MAPPING]¶
- discriminator: RecordDiscriminator | None¶
- requires_positive_casilla_id: CasillaId | None¶
- fields: tuple[ExportFieldDefinition, ...]¶
- class XmlDictionaryPathOverride(**data)[source]¶
Bases:
RegistryModelOne official dictionary row whose declared path AEAT itself got wrong.
The bundled
.propertiesdictionaries are official AEAT evidence bytes and are never edited: their value is that they are what AEAT published, defects included. So where a row’s path contradicts AEAT’s own XSD, the correction is declared here instead, beside the layout that consumes it.Each override carries the evidence for itself in
reason. That is not decoration: the override asserts that AEAT’s own published dictionary is wrong about a row, which is a claim a later reader must be able to audit rather than take on trust. “It disagrees with the XSD” is not sufficient grounds on its own, because AEAT republishes these schemas mid-year — so which of two AEAT artefacts to believe is a reviewed judgement about a specific row, never a fact derivable from the disagreement itself.- field_id: str¶
- path: str¶
- reason: str¶
- class ExportLayoutDefinition(**data)[source]¶
Bases:
RegistryModelDeclare the complete wire layout used to render an official export.
- id: ExportLayoutId¶
- format: ExportLayoutFormatValue¶
- dictionary_source_ref: SourceRefId | None¶
- source_refs: SourceRefs¶
- legal_refs: LegalRefs¶
- records: tuple[ExportRecordDefinition, ...]¶
- filing_envelope: FilingEnvelopeDefinition | None¶
Variable-composition wrapper this fixed-width layout’s records live inside.
Absent for the majority of layouts, whose records ARE the payload. Present where the official design declares a
Total: Variableenvelope, in which case the records are its body members rather than the whole file.
- auxiliary_envelope_header: AuxiliaryEnvelopeHeaderDefinition | None¶
Total-less 328-byte page-zero header emitted before this layout’s records.
Absent for every layout whose design declares no such header. Present where the design prints one (Modelo 232’s
DR23200; Modelo 390’s page zero): the records remain the payload and the header is emitted as their prefix. A layout declaring both this and a filing envelope is refused, since no design composes a variable body behind a total-less page-zero header.
- dictionary_path_overrides: tuple[XmlDictionaryPathOverride, ...]¶
Dictionary rows whose AEAT-declared path is corrected before use.
Applied where the dictionary is read rather than where it is rendered, because the writer and the export parser resolve their rows from the same call: a correction applied to only one of them would make an artefact verify as drift against itself.
- aux_idioma: DeclaracionIdiomaValue¶
Language the declaration’s mandatory
Aux/Idiomaelement declares.The AEAT dictionary that drives an
xml_dictionaryrender describes noAuxrow at all, in any bundled revision, while every XSD makes the block mandatory and first — so the value cannot come from the dictionary and is declared here instead, beside the format that requires it.
- aux_version: str | None¶
Producer token the declaration’s mandatory
Aux/VERSIONelement carries.Deliberately has NO default, and that is load-bearing rather than caution. AEAT declares the element as
tipo_String4L— four characters against a permissive pattern, with no enumeration, no annotation, and no worked example carrying a genuine value anywhere in the bundled corpus. So a plausible token such as"1.00"would VALIDATE while asserting something nothing verified, the document would start passing our own checks, and the gap would stop being reported at all.Two sources that look authoritative are not. A real AEAT-submitted declaration in the fixture corpus carries
<VERSION>2.02</VERSION>, which is a redaction placeholder — the sanitiser assigned sequential field-position indices, and its siblings include anECIVILof6where the schema admits only 1-4. A governed fact would require legal evidence that this value lacks; declaring one would have meant inventing a citation.Absent, the export refuses rather than emitting a partial
Aux— which would be invalid regardless, since the element isminOccurs="1".