aeat.application.invoices._creation module

Application service for creating one rich catalogue Invoice.

The operator-facing aeat app ledger invoice catalogue create verb needs a path to mint a linkable invoice. The slim BusinessOperationInvoice written by invoice add is an operator-edit record with no linked_transaction_ids field, so link --invoice-id cannot resolve it (the documented sharp edge of 2026-06-10-ledger-invoice-unification-adr). Only the rich Invoice in the InvoiceCatalogue carries linked_transaction_ids and is the reconciliation authority link targets.

create_catalogue_invoice() builds a strict Invoice from operator-friendly fields — synthesising a single line item from a taxable base and IVA rate, mirroring the single-line synthesis the import path uses — and persists it through the sanctioned InvoiceCatalogueRepository (no parallel write path). The returned Invoice.invoice_id is the content-addressed hash link --invoice-id resolves, closing the documented add->link gap without collapsing the two stores.

numeric_iva_rate_slots()[source]

Return the closed set of operator-supplied IVA percentage slots.

A copy of the module-private mapping _resolve_iva_rate_slot() and build_catalogue_invoice() consume internally, exposed for other invoice-creation transports (e.g. the manual-entry wizard) that must validate a percentage against the same accepted set before it reaches build_catalogue_invoice().

Return type:

dict[Decimal, IvaRate]

class CatalogueInvoiceCreateResult(**data)[source]

Bases: BaseModel

Result of persisting one rich catalogue invoice.

Parameters:
invoice: Invoice
catalogue: InvoiceCatalogue
build_catalogue_invoice(*, bucket_id, kind, counterparty_name, counterparty_tax_id, counterparty_country, invoice_number, issued_at, taxable_base, iva_rate, currency, payment_status=PaymentStatus.PENDING, notes='', iva_category=None, operation_type=None)[source]

Return a strict rich Invoice from operator-supplied fields.

A single line item is synthesised from taxable_base and the resolved IVA rate slot; the invoice totals are derived from that line so the Invoice arithmetic invariants hold. The returned invoice carries no linked transactions yet — link --invoice-id populates them later.

iva_category carries the intra-community classification the M349 recapitulative resolver reads for historical goods/triangulation records. operation_type carries the explicit Modelo 349 clave for invoice records that need a key not represented by an IVA category.

Return type:

Invoice

Parameters:
create_catalogue_invoice(*, bucket_id, kind, counterparty_name, counterparty_tax_id, counterparty_country, invoice_number, issued_at, taxable_base, iva_rate, currency, payment_status=PaymentStatus.PENDING, notes='', iva_category=None, operation_type=None, repository=None)[source]

Persist one rich catalogue Invoice and return the updated catalogue.

The invoice is built via build_catalogue_invoice(), merged into the loaded InvoiceCatalogue, and written back through the sanctioned InvoiceCatalogueRepository. A duplicate logical identity (same derived invoice_id already present) is refused so an accidental re-create cannot silently overwrite a linked record.

Return type:

CatalogueInvoiceCreateResult

Parameters: