aeat.domain.modelos._row_models module¶
Typed CLI row models for multi-row informational modelos.
Provides strictly-validated pydantic row shapes for operator-supplied detail rows on modelos whose filing content is a list of repeating records rather than a set of scalar casilla values.
Supported row types:
Modelo184MemberRow— atribución member for modelo 184 (--row miembro nif=X share=Y importe=Z)Modelo232VinculadaRow— operación vinculada for modelo 232 (--row vinculada nif=X tipo_vinculacion=Y importe=Z metodo=M pais=P)Modelo349OperadorRow— operador intracomunitario for modelo 349 (--row operador codigo_pais=DE nif_comunitario=DE123456789 razon_social=X clave_operacion=E importe=Y) Used when no collectible-invoice ledger exists; maps directly to the Tipo-2 operador record layout (Orden HAC/174/2020 Anexo II).Modelo349RectificacionRow— rectificación intracomunitaria for modelo 349 (--row rectificacion codigo_pais=DE nif_comunitario=DE123456789 razon_social=Xclave_operacion=E ejercicio=2025 periodo=2T base_rectificada=Y base_anterior=Z) Used when the operator declares Tipo-2 rectification records directly.Modelo347ContraparteRow— contraparte declarada for modelo 347 (--row contraparte nif=X nombre=Y importe_Q1=Z clave_operacion=A) One row per counterparty. Annual importe threshold check (> €3,005.06) is performed by the CLI validator, not the model, so partial row sets accumulate correctly before final validation.
These models are the CLI boundary layer. They validate operator input
before being carried into detail_rows on the CalculationRevision.
- class Modelo184MemberRow(**data)[source]¶
Bases:
BaseModelOne atribución member row for Modelo 184.
Fields mirror the per-record Tipo-2 layout declared in the M184
bindings/0001-bindings.tomlatribucion_member source block.Parity assertions: *
nif→member_tax_id(binding: modelo-184-member-row-nif) *nombre→member_legal_name(binding: modelo-184-member-row-name) *porcentaje→share_percentage(binding: modelo-184-member-row-share) *importe→base_imponible_assigned(binding: modelo-184-member-row-base-assigned) *pais→country_code(ES default)- Parameters:
row_type (Literal['miembro'])
nif (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=20, pattern=None, ascii_only=None)])
nombre (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=200, pattern=None, ascii_only=None)])
pais (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=2, max_length=2, pattern=None, ascii_only=None)])
porcentaje (Decimal)
importe (Decimal)
- row_type: Literal['miembro']¶
- nif: _NifStr¶
- nombre: _NameStr¶
- pais: _IsoCountryCode¶
- porcentaje: Decimal¶
- importe: Decimal¶
- class Modelo232VinculadaRow(**data)[source]¶
Bases:
BaseModelOne operación vinculada row for Modelo 232.
Fields mirror the related_party_operation binding source declared in
232/revisions/2018-y-siguientes/bindings/0218…0223-*.toml.Parity assertions: *
nif→counterparty_tax_id(binding: modelo-232-related-party-row-nif) *nombre→counterparty_legal_name(binding: modelo-232-related-party-row-name) *pais→country_code(binding: modelo-232-related-party-row-country) *tipo_operacion→operation_kind_code(binding: modelo-232-related-party-row-operation-kind) *metodo→transfer_pricing_method_code(binding: modelo-232-related-party-row-tpr-method) *importe→amount(binding: modelo-232-related-party-row-amount)- Parameters:
row_type (Literal['vinculada'])
nif (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=20, pattern=None, ascii_only=None)])
nombre (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=200, pattern=None, ascii_only=None)])
pais (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=2, max_length=2, pattern=None, ascii_only=None)])
tipo_vinculacion (str)
tipo_operacion (str)
metodo (str)
importe (Decimal)
- row_type: Literal['vinculada']¶
- nif: _NifStr¶
- nombre: _NameStr¶
- pais: _IsoCountryCode¶
- tipo_vinculacion: str¶
- tipo_operacion: str¶
- metodo: str¶
- importe: Decimal¶
- exception Modelo349CountryPrefixContextError(*, country_code, clave_operacion, filing_year, period, reason)[source]¶
Bases:
AeatError,ValueErrorA Modelo 349 country prefix is invalid for the filing context.
- Parameters:
- Return type:
None
- code: ClassVar[ErrorCode]¶
- class Modelo349OperadorRow(**data)[source]¶
Bases:
BaseModelOne operador intracomunitario row for Modelo 349 (manual-entry path).
Fields mirror the Tipo-2 operador record layout declared in
349/revisions/2020-y-siguientes/bindings/0007-bindings.toml.This row is used when the collectible-invoice ledger is absent and the operator declares intracom counterparties directly via the CLI.
Parity assertions: *
codigo_pais->op.codigo-pais(record positions 76-77) *nif_comunitario->op.nif-comunitario(record positions 78-92) *razon_social->op.apellidos-razon-social(record positions 93-132) *clave_operacion->op.clave-operacion(record position 133) *importe->op.base-imponible(record positions 134-146)- Parameters:
row_type (Literal['operador'])
codigo_pais (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=2, max_length=2, pattern=None, ascii_only=None)])
nif_comunitario (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=20, pattern=None, ascii_only=None)])
razon_social (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=200, pattern=None, ascii_only=None)])
clave_operacion (Literal['E', 'M', 'H', 'A', 'T', 'S', 'I', 'R', 'D', 'C'])
importe (Decimal)
- row_type: Literal['operador']¶
- codigo_pais: _IsoCountryCode¶
- nif_comunitario: _NifStr¶
- razon_social: _RequiredNameStr¶
- clave_operacion: _M349_CLAVE_OPERACION¶
- importe: Decimal¶
- class Modelo349RectificacionRow(**data)[source]¶
Bases:
BaseModelOne rectificación row for Modelo 349 (manual-entry path).
Fields mirror the Tipo-2 rectificación record layout declared in
349/revisions/2020-y-siguientes/bindings/0007-bindings.toml.Parity assertions: *
codigo_pais->op.codigo-pais(record positions 76-77) *nif_comunitario->op.nif-comunitario(record positions 78-92) *razon_social->op.apellidos-razon-social(record positions 93-132) *clave_operacion->op.clave-operacion(record position 133) *ejercicio->rect.ejercicio-rectificado(record positions 147-150) *periodo->rect.periodo-rectificado(record positions 151-152) *base_rectificada->rect.base-rectificada(record positions 153-165) *base_anterior->rect.base-anterior(record positions 166-178)- Parameters:
row_type (Literal['rectificacion'])
codigo_pais (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=2, max_length=2, pattern=None, ascii_only=None)])
nif_comunitario (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=20, pattern=None, ascii_only=None)])
razon_social (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=200, pattern=None, ascii_only=None)])
clave_operacion (Literal['E', 'M', 'H', 'A', 'T', 'S', 'I', 'R', 'D', 'C'])
ejercicio (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=4, max_length=4, pattern=None, ascii_only=None)])
periodo (Literal['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '1M', '1T', '2T', '3T', '4T'])
base_rectificada (Decimal)
base_anterior (Decimal)
- row_type: Literal['rectificacion']¶
- codigo_pais: _IsoCountryCode¶
- nif_comunitario: _NifStr¶
- razon_social: _RequiredNameStr¶
- clave_operacion: _M349_CLAVE_OPERACION¶
- ejercicio: Annotated[str, StringConstraints(strip_whitespace=True, min_length=4, max_length=4)]¶
- periodo: _M349_RECTIFICACION_PERIODO¶
- base_rectificada: Decimal¶
- base_anterior: Decimal¶
- validate_m349_nif_format(nif, pais)[source]¶
Return True when
nifmatches the expected NIF-IVA format forpais.Every current EU Member State (plus
XI) resolves its structural pattern from the canonicalaeat.core.identity.nif_iva_format_for_country()authority.GBis validated against Modelo 349’s own Brexit-transition pattern (see_M349_GB_NIF_PATTERN), since post-Brexit UK carries no entry in the general EU NIF-IVA authority. Unsupported country prefixes fail closed. The NIF string must include the same two-letter country prefix.
- validate_m349_country_prefix_context(*, country_code, clave_operacion, filing_year, period, is_rectification=False, rectified_year=None, rectified_period=None)[source]¶
Validate post-Brexit
GB/XIrules for Modelo 349.AEAT’s Brexit IVA instructions keep
XIfor Northern Ireland goods operations after 2021 and excludeS/Iservice keys fromXI. OrdinaryGBrows are not valid for post-transition periods, except for the limited 2021 first-period and pre-2021 rectification cases named by the official instructions.
- m349_nif_number_for_export(nif, pais)[source]¶
Return the BOE NIF subfield without the separate country-code prefix.
Modelo 349 operator records split the VAT identifier into
codigo_paisandnif_comunitariofields. The CLI accepts and validates the full prefixed VAT identifier for operator ergonomics, but the fixed-width export must write only the number part into positions 78-92.
- class Modelo347ContraparteRow(**data)[source]¶
Bases:
BaseModelOne contraparte declarada row for Modelo 347.
Fields mirror the per-counterparty Tipo-2 record layout declared in
347/revisions/2008-y-siguientes.One row per counterparty. The annual total importe (sum of Q1-Q4) must exceed €3,005.06 per RD 1065/2007 art. 33.1.
Parity assertions: *
nif→contraparte.nif(counterparty tax id) *nombre→contraparte.nombre(legal name) *importe_Q1/Q2/Q3/Q4→ quarterly importe slots *clave_operacion→ operation type code *pais_codigo→contraparte.pais(ISO 3166-1; None = domestic)- Parameters:
row_type (Literal['contraparte'])
nif (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=1, max_length=20, pattern=None, ascii_only=None)])
nombre (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=None, max_length=200, pattern=None, ascii_only=None)])
importe_Q1 (Decimal)
importe_Q2 (Decimal)
importe_Q3 (Decimal)
importe_Q4 (Decimal)
clave_operacion (Literal['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'])
pais_codigo (Annotated[str, StringConstraints(strip_whitespace=True, to_upper=None, to_lower=None, strict=None, min_length=2, max_length=2, pattern=None, ascii_only=None)] | None)
- row_type: Literal['contraparte']¶
- nif: _NifStr¶
- nombre: _NameStr¶
- importe_Q1: Decimal¶
- importe_Q2: Decimal¶
- importe_Q3: Decimal¶
- importe_Q4: Decimal¶
- clave_operacion: _M347_CLAVE_OPERACION¶
- pais_codigo: _IsoCountryCode | None¶
- exception Modelo347ThresholdError(*, nif, total)[source]¶
Bases:
AeatError,ValueErrorA Modelo 347 contraparte row falls at or below the declarability threshold.
- Parameters:
nif (str)
total (Decimal)
- Return type:
None
- code: ClassVar[ErrorCode]¶
Bases:
AeatError,ValueErrorModelo 184 member share percentages do not sum to exactly 100%.
- Parameters:
total (Decimal)
count (int)
- Return type:
None
- validate_m347_threshold(rows)[source]¶
Enforce the Modelo 347 per-counterparty declarability threshold.
RD 1065/2007 art. 33.1: only counterparties whose annual operations exceed EUR 3,005.06 are declarable. The threshold applies to the SUM of every operation with the same person (same NIF), aggregated across all contraparte rows — not to each row in isolation. A counterparty’s operations may be split across several rows (e.g. entregas and adquisiciones), so a per-row check would wrongly reject a counterparty whose individual rows are each at/below the threshold while their annual aggregate exceeds it (a missed declaration), and would never apply the “same person” threshold the regulation defines.
- Raises:
Modelo347ThresholdError – for the first counterparty (in NIF first-appearance order) whose AGGREGATED annual total is at or below the threshold.
- Return type:
- Parameters:
rows (Sequence[Modelo347ContraparteRow])
Enforce that Modelo 184 member share percentages sum to exactly 100%.
Only checked when at least one miembro row is present (partial sets are skipped).
- Raises:
Modelo184ShareSumError – when the share percentages do not total exactly 100.
- Return type:
- Parameters:
rows (Sequence[Modelo184MemberRow])