# Migración: Portal Docentes → `admin_docentes/`

Plan de migración del portal de docentes, desde el legacy
`F:\laragon\Jesistemas\uepca\docentes\` (BD `jesistem_uepca`, deploy de un
solo colegio) hacia un módulo multi-tenant nuevo `admin_docentes/` en este
repo, siguiendo el mismo patrón que ya se aplicó a `admin_alumnos/` (ver
`CLAUDE.md`).

Este documento es el mapa maestro. **Fases 0 (Fundación), 1
(Calificaciones), 2 (Evaluaciones en Línea), 3 (Aula Virtual) y 4
(Comunicación) ya están migradas** — ver sección 4 y
`admin_docentes/documentacion/fase0-fundacion-migracion.md` /
`fase1-calificaciones-migracion.md` / `fase2-evaluaciones-migracion.md` /
`fase3-aula-virtual-migracion.md` / `fase4-comunicacion-migracion.md`. El
resto de las fases no se han migrado; el legacy sigue en producción
sirviendo tráfico real y así se mantiene hasta que cada fase quede migrada,
probada contra un colegio real y aprobada. Cada
fase, al completarse, agrega su propio `.md` en esta misma carpeta (mismo
criterio que `documentacion/evaluaciones-en-linea-migracion.md`, que de
hecho ya deja anotado el pendiente que este documento retoma: *"el lado
docente... queda fuera de este trabajo: no existe todavía un portal de
docentes en este repo"*) y este archivo se actualiza marcando la fase como
hecha.

## 1. Alcance y estado actual

`uepca/docentes/` (~90 archivos `.php`) es el portal donde los docentes:
cargan notas (primaria y bachillerato/liceo), suben material de clases y
video-clases, gestionan el banco de preguntas y las evaluaciones en línea,
corrigen respuestas de texto libre, se comunican con estudiantes/
representantes, consultan su ficha personal/carnet/horario, y generan
algunos reportes (boletas, históricos, cortes).

Depende de infraestructura legacy fuera de `docentes/`:

| Archivo | Uso |
|---|---|
| `uepca/conexion.php` | `Conectarse()` real (mysqli, hardcoded a una sola BD). Distinto de `uepca/docentes/conexion.php`, que es un stub viejo con `mysql_connect` (API `mysql_*` deprecada) — **no se usa**, no migrar. |
| `uepca/inicia.php` | Define constantes institucionales (`NKXS`, `EKKS`, `ANOESCM`, `DOMINIO`, etc.) — equivalente legacy de `cargar_config_legacy()` en este repo. |
| `uepca/includes/funciones.php` | `encriptar()`/`desencriptar()` y utilidades — ya existen en `core/funciones.php` de este repo, no se duplican. |
| `uepca/login.php` | Login único para alumnos y docentes contra `alumcer`, diferenciado por `cargo`. Ya tiene su equivalente migrado en `admin_alumnos/login.php`. |

No es multi-tenant (no usa `resolver_tenant()`/`db_colegio()`), no usa
prepared statements (concatenación directa de `$_SESSION`/`$_POST` en SQL en
casi todo el módulo), y su UI es Bootstrap 3 suelto con `sweetalert-master`
vendored — no coincide con SB Admin 2 / Bootstrap 4 / Font Awesome que ya usa
el resto del portal migrado.

**Fuera de alcance de este plan** (no se migran): variantes duplicadas
detectadas por nombre de archivo — sufijos `-ORI`, `-VIE`, `-vieja`, `_res`,
y archivos "hermanos" viejos (`index1.php`, `login-VIE.php`,
`examen-list-ORI.php`, `preguntas-list-ORI.php`, `examen-perfil-ORI.php`,
`examen-vistos-ORI.php`, `notabachi_n-vie.php`, `notabachi_n_res.php`,
`guarnotas-VIE.php`, `guarnotasviejo.php`, `list-tareas-VIE.php`,
`listmateprof-vie.php`, `listmateprof_res.php`, `list-alu-hist-vie.php`,
`fichaprof-VIE.php`, `archivosMateria-VIE.php`, `guardarprof-VIE.php`,
`guarnotabachi-n-vie.php`, `verTarea-VIE.php`). Antes de descartar cada uno
en su fase correspondiente, confirmar que no recibe tráfico real (no solo
por el nombre) — no se asume en bloque.

## 2. Arquitectura objetivo

Replica el patrón ya validado en `admin_alumnos/`:

- **Bootstrap**: cada script de `admin_docentes/` hace
  `require_once '../bootstrap.php'` (igual que `admin_alumnos/login.php`) →
  `resolver_tenant()` + `cargar_config_legacy()` + `cargar_modulos()`. No
  existe un tenant separado para docentes: es el mismo colegio, la misma
  `$_SESSION['tenant_bdColeg']`, la misma BD.
- **DB**: mismo `db_colegio($bdColeg)` / `Conectarse()` legacy que ya usa
  `admin_alumnos`. No se crea conexión ni BD nueva.
- **Sesión de docente**: reutiliza las claves que ya escribe
  `admin_alumnos/login.php` contra `alumcer` (`usuario`, `cargo`, `idAlum`,
  `nomuser`, `apelluser`, `tablaPeriodo`, `periodoActivo`, `lapsoActivo`) y
  agrega las que hoy calculan `uepca/login.php` (rama `cargo>1`) y
  `uepca/docentes/sesion.php` de forma duplicada:
  - `maeDa` ('S'/'N') — tiene grados asignados en
    `trgsp{periodo} A JOIN grado{periodo} B ON A.id_grado1=B.grado OR A.id_grado2=B.grado WHERE A.ced_prof=<cedula>` → acceso a opciones de **Primaria**.
  - `docDa` ('S'/'N') — tiene secciones asignadas en
    `trgsmp{periodo} A JOIN grado{periodo} B ON A.cod_grado=B.grado WHERE A.cod_grado>60 AND A.ced_prof=<cedula>` → acceso a opciones de **Bachillerato/Liceo**.
  - `idAlum` de la fila de `alumcer` hace de `idDocente` (mismo id, no hay
    tabla `docente` separada — es la misma persona/registro que un alumno
    con `cargo>1`).
  Este cálculo queda en **un solo lugar** en el portal migrado (ver punto
  siguiente), no duplicado como en el legacy.
- **Login (fix, no login nuevo)**: `admin_alumnos/login.php:202-204` ya
  detecta `cargo > 1` pero redirige a una ruta rota
  (`../docentes/index.php`, inexistente en este repo). Se completa esa rama:
  calcular `maeDa`/`docDa` ahí mismo y redirigir a `admin_docentes/home.php`.
  **Decisión confirmada**: no se crea `admin_docentes/login.php` — un solo
  formulario de acceso para todo el colegio, igual que hoy.
- **Gating de módulos**: se reutiliza `core/modulos.php`
  (`requiere_modulo()`, `modulo_habilitado()`, `cargar_modulos()`) sin
  cambios de firma. `MODULOS_CON_MOROSO` **no aplica** a docentes (son
  personal, no deudores) — sus slugs no entran en esa lista.
- **Slugs**: el catálogo `modulos` es global (`slug` UNIQUE) y ya usa
  nombres del lado alumno (`calendario`, `chat-docentes`, `material`,
  `docente-guia`...). Los módulos del portal docente usan **prefijo `doc-`**
  para no colisionar y para que `panel_admin` los agrupe aparte:

  | Slug | Nombre | grupo_menu |
  |---|---|---|
  | `doc-perfil` | Mi Perfil (docente) | — |
  | `doc-carnet` | Carnet de Empleado | — |
  | `doc-horario` | Mi Horario | — |
  | `doc-notas-primaria` | Carga de Notas — Primaria | Docentes - Calificaciones |
  | `doc-notas-bachillerato` | Carga de Notas — Bachillerato/Liceo | Docentes - Calificaciones |
  | `doc-material` | Material de Clases | Docentes - Aula Virtual |
  | `doc-video-aula` | Video Clases | Docentes - Aula Virtual |
  | `doc-preguntas` | Banco de Preguntas | Docentes - Evaluaciones |
  | `doc-examenes` | Evaluaciones en Línea | Docentes - Evaluaciones |
  | `doc-calendario-evaluaciones` | Calendario de Evaluaciones | Docentes - Evaluaciones |
  | `doc-chat-alumnos` | Mensajes con Estudiantes | Docentes - Comunicación |
  | `doc-comunicados` | Comunicados a Estudiantes | Docentes - Comunicación |
  | `doc-guia` | Observaciones Docente Guía | Docentes - Comunicación |
  | `doc-boletas` | Boletas / Reportes | Docentes - Reportes |

  Nombres definitivos y agrupación se ajustan al implementar cada fase; esta
  tabla es la propuesta base.
- **Layout**: `admin_docentes/layout/base.php`, clonado de
  `admin_alumnos/layout/base.php` (misma paleta SB Admin 2 / Bootstrap 4 /
  Font Awesome, mismo patrón `ob_start()` + `$pageTitle`/`$activePage` +
  `require layout/base.php`). Sidebar propio con las secciones: Inicio, Mi
  Perfil, Calificaciones (Primaria/Bachillerato condicionadas a
  `$_SESSION['maeDa']`/`$_SESSION['docDa']`), Aula Virtual, Evaluaciones en
  Línea, Comunicación, Reportes.
- **Assets**: `admin_docentes/assets/{css,js,vendor,img}` — copia propia,
  mismo criterio que ya usa `admin_alumnos/assets/` (carpeta por portal, sin
  symlink).
- **Ajuste necesario en helper compartido**: `core/perfil_colegio.php` →
  `logo_colegio_actual()` devuelve una ruta **relativa a `admin_alumnos/`**
  (`colegios/<carpeta>/img/logo.png`). Si `admin_docentes/layout/base.php`
  la usa tal cual, la ruta queda rota (cwd distinto). Al implementar la Fase
  0 hay que generalizar la función (parámetro de carpeta base, ej.
  `logo_colegio_actual(string $default, string $baseDir = 'admin_alumnos')`)
  o anteponer `../admin_alumnos/` al resultado desde `admin_docentes`. No
  duplicar el helper.
- **`panel_admin/colegio.php`** ya es genérico (itera `modulos` agrupado por
  `grupo_menu`) — no necesita cambios de código, solo los `INSERT` en el
  catálogo `modulos` de cada fase.

## 3. Inventario de archivos legacy → destino

Todas las tablas listadas ya viven en la BD de cada colegio (`db_colegio`) y
ya las usa `admin_alumnos` del lado alumno, **salvo que se compruebe lo
contrario al implementar cada fase** — no se asume, se verifica contra la BD
real del colegio piloto (punto QA obligatorio de `CLAUDE.md`).

### Fundación (Fase 0)

| Origen (`uepca/docentes/`) | Destino (`admin_docentes/`) | Tablas BD | Notas |
|---|---|---|---|
| `index.php` | `home.php` | `chat` | Menú principal; hoy condiciona botones por `maeDa`/`docDa`. Reescribir como sidebar + tarjetas del layout, no como grid de imágenes-botón. |
| `sesion.php` | — (se elimina) | `alumcer`, `trgsp{p}`, `trgsmp{p}`, `grado{p}` | Absorbido por el fix de `admin_alumnos/login.php` (cálculo de `maeDa`/`docDa` en un solo lugar). |
| `encabezado1.php` + `footer1.html` | — (se elimina) | — | Absorbido por `admin_docentes/layout/base.php`. |
| `fichaprof.php` | `perfil.php` | `alumcer`, `cargos` | Datos personales del docente. |
| `carnet.php` | `carnet.php` | `alumcer` | Igual patrón que `admin_alumnos/carnet.php` (PDF vía FPDF/Composer, no `admin_alumnos/fpdf/` legacy). |
| `horario-pdf.php` | `horario.php` | `horario_grado`, `horario_docentes`, `horario_dias` | Confirmar existencia de estas 3 tablas en BD piloto antes de migrar — no confirmado en este análisis. |
| `tutorial.php`, `tutoPower.php`, `tutoYou.php` | `manual.php` (o carpeta `tutoriales/`) | — | Contenido estático/embebido, bajo riesgo. |

### Fase 1 — Calificaciones (migrada — ver `fase1-calificaciones-migracion.md`)

| Origen | Destino | Tablas BD | Notas |
|---|---|---|---|
| `bus-gra-secprof.php` + `bus-gra-sec2prof.php` | `notas-primaria.php` | `trgsp{p}`, `grado{p}`, `secciones`, `alumcer` | Selector grado/sección + listado de alumnos, combinados en un solo archivo. |
| `carganotapri.php` | `notas-primaria-boletin.php` | `notaprimaria{p}`, `grado{p}`, `boletas{p}` | Boletín A-E por materia/indicador, un alumno. |
| `guarnotas.php` | `notas-primaria-guardar.php` | `notaprimaria{p}` | Guarda el boletín. Reescrito con prepared statements. |
| `listmateprof.php` | `mis-materias.php` | `trgsmp{p}`, `materiass{p}`, `cortes1{p}` | Materias asignadas al docente (bachillerato). |
| `notabachi_n.php` | `notas-bachillerato.php` | `cortes{p}`, `cortes1{p}`, `alumcer`, `preinscripcion` | Carga masiva de notas por grado/sección/materia/estrategia. |
| `guarnotabachi-n.php` | `notas-bachillerato-guardar.php` | `cortes{p}`, `cortes1{p}`, `evalua_calendario`, `matri{p}` | Guarda notas + recalcula promedio ponderado del lapso en `matri`. |
| `bus-gra-secMae.php`, `busGraVid.php` | (no son de Calificaciones) | — | `bus-gra-secMae.php` va a "Tareas de Primaria" (`list-tareasPri.php`, Fase 3); `busGraVid.php` a Video Aula (Fase 3). Corrección sobre la categorización original de este plan. |
| `guarnotasviejo.php`, `guarnotabachi-n2.php`, `guarnotabachi-n-vie.php`, `guarnotas-VIE.php`, `notabachi_n_res.php`, `notabachi_n-vie.php`, `listmateprof_res.php`, `listmateprof-vie.php` | — (excluidos) | — | Confirmado por grafo real de enlaces (`action=`/`href=`) que no son alcanzables desde `index.php` — duplicados sin uso vigente. |
| `materias-buscar.php` | endpoint AJAX | `materiass{p}` | — |

### Fase 2 — Evaluaciones en línea (lado docente, migrada — ver `fase2-evaluaciones-migracion.md`)

Se apoya 100% en el esquema ya creado por `db/fase9-evaluaciones-online.sql`
y en el trabajo ya migrado del lado alumno
(`documentacion/evaluaciones-en-linea-migracion.md`), que dejó esto como
pendiente explícito. `examen-perfil.php`/`examen-corregir.php`/`examenes-list.php`
absorbieron los ~10 endpoints AJAX del legacy (guardado campo-por-campo,
modales) en formularios normales — ver `fase2-evaluaciones-migracion.md`
para el detalle exacto de la consolidación.

| Origen | Destino | Tablas BD | Notas |
|---|---|---|---|
| `preguntas-list.php`, `preguntas-buscar-ajax.php`, `pregunta-ver-agrega.php` | `preguntas-list.php` + endpoints AJAX | `examen_pregunta`, `examen_opciones` | Banco de preguntas (simple/múltiple/texto). |
| `examen-list.php` | `examenes-list.php` | `examen_varios` | Listado + creación de evaluaciones. |
| `examen-perfil.php` | `examen-perfil.php` | `examen_varios`, `examen_preguntas`, `examen_pregunta` | Arma un examen a partir del banco de preguntas. |
| `examen-corregir.php`, `examen-nota-actual.php`, `examen-nota-observacion.php` | `examen-corregir.php` | `examen_respuesta`, `examen_notas` | Corrección manual de preguntas de texto libre — la única parte que el lado alumno no puede autocalificar. |
| `examen-vistos.php` | `examen-vistos.php` | `examen_vio`, `examen_respuesta` | Quién abrió/respondió. |
| `examen-resultados.php` | `examen-resultados.php` | `examen_notas`, `examen_respuesta` | Notas consolidadas por examen. |
| `examen-respuesta-borrar.php`, `examen-pregunta-quitar-ajax.php`, `examen-pregunta-ver-ajax.php` | endpoints AJAX | `examen_respuesta`, `examen_preguntas` | — |
| `calendario.php` (el de `docentes/`, crea eventos) | `doc-calendario-evaluaciones.php` | `evalua_calendario`, `trgsmp{p}`, `grado{p}`, `secciones` | Distinto del `calendario.php` de `admin_alumnos` (ese es de actividades institucionales, solo lectura). |
| — (gap ya anotado en la migración de exámenes) | — | — | Imágenes de preguntas (`imagen_question/`) — decidir dónde viven al implementar esta fase; mismo patrón que `fotoalu/`/`fotorep/` por dominio legacy de colegio. |

**DB**: agregar los slugs `doc-preguntas`, `doc-examenes`,
`doc-calendario-evaluaciones` al catálogo `modulos` vía nuevo archivo
`db/fase10-portal-docentes.sql` (Parte A en `siscev`). No se esperan tablas
nuevas — `fase9` ya las creó.

### Fase 3 — Aula Virtual (lado docente)

| Origen | Destino | Tablas BD | Notas |
|---|---|---|---|
| `archivosMateria.php` | `material.php` | `materiass{p}`, `tareas{...}`/`tareaspri{...}` | Contraparte docente de `admin_alumnos/material.php` (que ya existe del lado alumno). |
| `videoMateriaDoc.php`, `videoListPri.php`, `videoListBach.php` | `video-aula.php` | `video{p}`, `videopri{p}` | Contraparte docente de `admin_alumnos/video-aula.php`. |
| `buscarVideo.php`, `buscarVideoPri.php` | endpoint AJAX | `video{p}`, `videopri{p}` | — |
| `list-tareas.php`, `list-tareasPri.php` | fusiona con `material.php` | `tareas{...}`, `tareaspri{...}` | — |
| `verTarea.php`, `verTareaPri.php` | vista de detalle en `material.php` | `tareas{...}`, `vio_tarea` | — |

### Fase 4 — Comunicación

| Origen | Destino | Tablas BD | Notas |
|---|---|---|---|
| `contactoAlum.php` | `chat-alumnos.php` | `chat` | Contraparte docente de `admin_alumnos/chat-docentes.php`. Mismo `chat`, filtrado por `id_docente`. |
| `chat-buscar.php`, `chat-nuevo.php` | endpoints AJAX | `chat` | — |
| `list-archivos.php`, `comunicado-buscar.php` | `comunicados.php` | `tbl_documentos` | Contraparte docente de `admin_alumnos/publicacion.php`/`comunicados.php`. |
| `observ-guia.php`, `guarda-obs-guia2.php` | `docente-guia.php` | `observa_guia`, `observa_guia_alum` | Contraparte docente de `admin_alumnos/docente-guia.php` (que hoy es solo lectura del lado alumno). |

### Fase 5 — Reportes / misceláneos

| Origen | Destino | Tablas BD | Notas |
|---|---|---|---|
| `boletas-list.php`, `boleta-pri.php`, `boleta_pri.php`, `boleta-actual.php`, `boleta-perfil.php` | `boletas.php` | `boletas`, `notas{...}`, `notaprimaria{p}` | Varias variantes casi duplicadas — unificar, no migrar las 5 tal cual. |
| `hist-alu.php`, `list-alu-hist.php`, `list-historial.php`, `ver-historial.php` | `historial.php` | `historial` | — |
| `rep-cortes.php` | `rep-cortes.php` | `cortes`, `cortes1` | — |
| `revisionPdfListado.php` | `revision-pdf.php` | `tbl_documentos` | Confirmar objeto real antes de migrar (nombre ambiguo). |

## 4. Fases de implementación

- [x] **Fase 0 — Fundación**: fix de login, `bootstrap.php`, `layout/base.php`,
  sidebar, `home.php`, `perfil.php`/`carnet.php`/`horario.php` (tutoriales
  quedaron fuera de esta pasada, ver detalle abajo). Incluye el ajuste de
  `logo_colegio_actual()`. Detalle completo, bugs encontrados y verificación
  end-to-end en `fase0-fundacion-migracion.md`.
- [x] **Fase 1 — Calificaciones**: carga de notas primaria y
  bachillerato/liceo, listado de materias, selectores grado/sección.
  Detalle completo, hallazgos de esquema (específicos de
  `jesistem_juanxxiii`) y verificación end-to-end en
  `fase1-calificaciones-migracion.md`.
- [x] **Fase 2 — Evaluaciones en línea (docente)**: banco de preguntas,
  armado de exámenes, corrección de texto libre, resultados, calendario de
  evaluaciones. Cierra el pendiente de `evaluaciones-en-linea-migracion.md`.
  Detalle completo, bugs encontrados (incl. fix de timezone global en
  `bootstrap.php`) y verificación end-to-end en
  `fase2-evaluaciones-migracion.md`.
- [x] **Fase 3 — Aula Virtual (docente)**: material de clases (con fecha de
  entrega) y video-clases, Primaria y Bachillerato/Liceo. Detalle completo,
  verificación end-to-end y un hallazgo de higiene de datos (dato de prueba
  con cédula real encontrado y borrado con autorización del usuario) en
  `fase3-aula-virtual-migracion.md`.
- [x] **Fase 4 — Comunicación**: mensajes con estudiantes (solo responde
  hilos ya iniciados por el alumno), comunicados a grado/sección/materia,
  observaciones de docente guía (tablas `observa_guia`/`observa_guia_alum`
  nuevas — no existían en la BD del colegio piloto). Detalle completo, bug
  de `bind_param` encontrado y corregido, y verificación end-to-end en
  `fase4-comunicacion-migracion.md`.
- [ ] **Fase 5 — Reportes / misceláneos**: boletas, históricos, cortes.

Cada fase completada agrega su propio `.md` en `admin_docentes/documentacion/`
(mismo formato que `documentacion/evaluaciones-en-linea-migracion.md`:
alcance, archivos origen→destino, decisiones de diseño, migración de BD,
cómo activar el módulo, pendientes) y marca su casilla aquí arriba.

## 5. Base de datos

Nuevo archivo `db/fase10-portal-docentes.sql`, mismo patrón que
`fase9-evaluaciones-online.sql`:

- **Parte A** (`siscev`, una sola vez): `INSERT IGNORE INTO modulos (...)`
  con los slugs `doc-*` de la fase que se esté implementando (no se cargan
  todos de una vez — cada fase agrega los suyos cuando se implementa, igual
  que se hizo con `examenes-list` en `fase9`).
- **Parte B** (BD de cada colegio que active el módulo): solo si una fase
  descubre que le falta una tabla que no está ya en uso por `admin_alumnos`
  (ej. `horario_grado`/`horario_docentes`/`horario_dias`, a confirmar en
  Fase 0). No se crean tablas especulativamente — se verifica primero contra
  la BD real del colegio piloto.

## 6. QA obligatorio por fase

Aplicar íntegro el checklist de `CLAUDE.md` → "QA Obligatorio Post-Cambio" en
cada fase, en particular:

- Aislamiento multi-tenant: toda query nueva usa `db_colegio($bdColeg)` del
  colegio en sesión, nunca un `id_colegio`/BD hardcodeado.
- Prepared statements en el 100% de las queries nuevas o reescritas (el
  legacy concatena `$_SESSION`/`$_POST` directo — no se copia ese patrón).
- `htmlspecialchars()` en todo output.
- Cada script nuevo llama `requiere_modulo('doc-...')` al inicio.
- Sigue el patrón `ob_start()` + `$pageTitle`/`$activePage` + `layout/base.php`.
- Sin `var_dump`/`echo` de depuración.
- Probado contra al menos un colegio real (mismo colegio piloto usado en
  `evaluaciones-en-linea-migracion.md`: `jesistem_juanxxiii`, id 11), no solo
  en abstracto.

## 7. Riesgos y puntos abiertos

- `logo_colegio_actual()` necesita generalizarse para funcionar fuera de
  `admin_alumnos/` (ver sección 2) — resolver en Fase 0, no duplicar el
  helper.
- Decidir si `maeDa`/`docDa` se recalculan en cada carga de
  `layout/base.php` (defensivo, cubre cambios de asignación a mitad de
  sesión) o solo una vez en login (más simple, ya es el patrón que usa el
  resto de la sesión de alumno) — por defecto, seguir el patrón existente
  (solo en login) salvo que aparezca un caso real que lo justifique.
- Imágenes de preguntas (`imagen_question/`) del lado docente — mismo gap ya
  anotado en la migración de exámenes; decidir dónde viven al implementar la
  Fase 2.
- Confirmar existencia real de `horario_grado`/`horario_docentes`/
  `horario_dias` en la BD del colegio piloto antes de migrar `horario.php`
  en la Fase 0.
- Varias áreas (calificaciones, boletas) tienen 2-5 archivos casi duplicados
  en el legacy (`guarnotabachi-n.php` vs `guarnotabachi-n2.php`,
  `boleta-pri.php` vs `boleta_pri.php`, etc.) — cada fase debe diffear esas
  variantes y unificar en una sola implementación, no migrar la duplicación
  tal cual.
- Confirmar con el usuario, fase por fase, qué variantes `-ORI`/`-VIE`
  siguen recibiendo tráfico real antes de descartarlas definitivamente.
