feat: plantilla base workspace SaaS
Some checks failed
Build Producción & Push a Harbor / test (push) Failing after 3s
Build Producción & Push a Harbor / build (push) Has been skipped
Aduanasoft/plantillas-proyectos/pipeline/head There was a failure building this commit

This commit is contained in:
2026-07-21 13:59:00 -05:00
commit bdd089954b
470 changed files with 70022 additions and 0 deletions

View File

@@ -0,0 +1,141 @@
# 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`