# 21 — Trazabilidad

> Tabla de navegación rápida: de una funcionalidad al código responsable, sin abrir nada.
>
> Formato: **Funcionalidad → Módulo → Controlador::acción → Modelo/Servicio → Tabla(s) → Vista**

---

## Cómo usar este documento

```
1. Localiza la funcionalidad en la tabla de su dominio
2. Abre el controlador y la acción indicados
3. Comprueba las reglas de negocio del módulo en 10_BUSINESS_LOGIC.md
4. Comprueba el esquema de las tablas en 05_DATABASE.md
5. Antes de modificar, comprueba las dependencias en 19_DEPENDENCY_MAP.md
```

---

## 1. Autenticación y sesión

| Funcionalidad | Controlador::acción | Modelo | Tablas | Vista |
|---|---|---|---|---|
| Formulario de login del backoffice | `LoginController::admin` | — | — | `login/admin.php` |
| Validar login del backoffice | `LoginController::validate` | `UsuariosModel::validateUser()` · `RateLimiter` | `usuarios`, `roles`, `permisos`, `log_acceso` | — |
| Cerrar sesión | `LoginController::logout` | — | — | — |
| Formulario de login del portal | `PublicController::index` | `PeriodosModel::getActivos()` | `periodos` | `public/login.php` |
| Validar login del portal | `PublicController::validate` | `ColaboradoresModel::validateUser()` | `colaboradores`, `roles`, `permisos` | — |
| Login institucional (Microsoft) | `PublicController::validated` | — | `usuarios` | — |
| Comprobar sesión (heartbeat) | *(fuera del router)* `public/check_session.php` | — | — | — |
| Modo demo | `DemoController::index` / `salir` | `UsuariosModel::loadDemoMenu()` | Múltiples (siembra) | `demo/index.php` |

---

## 2. Colaboradores

| Funcionalidad | Controlador::acción | Modelo | Tablas | Vista |
|---|---|---|---|---|
| Listar colaboradores | `ColaboradoresController::list` / `dataListAjax` | `ColaboradoresModel` | `vista_colaboradores` | `colaboradores/list.php` |
| Crear colaborador | `ColaboradoresController::create` | `ColaboradoresModel::save()` | `colaboradores` | `colaboradores/create.php` + `_form.php` |
| Editar colaborador | `ColaboradoresController::edit` | `ColaboradoresModel::loadById()` + `save()` | `colaboradores` | `colaboradores/edit.php` |
| Ficha 360 del colaborador | `ColaboradoresController::view` / `ver` | Múltiples | Múltiples | `colaboradores/view.php` |
| Eliminar colaborador | `ColaboradoresController::remove` | `ColaboradoresModel::deleteCascade()` | ~15 tablas, en transacción | — |
| Organigrama | `ColaboradoresController::organigrama` | `buildOrganigramaTree()` | `colaboradores` (`IdJefeInmediato`) | `colaboradores/organigrama.php` |
| Pestaña: contrato y documentos | `ColaboradoresController::tabContratoDocumentos` | `ColaboradorEducacionModel`, `ColaboradorExperienciaModel` | `colaborador_educacion`, `colaborador_experiencia` | `colaboradores/partials/` |
| Pestaña: asistencia | `::tabAsistencia` | `AsistenciaRegistrosModel` | `asistencia_registros` | idem |
| Pestaña: vacaciones | `::tabVacaciones` | `SolicitudesVacacionesModel`, `SaldosVacacionesModel` | `solicitudes_vacaciones`, `saldos_vacaciones` | idem |
| Pestaña: nómina | `::tabNomina` | `NominaLiquidacionesModel` | `nomina_liquidaciones` | idem |
| Pestaña: tickets | `::tabTickets` | `ServicioTicketsModel` | `servicio_tickets` | idem |
| Pestaña: capacitación | `::tabCapacitacion` | `CapacitacionInscripcionesModel` | `capacitacion_inscripciones` | idem |
| Pestaña: beneficios | `::tabBeneficios` | `BeneficiosAsignacionesModel`, `BeneficiosSolicitudesModel` | `beneficios_*` | idem |
| Pestaña: adelantos | `::tabAdelantos` | `AdelantoSolicitudesModel`, `AdelantoCuotasModel` | `adelanto_*` | idem |
| Pestaña: carrera y talento | `::tabCarreraTalento` | `CarreraPlanColaboradorModel`, `PotencialEvaluacionesModel` | `carrera_*`, `potencial_*` | idem |
| Pestaña: evaluación | `::tabEvaluacion` | `EvaluacionesModel` | `evaluaciones` | idem |
| Pestaña: metas | `::tabMetas` | `MetasModel`, `MetasConsolidadoModel` | `metas`, `metas_consolidado` | idem |
| Pestaña: planes de desarrollo | `::tabPlanesDesarrollo` | `PlanesDesarrolloModel` | `planes_desarrollo` | idem |
| Pestaña: reclutamiento | `::tabReclutamiento` | `ProcesosSeleccionColaboradorModel` | `procesos_seleccion_colaborador` | idem |
| Pestaña: trayectoria | `::tabTrayectoria` | Múltiples | Múltiples | idem |
| Pestaña: auditoría | `::tabAuditoria` | `LogModulesModel` | `log_modules` | idem |
| **Portal:** mi perfil | `PerfilColaboradorController::panel` | `ColaboradoresModel` | `vista_colaboradores` | `perfil_colaborador/panel.php` |
| **Portal:** editar mi perfil | `PerfilColaboradorController::edit` | `ColaboradoresModel` | `colaboradores` | `perfil_colaborador/edit.php` |
| **Portal:** mi asistencia | `PerfilColaboradorController::asistencia` | `AsistenciaRegistrosModel` | `asistencia_registros` | `perfil_colaborador/asistencia.php` |

---

## 3. Reclutamiento

| Funcionalidad | Controlador::acción | Modelo/Servicio | Tablas | Vista |
|---|---|---|---|---|
| Pipeline global | `ReclutamientoController::pipeline` · `stageCreate` · `stageReorder` · `stageToggle` | `RecruitmentPipelineStagesModel` | `reclutamiento_etapas_pipeline` | `reclutamiento/pipeline.php` |
| Motivos de rechazo | `::reasonCreate` | `RecruitmentRejectionReasonsModel` | `reclutamiento_motivos_rechazo` | `reclutamiento/pipeline.php` |
| Listar vacantes | `::vacantes` | `RecruitmentVacanciesModel` | `reclutamiento_vacantes` | `reclutamiento/vacantes.php` |
| Crear / editar / duplicar vacante | `::vacanteCreate` · `vacanteEdit` · `vacanteDuplicar` | `RecruitmentVacanciesModel` · `EtapasEmbudoVacanteModel::sincronizarConPipelineGlobal()` | `reclutamiento_vacantes`, `etapas_embudo_vacante` | `reclutamiento/vacante_form.php` |
| Ver vacante | `::vacanteView` | `RecruitmentVacanciesModel`, `ReglasFiltroVacanteModel` | `reclutamiento_vacantes`, `reglas_filtro_vacante` | `reclutamiento/vacante_view.php` |
| Cambiar estado de vacante | `::vacanteChangeEstado` | `RecruitmentVacanciesModel` | `reclutamiento_vacantes` | — |
| Candidatos | `::candidatos` · `candidatoView` · `candidatoCreate` · `candidatoEdit` | `RecruitmentCandidatesModel` | `reclutamiento_candidatos` | `reclutamiento/candidato*.php` |
| Postulaciones | `::applications` · `applicationCreate` · `applicationView` | `RecruitmentApplicationsModel::crearPostulacion()` · `ScoringCandidatosService` | `reclutamiento_postulaciones` | `reclutamiento/applications.php` |
| Kanban del embudo | `::kanban` | `EtapasEmbudoVacanteModel::getEtapasPorVacante()` | `etapas_embudo_vacante` | `reclutamiento/kanban.php` |
| **Mover de etapa** | `::moveStage` | **`RecruitmentApplicationsModel::moverEtapa()`** | `reclutamiento_postulaciones`, `reclutamiento_historial_etapas_postulacion` | — |
| Entrevistas | `::interviewCreate` · `interviewReprogramar` | `RecruitmentInterviewsModel` | `reclutamiento_entrevistas`, `historial_entrevista_postulacion` | `reclutamiento/application_view.php` |
| Ofertas | `::offerCreate` · `offerChangeEstado` | `RecruitmentOffersModel` | `reclutamiento_ofertas` | idem |
| Contratos | `::contractCreate` · `contractChangeEstado` | `RecruitmentContractsModel` · `ContratacionDesdeOfertaService` | `reclutamiento_contratos`, `colaboradores`, `procesos_seleccion_colaborador` | idem |
| **Público:** bolsa de empleo | `PublicController::vacantesPublicas` | `RecruitmentVacanciesModel` | `reclutamiento_vacantes` | `public/vacantes_publicas.php` |
| **Público:** postularse | `PublicController::postularVacante` | `RecruitmentCandidatesModel`, `RecruitmentApplicationsModel` | `reclutamiento_candidatos`, `reclutamiento_postulaciones` | — |

---

## 4. Metas

| Funcionalidad | Controlador::acción | Modelo | Tablas | Vista |
|---|---|---|---|---|
| Listar metas | `MetasController::list` / `dataListAjax` | `MetasModel` | `vista_metas` | `metas/list.php` |
| Crear meta | `MetasController::create` | `MetasModel::validateMetaPayload()` | `metas` | `metas/create.php` + `_form.php` |
| Editar meta | `MetasController::edit` | `MetasModel::isMetaEditable()` + `validateMetaPayload()` | `metas` | `metas/edit.php` |
| Ver meta | `MetasController::view` | `MetasModel` | `vista_metas` | `metas/view.php` |
| **Aprobar meta** | `MetasController::aprobarMeta` | `MetasModel::shouldRequireExactHundred()` | `metas` | — |
| **Rechazar meta** | `MetasController::rechazarMeta` | `MetasModel` | `metas` (`ComentarioRevision`) | — |
| Consolidado | `::consolidado` · `noConsolidado` | `MetasConsolidadoModel` | `vista_metas_consolidado` | `metas/consolidado.php` |
| Consolidar final | `::consolidarFinal` | `MetasConsolidadoModel` | `metas_consolidado` | — |
| Heredar metas | `::heredar` | `MetasModel::heredarMetasPeriodo()` | `metas` | `metas/heredar.php` |
| Cambio de cargo | `::cambioCargo` | `MetasModel` | `metas` | `metas/cambio_cargo.php` |
| Sincronizar jefes | `::sincronizacionJefes` | `MetasModel` | `metas` | `metas/sincronizacionJefes.php` |
| Categorías de metas | `MetasCategoriasController` (CRUD) | `MetasCategoriasModel` | `metas_categorias` | `metas_categorias/` |
| Seguimientos | `MetasSeguimientosController::create` · `edit` · `remove` | `MetasSeguimientosModel` | `metas_seguimientos` | `metas_seguimientos/` |
| **Portal:** mis metas | `MetasColaboradorController::list` | `MetasModel`, `PeriodosModel::getMetasWindowState()` | `vista_metas`, `periodos` | `metas_colaborador/list.php` |

---

## 5. Evaluación 360

| Funcionalidad | Controlador::acción | Modelo | Tablas | Vista |
|---|---|---|---|---|
| Listar evaluaciones | `EvaluacionesController::list` | `EvaluacionesModel` | `vista_evaluaciones` | `evaluaciones/list.php` |
| Generar evaluaciones | `::generar` | `EvaluacionesModel` | `evaluaciones` | `evaluaciones/generar.php` |
| Calcular totales | `::calcular` | `EvaluacionesModel` | `evaluaciones`, `respuestas` | `evaluaciones/calcular.php` |
| Consolidar | `::consolidar` | `ConsolidadoEvaluacion360Model` | `consolidado_evaluacion_360` | `evaluaciones/consolidar.php` |
| Recalcular | `::recalcular` | `EvaluacionesModel` | `evaluaciones` | — |
| Imprimir | `::imprimir` | `EvaluacionesModel`, `RespuestasModel` | `vista_respuestas` | `evaluaciones/imprimir.php` |
| Carga masiva | `::cargueMasivo` | `EvaluacionesModel` | `evaluaciones` | `evaluaciones/cargue_masivo_datos.php` |
| Resolver duplicados | `::solucionarRepetidos` | `EvaluacionesModel` | `evaluaciones` | — |
| **Portal:** mi evaluación | `EvaluacionesColaboradorController::list` | `EvaluacionesModel` | `vista_evaluaciones` | `evaluaciones_colaborador/list.php` |
| **Portal:** responder encuesta | `EvaluacionesColaboradorController::encuesta` | `RespuestasModel`, `PreguntasModel`, `EscalasModel` | `respuestas`, `preguntas`, `escalas` | `evaluaciones_colaborador/encuesta.php` |
| Competencias (CRUD) | `CompetenciasController` | `CompetenciasModel` | `competencias` | `competencias/` |
| Preguntas (CRUD) | `PreguntasController` | `PreguntasModel` | `vista_preguntas` | `preguntas/` |
| Escalas (CRUD) | `EscalasController` | `EscalasModel` | `escalas` | `escalas/` |
| Competencias por colaborador | `CompetenciasColaboradoresController` | `CompetenciasColaboradoresModel` | `competencias_colaboradores` | `competencias_colaboradores/` |

---

## 6. Talento y desarrollo

| Funcionalidad | Controlador::acción | Modelo/Servicio | Tablas | Vista |
|---|---|---|---|---|
| Periodos de potencial | `PotencialesController::periodos` | `PotencialPeriodosModel` | `potencial_periodos` | `carrera_talento/potenciales_periodos.php` |
| Criterios HiPo | `::criterios` | `PotencialCriteriosModel` | `potencial_criterios` | `carrera_talento/potenciales_criterios.php` |
| Evaluar potencial | `::evaluar` | `PotencialEvaluacionesModel`, `PotencialEvaluacionDetalleModel` | `potencial_evaluaciones`, `potencial_evaluacion_detalle` | `carrera_talento/potenciales_evaluar.php` |
| **Recalcular talento** | `::recalcular` | **`TalentScoreService::actualizarEvaluacion()`** | `potencial_evaluaciones`, `metas_consolidado`, `evaluaciones` | `carrera_talento/potenciales_recalcular.php` |
| Validar categoría | `::validarCategoria` | `TalentScoreService::puedeCategorizar()` | `talento_categorias` | — |
| Listado de Altos Potenciales | `::listado` | `TalentScoreService::getUmbralHipo()` | `vista_potencial_evaluaciones` | `carrera_talento/potenciales_listado.php` |
| **Mapa de Talento 9-Box** | `::mapaTalentos` | `TalentScoreService::categorizarTalento()` | `talento_celdas_9box`, `talento_categorias` | `carrera_talento/potenciales_mapa_talentos.php` |
| Cerrar periodo / exportar | `::cerrarPeriodo` · `exportar` | `PotencialEvaluacionesModel` | `potencial_evaluaciones` | — |
| Planes de desarrollo | `PlanesDesarrolloController::list` · `create` · `edit` · `view` | `PlanesDesarrolloModel`, `AccionesDesarrolloModel` | `planes_desarrollo`, `acciones_desarrollo` | `planes_desarrollo/` |
| Generar plan sugerido | `::generarSugerido` | `GeneradorPlanesDesarrolloService` | `competencias`, `evaluaciones`, `planes_desarrollo` | — |
| Recalcular pesos | `::recalcularPesos` | `CalculadorProgresoPlanService` | `acciones_desarrollo` | — |
| **Portal:** mis planes | `PortalPlanesDesarrolloController::list` · `view` | `PlanesDesarrolloModel` | `vista_planes_desarrollo` | `portal_planes_desarrollo/` |
| **Portal:** planes del equipo | `PlanesDesarrolloEquipoController::list` · `view` · `equipoTalento` | `PlanesDesarrolloModel`, `TalentScoreService::obtenerResumenEquipo()` | `planes_desarrollo`, `potencial_evaluaciones` | `planes_desarrollo_equipo/` |

---

## 7. Carrera, sucesión y reconocimientos

| Funcionalidad | Controlador::acción | Modelo | Tablas | Vista |
|---|---|---|---|---|
| Rutas de carrera | `PlanesCarreraController::index` · `crearRuta` · `guardarRuta` · `verRuta` · `editarRuta` · `desactivarRuta` | `CarreraRutasModel` | `carrera_rutas` | `carrera_talento/planes_*.php` |
| Etapas de una ruta | `::gestionarEtapas` | `CarreraRutaEtapasModel` | `carrera_ruta_etapas` | `carrera_talento/planes_ruta_ver.php` |
| Asignar plan a colaborador | `::asignarPlan` | `CarreraPlanColaboradorModel`, `CarreraPlanEtapasModel` | `carrera_plan_colaborador`, `carrera_plan_etapas` | `carrera_talento/planes_asignar_plan.php` |
| Ver plan de un colaborador | `::verPlanColaborador` | `CarreraPlanColaboradorModel` | `carrera_plan_colaborador` | `carrera_talento/planes_plan_ver.php` |
| Actualizar avance | `::actualizarAvance` | `CarreraPlanEtapasModel` | `carrera_plan_etapas` | — |
| Reporte de carrera | `::reporte` | `CarreraPlanColaboradorModel` | `carrera_plan_colaborador` | `carrera_talento/planes_reporte.php` |
| **Portal:** mi plan de carrera | `CarreraPortalController::miPlanCarrera` | `CarreraPlanColaboradorModel` | `carrera_plan_colaborador` | `carrera_portal/mi_plan_carrera.php` |
| **Portal:** mi desempeño | `CarreraPortalController::miEstadoTalento` | `TalentScoreService` | `potencial_evaluaciones` | `carrera_portal/mi_estado_talento.php` |
| Puestos clave | `SucesionController::puestosClave` | `SucesionPuestosClaveModel` | `sucesion_puestos_clave` | `carrera_talento/sucesion_puestos.php` |
| Planes de sucesión | `::planes` · `cambiarEstadoPlan` | `SucesionPlanesModel` | `sucesion_planes` | `carrera_talento/sucesion_planes.php` |
| Candidatos a sucesión | `::candidatos` | `SucesionCandidatosModel` | `vista_sucesion_candidatos` | `carrera_talento/sucesion_candidatos.php` |
| Reporte de riesgo | `::reporteRiesgo` | `SucesionPuestosClaveModel` | `sucesion_puestos_clave` | `carrera_talento/sucesion_reporte_riesgo.php` |
| Tipos de reconocimiento | `ReconocimientosController::tipos` | `ReconocimientoTiposModel` | `reconocimiento_tipos` | `carrera_talento/reconocimientos_tipos.php` |
| Enviar reconocimiento | `::enviar` | `ReconocimientosModel::countByEmisorRango()` | `reconocimientos`, `reconocimiento_reglas` | `carrera_talento/reconocimientos_enviar.php` |
| Aprobar / rechazar / publicar | `::aprobar` · `rechazar` · `publicar` | `ReconocimientosModel` | `reconocimientos` | — |
| Muro de reconocimientos | `::muro` | `ReconocimientosModel::listarPublicadosConNombres()` | `vista_reconocimientos` | `carrera_talento/reconocimientos_muro.php` |
| Mis reconocimientos | `::misReconocimientos` | `ReconocimientosModel::listarRecibidosConNombres()` | `vista_reconocimientos` | `carrera_talento/reconocimientos_mis.php` |
| Reglas | `::reglas` | `ReconocimientoReglasModel` | `reconocimiento_reglas` | `carrera_talento/reconocimientos_reglas.php` |

---

## 8. Tiempo y compensación

| Funcionalidad | Controlador::acción | Modelo/Servicio | Tablas | Vista |
|---|---|---|---|---|
| Listar solicitudes de vacaciones | `VacacionesController::list` | `SolicitudesVacacionesModel` | `vista_solicitudes_vacaciones` | `vacaciones/list.php` |
| Detalle de solicitud | `::detalle` | `SolicitudesVacacionesModel`, `SaldosVacacionesModel` | `solicitudes_vacaciones`, `saldos_vacaciones` | `vacaciones/detalle.php` |
| **Aprobar vacaciones** | `::aprobar` → `aprobarSolicitudInterna()` | `SaldosVacacionesModel::getOrCreateSaldo()` + `actualizarSaldo()` | `solicitudes_vacaciones`, `saldos_vacaciones`, `politicas_vacaciones` | — |
| Rechazar / cancelar | `::rechazar` · `cancelar` | `SolicitudesVacacionesModel` | `solicitudes_vacaciones` | — |
| Políticas de vacaciones | `::politicas` | `PoliticasVacacionesModel` | `vista_politicas_vacaciones` | `vacaciones/politicas.php` |
| **Portal:** mis vacaciones | `VacacionesColaboradorController::list` | `SolicitudesVacacionesModel::existeCruce()` + `calcularDiasSolicitados()` | `solicitudes_vacaciones`, `festivos` | `vacaciones_colaborador/list.php` |
| Panel de asistencia | `AsistenciaController::index` | `AsistenciaRegistrosModel` | `vista_asistencia_registros` | `asistencia/index.php` |
| **Marcar entrada** | `::registrarEntrada` | `AsistenciaRegistrosModel::marcarEntrada()` | `asistencia_registros` | — |
| **Marcar salida** | `::registrarSalida` | `marcarSalida()` + `calcularMinutosExtra()` | `asistencia_registros`, `asistencia_horas_extra` | — |
| Calendario / reporte mensual | `::calendario` · `reporteMensual` | `AsistenciaRegistrosModel` | `asistencia_registros` | `asistencia/calendario.php`, `reporte_mensual.php` |
| Turnos | `TurnosController::index` · `crear` · `guardar` · `eliminar` · `asignar` | `AsistenciaTurnosModel`, `AsistenciaColaboradorTurnosModel` | `asistencia_turnos`, `asistencia_colaborador_turnos` | `turnos/` |
| Ausencias | `AusenciasController::index` · `crear` · `guardar` · `aprobar` · `ver` | `AsistenciaAusenciasModel` | `asistencia_ausencias` | `ausencias/` |
| Periodos de nómina | `NominaController::list` · `crearPeriodo` · `periodo` | `NominaPeriodosModel` | `vista_nomina_periodos` | `nomina/list.php`, `periodo.php` |
| Conceptos de nómina | `::conceptos` · `eliminarConcepto` | `NominaConceptosModel` | `vista_nomina_conceptos` | `nomina/conceptos.php` |
| Novedades | `::guardarNovedad` · `plantillaCsvNovedades` | `NominaNovedadesModel` | `nomina_novedades` | — |
| **Recalcular nómina** | `::recalcular` | **`NominaCalculoModel::recalcularPeriodo()`** | `nomina_liquidaciones`, `nomina_liquidacion_detalle`, `nomina_parametros`, `bitacora_auditoria` | — |
| Cerrar periodo | `::cerrarPeriodo` | `NominaPeriodosModel::cambiarEstado()` | `nomina_periodos` | — |
| Detalle / comprobante / CSV | `::detalleLiquidacion` · `comprobante` · `exportCsv` | `NominaLiquidacionDetalleModel` | `vista_nomina_liquidacion_detalle` | `nomina/liquidacion_detalle.php`, `comprobante.php` |
| Solicitudes de adelanto (admin) | `AdelantosNominaController::index` · `ver` | `AdelantoSolicitudesModel::listarConFiltros()` | `vista_adelanto_solicitudes` | `adelantos_nomina/` |
| Aprobar / rechazar adelanto | `::aprobar` · `rechazar` · `cambiarEstado` | `AdelantoSolicitudesModel`, `AdelantoHistorialModel` | `adelanto_solicitudes`, `adelanto_historial` | — |
| Desembolsar | `::registrarDesembolso` | `AdelantoDesembolsosModel`, `AdelantoPlanDescuentoModel`, `AdelantoCuotasModel` | `adelanto_desembolsos`, `adelanto_plan_descuento`, `adelanto_cuotas` | — |
| Marcar cuota descontada | `::marcarCuotaDescontada` | `AdelantoCuotasModel` | `adelanto_cuotas` | — |
| Políticas de adelanto | `AdelantoPoliticasController::ver` · `editar` · `guardar` | `AdelantoPoliticasModel` | `adelanto_politicas` | `adelanto_politicas/ver.php` |
| **Portal:** solicitar adelanto | `AdelantosNominaPortalController::crear` · `guardar` | **`AdelantoSolicitudesModel::validarSolicitud()`** | `adelanto_solicitudes`, `adelanto_politicas` | `adelantos_nomina_portal/crear.php` |
| **Portal:** mis recibos | `::misRecibos` | `NominaLiquidacionesModel` | `vista_nomina_liquidaciones` | `adelantos_nomina_portal/mis_recibos.php` |
| **Portal:** certificado laboral | `::certificadoLaboral` | `ColaboradoresModel`, `ConfiguracionesModel` | `colaboradores`, `configuraciones` | `adelantos_nomina_portal/certificado_laboral.php` |

---

## 9. Beneficios

| Funcionalidad | Controlador::acción | Modelo | Tablas | Vista |
|---|---|---|---|---|
| Catálogo de beneficios | `BeneficiosController::index` · `crear` · `guardar` · `ver` | `BeneficiosModel` | `vista_beneficios`, `beneficios_reglas` | `beneficios/` |
| Activar / inactivar / archivar | `::activar` · `inactivar` · `archivar` | `BeneficiosModel` | `beneficios` | — |
| Solicitudes (admin) | `BeneficiosSolicitudesController::index` · `ver` | `BeneficiosSolicitudesModel::listarConFiltros()` | `vista_beneficios_solicitudes` | `beneficios_solicitudes/` |
| **Aprobar solicitud** | `::aprobar` | `BeneficiosSolicitudesModel::aprobarSolicitud()` + **`BeneficiosModel::aplicarConsumoAprobacion()`** | `beneficios_solicitudes`, `beneficios`, `beneficios_solicitud_historial` | — |
| Rechazar / entregar | `::rechazar` · `entregar` · `cambiarEstado` | `BeneficiosSolicitudesModel` | `beneficios_solicitudes` | — |
| Asignaciones | `BeneficiosAsignacionesController::asignar` · `asignarMasivo` · `entregar` · `cancelar` | `BeneficiosAsignacionesModel` | `beneficios_asignaciones` | `beneficios_asignaciones/index.php` |
| **Portal:** beneficios disponibles | `BeneficiosPortalController::disponibles` | **`BeneficiosModel::obtenerBeneficiosElegibles()`** | `beneficios`, `beneficios_reglas` | `beneficios_portal/disponibles.php` |
| **Portal:** solicitar | `::crearSolicitud` · `guardarSolicitud` | `BeneficiosSolicitudesModel::puedeSolicitarPorFrecuencia()` | `beneficios_solicitudes` | `beneficios_portal/crear_solicitud.php` |
| **Portal:** mis solicitudes / asignaciones | `::misSolicitudes` · `misAsignaciones` · `verSolicitud` · `cancelarSolicitud` | `BeneficiosSolicitudesModel`, `BeneficiosAsignacionesModel` | `vista_beneficios_*` | `beneficios_portal/` |

---

## 10. Capacitación (LMS)

| Funcionalidad | Controlador::acción | Modelo | Tablas | Vista |
|---|---|---|---|---|
| Cursos | `CapacitacionController::index` · `crear` · `guardar` · `ver` · `publicar` · `archivar` · `eliminar` | `CapacitacionCursosModel` | `vista_capacitacion_cursos` | `capacitacion/` |
| Lecciones | `CapacitacionLeccionesController::index` · `crear` · `guardar` · `eliminar` · `reordenar` | `CapacitacionLeccionesModel` | `capacitacion_lecciones` | `capacitacion_lecciones/` |
| Inscripciones | `CapacitacionInscripcionesController::index` · `asignar` · `asignarMasivo` · `marcarCompletado` · `cancelar` · `exportar` | `CapacitacionInscripcionesModel::asignar()` | `capacitacion_inscripciones` | `capacitacion_inscripciones/` |
| **Portal:** mis cursos | `CapacitacionPortalController::misCursos` · `verCurso` · `iniciar` | `CapacitacionInscripcionesModel` | `vista_capacitacion_inscripciones` | `capacitacion_portal/mis_cursos.php` |
| **Portal:** completar lección | `::completarLeccion` · `verProgreso` | `CapacitacionLeccionProgresoModel` | `capacitacion_leccion_progreso` | `capacitacion_portal/ver_progreso.php` |
| **Portal:** quiz | `::presentarQuiz` · `enviarQuiz` | `CapacitacionQuizModel`, `CapacitacionQuizPreguntasModel`, `CapacitacionQuizIntentosModel` | `capacitacion_quiz*` | `capacitacion_portal/quiz.php` |
| **Portal:** certificado (PDF) | `::descargarCertificado` · `misCertificados` | `CapacitacionCertificadosModel` + **mPDF** | `capacitacion_certificados` | `capacitacion_certificados/plantilla.php` |
| Validar certificado | `CapacitacionCertificadosController::validar` · `ver` · `generar` | `CapacitacionCertificadosModel` | `capacitacion_certificados` | — |

---

## 11. Servicio al colaborador

| Funcionalidad | Controlador::acción | Modelo | Tablas | Vista |
|---|---|---|---|---|
| Listar tickets | `TicketsController::index` | `ServicioTicketsModel::listarConFiltros()` | `vista_servicio_tickets` | `tickets/index.php`, `portal_index.php` |
| Crear ticket | `::crear` · `guardar` | `ServicioTicketsModel::generarCodigo()` | `servicio_tickets`, `servicio_ticket_historial` | `tickets/crear.php` |
| Ver ticket | `::ver` | `ServicioTicketComentariosModel`, `ServicioTicketHistorialModel` | `servicio_ticket_*` | `tickets/ver.php` |
| Asignar / cambiar estado / prioridad | `::asignar` · `cambiarEstado` · `cambiarPrioridad` | `ServicioTicketsModel::actualizarSlaEstado()` | `servicio_tickets`, `servicio_sla_politicas` | — |
| Responder | `::responder` | `ServicioTicketComentariosModel` | `servicio_ticket_comentarios` | — |
| Cerrar / calificar | `::cerrar` · `calificar` | `ServicioTicketsModel::recalcularSla()` | `servicio_tickets` | — |
| Centro de Ayuda | `CentroAyudaController::index` · `ver` · `adminIndex` · `crear` · `guardar` · `editar` · `eliminar` | `ServicioArticulosModel` | `vista_servicio_articulos` | `centro_ayuda/` |
| Configuración de servicio | `ServicioConfiguracionController::categorias` · `subcategorias` · `sla` (+ guardar/eliminar) | `ServicioCategoriasModel`, `ServicioSubcategoriasModel`, `ServicioSlaPoliticasModel` | `servicio_categorias`, `servicio_subcategorias`, `servicio_sla_politicas` | `servicio_configuracion/` |

---

## 12. Línea de ética

| Funcionalidad | Controlador::acción | Modelo | Tablas | Vista |
|---|---|---|---|---|
| **Público:** radicar denuncia | `LineaEticaPublicaController::crear` · `guardar` | `LineaEticaCasosModel::generarCodigoUnico()` + `generarPinTemporal()` + `crearPinHash()` | `linea_etica_casos`, `linea_etica_bitacora` | `linea_etica_publica/crear.php`, `confirmacion.php` |
| **Público:** seguimiento | `::seguimiento` · `verCaso` | `LineaEticaCasosModel::getByCodigo()` + `verificarPin()` | `linea_etica_casos`, `linea_etica_mensajes` | `linea_etica_publica/seguimiento.php`, `ver_caso.php` |
| **Público:** añadir mensaje | `::agregarMensaje` | `LineaEticaMensajesModel` | `linea_etica_mensajes` | — |
| **Gestión:** listar casos | `LineaEticaController::index` | `LineaEticaCasosModel::listarConFiltros()` + `getKpis()` | `vista_linea_etica_casos` | `linea_etica/index.php` |
| **Gestión:** ver caso | `::ver` | `LineaEticaMensajesModel`, `LineaEticaNotasInternasModel`, `LineaEticaBitacoraModel` | `linea_etica_*` | `linea_etica/ver.php` |
| Asignar / cambiar estado / prioridad | `::asignar` · `cambiarEstado` · `cambiarPrioridad` | **`LineaEticaCasosModel::puedeTransicionarEstado()`** | `linea_etica_casos`, `linea_etica_bitacora` | — |
| Responder / nota interna | `::responder` · `agregarNota` | `LineaEticaMensajesModel`, `LineaEticaNotasInternasModel` | `linea_etica_mensajes`, `linea_etica_notas_internas` | — |
| Cerrar / archivar | `::cerrar` · `archivar` | `LineaEticaCasosModel` | `linea_etica_casos` | — |
| Configuración | `::configuracion` · `guardarTipo` · `guardarCategoria` · `desactivarTipo` · `desactivarCategoria` | `LineaEticaTiposModel`, `LineaEticaCategoriasModel` | `linea_etica_tipos`, `linea_etica_categorias` | `linea_etica/configuracion.php` |

---

## 13. Comunicación interna

| Funcionalidad | Controlador::acción | Modelo | Tablas | Vista |
|---|---|---|---|---|
| Noticias (admin) | `ComunicacionInternaController::noticias` · `crearNoticia` · `guardarNoticia` · `verNoticia` · `publicarNoticia` · `archivarNoticia` | `ComunicacionNoticiasModel`, `ComunicacionNoticiasAudienciasModel` | `comunicacion_noticias`, `comunicacion_noticias_audiencias` | `comunicacion_interna/noticias_*.php` |
| Murales | `::murales` · `crearMural` · `guardarMural` · `publicarMural` · `archivarMural` · `ordenarMurales` | `ComunicacionMuralesModel` | `comunicacion_murales` | `comunicacion_interna/murales_*.php` |
| **Público:** portal de noticias | `::portalNoticias` | `ComunicacionNoticiasModel` | `comunicacion_noticias` | `comunicacion_interna/portal_noticias.php` |
| Notificaciones | `NotificacionesController::index` · `crear` · `enviarMasivo` · `marcarLeido` · `marcarTodasLeidas` · `configurar` | `ComunicacionNotificacionesModel` | `comunicacion_notificaciones` | `notificaciones/` |
| Mensajería interna | `MensajesInternosController::bandeja` · `nuevaConversacion` · `verConversacion` · `enviar` · `marcarLeido` · `archivar` | `ComunicacionConversacionesModel`, `ComunicacionMensajesModel`, `ComunicacionMensajesEstadoModel` | `comunicacion_conversaciones`, `comunicacion_mensajes`, `comunicacion_mensajes_estado` | `mensajes_internos/` |

---

## 14. Dashboard y portal

| Funcionalidad | Controlador::acción | Modelo | Tablas | Vista |
|---|---|---|---|---|
| Dashboard del backoffice | `HomeController::index` (14 agregadores) | Múltiples | `colaboradores`, `solicitudes_vacaciones`, `servicio_tickets`, `log_acceso`, `festivos`, `areas`, `cargos`, `sedes`, `metas_consolidado`, … | `home/admin.php` |
| Modal de selección de periodo | `::modalSede` | `PeriodosModel` | `periodos` | `home/seleccion_periodo_modal.php` |
| Cambiar filtro de sesión | `Controller::changeFiltersSesion` | `PeriodosModel::getAllFiltersSesion()` | `periodos` | — |
| **Portal:** inicio | `PublicController::home` · `gestiones` | `PublicModel` | Múltiples | `public/home.php`, `gestiones.php` |
| **Portal:** desempeño | `DesempenoController::home` | `MetasModel`, `EvaluacionesModel`, `TalentScoreService` | Múltiples | `desempeno/home.php` |
| **Portal:** tiempo y beneficios | `TiempoBeneficiosController::home` | `SolicitudesVacacionesModel`, `BeneficiosSolicitudesModel` | Múltiples | `tiempo_beneficios/home.php` |
| **Portal:** mi equipo | `MiEquipoController::index` · `colaborador` | `ColaboradoresModel::esLiderEquipo()`, `TalentScoreService::obtenerResumenEquipo()` | `colaboradores`, `potencial_evaluaciones`, `metas` | `mi_equipo/` |

---

## 15. Configuración y administración

| Funcionalidad | Controlador::acción | Modelo | Tablas | Vista |
|---|---|---|---|---|
| Configuración general | `ConfiguracionesController::view` · `editGeneral` · `removeConfig` | `ConfiguracionesModel::getValor()` | `configuraciones` | `configuraciones/view.php` |
| Roles | `RolesController` (CRUD) | `RolesModel` | `roles` | `roles/` |
| Usuarios | `UsuariosController::create` · `edit` · `view` · `remove` | `UsuariosModel` | `usuarios` | `usuarios/` |
| Cambiar contraseña | `UsuariosController::editPass` | `UsuariosModel::save(['Contrasena'])` + `PasswordPolicy` | `usuarios` | `usuarios/change_pass.php` |
| Cambiar foto | `UsuariosController::editPhoto` | `UsuariosModel` | `usuarios`, `files/usuarios/fotos/` | `usuarios/change_photo.php` |
| Permisos | `PermisosController` (CRUD) | `PermisosModel` | `permisos` | `permisos/` |
| Periodos | `PeriodosController` (CRUD) | `PeriodosModel` | `periodos` | `periodos/` |
| Sedes | `SedesController` (CRUD) | `SedesModel` | `sedes` | `sedes/` |
| Tipos de contrato | `TiposContratoController` (CRUD) | `TiposContratoModel` | `tipos_contrato` | `tipos_contrato/` |
| Cargos | `CargoAdministrativoController` (CRUD) | `CargosModel` | `cargos` | `cargos/` |
| Dependencias (áreas) | `DependenciasController` (CRUD) | `AreasModel` | `areas` | `dependencias/` |
| Alertas | `AlertasController::view` · `generate` · `toggleEstado` | `AlertasModel` | `alertas` | `alertas/` |
| Alertas por correo | `AlertasEmailController` (CRUD + `send`) | `AlertasEmailModel` + **PHPMailer** | `alertas_email` | `alertas_email/` |
| **Cron:** envío programado | `AlertasEmailController::sendCron` · `sendCronSolicitudAdmin` | `guardCronAccess()` + `ConfiguracionesModel` | `alertas_email`, `configuraciones` | — |
| IPs autorizadas | `IpsAutorizadasController` (CRUD) | `IpsAutorizadasModel` | `ips_autorizadas` | `ips_autorizadas/` |

---

## 16. Transversales

| Funcionalidad | Controlador::acción | Modelo/Servicio | Tablas | Vista |
|---|---|---|---|---|
| Asistente IA (interfaz) | `AsistenteIAController::index` | `AsistenteIAModel` | — | `asistente_ia/index.php` + `_asistente_ia_widget.php` |
| Asistente IA (consulta) | `::ask` | `AsistenteIAService` → `SQLGenerator` → `OllamaProvider` | Toda la BD (solo lectura) | — |
| Búsqueda rápida | `ApiController::quickSearch` | `QuickSearchModel::search()` | — | `public/js/quick-search.js` |
| Gestor de ficheros | `ElFinderController::conector` | **elFinder** | — | `files/` |
| Endpoints AJAX | `AjaxController::getAll` · `setAlertaVista` · `getEstadosPais` · `getCiudadesEstado` · `subirImagenBase64` · `textoAImagenBase64` | Varios | Varios | — |
| Permisos generales | `GeneralController::copy` · `dropFiles` | — | — | — |
| Sincronización académica | `SincronizacionController` (17 acciones) | 🔴 **Modelos inexistentes** | — | `sincronizacion/consola.php` |
| Pruebas | `TestController::index` · `test` · `modelTest` · `log` | `DebugModel` (🔴 inexistente) | — | `_test/`, `test/` |

---

## 17. De una tabla a su código

Índice inverso: dada una tabla, dónde se toca.

| Tabla | Modelo | Controlador(es) |
|---|---|---|
| `colaboradores` | `ColaboradoresModel` | `ColaboradoresController`, `PerfilColaboradorController`, `PublicController`, `MiEquipoController` |
| `usuarios` | `UsuariosModel` | `UsuariosController`, `LoginController` |
| `roles` / `permisos` | `RolesModel` / `PermisosModel` | `RolesController`, `PermisosController` |
| `periodos` | `PeriodosModel` | `PeriodosController`, `HomeController`, `PublicController` |
| `metas` | `MetasModel` | `MetasController`, `MetasColaboradorController` |
| `metas_consolidado` | `MetasConsolidadoModel` | `MetasController`, `TalentScoreService` |
| `evaluaciones` / `respuestas` | `EvaluacionesModel` / `RespuestasModel` | `EvaluacionesController`, `EvaluacionesColaboradorController` |
| `potencial_evaluaciones` | `PotencialEvaluacionesModel` | `PotencialesController`, `CarreraPortalController` |
| `planes_desarrollo` | `PlanesDesarrolloModel` | `PlanesDesarrolloController`, `PortalPlanesDesarrolloController`, `PlanesDesarrolloEquipoController` |
| `reclutamiento_*` | `Recruitment*Model` | `ReclutamientoController`, `PublicController` |
| `solicitudes_vacaciones` / `saldos_vacaciones` | `SolicitudesVacacionesModel` / `SaldosVacacionesModel` | `VacacionesController`, `VacacionesColaboradorController` |
| `asistencia_*` | `Asistencia*Model` | `AsistenciaController`, `TurnosController`, `AusenciasController` |
| `nomina_*` | `Nomina*Model` + `NominaCalculoModel` | `NominaController` |
| `adelanto_*` | `Adelanto*Model` | `AdelantosNominaController`, `AdelantoPoliticasController`, `AdelantosNominaPortalController` |
| `beneficios*` | `Beneficios*Model` | `BeneficiosController`, `BeneficiosSolicitudesController`, `BeneficiosAsignacionesController`, `BeneficiosPortalController` |
| `capacitacion_*` | `Capacitacion*Model` | `CapacitacionController`, `CapacitacionLeccionesController`, `CapacitacionInscripcionesController`, `CapacitacionPortalController`, `CapacitacionCertificadosController` |
| `servicio_*` | `Servicio*Model` | `TicketsController`, `CentroAyudaController`, `ServicioConfiguracionController` |
| `linea_etica_*` | `LineaEtica*Model` | `LineaEticaController`, `LineaEticaPublicaController` |
| `comunicacion_*` | `Comunicacion*Model` | `ComunicacionInternaController`, `NotificacionesController`, `MensajesInternosController` |
| `carrera_*` | `Carrera*Model` | `PlanesCarreraController`, `CarreraPortalController` |
| `sucesion_*` | `Sucesion*Model` | `SucesionController` |
| `reconocimiento*` | `Reconocimiento*Model` | `ReconocimientosController` |
| `talento_*` | *(sin modelo propio)* | `TalentScoreService`, `PotencialesController` |
| `configuraciones` | `ConfiguracionesModel` | `ConfiguracionesController` + consultado desde `Config` y muchos módulos |
| `log_*` / `bitacora_auditoria` | `Log*Model` / `BitacoraAuditoriaModel` | `core/Model::log()`, `NominaCalculoModel`, `ColaboradoresController::tabAuditoria` |

---

## Documentos relacionados
- [04_MODULES.md](04_MODULES.md)
- [05_DATABASE.md](05_DATABASE.md)
- [10_BUSINESS_LOGIC.md](10_BUSINESS_LOGIC.md)
- [19_DEPENDENCY_MAP.md](19_DEPENDENCY_MAP.md)
