aeat.domain.iva._schema module

Strict pydantic v2 schema for the aeat.domain.iva subpackage.

Every record the subpackage exposes — enumerations, per-rate values, citations, regulations, catalogues, verification reports — is defined here. The schema is frozen and strict wherever the loader idiom permits it, matching the current registry-backed legal grounding conventions.

Closed catalogues (IvaCategory, EUMemberState, IvaRateKind, IvaCitationSource) are enum.StrEnum subclasses. Multilingual fields use aeat.core.i18n.tr to ensure the internationalization engine can dynamically resolve the correct locale at runtime for UI labels and descriptions. Legal quotes remain Spanish- authoritative.

class IvaCategory(*values)[source]

Bases: StrEnum

Closed catalogue of Spanish IVA (IVA) situations.

The member names and string values are the authoritative identifiers used by the downstream classifier layers (financial providers, the spending category taxonomy, and the transaction-data-pipeline engine) to tag a transaction.

DOMESTIC_GENERAL_21
DOMESTIC_REDUCED_10
DOMESTIC_SUPER_REDUCED_4
DOMESTIC_ZERO
DOMESTIC_EXEMPT
DOMESTIC_NOT_SUBJECT
DOMESTIC_REVERSE_CHARGE
INTRA_COMMUNITY_SUPPLY
INTRA_COMMUNITY_ACQUISITION_REVERSE_CHARGE
INTRA_COMMUNITY_TRIANGULATION
EXPORT_THIRD_COUNTRY_ZERO_RATED
EXPORT_ASSIMILATED_ZERO_RATED
IMPORT_THIRD_COUNTRY
RECARGO_EQUIVALENCIA
REGIMEN_SIMPLIFICADO
OPERACION_NO_SUJETA
ERRONEOUS_INVOICE
UNKNOWN
class IvaCashAccountingTreatment(*values)[source]

Bases: StrEnum

Independent cash-accounting treatment axis for IVA observations.

Cash accounting is a settlement-timing and informational-reporting regime, not an operation category. The values here deliberately do not overlap with IvaCategory: a row keeps its domestic/export/intracom/etc. category and separately declares whether cash-accounting timing applies.

NONE
TAXPAYER_REGIME
SUPPLIER_REGIME
class IvaCashAccountingPaymentEvidence(**data)[source]

Bases: BaseModel

Collection/payment evidence for an operation affected by criterio de caja.

The amounts are the IVA substrate settled by the collection/payment event, not a gross bank amount that downstream code must reinterpret. Partial evidence therefore remains explicit and auditable.

Parameters:
payment_date: date
taxable_base: Decimal
iva_amount: Decimal
recargo_amount: Decimal
class IvaExemptionArticle(*values)[source]

Bases: StrEnum

Closed catalogue of Ley 37/1992 Art. 20 sub-articles.

Differentiates downstream-deduction routing on operations classified as IvaCategory.DOMESTIC_EXEMPT.

The MVP set covers the three sub-articles whose deduction-right or Modelo 303 routing semantics diverge from the default DOMESTIC_EXEMPT collapse, plus a catch-all for other Art. 20 cases. The discriminator is OPTIONAL on the classification result: None means the operation is exempt with no further sub-article distinction needed; a stamped value means the calculation chain can route to the sub-article-specific casilla (e.g. Modelo 303 casilla 61 for ART_20_UNO_26 artistas plena con prorrata).

The discriminator’s legal grounding follows Ley 37/1992 (BOE-A-1992-28740). Each sub-article cites the matching article in its docstring; the registry-side casilla bindings carry the full legal_refs chain per the registry-calculation-legal-grounding rule.

Authority: 2026-06-03-iva-exemption-article-adr.

ART_20_UNO_8

Enseñanza — exenta sin derecho a deducción (Ley 37/1992 Art. 20.Uno.8).

ART_20_UNO_14

Sanitarios — exenta sin derecho a deducción (Ley 37/1992 Art. 20.Uno.14).

ART_20_UNO_26

Servicios artísticos — exenta con plena prorrata (Ley 37/1992 Art. 20.Uno.26). Routes to Modelo 303 casilla 61.

ART_20_OTHER

Other Art. 20 sub-articles whose routing semantics do not yet warrant a dedicated enum slot. New slots open as their routing demands surface.

class EUMemberState(*values)[source]

Bases: StrEnum

Current EU IVA country prefixes accepted at IVA-facing boundaries.

The canonical 27 EU member states use ISO 3166-1 alpha-2 codes. XI is the post-Brexit Northern Ireland VAT prefix accepted for goods movements in Modelo 349 / intra-community IVA contexts; predicates that need strict member-state membership must exclude it explicitly.

AT
BE
BG
CY
CZ
DE
DK
EE
ES
FI
FR
GR
HR
HU
IE
IT
LT
LU
LV
MT
NL
PL
PT
RO
SE
SI
SK
XI
class IvaRateKind(*values)[source]

Bases: StrEnum

Closed catalogue of rate tiers referenced by IvaRateRecord.

GENERAL
REDUCED
SUPER_REDUCED
ZERO
EXEMPT
class IvaCitationSource(*values)[source]

Bases: StrEnum

Closed catalogue of legal/regulatory sources cited by IVA rules.

LEY_37_1992
MANUAL_IVA_2025
DIRECTIVE_2006_112_EC
OTHER
class IvaRateRecord(**data)[source]

Bases: _IvaStrictFrozen

A single IVA rate line item keyed by member state and rate kind.

Variables:
  • member_state – Issuing member state.

  • kind – Rate tier (general / reduced / …).

  • pct – Rate percentage as a Decimal in [0, 100].

  • effective_from – First date the rate applies.

  • effective_until – Last date the rate applies, or None for open-ended.

  • boe_or_directive_reference – Free-form reference to the BOE entry or Council Directive article that backs this rate.

Parameters:
  • member_state (EUMemberState)

  • kind (IvaRateKind)

  • pct (Decimal)

  • effective_from (date)

  • effective_until (date | None)

  • boe_or_directive_reference (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=256, pattern=None, ascii_only=None)])

member_state: EUMemberState
kind: IvaRateKind
pct: Decimal
effective_from: date
effective_until: date | None
boe_or_directive_reference: _BoeOrDirectiveRef
class IvaCitation(**data)[source]

Bases: _IvaStrictFrozen

A legal or regulatory citation backing a IvaRegulation.

The quoted_text field must be an authoritative translation key pointing to a non-empty Spanish string. It may be a faithful paraphrase of the article’s statutory language when a verbatim extract is not practical. Auditability relies on the combination of source, article and quoted_text.

Variables:
  • source – Legal source of the citation.

  • article – Article reference, for example Art. 91.Uno.2.1º.

  • url – Optional deep link to the cited article.

  • quoted_text – Non-empty Spanish quote or faithful paraphrase.

  • retrieval_date – Date the citation was retrieved or last reviewed.

Parameters:
  • source (IvaCitationSource)

  • article (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=128, pattern=None, ascii_only=None)])

  • url (AnyHttpUrl | None)

  • quoted_text (Translatable)

  • retrieval_date (date)

source: IvaCitationSource
article: _ArticleRef
url: AnyHttpUrl | None
quoted_text: tr
retrieval_date: date
class IvaRegulation(**data)[source]

Bases: _IvaStrictFrozen

A single codified IVA rule for a IvaCategory.

Every regulation carries at least one IvaCitation. The substrate-level invariant enforced by aeat.domain.iva.verify_catalogue() additionally requires every shipped regulation to cite real legal articles so downstream tools can surface the legal backing of any classification.

Variables:
  • category – The IVA situation codified by this rule.

  • label – Short human-readable label key.

  • description – One-paragraph plain-language description key.

  • triggers_when – Plain-language description of when this rule fires (key).

  • iva_treatment – Plain-language description of the fiscal treatment (key).

  • requires_reverse_charge – Whether the rule triggers inversión del sujeto pasivo.

  • requires_supplier_iva_id – Whether a supplier NIF-IVA is mandatory.

  • boe_references – Registry legal-reference document ids backing this rule.

  • manual_references – Optional Manual práctico IVA rule ids or section references.

  • citations – At least one IvaCitation is required.

  • notes – Free-form reviewer notes.

Parameters:
  • category (IvaCategory)

  • label (Translatable)

  • description (Translatable)

  • triggers_when (Translatable)

  • iva_treatment (Translatable)

  • requires_reverse_charge (bool)

  • requires_supplier_iva_id (bool)

  • boe_references (tuple[Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=128, pattern=^[a-z0-9][a-z0-9-]*$, ascii_only=None)], ...])

  • manual_references (tuple[Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=256, pattern=None, ascii_only=None)], ...])

  • citations (tuple[IvaCitation, ...])

  • notes (str)

category: IvaCategory
label: tr
description: tr
triggers_when: tr
iva_treatment: tr
requires_reverse_charge: bool
requires_supplier_iva_id: bool
boe_references: tuple[_NormativeId, ...]
manual_references: tuple[_ManualRef, ...]
citations: tuple[IvaCitation, ...]
notes: str
class IvaCatalogue(**data)[source]

Bases: _IvaStrictMutable

Aggregate view over a collection of IvaRegulation records.

The aggregate is mutable to keep the loader idiom simple — the loader populates the mapping incrementally. Individual IvaRegulation records remain frozen.

Variables:

regulations – Regulations keyed by their IvaCategory.

Parameters:

regulations (dict[IvaCategory, IvaRegulation])

regulations: dict[IvaCategory, IvaRegulation]
get(category)[source]

Return the IvaRegulation for category or None if absent.

Return type:

IvaRegulation | None

Parameters:

category (IvaCategory)

class IvaVerificationIssue(**data)[source]

Bases: _IvaStrictFrozen

A single finding produced by aeat.domain.iva.verify_catalogue().

Variables:
  • level – Severity, either "error" or "warning".

  • code – Short stable issue code.

  • message – Human-readable detail.

  • category_id – Affected IVA category value, if any.

Parameters:
  • level (str)

  • code (str)

  • message (str)

  • category_id (str | None)

level: str
code: str
message: str
category_id: str | None
class IvaVerificationReport(**data)[source]

Bases: _IvaStrictFrozen

Aggregate verification report for a IvaCatalogue.

Variables:

issues – All findings produced by aeat.domain.iva.verify_catalogue().

Parameters:

issues (tuple[IvaVerificationIssue, ...])

issues: tuple[IvaVerificationIssue, ...]
property errors: tuple[IvaVerificationIssue, ...]

Return the subset of issues whose IvaVerificationIssue.level is "error".

Returns:

Tuple of IvaVerificationIssue objects with error-level severity.

property clean: bool

Return True when no error-level issues were found.