feat: plantilla base workspace SaaS
This commit is contained in:
141
docs/analisis_flujo_migracion_csv_transporte_sin_validaciones.md
Normal file
141
docs/analisis_flujo_migracion_csv_transporte_sin_validaciones.md
Normal 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`
|
||||
Reference in New Issue
Block a user