# Plan — Plan de estudios PDF en cursos + retiro del temario

## Contexto

Hoy cada curso tiene un **temario** (`topics`: nombre + orden) anidado en el
modal de edición (`CatalogSimple` → `CourseTopics`). Al fichar (kiosko) y al
crear/corregir registros de asistencia, el docente/admin **debe** elegir un
tema (`attendance_records.topic_id` NOT NULL).

La Facultad indica que el temario por ítems **no hace falta**: basta con
adjuntar el **plan de estudios en PDF** al curso (opcional). El PDF se
guarda en disco del servidor (mismo patrón que fotos de referencia /
evidencias: `Storage` disco `public`) — **no** es `localStorage` del
navegador.

Evidencia verificada:
- `courses`: migración `2026_09_13_100003_create_courses_table.php` (sin columna de archivo).
- `topics`: migración `2026_09_13_100004_create_topics_table.php` + `CourseTopics` Livewire (sin ruta propia; solo embebido al editar curso).
- Uso de `topic_id`: `Kiosk`, `AttendanceRecords` (alta), `AttendanceRecordDetail` (corrección), seeders y tests de Fases 1–5.
- Patrón de subida: `Users.php` → `store('reference-photos', 'public')`; kiosko → `attendance-evidence/`.

## Alcance

**Incluye:**
- Columna nullable `study_plan_path` en `courses` + subida/visualización/quitar PDF en el CRUD de cursos.
- Eliminación completa del dominio **temario**: tabla `topics`, modelo, Livewire, vistas, FKs, selects de “Tema” en kiosko y panel de asistencia, seeders y tests.
- Documentación (`MODELO-DATOS.md`, `CAMBIOS.md`, `CLAUDE.md` — novena pasada).

**No incluye:**
- `migrate:fresh` en MySQL local (solo cuando el usuario lo autorice).
- Migraciones nuevas (política vigente: editar migraciones existentes in-place).
- Visor PDF embebido avanzado (basta enlace “Ver plan de estudios” que abra el archivo en otra pestaña).
- Versionado histórico de PDFs (reemplazar borra el archivo anterior, igual que la foto de referencia).
- Cambios en asignaciones/horarios (ya no usan `topic_id`).

## Decisiones (no reabrir al implementar)

1. **Nombre de columna:** `study_plan_path` (string, nullable). UI en español: “Plan de estudios”.
2. **Almacenamiento:** disco `public`, carpeta `course-study-plans/`. Path relativo en BD; URL con `Storage::disk('public')->url(...)`.
3. **Validación:** `nullable`, `mimes:pdf`, `max:10240` (10 MB). Opcional al crear y al editar. Botón “Quitar” permitido (el curso puede quedar sin PDF).
4. **Retiro del temario = retiro de `topic_id`:** se elimina la columna de `attendance_records` (no se deja nullable “por si acaso”). El fichaje ya no pide tema; el plan vive a nivel de curso.
5. **Migraciones in-place:**
   - Ampliar `create_courses_table` con `study_plan_path`.
   - Eliminar por completo el archivo `2026_09_13_100004_create_topics_table.php`.
   - Quitar `topic_id` de `create_attendance_records_table`.
6. **Orden de migraciones:** al borrar `topics`, no debe quedar ninguna FK huérfana en el código de migración de `attendance_records`.

## Tareas

### Dominio y esquema
- [x] 1. En `2026_09_13_100003_create_courses_table.php`, agregar `$table->string('study_plan_path')->nullable();` (junto a los campos curriculares).
- [x] 2. Eliminar `database/migrations/2026_09_13_100004_create_topics_table.php`.
- [x] 3. En `2026_09_13_100006_create_attendance_records_table.php`, quitar la FK/columna `topic_id`.
- [x] 4. `Course.php`: añadir `study_plan_path` a fillable; eliminar relación `topics()`.
- [x] 5. Eliminar `app/Models/Topic.php`.
- [x] 6. `AttendanceRecord.php`: quitar `topic_id` del fillable y la relación `topic()`.

### CRUD de cursos (PDF)
- [x] 7. `CatalogSimple.php`: trait `WithFileUploads`; propiedades `studyPlan` (upload) y `removeExistingStudyPlan` (bool); validación PDF; en `save()` guardar/reemplazar/borrar en `course-study-plans` (mismo criterio que foto de referencia en `Users`); limpiar en `resetForm()` / cargar path existente en `edit()`.
- [x] 8. `catalog-simple.blade.php` (solo `type === 'courses'`):
  - En el modal: bloque “Plan de estudios (PDF, opcional)” con input file, enlace “Ver PDF actual” si hay path, botón “Quitar”.
  - En la tabla: columna compacta (ícono/enlace “PDF” o “—”).
  - **Quitar** el embed `@if ($editingId) <livewire:admin.course-topics …>`.
- [x] 9. Eliminar `app/Livewire/Admin/CourseTopics.php` y `resources/views/livewire/admin/course-topics.blade.php`.

### Kiosko y asistencia (sin tema)
- [x] 10. `Kiosk.php` + `kiosk.blade.php`: eliminar `topicId`, validación, select “Tema”, y lógica de `updatedCourseId` que limpiaba el tema. Al crear el registro, no setear `topic_id`.
- [x] 11. `AttendanceRecords.php` + vista: quitar select/filtro/campo de tema en alta manual.
- [x] 12. `AttendanceRecordDetail.php` + vista: quitar corrección auditada de `topic_id` / etiqueta “Tema”.
- [x] 13. Revisar cualquier helper de tests o listados que asuma `topic` cargado en el registro.

### Seeders
- [x] 14. `CatalogSeeder`: dejar de crear `TEMA DE EJEMPLO 1/2`.
- [x] 15. `AttendanceRecordSeeder`: dejar de asignar `topic_id`.

### Tests
- [x] 16. `Fase1CatalogsTest`: quitar asserts de tabla `topics` y el test `test_course_topics_crud_and_reorder`; actualizar `test_deleting_course_with_topics_is_blocked` (ya no aplica — reemplazar por bloqueo vía assignments/attendance si hace falta, o eliminar si queda cubierto por otro test); añadir cobertura de subir/quitar PDF opcional en cursos.
- [x] 17. `Fase2bKioskManualTest`, `Fase3AssignmentsTest`, `Fase4AttendanceRecordsTest`, `Fase5DashboardReportsTest`: eliminar `topicId` / creación de `Topic` en helpers y flujos; ajustar asserts de esquema (`topic_id` ausente).
- [x] 18. Suite completa en verde + Pint.

### Documentación
- [x] 19. `docs/MODELO-DATOS.md`: documentar `study_plan_path` en § courses; **eliminar** § topics; quitar `topic_id` de § attendance_records; actualizar tabla resumen de estado.
- [x] 20. `docs/CAMBIOS.md`: entrada “Plan de estudios PDF + retiro del temario”.
- [x] 21. `CLAUDE.md`: novena pasada (qué se añadió, qué se retiró, conteo de tests, pendiente de `migrate:fresh`).

## Criterios de aceptación

- [x] En `/admin/catalogs/courses`: se puede crear/editar un curso **sin** PDF; con PDF se guarda y se puede abrir/quitar.
- [x] El modal de curso **ya no** muestra CRUD de temario; no existen archivos `CourseTopics` / `Topic` / migración `topics`.
- [x] Kiosko y alta/corrección de asistencia **no** piden ni muestran “Tema”.
- [x] `attendance_records` no tiene columna `topic_id`; la migración de `topics` no existe.
- [x] `./vendor/bin/pint --test` limpio.
- [x] `docker compose run --rm app php artisan test` en verde (todos los tests que usaban topics adaptados).
- [x] **No** se ejecuta `migrate:fresh` hasta orden expresa del usuario.
- [x] Docs actualizados (`MODELO-DATOS`, `CAMBIOS`, `CLAUDE`).

## Notas para quien implemente

- Identificadores en inglés (`study_plan_path`, `studyPlan`); UI 100 % en español (“Plan de estudios”).
- Comentarios en español solo si explican un *por qué* no obvio.
- Reutilizar el patrón visual de subida de `Users` (preview/acciones) adaptado a PDF: no hay preview de imagen — mostrar nombre del archivo temporal o enlace al PDF guardado + “Cambiar” / “Quitar”.
- Al borrar un curso, si tiene `study_plan_path`, borrar también el archivo del disco (si el delete llega a ejecutarse; hoy el delete se bloquea con dependencias — igual conviene limpiar el archivo al quitar/reemplazar el PDF).
- Riesgo principal: cascada amplia en tests de kiosko/asistencia. Grepear `topic` / `Topic` / `topicId` / `topic_id` en todo el repo antes de dar por cerrado.
- No tocar `mockup-unamba/`; gana este repo.
- No mencionar coautoría en commits si más adelante se pide commit.
