aeat.domain.invoices._models module

Strict immutable models for the invoice catalogue.

Defines the pydantic v2 records that back aeat.domain.invoices: InvoiceLine, Invoice, and the keyed InvoiceCatalogue. Every model is strict, frozen, and forbids extra fields; identity-bearing fields on Invoice are canonicalised in a model_validator and the stable Invoice.invoice_id is derived via derive_invoice_id(). Counterparty identity validation is delegated to aeat.domain.invoices._validators.

derive_invoice_id(*, kind, invoice_number, issued_at, counterparty_tax_id, currency, grand_total)[source]

Return the stable invoice hash for one invoice record.

The digest is computed over a canonical JSON payload so that two invoices with equal logical identity produce identical IDs regardless of whitespace or numeric formatting.

Parameters:
  • kind (InvoiceKind) – Invoice direction (issued / received).

  • invoice_number (str) – AEAT-significant invoice number as printed on the document.

  • issued_at (date) – ISO calendar date printed on the invoice.

  • counterparty_tax_id (str) – Counterparty NIF / NIE / CIF / IVA number already validated and uppercased.

  • currency (str) – ISO-4217 currency code already uppercased.

  • grand_total (Decimal) – Invoice grand total.

Return type:

str

Returns:

A lowercase SHA-256 digest that uniquely identifies the invoice.

class InvoiceLine(**data)[source]

Bases: BaseModel

Immutable line item on an invoice.

Parameters:
description: str
quantity: Decimal
unit_price: Decimal
subtotal: Decimal
iva_rate: IvaRate
iva_amount: Decimal
category_id: str | None
oss_rate_kind: IvaRateKind | None
class Invoice(**data)[source]

Bases: BaseModel

Strict frozen record for one issued or received invoice.

Parameters:
invoice_id: InvoiceId
bucket_id: BucketId | None
kind: InvoiceKind
invoice_number: str
issued_at: date
counterparty_name: str
counterparty_tax_id: str
counterparty_country: str
base_total: Decimal
iva_total: Decimal
grand_total: Decimal
currency: str
lines: tuple[InvoiceLine, ...]
payment_status: PaymentStatus
linked_transaction_ids: tuple[str, ...]
notes: str
iva_category: IvaCategory | None
operation_type: IntracomOperationType | None
oss_ioss_regime: OssIossRegime | None
oss_transaction_kind: TransactionKind | None
retention_rate: Decimal | None
retention_amount: Decimal | None
payment_id: str | None
property counterparty_eu_member_state: EUMemberState | None

Return the substrate-typed EUMemberState for the counterparty, or None for non-EU.

counterparty_country carries the raw uppercase ISO-3166-1 alpha-2 code (validated at construction time). This typed accessor lets downstream consumers (Modelo 369 OSS bindings, intra-community classification, OSS classifier dispatch) work with the closed substrate enum without a per-call lowercase / membership check. Anchored to aeat.domain.invoices.EU_MEMBER_STATE_CODES which derives from aeat.domain.iva.EUMemberState.

property counterparty_is_eu_member: bool

Return True iff the counterparty is in one of the 27 EU Member States.

Convenience predicate keyed off the substrate enum; equivalent to invoice.counterparty_eu_member_state is not None. Modelo classification routes (OSS / IOSS / intra-community) gate on this predicate to decide which substrate flow path applies.

class InvoiceCatalogue(**data)[source]

Bases: BaseModel

Immutable invoice catalogue keyed by invoice_id.

Parameters:

invoices (Mapping[str, Invoice])

invoices: Mapping[str, Invoice]
classmethod from_invoices(invoices)[source]

Build an immutable catalogue from an iterable of invoices.

Parameters:

invoices (Iterable[Invoice | Mapping[str, object]]) – Invoices or invoice payloads to load.

Return type:

Self

Returns:

A validated immutable invoice catalogue.

get(invoice_id)[source]

Fetch one invoice by ID if present.

Parameters:

invoice_id (str) – Stable invoice identifier.

Return type:

Invoice | None

Returns:

The matching Invoice, or None when absent.

values()[source]

Iterate over catalogue Invoice records.

Return type:

Iterator[Invoice]