# SGETECBA — Changelog de Sesión
**Fecha:** 08/06/2026  
**Branch:** `features/MirkoALS`  
**Repo:** https://github.com/ZIS-TECBA/sgetecba

---

## Frontend

### `frontend/src/api/client.ts`
- **[A]** `createAsignatura`: campo `codigo` → `codigo_referencia` en el payload (corregía 422 del backend)
- **[B]** `updateAsignatura`: campo `codigo?` → `codigo_referencia?` en el payload
- **[C]** `fetchAsignaturasPorCarreraNivel`: mapeaba `codigo_referencia: ""` hardcodeado → ahora usa `o.asignatura_codigo ?? ""` y `o.asignatura_nombre_normalizado ?? ""`
- **[D]** Eliminada variable `params` local declarada pero nunca usada en el GET (dead code)
- **[E]** Eliminada redeclaración local de `CatalogoItem` que causaba error TS `Duplicate identifier`
- **[F]** `fetchPeriodosLista`: agrega `solo_activos: true` para traer solo períodos activos en los dropdowns de Ofertas
- **[G]** `fetchSesionesPorOferta`: acepta segundo parámetro `sinAsistencia = false`; cuando es `true` pasa `sin_asistencia: true` al backend

---

### `frontend/src/pages/Asignaturas.tsx`
- **[H]** `emptyForm`: clave `codigo` → `codigo_referencia`
- **[I]** `openEdit`: seteaba `codigo:` en el form → `codigo_referencia:`
- **[J]** `handleSave`: payload enviaba `codigo:` → `codigo_referencia:`
- **[K]** Validación chequeaba `form.codigo` → `form.codigo_referencia`
- **[L]** Input `value` y `onChange` usaban `form.codigo` → `form.codigo_referencia`
- **[M]** Fix de refresco: `setPage(1)` + `void load(1)` explícito al crear, para que la tabla refresque aunque `page` ya fuera 1

---

### `frontend/src/pages/Ofertas.tsx`
- Eliminado selector de **Modalidad** del formulario — el usuario ya no lo toca
- Reemplazado por selector de **Período** directo, agrupado por modalidad con `<optgroup>`
- Los períodos activos llevan indicador visual `✓`
- `handlePeriodoChange` extrae `modalidad_academica_id` del período elegido y lo setea automáticamente en el form
- **Badge informativo** de modalidad inferida aparece debajo del selector de Período
- **Preselección automática**: si solo hay un período activo en toda la lista, se preselecciona solo
- Modo edición: muestra badge de modalidad en lugar de texto plano
- Eliminado `fetchAsignaturasPorCarreraNivel` del import; reemplazado por `fetchAsignaturasLista` (todo el catálogo, sin filtrar por carrera)
- Selector de Asignatura reemplazado por **combobox con búsqueda en tiempo real**: filtra por nombre y código, muestra pill naranja con ✕ al seleccionar
- `recargarAsignaturas(carrera_id)` → `cargarAsignaturas()` sin parámetro; se llama una sola vez al abrir el modal, no al cambiar carrera

---

### `frontend/src/pages/Asistencias.tsx` *(Admin)*
- Filtros: Carrera → Materia en cascada + Desde / Hasta + botón Buscar
- Tabla con badges de color por estado (verde/rojo/azul/amarillo), columna observación, botón Editar por fila
- Modal de edición: selección de estado + motivo obligatorio para auditoría
- 3 botones de PDF: Planilla del período, Historial de asistencia, Informe PDF
- Fix de descarga: `a.download = "nombre.pdf"` en todos los botones PDF (antes usaban `target="_blank"` sin nombre ni extensión)

---

### `frontend/src/pages/secretaria/AsistenciasSecretaria.tsx`
- Fix de scope: estados `exportandoLibro` y `exportandoHistorial` movidos a `TabRegistro` (estaban en `TabHistorial`, causaban `ReferenceError`)
- Fix de descarga PDF: `a.download = "nombre.pdf"` en los 5 botones de PDF (planilla sesión, planilla período, historial, informe)
- Combobox con búsqueda en tiempo real para **Carrera** y **Materia** (reemplazan los `<select>` simples)
- Selector de **Sesión/Fecha** ahora llama `fetchSesionesPorOferta(ofertaId, true)` → muestra solo sesiones sin asistencia registrada (desde hoy en adelante)
- 4 botones de PDF en tab Registro cuando hay `ofertaId`:
  | Botón | Color | Endpoint |
  |-------|-------|----------|
  | Planilla esta sesión | Naranja sólido | `/sesiones/{id}/planilla-pdf` |
  | Planilla del período | Azul oscuro sólido | `/asistencias/planilla-libro/pdf` |
  | Historial de asistencia | Azul oscuro borde | `/asistencias/historial-libro/pdf` |
  | Informe PDF | Naranja borde | `/asistencias/informe/pdf` |

---

## Backend

### `backend/app/api/v1/routes/asignaturas.py`
- `crear_asignatura`: `data.codigo` → `data.codigo_referencia` en el `{"codigo": ...}` del INSERT (el campo Pydantic es `codigo_referencia`, la columna DB es `codigo`)
- `actualizar_asignatura`: agrega mapeo `campos["codigo"] = campos.pop("codigo_referencia")` antes del SET clause, para que el SQL use la columna correcta

---

### `backend/app/api/v1/routes/periodos_academicos.py`
- Nuevo parámetro `solo_activos: bool = Query(default=False)` en `get_periodos`
- Cuando `solo_activos=True` aplica `_WHERE_ACTIVO` en COUNT y SELECT:
  ```sql
  p.eliminado_en IS NULL
  AND p.activo = true
  AND (p.fecha_fin IS NULL OR p.fecha_fin >= CURRENT_DATE)
  ```
- `default=False` preserva el comportamiento existente en la página de administración de períodos

---

### `backend/app/api/v1/routes/sesiones.py`
- Nuevo parámetro `sin_asistencia: bool = Query(default=False)` en `listar_sesiones`
- Cuando es `true` filtra con `NOT EXISTS` en `detalle_asistencia` + `fecha_clase >= CURRENT_DATE` + excluye estado `CANCELADA`
- Eliminada columna `sa.observacion` del SELECT (no existe en la tabla `sesiones_asistencia`)
- Endpoint `/planilla-pdf`: `Content-Disposition` cambiado de `inline` → `attachment` para forzar descarga

---

### `backend/app/api/v1/routes/asistencias.py`
- 2 nuevos endpoints antes de `/reporte`:
  - `GET /asistencias/planilla-libro/pdf?oferta_asignatura_id=X` → planilla libro con todas las sesiones (celdas vacías para imprimir)
  - `GET /asistencias/historial-libro/pdf?oferta_asignatura_id=X` → historial solo sesiones CERRADAS con A/F/L coloreados

---

### `backend/app/services/planilla_libro.py` *(NUEVO)*
Nuevo servicio con dos funciones:

- **`generar_planilla_libro(db, oferta_asignatura_id)`** — todas las sesiones, celdas vacías para imprimir y llenar a mano
- **`generar_historial_libro(db, oferta_asignatura_id)`** — solo sesiones CERRADAS, celdas con A/F/L/T coloreadas

Formato del PDF:
- Landscape A4
- Encabezado institucional (asignatura, carrera, docente, período, turno, nivel)
- Columnas: `#` | `Código` | `Apellidos y Nombres` | `C.I.` | `[fechas...]` | `OBS`
- Encabezado de fechas: fila 1 = `DD/MM`, fila 2 = inicial del día (`L`, `M`, `Mi`, `J`, `V`)
- Hasta 16 columnas de fecha por página antes de paginar
- Pie con firmas
- Altura mínima de celda 0.65cm para espacio de escritura

---

## Base de Datos

### `BD/sesiones_prueba.sql` *(nuevo, no commiteado a Git)*
- Script SQL de prueba: inserta 16 sesiones para oferta 1 (Matemáticas I)
- Fechas: martes y jueves de junio y julio 2026
- Estado: `PROGRAMADA`

---

## Pendientes / Bugs conocidos

- [ ] PDF planilla libro — diseño aún difiere de la imagen de referencia (en revisión)
- [ ] Selector Sesión/Fecha en Registro — vacío si no hay sesiones futuras sin asistencia para la oferta seleccionada
- [ ] Sesiones de prueba `sesiones_prueba.sql` — ejecutar manualmente en pgAdmin para poblar datos de prueba
- [ ] `BD/data_only.sql` — dump actualizado generado con `pg_dump` el 08/06/2026
- [ ] Continuar con: Ítem 5 de la lista de pendientes — **Asignación docente a oferta**
