Ir al contenido

Expediente Admin

Generada 2026-08-13. Fuente: exploración de código de controlgmg-v2 + observación manual del navegador (QA).

  • Modelo: App\Core\Admin\AdminRecord (app/Core/Admin/AdminRecord.php), tabla admin_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 a Operator (expediente de operadores) pero para staff/oficina.
  • extends BaseModel, implements HasModule (getModule() devuelve Module::expediente_admin). Usa SoftDeletes.
  • 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étodo changeStatus($type) con tipos AdminRecordApprovalTypes::reclutamiento y '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 modelo ArriveReason, 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 rutas directSalaryRequest / 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 en app/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, probablemente AdminController o AdminRecordController en 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ísica admin/{id}/images/... para foto).
  • commonWith() define los with() estándar del listado: files, approvals (con user), admin_record_salaries (con user y approvals).

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 middleware permission:{read,create,update,delete}-job-profile.
  • Subgrupo market-study → rutas de /expediente-admin/estudio-de-mercado/* (permisos análogos bajo el resource market-study, no detallado en esta pasada — por verificar).
  • 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, guard can('view-job-profile').
    • /expediente-admin/estudio-de-mercado/ → components/Admin/MarketStudy/MarketStudyPage.vue, guard can('view-market-study').
    • /expediente-admin/reportes/ → components/Admin/AdminReports.vue, guard can('view-admin-reports').
    • /organigrama-laboral → components/Admin/AdminCaseFile/Reports/AdminRecordKpi5.vue, guard can('view-admin-reports') (reporte de organigrama, vive fuera del prefijo /expediente-admin pero es del mismo dominio).
  • AdminCaseFile.vue es el componente principal del expediente (listado). Contiene subcomponentes de formulario bajo components/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): entrada name: '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 bloque options.submodules en 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 para job-profile/ (incluye job-profile-tree-service.js) y market-study/ (incluye -candidate-, -announcement- variantes de archivo/comentario/aprobación).

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-admin
  • comment-admin, approve-admin, notify-admin
  • update-direct-salary-admin, approve-direct-salary-admin (flujo de solicitud/aprobación de sueldo directo, rutas directSalaryRequest/approveDirectSalary)
  • reactivate-admin, notify-reactivation-admin (flujo de reactivación, rutas reactivate/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-admin
  • notify-dept-manager-admin
  • view-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-testid en la app (patrón general de controlgmg-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-tabs vs el-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 tipo info-row (patrón visto en Remolques/Liquidaciones) — por verificar.
  • El submódulo “Perfil - Puesto” tiene su propio componente JobProfile.vue con filas ProfilePostRow.vue; “Estudio de Mercado” tiene ProfilePostMarketStudiesRow.vue — si un test necesita cruzar Expediente Admin con Perfil-Puesto (p.ej. verificar job_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.

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.