cadrumo.application.invoices._bulk_import_columns module

Resolve a bulk-invoice-import file’s own headers onto importer fields.

A real libro registro carries every field the importer needs under names it has never seen — fecha_expedicion, base_imponible, nif_destinatario — and not one of them matches a canonical column name. The importer used to refuse such a file whole, so a book with every required field present imported nothing.

Resolution is deterministic first: a column whose header is already a canonical importer column keeps that field without consulting anything. Only the columns left over are put to the semantic mapping lane, once per file, over the closed FieldRole vocabulary. Exact-first matters for the same reason it does in the statement lane — a file already written in the product’s own vocabulary must never depend on a judgement to be read.

A column that resolves to no importer field is reported, never refused. The book that carries cuota_iva and total_factura — figures the importer derives rather than accepts — still imports every row; the operator is told which columns were not used instead of being handed a rejected file.

See also

FieldRole

The closed vocabulary the mapping lane selects from.

bulk_import

Reads the file and applies this resolution to each row.

BULK_IMPORT_FIELD_BY_ROLE: dict[FieldRole, str]

a role the importer has no field for (the IVA cuota and the grand total, both of which it derives rather than accepts) is absent here, so a column carrying one resolves to no field and is reported rather than quietly discarded.

A retención rate is accepted only beside its amount: the importer checks the two against each other and never derives the amount from the rate.

Type:

Which importer field each role feeds. Deliberately partial

ColumnRoleMapper

Establishes one role per column for a header row, or None when it cannot.

alias of Callable[[Sequence[str]], Sequence[FieldRole] | None]

class ResolvedColumn(**data)[source]

Bases: BaseModel

One source column and the importer field it feeds.

Variables:
  • column_index – Zero-based position in the source header.

  • header – The header text exactly as the file printed it.

  • field – The importer field this column supplies, or None when the column’s meaning was not established or maps to nothing the importer accepts.

  • role – The role the column was mapped to. UNMAPPED when the mapping lane could not place it; a real role with field still None means the product understood the column but has no slot for it.

Parameters:

data (Any)

column_index: NonNegativeInt
header: str
field: str | None
role: FieldRole
class BulkImportColumnResolution(**data)[source]

Bases: BaseModel

How one file’s header row resolved onto importer fields.

Variables:
  • columns – Every source column, in order.

  • consulted_mapping_lane – Whether the semantic lane was called. False means every column matched a canonical name outright.

Parameters:

data (Any)

columns: tuple[ResolvedColumn, ...]
consulted_mapping_lane: bool
property field_by_index: dict[int, str]

Return the importer field for each column that feeds one.

property unmapped_columns: tuple[ResolvedColumn, ...]

Return every column that feeds no importer field, for reporting.

property fields_present: frozenset[str]

Return the importer fields this file can supply.

resolve_bulk_import_columns(headers, *, mapper=None, required_fields=frozenset({}))[source]

Resolve headers onto importer fields, exact names first.

A header that already names a canonical importer column is bound to it without consulting mapper at all. The mapping lane is called at most once, and only when exact matching cannot supply every required field — a file already written in the product’s own vocabulary is read without any judgement, even when it carries extra columns the importer has no slot for. Those extras are simply reported. Its verdict is applied only to columns exact matching left open, so it can never displace an exact match.

Parameters:
  • headers (Sequence[str]) – The source header cells, in column order.

  • mapper (Callable[[Sequence[str]], Sequence[FieldRole] | None] | None) – Establishes roles for the columns exact matching did not resolve. None leaves them unmapped and reported.

  • required_fields (frozenset[str]) – Fields the importer cannot proceed without. The mapping lane is consulted only if exact matching misses one.

Return type:

BulkImportColumnResolution

Returns:

The per-column resolution, with everything unresolved reported rather than refused.