aeat.adapters.outbound.aeat.sede._schema module

Strict pydantic records for the authenticated AEAT sede surface.

Every record represents a read-only AEAT filing, document, or notification observation. The schema is intentionally narrow so malformed or unsupported AEAT response shapes fail during parsing.

Every boundary-crossing record carries mode: Literal["read"] as part of the structural write-guard — the sede module is incapable of mutating AEAT state.

Public surface: Expediente, JustificanteRef, SedeCapture, FiledDeclaracionArtefact, ObservedCasillaValue, FiledDeclaracionObservation.

class Expediente(**data)[source]

Bases: BaseModel

One AEAT expediente as listed under Mis Expedientes.

The sede renders an AJAX-expanded category tree at /wlpl/TEWV-CORE/ResumenVlt; leaf rows carry the expediente id as the link text and the detail URL on the <a> href.

Variables:
  • expediente_id – AEAT-assigned identifier. Shape <year><sequence><checksum-letter>, e.g. "202310013522456T".

  • modelo – Modelo code inferred from the category path when resolvable (e.g. "100" for IRPF anuales). None for categories that do not map 1:1 to a modelo (sanciones, recursos, certificados).

  • ejercicio – Tax year inferred from the expediente id’s leading four digits. Captured against 2021 / 2022 / 2023 IRPF.

  • category_path – Breadcrumb through the sede’s tree, from root to leaf. Example: a four-element tuple from “Agencia Estatal de Administración Tributaria” down to “Modelo 100- Modelo 102. IRPF. Declaración y documento de ingreso o devolución.”.

  • detail_url – Full URL of the expediente’s detail page. Per-year endpoint for IRPF: /wlpl/DASR-CORE/AccesoDR<YYYY>RVlt?exp=<id>.

  • mode – Structural read-only marker.

Parameters:
  • expediente_id (str)

  • modelo (str | None)

  • ejercicio (int | None)

  • category_path (tuple[str, ...])

  • detail_url (AnyHttpUrl)

  • mode (Literal['read'])

expediente_id: str
modelo: str | None
ejercicio: int | None
category_path: tuple[str, ...]
detail_url: AnyHttpUrl
mode: Literal['read']
class JustificanteRef(**data)[source]

Bases: BaseModel

CSV-keyed handle for AEAT’s document verifier.

On every expediente detail page, the Grabación de la declaración link carries the document’s CSV in its href. The same CSV unlocks both the HTML cotejo viewer (CotejoIdSv) and the raw PDF (CotejoDocIdSv).

Variables:
  • csv – Código Seguro de Verificación — AEAT’s per-document hash.

  • expediente_id – The expediente this CSV belongs to; tracked so reconciliation can tie a justificante back to its listing row.

  • cotejo_url – Viewer URL /wlpl/KATA-APLI/cotejo/CotejoIdSv?CSV=<csv>.

  • pdf_url – Raw PDF URL /wlpl/KATA-APLI/cotejo/CotejoDocIdSv?CSV=<csv>.

  • mode – Structural read-only marker.

Parameters:
  • csv (str)

  • expediente_id (str)

  • cotejo_url (AnyHttpUrl)

  • pdf_url (AnyHttpUrl)

  • mode (Literal['read'])

csv: str
expediente_id: str
cotejo_url: AnyHttpUrl
pdf_url: AnyHttpUrl
mode: Literal['read']
class SedeCapture(**data)[source]

Bases: BaseModel

One complete sede-side capture of a filing.

Bundles the expediente listing metadata, the CSV handle, the raw PDF bytes, and the captured-at timestamp. Produced by adapters.outbound.aeat.sede.capture_justificante(); consumed by the reconciler.

Variables:
  • expediente – The expediente the capture originated from.

  • ref – The CSV handle the capture used.

  • pdf_bytes – Raw PDF body as served by AEAT.

  • pdf_sha256 – Lowercase hex sha-256 of pdf_bytes.

  • captured_at – UTC timestamp of the fetch completion.

  • mode – Structural read-only marker.

Parameters:
expediente: Expediente
ref: JustificanteRef
pdf_bytes: bytes
pdf_sha256: str
captured_at: datetime
mode: Literal['read']
class FiledDeclaracionArtefact(**data)[source]

Bases: BaseModel

One immutable artefact captured from AEAT’s filed-declaration surface.

The artefact is evidence of what AEAT served during a read-only session. It is not calculation authority; legal/formula authority remains in BOE, AEAT instructions, manuals, and registry definitions.

Parameters:
  • kind (Literal['register_row', 'submitted_file', 'declaration_pdf', 'justificante_pdf'])

  • source_url (AnyHttpUrl)

  • content_type (str)

  • byte_count (int)

  • sha256 (str)

  • captured_at (datetime)

  • storage_ref (str | None)

  • mode (Literal['read'])

kind: Literal['register_row', 'submitted_file', 'declaration_pdf', 'justificante_pdf']
source_url: AnyHttpUrl
content_type: str
byte_count: int
sha256: str
captured_at: datetime
storage_ref: str | None
mode: Literal['read']
class ObservedCasillaValue(**data)[source]

Bases: BaseModel

One casilla value observed from an AEAT filed-data artefact.

Parameters:
  • casilla_id (CasillaId)

  • value (str)

  • source_artefact_kind (Literal['submitted_file', 'declaration_pdf', 'justificante_pdf', 'derived_registry_formula', 'derived_carry_policy'])

  • source_locator (str)

  • confidence (float)

  • mode (Literal['read'])

casilla_id: CasillaId
value: str
source_artefact_kind: Literal['submitted_file', 'declaration_pdf', 'justificante_pdf', 'derived_registry_formula', 'derived_carry_policy']
source_locator: str
confidence: float
mode: Literal['read']
class IvaCompensationWalletRow(**data)[source]

Bases: BaseModel

One AEAT wallet row for IVA compensation generated in a source period.

The row represents external AEAT state, not a filed-declaration casilla. It maps one line of AEAT’s “Cartera de cuotas de IVA a compensar” detail table: the period that generated the credit plus its still-available balance (the “Cuota Disponible” column), carried in pending_amount.

AEAT’s read-only cartera consultation surface exposes only the available balance per generation period; it does not break out the original generated amount or the cumulative applied amount. generated_amount and applied_amount are therefore optional and stay None for this surface, reserved for a richer AEAT view that itemises the movement columns.

Parameters:
generation_year: int
generation_period: Period
generated_amount: Decimal | None
applied_amount: Decimal | None
pending_amount: Decimal
raw_label: str | None
mode: Literal['read']
class IvaCompensationWalletObservation(**data)[source]

Bases: BaseModel

Read-only observation of AEAT’s IVA compensation wallet.

Produced by the authenticated Sede wallet reader. Calculation code must not consume this record directly; it is raw evidence consumed by the reconciliation layer, which emits the effective binding decision for Modelo 303 casilla 110.

Parameters:
taxpayer_nif: str
authenticated_identity: str
target_modelo: Literal[Modelo.M303]
target_year: int
target_period: Period
rows: tuple[IvaCompensationWalletRow, ...]
total_pending: Decimal
source_url: AnyHttpUrl
captured_at: datetime
raw_sha256: str | None
mode: Literal['read']
class FiledDeclaracionObservation(**data)[source]

Bases: BaseModel

Normalized read-only observation of one filed AEAT declaration.

A complete observation starts from the register row and may include submitted machine-readable data, declaration PDFs, and justificante PDFs. Parsed casillas are observations only; downstream calculation logic must validate them through registry extraction profiles.

Parameters:
modelo: str
ejercicio: int
period: Period
expediente_id: str
status: str
presented_at: datetime
authenticated_identity: str
artefacts: tuple[FiledDeclaracionArtefact, ...]
casillas: tuple[ObservedCasillaValue, ...]
metadata: dict[str, str]
extraction_coverage: dict[str, float]
registry_snapshot_id: str | None
mode: Literal['read']