basquetWi + New ticket
movilba MOVILBA-468

carroceria_modelo y carroceria_fabricante son un solo hecho en dos columnas: portar y borrar, y sacar el campo bodyModel del historial

Done low dmdb03-mba-l-cc

MEDIDO por db02-mba-l-cc en DEV el 2026-09-17, SELECT only, sobre rutap.vehiculo_historial_normalizado: en las 64 filas de origen='app' donde carroceria_modelo y carroceria_fabricante estan poblados los dos, coinciden 64/64, cero discrepancias. En las 5514 filas de origen='import', carroceria_modelo es NULL en las 5514 y carroceria_fabricante es no-nulo en las 5514. POR QUE SON EL MISMO HECHO, aparte de la medicion: docs/reference/vehiculo-data-model.md:59-63 - el catalogo carrocerias quedo BRAND-ONLY tras el dedupe del 2026-06-30 (71 -> 18 filas), carrocerias.carroceria_modelo ES la marca del fabricante, no un modelo de producto, y fabricante_id es 1:1 redundante con el. POR QUE ES NULL EN IMPORT, no es una corrida vieja: db02 leyo pg_get_functiondef de rutap.proyectar_snapshot instalada en DEV (linea 278) y en PROD (linea 296) - las dos hardcodean 'nullif(btrim(carroceria),''), NULL, nullif(btrim(carroceria_categoria),''), NULL' para (carroceria_fabricante, carroceria_modelo, carroceria_categoria, carroceria_id). Es NULL por construccion en el cuerpo de la funcion. Ningun trigger ni ninguna otra funcion escribe esas dos columnas en el camino de import, en ninguna de las dos bases. Eso es MOVILBA-366 y sigue abierto; este item NO lo resuelve. LADO APP, tres defectos distintos en el campo bodyModel: 1. src/lib/rutap-history-fields.ts:107-111 lo declara sin 'face', asi que HistoryPeriodContent.tsx nunca lo pinta como cara. 2. No esta en RUTAP_HISTORY_FIELDS (los 39 del contrato de MOVILBA-97), asi que no tiene raw_*, no entra al diff del servidor, no sale en el PDF y no lo ve el clasificador de subtipo - aunque rutap-modification-subtype.ts:17 y :85 igual le reservan una entrada 'CARROCERIA' que duplica la de 'body'. 3. Su valor SI se calcula: rutap-history-values.ts recorre HISTORY_FIELDS entero sin mirar face. Trabajo muerto. Y cuando el periodo es de app, rutap-history-presentation.ts:41-44 lo mete igual al set del diff de pantalla, o sea puede emitir un cambio 'Modelo de carroceria' que duplica el de 'Carroceria'. ENTREGABLE, en este orden: (a) sacar bodyModel de rutap-history-fields.ts y de las dos entradas de rutap-modification-subtype.ts; (b) frenar al escritor - src/repositories/vehiculos.ts escribe carroceria_modelo, tiene que dejar de hacerlo antes de que la columna se vaya; (c) recien ahi la migracion que borra rutap.vehiculo_historial_normalizado.carroceria_modelo en DEV, con la de PROD encolada en docs/migrations/pending-prod-changes.md. Es portar-y-borrar, no convivencia. CUIDADO: 14 vistas referencian esas columnas segun el censo de db02. Se enumeran con pg_depend ANTES de tocar nada y nunca se usa CASCADE. NO EJERCITADO: si algun consumidor fuera de la app (api-external, un reporte, un export) lee carroceria_modelo de la tabla ancha. Eso se mide antes de (c).

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 4w ago
  • coder03-mba-l-cc assigned · 2w ago
    db03-mba-l-cc
  • coder03-mba-l-cc assigned · 2w ago
    db04-mba-l-ca
  • coder03-mba-l-cc assigned · 1w ago
    db03-mba-l-cc / db
  • db03-mba-l-cc note · 1w ago
    MEASURED db03 2026-10-09 (db-lane NOT-EXERCISED check, SELECT-only): zero live consumers of the raw carroceria_modelo column anywhere. pg_depend column-level census on PROD (narrower than db02's table-level '14 vistas'): 4 direct dependents, all passing the raw column through verbatim - rutap.v_vehiculo_historial_normalizado_fuente_actual -> rutap.v_vehiculo_historial_actual -> public.v_vehiculos_ciclo_actual / public.v_vehiculos_export_periodo_actual. The other bodyModel-emitting consumer, src/repositories/rutap-historial.ts:164, does NOT read this column at all - it joins the carrocerias catalog by h.carroceria_id (the kept FK) and reads THAT table's carroceria_modelo, confirmed via the actual JOIN at :173. api-external/{nodejs-api,php-api} (out-of-repo, read-only) do reference a carroceria_modelo JSON key in sync.php/dev_sync.php, but no caller of that /sync endpoint exists anywhere in src/ - dead/unreachable from the current app. Published /api/v1/exports contract: zero hits. Steps (a) and (b) from the ticket's own entregable are STILL NOT DONE in app code - verified live 2026-10-09: bodyModel is still in rutap-history-fields.ts and both rutap-modification-subtype.ts entries; columnasDesdeFicha() in src/repositories/vehiculos.ts still selects ca.carroceria_modelo and every historial insert spreads it in via ...desdeFicha. Drafted (not run) docs/migrations/2026-10-09-movilba-468-drop-carroceria_modelo-vehiculo-historial-DEV.sql with a hard-stop guard - blocked on (a)/(b) landing in coder-lane first, sequence matters (portar y borrar, no convivencia). Redirecting (a)/(b) to coder-lane; db-lane resumes with the DROP+CASCADE-free multi-view migration once those ship.
  • audit-mba-l-cc audit-finding · 1w ago
    audit-mba-l-cc 2026-10-09. PASS. Author coder03-mba-l-cc. Pins: rutap-history-fields.ts 439423fb, rutap-modification-subtype.ts 9c8fec2f, rutap-history-diff.ts 19b943fc, rutap-historial.ts c5c66f54, vehiculos.ts 3933bcd9. ## Diff read, per file bodyModel removed as a display/diff concept cleanly: field def, display order, field-union type, FIELD_TO_GROUP map, catalog object + jsonb_build_object, all five sites touched match the claim exactly. columnasDesdeFicha() drops carroceriaModelo select + type. ## Independently checked, not taken on word grep for bodyModel/carroceriaModelo/carroceria_modelo across src/ and tools/ (excluding tests): zero stray references to the removed concept. The remaining carroceriaModelo hits are all the UNRELATED carrocerias catalog table's own live field (brand+model CRUD, src/repositories/carrocerias.ts, src/services/carrocerias.ts) - correctly out of this diff's scope, not touched. Confirmed no caller reads .carroceriaModelo off columnasDesdeFicha()'s result (grep on its 4 call sites). ## Gates, run fresh typecheck rc=0. test:source 68/68 pass. ## NOT EXERCISED No live ficha/historial render exercised (display-only confirmed by type/grep, not by opening a page). The gated DROP migration (docs/migrations/2026-10-09-movilba-468-drop-carroceria_modelo-vehiculo-historial-DEV.sql, untracked) is a separate DB artifact, not reviewed here - db03's leg, own gate.
  • audit-mba-l-cc audited · 1w ago
    audit pass: Diff read per-file, cross-repo grep for stray references, gates run fresh
    payload
    {"scope":"Diff read per-file, cross-repo grep for stray references, gates run fresh","outcome":"pass","evidence":"5 pins confirmed, typecheck rc=0, test:source 68/0, zero stray bodyModel/carroceriaModelo references outside unrelated carrocerias catalog","reportRef":null}
  • coder03-mba-l-cc completed · 1w ago
    App-code (a)+(b) shipped: dev 70f0b96a, prod c949595c, both patch 239. bodyModel removed as display/diff concept (duplicate of body/brand); columnasDesdeFicha() stopped writing dead raw carroceria_modelo. Audit PASSed. DROP migration (db-lane's own gate) now unblocked - DMing db03.
  • db03-mba-l-cc blocked · 1w ago
    DROP rehearsed on DEV, caught by Postgres's own dependency check before anything committed (clean ROLLBACK) - original pg_depend column-level census only found 4 direct dependents, missing 13 transitive ones because a base-table column-level search can't see views-on-views (v_vehiculo_historial_normalizado_fuente_actual -> v_vehiculo_historial -> 9 more, plus agents.v_vehiculo_lookup, v_vehiculos_detalle, v_vehiculos_api_public, v_vehiculos_export). Of those 13, only 4 (v_vehiculos_detalle, v_vehiculos_api_public, v_vehiculos_export, agents.v_vehiculo_lookup) actually read carroceria_modelo; the other 9 must still be dropped+recreated in dependency order because DROP VIEW cascades on the whole view, not per-column. Chain reaches v_vehiculos_api_public/v_api_status (public-facing) and the agents schema - too large to improvise under this pass. Need to capture all 14 view defs fresh, verify dependency order, before a real attempt. Also discovered a 5th DEV-only leaf (agents.v_rutap_historial_carroceria_normalizacion_invariante) not present on PROD - handled, drop-only, no recreate.
  • db03-mba-l-cc note · 1w ago
    Decision (coder03, 2026-10-08T05:32 UTC): (b) - ship as-is, defer physical DROP. Writer already stopped, zero functional risk leaving column present. Deferred-drop item filed for the bundled 32-view regen.
  • db03-mba-l-cc unblocked · 1w ago
    cleared: DROP rehearsed on DEV, caught by Postgres's own dependency check before anything committed (clean ROLLBACK) - original pg_depend column-level census only found 4 direct dependents, missing 13 transitive ones because a base-table column-level search can't see views-on-views (v_vehiculo_historial_normalizado_fuente_actual -> v_vehiculo_historial -> 9 more, plus agents.v_vehiculo_lookup, v_vehiculos_detalle, v_vehiculos_api_public, v_vehiculos_export). Of those 13, only 4 (v_vehiculos_detalle, v_vehiculos_api_public, v_vehiculos_export, agents.v_vehiculo_lookup) actually read carroceria_modelo; the other 9 must still be dropped+recreated in dependency order because DROP VIEW cascades on the whole view, not per-column. Chain reaches v_vehiculos_api_public/v_api_status (public-facing) and the agents schema - too large to improvise under this pass. Need to capture all 14 view defs fresh, verify dependency order, before a real attempt. Also discovered a 5th DEV-only leaf (agents.v_rutap_historial_carroceria_normalizacion_invariante) not present on PROD - handled, drop-only, no recreate.
  • db03-mba-l-cc completed · 1w ago
chore
4w ago by wi-cli-venus
1w ago
2026-10-09 05:32