cadrumo.domain.iva.flow module

IVA flow direction enum — repercutido / soportado / INVERSION_SUJETO_PASIVO.

Codifies the IVA collectability axis the ledger and modelo registries need alongside the operation-kind axis (IvaCategory) and the rate axis (IvaRateKind). Every IVA-bearing ledger line classifies along all three axes:

  • IvaCategory — operation kind (domestic, intracomunitaria, recargo, OSS, etc.).

  • IvaRateKind — rate tier (general / reduced / super-reduced / zero / exempt).

  • IvaFlowDirection — flow direction (output / input / self-assessed reverse charge).

Together the triple resolves to a single ledger-bookable Cuota.

The three flow directions are anchored to LIVA articles:

  • IvaFlowDirection.REPERCUTIDO — LIVA art. 88 (repercusión del impuesto). The sujeto pasivo charges IVA to its customer; the customer is the obligado a soportar.

  • IvaFlowDirection.SOPORTADO — LIVA art. 92 (cuotas tributarias deducibles). The sujeto pasivo bears IVA via direct repercusión from suppliers and may deduct that IVA from its own output IVA.

  • IvaFlowDirection.INVERSION_SUJETO_PASIVO — LIVA art. 84.Uno.2.º (inversión del sujeto pasivo). The recipient of certain operations (intra-community acquisitions, art. 84.Uno.2.º.f construction reverse charge, etc.) is the sujeto pasivo and self-assesses both an IVA repercutido entry (output) and a matching IVA soportado entry (input) on the same operation.

The derive_flow_for_classification() helper computes the flow direction from the substrate’s IvaCategory plus the invoice InvoiceKind axis so consumers do not have to encode the mapping by hand.

Settlement-side cornerstones — devengada vs deducible

The IVA settlement model rests on two cornerstone concepts:

  • IVA devengada (output IVA, “cuota tributaria devengada”) — the amount the sujeto pasivo OWES to the Treasury as the IVA chargeable on its sales. LIVA arts. 75-77 establish when IVA accrues (devengo); LIVA art. 88 governs how the sujeto pasivo charges it to the customer (repercusión).

  • IVA deducible (input IVA, “cuotas tributarias deducibles”) — the amount the sujeto pasivo may DEDUCT from its devengada because it bore IVA on inputs. LIVA art. 92 establishes the right to deduction; arts. 93-104 establish the conditions, scope, and limits.

The cuota neta a ingresar (or a devolver) at the period level is devengada - deducible; this is the canonical Modelo 303 “resultado régimen general” line.

Every IvaFlowDirection member contributes to one or both cornerstones:

Flow direction

Devengada

Deducible

REPERCUTIDO

✓

─

SOPORTADO

─

✓

INVERSION_SUJETO_PASIVO

✓

✓

INVERSION_SUJETO_PASIVO is the only flow that contributes to BOTH sides on the SAME operation: the recipient self-assesses an output entry (devengada) and a matching input entry (deducible) for the cuota that would have been repercutida by a non-existent or non-EU supplier. The two entries cancel arithmetically inside Modelo 303 (devengada - deducible = 0 for that line) but both must be booked to satisfy the LIVA art. 84.Uno.2 inversión-del-sujeto-pasivo mechanism.

The IvaSettlementSide enum + settlement_sides_for_flow() helper let the ledger and modelo registries categorize transactions without re-deriving the mapping. The closed-set helpers is_devengada_flow() and is_deducible_flow() are the canonical predicates for “does this flow contribute to the cuota devengada / cuota deducible total?”.

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

Bases: StrictRegistryToken

Opaque IVA flow token projected from fact 0083.

Flow membership, legal descriptions, and settlement-side semantics belong to the dated facts registry. This wire type deliberately carries no closed Python member list; callers must obtain tokens through the typed registry projection.

Parameters:
  • value (str)

  • _registry_validated (bool)

Return type:

Self

flow_direction_for_invoice_kind(invoice_kind)[source]

Return the IVA flow direction an invoice’s issuance side settles as.

This is the base rule the tax itself states: an invoice the autónomo ISSUED charges output IVA onward (IvaFlowDirection.REPERCUTIDO); one it RECEIVED bears input IVA (IvaFlowDirection.SOPORTADO). derive_flow_for_classification() and classify_invoice_line_for_iva() both call this for their standard-case resolution and OVERRIDE it for the special regimes (reverse charge, intra-community) that route the same members differently.

Return type:

IvaFlowDirection

Parameters:

invoice_kind (InvoiceKind)

derive_flow_for_classification(*, category, invoice_direction)[source]

Return the IVA flow direction for a substrate-classified line.

The mapping is:

  • Recipient-only reverse-charge categories (the intra-community acquisitions in _recipient_only_reverse_charge_categories()) resolve to IvaFlowDirection.INVERSION_SUJETO_PASIVO irrespective of the invoice direction, because their supply counterpart is not located in Spain and so raises no Spanish cuota to self-assess.

  • Domestic reverse charge resolves BY DIRECTION, because both sides of the operation are Spanish and the form asks for them separately: InvoiceKind.RECEIVED is the recipient self-assessing, so IvaFlowDirection.INVERSION_SUJETO_PASIVO; InvoiceKind.ISSUED is the supplier making a sujeta y no exenta supply that repercutes nothing, so IvaFlowDirection.OPERACION_CON_INVERSION. Collapsing the two once put the supplier’s turnover on the recipient’s line.

  • Otherwise: InvoiceKind.ISSUED resolves to IvaFlowDirection.REPERCUTIDO (the autónomo charged output IVA on a sale) and InvoiceKind.RECEIVED resolves to IvaFlowDirection.SOPORTADO (the autónomo bore input IVA on a purchase).

Parameters:
  • category (IvaCategory) – The IvaCategory resolved by the substrate classifier.

  • invoice_direction (InvoiceKind) – Whether the invoice was issued or received by the autónomo.

Return type:

IvaFlowDirection

Returns:

The IvaFlowDirection that matches the classification.

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

Bases: StrictRegistryToken

Opaque IVA settlement-side token projected from fact 0083.

Parameters:
  • value (str)

  • _registry_validated (bool)

Return type:

Self

settlement_sides_for_flow(flow)[source]

Return the settlement side(s) flow contributes to.

This is the CUOTA axis: which side of the settlement a line’s cuota is reckoned on. It is not the axis of which half of the return a line’s amounts appear in, and the two come apart on every zero-cuota operation. An exempt sale is an output operation whose base belongs on the devengada half of the return while settling no cuota at all, so reading a {DEVENGADA} here as “this line owes output IVA” is wrong for it.

That distinction is easy to lose, because the Axis-A component table’s cuota_settlement column and this function look like two statements of one fact and are not. Compare the two directly and roughly half the arising pairs appear to disagree; every one of those apparent conflicts is a zero-cuota operation where the table says “no cuota arises” and this function says “output side”, both of which are true. The check worth making is per consumer, not per pair.

Both production consumers screen on a positive cuota before asking, so the zero-cuota rows never reach the question. A future consumer that does not screen first is the one that would be misled, and it is the reason this paragraph exists rather than a coherence gate over two axes that do not answer the same question.

Parameters:

flow (IvaFlowDirection) – The IvaFlowDirection to classify.

Returns:

{DEVENGADA} for IvaFlowDirection.REPERCUTIDO, {DEDUCIBLE} for IvaFlowDirection.SOPORTADO, {DEVENGADA, DEDUCIBLE} for IvaFlowDirection.INVERSION_SUJETO_PASIVO, and the empty set for IvaFlowDirection.OPERACION_CON_INVERSION, whose supplier repercutes no cuota and bears none.

Return type:

Frozenset of IvaSettlementSide values

is_devengada_flow(flow)[source]

Return True iff flow contributes to cuota devengada.

Canonical predicate for the ledger / modelo registries when aggregating cuota devengada totals — equivalent to flow in {REPERCUTIDO, INVERSION_SUJETO_PASIVO} but anchored to the substrate’s settlement-side codification so downstream consumers don’t have to re-enumerate the mapping.

Return type:

bool

Parameters:

flow (IvaFlowDirection)

is_deducible_flow(flow)[source]

Return True iff flow contributes to cuota deducible.

Canonical predicate for the ledger / modelo registries when aggregating cuota deducible totals — equivalent to flow in {SOPORTADO, INVERSION_SUJETO_PASIVO} but anchored to the substrate’s settlement-side codification.

Return type:

bool

Parameters:

flow (IvaFlowDirection)

is_inversion_sujeto_pasivo_flow(flow)[source]

Return whether flow is the recipient reverse-charge direction.

Return type:

bool

Parameters:

flow (IvaFlowDirection)

is_standard_issued_or_received_flow(flow)[source]

Return whether flow is one of the ordinary invoice-side flows.

Return type:

bool

Parameters:

flow (IvaFlowDirection)

issued_flow_direction()[source]

Return the registry-declared flow for an issued invoice.

Return type:

IvaFlowDirection

received_flow_direction()[source]

Return the registry-declared flow for a received invoice.

Return type:

IvaFlowDirection