cadrumo.application.aggregation._renta_income_evidence module

Sales-invoice evidence and retención inference for Renta income rows.

This sibling owns the document-facing facts that enrich an already eligible income transaction. The ledger projection remains responsible for deciding whether a row belongs to a filing period; this module decides whether a linked issued invoice may supply its fiscal figures and, where it may not, whether a bounded retención can be inferred from the transaction itself.

class SalesInvoiceEvidenceRefusal(*values)[source]

Bases: StrEnum

Why a linked sales invoice was not trusted for a row’s fiscal figures.

NOT an exclusion. Every member here leaves the row IN the aggregation, contributing its bank cash under CASH_FALLBACK grounding, because the taxpayer was paid and that income is declarable whatever state its paperwork is in. What the refusal withholds is the invoice’s FIGURES, not the row.

This is the income side of an asymmetry worth stating. An unevidenced gasto must NOT be claimed, so the expense pipeline excludes it. An unevidenced ingreso must STILL be declared, so this one degrades it. Same checks, opposite consequence; only the checks transfer.

Spelled per failure rather than as one generic mismatch: which check rejected the link is what an operator needs to repair it, and one reason would make five different repairs look like one problem.

BUCKET_MISMATCH
UNSUPPORTED_KIND
PARTIAL_OR_MULTI_TRANSACTION
AMOUNT_MISMATCH
UNGROUNDED_DECOMPOSITION
sales_invoice_evidence_payload(*, invoices, bucket_id, transaction)[source]

Return the figures a linked sales invoice contributes, or why it is refused.

Derive-on-read: nothing is copied onto the transaction at link time, so a corrected invoice is reflected on the next aggregation and no stale figure can outlive it.

One guard differs from the expense side, and the difference is the point. An expense pays the whole contraprestación, so that side asserts the cash equals grand_total. A sales invoice subject to retención is paid NET – the payer withholds and remits the retención on the taxpayer’s account – so the bank credit is grand_total - retention_amount. Asserting equality against grand_total here would refuse precisely the net-paid professional invoices this evidence path exists to ground; asserting it against the cash without the retención term would accept an invoice that does not describe the payment.

Core types: InvoiceCatalogue.

Return type:

tuple[_SalesInvoiceEvidencePayload, SalesInvoiceEvidenceRefusal | None]

Parameters:
income_withheld_amount(transaction, *, evidence=None)[source]

Derive the retención practicada on one income row.

Bounded inference only: the figure is the declared invoice gross minus the cash actually received. The base is never reconstructed from the cash by assuming a rate – selecting the applicable rate (15 %, 7 %, a sectoral or convenio figure) is a per-row legal fact this application cannot determine, and inventing it would manufacture legal behaviour rather than read it.

The result is capped by the registry maximum supported rate. That bound exists on the transaction gross invariant too, but only for rows carrying both a base and a cuota; zero-cuota rows admitted here never meet it, so the inference applies the bound uniformly.

Return type:

_WithheldInference

Parameters:
  • transaction (Transaction)

  • evidence (_SalesInvoiceEvidencePayload | None)