Expediente Admin
Generada 2026-08-13. Fuente: exploración de código de controlgmg-v2 + observación manual del navegador (QA).
Backend
Sección titulada «Backend»- Modelo:
App\Core\Admin\AdminRecord(app/Core/Admin/AdminRecord.php), tablaadmin_records. Las rutas usan el parámetro{adminRecord}/{admin}de forma inconsistente entre endpoints (ver tabla de rutas), pero ambos apuntan al mismo modelo. Es el “expediente” del personal administrativo, análogo aOperator(expediente de operadores) pero para staff/oficina. extends BaseModel,implements HasModule(getModule()devuelveModule::expediente_admin). UsaSoftDeletes.- Traits relevantes:
ApprovableTrait,FileableTrait,ImageUrlTrait,SearchableTrait,BusinessRuleLockableTrait,MessageCenterNotifiableTrait,BusinessRuleAppendsTrait,CommentableTrait,UserNotifiableTrait— mismo set de capacidades que otros expedientes (comentarios, aprobaciones, archivos, notificaciones, reglas de negocio). - Columnas clave (
$fillable):code, photo_path, name, cellphone_number, nationality, curp, email, status, salary, new_hiring, is_hired, is_viable, arrive_way_id, arrive_reason_id, viability_arrive_reason_id, job_profile_id, company_id, team_id, is_training_interview_confirmed, is_area_interview_confirmed, training_interview_at, area_interview_at, emergency_contact, emergency_number. - Casts:
code:int, salary:float, new_hiring:bool, is_viable:bool, is_hired:bool, arrive_way_id:int, arrive_reason_id:int, viability_arrive_reason_id:int, job_profile_id:int, company_id:int, team_id:int, is_training_interview_confirmed:bool, is_area_interview_confirmed:bool, user_id:int. - Estados (
status):PROSPECT(prospect, Prospecto),CANDIDATE(candidate, Candidato),REGISTERED(registered, Alta),EMPLOYEE(employee, Empleado),UNREGISTERED(unregistered, Baja),REJECTED(rejected, Rechazado). Flujo de reclutamiento: prospecto → candidato → (viable+contratado) alta → empleado / (no viable o no contratado) rechazado; métodochangeStatus($type)con tiposAdminRecordApprovalTypes::reclutamientoy'register'. - Relaciones clave:
company()→belongsTo(Company::class)->withTrashed().job_profile()→belongsTo(JobProfile::class)(App\Core\Admin\JobProfiles\JobProfile) — vínculo con el submódulo “Perfil - Puesto”.arrive_reason(),viability_arrive_reason()(mismo modeloArriveReason, distinta FK),arrive_way().team()→belongsTo(Team::class).admin_record_salaries()→hasMany(AdminRecordSalary::class)(app/Core/Admin/AdminRecordSalary.php) — historial de solicitudes/cambios de sueldo directo (ver rutasdirectSalaryRequest/approveDirectSalary).user()→belongsTo(User::class)->withTrashed().admin_files()→morphMany(File::class, 'fileable')->whereFileableType('admin-record').
- Otros archivos del dominio en
app/Core/Admin/:AdminRecordRepository.php,AdminRecordFileTypes.php,AdminRecordApprovalTypes.php. Controladores enapp/Http/Controllers/Admin/:AdminRecordCommentController.php,AdminRecordFileController.php,AdminRecordApprovalController.php(no se localizó/leyó el controlador principal de CRUD por nombre exacto en esta pasada — por verificar, probablementeAdminControlleroAdminRecordControlleren la misma carpeta). getActionUrlAttribute()→/expediente-admin?id={id}(deep-link directo a un registro, útil para navegación de tests).getFileBasePath()→'admin'(prefijo de storage de archivos, ruta físicaadmin/{id}/images/...para foto).commonWith()define loswith()estándar del listado:files,approvals(conuser),admin_record_salaries(conuseryapprovals).
routes/admin/routes.php, prefix admin, dentro de auth:api + password_expired + hasTeam, sin middleware permission:/role: explícito a nivel de ruta (la autorización de “admin” vive en controladores/FormRequests, no en el router):
| Método | Ruta | Acción |
|---|---|---|
| POST | /admin/store |
crear |
| DELETE | /admin/{adminRecord} |
eliminar (soft delete) |
| PATCH | /admin/{adminRecord} |
restaurar |
| GET | /admin/{admin}/download-history |
historial de descargas de archivos |
| PUT | /admin/updateInterviewInfo/{admin} |
actualizar info de entrevista |
| PUT | /admin/update/{admin} |
actualizar |
| POST | /admin/directSalaryRequest/{adminRecord} |
solicitar cambio de sueldo directo |
| POST | /admin/approveDirectSalary/{adminRecord} |
aprobar cambio de sueldo directo |
| GET | /admin/getProfiles |
catálogo de perfiles de puesto |
| GET | /admin/getCompanyName |
catálogo de compañías |
| GET | /admin/get |
obtener un registro |
| GET | /admin |
listado paginado |
| POST | /admin/export |
exportar |
| GET | /admin/getProfileComponentInfo |
info de componente de perfil |
| GET | /admin/recruitmentInit |
datos iniciales de reclutamiento |
| GET | /admin/getAdminStatus |
catálogo de estatus |
| POST | /admin/reactivate/{admin} |
reactivar |
| POST | /admin/notifyReactivate/{adminRecord} |
notificar reactivación |
| GET | /admin/{admin}/staff-logs |
logs/bitácora de staff |
También se cargan (required junto a routes.php, mismo grupo): routes/admin/files.php, routes/admin/comments.php, routes/admin/approvals.php, routes/admin/reports.php — CRUD de archivos, comentarios, aprobaciones y reportes del expediente (no detallados endpoint por endpoint en esta pasada).
Subgrupos con permisos explícitos (a diferencia del CRUD principal de “admin”):
routes/admin/job-profile/{files,comments,approvals}.php+routes/admin/job-profile/profile_position.php→ rutas/expediente-admin/perfil-puesto/*, protegidas con middlewarepermission:{read,create,update,delete}-job-profile.- Subgrupo
market-study→ rutas de/expediente-admin/estudio-de-mercado/*(permisos análogos bajo el resourcemarket-study, no detallado en esta pasada — por verificar).
Frontend (Vue 2)
Sección titulada «Frontend (Vue 2)»- Ruta raíz
/expediente-admin/(resources/js/routes.js) →resources/js/components/Admin/AdminCaseFile/AdminCaseFile.vue,beforeEnter: can('view-admin'). - Rutas hermanas bajo el mismo módulo:
/expediente-admin/perfil-puesto/→components/Admin/JobProfile/JobProfile.vue, guardcan('view-job-profile')./expediente-admin/estudio-de-mercado/→components/Admin/MarketStudy/MarketStudyPage.vue, guardcan('view-market-study')./expediente-admin/reportes/→components/Admin/AdminReports.vue, guardcan('view-admin-reports')./organigrama-laboral→components/Admin/AdminCaseFile/Reports/AdminRecordKpi5.vue, guardcan('view-admin-reports')(reporte de organigrama, vive fuera del prefijo/expediente-adminpero es del mismo dominio).
AdminCaseFile.vuees el componente principal del expediente (listado). Contiene subcomponentes de formulario bajocomponents/Admin/AdminCaseFile/FormSections/:AdminAttendanceWidget.vue,AdminComplementaryForm.vue,AdminRequiredFilesForm.vue,AdminRegulationsFilesForm.vue,AdminProfilePostForm.vue,AdminOtherFilesForm.vue,AdminLeavingForm.vue— sugiere un formulario largo dividido en secciones (datos complementarios, archivos requeridos, reglamentos, puesto, otros archivos, baja), patrón similar a un expediente de Operador.- Menú lateral (
resources/js/components/Nav/menuOptions.js): entradaname: 'Expediente Admin',module: 'admin',path: '/expediente-admin',canView/getMainSlotByPermission: 'view-admin', ícono/img/expediente-admin.svg. Submódulos: “Expediente Admin” (/expediente-admin), “Perfil - Puesto” (/expediente-admin/perfil-puesto), y (por estructura del archivo) probablemente “Estudio de Mercado” y “Reportes” — no se leyeron todas las líneas del bloqueoptions.submodulesen esta pasada (por verificar el listado completo y el orden en el sidebar). - Servicios JS en
resources/js/services/admin/:admin-record-service.js(CRUD principal, probablemente wrapper de las rutas/admin/*de arriba),admin-approval-service.js,admin-comment-service.js,admin-file-service.js,admin-report-service.js. Subcarpetas de servicios paralelas parajob-profile/(incluyejob-profile-tree-service.js) ymarket-study/(incluye-candidate-,-announcement-variantes de archivo/comentario/aprobación).
Permisos (Laratrust)
Sección titulada «Permisos (Laratrust)»Fuente: config/laratrust_seeder.php, resource admin: v,c,r,u,d,co,n,update-direct-salary,set-registration-imss,set-leaving-reason,upload-other-files,set-leaving-imss-file,reactivate,restore (lista varía ligeramente por rol; algunos roles añaden approve-direct-salary, notify-dept-manager, notify-reactivation, upload-jc-evidence, upload-ja-evidence) → expandidas en App\Core\Security\PermissionConst:
view-admin,create-admin,read-admin,update-admin,delete-admin,restore-admincomment-admin,approve-admin,notify-adminupdate-direct-salary-admin,approve-direct-salary-admin(flujo de solicitud/aprobación de sueldo directo, rutasdirectSalaryRequest/approveDirectSalary)reactivate-admin,notify-reactivation-admin(flujo de reactivación, rutasreactivate/notifyReactivate)set-registration-imss-admin,set-leaving-reason-admin,set-leaving-imss-file-admin(altas/bajas IMSS)upload-other-files-admin,upload-jc-evidence-admin,upload-ja-evidence-adminnotify-dept-manager-adminview-admin-reports,read-admin-reports(gobierna/expediente-admin/reportes/y/organigrama-laboral)
Ya conocidas por investigación previa (no repetidas aquí en detalle): {read,create,update,delete}-job-profile para /expediente-admin/perfil-puesto/*, y el set análogo para market-study.
Roles con permisos notables sobre admin en config/modules.php/seeder: admin, owner, roles de RH (recursosHumanos), jefeArea (permisos amplios incl. set-registration-imss, notify-reactivation, update-direct-salary), jefeFactorHumano (solo v,r — lectura), un rol comentado/deshabilitado (//'admin' => 'v,r,upload-other-files', línea ~367, por verificar a qué rol corresponde, probablemente desactivado intencionalmente).
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), Expediente Admin no ha sido explorado con Playwright/codegen contra QA real. Todo lo documentado arriba es inferencia de código, no verificación en vivo:
- No hay
data-testiden la app (patrón general decontrolgmg-v2; no se modifica el repo para agregarlos). - El formulario del expediente está dividido en múltiples
FormSections/*.vue(Complementary, RequiredFiles, RegulationsFiles, ProfilePost, OtherFiles, Leaving, AttendanceWidget) — es probable que la UI use pestañas/acordeón para navegar entre secciones, pero la estructura visual exacta no se inspeccionó (clases,el-tabsvsel-collapse, etc.) — por verificar antes de escribir cualquier selector basado en estructura. - El listado principal (
AdminCaseFile.vue) no se leyó a nivel de template/filas — no se sabe si usa tabla HTML o divs tipoinfo-row(patrón visto en Remolques/Liquidaciones) — por verificar. - El submódulo “Perfil - Puesto” tiene su propio componente
JobProfile.vuecon filasProfilePostRow.vue; “Estudio de Mercado” tieneProfilePostMarketStudiesRow.vue— si un test necesita cruzar Expediente Admin con Perfil-Puesto (p.ej. verificarjob_profile_id), estos son los componentes a inspeccionar.
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)»La página carga en https://qa.controlgmg.com/expediente-admin bajo el título “Expediente Admin”. No se inspeccionó el contenido a mayor detalle visual.