cadrumo.domain.justificante.schema module

Strict pydantic v2 schema for parsed AEAT justificantes.

The Justificante record is the boundary-crossing type consumed by downstream subpackages (the submission engine and the status reader). It is frozen and strict so callers can rely on deterministic field types, and so mutating it after parse requires an explicit pydantic.BaseModel.model_copy().

class JustificanteParserBackend(*values)[source]

Bases: StrEnum

Closed set of supported parser backends.

Variables:

PDFPLUMBER – Fidelity-first default backend.

PDFPLUMBER
class Justificante(**data)[source]

Bases: BaseModel

Parsed AEAT justificante de presentación receipt.

A Justificante represents a single successful filing receipt produced by AEAT after a modelo has been submitted. Every field is either pulled verbatim from the PDF body or derived deterministically from the source file (source_pdf_sha256, parsed_at).

Variables:
  • csv – Código Seguro de Verificación — the short AEAT-assigned hash used to verify the document on the Sede electrónica.

  • modelo – String ID of the modelo the receipt belongs to. References the modelo catalogue in domain.modelos.

  • period – Typed filing period resolved from the AEAT period token printed on the receipt and ejercicio.

  • ejercicio – Four-digit tax year as printed on the receipt, when present. None for receipts that omit the label.

  • presentation_id – AEAT’s internal Número de justificante if present on the receipt; None when the modelo does not print a separate presentation ID.

  • presented_at – Timestamp AEAT stamped on the receipt at submission.

  • tax_id – NIF/NIE of the taxpayer who filed (the autónomo owner).

  • total_a_ingresar – Amount to be paid in, if the receipt includes one.

  • total_a_devolver – Amount to be refunded, if the receipt includes one.

  • verification_url – AEAT URL printed on the receipt where the CSV can be re-verified against the Sede electrónica.

  • source_pdf_path – Privacy-preserving source reference derived from the source PDF digest.

  • source_pdf_sha256 – Lowercase hex sha-256 of the source PDF bytes.

  • parsed_at – UTC wall-clock time the parse finished.

Parameters:

data (Any)

csv: AeatCsv
modelo: str
ejercicio: str | None
period: Period
presentation_id: AeatPresentationId | None
presented_at: datetime

the receipt prints a Europe/Madrid wall-clock time.

AEAT stamps the local time on the justificante without an offset, and the extractor reads it with strptime, so no instant is available to validate. Typing this as a UTC instant refuses every real receipt – which is what it did until this line was corrected – and inventing an offset here would be guessing at a timezone the document never states.

Type:

Naive by design

tax_id: SubjectTaxId
total_a_ingresar: Decimal | None
total_a_devolver: Decimal | None
verification_url: AnyHttpUrl
source_pdf_path: Path
source_pdf_sha256: ContentDigest
parsed_at: UtcInstant
matches_filing_target(*, modelo, filing_year, period, tax_id=None)[source]

Return whether this receipt belongs to one filing target.

tax_id is an optional refinement for receipt sources that do not expose that axis.

Verifying that the receipt is the one AEAT issued for a filing is the caller’s job, and it is a csv comparison against a csv the caller obtained from somewhere other than this PDF. This predicate deliberately offers no parameter for that axis: the only receipt identifier printed beside the csv is presentation_id, AEAT’s Número de justificante, and the values callers actually hold are register-issued expediente ids from Consultar declaraciones presentadas — a different AEAT namespace that never appears on a receipt body, so no caller could populate such a parameter correctly.

Return type:

bool

Parameters: