# 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`