aeat.domain.iva._prorrata module

Legal IVA prorrata substrate (LIVA arts. 101-103).

This module implements the Spanish Value-Added-Tax (IVA) prorrata mechanism that governs how a taxable person who performs both deductible and non-deductible operations may deduct input IVA. The substrate is pure domain logic: it produces immutable result objects and never touches persistence, the registry, or the CLI.

Legal sources (Ley 37/1992 del IVA, BOE-A-1992-28740):

  • Art. 101 triggers the rule when a taxpayer performs operations that grant the right to deduction (taxable supplies, deemed-domestic intracomunitarias, intra-EU services, etc.) alongside operations that do NOT grant the right (LIVA arts. 20 and 21 exempt supplies and similar). The default form is prorrata general (art. 102); prorrata especial (art. 103) applies on election or as a mandatory fallback when the general regime overstates the deduction by more than ten percent.

  • Art. 102.Uno — general prorrata formula: deductible_percentage = operaciones_con_derecho / total_operaciones. operaciones_con_derecho is the sum of the year’s operations that grant the right to deduct input IVA. total_operaciones is the sum of operaciones_con_derecho plus operaciones_sin_derecho (LIVA-art.-20 exempt supplies and similar). Subvenciones not linked to operations, autoconsumos, and the disposal of bienes de inversión are excluded from both numerator and denominator per art. 104 LIVA; the exclusion is the caller’s responsibility; this module only accepts already-filtered operation totals.

  • Art. 102.Dos — the resulting percentage is rounded up to the next whole integer (ROUND_CEILING against Decimal("1")).

  • Art. 103.Dos — prorrata especial is mandatory whenever the deduction computed under the general regime exceeds the deduction computed under the especial regime by more than ten percent (i.e. deduction_general > deduction_especial * Decimal("1.10")).

  • Art. 9.1.c — sectoral separation (régimen de sectores diferenciados) applies when the taxpayer’s activities form two or more distinct sectors and the difference between the highest and lowest general prorrata across sectors exceeds fifty percentage points. Each sector then runs its own prorrata (general or especial). This module computes the predicate; sector identification itself is a profile/ registry concern carried in ProrrataSector.

The substrate distinguishes provisional and definitiva prorrata percentages explicitly (LIVA arts. 105 and 109). The provisional percentage applies during quarterly/monthly Modelo 303 filings and is typically the prior year’s definitiva. The definitiva percentage is computed at year-end with the year’s actual operations and produces a regularisation entry in Q4 303 (casilla 44) and Modelo 390.

Live submission is not the concern of this module. Current filing surfaces either use registry-defined formula/manual prorrata casillas or carry validated prorrata references on IVA ledger observations.

class ProrrataRegime(*values)[source]

Bases: StrEnum

LIVA-defined prorrata regime kinds.

  • GENERAL — single deduction percentage applied to every input IVA amount (art. 102 LIVA).

  • ESPECIAL — per-input classification: 100% deductible if used exclusively in deductible activities, 0% if used exclusively in non-deductible, the general percentage if used in both (common-bien under art. 103 LIVA).

GENERAL
ESPECIAL
class ProrrataKind(*values)[source]

Bases: StrEnum

Lifecycle stage of the prorrata percentage.

  • PROVISIONAL — applied during the tax year on Modelo 303 quarters or months, normally derived from the prior year’s definitiva.

  • DEFINITIVA — computed at year-end with the year’s actual operations; drives the regularisation entry on Q4 303 and Modelo 390.

PROVISIONAL
DEFINITIVA
class InputClassification(*values)[source]

Bases: StrEnum

How a specific input IVA amount maps to deductible activity under prorrata especial.

Governed by art. 103 LIVA.

  • EXCLUSIVELY_DEDUCTIBLE — used only in operations that grant the right to deduct; 100% deductible.

  • EXCLUSIVELY_NON_DEDUCTIBLE — used only in operations that do NOT grant the right; 0% deductible.

  • COMMON — used in both kinds of operations; the general prorrata percentage applies.

EXCLUSIVELY_DEDUCTIBLE
EXCLUSIVELY_NON_DEDUCTIBLE
COMMON
class ProrrataInputs(**data)[source]

Bases: _ProrrataStrictFrozen

Aggregated operation amounts for one prorrata computation window.

The aggregator producing these inputs is responsible for applying the art. 104 LIVA exclusions (subvenciones not linked to operations, autoconsumos, sale of bienes de inversión, non-recurring financial and immovable operations meeting the art. 104.Tres tests). This model therefore treats both fields as already-filtered annual totals expressed in euros.

Parameters:
  • operaciones_con_derecho_deduccion (Decimal)

  • operaciones_sin_derecho_deduccion (Decimal)

operaciones_con_derecho_deduccion: Decimal
operaciones_sin_derecho_deduccion: Decimal
class ProrrataSector(**data)[source]

Bases: _ProrrataStrictFrozen

A single sector under the sectoral-separation regime (art. 9.1.c LIVA).

A taxpayer with two or more economic sectors whose general prorratas differ by more than fifty percentage points must compute the prorrata independently per sector. Each sector carries its own filtered totals and may run under GENERAL or ESPECIAL regime.

Parameters:
  • sector_id (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=64, pattern=^[-._a-zA-Z0-9]+$, ascii_only=None)])

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

  • inputs (ProrrataInputs)

  • regime (ProrrataRegime)

sector_id: SectorId
name: Annotated[str, StringConstraints(strip_whitespace=True, min_length=1, max_length=200)]
inputs: ProrrataInputs
regime: ProrrataRegime
class ProrrataResult(**data)[source]

Bases: _ProrrataStrictFrozen

Outcome of a single prorrata computation.

The percentage is stored as a Decimal whole-integer value between 0 and 100 inclusive, already rounded up per LIVA art. 102.Dos. Sectoral results carry their sector_id; whole-entity results carry None.

Parameters:
  • regime (ProrrataRegime)

  • kind (ProrrataKind)

  • percentage (Decimal)

  • inputs (ProrrataInputs)

  • sector_id (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=64, pattern=^[-._a-zA-Z0-9]+$, ascii_only=None)] | None)

  • year (Annotated[int, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=2000), Le(le=2100)])])

  • period (Annotated[str | None, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=None, pattern=^(Q[1-4]|M(0[1-9]|1[0-2])|annual)$, ascii_only=None)])

regime: ProrrataRegime
kind: ProrrataKind
percentage: Decimal
inputs: ProrrataInputs
sector_id: SectorId | None
year: Annotated[int, Field(ge=2000, le=2100)]
period: Annotated[str | None, StringConstraints(strip_whitespace=True, pattern='^(Q[1-4]|M(0[1-9]|1[0-2])|annual)$')]
class ProrrataReference(**data)[source]

Bases: _ProrrataStrictFrozen

Stable identifier for a persisted IVA prorrata percentage.

References use the canonical shape prorrata:{year}:{kind}:{regime}, with an optional sector suffix :{sector_id} for sectoral-separation cases. The reference is a pointer to a legal IVA prorrata substrate value; it is not a proportional-use ratio and it is not derived from usage-ratio data.

Parameters:
  • reference_id (str)

  • year (Annotated[int, FieldInfo(annotation=NoneType, required=True, metadata=[Ge(ge=2000), Le(le=2100)])])

  • kind (ProrrataKind)

  • regime (ProrrataRegime)

  • sector_id (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=64, pattern=^[-._a-zA-Z0-9]+$, ascii_only=None)] | None)

reference_id: str
year: Annotated[int, Field(ge=2000, le=2100)]
kind: ProrrataKind
regime: ProrrataRegime
sector_id: SectorId | None
class ProrrataInputDeduction(**data)[source]

Bases: _ProrrataStrictFrozen

One per-input deductibility decision under prorrata especial.

Used to enumerate every input IVA amount classified under art. 103 LIVA and the resulting deductible portion. The deductible_amount field equals input_iva_amount * deductible_percentage / 100, rounded to two decimals using banker’s rounding (the default Decimal quantizer); the caller’s modelo binding provider is responsible for further rounding if the registry casilla requires whole euros.

Parameters:
classification: InputClassification
input_iva_amount: Decimal
deductible_percentage: Decimal
deductible_amount: Decimal
validate_prorrata_reference(reference_id)[source]

Parse and validate a legal IVA prorrata reference id and return a ProrrataReference.

The accepted id shape is prorrata:{year}:{kind}:{regime}, plus an optional :{sector_id} suffix. Values from the expense proportionality/usage-ratio substrate intentionally fail this parser; callers must keep both concepts separate.

Return type:

ProrrataReference

Parameters:

reference_id (str)

compute_prorrata_general(inputs, *, year, kind, period=None, sector_id=None)[source]

Compute the general prorrata percentage for one window.

Implements LIVA art. 102.Uno + art. 102.Dos. The caller supplies the filtered annual totals (or annualised totals if the year is a fractional first/last year) and the lifecycle kind.

Raises ProrrataInputError when the year is out of the supported range or when kind/period combination is inconsistent.

Return type:

ProrrataResult

Returns:

A ProrrataResult with the computed percentage and inputs.

Parameters:
  • inputs (ProrrataInputs)

  • year (int)

  • kind (ProrrataKind)

  • period (str | None)

  • sector_id (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=64, pattern=^[-._a-zA-Z0-9]+$, ascii_only=None)] | None)

deductible_percentage_for(classification, general_percentage)[source]

Map an input classification to its deductible percentage under LIVA arts. 103/106.

The single canonical mapping of the art. 106.Uno reglas: EXCLUSIVELY_DEDUCTIBLE → 100 (regla 1.ª, deducted in full), EXCLUSIVELY_NON_DEDUCTIBLE → 0 (regla 2.ª, no deduction), COMMONgeneral_percentage (regla 3.ª, deducted at the general prorrata percentage). Consumed both by classify_input_deduction() (per-input deduction) and by the ledger IVA aggregation’s regime-aware especial apportionment, so the reglas live in exactly one place.

Return type:

Decimal

Parameters:
classify_input_deduction(classification, input_iva_amount, general_percentage)[source]

Compute one deductible amount and return a ProrrataInputDeduction.

Implements prorrata especial (art. 103). The general_percentage is the value produced by compute_prorrata_general() for the same window; it only enters the calculation when the classification is COMMON.

Return type:

ProrrataInputDeduction

Parameters:
is_especial_mandatory(deduction_under_general, deduction_under_especial)[source]

Return True when LIVA art. 103.Dos forces the prorrata especial regime.

The rule: the prorrata especial regime is mandatory whenever the deduction computed under the general regime would exceed the deduction computed under the especial regime by more than ten percent, i.e. deduction_general > deduction_especial * 1.10. When the especial deduction is zero this function returns True if the general deduction is positive (the general regime would over- deduct without bound).

Return type:

bool

Parameters:
  • deduction_under_general (Decimal)

  • deduction_under_especial (Decimal)

class RegularizacionProrrataDireccion(*values)[source]

Bases: StrEnum

Direction of the annual prorrata-general regularisation (LIVA art. 105.Cuatro).

  • DEDUCCION — the year’s definitive percentage exceeds the provisional one applied across the quarters, so a deducción complementaria is due: the taxpayer may deduct more input IVA and the Modelo 303 casilla-44 value is positive (it increases the total deductible cuota).

  • INGRESO — the definitive percentage is lower than the provisional one, so the provisional deductions were excessive and an ingreso is due: the casilla-44 value is negative (it reduces the total deductible cuota).

  • NINGUNA — the two percentages coincide; no regularisation is practised.

DEDUCCION
INGRESO
NINGUNA
class RegularizacionProrrataResult(**data)[source]

Bases: _ProrrataStrictFrozen

Outcome of the annual prorrata-general regularisation (LIVA art. 105.Cuatro).

Variables:
  • cuotas_soportadas_deducibles – The year’s total deductible input IVA the percentages apply to (art. 105.Seis: the sum of the year’s cuotas soportadas, excluding the arts. 95/96 non-deductibles).

  • prorrata_provisional_pct – The provisional percentage applied during the year (art. 105.Uno: normally the prior year’s definitive percentage).

  • prorrata_definitiva_pct – The definitive percentage computed at year-end from the year’s actual operations (art. 104).

  • deduccion_provisionalcuotas × provisional% / 100 — the deduction already practised across the year’s provisional liquidations.

  • deduccion_definitivacuotas × definitiva% / 100 — the deduction that definitively applies.

  • importededuccion_definitiva deduccion_provisional, rounded to cents. The signed value proposed for Modelo 303 casilla 44 / the Modelo 390 annual regularisation field. Positive = additional deduction; negative = repayment.

  • direccionRegularizacionProrrataDireccion describing the sign.

Parameters:
cuotas_soportadas_deducibles: Decimal
prorrata_provisional_pct: Decimal
prorrata_definitiva_pct: Decimal
deduccion_provisional: Decimal
deduccion_definitiva: Decimal
importe: Decimal
direccion: RegularizacionProrrataDireccion
compute_prorrata_definitiva_anual(inputs, *, year, sector_id=None)[source]

Compute the year-end DEFINITIVA general prorrata percentage (LIVA arts. 104-105).

Thin, named wrapper over compute_prorrata_general() fixing kind = DEFINITIVA and period = "annual": the caller supplies the full-year operation volumes (con-derecho / sin-derecho) with the art-104 exclusions already applied, and receives the definitive percentage that art. 105.Cuatro regularises the provisional deductions against. This is the definitive-percentage source the capital-goods regularización (LIVA arts. 107-110) and the annual prorrata regularización both consume; deriving it from a single quarter’s volume is a correctness defect (a single period computes neither the provisional nor the annual-regularised percentage), so the definitive percentage MUST come from the full-year rollup.

Return type:

ProrrataResult

Returns:

The definitive ProrrataResult for the year.

Parameters:
  • inputs (ProrrataInputs)

  • year (int)

  • sector_id (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=64, pattern=^[-._a-zA-Z0-9]+$, ascii_only=None)] | None)

compute_regularizacion_prorrata_anual(*, cuotas_soportadas_deducibles, prorrata_provisional_pct, prorrata_definitiva_pct)[source]

Compute the annual prorrata-general regularisation cuota (LIVA art. 105.Cuatro).

Implements the art-105 procedure. A taxpayer under prorrata general applies a PROVISIONAL deduction percentage across the year’s liquidations (art. 105.Uno: “el porcentaje de deducción provisionalmente aplicable cada año natural será el fijado como definitivo para el año precedente”); then, in the last liquidation of the year, computes the DEFINITIVA percentage from the year’s actual operations (art. 104) and “practicará la consiguiente regularización de las deducciones provisionales” (art. 105.Cuatro). The regularisation cuota is the difference between the deduction that definitively applies and the deduction already practised provisionally:

deduccion_definitiva  = cuotas × definitiva% / 100
deduccion_provisional = cuotas × provisional% / 100
importe               = deduccion_definitiva − deduccion_provisional

Unlike the capital-goods regularisation (arts. 107-110), the prorrata-general regularisation carries no >10-point gate: art. 105.Cuatro practises it in every year the two percentages differ. Both percentages are supplied as inputs; deriving the definitive percentage from the annual volumes is compute_prorrata_definitiva_anual(), and carrying the prior-year definitive as this year’s provisional (art. 105.Uno) is the profile-scoped carry the application layer owns.

Parameters:
  • cuotas_soportadas_deducibles (Decimal) – The year’s total deductible input IVA (art. 105.Seis), non-negative.

  • prorrata_provisional_pct (Decimal) – Provisional deduction percentage applied during the year (0-100).

  • prorrata_definitiva_pct (Decimal) – Definitive deduction percentage for the year (0-100).

Return type:

RegularizacionProrrataResult

Returns:

A RegularizacionProrrataResult carrying the signed casilla-44 importe and its RegularizacionProrrataDireccion.

Raises:

ProrrataInputError – on a negative cuota or an out-of-range percentage.

requires_sectoral_separation(sectors)[source]

Return True when LIVA art. 9.1.c mandates sectoral separation.

The rule: a taxpayer with two or more economic sectors must compute prorrata independently per sector whenever the difference between the highest and lowest general prorrata across sectors exceeds fifty percentage points.

Sectors are identified by stable sector_id; the caller is responsible for assigning activity codes (e.g., CNAE / IAE-epígrafe) to sectors before invoking this function. A sectors list with fewer than two members returns False because the threshold cannot apply.

Return type:

bool

Parameters:

sectors (Sequence[ProrrataSector])

compute_sectoral_prorrata(sectors, *, year, kind, period=None)[source]

Compute the general prorrata for each sector.

Returns one ProrrataResult per input sector, in the same order. This function does NOT enforce whether sectoral separation applies — that decision lives in requires_sectoral_separation(); this calculator runs once the caller has decided separation is required.

Return type:

tuple[ProrrataResult, ...]

Parameters:
sum_deductible_amounts(deductions)[source]

Sum the deductible_amount field across a collection of inputs.

Callers use this to roll up per-input deductions after running classify_input_deduction() for each purchase invoice evidence row. Modelo casilla routing remains registry-owned.

Return type:

Decimal

Parameters:

deductions (Iterable[ProrrataInputDeduction])