"""M232 related-party row materialisation into positional casillas.
Rows come from CLI input as ``Modelo232VinculadaRow`` objects and are
materialised into the selected revision's positional casillas. The selected
revision owns the row capacity, field declarations, binding identities, and
export layout; this module retains only the row-materialisation boundary.
"""
from __future__ import annotations
from collections.abc import Callable, Mapping
from datetime import date
from decimal import Decimal
from typing import Final
from ...core.casilla_id import CasillaId
from ...core.time.clock import today_madrid
from ..calculations.registry.authority import PinnedAuthorityOperation, bundled_indexed_authority
from ..calculations.registry.errors import RegistryValidationError
from ..calculations.registry.facts.resolution import (
MappingFactQuery,
ResolvedMappingFact,
required_mapping_entry,
unique_mapping_tokens,
)
from ..calculations.registry.schema_base import DateAxis
from .row_models import Modelo232VinculadaRow
_FACT_ID: Final = "modelo-232-related-party-row-materialisation-mapping"
_SUBJECT: Final = "Modelo 232 related-party row mapping"
#: How each registry-declared row field reads its value off a row. The registry
#: owns which fields exist and in what order; an undeclared field id is refused.
_ROW_FIELD_READERS: Final[Mapping[str, Callable[[Modelo232VinculadaRow], str | Decimal]]] = {
"nif": lambda row: row.nif,
"tipo-vinculacion": lambda row: str(row.tipo_vinculacion),
"tipo-operacion": lambda row: str(row.tipo_operacion),
"metodo-valoracion": lambda row: str(row.metodo),
"importe": lambda row: row.importe,
}
def _resolve_m232_registry_declarations(
*,
effective_date: date,
operation: PinnedAuthorityOperation,
) -> ResolvedMappingFact:
"""Resolve the selected Modelo 232 row declaration and mapping fact."""
resolved = operation.resolve_governed_fact(
MappingFactQuery(
fact_id=_FACT_ID,
date_axis=DateAxis.FILING_PERIOD,
effective_date=effective_date,
),
)
if not isinstance(resolved, ResolvedMappingFact):
raise TypeError("Modelo 232 row declarations must resolve as a mapping fact")
return resolved
def _row_capacity(entries: Mapping[str, str], slot_ids: tuple[str, ...]) -> int:
raw = required_mapping_entry(entries, "row.capacity", subject=_SUBJECT)
if not raw.isdigit() or int(raw) != len(slot_ids):
raise RegistryValidationError(f"{_SUBJECT} 'row.capacity' must equal the number of declared row slots")
return int(raw)
__all__ = [
"m232_related_party_row_casilla_values",
]