cadrumo.domain.calculations.registry.invoice_bindings module¶
Invoice-shaped registry binding helpers.
- class RectificationScope(*values)[source]¶
Bases:
StrEnumWhich rectification rows an invoice or counterpart selector admits.
- ONLY_RECTIFICATIONS¶
Rectification rows alone.
- EXCLUDE_RECTIFICATIONS¶
Every row except rectifications.
- ANY¶
No rectification filter; the default when a selector is silent.
- class InvoiceObservation(**data)[source]¶
Bases:
BaseModelOne factual line from the user’s invoice ledger.
The fields are scoped to the facts every IVA modelo needs to classify a transaction.
base_amountcarries the taxable base;invoice_total_amountcarries the gross invoice total for modelos such as M347 whose declaration floor is not the taxable-base amount.intracommunity_clavefollows the AEAT clave-de-operacion enum (E, M, H, A, T, S, I, R, D, C) for M349.operation_clavecarries M347’s OWN, unrelated clave-de-operacion vocabulary (A-G; seem347_operation_clave()) – the two claves share no values in common and a row must never mix them.iva_regimeis open-ended so domestic-IVA modelos can carry their regime classification alongside.- Parameters:
data (Any)
- invoice_id: str¶
- source_kind: BindingSourceKind¶
- party_tax_id: TaxIdIdentityToken¶
- country_code: CountryCodeAlpha2¶
- transaction_date: date¶
- base_amount: Decimal¶
- invoice_total_amount: Decimal | None¶
- iva_regime: str | None¶
- intracommunity_clave: str | None¶
- operation_clave: str | None¶
- is_rectification: bool¶
- rectified_year: FilingYear | None¶
- rectified_period: str | None¶
- rectified_base_previous: Decimal | None¶
- party_legal_name: str | None¶
- class LedgerTransactionProvider(**data)[source]¶
Bases:
InvoiceProviderBaseA counterparty-side ledger transaction aggregate over the invoice grammar.
- Parameters:
data (Any)
- kind: Literal[BindingSourceKind.LEDGER_TRANSACTION]¶
- class PurchaseInvoiceEvidenceProvider(**data)[source]¶
Bases:
InvoiceProviderBaseEvidence rows for purchase invoices, projected through the invoice grammar.
- Parameters:
data (Any)
- kind: Literal[BindingSourceKind.PURCHASE_INVOICE_EVIDENCE]¶
- class PayableInvoiceProvider(**data)[source]¶
Bases:
InvoiceProviderBaseAn invoice the taxpayer must pay: a purchase, clave A under RD 1065/2007 art. 33.1.
- Parameters:
data (Any)
- kind: Literal[BindingSourceKind.PAYABLE_INVOICE]¶
- class CollectibleInvoiceProvider(**data)[source]¶
Bases:
InvoiceProviderBaseAn invoice the taxpayer will collect: a sale, clave B under RD 1065/2007 art. 33.1.
- Parameters:
data (Any)
- kind: Literal[BindingSourceKind.COLLECTIBLE_INVOICE]¶
- class M347ThirdPartyOperationProvider(**data)[source]¶
Bases:
InvoiceProviderBaseThe combined-direction M347 third-party operation total, grouped by counterparty.
- Parameters:
data (Any)
- kind: Literal[BindingSourceKind.M347_THIRD_PARTY_OPERATION]¶
- is_m347_declarante_summary_invoice_binding(binding)[source]¶
Return whether
bindingis the M347 declarante-summary invoice binding.The canonical, single-defined predicate over
_M347_DECLARANTE_SUMMARY_RECORD, read through the typed_invoice_selector()rather than a rawselector_as_dict(binding).get("record"): a caller outside this module (application/invoices/source_resolver.py) once carried its own copy of both the literal and a.get()read, so a rename of therecordfield would have silently, permanently misclassified the M347 declarante-summary binding as absent rather than raising.binding.sourceis checked first becauseInvoiceProviderBasevalidates only invoice-family selectors; a non-invoice binding’s selector shape is a different family’s concept entirely, never this one’s business.- Return type:
- Parameters:
binding (BindingDefinition)
- m347_operation_clave(source_kind)[source]¶
Return the M347 clave de operacion determinable from
source_kindalone.Grounded against RD 1065/2007 art. 33.1. Only two of the seven claves are determinable from the invoice direction alone:
PAYABLE_INVOICE(an invoice the taxpayer must pay – a purchase) is claveA, adquisiciones de bienes y servicios superiores a 3.005,06 EUR.COLLECTIBLE_INVOICE(an invoice the taxpayer will collect – a sale) is claveB, entregas de bienes y prestaciones de servicios superiores a 3.005,06 EUR.
Claves F/G (mediaci�n de agencia de viajes under RD 1619/2012 disposici�n adicional cuarta) are classified by the resolver caller from a fact this function’s single
source_kindargument cannot carry – the invoice’s own travel-agency mediation flag, not its direction. The remaining three claves each still need a fact neither this function nor the resolver caller has:C(cobros por cuenta de terceros) needs a professional-fees-collection classification distinct from ordinary purchase/sale direction;D/Ekey on the FILER’s own type (entidad p�blica, partido, sindicato, …) rather than on any transaction classification. ReturnsNonefor those and for any non-invoice source kind, rather than guessing – a caller distinguishing them needs a fact this function does not have, not a default.source_kindalso accepts a barestrvalue-equal to a member: the registry’s own TOML-to-enum hydration boundary can still hold the raw value when this is consulted, and comparison below is by equality, never identity, so a value-equal string classifies exactly like its member.- Return type:
- Parameters:
source_kind (BindingSourceKind | str)
- validate_invoice_binding(binding)[source]¶
Validate an invoice-source binding at registry-build time.
Accumulating
list[str]validator: validates the selector againstInvoiceProviderBaseand lifts the invoice fact/op invariants to build time, preserving the underlying pydantic field error. Both this validator and the invoice resolvers run the same inner_validated_invoice_selector(), so the fact/op invariants are genuinely re-checked at resolve time;validate_invoice_binding()is the public raise-style wrapper over that same inner check.- Return type:
- Parameters:
binding (BindingDefinition)
- validate_invoice_family_fact_and_aggregation(binding, selector, *, family_label, strict_scalar_shape)[source]¶
Shared invoice/counterpart fact + aggregation-op cross-invariant.
The invoice and counterpart families share one selector shape (
InvoiceProviderBase) and one fact set (_INVOICE_FACTS); their op/fact cross-checks were near-verbatim copies differing only in the family-name in the unsupported-fact message and in whether the invoice-only scalar-shape guards (non-row fact must not declare row_field/groupingandop 'rows' requires fact 'row_field') run.family_labelselects the error wording;strict_scalar_shapetoggles the invoice-only guards (the counterpart variant historically omitted them, so the flag preserves that behaviour exactly).- Return type:
- Parameters:
binding (BindingDefinition)
selector (InvoiceProviderBase)
family_label (str)
strict_scalar_shape (bool)
- resolve_invoice_family_scalar_values(revision, *, source_kinds, validate_selector, observations_for_binding)[source]¶
Resolve scalar bindings on a
ModeloRevisionfor one invoice family into Decimal aggregates.Shared core for both the invoice and counterpart scalar resolvers; the two differed only in (a) the family membership set, (b) the per-family selector validator, and (c) whether observations are filtered directly (invoice) or matched by
source_kindand converted from counterpart observations. Row-producer bindings (fact == "row_field") are skipped here.- Return type:
- Parameters:
revision (ModeloRevision)
validate_selector (Callable[[BindingDefinition], InvoiceProviderBase])
observations_for_binding (Callable[[BindingDefinition], tuple[InvoiceObservation, ...]])
- resolve_invoice_family_row_values(revision, *, source_kinds, validate_selector, observations_for_binding, cohort_by_source, m347_threshold_filter)[source]¶
Resolve row-producer bindings on a
ModeloRevisionfor one invoice family into per-row values.Shared core for both the invoice and counterpart row resolvers. Bindings sharing the same cohort key share one-based row indexes so that an export record with
repeat = "binding_rows"correlates field values across bindings on the same row. The counterpart family addsbinding.sourceto the cohort key (cohort_by_source = True) so a different counterpart source kind does not share rows; the invoice family does not.M347’s
contraparte_clavegrouping needs every clave to share ONE row sequence, because the dise�o de registro’s Tipo-2 declarado record is one shared physical sequence regardless of clave (grounded in the tui-architecture modelo 347 contraparte binding inventory reference). That now falls out ofcohort_by_sourcedirectly rather than needing a grouping-keyed exception: everycontraparte_clavebinding declares the combined-directionM347_THIRD_PARTY_OPERATIONsource (see that member’s docstring), sobinding.sourceis already identical across claves and the cohort key naturally coincides. M349’s own two groupings, which still declare distinctpayable_invoice/collectible_invoicesources per binding, are unaffected.- Return type:
- Parameters:
revision (ModeloRevision)
validate_selector (Callable[[BindingDefinition], InvoiceProviderBase])
observations_for_binding (Callable[[BindingDefinition], tuple[InvoiceObservation, ...]])
cohort_by_source (bool)
m347_threshold_filter (Callable[[tuple[InvoiceObservation, ...]], tuple[InvoiceObservation, ...]])
- resolve_invoice_binding_values(revision, observations, *, effective_date=None)[source]¶
Resolve scalar invoice-source bindings into Decimal aggregates.
Row-producer bindings (
aggregation.op == "rows") are skipped here; they are resolved byresolve_invoice_binding_row_values().- Parameters:
revision (
ModeloRevision) – TheModeloRevisionwhose bindings are resolved.observations (
Iterable[InvoiceObservation]) – Invoice ledger lines to aggregate over.effective_date (
date|None) – Filing-period date required when the revision contains M347 declarante-summary threshold bindings; otherwise unused.
- Return type:
- resolve_invoice_binding_row_values(revision, observations, *, effective_date=None)[source]¶
Resolve row-producer invoice bindings into per-row indexed values.
Bindings with
aggregation.op == "rows"aggregate observations into rows deterministically grouped byselector.grouping. Bindings sharing the same grouping/scope/clave-filter share row indexes, so that an export record withrepeat = "binding_rows"can correlate field values across bindings on the same row. Returns a flat mapping keyed by(binding_id, row_index). Row indexes are one-based to matchModeloBindingValue.row_index.- Parameters:
revision (
ModeloRevision) – TheModeloRevisionwhose row-producer bindings to resolve.observations (
Iterable[InvoiceObservation]) – TypedInvoiceObservationrows the row-producer bindings group, filter, and aggregate into indexed row values.effective_date (
date|None) – Filing-period date required when acontraparte_claverow family needs the M347 declaration threshold; otherwise unused.
- Return type:
- class InvoiceProviderBase(**data)[source]¶
Bases:
BaseModelStrict validator for the selector mapping of an invoice-source binding.
- Parameters:
data (Any)
- fact: _InvoiceFact¶
- claves: tuple[str, ...]¶
- rectification_scope: RectificationScopeField¶
- iva_regime: str | None¶
- row_field: _InvoiceRowField | None¶
- grouping: InvoiceGrouping | None¶
- record: str | None¶
- data_type: ExportFieldDataType | None¶
Scalar type of the value this row field contributes to the export.
The same fact
BindingRowExportSelector.data_typecarries; declared here so the selector model admits the key, since a source-family selector is validated whole against its own strict model. Optional while the families adopt it.
- invoice_selector(binding)¶
- Return type:
- Parameters:
binding (BindingDefinition)