fix(catalogo): los alias compartidos ya no cruzan a una empresa al azar
Investigando por qué el filtro de Tickets muestra "CAABSA" (que no existe en la hoja de osTicket) salió que el catálogo comparte aliases entre empresas y el matcher los resolvía de forma arbitraria:
CAABSA -> alias de Constructora, Infraestructura y Desarrolladora Yucateca (3 empresas) CAABSA DESARROLLOS -> nombre de la 285 y alias de HERAM (286) HERAM -> nombre de la 286 y alias de la 285 FUNDACIÓN -> alias de la 309 y nombre de la 310
build_canon_index indexaba nombre_comercial, razones_sociales y aliases en un
solo pase y conservaba la PRIMERA entrada. Como el SELECT del catálogo no lleva
ORDER BY, el ganador lo decidía Postgres y podía cambiar entre reinicios: 4
nombres resolvían a una empresa distinta con sólo invertir el orden de las filas.
'HERAM' cruzaba a 'CAABSA DESARROLLOS' — mal, y en silencio.
El fix aplica a los aliases la misma regla de "inequívoco" que el archivo ya
usaba para empresa_razon_social, en dos pases:
-
nombre_comercialprimero y sin condición: es la identidad de la empresa y le gana al alias de otra. Esto vuelve deterministas los tres cruzados. - aliases/razones del grupo sólo si apuntan a UNA empresa. Si son ambiguos
siguen votando en el índice de forma legal (el voto es lo que detecta la
ambigüedad) pero no entran a
by_norm.
Resultado contra el catálogo real:
- no-determinismo por orden de filas: 4 nombres -> 0
- HERAM : 'CAABSA DESARROLLOS' -> 'HERAM' (se corrige)
- FUNDACIÓN : 'Fundación Grupo Caabsa' -> 'FUNDACIÓN' (cambia)
- CAABSA : 'Caabsa Constructora' -> sin catálogo (era arbitrario)
- CAABSA DESARROLLOS : igual, ahora determinista
- los 14 valores crudos de Tickets resuelven idéntico: sin impacto en la vista.
'CAABSA' pasa a no cruzar. Es lo correcto: es ambiguo de verdad, y el fallback ("sin catálogo") es visible y curable con un alias en /admin — mejor que un dato falso silencioso. Mismo criterio que el comentario ya existente sobre 'Corporativo'.
Tests: 12 casos nuevos con el catálogo mockeado (sin Postgres), cubriendo el fix, el determinismo ante el orden de filas y el comportamiento previo que no debe romperse. Los 3 fallos de test_juicios_api.py son preexistentes y ajenos a este cambio (verificado con el fix stasheado).
Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com