aeat.core._irnr module

Closed value sets for the IRNR (non-resident income tax) treaty surface.

Two closed axes governing the Modelo 210 IRNR rate-resolution path — and, by design, every future IRNR consumer (M216 retenciones a no residentes) — are declared here as enum.StrEnum per the core-authority discipline (closed axes live in core/, hydrated at boundaries, asserted as members in tests, surfaced as click Choice at the CLI):

  • TipoRentaIrnr — the income-type axis an IRNR filer tags each item with. It keys the TRLIRNR baseline rate table, the treaty override rows, and the Art. 25.1.b pension tariff branch. It was previously a free-text casilla value with no enum home, which forced adjacent verification work to route a categorical-equality predicate around the untyped axis.

  • ConvenioOverrideKind — how a bilateral double-taxation treaty (Convenio para evitar la doble imposición, CDI) override acts on the domestic rate. Making the kind typed data turns “más favorable” / limitation-of-benefits from a numeric coincidence (a flat treaty rate that happens to be lower than the domestic baseline) into a computable decision.

Both enums are consumed by the cross-cutting registry/aeat/treaties/ authoring tree and its ConvenioAuthority projection. The registry TOML stays free-form (a plain string token); the loader hydrates the enum at the boundary.

class TipoRentaIrnr(*values)[source]

Bases: StrEnum

The IRNR income-type axis (TRLIRNR RDLeg 5/2004 arts. 24-25).

Each member’s value is the byte-identical token stored in the registry tipo_renta casilla and used as the lookup key for the baseline rate table (m210-tipo-gravamen-2025), the treaty override rows, and the Art. 25.1.b pension tariff branch. The value set is closed by the TRLIRNR rate schedule; a new income category is added here first.

Members:

GENERAL: Art. 25.1.a general non-resident rate (24%).

UE_RESIDENTE: Art. 25.1.a reduced rate for EU/EEA residents (19%).

PENSION: Art. 25.1.b progressive pension tariff (bracket table).

DIVIDEND: Art. 25.1.f.1º dividends / other income from participation

in an entity’s own funds (19%).

INTEREST: Art. 25.1.f.2º interest / capital-cession income (19%).

GANANCIA_PATRIMONIAL: Art. 25.1.f.3º capital gains (19%).

INMOBILIARIA: Art. 13.1.h imputed urban real-estate income (the source

article), taxed at the Art. 25.1.a general 24% rate.

CANONES: Art. 25.1.a cánones (royalties). The consolidated Art. 25.1

carries no cánones-specific letter, so royalties are taxed at the general rendimiento rate (24%, or the Art. 25.1.a reduced 19% for EU/EEA residents). Bilateral treaties routinely cap or exempt the source-state cánones rate via their Art. 12.

GENERAL
UE_RESIDENTE
PENSION
DIVIDEND
INTEREST
GANANCIA_PATRIMONIAL
INMOBILIARIA
CANONES
class ConvenioOverrideKind(*values)[source]

Bases: StrEnum

How a double-taxation treaty override acts on the domestic IRNR rate.

The override is one branch of the single tipo-de-gravamen resolution path, not a second resolver. On a matched treaty override row the resolver applies the kind:

Members:

FLAT: The treaty rate REPLACES the domestic baseline outright.

CEILING: The treaty caps the source-state rate (“may not exceed X%”);

the resolver applies min(domestic, treaty) so the “más favorable” outcome is computed rather than assumed.

ALLOCATION_DOMESTIC_TARIFF: The treaty allocates taxation to Spain but

fixes no rate; the amount is delegated to the domestic tariff (e.g. the Art. 25.1.b progressive pension tariff). Rows of this kind carry no rate.

EXEMPT: The source state may not tax the income; the resolver yields a

zero rate. Rows of this kind carry no rate.

FLAT
CEILING
ALLOCATION_DOMESTIC_TARIFF
EXEMPT
property carries_rate: bool

True when a row of this kind MUST declare a numeric rate.

FLAT and CEILING operate on a treaty rate; ALLOCATION_DOMESTIC_TARIFF and EXEMPT do not (the amount is delegated to the domestic tariff or driven to zero). Consumed by the treaty-row validator so a malformed row (a rate on an exempt override, or a missing rate on a ceiling) fails at registry-build time.

class TipoRentaGroundingTier(*values)[source]

Bases: StrEnum

How firmly the bundled corpus grounds an official code’s rate concept.

The official Modelo 210 tipo-de-renta code axis (Orden EHA/3316/2010, “HOJA INFORMATIVA 210 - TIPOS DE RENTA”) is a numeric code list, but the rate each code bears is only bundled-verifiable for the codes whose rate concept is named by a bundled TRLIRNR Art. 25 letter (the shipped corpus is a Phase-1 extract carrying Art. 25 letters a, b, and f only; the special-rate letters c/d/e/g/h are absent). This tier records, per declared code, how its TipoRentaIrnr rate concept is grounded:

Members:
RATE_VERIFIED: The rate concept is explicitly modelled by the bundled

corpus — a bundled Art. 25 special letter that names the income (25.1.b pensions, 25.1.f dividends / interest / capital gains) or a dedicated bundled mechanism (Art. 13.1.h imputed real-estate).

RESIDUAL: The code is an ordinary rendimiento with no special regime,

mapped to TipoRentaIrnr.GENERAL on the Art. 25.1.a “con carácter general, el 24 por ciento” residual clause. A later fetch of the full consolidated Art. 25 that reveals a special rate for such a code is a CORRECTION of this row, never a contradiction of its grounding.

RATE_VERIFIED
RESIDUAL
class OfficialTipoRentaCode(code, concept, rate_legal_ref, grounding_tier)[source]

Bases: object

One official Modelo 210 tipo-de-renta code and its rate projection.

The operator enters the two-digit official code the form asks for; the engine keeps TipoRentaIrnr as its rate key. This record is the single projection from the official code to that conceptual key, carried with the grounding that justifies the mapping. The official codes are many-to-one onto the rate concepts (every ordinary rendimiento folds into general), which is why the code axis is declared alongside — not in place of — the conceptual enum.

Variables:
  • code – The two-digit official code, byte-identical to the “Tipo” column of the bundled HOJA INFORMATIVA 210 (Orden EHA/3316/2010).

  • concept – The TipoRentaIrnr rate concept the code folds into.

  • rate_legal_ref – The legal-catalogue id (a TRLIRNR article) that establishes the concept’s rate for this code. The load-bearing grounding is registry-resident: the m210-tipo-renta-code-2025 parameter carries the legal_refs the canonical registry legal-grounding gate validates against the bundled corpus.

  • grounding_tier – Whether the rate concept is directly rate-verified from the bundled corpus or rests on the Art. 25.1.a residual clause.

Parameters:
code: str
concept: TipoRentaIrnr
grounding_tier: TipoRentaGroundingTier
M210_TIPO_RENTA_CODE_PROJECTION: MappingProxyType

Read-only official-code → TipoRentaIrnr projection.

Derived from OFFICIAL_M210_TIPO_RENTA_CODES; the single mapping the CLI hydrates to resolve an operator-entered official code to its rate concept. Keys are the byte-identical two-digit official codes; values are the rate concept the engine dispatches on. The registry-build parity gate (validate_m210_tipo_renta_code_projection_parity) cross-checks this projection against the registry-declared m210-tipo-renta-code-2025 code set in both directions, so a declared code without a projection — or a projected code the registry does not declare — fails the build.

project_m210_tipo_renta_code(code)[source]

Project an official Modelo 210 tipo-de-renta code to its rate concept.

Parameters:

code (str) – A two-digit official code from the HOJA INFORMATIVA 210.

Return type:

TipoRentaIrnr

Returns:

The TipoRentaIrnr rate concept the code folds into.

Raises:

KeyError – When code is not a declared, rate-grounded official code. A fetch-gated code (whose rate is not yet bundle-verifiable) raises here rather than resolving to a fabricated rate.