Liquidaciones
Generada 2026-08-12. Fuente: exploración de código de controlgmg-v2 + observación manual del navegador (QA).
Backend
Sección titulada «Backend»- Modelo:
App\Core\Operations\Operation(app/Core/Operations/Operation.php), tablaoperations. Ojo: internamente el dominio se llama “Operations” en todo el código (namespace, controlador, rutas, servicio JS); “Liquidaciones” es solo el nombre visible en UI/menú/módulo. No busques un modeloSettlement/Liquidacion— no existe. - Migración base:
database/migrations/2018_04_05_210027_create_operations_table.php(columnas originales:user_id, company_id, unit_id, operator_id, checkbook, policy_number, policy_date, amount, settlement, settlement_date, performance, authorized, authorized_by, authorized_on, paid_on). El modelo actual usa muchas más columnas añadidas después vía migraciones incrementales no localizadas por nombre de tabla explícito (team_id,status,expected_payment_date,expected_date_set_by,expected_date_set_on,paid_by,checkbook_id,check_id,bank_account,performance_notes) — usaOperationFactory(database/factories/OperationFactory.php) como referencia rápida de shape en vez de perseguir cada migración. guarded: ['id'](nofillableexplícito). Casts:amountyperformanceafloat.SoftDeletesactivo (deleted_at).- Team scope: vía
App\Scopes\OperationScope(global scope, filtra poroperations.team_id = currentTeam()->id), NO porBelongsToTeamTrait/BaseModel.config/modules.php→ móduloliquidacionestienehas_team_scope: true(a diferencia de Remolques, que esfalse). - Estados (
status): constantes en el modelo —REC_DATOS(rec-datos),AUTORIZACION(autorizacion),NO_AUTORIZADO(no-autorizado),AUTORIZADO(autorizado),POR_PAGAR(por-pagar),PROCESO_OK(proceso-ok). Es el flujo de aprobación: captura → autorización → autorizado/rechazado → por pagar → pago confirmado. - Relaciones clave:
unit()→belongsTo(App\Core\Unit::class)(Tractor),withTrashed().operator()→belongsTo(App\Core\Operators\Operator::class),withTrashed().company(),user(),authorizer()(authorized_by),payer()(paid_by),epdsetter()(expected_date_set_by),checkbook_model()(App\Core\LegacyCatalogs\Checkbook),check_model()(App\Core\Catalogs\Check).- Archivos adjuntos vía
hasMany:lectures()(LectureFiles),policies()(PolicyFiles),settlements()(SettlementFiles— ojo, es el nombre de la relación de ARCHIVOS de liquidación, no el modelo principal),invoices()(InvoiceFiles). file_downloads()→OperationFileDownload(historial de descargas de documentos).
- Relación Tractor↔Liquidación (la que ves en el módulo Tractores):
App\Core\Unit::operations()→hasMany(Operation::class)->withoutGlobalScopes()(app/Core/Unit.php). El reporte de Tractores (resources/js/components/Catalogs/Units/Reports/UnitsReport.vue) ordena/filtra por el aliasoperations_count(columna “# Liquidaciones”, víawithCount('operations')enUnit::scopeWithOperationAndVoucher()), y también hay un filtro “Sin liquidaciones” (without_operation). - Controlador:
App\Http\Controllers\OperationController(app/Http/Controllers/OperationController.php, sin subcarpetaOperations/) — no usa Form Requests para todo (p.ej.all()recibeRequestplano), sí parastore/update/authorize/programPayment/confirmPayment/addComment/destroy/reject(App\Http\Requests\Operations\*). - Export: reutiliza
App\Core\Exportcon tiposExport::TYPE_OPERATIONS/TYPE_OPERATIONS_REPORTvíaExportController.
Todas bajo el grupo global (auth:api + password_expired) directamente en routes/web.php (líneas ~38-58) — no vive en un archivo routes/operations/* propio como otros dominios:
| Método | Ruta | Acción |
|---|---|---|
| GET | /operations |
listado paginado + stats por estatus |
| POST | /operations |
crear |
| POST | /operations/update |
actualizar |
| DELETE | /operations |
eliminar (soft delete) |
| PATCH | /operations/{id} |
restaurar |
| POST | /operations/authorize |
autorizar/rechazar |
| POST | /operations/payment/program |
programar fecha de pago |
| POST | /operations/payment/confirm |
confirmar pago |
| POST | /operations/reject |
rechazar |
| POST | /operations/comments/add |
comentario |
| GET | /operations/{id}/download-history |
historial de descargas de archivos |
| GET | /operations/performance/stats, /operations/getChartInfo |
KPIs de rendimiento |
| GET | /operations/liquidators, /operations/getLiquidatorsOperations, /operations/filterLiqByRole |
reportes por liquidador (usuario) |
| GET | /operations/excel, POST /operations/exportOpExcel, POST /operations/export |
exportaciones |
No hay middleware permission: a nivel de ruta — la autorización vive en los FormRequests (mismo patrón que Remolques).
Frontend (Vue 2)
Sección titulada «Frontend (Vue 2)»- Ruta raíz
/liquidaciones/→resources/js/components/Operations/Operations.vue(listado principal, sinbeforeEnter— el control de vista lo hace el propio componente/menú concan('view-operation')). /liquidaciones/reportes/→OperationsReports.vue(guardcan('view-operations-reports')), con hijos:reportes/tractor→Reports/Units.vue,reportes/operador→Reports/Operators.vue,reportes/liquidaciones→Reports/Operations.vue./liquidaciones/catalogos/→OperationsCatalogs.vue(guardcan('view-operations-catalogs')), con hijoscompanias,tractores, etc. bajoCatalogs/.Operations.vue— página de listado: filtros (búsqueda, estatus, rango de fecha con selector de campooperations.created_at/policy_date/settlement_date/paid_on), orden por póliza/operador/tractor/liquidación/captura/pago, botón “Agregar” (can('create-operation')), exportador Excel, toggle papelera (can('delete-operator')— permiso compartido/heredado de Operadores, posible bug de copy-paste a validar).OperationRow.vue— fila de la lista: póliza, monto + chequera, autorizador, usuario que capturó, código de compañía, código de operador, código de tractor (operation.unit.code), barra de progreso de estatus (%), fechas (Liquidación/Captura/Pago), botón de comentarios, historial de descargas (AsyncFileDownloadHistoryDialog, solo sifile_downloads_count > 0).OperationForm.vue— formulario expandible inline (alta/edición), aparece al click en “Agregar” o al hacer click en una fila (mismo patrón de expansión que Remolques).- Servicio:
resources/js/services/operations/operation-service.js—GET /operations(con params),POST /operations(crear, víaSpark.post),POST /operations/update,POST /operations/reject,DELETE /operations,PATCH /operations/{id}(restaurar),POST /operations/payment/confirm,POST /operations/payment/program,POST /operations/authorize,GET /operations/excel(descarga víaDownloadService). Comentarios en servicio aparte:resources/js/services/operations/operation-comment-service.js. - Menú lateral: definido en
resources/js/components/Nav/menuOptions.js— primer ítem del arreglomenuOptions,name: 'Liquidaciones',module: 'operation',path: '/liquidaciones',canView: 'view-operation', ícono/img/liquidaciones.svg. Submenús:submodules(Liquidaciones),catalogs(Compañías, Tractores),reports(Tractor, Operador, Liquidaciones).
Permisos (Laratrust)
Sección titulada «Permisos (Laratrust)»Fuente: config/laratrust_seeder.php (resource operation: c,r,u,d,co,confirm-payment,program-payment,reject,a,v) → generadas en App\Core\Security\PermissionConst:
view-operation,create-operation,read-operation,update-operation,delete-operationcomment-operation,approve-operation,confirm-payment-operation,program-payment-operation,reject-operationview-operations-reports(gobierna/liquidaciones/reportes/*),view-operations-catalogs(gobierna/liquidaciones/catalogos/*)
Roles relevantes en config/modules.php (módulo liquidaciones): admin, owner, liquidador, jefeLiquidaciones (Jefe de Liquidaciones — flujo de autorización), jefeBancos (autoriza pagos), jefeFinanzas (programa pagos). Los eventos del Message Center (comment, rejected, authorization-request, authorized, not-authorized, payment-programed, payment-confirmed) mapean 1:1 con las transiciones de status del OperationController.
Selectores usados por el tester (riesgo de fragilidad)
Sección titulada «Selectores usados por el tester (riesgo de fragilidad)»No hay specs de Playwright para este módulo todavía — a diferencia de Remolques (que sí tiene tests/remolques/expand-trailer-detail.spec.ts), Liquidaciones no ha sido explorado con Playwright/codegen contra QA real. Todo lo que sigue es inferencia de código, no verificación en vivo:
- No hay
data-testiden la app (mismo patrón que el resto decontrolgmg-v2, no se modifica el repo para agregarlos). - El link “Liquidaciones” del sidebar (
menuOptions.js) es el primer ítem, por lo que probablemente SÍ esté visible sin necesidad de scroll (a diferencia de “Remolques”, que queda fuera del viewport) — pero esto debe confirmarse contra QA real, no asumirse. - La fila de la lista (
OperationRow.vue) no usa una tabla HTML sino divs (info-row/column), igual que Remolques — probablemente aplique una estrategia similar degetByText(policy_number)+ heurística de ancestro para ubicar la fila. - El formulario de alta/edición (
OperationForm.vue) se expande inline igual que en Remolques (mismo patrónel-collapse-transition), pero su estructura interna de campos no ha sido inspeccionada — no asumir que los labels de campo estén asociados correctamente a inputs sin verificar (en Remolques el login ya demostró quegetByLabelpuede fallar). - El filtro “Sin liquidaciones” / “# Liquidaciones” vive en el módulo Tractores (
UnitsReport.vue), no en Liquidaciones — si un test necesita verificar la relación Tractor↔Liquidación, navegar a/unidades(o la ruta de Tractores) y no a/liquidaciones.
Antes de escribir cualquier spec para este módulo, correr npm run codegen:gmg contra QA real para verificar selectores, igual que se hizo para Remolques.
Datos observados en QA (2026-08-12)
Sección titulada «Datos observados en QA (2026-08-12)»- URL:
https://qa.controlgmg.com/liquidaciones— primer ítem del sidebar, título de página “Liquidaciones”. - El módulo Tractores muestra una columna “# Liquidaciones” que cuenta liquidaciones por tractor — confirma en vivo la relación
Unit::operations()descrita arriba. No se registró en esta pasada el valor exacto de ningún tractor/liquidación de ejemplo; falta una exploración manual más profunda del listado y del formulario de alta/edición para documentar selectores y datos de prueba concretos (pendiente, análogo a lo hecho para Remolques).