Source code for cadrumo.application.ledger.evidence_advisory
"""Printed-vs-derived IVA advisory cross-check.A non-blocking diagnostic: when an invoice's on-host-extracted text appears toprint an IVA figure that disagrees with the registry-DERIVED IVA, surface anadvisory so the operator verifies before filing. The public:func:`printed_iva_advisory` helper feeds the ``evidence_advisory`` field on:class:`cadrumo.application.ledger.llm_classification_ports.LLMSaturatedSuggestion`after the saturation path has resolved evidence through:class:`cadrumo.domain.transactions.llm.PromptSpec`.The printed figure is parsed deterministically on-host from the evidence text(never emitted by the model) and is used ONLY for this advisory -- it is neverpersisted and never overrides the derived value(llm-selects-system-derives-tax-numbers / no-silent-under-declaration). Parsingis best-effort; a miss simply yields no advisory."""from__future__importannotationsimportrefromdecimalimportDecimalfrom...core.decimal.coercionimportcoerce_finite_european_decimal__all__=["printed_iva_advisory"]# "IVA" followed (within a short gap) by a Spanish- or plain-formatted amount.## Every alternative must capture the WHOLE numeric token. One that can stop# mid-token hands the parser a well-formed lie instead of the ambiguous string# it exists to judge: the plain alternative matched 8.00 out of a printed# 8.000, so the coercer -- which correctly drops 8.000 as an unsettleable# convention -- received an unambiguous eight euros and returned it. The# advisory then told the operator the document printed 8.00 when it printed# 8.000: a thousandfold error inside the message that exists to catch errors.## Hence the third alternative (Spanish thousands with no decimal part) and the# negative lookahead on the fourth. The token now reaches the coercer intact# and is dropped there when its reading cannot be settled._IVA_AMOUNT=re.compile(r"\bIVA\b[^\d-]{0,12}("r"\d{1,3}(?:\.\d{3})*,\d{2}"# 1.234,56r"|\d+,\d{2}"# 21,00r"|\d{1,3}(?:\.\d{3})+(?!\d)"# 8.000 -- ambiguous, left for the coercer to refuser"|\d+(?:\.\d{1,2})?(?!\d)"# 10.50, or a bare 8r")",re.IGNORECASE,)def_parse_amount(raw:str)->Decimal|None:"""Parse a Spanish- or plain-formatted :class:`~decimal.Decimal` string, best-effort. The EXTRACTION contract, read from the canonical home rather than re-implemented here. This function previously spelled out the same normalise-then-construct sequence inline, which is how it came to disagree with the rest of the codebase: a printed ``8.000`` was read as eight euros, because the thousands strip only fires when a comma is present to settle the convention. The canonical helper drops a token whose reading cannot be settled, so the advisory reports nothing rather than a figure a thousandfold out, and the operator is asked instead. """returncoerce_finite_european_decimal(raw)
[docs]defprinted_iva_advisory(evidence_text:str|None,derived_iva_amount:Decimal|None,*,tolerance:Decimal=Decimal("0.01"),)->str|None:"""Return an advisory string when the printed IVA disagrees with the derived IVA. The comparison is a best-effort cross-check between on-host-extracted evidence text and the registry-derived IVA amount carried by :class:`cadrumo.application.ledger.llm_classification_ports.LLMSaturatedSuggestion`; it never supplies a tax value for persistence. Args: evidence_text: On-host-extracted text of the attached evidence, or ``None``. derived_iva_amount: The registry-derived :class:`~decimal.Decimal` IVA amount, or ``None``. tolerance: Absolute cent :class:`~decimal.Decimal` tolerance for the comparison. Returns: A non-blocking advisory message when a printed IVA figure is found and differs from ``derived_iva_amount`` beyond ``tolerance``; otherwise ``None`` (no evidence, no derived value, no parseable printed figure, or a match). """ifnotevidence_textorderived_iva_amountisNone:returnNonematch=_IVA_AMOUNT.search(evidence_text)ifmatchisNone:returnNoneprinted=_parse_amount(match.group(1))ifprintedisNone:returnNoneifabs(printed-derived_iva_amount)>tolerance:return(f"the attached evidence appears to print an IVA of {printed} but the registry-derived "f"IVA is {derived_iva_amount}; verify the classification before filing (advisory only -- "f"the derived value is authoritative)")returnNone