# Analisis de flujo de migracion CSV de transporte (sin validaciones)

## Objetivo

Definir como migrar el flujo de importacion CSV de facturas hacia columnas nuevas de transporte, priorizando continuidad operativa y consistencia de IDs en `invoice_logistics`, sin depender de reglas de validacion funcional.

## Estado actual de la rama

- El pipeline actual ya separa `scan` y `commit` en `tasks.py`.
- El mapeo de plantillas (`template_config.py`) aun esta centrado en `NUMERO TRANSPORTE`.
- En `commit`, la persistencia de logistica usa principalmente:
  - `carrier_id` / `carrier_int_id` desde `CLAVE TRANSPORTISTA`.
  - `transport_type` desde `TIPO TRANSPORTE`.
  - `transport_num` desde `NUMERO TRANSPORTE`.
- No existe aun una ruta establecida para columnas nuevas `CLAVE TRANSPORTE` y `NUMERO CAJA`.

## Intencion funcional identificada en los commits analizados

Sin copiar su logica de validacion, la idea de flujo que se quiso introducir es:

1. Separar los datos de transporte en dos entradas semanticas:
   - clave de vehiculo (`CLAVE TRANSPORTE`)
   - numero de caja/remolque (`NUMERO CAJA`)
2. Mantener compatibilidad con archivos legacy:
   - usar `NUMERO TRANSPORTE` como fallback cuando no existan columnas nuevas.
3. Resolver IDs internos en commit contra catalogos:
   - `vehicle_key` -> `vehicle_id`
   - `trailer_number` -> `trailer_id`
4. Persistir tanto la clave legible (string) como su ID interno (int) en `invoice_logistics`.
5. Mantener paridad de flujo entre scan y commit en cuanto a normalizacion y resolucion de campos, pero sin convertir scan en un bloqueo por validaciones de negocio.

## Flujo propuesto (sin validaciones de negocio)

### 1) Scan (preprocesamiento y trazabilidad)

Objetivo: preparar datos y metadatos, no rechazar por reglas funcionales.

- Leer CSV con `row_from_template`.
- Normalizar celdas relevantes de transporte:
  - trim
  - reemplazo de NBSP por espacio
  - `None`/vacio a cadena vacia
- Construir una estructura por renglon con campos de transporte efectivos:
  - `effective_transport_type`
  - `effective_vehicle_key`
  - `effective_trailer_number`
  - `effective_legacy_transport_num` (solo trazabilidad)
- Guardar errores tecnicos (parseo CSV, formato bruto no interpretable), pero no bloquear por reglas de catalogo/negocio.

### 2) Commit (resolucion y persistencia de IDs)

Objetivo: persistir de forma consistente los IDs nuevos de migracion.

- Determinar campos efectivos por precedencia (ver tabla siguiente).
- Resolver `carrier_int_id` con `CLAVE TRANSPORTISTA` (flujo ya existente).
- Resolver `transport_int_id` cuando exista `effective_vehicle_key`:
  - lookup en `vehicle.vehicle_key`
- Resolver `trailer_int_id` cuando exista `effective_trailer_number`:
  - lookup en `trailer.trailer_number`
- Persistir en `InvoiceLogistics`:
  - string keys: `carrier_id`, `transport_id`, `trailer_num`, `transport_num`
  - int refs: `carrier_int_id`, `transport_int_id`, `trailer_int_id`

Importante: para migracion, si hay string pero no hay match de ID, **no romper flujo**; persistir string y dejar int en `NULL` (el FK ya permite `SET NULL`).

## Matriz de mapeo CSV -> `invoice_logistics`

| Entrada CSV | Rol | Campo destino (string) | Campo destino (int) | Catalogo/lookup |
|---|---|---|---|---|
| `CLAVE TRANSPORTISTA` | Transportista | `carrier_id` | `carrier_int_id` | `transporter.transporter_key -> transporter_id` |
| `CLAVE TRANSPORTE` | Vehiculo | `transport_id` | `transport_int_id` | `vehicle.vehicle_key -> vehicle_id` |
| `NUMERO CAJA` | Caja/Remolque | `trailer_num` | `trailer_int_id` | `trailer.trailer_number -> trailer_id` |
| `NUMERO TRANSPORTE` (legacy) | Fallback | `transport_num` (siempre trazable) y apoyo para resolver vehicle/trailer segun precedencia | opcional | depende de reglas de precedencia |
| `TIPO TRANSPORTE` | Tipo logistica | `transport_type` | n/a | enum interno |

## Reglas de precedencia de datos (nuevas vs legacy)

Definicion para no generar ambiguedad:

1. Si viene `CLAVE TRANSPORTE`, usarla para `transport_id`.
2. Si viene `NUMERO CAJA`, usarla para `trailer_num`.
3. Si faltan columnas nuevas y viene `NUMERO TRANSPORTE`:
   - usarlo como `transport_num` (trazabilidad legacy)
   - y usarlo como fallback de resolucion para `transport_id`/`trailer_num` solo cuando el campo nuevo correspondiente este vacio.
4. Nunca sobreescribir un dato nuevo con legacy si el nuevo viene poblado.

Sugerencia para parciales (`actualizar=true`):
- aplicar merge campo a campo: solo actualizar datos de transporte que lleguen informados en CSV; conservar los demas en la fila existente.

## Relacion con la migracion de IDs

La migracion `ca7d3c4e8b2a` ya formaliza:

- `carrier_int_id` -> FK a `transporter.transporter_id`
- `transport_int_id` -> FK a `vehicle.vehicle_id`
- `trailer_int_id` -> FK a `trailer.trailer_id`

Por lo tanto, el flujo CSV debe priorizar:

- resolver claves string de catalogo de forma determinista
- poblar IDs internos cuando haya match
- mantener string keys para trazabilidad y backfill futuro

## Impacto de implementacion por archivo (sin validaciones)

### `backend/api/v1/modules/a76/layouts_csv/facturas/template_config.py`

- Agregar columnas canonicas nuevas en encabezados:
  - `CLAVE TRANSPORTE`
  - `NUMERO CAJA`
- Mantener `NUMERO TRANSPORTE` como compatibilidad legacy (no eliminar de inmediato).
- Ajustar aliases para tolerar variantes de cabecera.

### `backend/api/v1/modules/a76/layouts_csv/facturas/tasks.py`

- Incorporar helper de resolucion de campos efectivos de transporte:
  - prioridad nuevas columnas
  - fallback legacy
- En `scan`, registrar estructura normalizada (sin rechazo por reglas de catalogo).
- En `commit`, poblar `InvoiceLogistics` con:
  - `transport_id`/`transport_int_id`
  - `trailer_num`/`trailer_int_id`
  - `transport_num` como legado/trazabilidad
- Mantener comportamiento de no falla por ausencia de match de IDs.

### Nuevo helper recomendado: `backend/api/v1/modules/a76/layouts_csv/facturas/validators/transport_catalog.py`

- Aunque no se usen validaciones de negocio, centralizar funciones de:
  - normalizacion de celdas
  - resolucion de keys efectivas
  - lookups de IDs de vehiculo/remolque
- Evita duplicar logica entre scan y commit.

## Criterios de aceptacion de esta migracion de flujo

- Queda definida una sola fuente de verdad para precedencia de columnas nuevas/legacy.
- `commit` persiste consistentemente claves string e IDs int de logistica.
- El flujo funciona aun cuando no haya match de catalogo (sin bloqueo por validacion).
- No hay ambiguedad entre:
  - `transport_id` vs `transport_num`
  - `transport_int_id` vs `trailer_int_id`
