Tractores
Generada 2026-08-13. Actualizada 2026-08-13 (misma fecha, sesión posterior) con exploración interactiva completa en vivo (kimi webbridge: filtros, panel de detalle, sub-reportes) — se encontraron 3 bugs reproducibles, ver sección “Bugs / hallazgos encontrados”. Fuente: exploración de código de controlgmg-v2 + observación manual del navegador (QA). Comparar contra
remolques.md— Tractores es casi un gemelo estructural de Remolques, pero con una diferencia importante en la llave de identidad usada por el sync AS400 (ver abajo).
Backend
Sección titulada «Backend»- Modelo:
App\Core\Unit(app/Core/Unit.php), tablaunits. En UI/negocio se llama “Tractor” (getModelTitleAttribute()devuelve literalmente'Tractor';getActionUrlAttribute()apunta a/tractores?unit_id=...). - Fillable clave:
code, name, fleet_code, fleet_name, user_id, unit_brand_id, unit_model_id, unit_engine_id. - Llave de identidad para sync AS400:
(units.code, company.code)— verUnit::createOrFindFromAS400(). No incluye ningún campo tipo “owner”/propietario (a diferencia de Trailer, que usa(company_id, code, trailer_owner_id)). - Estado/situación: vive en relación
last_movement(App\Core\Unit\UnitLastMovement, hasOne), que a su vez referenciaunit_situation_id(FK aUnitSituation) ymovement_at.current_situation()es unhasOneThroughsobreUnitLastMovement.hidden(baja AS400, boolean) es distinto dedeleted_at(soft delete de Eloquent). - Prioridad: columna
priorityenunits(se resetea anullcuando cambia la situación, versyncLastMovement). - Sync status: vía
SynchronizableTrait(tabla polimórficasynchronizations), igual patrón que Trailer. - Historial de movimientos:
App\Core\Unit\UnitMovementHistory(unit_movement_history()hasMany), análogo aTrailerMovementHistory. Cada cambio de situación real crea una fila y cierra (finished_at) la anterior. getModule()devuelveModule::tractor— el módulo de negocio para reglas/eventos se llama “tractor” internamente, aunque el modelo Eloquent esUnit.
Sync con AS400
Sección titulada «Sync con AS400»- No comparte el bug GMG-3084. La causa raíz de GMG-3084 en Trailer es que
firstOrCreateusa una llave compuesta que incluyetrailer_owner_id(propietario), y un cambio de propietario reportado por AS400 hace que Eloquent no encuentre la fila existente y cree una nueva (“duplicidad por cambio de dueño”). - En
Unit::createOrFindFromAS400(Tractor $tractor)(app/Core/Unit.php:118-134) la búsqueda es:Es decir, soloself::where('units.code', trim($tranum))->whereJoin('company.code', '=', $tractor->traemp)->withTrashed()->first();(code, company)— no hay una dimensión “propietario” mutable en la llave, porque conceptualmente un tractor (unidad propia de GMG) no cambia de “dueño” como sí lo hace un remolque de terceros. Si se encuentra, se actualiza (updateAs400Unit/syncUnitAndTractor); si no, se crea. No hay patrónfirstOrCreatecon llave de 3+ columnas. - Riesgo residual distinto (no confirmado como bug, solo observación de código): si un tractor cambia de
companyen AS400 (traemp), la búsqueda por(code, company_nueva)no encontrará la fila existente (que tienecompany_vieja) ycreateFromAS400creará una fila nueva — un mecanismo de duplicidad potencialmente análogo pero disparado por cambio de empresa, no de propietario. No hay evidencia en el código de que esto ocurra en la práctica (los tractores probablemente no cambian de empresa con frecuencia, al contrario que el propietario de un remolque rentado/subcontratado). Por verificar: no se encontró un ticket equivalente a GMG-3084 para tractores; no se corrió ninguna query de regresión contra la BD. - Sync manual:
GET /units/sync/{unit}→UnitController@sync(ruta enroutes/units/unit.php:9), análogo aGET /units/trailer/sync/{trailer}. - Sync masivo:
UnitSyncService::sync()(app/AS400/Ein00dat/AS400Sync/Unit/UnitSyncService.php), gateado porisVPNConnected()— igual que Trailer, no disparable de forma realista desde el tester. - Conclusión para testing: Tractores usa un patrón de sync estructuralmente más simple/seguro que Remolques (llave de 2 columnas sin dimensión de propietario), por lo que no debería sufrir el mismo tipo de duplicidad que GMG-3084 bajo el mecanismo actual. No se descarta un bug análogo por cambio de compañía, pero no hay evidencia ni reporte que lo confirme — tratar como hipótesis no verificada, no como hallazgo.
Rutas (backend)
Sección titulada «Rutas (backend)»Bajo /units (grupo auth:api + password_expired), archivo routes/units/unit.php:
| Método | Ruta | Acción |
|---|---|---|
| GET | /units, /units/paginated, /units/with-trashed |
listado |
| GET | /units/sync/{unit} |
sync manual de un tractor |
| GET | /units/codes |
catálogo de códigos |
| PUT | /units/executive/{unit} |
Units\UpdateUnitExecutiveController (usuario ejecutivo) |
| POST | /units/{unit}/comment |
comentario |
| GET | /units/{unit}/history, /{unit}/download-history, /{unit}/kilometer-history, /{unit}/arquimedes-kilometer-history |
historiales |
| PUT | /units/{unit}/properties |
propiedades (marca/modelo/motor) |
| POST | /units/{unit}/restore |
restaurar soft-delete |
Reportes/KPI (routes/units/reports.php, prefijo probable /units/report o similar, controller Units\ReportsController):
GET /situations, /situations-units, /situations-chart-info, /situations-histories,
/situations-histories-chart-info, /situations-his-units, /situation-totals, POST /situations-his-units-excel.
No se encontró un archivo tractor.php — el hermano directo de trailer.php es unit.php (nombre del modelo, no
del dominio de negocio), y el reporte de KPIs vive separado en reports.php (compartido conceptualmente con
Situations/SituationHistories, no exclusivo de tractores por nombre de archivo aunque sí por contenido).
Frontend (Vue 2)
Sección titulada «Frontend (Vue 2)»- Ruta
/tractores→resources/js/components/Catalogs/Units/Reports/UnitsReport.vue(guardcan('view-unit-reports'), definido enresources/js/routes.js). Nótese la carpeta:Catalogs/Units/Reports, noUnits/Reports— distinto al patrónTrailer/Reportsde Remolques. UnitRow.vue(misma carpeta) — una fila de la lista: código (unit.code), prioridad, vales (unit.vouchers.length), último movimiento, días transcurridos, situación (unit.last_movement.unit_situation.name), sync-status (<sync-model-status>), descarga de historial. Estructura muy similar aTrailerRow.vue.UnitReportDetail.vue+UnitAs400Data.vue(enCatalogs/Units/) +UnitMovementHistory.vue(Catalogs/Units/Reports/) — panel de detalle expandido, análogo aTrailerReportDetail.vue+TrailerAs400Data.vueTrailerMovementHistory.vue.
- Sub-reportes KPI:
Situations/SituationsKpi.vue,SituationHistories/SituationHistoriesKpi.vue(rutas/tractores/reportes/situacionesy/tractores/reportes/historial-situaciones, guardcan('view-unit-sub-reports')). - Filtros usados en
UnitsReport.vue, verificados en vivo en QA 2026-08-13 (navegación real con kimi webbridge, no solo lectura de código):- Búsqueda global (
Buscar en cualquier campo...). - Checkboxes:
Sin liquidaciones,Sin vales,Con usuario ejecutivo,Alerta por regla de negocio. - Rango de fechas (
Fecha inicial-Fecha final). Flota(select, catálogo confirmado:2 - Autos Utilitarios,3 - Locales MTY,4 - NLD-GDL,6 - NLD-MTY,7 - NLD-MEX,8 - Intermodal MEX,9 - Intermodal GDL).Situaciones(select múltiple, catálogo largo con conteo inline, ej.ACCIDENTADO - 12,CONDUCTOR AUSENTE - 98,BAJA - 41, etc. — decenas de valores).Oficina(select, catálogo confirmado con una métrica numérica junto a cada oficina —3195 - OFC. MTY,588 - OFC. MEX,141 - OFC. NLD,3188 - OFC. GDL,13525 - OFC. AGS,14554 - OFC. SLP; por verificar qué representa el número, probablemente Kms acumulados).Cliente que Paga,Cliente Remitente,Cliente Destinatario(tres selects tipo “Seleccionar”).Prioridad(select) — BUG encontrado, ver sección “Bugs/hallazgos” abajo: nunca muestra opciones.Usuario Ejecutivo(select) — confirmado funcional, catálogo de nombres de usuarios (AGUSTÍN ROBLEDO,Dora Hernandez,Aparicio Gaona, etc.), respaldado porGET /users/by-module/12yGET /users/assigned-to-units(ambos responden con datos).- Botón “borrar” (limpia todos los filtros).
- Búsqueda global (
- Servicio dedicado: no se confirmó el nombre exacto del archivo, pero la app llama
GET /units/paginated?page=N&search=&without_voucher=&without_operation=&active=false&with_position=true&with_operations_and_vouchers=true&with_executive_user=false(paginado, 40 registros por página),GET /units/situation(catálogo de situaciones) yGET /modules/tractor/last-sync(barra de sync). No existe ninguna llamada de red para un catálogo de prioridades — confirmado con captura de tráfico completa en carga de página (ver bug).
Panel de detalle expandido (fila) — verificado en vivo 2026-08-13
Sección titulada «Panel de detalle expandido (fila) — verificado en vivo 2026-08-13»Al hacer click en el chevron de una fila se despliega, en este orden:
- Editores inline (no modal):
Prioridad(select) yUsuario/Ejecutivo(select), lado a lado, justo debajo del resumen de la fila. Cambian el valor directamente sobre esa unidad sin navegar. - AS-400 (columna izquierda): “Última sincronización” + botón de refresh manual, luego:
Posición actual(timestamp +OFC. <código> (Kms: N)),Último movimiento(timestamp),Días transcurridos,Operador(a menudo vacío),Situación,Guía(vacío),Cliente remitente(vacío),Cliente destinatario(vacío),Cliente que paga(vacío),Flota. - Vales (columna derecha): lista de números de vale + fecha (ej.
55913 — agosto 3°, 2026 1:50 PM). - Otros archivos: gestor de documentos por unidad — selector de tipo de documento + botón
“Editar” + fecha del archivo actual, y fila final con selector vacío + botón “Subir Archivo”.
Catálogo de tipos observado (parcial, hay más scrolleando):
Alta control vehicular,avance estetica,Examen prueba de manejo,Factura Cabina,Factura de proveedor,Foto de refacciones,Foto de unidad,Foto engomado emisiones contaminantes,Foto tractor interior cabina,Foto tractor lateral derecho/izquierdo,Foto tractor numero de motor/serie,Foto tractor parte delantera/trasera,Foto Unidad Accidentada,Fotos,Fumigacion,Inspeccion Fisico Mecanica,Orden de compra,PAGO DE SEGURO,Poliza de Seguro,Poliza de Seguro Endoso,Verificacion de Contaminantes,Tarjeta de Circulacion(y al menos uno más truncado como “Requisi…”, por verificar el catálogo completo). - Liquidaciones: lista de números de liquidación + fecha, mismo patrón visual que Vales.
- Historial: sección de movimientos — para TRE21 apareció vacía (sin filas), a pesar de que
la unidad sí tiene
Días transcurridos: 3y unÚltimo movimientoreciente. Por verificar: si “Historial” aquí es historial de comentarios/observaciones (no de situación — ese ya vive en AS-400) y simplemente no hay ninguno para esta unidad, o si es otro punto de fragilidad.
- El icono de “burbuja de comentarios” junto al chevron (badge grande, ej.
997para TRE21,873para TRE57,880para TRE60) no es clickeable como se esperaba — el link asociado (ícono de mapa contiguo) no abre nada visible al hacer click (intento de navegación externa sin efecto observable, posible popup bloqueado). El número no correlaciona con # Vales/# Liquidaciones de esa fila — por verificar qué mide exactamente (hipótesis: contador de comentarios/eventos automáticos de sync, dado el volumen).
Sub-reportes KPI — verificado en vivo 2026-08-13
Sección titulada «Sub-reportes KPI — verificado en vivo 2026-08-13»/tractores/reportes/situaciones
Sección titulada «/tractores/reportes/situaciones»- Filtros: búsqueda global,
Flota, radioCon tractores/Sin tractores/Todos(defaultTodos). - Vista lista (default): tabla
Situación | Tractores | [PDF] [Exportador]— una fila por situación con conteo y exportación individual. Valores observados:ACCIDENTADO — 10,AUTOS UTILITARIOS TALLER — 5,BAJA — 0,CARGADO DOMESTICO — 5,CARGADO EXPO PATIO NUEVO LARED — 6, etc. (catálogo largo). - Toggle de vista (dos íconos arriba a la derecha de la tabla,
img/graph.svgvs vista lista) cambia a gráfica de pastel “Situaciones al momento” — BUG, ver abajo.
/tractores/reportes/historial-situaciones
Sección titulada «/tractores/reportes/historial-situaciones»- Filtros:
Situaciones,Flota,Tractor(selects), radioCon movimientos/Sin movimientos/Todos(defaultCon movimientos), rango de fechas de inicio de movimiento, rango de fechas de fin de movimiento. - Encabezados de tabla:
Situación | Movimientos | Días totales | Días promedio. - Totales agregados (
Σ movimientos,Σ días totales,Σ días promedio) — BUG, ver abajo.
Bugs / hallazgos encontrados (exploración en vivo 2026-08-13, QA, usuario Benjamin/Oficina Mexico)
Sección titulada «Bugs / hallazgos encontrados (exploración en vivo 2026-08-13, QA, usuario Benjamin/Oficina Mexico)»Estos tres son reproducibles y estables (confirmados con captura de red y re-verificación, no son parpadeos de carga). Buenos candidatos a spec de regresión de Playwright.
-
Selector “Prioridad” nunca muestra opciones — ni en el filtro superior ni en el editor inline de fila.
- Repro: en
/tractores, click en el select “Prioridad” (filtro superior) o en el “Prioridad” del panel expandido de cualquier fila (probado conTRE21). El caret gira a estado abierto (claseis-reverse/is-focusde Element UI) pero el panel.el-select-dropdowncorrespondiente queda sin opciones visibles/renderizadas. - Evidencia de causa: captura completa de red (
network start+ reload de/tractores) no muestra ninguna petición a un catálogo de prioridades (sí hayGET /units/situation,GET /catalogs/geopoint,GET /users/by-module/12,GET /users/assigned-to-unitspara los otros selects). El frontend nunca pide el catálogo de prioridades. - Control: el select “Usuario Ejecutivo” en el mismo filtro sí funciona (muestra nombres reales al
abrirlo), así que no es un problema genérico de todos los
el-selectde la página. - Impacto: no se puede filtrar por prioridad ni cambiar la prioridad de un tractor desde la UI, aunque
el campo sí se muestra y tiene valor (
Prioridad: Normalen todas las filas observadas).
- Repro: en
-
Reporte “Historial Situaciones” — los totales agregados sí calculan pero la tabla de detalle siempre sale vacía.
- Repro: ir a
/tractores/reportes/historial-situaciones, cambiar el radio aTodos(o dejar el defaultCon movimientos). En ambos casos apareceNo hay más elementosbajo los encabezados de tabla (Situación | Movimientos | Días totales | Días promedio). - Con
Todosseleccionado, los totales sí muestran datos reales:Σ movimientos: 556,890,Σ días totales: 519,368.02,Σ días promedio: 219.4— prueba de que el backend sí tiene datos para agregar, pero el listado desglosado por situación no se renderiza en ningún filtro probado.
- Repro: ir a
-
Vista de gráfica “Situaciones al momento” (pie chart) no dibuja datos.
- Repro: en
/tractores/reportes/situaciones, click en el ícono de gráfica (img/graph.svg). - Se renderiza un
<canvas>de 1618x575 pero visualmente solo aparece un círculo gris sólido, sin colores por segmento, sin leyenda ni etiquetas — pese a que la vista de lista, en la misma página, sí muestra conteos reales por situación (ACCIDENTADO — 10, etc.). Estable tras esperar y re-capturar (no es un parpadeo de carga).
- Repro: en
Nota: faltó explorar con un usuario que tenga permisos de escritura reales para confirmar si el bug de Prioridad también ocurre para roles distintos a Benjamin/Oficina Mexico, y faltó probar el flujo de subida de archivo (“Subir Archivo”) de punta a punta (se documentó el catálogo de tipos pero no se subió un archivo real, para no ensuciar el ambiente QA compartido).
Permisos (Laratrust)
Sección titulada «Permisos (Laratrust)»Resource unit-reports (constantes en app/Core/Security/PermissionConst.php):
view-unit-reports (listado principal /tractores), read-unit-reports,
update-executive-user-unit-reports, update-priority-unit-reports.
Resource separado unit-sub-reports: view-unit-sub-reports (gobierna los KPIs de situaciones/historial).
Por verificar: no se encontró una constante sync-unit-reports explícita (sí existe sync-trailer-reports
en Remolques) — puede que el sync de tractor no tenga guard de permiso propio, o que la constante tenga otro
nombre no capturado por el grep usado (unit-reports|unit_reports|UNIT_REPORT).
Selectores usados por el tester (riesgo de fragilidad)
Sección titulada «Selectores usados por el tester (riesgo de fragilidad)»Actualizado 2026-08-13 — ya hay un spec y pasó a la primera: tests/tractores/expand-tractor-detail.spec.ts
(pages/tractores/TractorListPage.ts, TractorRowComponent.ts, TractorDetailPanel.ts), copia literal del
patrón de Remolques. La hipótesis por analogía se confirmó tal cual, sin ajustes:
getByText(code, { exact: true })(tractorTRE21) + heurística de ancestro con botón para la fila — funcionó igual.- Labels y valores del panel de detalle como nodos hermanos (
<strong>Label:</strong>+<generic>Valor</generic>) — igual. - Navegación directa por URL (
page.goto('/tractores')) en vez de clickear el link del sidebar — funcionó, no se probó el click del link así que no se confirmó si también tiene el problema de viewport de Remolques. - Solo se verificó el campo “Situación” (
PROGRAMADO CON VIAJEpara TRE21) — a diferencia de Remolques, la lista de Tractores no muestra Propietario/Ubicación como columnas, así que no se asumió que esos campos existan igual en el panel de detalle de Tractor; falta verificar qué campos SÍ tiene ese panel más allá de Situación.
Datos observados en QA (2026-08-12, columnas/filtros; ampliado 2026-08-13 con navegación real)
Sección titulada «Datos observados en QA (2026-08-12, columnas/filtros; ampliado 2026-08-13 con navegación real)»URL: https://qa.controlgmg.com/tractores. 287 registros en el listado, 40 por página. Sync: Ok,
última sincronización 2026-08-10 13:10:31 (barra muestra 287 / 0 / 0 — total/pendientes/error).
- Columnas: Tractor (código, ej.
TRE21,TRE57), # Liquidaciones, # Vales, Último movimiento, Días transcurridos, Situación (valores vistos:PROGRAMADO CON VIAJE,CONDUCTOR AUSENTE,DISPONIBLE,TALLER MEDIANO PLAZO,SIN CONDUCTOR Y DISPONIBLE,LIBERACIONES INTERMODAL,ACCIDENTADO,PATIERO TALLER REMOLQUES,TALLER CORTO/MEDIANO PLAZO,TALLER ALINEACION BALANCEO,DESENGANCHA CONTENEDOR (FINAL),REVISION GPS,DESCARGANDO IMPORTACION), Prioridad. - Filtros: ver lista completa y verificada arriba (sección “Frontend (Vue 2)”).
- Cada fila: tiene un chevron para expandir el detalle — mismo patrón interactivo que Remolques.
Fixture de prueba fijo: TRE21 (capturado 2026-08-13, QA es ambiente compartido — puede cambiar)
Sección titulada «Fixture de prueba fijo: TRE21 (capturado 2026-08-13, QA es ambiente compartido — puede cambiar)»- Prioridad:
Normal· # Vales:11· Último movimiento:2026-08-10 13:00:00· Días transcurridos:3 - Situación:
PROGRAMADO CON VIAJE· Sincronizado:(2026-08-10 13:10:27)· Badge comentarios:997 - AS-400: Posición actual
2026-08-10 01:09 PM,OFC. MTY (Kms: 0), Operador/Guía/Clientes vacíos, Flota:3 - Locales MTY. - Vales (primeros):
55913(ago 3, 2026 1:50 PM),421760,055867,55867,421638,421631… - Liquidaciones (primeras):
57265(ago 4, 2026 6:20 AM),57173,57078,56972,56603,56509. - Historial (sección “Historial”, movimientos): vacío para esta unidad.
- Otras filas capturadas de la misma página (para variedad de fixtures):
TRE57(Conductor Ausente, 4 vales, badge873),TRE60(Disponible, 13 vales, badge880),TRE54(Taller Mediano Plazo, 10 días transcurridos, tiene ícono de alerta adicional en la fila),TRE68(0 vales, 17 días, Patiero Taller Remolques, alerta),TRE48(Sin Conductor y Disponible, alerta).