cadrumo.application.aggregation.counterpart module

Modelo 347/349 counterpart aggregation for informativa declarations.

Used by service, the per-modelo aggregation service. This is an operator preview surface, not the live calculation source mesh: standalone CounterpartObservation rows are operator-supplied, while calculation uses enrolled repository-backed sources.

Modelo 347 covers annual operations with third parties whose total exceeds the declaration floor. Modelo 349 covers intra-EU operations by member-state operation kind. Both aggregate per (source_kind, counterparty_nif, operation_kind) using the counterpart subset of the canonical source-kind taxonomy.

counterpart_operation_catalogue_entries(effective_date, *, operation)[source]

Return the dated M347/M349 counterpart operation mapping as unique string pairs.

Return type:

dict[str, str]

Parameters:
class CounterpartObservation(**data)[source]

Bases: _CounterpartBoundaryModel

One typed observation for a 347 or 349 aggregator pass.

This model is the operator boundary: aeat app modelo aggregate validates each --counterpart-observation JSON object directly against it, so whatever it admits reaches the preview rollups unchecked.

accrued_on and operation_period are therefore admitted by the same authorities the rest of the system uses. Bounding them by string length alone let an impossible calendar date (2026-99-99 and 2026-02-30 are both ten characters) and an arbitrary period token into a rollup the operator reads as a preview of a real declaration, while the adjacent registry counterpart binding types the same concepts as a date and a registry period code.

Parameters:

data (Any)

source_kind: CounterpartSourceKind
source_object_id: str
counterparty_nif: str
counterparty_name: str
counterparty_country: CountryCodeAlpha2
operation_kind: str
operation_period: FilingPeriodCode
taxable_base: Decimal
invoice_total: Decimal
accrued_on: IsoDateString
groi_verified: bool
nif_iva_verified: bool
class CounterpartRollup(**data)[source]

Bases: _CounterpartBoundaryModel

One (source_kind, counterparty_nif, operation_kind) rollup row.

Parameters:

data (Any)

source_kind: CounterpartSourceKind
counterparty_nif: str
counterparty_name: str
counterparty_country: CountryCodeAlpha2
operation_kind: str
observations_count: NonNegativeInt
total_taxable_base: Decimal
total_invoice_total: Decimal
requires_groi_check: bool
requires_nif_iva_check: bool
groi_ready: bool
nif_iva_ready: bool
declarable_readiness_satisfied: bool
class CounterpartAggregation(**data)[source]

Bases: BaseModel

347 / 349 counterpart aggregation output.

Parameters:

data (Any)

modelo: str
period: InstanceOf[Period]
rollups: tuple[CounterpartRollup, ...]
total_counterparties: NonNegativeInt
total_taxable_base: Decimal
total_invoice_total: Decimal
aggregate_counterpart_347(observations, *, period, operation=None)[source]

Aggregate Modelo 347 (operaciones con terceros, annual).

Filters to 347 operation kinds. Threshold gating (the €3,005.06 declaration floor) belongs to the modelo binding consumer; this aggregator returns raw per-counterparty totals.

Returns a CounterpartAggregation.

Return type:

CounterpartAggregation

Parameters:
aggregate_counterpart_349(observations, *, period, operation=None)[source]

Aggregate Modelo 349 (operaciones intracomunitarias).

Filters to 349 intracomunitarias operation kinds. Rollups carry the additional NIF-IVA / GROI readiness gates: Spanish counterparties require GROI readiness and non-Spanish counterparties require NIF-IVA readiness.

Returns a CounterpartAggregation with rollups sorted by (source_kind, counterparty_nif, operation_kind).

Return type:

CounterpartAggregation

Parameters: