aeat.domain.calculations.registry._convenio module

Cross-cutting Convenio doble imposición (CDI) treaty-override authority.

A dedicated registry authoring surface — registry/aeat/treaties/ — sibling to the cross-cutting legal/ tree. One TOML file per bilateral double-taxation treaty declares the counterpart country, the treaty BOE document_id, and a list of per-income-type override rows keyed by TipoRentaIrnr. The loader compiles the tree into a ConvenioAuthority projection that any IRNR rate formula consumes through the RegistrySnapshot — so a second consumer (M216 retenciones a no residentes) reads treaty data without reaching across a modelo boundary.

Each override row carries a typed ConvenioOverrideKind so the “más favorable” / limitation-of-benefits decision is computed rather than coincidental: flat replaces the domestic rate, ceiling applies min(domestic, treaty), allocation_domestic_tariff delegates the amount to the domestic tariff, and exempt drives the source-state rate to zero.

class ConvenioOverrideRow(**data)[source]

Bases: RegistryModel

One per-income-type treaty override keyed by TipoRentaIrnr.

The typed ConvenioOverrideKind decides how the row acts on the domestic IRNR rate. flat and ceiling rows MUST declare a rate in [0, 1]; allocation_domestic_tariff and exempt rows MUST NOT (the amount is delegated to the domestic tariff or driven to zero). The legal_ref_anchor MUST be one of the row’s legal_refs and resolve to a treaty article in the shared legal/ catalogue.

Parameters:
tipo_renta: TipoRentaIrnr
kind: ConvenioOverrideKind
rate: str | None
legal_ref_anchor: LegalRefId
legal_refs: tuple[LegalRefId, ...]
notes: str | None
valid_from: date
valid_to: date | None
property rate_decimal: Decimal | None

The parsed rate for a rate-bearing kind, else None.

class ConvenioTreaty(**data)[source]

Bases: RegistryModel

One bilateral double-taxation treaty and its per-income-type overrides.

Authored one file per treaty under registry/aeat/treaties/ and keyed by the counterpart country_code (ISO 3166-1 alpha-2). The optional permanent-establishment / employment-income surfaces named by issue #537 are deliberately not modelled in the first slice; the schema leaves room for them without foreclosing.

Parameters:
country_code: str
document_id: str
overrides: tuple[ConvenioOverrideRow, ...]
notes: str | None
class ConvenioOverride(**data)[source]

Bases: RegistryModel

The resolved treaty override returned by ConvenioAuthority.resolve().

A flat projection of the matched ConvenioOverrideRow bound to its treaty’s country_code and document_id — the shape the IRNR rate op and the application verification sweep branch on. rate is populated only for the rate-bearing kinds (flat / ceiling).

Parameters:
country_code: str
document_id: str
tipo_renta: TipoRentaIrnr
kind: ConvenioOverrideKind
rate: Decimal | None
legal_refs: tuple[LegalRefId, ...]
class ConvenioAuthority(**data)[source]

Bases: RegistryModel

The compiled cross-cutting treaty authority projected onto every snapshot.

Owns the {country_code: ConvenioTreaty} map and the single resolve() lookup any IRNR rate formula consumes. Projected onto the RegistrySnapshot the same way the shared legal/ catalogue is, so the treaty override is one branch of the single tipo-de-gravamen resolution path, never a parallel rate mechanism.

Parameters:

treaties (Mapping[str, ConvenioTreaty])

treaties: Mapping[str, ConvenioTreaty]
classmethod empty()[source]

Return a ConvenioAuthority with no treaties (the no-override default).

Return type:

ConvenioAuthority

resolve(country_code, tipo_renta, year)[source]

Return the ConvenioOverride for (country_code, tipo_renta, year), or None.

None means no treaty row applies — the caller keeps the domestic baseline (no country declared) or raises the missing-row BLOCKING sentinel (a treaty country was declared but carries no row for the filed income type), never a silent blank.

Return type:

ConvenioOverride | None

Parameters:

Every legal_ref cited by any override row across every treaty.

Return type:

frozenset[TypeAliasType]

load_convenio_authority(treaties_dir)[source]

Compile the treaties/ TOML tree into a ConvenioAuthority.

Reads one [treaty] table per file, rejecting a duplicate counterpart country declared across two files. An absent tree yields an empty authority.

Return type:

ConvenioAuthority

Returns:

The compiled ConvenioAuthority.

Parameters:

treaties_dir (Path)

collect_convenio_fingerprints(root)[source]

Return (path, size, mtime_ns) fingerprints for every treaties/*.toml.

Folded into the authority-level cache key so a treaty content edit (which does not bump the parent directory mtime the registry-tree walk observes) invalidates the compiled authority, per aeat-registry-authority-flow.

Return type:

tuple[tuple[str, int, int], ...]

Parameters:

root (Path)

Raise when a treaty override cites a legal_ref absent from the catalogue.

The grounding gate: every treaty rate MUST cite a treaty article defined in the shared legal/ catalogue (which itself resolves to bundled BOE corpus text). An override pointing at an undefined ref is a build-time failure.

Return type:

None

Parameters: