# 04 — Módulos funcionales (mapa del código)

Cada módulo = un controlador (`app/controllers/<X>Controller.php`) + un modelo principal
(`app/models/<X>Model.php`) + una carpeta de vistas (`app/views/<modulo>/`).
El nombre del módulo se declara en `public static $MODULE_NAME` y **es el que aparece en la URL**
(`?c=<MODULE_NAME>&a=<accion>`) y el que se usa como clave en la tabla `permisos`.

Notación de acciones: las marcadas `*` son públicas (sin sesión), `@` requieren sesión + permiso.

---

## 4.1 Núcleo transversal

### `login` — `LoginController`
Acceso al **backoffice**. `admin` (`*`) y `klee` (`*`, fuerza login manual) pintan el formulario;
`validate` (`*`) autentica contra `usuarios` vía `UsuariosModel::validateUser()`; `logout` (`@`)
destruye `$_SESSION[appId]`. Layout `metronicEmpty`.

### `public` — `PublicController` (1.088 líneas, el más grande del portal)
Es **todo el portal público**. Ver detalle de flujos en [05](05-flujos-clave.md).
- Acceso: `index` `*` (login automático SSO o manual según `LOGIN_AUTOMATICO`/`LOGIN_MANUAL`), `loginManual` `*`, `validate` `*`, `validated` `*` (callback OAuth Microsoft), `validateChange` `*` (cambiar de rol), `manual` `*`.
- Comunes: `home`, `gestiones` (muestra ventanas de fechas del periodo).
- Estudiante: `estudiantesSeleccion`, `estudiantesEvaluacion`.
- Docente: `docentesAutoSeleccion`, `docentesAutoEvaluacion`, `docentesSeleccion`/`docentesEvaluacion` (pares), `docentesPlanes(+Create/Edit/Remove/View)`, `docentesDesempeno`, `docentesActas`, `docentesActasView`, `docentesConvocatorias`, `docentesEscalafonEstado`.
- Director/Líder: `directoresMisDocentes`, `directoresSeleccion`, `directoresEvaluacion`, `directoresLabores`, `directoresLaboresView`, `directoresPostulaciones`.
- Método clave: `verificarGestion()` — bloquea la acción si la fecha actual está fuera de la ventana del rol en el periodo, y **salta automáticamente a otro periodo abierto** si lo encuentra.

### `home` — `HomeController`
Dashboards. `index` (admin, arma tres donuts desde la caché `graficas` con códigos `GEED`, `GAD`, `GED`),
`default`, `docente`, `estudiante`, `director`, `liderNacional` (uno por rol; `roles.Inicio` decide
a cuál se envía a cada usuario) y `modalSede` (fragmento AJAX de selección de periodo).

### `ajax` — `AjaxController`
Endpoints JSON para selects dependientes y widgets. Todos validan cabecera `X-Requested-With`.
`getAll` (catálogo genérico: Asignaturas, Estudiantes, Facultades, Programas, ResumenEvaluacion,
EstudiantesRespuestas), `update`, `setAlertaVista`, `getResumen`, `getDocente`, `getDocentes`,
`getProductosIntelectuales`, `getReporteEvaluaciones`, `subirImagenBase64`, `textoAImagenBase64`
(genera la imagen de una firma manuscrita a partir de texto + fuentes de `app/fonts/`).

### `general` — `GeneralController`
Utilidades de UI: `copy`, `dropFiles`.

### `test` — `TestController`
Banco de pruebas de desarrollo (`index`, `test`, `modelTest`, `log`). No usar en producción.

---

## 4.2 Configuración (menú "Configuración")

| Módulo | Controlador | Notas |
|---|---|---|
| `configuraciones` | `ConfiguracionesController` | `view` + `editGeneral`. Edita el clave-valor de la tabla `configuraciones` agrupado por `Grupo` (pesos de consolidación, plantillas de notificación, banderas de envío) |
| `roles` | `RolesController` | CRUD de roles |
| `permisos` | `PermisosController` | Matriz de permisos por rol y módulo. Lee las acciones de cada controlador y los `Tabs` |
| `alertas` | `AlertasController` | `view`, `generate` — alertas in-app |
| `periodos` | `PeriodosController` | CRUD de periodos + `clone`. Es el módulo de referencia para el patrón CRUD (ver [08](08-guia-desarrollo.md)) |
| `sedes` / `facultades` / `programas` / `asignaturas` | homónimos | CRUD de estructura académica |
| `usuarios` | `UsuariosController` | CRUD + `editPass` + `editPhoto` |
| `tipoLaborDocente` | `TipoLaborDocenteController` | Catálogo de tipos de labor, con `Area` e `IdDirector` |
| `preguntas` | `PreguntasController` | CRUD del banco de preguntas (`Tipo`, `Metodologia`, `Area`, `Peso`, `Orden`) |
| `ipsAutorizadas` | `IpsAutorizadasController` | Lista blanca de IPs (activable con `Config::$IP_BLOCKING`) |

---

## 4.3 Personas

| Módulo | Controlador | Acciones destacadas |
|---|---|---|
| `estudiantes` | `EstudiantesController` | CRUD + `reopen` (reabrir evaluaciones cerradas) + `buscar` |
| `docentes` | `DocentesController` | CRUD + `reopen`, `editPhoto`, `changePass`. Tabs con educación/experiencia/investigaciones |
| `directores` | `DirectoresController` | CRUD + `reopen` + `asignar` (asignar docentes a un director) |
| `docentesEducacion` / `docentesExperiencia` / `docentesInvestigaciones` | homónimos | Sub-CRUD del perfil docente |
| `docentesAsignaturas` / `estudiantesAsignaturas` | homónimos | CRUD de la carga académica (normalmente la llena la sincronización) |
| `docentesPares` | `DocentesParesController` | Asignación de pares evaluadores |

---

## 4.4 Evaluación y resultados

| Módulo | Controlador | Qué hace |
|---|---|---|
| `consolidados` | `ConsolidadosController` | `evaluaciones` ejecuta la **consolidación** (ver [05.3](05-flujos-clave.md#53-consolidación-de-resultados)); `graficaEstudiante`, `graficaAutoevaluacion`, `graficaDirector`, `graficaDirectorNacional` (`*`) generan/actualizan la caché de la tabla `graficas` |
| `planes` | `PlanesController` | CRUD de planes de mejora + `list` |
| `notificaciones` | `NotificacionesController` | `configurar` (plantillas), `list` (interruptor de envíos), `estudiantes`/`docentes`/`directores` (**encolan** correos a los pendientes, en lotes de 500 destinatarios) |
| `alertasEmail` | `AlertasEmailController` | CRUD de la cola de correos + `send` (envío manual) + **`sendCron` (`*`)**: procesa 2–4 alertas pendientes con `sleep(5)` entre cada una. Pensado para invocarse desde un cron externo |
| `reportes` | `ReportesController` | ~34 acciones de reporte. Familias: `general`/`desempeno`/`consolidado`; por fuente (`estudiantes`, `autoevaluaciones`, `directores`, `directoresNacionales`, `facultades`); `estados*` (avance de diligenciamiento); `respuestas*` (detalle pregunta a pregunta); `observaciones*` + `observacionesIA`; `ods`, `actas`, `resumenLabor`; `convocatorias*`. Las variantes `*Ajax` son el endpoint DataTables de su reporte |
| `graficas` | `GraficasController` | Dashboards Highcharts: `general`, `generalSede`, `estudiantes`, `estudiantesPrograma`, `estudiantesGrupo`, `autoevaluacion`, `directores`, `directoresNacionales`, `programas`, `planes`, `planesSede`, `laborDocente`, `laborDocenteSede`, `analisisIA` |
| `archivos` | `ArchivosController` | Exportación e importación masiva: `exportPDF` (recibe HTML por POST y lo pasa por **mPDF**), `generarCarta` (cartas de escalafón con plantillas FOR-PAJ-70/71), `importPostulaciones`, `importEscalafonDocente`, `importObservacionesClasificacion`, `importResumenEvaluacion`, `generarCandidatos`, más scripts de corrección puntual (`arreglarResultados`, `ajustarMetodologias`) |
| `sincronizacion` | `SincronizacionController` | Consola de sincronización con Academusoft e IA (ver [05.5](05-flujos-clave.md#55-sincronización-con-academusoft) y [05.4](05-flujos-clave.md#54-análisis-con-ia)) |

---

## 4.5 Gestión docente y contratación

| Módulo | Controlador | Qué hace |
|---|---|---|
| `laborDocente` | `LaborDocenteController` | CRUD de labores + `importLabores` (importa desde un sistema externo por periodo) |
| `proyectos` / `proyectosDocentes` / `proyectosEntregables` | homónimos | Proyectos institucionales, su asignación a docentes (ligada a la ODS) y sus entregables |
| `ods` | `OdsController` (870 líneas) | CRUD + `generar` (crea ODS masiva por programa), `director`, `recibir`, `imprimir`, `imprimirLabor`, `corregirLabor`, `labor` |
| `odsDocentes` | `OdsDocentesController` | Línea de la ODS por docente + `firmarActa` |
| `ops` | `OpsController` | Órdenes de prestación de servicios + `check` (aprobación) + `getNombre` |
| `requisiciones` | `RequisicionesController` | CRUD + flujo por estado: `solicitadas`, `recibidas`, `seleccionadas`, `listaNN`, `devolver`, `buscar`, `getSalario`, `imprimir` |
| `contratacion` | `ContratacionController` | Registro de contratos firmados |

## 4.6 Escalafón docente

| Módulo | Controlador | Qué hace |
|---|---|---|
| `escalafon` | `EscalafonController` | CRUD de categorías del escalafón (puntajes y salarios por dedicación) |
| `produccionIntelectual` | `ProduccionIntelectualController` | Catálogo de productos con puntaje |
| `convocatorias` | `ConvocatoriasController` | CRUD + `resultados`, `docente` (evaluación individual del ascenso), `postulados`, `postulaciones` (calificación de evidencias) |

Lógica de ascenso (en `ConvocatoriasController::docenteAction()`):
`PuntajeTotal = docentes_convocatorias.PuntosAcumulados + Σ postulaciones.Calificacion`;
se compara con `escalafon.PuntajeRequerido<Dedicacion>` de la **siguiente** categoría
(`EscalafonModel::siguienteEscalafon()`). Los motivos de no-ascenso son la lista `$requisitos`
de `ArchivosController`.

---

## 4.7 Módulos sin tabla propia

| Modelo | Rol |
|---|---|
| `PublicModel` | Autenticación y multi-rol del portal público |
| `SincronizacionModel` | Cliente HTTP del API Academusoft |
| `ReportesModel` | Consultas agregadas para reportes |
| `LogAccionesModel` | Fachada de auditoría (`saveAccess`) |
| `DebugModel` | Bitácora de desarrollo |
| `OllamaService` (en `app/services/`) | Cliente del LLM |
