cadrumo.domain.iva.prorrata module

Legal IVA prorrata substrate (LIVA arts. 102-106).

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 arithmetic substrate produces immutable result objects; its regime vocabulary is resolved through the typed facts projection rather than defined as a Python catalogue.

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

  • Art. 102.Uno (“Regla de prorrata”) triggers the rule when a taxpayer performs, conjuntamente, operations that grant the right to deduction (taxable supplies, deemed-domestic intracomunitarias, intra-EU services, etc.) alongside operations of an analogous nature that do NOT grant the right (LIVA arts. 20 and 21 exempt supplies and similar). Art. 102.Dos is a separate rule about autoconsumos and carries nothing this module implements.

  • Art. 103.Uno (“Clases de prorrata y criterios de aplicación”) splits the rule into two modalities: prorrata general (arts. 104-105) is the default, and prorrata especial (art. 106) applies on election or, per art. 103.Dos.2.º, whenever the year’s deductible cuotas under the general regime exceed those under the especial regime by the margin in force for that filing year.

  • Art. 104.Dos (“La prorrata general”) — 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 (regla 1.ª, the numerator). total_operaciones is the sum of operaciones_con_derecho plus operaciones_sin_derecho (LIVA-art.-20 exempt supplies and similar; regla 2.ª, the denominator). Art. 104.Tres excludes subvenciones not linked to operations, autoconsumos, and the disposal of bienes de inversión from both terms; the exclusion is the caller’s responsibility; this module only accepts already-filtered operation totals. Art. 104.Uno confines the percentage limitation to the cases where the regla de prorrata applies at all, so a taxpayer with no exempt-without-right operations deducts in full (arts. 92 and 94).

  • Art. 104.Dos, closing paragraph — “La prorrata de deducción resultante de la aplicación de los criterios anteriores se redondeará en la unidad superior”: the percentage is rounded up to the next whole integer (ROUND_CEILING against Decimal("1")). This is the only rounding clause in the whole of Ley 37/1992.

  • Art. 103.Dos.2.º — prorrata especial is mandatory whenever the year’s total deductible cuotas under the general regime exceed those under the especial regime by the statutory margin. The provision is NOT invariant across the filing years this module serves: the original redaction (in force to 31-12-2014) read “exceda en un 20 por 100 del que resultaría”, while Ley 28/2014 art. 1.26 (BOE-A-2014-12329, in force from 01-01-2015) replaced it with “exceda en un 10 por ciento o más del que resultaría” — lowering the margin and making it inclusive. See is_especial_mandatory(), which selects on the filing year, and especial_mandatory_rule(), which reports the margin that selection applied.

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[source]

Bases: str

Opaque registry-projected LIVA prorrata regime token.

The regime vocabulary and its legal semantics are selected from the dated renta-iva-deduction-ratio-policy fact. This domain type keeps only the token shape; callers must use the typed registry projection when accepting a regime from a reference or producing a default result.

property value: str

Return the opaque token for canonical reference serialization.

class ProrrataKind(value, *, _registry_validated=False)[source]

Bases: _ProrrataRegistryToken

Opaque dated token for a provisional or definitive prorrata result.

Parameters:
  • value (str)

  • _registry_validated (bool)

Return type:

Self

class InputClassification(value, *, _registry_validated=False)[source]

Bases: _ProrrataRegistryToken

Opaque dated token for one LIVA art. 106 input-use classification.

Parameters:
  • value (str)

  • _registry_validated (bool)

Return type:

Self

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:

data (Any)

operaciones_con_derecho_deduccion: Decimal
operaciones_sin_derecho_deduccion: Decimal
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. 104.Dos. Sectoral results carry their sector_id; whole-entity results carry None.

Parameters:

data (Any)

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:

data (Any)

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

Bases: _ProrrataStrictFrozen

The LIVA art. 103.Dos.2.º mandatory-especial rule in force for one filing year.

Art. 103.Dos.2.º is not invariant across the filing years this substrate serves, so the rule is resolved per year by especial_mandatory_rule() rather than being a single constant. Carrying the comparison shape alongside the figure lets an operator-facing message state the margin AND whether reaching it is enough, without re-deriving either.

Variables:
  • year – The filing year the deductions belong to.

  • multiple – The factor the especial-regime deduction is scaled by to obtain the threshold (1.10 from 2015, 1.20 before).

  • margin_percentage – The same threshold expressed as the percentage the provision names (10 from 2015, 20 before).

  • inclusive – True when the provision reads “o más”, so a general deduction landing exactly on the threshold already makes the especial regime mandatory.

Parameters:

data (Any)

year: Annotated[int, Field(ge=2000, le=2100)]
multiple: Decimal
margin_percentage: Decimal
inclusive: bool
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. 104.Uno + art. 104.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 art. 106.Uno.

The selected 0116 input-classification definition supplies either a fixed deductible percentage or the general percentage source. Both the per-input deduction and the ledger’s especial apportionment therefore consume one dated registry projection.

Return type:

Decimal

Parameters:
especial_mandatory_rule(year, *, parameters)[source]

Return the LIVA art. 103.Dos.2 rule in force for filing year.

Both halves of the rule are registry data and neither is decided here. The margin and its comparison direction arrive already resolved from the revision the application boundary selected, because art. 103.Dos.2 has had two redactions differing on BOTH – the original required an excess “en un 20 por 100” with no “o más” and so exclusive, and Ley 28/2014 art. 1.26 replaced it from 01-01-2015 with “en un 10 por ciento o más”, lowering the margin and making it inclusive.

A pre-2015 ejercicio never reaches this function: the resolver refuses it by name, because the repealed redaction has no citable authority in this tree and no revision covers such a filing year.

Parameters:
Raises:

ProrrataInputError – when the year is outside the supported range.

Return type:

EspecialMandatoryRule

is_especial_mandatory(deduction_under_general, deduction_under_especial, *, year, parameters)[source]

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

The provision in force from filing year 2015 (Ley 28/2014 art. 1.26, BOE-A-2014-12329): the especial regime applies “cuando el montante total de las cuotas deducibles en un año natural por aplicación de la regla de prorrata general exceda en un 10 por ciento o más del que resultaría por aplicación de la regla de prorrata especial”. “O más” reaches the margin, so a general deduction landing exactly on it switches the regime: the comparison is >=, not >.

The original redaction (in force to filing year 2014) set the margin at twenty percent and carried no “o más”, so for those years the margin must be passed rather than merely reached. year selects between the two through especial_mandatory_rule(); it is the filing year the deductions belong to, not the year the calculation is run.

When the especial deduction is zero this function returns True if the general deduction is positive: a positive amount exceeds zero without bound, so both redactions agree the regime is mandatory.

Raises:
  • ProrrataInputError – on a negative deduction amount or a year

  • outside the supported range. –

Return type:

bool

Parameters:
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_provisional – cuotas × provisional% / 100 — the deduction already practised across the year’s provisional liquidations.

  • deduccion_definitiva – cuotas × definitiva% / 100 — the deduction that definitively applies.

  • importe – deduccion_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.

  • direccion – RegularizacionProrrataDireccion describing the sign.

Parameters:

data (Any)

cuotas_soportadas_deducibles: Decimal
prorrata_provisional_pct: Percentage
prorrata_definitiva_pct: Percentage
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.