cadrumo.core.decimal.printed_money module¶
Anchored shape check for AEAT’s own printed-money rendering.
AEAT prints a monetary figure to one house convention: an optional sign, thousands grouped in threes, and a mandatory two-decimal comma tail. This module owns the single anchored grammar for that convention.
It is a shape check, not a parser. It answers whether a token is an AEAT-printed amount end to end — never merely whether it contains one — and the callers that consult it run it as a gate before handing the token to a parser.
Why the two-decimal tail is mandatory¶
The tail is the whole point of the check. A template that began printing whole
euros would render 1.843, and a permissive read resolves that to either
1843 or 1.843 with nothing in the token to choose by — a thousandfold
error on a figure a taxpayer pays or appeals against. Requiring the comma tail
means such a template change surfaces as the refusal it is, instead of being
silently reinterpreted as a thousands-grouped integer.
This is the same ambiguity european_thousands_reading_is_ambiguous()
refuses for hand-typed text, closed here from the other side: that predicate
detects the missing evidence, this grammar demands the evidence be present.
Why it lives in core¶
The strict and the tolerant readings of a printed amount are one taxonomy, not two neighbouring conveniences. Which grammar a token is judged by follows from its provenance — AEAT printed it, or a human typed it — and that choice has to be made identically wherever an amount enters the system. A taxonomy whose members are decided together belongs where the whole tree can reach it, beside the separator and coercion helpers its callers already consume.
Its readers happen to be an inbound adapter (the sanción/liquidación
notification reader) and an outbound one (the sede IVA compensation wallet
reader). That is not itself the argument for the placement: this tree already
carries a runtime outbound-to-inbound adapter edge, so “an adapter may not own
a primitive its counterpart imports” would be a rule stated here and broken
elsewhere. The grammar lives in core because of what it is, not because of
who could not otherwise import it.
The check previously shipped as a hand-copied regex literal in each of those two modules — one of which described it in prose as “shared verbatim”, which is precisely what a duplicate looks like from the inside.
Relationship to the sibling grammars¶
try_parse_canonical_decimal() owns the hand-typed dot-decimal grammar;
this module owns the AEAT-printed comma-tailed one. Pick by provenance.
SPANISH_AMOUNT_GROUP is the UNANCHORED capture
group for this same convention, used to FIND an amount inside a longer printed
line. The two are deliberately not interchangeable: anchoring that capture
group would refuse an ungrouped 1234,56, which this grammar accepts.
- AEAT_THOUSANDS_SEPARATORS: Final[str]¶
., NBSP, narrow NBSP.Per UNE 82100, AEAT groups thousands with a full stop, a non-breaking space (U+00A0) or a narrow no-break space (U+202F) — and never a plain ASCII space, which is reserved for column separation. That distinction is the whole value of naming the set: admitting ASCII space would let a grammar walk across the gap between a label and its value and read two adjacent numbers as one.
Declared here so the anchored grammar in this module and the unanchored capture group
SPANISH_AMOUNT_GROUPcannot drift on which code points AEAT actually prints. They differ on anchoring, deliberately; they must not differ on this.- Type:
The code points AEAT prints between thousand groups
- is_aeat_printed_money(text)[source]¶
Return whether text is exactly one AEAT-printed monetary amount.
The token must BE the shape end to end. Grouped (
3.687,12, and the non-breaking-space renderings of the same figure) and ungrouped (1234,56) forms both conform, with or without a leading-; a missing or wrong-width two-decimal comma tail does not, and neither does a thousands group separated by a plain ASCII space.- Parameters:
text (
str) – The candidate token, already stripped of any currency unit, tabulation filler and surrounding whitespace by the caller.- Return type:
- Returns:
Truewhen text conforms to the AEAT printed-money grammar.
Examples
>>> is_aeat_printed_money("3.687,12") True >>> is_aeat_printed_money("1234,56") True >>> is_aeat_printed_money("-1.234,56") True >>> is_aeat_printed_money("1\u00a0234,56") True >>> is_aeat_printed_money("1 234,56") False >>> is_aeat_printed_money("1.843") False >>> is_aeat_printed_money("total 3.687,12 euros") False