cadrumo.application.aggregation._modelo_bindings_invoice_iva module¶
Invoice-to-ledger IVA screening for modelo binding resolution.
The calculation-facing ledger resolver remains in ._modelo_bindings. This sibling owns the supporting invoice evidence comparison, category and recargo diagnostics, and candidate screening required by that resolver.
- line_contributes_to_the_iva_screen(base_amount, iva_amount)[source]¶
Return whether one invoice line has anything the IVA screen can declare.
A line contributes when it carries a base OR a cuota. Screening on the cuota alone reads as a sensible “nothing to declare” filter and is not one: an exempt operation (LIVA art. 20), an intra-community supply (art. 25) and an issued-side reverse charge all carry a real base with a cuota that is zero BY LAW. The component table says so outright – both categories are
base=required, cuota=zero_by_law– and Modelo 303 declares those bases in its own base-only casillas.So a cuota-only filter dropped exactly the lines whose base was the only thing they were ever going to contribute, and the declaration understated the exempt base by the whole amount with nothing reporting it.
A line carrying neither is the only shape that genuinely contributes nothing, and is the only one this predicate declines.
This predicate alone does not make an exempt base reach Modelo 303, and was mistakenly reported as doing so. The loop classifies from the RATE SLOT, so an exempt line becomes
domestic_exempt/exemptwhile casilla 59 selectsintra_community_supply/zeroand casilla 60 the two export categories – a miss on both axes. No M303 binding selectsdomestic_exemptordomestic_zero, so such an observation routes nowhere rather than into a wrong casilla; the effect is inert, not harmful.Keeping the line is a PRECONDITION of the real fix, not the fix. The real fix is to construct the observation from the invoice’s own
iva_categorythe way the bank-transaction path already does (_iva_ledger.py: explicit category first, rate-derived domestic category only as a fallback, with the intracom/export counterparty gate). Two feeds populating one binding source with divergent logic is whatone-aggregation-path-pull-equals-calculateexists to prevent.
- category_counterparty_mismatch_diagnostics(invoices, *, resolver_id)[source]¶
Return one advisory per invoice withheld for a category the counterparty contradicts.
Withholding the volume is correct: an intra-community supply to a third country is not an intra-community supply whatever it claims, and routing it on the category alone would declare volume the taxpayer never supplied that way. What was missing is the operator being told, so a real operation left a declaration with nothing on any surface saying so.
The remedy names both fields, because either could be the wrong one – the category may be mis-tagged, or the counterparty country may be. The record does not know which, and guessing would point the operator at the wrong fix.
- reverse_charge_underivable_diagnostics(invoices, *, resolver_id)[source]¶
Return one advisory per received reverse charge whose cuota cannot be derived.
The operation IS declarable and the operator is liable for the cuota; what is missing is the rate to compute it against. Naming the invoice and the missing fact is what turns a silently short return into one the operator can correct, and it makes the population countable – which is what a decision about whether an invoice line may carry a rated slot with a zero cuota needs in order to be made on evidence.
- missing_invoice_deduction_authority_diagnostics(invoices, *, resolver_id)[source]¶
Report received invoice evidence that reached no IVA input row.
An invoice has an amount and a direction, but not the statutory deduction fact family nor the immutable evidence provenance that distinguishes a domestic current expense from an investment, import, acquisition, or rectification. Treating every received invoice as domestic-current would invent that authority, so the invoice is withheld instead.
Non-blocking by the time it reaches here: the enclosing guard has already established that the transaction ledger carries this cuota, so the filing’s totals are correct and only the invoice-to-transaction link is absent. Where the ledger does NOT carry it the guard refuses outright and this diagnostic is never reached.
- recargo_rate_mismatch_diagnostics(divergences, *, resolver_id)[source]¶
Return one advisory per invoice whose recargo departs from the published rate.
Advisory, never a refusal, and the filed figure is unchanged whether or not this fires. A legitimate invoice can carry a figure the table does not predict, so refusing here would block a correct filing on a correct invoice.
The message names both figures and the provision. Without the provision the advisory reads as the application second-guessing the supplier, and an operator who cannot see what authority is being cited will learn to dismiss it – which costs more than never having emitted it.
- Return type:
- Parameters:
- class ScreenedInvoiceIva(observations=(), invoice_ids=(), compared=(), category_counterparty_mismatches=(), reverse_charge_underivable=(), deduction_authority_missing=(), recargo_rate_divergences=(), storage_degraded=False)[source]¶
Bases:
objectWhat the invoice IVA screen found, named rather than positional.
Several fields are
tuple[Invoice, ...]and one more is a tuple of ids, so as a positional return they would be mutually substitutable and a type checker could not tell a mis-ordering from correct code. That is not hypothetical: the tuple was widened repeatedly as findings landed, the annotation fell out of step with the returns on the way, and every widening broke unpack sites in unrelated test modules.- Variables:
observations – the IVA observations the screen built.
invoice_ids – source invoice ids behind those observations.
compared – invoices whose IVA was compared against the ledger, so the caller can disclose how their period placement was arrived at.
category_counterparty_mismatches – invoices withheld because the declared category and the counterparty country contradict each other.
reverse_charge_underivable – invoices declaring a reverse charge whose line carries no rate slot, so no cuota can be derived without inventing one.
deduction_authority_missing – received invoices whose lines contribute IVA evidence but which are linked to no frozen transaction-ledger observation carrying the exact deduction family and immutable evidence provenance an input row requires, or whose linked observations disagree about it.
recargo_rate_divergences – invoices whose recorded recargo departs from the rate art. 161 publishes for that slot. Unlike the two above, these are NOT withheld – the figure is declared exactly as recorded and the advisory is a cross-check beside it.
- Parameters:
observations (tuple[IvaLedgerObservation, ...])
recargo_rate_divergences (tuple[_RecargoRateDivergence, ...])
storage_degraded (bool)
-
observations:
tuple[IvaLedgerObservation,...]¶
- class InvoiceIvaSilenceReport(compared=(), category_counterparty_mismatches=(), reverse_charge_underivable=(), deduction_authority_missing=(), recargo_rate_divergences=(), storage_degraded=False)[source]¶
Bases:
objectThe advisory surfaces the silence screen hands back to the resolver.
Same reasoning as
ScreenedInvoiceIva: all three fields aretuple[Invoice, ...], so positionally they were interchangeable. The annotation on the previous tuple form had already drifted to two slots while the code returned three, which is what an unchecked positional widening looks like just before it goes wrong.- Parameters:
-
deduction_authority_missing:
tuple[Invoice,...]¶ Received invoices withheld for want of a linked ledger deduction authority, whose cuota the transaction ledger nonetheless already carries. Not a refusal – the filing’s totals are right – but the operator still needs telling, or the unlinked invoice looks reconciled when it is not.
-
recargo_rate_divergences:
tuple[_RecargoRateDivergence,...]¶ Carried on every return path, including the two early ones. A divergence is a fact about the recorded figure, not about whether the screen went on to build an observation, so dropping it when the screen returns early would silence the advisory exactly when the invoice is least examined.
- screened_invoice_iva_observations(*, context, period, ledger_observations=(), ports, operation=None)[source]¶
- Return type:
- Parameters:
context (CalculationSourceContext)
period (Period)
ledger_observations (Sequence[IvaLedgerObservation])
ports (InvoiceCatalogueReadPorts)
operation (PinnedAuthorityOperation | None)
- out_of_window_summary_diagnostics(summary, *, source_kind, resolver_id)[source]¶
- Return type:
- Parameters:
summary (OutOfWindowTransactionSummary | None)
source_kind (str)
resolver_id (str)