basquetWi + New ticket
movilba MOVILBA-791

Filtro Empresa en /vehiculos muestra entidades cesadas sin soft-delete (17 de Agosto inconsistente con otras)

Done normal cmcoder04-mba-l-ca

Eugenia reporte via Elazar (2026-10-09 12:31-12:32 ART): el filtro 'Empresa' de /vehiculos (type=allEntities, src/app/vehiculos/page.tsx:127) muestra '17 DE AGOSTO S.A.' (id=54) aunque dejo de operar hace ~1 mes, mientras otras entidades tambien inactivas no aparecen - inconsistente. Investigado (PROD y DEV, solo lectura): - entidades NO tiene columna vigente/activa - solo borrado_en (soft-delete). allEntities (v_ui_todas_entidades) filtra unicamente WHERE borrado_en IS NULL; no mira vehiculos ni lineas vigentes. - Entidad 54 (17 DE AGOSTO): borrado_en NULL, 17 vehiculos todos con fecha_baja (0 vigentes). 4 asignaciones a lineas, las 4 con borrado_en seteado (todas de baja). - Entidad 53 (GENERAL TOMAS GUIDO): mismo patron - borrado_en NULL, 11 vehiculos, 0 vigentes. Por la misma logica DEBERIA aparecer tambien en el filtro Empresa, no reportado por Eugenia pero consistente con la causa. - Entidad 64 (M.O.D.O.): borrado_en SETEADO (2026-08-14) tras cesar - por eso NO aparece en allEntities. Confirma el patron: cuando se soft-deletea la entidad al cesar, el filtro la excluye; cuando no se soft-deletea (54 y presumiblemente 53), queda visible indefinidamente. - entitiesWithActiveLines (el otro dropdown de entidad, usado solo en vehiculos/agregar/colectivo) SI excluye correctamente a 53/54/64 en ambas bases - no es el filtro afectado. ROOT CAUSE: no existe un estado explicito 'entidad vigente/cesada'. El unico derivado disponible es borrado_en, y marcarlo al cesar operaciones es un paso manual aplicado de forma inconsistente (64 lo tiene, 53 y 54 no). El filtro Empresa de /vehiculos no filtra por actividad en absoluto - muestra toda entidad no borrada, cesada o no. No es un bug de codigo (allEntities hace lo que dice: todas las entidades no borradas). Es una brecha de proceso/dato: falta decidir si (a) se soft-deletea la entidad cuando cesa, (b) se agrega un filtro derivado de vehiculos/lineas vigentes al dropdown Empresa, o (c) se documenta que el filtro es deliberadamente 'todas las entidades alguna vez registradas'. Decision para Elazar.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • audit-mba-l-cc created · 1w ago
  • coder03-mba-l-cc note · 1w ago
    Elazar decision 2026-10-09 (CLI): (a) soft-delete entidades 54 (17 de Agosto) and 53 (Guido) now that they've ceased. Requirement: historial de cambios and any other surface showing a soft-deleted entidad's name must tag it '(Borrado)' - never drop/blank the name, since history must still show who it was. Check every surface that resolves entidad name (ficha, historial, PDF, exports) for whether it already handles borrado_en or would silently disappear/blank the name.
  • coder03-mba-l-cc assigned · 1w ago
    coder04-mba-l-ca / coder
  • coder04-mba-l-ca statusChanged · 1w ago
    Starting the requested surface census before the approved soft-delete: enumerate entidad-name resolution in ficha, history, PDF and exports; classify preservation/tagging vs blank/drop on soft-deleted entidades. No data writes until that census is complete.
  • coder03-mba-l-cc note · 1w ago
    Elazar clarification (CLI): the (Borrado) tag applies ONLY to historial/display surfaces showing past records (historial de cambios, ficha history, etc) - a borrado entidad must NEVER appear in any selection pulldown/dropdown used to pick an entidad (filter dropdowns, assignment forms). Pulldowns exclude it outright; history surfaces show it tagged.
  • coder04-mba-l-ca note · 1w ago
    --help
  • coder04-mba-l-ca note · 1w ago
    Read-only code census (2026-10-09): current/history name resolution is inconsistent. History: v_vehiculo_historial and v_vehiculos_detalle.historial (schema.ts 2240, 2347) join entidades by ID without borrado_en and preserve the bare name, no '(Borrado)'; getRutapHistorialByChain (src/repositories/rutap-historial.ts:154) and GET /api/vehiculos/[id]/entidad/history (:41) do likewise. The /api/reportes/vehiculos-historico query joins entidade_historica without filter and emits bare entidad_historica.nombre as identificadorEmpresa (:28,86), feeding CSV/XLSX; no tag. Ficha current entity comes through v_vehiculos_detalle/v_vehiculos_list, raw e.nombre with no tag; embedded history raw too. PDF data from same detail DTO/SSOT query path; no tag in SQL projections. Current XLSX/CSV + external FISCALIZACION API use v_vehiculos_export (), raw/no tag; lineas and line views also return bare names. Blank/drop risks: parque-movil.ts:172 filters e.borrado_en IS NULL on entity label join (API entity becomes NULL); :395 and :570 do same for installation/driver assignment JSON empresa_nombre. Selection surfaces correctly exclude deleted entities: v_ui_todas_entidades WHERE borrado_en IS NULL; v_ramales_lineas also filters entity; this is intentional and should remain. v_linea_detalle/v_linea_entidad_historial and v_vehiculos_lineas_entidades preserve names but do not tag. No code/data writes made. Census points to shared SQL view projections plus parque-movil label joins as likely fix scope; next step is to tag soft-deleted entity labels while retaining names on record/display/export surfaces, keep dropdown exclusion, then audit before the already-authorized entity soft-delete. Census is code-based; no HTTP/PDF/export runtime exercised.
  • coder04-mba-l-ca note · 1w ago
    Read-only code census (2026-10-09): name resolution is inconsistent. - History: v_vehiculo_historial and v_vehiculos_detalle.historial (schema.ts declarations around 2240/2347) join entidades by ID without borrado_en, preserving the bare name but adding no "(Borrado)". getRutapHistorialByChain (src/repositories/rutap-historial.ts:154) and GET /api/vehiculos/[id]/entidad/history (:41) also preserve bare names. The /api/reportes/vehiculos-historico query (:28,:86) emits raw entidad_historica.nombre as identificadorEmpresa into CSV/XLSX. - Ficha current entity comes from v_vehiculos_detalle/v_vehiculos_list, with raw e.nombre and no tag; nested history is raw too. PDF uses the same detail DTO/SSOT query path and contains no suffix logic. - Current CSV/XLSX and the external FISCALIZACION API use v_vehiculos_export (e.nombre AS entidad), raw/no tag. /api/export lineas and line views likewise return bare names. v_linea_detalle, v_linea_entidad_historial and v_vehiculos_lineas_entidades preserve names but do not tag. - Blank/drop risks: src/repositories/parque-movil.ts:172 filters e.borrado_en IS NULL on the vehicle entity join, yielding NULL for a retired entity; :395 and :570 likewise filter ent.borrado_en IS NULL in installation/driver-assignment JSON label joins. - Selection surfaces correctly exclude deleted entities: v_ui_todas_entidades WHERE borrado_en IS NULL; v_ramales_lineas also excludes deleted entities. Keep this behavior. No code/data writes made. Code-based census only; no HTTP/PDF/export runtime exercised. Likely implementation scope: tag soft-deleted entity labels in record/display/export surfaces, preserve labels, retain dropdown exclusion. Then audit before the authorized data soft-delete.
  • coder04-mba-l-ca progress · 1w ago
    Implementation follows the census. Record/display/export labels now append '(Borrado)' while preserving name and ID: vehicle list/detail (including embedded history and chain), RUTAP history API/query, entidad-history API, historical report CSV/XLSX, vehicle export CSV/XLSX and external FISCALIZACION API, Parque vehicle/installation/driver-assignment JSON, line outputs/history, and entity-person associations. Selection views remain unchanged and continue excluding soft-deleted entities. Code changes are in src/lib/entity-label.ts (+ unit test), src/repositories/vehiculos.ts, src/repositories/rutap-historial.ts, src/actions/vehiculos.ts, src/actions/lineas.ts, src/repositories/lineas.ts, src/repositories/asociaciones.ts, src/repositories/parque-movil.ts, src/lib/exports/vehiculos.ts, src/app/api/vehiculos/[id]/entidad/history/route.ts, src/app/api/reportes/vehiculos-historico/route.ts, and src/app/api/export/route.ts. No DB writes, DDL, or gates run. Code census only; no HTTP, PDF, or export runtime exercised. Please audit these exact changed files before the authorized soft-delete of entities 54/53.
  • coder04-mba-l-ca progress · 1w ago
    Implementation complete after read-only census: preserves retired entity names with '(Borrado)' across vehicle history/ficha/PDF/CSV/XLSX/API export and related line, Parque, driver-history, association, and installation-line record labels. Entity pickers remain active-only. Exact changed-file pins will be sent to audit; no tests/gates, HTTP/PDF/export runtime, or DB writes executed. Soft-delete of entidades 54/53 remains separate and waits for audit PASS.
  • coder04-mba-l-ca progress · 1w ago
    PM clarification (2026-10-09 12:49 ART): append '(Borrado)' only on record/history display surfaces; deleted entities must be completely absent from entity-selection dropdowns and assignment forms. Read-only source check: /vehiculos allEntities uses /api/dropdowns -> v_ui_todas_entidades (WHERE borrado_en IS NULL); API and server-action allEntities share that view; association/line/driver assignment entity pickers use active-only vEntidades or /api/entidades -> v_admin_entidades_search (WHERE e.borrado_en IS NULL). No selector was changed to include/tag deleted entities. Line picker metadata remains a line option, not an entity option. Census confirmation only; no DB writes or gates.
  • audit-mba-l-cc audit-finding · 1w ago
    13/14 files sound (entity-label.ts/test, choferes.ts, instalaciones.ts, lineas.ts action, vehiculos.ts action, export/route.ts, reportes/vehiculos-historico/route.ts, vehiculos/[id]/entidad/history/route.ts, exports/vehiculos.ts, asociaciones.ts, lineas.ts repo, vehiculos.ts repo - all 14/14 SHA-256 pins exact). vehiculos.ts repo cross-checked against v_vehiculos_hist_ultimo/v_vehiculos_export source to rule out a resolver mismatch between the override and the original value - confirmed same join path, no substitution risk. DEFECT in src/repositories/parque-movil.ts: the diff removes 'AND e.borrado_en IS NULL' from entidadJoin in findParqueVehiculos (line ~171) and 'AND ent.borrado_en IS NULL' from the entidad join in findParqueInstalaciones (~386) to let the CASE-tag resolve the deleted entity's name. This also changes what the join SELECTS for the id columns: 'e.id AS entidad_id' in findParqueVehiculos and 'empresa_id', ent.id in findParqueInstalaciones now return the soft-deleted entidad's real id instead of NULL. This breaks a DOCUMENTED, PUBLISHED contract clause (docs/reference/parque-movil-api/data-contract.md:174-177): 'Ids de padres borrados. Cuando un padre (entidad, linea, opcion de catalogo) esta borrado, la API no publica su id: el campo sale null junto con su etiqueta... un id presente en la respuesta siempre corresponde a una fila activa.' /api/v1/parque is the external SOTAMIT/FISCALIZACION contract per existing code comments (parque-movil.ts top-of-function comment, now rewritten, previously said exactly this: 'if the parent entidad is soft-deleted the join yields NULL, so the API does not publish the id of a deleted parent (active-only chain, §3)'). findParqueChoferes is NOT affected the same way - its entidad_id comes from lea.entidad_id (v_lineas_entidad_actual), not ent.id, so that id was never gated by the removed filter; only its name tag changed there, correctly. Fix needed: keep entidad_id/empresa_id null for a soft-deleted parent (restore the join-level NULL for the id), while resolving the tagged NAME from a source that doesn't gate the id - e.g. select the name via a second unfiltered join/subquery, or compute the CASE tag against a joined-but-unfiltered alias while still nulling the id column explicitly in the SELECT list when borrado_en is set.
  • audit-mba-l-cc audited · 1w ago
    audit fail: all 14 changed+new files reviewed in full diff against documented API contract and resolver sources
    payload
    {"scope":"all 14 changed+new files reviewed in full diff against documented API contract and resolver sources","outcome":"fail","evidence":"docs/reference/parque-movil-api/data-contract.md:174-177 requires null id for soft-deleted parent; parque-movil.ts findParqueVehiculos/findParqueInstalaciones now return the real id by removing the join-level borrado_en filter","reportRef":null}
  • coder03-mba-l-cc note · 1w ago
    audit FAIL 2026-10-09 13:04: fix ungates entidad_id/empresa_id for soft-deleted parents, breaking published contract (data-contract.md:174-177 - 'un id presente en la respuesta siempre corresponde a una fila activa'). Fix: keep id null for soft-deleted parent, resolve the (Borrado)-tagged name separately without ungating the id. Back to coder04.
  • coder04-mba-l-ca progress · 1w ago
    Audit FAIL corrected in Parque queries. src/repositories/parque-movil.ts now keeps active-only entidad aliases for entidad_id/empresa_id and related fields, while a separate unfiltered label-only alias appends '(Borrado)'. Installation filters by entity now require an active row, preserving the documented 'deleted parent IDs are null and do not match filters' contract. Driver-assignment JSON likewise emits ent.id (active-only/null for deleted) and resolves tagged names through a second label alias. Only parque-movil.ts changed after prior full pin set; new SHA-256 18e3c5be6fa7a441dfc40daf182cc40844c76111c554e4c68828773f076daeeb. No gates run.
  • coder04-mba-l-ca progress · 1w ago
    Correction to immediately preceding note: measured final SHA-256 of src/repositories/parque-movil.ts is 0d15b5505ab5b2ec9cb1350d6b0e0798907225d22957746e50107664ba2abb13 (not 18e3c5be...; that was measured before the driver-ID correction). This is the pin to review.
  • audit-mba-l-cc audit-finding · 1w ago
    parque-movil.ts fix (pin 0d15b550) reviewed and CORRECT: entidadJoin/ent active-only joins restored for IDs, new unfiltered e_label/ent_label aliases supply only the tagged name. findParqueInstalaciones entidadId filter now EXISTS-checks active_entity, matching the contract's 'filtros por ese id tampoco lo encuentran' clause - a latent gap fixed as a bonus. findParqueChoferes entidad_id switched from ungated lea.entidad_id to gated ent.id, fixing a pre-existing inconsistency with the same contract clause. Parque defect resolved. BUT pnpm typecheck now fails with 4 pre-existing errors, not introduced by this diff: asociaciones.ts:167,227 (entidadNombre now string|null|undefined vs AsociacionEntidadPersona wanting string|undefined - the CASE-tag sql<string|null> return type doesn't match the DTO's optional-not-nullable field) and vehiculos.ts:354,631 (number|undefined not assignable to number; VehiculoDto|undefined vs VehiculoDto|null - likely from this same batch's earlier getById/colectivo changes). Gate blocks the push regardless of origin.
  • audit-mba-l-cc audited · 1w ago
    audit fail: parque-movil.ts contract fix reviewed in full; pnpm typecheck run
    payload
    {"scope":"parque-movil.ts contract fix reviewed in full; pnpm typecheck run","outcome":"fail","evidence":"parque-movil.ts fix is correct (join/id separation verified by hand); typecheck fails with 4 errors at asociaciones.ts:167,227 and vehiculos.ts:354,631 - rc!=0 blocks any ship path","reportRef":null}
  • coder03-mba-l-cc note · 1w ago
    audit round 2 FAIL 13:07: parque-movil.ts contract fix itself is CORRECT (ids gated active-only, label aliases for tag, plus bonus fixes on installation/choferes gating). Still FAIL on typecheck: asociaciones.ts:167,227 (entidadNombre string|null|undefined vs AsociacionEntidadPersona wants string|undefined) and vehiculos.ts:354,631 (number|undefined->number; VehiculoDto|undefined vs |null). Fix DTO/return types, re-send.
  • coder04-mba-l-ca progress · 1w ago
    Audit typecheck follow-up: narrowed historial event entidadId through a local unknown value before adding it to Set<number>; guarded the single-row helper result with ?? response to preserve the repository's VehiculoDto|null contract; normalized nullable entidadNombre to undefined in create/update response objects. Candidate SHA-256: src/repositories/vehiculos.ts c7c47c6abe5eae550567db58fea34041d63442fff3c3c07b065535eabb3ee3ac; src/repositories/asociaciones.ts a955f765d19127f157e0ee914fe0394393128ac80c5b4a7885d1acbd1e72cb42; src/repositories/parque-movil.ts 0d15b5505ab5b2ec9cb1350d6b0e0798907225d22957746e50107664ba2abb13. No gates run; audit to rerun whole-tree typecheck and relevant gates.
  • audit-mba-l-cc audit-finding · 1w ago
    typecheck fix confirmed CORRECT (pins vehiculos.ts c7c47c6a, asociaciones.ts a955f765, parque-movil.ts 0d15b550 - all exact). pnpm typecheck rc=0. Two NEW gate failures, both caused by this diff, not pre-existing: 1) test:source FAILS: src/lib/rutap-history-values.test.ts:139 asserts the literal regex /entidad_historica\.nombre\s+AS "identificadorEmpresa"/ against the vehiculos-historico/route.ts source (MOVILBA-608 follow-up guard: every catalog-sourced field must resolve ONLY from its catalog column, never a raw_* fallback). This diff wrapped that projection in a CASE/Borrado-tag expression, so the literal match no longer applies - test doesn't know about the new, still-correct form. Fix: update the regex at line 139 to match the new CASE expression (confirm it still anchors on entidad_historica.nombre/entidad_historica.borrado_en, not a raw_* column, to preserve the guard's actual intent). 2) test:tools FAILS (3 tests in tools/tests/colectivo-expediente.test.cjs, e.g. line 330/345): 'Unexpected dependency @/lib/entity-label' from src/actions/vehiculos.ts:44 - this harness allowlists the dependencies vehiculos.ts's action module may pull in, and the new entity-label import isn't on it. Fix: add '@/lib/entity-label' to that allowlist in colectivo-expediente.test.cjs (or confirm with whoever owns that harness why the restriction exists before loosening it). Re-send after both are fixed; re-run full gates before next PASS.
  • audit-mba-l-cc audited · 1w ago
    audit fail: typecheck rerun, full test:source (73) and test:tools suites run
    payload
    {"scope":"typecheck rerun, full test:source (73) and test:tools suites run","outcome":"fail","evidence":"typecheck rc=0 confirmed; test:source 72/73 - rutap-history-values.test.ts:139 literal regex stale against new CASE projection; test:tools 3 failures in colectivo-expediente.test.cjs - entity-label import not in vehiculos.ts action dependency allowlist","reportRef":null}
  • coder03-mba-l-cc note · 1w ago
    audit round 3 FAIL 13:10: typecheck fix correct, rc=0, but 2 regressions - (1) test:source rutap-history-values.test.ts:139 literal regex for entidad_historica.nombre AS identificadorEmpresa (MOVILBA-608 guard) broke on the CASE/Borrado wrap, update regex to new form; (2) test:tools colectivo-expediente.test.cjs 3 failures, actions/vehiculos.ts:44 imports @/lib/entity-label not in that harness's allowlist for vehiculos.ts's action-module deps, add it. Fix both, re-send pins.
  • coder04-mba-l-ca progress · 1w ago
    Audit round 3 follow-up: updated rutap-history-values.test.ts MOVILBA-608 projection guard to recognize the intentional CASE that appends (Borrado) while retaining entidad_historica.nombre as its source; added @/lib/entity-label to the dependencies allowed by colectivo-expediente.test.cjs harness. Previous three implementation pins remain unchanged. Updated test pins: rutap-history-values.test.ts 3a9df3b46264a8b38fcd7a627ccd62597141ac97b582ec56937ee646c8fb000c; tools/tests/colectivo-expediente.test.cjs 3fe5935e36722e1bfdc5eac725e198426d1bd6d370967595c474f649b934fda7. No gates run before audit handoff per repository workflow.
  • audit-mba-l-cc audit-finding · 1w ago
    Round 3: colectivo-expediente.test.cjs allowlist fix CORRECT (pin 3fe5935e), entity-label added, verified. rutap-history-values.test.ts fix (pin 3a9df3b4) is still BROKEN - new regex typo. Actual source (vehiculos-historico/route.ts:30): ELSE entidad_historica.nombre || ' (Borrado)' END - note the SPACE before '(Borrado)'. New regex at line 139: '\(Borrado\)' with NO space before the escaped paren. Ran the test directly: still fails, same AssertionError, same unmatched regex. Fix: add the space - entidad_historica\.nombre \|\| ' \(Borrado\)' (or \s+\(Borrado\) to tolerate whitespace).
  • audit-mba-l-cc audited · 1w ago
    audit fail: pnpm exec tsx --test on the updated rutap-history-values.test.ts; read diff of both test fixes
    payload
    {"scope":"pnpm exec tsx --test on the updated rutap-history-values.test.ts; read diff of both test fixes","outcome":"fail","evidence":"test still fails identical AssertionError; regex is missing the literal space before '(Borrado)' that the actual source has","reportRef":null}
  • coder04-mba-l-ca progress · 1w ago
    Audit spacing correction: rutap-history-values.test.ts regex now requires whitespace before the literal (Borrado) suffix, matching route.ts output. Updated test SHA-256 f5643161cb5ce2531c6060c923a145aef451781fea0c92087f57e661de12639c. Implementation pins unchanged: vehiculos.ts c7c47c6abe5eae550567db58fea34041d63442fff3c3c07b065535eabb3ee3ac; asociaciones.ts a955f765d19127f157e0ee914fe0394393128ac80c5b4a7885d1acbd1e72cb42; parque-movil.ts 0d15b5505ab5b2ec9cb1350d6b0e0798907225d22957746e50107664ba2abb13; colectivo-expediente.test.cjs 3fe5935e36722e1bfdc5eac725e198426d1bd6d370967595c474f649b934fda7. No gates run; audit to recheck exact bytes.
  • audit-mba-l-cc audit-finding · 1w ago
    Round 4: rutap-history-values.test.ts (pin f5643161) regex fixed, ran it directly - passes now. Full gate run on final state (16 files total: 14 original + rutap-history-values.test.ts + colectivo-expediente.test.cjs, all pins verified exact across every round): pnpm typecheck rc=0; pnpm test:source 73/73 (71 baseline + 2 new entity-label.test.ts cases); pnpm test:tools 120/120. All green. Prior findings closed: parque-movil.ts id/name join separation verified correct, bonus fixes (installation entidadId filter now EXISTS-checks active parent, choferes entidad_id now gated) confirmed sound. No defects remaining.
  • audit-mba-l-cc audited · 1w ago
    audit pass: all 16 changed/new files across 4 rounds; full gate suite run on final pins
    payload
    {"scope":"all 16 changed/new files across 4 rounds; full gate suite run on final pins","outcome":"pass","evidence":"typecheck rc=0; test:source 73/73; test:tools 120/120; parque-movil.ts contract fix independently verified against docs/reference/parque-movil-api/data-contract.md:174-177; all SHA-256 pins exact at every round","reportRef":null}
  • coder03-mba-l-cc audited · 1w ago
    audit pass: 16 files across 4 rounds: parque-movil.ts contract fix, asociaciones.ts/vehiculos.ts DTO types, rutap-history-values.test.ts regex, colectivo-expediente.test.cjs allowlist
    payload
    {"scope":"16 files across 4 rounds: parque-movil.ts contract fix, asociaciones.ts/vehiculos.ts DTO types, rutap-history-values.test.ts regex, colectivo-expediente.test.cjs allowlist","outcome":"pass","evidence":"typecheck rc=0, test:source 73/73, test:tools 120/120","reportRef":null}
  • coder03-mba-l-cc note · 1w ago
    Shipped: dev commit 042b502e v5.6.247, prod merge 297e8c65 (e20ca171..297e8c65), both health-verified patch 247. POD stale at 239, manual/separate, expected. Entidades 54/53 soft-delete authorized to proceed now.
  • coder03-mba-l-cc completed · 1w ago
    completed
bug
1w ago by audit-mba-l-cc
1w ago
2026-10-09 16:20