aeat.application.storage.calc_sheets._records module¶
Strict records describing workbook plans produced from registry snapshots.
Every record is a frozen pydantic v2 model with extra=”forbid” so that schema drift surfaces as validation failures at the moment the engine assembles the plan rather than as silent payload divergence at the renderer boundary. The records are intentionally narrow: the engine produces them, the Google apply adapter and offline XLSX materializer consume them, and the pull/parity adapters compare incoming workbook cell values back against the same plan.
A1 addressing¶
Workbook cell addresses are expressed by the SheetCellAddress record which carries the human-readable A1 string plus the structured tab name, row index, and column index. Row and column indices are 1-based to match Sheets/openpyxl convention. The a1 string is recomputed from the tab + row + column at construction time, so callers never hand-roll A1 strings — they always go through this record.
See also
aeat.domain.calculations.registry.RegistrySnapshotRegistry snapshot compiled into these records by the engine.
SheetEvidenceFacetEvidence facet carried by the plan and rendered by both workbook export paths.
- class TabName(*values)[source]¶
Bases:
StrEnumThe tabs the engine emits in every workbook.
The set is fixed so that the pull adapter and the parity oracle have a stable layout to anchor against. New layers (for example a future “Pagos” tab for ingreso/devolución timings) are added by extending this enumeration; freeform tab names are rejected.
- ENTRADAS¶
- CALCULOS¶
- PROVENANCE¶
- TARIFFS¶
- DETALLE¶
- EVIDENCIA¶
- GUIDE¶
- class SheetCellAddress(**data)[source]¶
Bases:
BaseModelA single Sheets cell address, expressed as tab + row + column.
- tab: TabName¶
- row: int¶
- column: int¶
- a1: str¶
- class SheetValueCell(**data)[source]¶
Bases:
BaseModelA literal value the engine writes verbatim to a cell.
Used for operator-input cells (with value=None indicating “blank, awaiting operator entry”), for parameter mirror cells, and for the structural section/header labels.
- Parameters:
- address: SheetCellAddress¶
- value: Decimal | str | bool | None¶
- note: str | None¶
- casilla_id: CasillaId | None¶
- parameter: ParameterId | None¶
- role: Literal['operator_input', 'parameter_value', 'label', 'metadata']¶
- class SheetFormulaCell(**data)[source]¶
Bases:
BaseModelA computed cell whose value comes from a Sheets formula.
The formula string is exactly what is sent to the Sheets API, minus the leading “=” sign (the apply adapter prepends it). It must already be A1-resolved.
- Parameters:
address (SheetCellAddress)
formula (str)
casilla_id (CasillaId)
rounding_scale (int | None)
rounding_rule (Literal['money', 'integer', 'none'])
note (str | None)
- address: SheetCellAddress¶
- formula: str¶
- casilla_id: CasillaId¶
- rounding_scale: int | None¶
- rounding_rule: Literal['money', 'integer', 'none']¶
- note: str | None¶
- class SheetCellConstraint(**data)[source]¶
Bases:
BaseModelA declarative value constraint surfaced to one Sheets cell.
Mirrors the registry’s CasillaConstraints record into a Sheets setDataValidation rule. The apply adapter renders this as a condition block on the target cell so an operator who types an out-of-range value sees Sheets’s own validation banner reject it in the workbook UI.
The constraint also propagates to the cell’s note so the operator sees the legal grounding (“LIRPF art. 56 — non-negative”) even before they attempt invalid input.
- Parameters:
address (SheetCellAddress)
sign (Literal['any', 'non_negative', 'non_positive'])
min_value (Decimal | None)
max_value (Decimal | None)
legal_refs (tuple[LegalRefId, ...])
casilla_id (CasillaId)
- address: SheetCellAddress¶
- sign: Literal['any', 'non_negative', 'non_positive']¶
- min_value: Decimal | None¶
- max_value: Decimal | None¶
- legal_refs: tuple[LegalRefId, ...]¶
- casilla_id: CasillaId¶
- class SheetRowSetColumn(**data)[source]¶
Bases:
BaseModelOne column of a SheetRowSet, mapping a binding id to a header cell.
- Parameters:
binding (BindingId)
header_address (SheetCellAddress)
header_label (str)
legal_refs (tuple[LegalRefId, ...])
- binding: BindingId¶
- header_address: SheetCellAddress¶
- header_label: str¶
- legal_refs: tuple[LegalRefId, ...]¶
- class SheetRowSet(**data)[source]¶
Bases:
BaseModelA repeating-row data block in the Detalle tab.
Mirrors the registry’s row-producer binding pattern (bindings declared with aggregation = { op = “rows”, grouping = “…” }). Each row in the workbook represents one operator-supplied detail record (e.g., one perceptor on modelo 190, one VIES counterparty on modelo 349, one foreign asset on modelo 720). Columns are declared per row-producing binding sharing the same grouping.
The engine emits a header row carrying header_label for each column. Operators add row data freely below; the apply adapter leaves the data area unprotected. The pull adapter reads the operator-supplied rows back into structured RowSetEdit records keyed by binding id.
legal_refs and source_refs ground the row-set against AEAT’s diseño-de-registro authority that mandates the per-record fields.
- Parameters:
- grouping: str¶
- tab: TabName¶
- header_row: int¶
- first_data_row: int¶
- columns: tuple[SheetRowSetColumn, ...]¶
- legal_refs: tuple[LegalRefId, ...]¶
- source_refs: tuple[SourceRefId, ...]¶
- class SheetProtectedRange(**data)[source]¶
Bases:
BaseModelA contiguous range the apply adapter marks read-only.
Cálculos, Procedencia, and Tarifas are always fully protected. The pull adapter inspects these to decide which cells operators are allowed to mutate.
- Parameters:
- tab: TabName¶
- start_row: int¶
- end_row: int¶
- start_column: int¶
- end_column: int¶
- description: str¶
- class SheetNumberFormat(**data)[source]¶
Bases:
BaseModelDisplay-format directive for a numeric workbook cell.
- Parameters:
address (SheetCellAddress)
casilla_id (CasillaId)
data_type (Literal['money', 'integer', 'percentage'])
pattern (str)
- address: SheetCellAddress¶
- casilla_id: CasillaId¶
- data_type: Literal['money', 'integer', 'percentage']¶
- pattern: str¶
- class SheetSectionHeader(**data)[source]¶
Bases:
BaseModelSection-header styling directive for a section’s first label cell.
Marks the column-A cell where a casilla section first appears so both transports render it as a bold section header — the official AEAT workbooks group casillas under bold section banners for operator orientation.
- Parameters:
address (SheetCellAddress)
text (str)
- address: SheetCellAddress¶
- text: str¶
- class SheetAnchor(**data)[source]¶
Bases:
BaseModelAn explicit labelled start / final anchor on the calculation flow.
startmarks the opening of the operator-input region (Entradas);finalmarks the filing result (resultado / cuota) on Cálculos. Rendered as a labelled cell in both transports so the inputs→resultado flow is unambiguously oriented, mirroring the published workbook layout.- Parameters:
address (SheetCellAddress)
kind (Literal['start', 'final'])
label (str)
- address: SheetCellAddress¶
- kind: Literal['start', 'final']¶
- label: str¶
- class SheetStyledRange(**data)[source]¶
Bases:
BaseModelA contiguous range tagged with a presentation role.
The engine emits one styled range per role-region (the header band, each section banner, the operator-input column, the computed column, the result cell, wrapped body columns). Both transports resolve
roleto a concrete fill / font / alignment through the shared_themepalette, so the offline xls and online Sheets render the same look from the same declaration. Later ranges win on overlap, so a narrow accent range (e.g.result) may be emitted after the broad column range it refines.- Parameters:
- tab: TabName¶
- start_row: int¶
- end_row: int¶
- start_column: int¶
- end_column: int¶
- role: StyleRole¶
- wrap: bool¶
- class SheetColumnWidth(**data)[source]¶
Bases:
BaseModelA per-tab column width in approximate character units.
The offline renderer applies it as an openpyxl
column_dimensionswidth; the online renderer converts it to a pixel size (~7 pxper character) forupdateDimensionProperties. Sized so concept labels and legal-ref columns read without clipping.- tab: TabName¶
- column: int¶
- width: int¶
- class SheetFrozenView(**data)[source]¶
Bases:
BaseModelPer-tab frozen header rows / leading columns.
Freezes the column-title row (and, where useful, the leading label columns) so the header stays visible while an operator scrolls a long modelo.
- tab: TabName¶
- frozen_rows: int¶
- frozen_columns: int¶
- class SheetAutoFilter(**data)[source]¶
Bases:
BaseModelA per-tab basic-filter range over the header row plus its data rows.
Lets the operator sort / filter the tab by section or concept. Offline maps it to
worksheet.auto_filter.ref; online tosetBasicFilter.- tab: TabName¶
- start_row: int¶
- end_row: int¶
- start_column: int¶
- end_column: int¶
- class SheetProvenanceRow(**data)[source]¶
Bases:
BaseModelOne row of the Procedencia audit tab.
Each computed casilla emits a row recording the formula id, the rounding rule, the legal references, and the workbook cell that holds the value. Operators reading the workbook can audit every figure back to a registry source.
- Parameters:
- casilla_id: CasillaId¶
- display_number: str¶
- casilla_label: str¶
- formula_id: FormulaId | None¶
- rounding_rule: Literal['money', 'integer', 'none']¶
- legal_refs: tuple[LegalRefId, ...]¶
- source_refs: tuple[SourceRefId, ...]¶
- target_address: SheetCellAddress¶
- class SheetEvidenceContributorRow(**data)[source]¶
Bases:
BaseModelOne ledger contributor rendered into the workbook evidence surface.
- Parameters:
- casilla_id: CasillaId¶
- transaction_id: str¶
- amount: Decimal¶
- currency: str¶
- taxable_base: Decimal | None¶
- iva_rate: Decimal | None¶
- iva_amount: Decimal | None¶
- counterparty: str | None¶
- attachment_ids: tuple[str, ...]¶
- document_link_ids: tuple[str, ...]¶
- legal_refs: tuple[LegalRefId, ...]¶
- source_refs: tuple[SourceRefId, ...]¶
- class SheetEvidenceManualEntry(**data)[source]¶
Bases:
BaseModelOne non-ledger fact basis entry rendered into the evidence surface.
- Parameters:
- casilla_id: CasillaId¶
- value: str¶
- kind: str¶
- note: str¶
- legal_refs: tuple[LegalRefId, ...]¶
- source_refs: tuple[SourceRefId, ...]¶
- class SheetEvidenceFacet(**data)[source]¶
Bases:
BaseModelEvidence rows attached to a workbook export plan.
Contributor rows carry ledger-derived transaction facts by casilla; manual entries carry non-ledger fact basis values. The offline serializer writes this facet to both the Evidencia worksheet and the adjacent JSON sidecar.
- Parameters:
snapshot_fingerprint (str | None)
contributor_rows (tuple[SheetEvidenceContributorRow, ...])
manual_entries (tuple[SheetEvidenceManualEntry, ...])
- snapshot_fingerprint: str | None¶
- contributor_rows: tuple[SheetEvidenceContributorRow, ...]¶
- manual_entries: tuple[SheetEvidenceManualEntry, ...]¶
- class SheetTariffTableRow(**data)[source]¶
Bases:
BaseModelOne row of a parameter bracket table mirrored to the Tarifas tab.
- Parameters:
lower_bound (Annotated[Decimal, BeforeValidator(func=~aeat.domain.calculations.registry._schema_scalars._coerce_decimal, json_schema_input_type=PydanticUndefined)])
upper_bound (Annotated[Decimal, BeforeValidator(func=~aeat.domain.calculations.registry._schema_scalars._coerce_decimal, json_schema_input_type=PydanticUndefined)] | None)
fixed_addition (Annotated[Decimal, BeforeValidator(func=~aeat.domain.calculations.registry._schema_scalars._coerce_decimal, json_schema_input_type=PydanticUndefined)])
marginal_rate (Annotated[Decimal, BeforeValidator(func=~aeat.domain.calculations.registry._schema_scalars._coerce_decimal, json_schema_input_type=PydanticUndefined)])
valid_from (date)
valid_to (date | None)
- lower_bound: DecimalValue¶
- upper_bound: DecimalValue | None¶
- fixed_addition: DecimalValue¶
- marginal_rate: DecimalValue¶
- valid_from: date¶
- valid_to: date | None¶
- class SheetTariffTable(**data)[source]¶
Bases:
BaseModelA parameter mirrored into the workbook as a lookup table.
Two flavours are supported: scalar dated values and bracket tables (bracket_table parameters). The engine emits one of the two depending on the parameter’s data_type.
- Parameters:
parameter (ParameterId)
label (str)
data_type (Literal['decimal', 'money', 'integer', 'ratio', 'bracket_table'])
anchor (SheetCellAddress)
scalar_value (Annotated[Decimal, BeforeValidator(func=~aeat.domain.calculations.registry._schema_scalars._coerce_decimal, json_schema_input_type=PydanticUndefined)] | None)
bracket_rows (tuple[SheetTariffTableRow, ...])
- parameter: ParameterId¶
- label: str¶
- data_type: Literal['decimal', 'money', 'integer', 'ratio', 'bracket_table']¶
- anchor: SheetCellAddress¶
- scalar_value: DecimalValue | None¶
- bracket_rows: tuple[SheetTariffTableRow, ...]¶
- class ParameterCell(**data)[source]¶
Bases:
BaseModelPointer from a parameter id to its anchor cell in the Tarifas tab.
The translator consults this mapping when an expression references a parameter, so that the emitted Sheets formula reads from the mirrored value instead of inlining a literal.
- Parameters:
parameter (ParameterId)
anchor (SheetCellAddress)
- parameter: ParameterId¶
- anchor: SheetCellAddress¶
- class OperatorInput(**data)[source]¶
Bases:
BaseModelOne pre-populated operator-input value.
Operator inputs are casilla values the caller already knows (for example from the ledger or from a previous filing). They are written as literal values into the Entradas tab; the operator is free to overwrite them in the workbook.
- casilla_id: CasillaId¶
- value: Decimal | str | bool | None¶
- class OperatorInputs(**data)[source]¶
Bases:
BaseModelCaller-supplied seed values for the Entradas tab.
- Parameters:
values (tuple[OperatorInput, ...])
- values: tuple[OperatorInput, ...]¶
- by_casilla_id()[source]¶
Return a
CasillaId->OperatorInputlookup mapping.- Returns:
A
Mappingkeyed by canonical casilla.id. Later duplicates overwrite earlier ones; the registry enforces uniqueness so duplicates are not expected in practice.- Return type:
Mapping[CasillaId,
OperatorInput]
- class RelationValue(**data)[source]¶
Bases:
BaseModelOne pre-resolved cross-revision relation value.
Relations aggregate values from a different modelo’s filings (typically rolling quarterly filings up into an annual summary). The local side resolves them through resolve_relation_values_from_observations and supplies the result here; the engine mirrors it as a scalar cell in Tarifas so the workbook’s formulas can consume it.
provenance carries the source tier the value came from: local_filing (operator’s own prior filing in SecureObjectRepository), aeat_live (remote AEAT Sede justificante parse), operator_manual (operator entered the value into Sheets directly). The engine stamps the provenance on the workbook so the pull adapter can detect stale prefills. The source_* and ref fields mirror the registry relation so the scalar workbook value remains joinable back to its official source modelo, source casilla, and legal grounding.
- Parameters:
relation (RelationId)
value (Decimal | None)
provenance (Literal['local_filing', 'aeat_live', 'operator_manual'])
source_modelo (ModeloId | None)
source_filing_year (int | None)
source_casilla_ids (tuple[CasillaId, ...])
legal_refs (tuple[LegalRefId, ...])
source_refs (tuple[SourceRefId, ...])
resolved_at (datetime | None)
note (str | None)
- relation: RelationId¶
- value: Decimal | None¶
- provenance: Literal['local_filing', 'aeat_live', 'operator_manual']¶
- source_modelo: ModeloId | None¶
- source_filing_year: int | None¶
- source_periods: tuple[str, ...]¶
- source_casilla_ids: tuple[CasillaId, ...]¶
- legal_refs: tuple[LegalRefId, ...]¶
- source_refs: tuple[SourceRefId, ...]¶
- resolved_at: datetime | None¶
- note: str | None¶
- class RelationValues(**data)[source]¶
Bases:
BaseModelCaller-supplied relation aggregations for the Tarifas tab.
- Parameters:
values (tuple[RelationValue, ...])
- values: tuple[RelationValue, ...]¶
- by_relation()[source]¶
Return a
RelationId→RelationValuelookup mapping.- Returns:
A
Mappingkeyed by relation id for fast lookup when the engine resolves cross-revision formula references.- Return type:
Mapping[RelationId,
RelationValue]
- class SheetGuideContent(**data)[source]¶
Bases:
BaseModelPlain-text content for the Guía tab.
The guide tab is the human-readable preamble: how to use the workbook, what each tab contains, and where to find the bidirectional sync command. Strings are caller-supplied (the CLI surface resolves them through tr() so locale parity holds).
- title: str¶
- paragraphs: tuple[str, ...]¶
- class SheetExportMetadata(**data)[source]¶
Bases:
BaseModelStamps the workbook with the registry + engine identities.
Stored both in the workbook’s developer metadata (so the pull adapter can validate compatibility before merging operator edits) and rendered as plain-text in the Guía tab so a human reader can see provenance at a glance.
- Parameters:
- modelo_id: str¶
- revision_id: RevisionId¶
- filing_year: int¶
- period: Period¶
- engine_version: str¶
- registry_sha: str¶
- exported_at: datetime¶
- class SheetExportPlan(**data)[source]¶
Bases:
BaseModelComplete description of the workbook every renderer will write.
The plan is the shared contract between the registry-backed engine, Google Sheets apply adapter, offline XLSX materializer, pull adapter, and parity harness. It includes calculation cells, protected ranges, display facets, registry metadata, relation provenance, row sets, and workbook evidence.
- Parameters:
metadata (SheetExportMetadata)
value_cells (tuple[SheetValueCell, ...])
formula_cells (tuple[SheetFormulaCell, ...])
tariffs (tuple[SheetTariffTable, ...])
provenance (tuple[SheetProvenanceRow, ...])
protected_ranges (tuple[SheetProtectedRange, ...])
number_formats (tuple[SheetNumberFormat, ...])
section_headers (tuple[SheetSectionHeader, ...])
anchors (tuple[SheetAnchor, ...])
cell_constraints (tuple[SheetCellConstraint, ...])
row_sets (tuple[SheetRowSet, ...])
relation_provenance (RelationValues | None)
evidence (SheetEvidenceFacet)
font_family (str)
styled_ranges (tuple[SheetStyledRange, ...])
column_widths (tuple[SheetColumnWidth, ...])
frozen_views (tuple[SheetFrozenView, ...])
auto_filters (tuple[SheetAutoFilter, ...])
guide (SheetGuideContent)
- metadata: SheetExportMetadata¶
- value_cells: tuple[SheetValueCell, ...]¶
- formula_cells: tuple[SheetFormulaCell, ...]¶
- tariffs: tuple[SheetTariffTable, ...]¶
- provenance: tuple[SheetProvenanceRow, ...]¶
- protected_ranges: tuple[SheetProtectedRange, ...]¶
- number_formats: tuple[SheetNumberFormat, ...]¶
- section_headers: tuple[SheetSectionHeader, ...]¶
- anchors: tuple[SheetAnchor, ...]¶
- cell_constraints: tuple[SheetCellConstraint, ...]¶
- row_sets: tuple[SheetRowSet, ...]¶
- relation_provenance: RelationValues | None¶
- evidence: SheetEvidenceFacet¶
- font_family: str¶
- styled_ranges: tuple[SheetStyledRange, ...]¶
- column_widths: tuple[SheetColumnWidth, ...]¶
- frozen_views: tuple[SheetFrozenView, ...]¶
- auto_filters: tuple[SheetAutoFilter, ...]¶
- guide: SheetGuideContent¶
- all_addresses()[source]¶
Return every cell address referenced by value or formula cells.
Useful for collision detection and for building the full write list before sending requests to the Sheets API.
- Returns:
objects from
value_cellsfollowed by those fromformula_cells, in declaration order.- Return type:
tuple[
SheetCellAddress, …]