aeat.application.invoices._wizard module¶
Guided, non-blocking manual-entry path for one catalogue Invoice.
aeat app ledger invoice catalogue wizard is the fallback entry point for
when automated extraction (ledger evidence extract / vision OCR) is
unavailable or insufficient: the operator (an autonomous LLM agent that cannot
answer an interactive prompt) supplies every invoice field as CLI options in
one call. This module validates each field independently – reusing the same
grounded heuristics validate_spanish_tax_id() and the
ISO-8601 / canonical-decimal parsers already enforce on the extract/confirm
path – and accumulates every failing field into one refusal
(no-silent-under-declaration: a malformed field is named, never silently
dropped or reported one-at-a-time when several are wrong).
The write itself delegates to create_catalogue_invoice()
– the sole sanctioned Invoice writer
(composition-service-no-parallel-write-path); this module never persists a
row itself. Because Invoice identity is a
content-derived hash, a retry that resolves to an already-catalogued identity
is a guarded no-op (single-subject-mutation-is-idempotent-guarded): the
existing record is returned, not re-written or raised as an error, mirroring
the re-import-of-an-unchanged-file semantics
import_invoices_from_rows() already implements for
the bulk path.
See also
create_invoice_via_wizard()Public application facade for this guided manual-entry path.
create_catalogue_invoice()Single catalogue writer used after field validation succeeds.
import_invoices_from_rows()Spreadsheet-oriented sibling path with matching idempotency semantics.
extract_invoice_draft_from_evidence()Automated evidence extraction path this non-interactive wizard complements when OCR is unavailable or insufficient.
- class InvoiceWizardFieldError(**data)[source]¶
Bases:
BaseModelOne field that failed the wizard’s guided validation.
Mirrors
BulkInvoiceImportRowFailure’sfield/reasonshape so a manual-entry refusal reads consistently with the bulk-import refusal surface, minus the row number a single-invoice wizard has no use for.- field: str¶
- reason: str¶
- class InvoiceWizardResult(**data)[source]¶
Bases:
BaseModelOutcome of one guided manual-entry invoice creation.
already_existedisTruewhen the derived identity already named a catalogued invoice – the guarded idempotent no-op path (single-subject-mutation-is-idempotent-guarded):invoiceis the pre-existing record and nothing was written.- invoice: Invoice¶
- already_existed: bool¶
- create_invoice_via_wizard(*, bucket_id, kind, counterparty_nif, counterparty_name, invoice_number, invoice_date, taxable_base, iva_rate, currency, country_code='ES', notes='', iva_category=None, operation_type=None, repository=None)[source]¶
Validate every field, then create (or resolve) one catalogue invoice.
Every field is validated independently and every failure is accumulated before raising, so a malformed NIF and a malformed date are BOTH reported in one refusal rather than the first field masking the second (
no-silent-under-declaration). This is a step-wise, non-interactive entry point: it never blocks on stdin – every field is supplied up front as a keyword argument, matching the CLI’s all-options-up-front shape.- Parameters:
bucket_id (
str) – Active profile bucket the invoice is scoped to.kind (
InvoiceKind) – Invoice direction (issued / received).counterparty_nif (
str) – Raw counterparty NIF/NIE/CIF or EU IVA number.counterparty_name (
str) – Raw counterparty display name.invoice_number (
str) – Raw AEAT-significant invoice number.invoice_date (
str) – Raw ISO-8601 invoice date string.taxable_base (
str) – Raw non-negative decimal taxable base string.iva_rate (
str|None) – Raw decimal IVA percentage string, orNone/blank for a base-only (exempt) invoice.currency (
str) – Raw ISO-4217 currency code (defaults are the caller’s concern; this function validates whatever is passed).country_code (
str) – Raw ISO-3166 alpha-2 counterparty country code.notes (
str) – Free-text notes.iva_category (
IvaCategory|None) – Optional intra-community IVA classification.operation_type (
IntracomOperationType|None) – Optional Modelo 349 operation-type clave.repository (
InvoiceCatalogueRepositoryProtocol|None) – Optional injected catalogue repository (tests).
- Return type:
- Returns:
InvoiceWizardResultnaming the resolved invoice and whether it was newly created or already existed under the same derived identity (the guarded idempotent no-op).- Raises:
InvoiceValidationError – naming every failing field in one message when one or more fields are malformed.