cadrumo.domain.invoices.validators module¶
Counterparty identity validators for invoice records.
The EU-IVA prefix check and ISO-3166 alpha-2 country-code normaliser
remain in this module because they are invoice-domain concerns.
Each helper raises ValueError on failure so pydantic
surfaces the error as a validation error in the enclosing
Invoice model.
The registry-grounded is_eu_member_state_code() helper anchors the EU
axis to the substrate’s registry-projected cadrumo.domain.iva.schema.EUMemberState
token. Modelo 369 binding selectors and the OSS / IOSS classifier
boundary checks consume these helpers so the EU membership decision
flows from the substrate, not from a hand-maintained list.
- validate_country_code(value)[source]¶
Normalise and validate an ISO-3166 alpha-2 country code.
Folds case, unlike
normalise_iso_3166_alpha2_jurisdiction(), which refuses a lowercase token so the regulatory treatment of a ledger row is never guessed. A counterparty’s country is a label on an invoice rather than a treatment selector, so folding an operator’s"es"here costs nothing. The two shareCOUNTRY_CODE_ALPHA2_PATTERNand nothing else.- Parameters:
value (
str) – Raw country code to validate.- Return type:
- Returns:
The uppercased two-letter country code.
- Raises:
InvoiceValidationError – If the input is not exactly two alphabetic characters.
- is_eu_member_state_code(value)[source]¶
Return
Truewhenvaluematches one of the 27 EU Member State codes.The membership check is anchored to
cadrumo.domain.iva.schema.EUMemberState; if fact 0131 changes (Brexit-style additions or withdrawals) the helper picks up the selected membership automatically.
- validate_iva_number(value, country)[source]¶
Validate a non-ES IVA number shape against its country format.
For an EU Member State (and Northern Ireland
XI) the number is matched against the country’s published NIF-IVA structural pattern, sourced from the centralcadrumo.core.identity.nif_iva.NIF_IVA_FORMATSauthority: a malformed intra-community IVA number is bounced by AEAT’s Modelo 349 validator, so the refusal names the country and the expected format. Live VIES existence is not checked — only the structure. For a non-EU counterparty (no published pattern) the helper falls back to a generic leading-prefix plus 4-20 character alphanumeric body check, so non-EU counterparties remain acceptable.- Parameters:
- Return type:
- Returns:
The uppercased, whitespace-trimmed IVA identifier.
- Raises:
InvoiceValidationError – If the value is malformed, the prefix does not match
country, or the EU NIF-IVA format does not match.
- validate_counterparty_tax_id(tax_id, *, country)[source]¶
Validate a counterparty’s tax identifier under its country’s regime.
Which regime applies is a domain rule, not a detail of whichever surface happens to hold the values: a Spanish counterparty is checked against the AEAT checksum, an EU one against its Member State’s NIF-IVA structure. That choice was written twice – once as a mapping with a default in the invoice normaliser, once as an
if country == "ES"in the CLI wire projection – and a third regime, or a change to which countries take which, would have had to reach both.An ABSENT country returns the identifier unvalidated, and that is the deliberate half. A factura simplificada may legitimately carry no counterparty country (RD 1619/2012 art. 6.1.d), and with no country there is no regime to check against; guessing one from the identifier’s own shape is the substitution the identification-state fact exists to prevent.
- Parameters:
- Return type:
- Returns:
The identifier in the canonical form its regime’s validator returns, unchanged when no country was declared.
- Raises:
InvoiceValidationError – The identifier does not satisfy its regime.