# RF-TEACH-002: Sistema de Asignaciones

**Epic:** EXT-001 - Portal de Maestros
**Fase:** 3 - Extensiones
**Prioridad:** ALTA
**Estado:** ✅ IMPLEMENTADO
**Tipo:** Feature - Sistema de Gestión de Asignaciones

---

## 📋 Descripción

Sistema completo de asignaciones que permite a los maestros crear tareas personalizadas, asignarlas a estudiantes (individual o grupalmente), y evaluar las entregas. El sistema integra ejercicios del contenido educativo existente con la capacidad de crear evaluaciones personalizadas.

---

## 🎯 Objetivo

Proporcionar a los maestros herramientas para:
- Crear asignaciones personalizadas combinando ejercicios existentes
- Asignar tareas a estudiantes individuales o grupos completos (classrooms)
- Realizar seguimiento de entregas y progreso
- Calificar y proporcionar retroalimentación
- Mantener notas privadas sobre el desempeño de estudiantes

---

## 👥 Actores

- **Maestro (Teacher)**: Crea, asigna, y califica assignments
- **Estudiante (Student)**: Recibe, completa, y entrega assignments
- **Sistema**: Gestiona notificaciones, deadlines, y tracking automático

---

## 📊 Modelo de Datos

### Tabla: `assignments`

**Schema:** `educational_content`
**Descripción:** Tabla principal de asignaciones creadas por maestros

> **NOTA (2025-12-18):** Migrado de schema `public` a `educational_content` en 2025-11-08.
> Backend usa datasource 'educational' para esta entidad.

```sql
CREATE TABLE educational_content.assignments (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    teacher_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
    title VARCHAR(255) NOT NULL,
    description TEXT,
    assignment_type VARCHAR(50) NOT NULL CHECK (assignment_type IN ('practice', 'quiz', 'exam', 'homework')),
    due_date TIMESTAMP WITH TIME ZONE,
    total_points INTEGER NOT NULL DEFAULT 100,
    is_published BOOLEAN NOT NULL DEFAULT false,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
```

**Columnas clave:**
- `teacher_id`: Maestro creador (FK → auth.users)
- `assignment_type`: Tipo de asignación
  - `practice`: Práctica (sin calificación formal)
  - `quiz`: Quiz/prueba corta
  - `exam`: Examen formal
  - `homework`: Tarea
- `total_points`: Puntaje máximo (default: 100)
- `is_published`: Control de visibilidad (draft vs published)
- `due_date`: Fecha límite de entrega (opcional)

**Índices:**
- `idx_assignments_teacher_id` (btree)
- `idx_assignments_is_published` (btree)
- `idx_assignments_due_date` (btree, WHERE due_date IS NOT NULL)
- `idx_assignments_type` (btree)

---

### Tabla: `assignment_exercises`

**Schema:** `educational_content`
**Descripción:** Relación M2M entre assignments y ejercicios del sistema

```sql
CREATE TABLE educational_content.assignment_exercises (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    assignment_id UUID NOT NULL REFERENCES educational_content.assignments(id) ON DELETE CASCADE,
    exercise_id UUID NOT NULL REFERENCES educational_content.exercises(id) ON DELETE CASCADE,
    order_index INTEGER,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(assignment_id, exercise_id)
);
```

**Propósito:**
- Permite incluir múltiples ejercicios en un assignment
- Mantiene orden de presentación (`order_index`)
- Reutiliza ejercicios existentes del catálogo educativo

**Índices:**
- `idx_assignment_exercises_assignment_id` (btree)
- `idx_assignment_exercises_exercise_id` (btree)
- `idx_assignment_exercises_order` (btree composite: assignment_id, order_index)

---

### Tabla: `assignment_classrooms`

**Schema:** `social_features`
**Descripción:** Asignación de assignments a classrooms completos

> ⚠️ **NOTA (2025-11-29):** Esta tabla fue movida del schema `public` al schema `social_features`
> para mantener coherencia arquitectónica con las entidades de classrooms.
> Ver: `apps/backend/src/modules/social/entities/assignment-classroom.entity.ts`

```sql
CREATE TABLE social_features.assignment_classrooms (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    assignment_id UUID NOT NULL REFERENCES educational_content.assignments(id) ON DELETE CASCADE,
    classroom_id UUID NOT NULL REFERENCES social_features.classrooms(id) ON DELETE CASCADE,
    assigned_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(assignment_id, classroom_id)
);
```

**Propósito:**
- Distribución masiva de assignment a todos los estudiantes de un classroom
- Simplifica administración para grupos grandes
- Timestamp de asignación para auditoría

**Índices:**
- `idx_assignment_classrooms_assignment_id` (btree)
- `idx_assignment_classrooms_classroom_id` (btree)

---

### Tabla: `assignment_students`

**Schema:** `educational_content`
**Descripción:** Asignación de assignments a estudiantes individuales

```sql
CREATE TABLE educational_content.assignment_students (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    assignment_id UUID NOT NULL REFERENCES educational_content.assignments(id) ON DELETE CASCADE,
    student_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
    assigned_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(assignment_id, student_id)
);
```

**Propósito:**
- Asignación individualizada (refuerzo, remediación, avanzados)
- Permite personalización por estudiante
- Complementa asignación por classroom

**Índices:**
- `idx_assignment_students_assignment_id` (btree)
- `idx_assignment_students_student_id` (btree)

---

### Tabla: `assignment_submissions`

**Schema:** `educational_content`
**Descripción:** Entregas y calificaciones de estudiantes

```sql
CREATE TABLE educational_content.assignment_submissions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    assignment_id UUID NOT NULL REFERENCES educational_content.assignments(id) ON DELETE CASCADE,
    student_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
    submitted_at TIMESTAMP WITH TIME ZONE,
    status VARCHAR(50) NOT NULL DEFAULT 'not_started' CHECK (status IN ('not_started', 'in_progress', 'submitted', 'graded')),
    score NUMERIC(5,2),
    feedback TEXT,
    graded_at TIMESTAMP WITH TIME ZONE,
    graded_by UUID REFERENCES auth.users(id),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(assignment_id, student_id)
);
```

**Propósito:**
- Tracking de entregas por estudiante
- Calificación y retroalimentación
- Workflow de estados (not_started → in_progress → submitted → graded)

**Estados:**
- `not_started`: Asignado pero no iniciado
- `in_progress`: Estudiante trabajando
- `submitted`: Entregado, pendiente de calificación
- `graded`: Calificado con score y feedback

**Columnas de calificación:**
- `score`: Calificación numérica (0.00-999.99)
- `feedback`: Retroalimentación textual del maestro
- `graded_by`: Maestro que calificó (FK → auth.users)
- `graded_at`: Timestamp de calificación

**Índices:**
- `idx_assignment_submissions_assignment_id` (btree)
- `idx_assignment_submissions_student_id` (btree)
- `idx_assignment_submissions_status` (btree)
- `idx_assignment_submissions_graded_by` (btree, WHERE graded_by IS NOT NULL)
- `idx_assignment_submissions_submitted_at` (btree, WHERE submitted_at IS NOT NULL)

---

### Tabla: `teacher_notes`

**Schema:** `educational_content`
**Descripción:** Notas privadas de maestros sobre estudiantes

```sql
CREATE TABLE educational_content.teacher_notes (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    teacher_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
    student_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
    note TEXT NOT NULL,
    is_private BOOLEAN NOT NULL DEFAULT true,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
```

**Propósito:**
- Seguimiento cualitativo de estudiantes
- Observaciones de comportamiento, progreso, áreas de mejora
- Notas privadas no visibles para estudiantes/padres

**Índices:**
- `idx_teacher_notes_teacher_id` (btree)
- `idx_teacher_notes_student_id` (btree)
- `idx_teacher_notes_created_at` (btree)
- `idx_teacher_notes_teacher_student` (btree composite)

---

## 🔄 Flujos de Trabajo

### 1. Creación de Assignment

```
Maestro → Crear Assignment (draft)
       → Agregar Ejercicios (assignment_exercises)
       → Configurar deadline, puntos, tipo
       → Publicar (is_published = true)
```

### 2. Distribución de Assignment

**Opción A: Por Classroom**
```
Maestro → Seleccionar Assignment
       → Asignar a Classroom(s) → assignment_classrooms
       → Sistema crea submissions automáticas para c/estudiante
```

**Opción B: Individual**
```
Maestro → Seleccionar Assignment
       → Asignar a Estudiante(s) → assignment_students
       → Sistema crea submissions individuales
```

### 3. Workflow de Estudiante

```
Estudiante → Ve assignment (status: not_started)
          → Inicia trabajo (status: in_progress)
          → Completa ejercicios
          → Entrega (status: submitted, submitted_at = NOW)
```

### 4. Calificación

```
Maestro → Ve queue de submissions (status = submitted)
       → Revisa trabajo
       → Asigna score + feedback
       → Guarda (status: graded, graded_at = NOW, graded_by = teacher_id)
```

### 5. Notas de Seguimiento

```
Maestro → Observa desempeño/comportamiento
       → Crea nota en teacher_notes
       → Nota privada (is_private = true)
       → Consulta histórico de notas por estudiante
```

---

## 🎓 Casos de Uso

### CU-1: Crear Tarea Semanal
**Actor:** Maestro
**Descripción:** Crear asignación semanal con ejercicios de comprensión lectora

**Flujo:**
1. Maestro crea assignment (title: "Semana 3 - Comprensión Literal")
2. Agrega 5 ejercicios de módulo 1 via assignment_exercises
3. Establece due_date: Viernes 5pm
4. Asigna a 3 classrooms via assignment_classrooms
5. Sistema crea ~90 submissions (30 estudiantes × 3 classrooms)

---

### CU-2: Asignación Remedial Individual
**Actor:** Maestro
**Descripción:** Asignar trabajo extra a estudiantes que necesitan refuerzo

**Flujo:**
1. Maestro identifica 3 estudiantes con bajo desempeño
2. Crea assignment tipo "practice" con ejercicios básicos
3. Asigna individualmente via assignment_students (no classrooms)
4. Sistema crea 3 submissions
5. Maestro monitorea progreso individual

---

### CU-3: Examen Final
**Actor:** Maestro
**Descripción:** Crear examen formal con tracking estricto

**Flujo:**
1. Maestro crea assignment tipo "exam"
2. Agrega 20 ejercicios variados (order_index 1-20)
3. Establece total_points: 100, due_date: día del examen
4. Asigna a todos los classrooms
5. Estudiantes completan y entregan
6. Maestro califica con scores y feedback detallado

---

### CU-4: Notas de Observación
**Actor:** Maestro
**Descripción:** Registrar observaciones sobre progreso de estudiante

**Flujo:**
1. Maestro nota que estudiante mejoró en ortografía
2. Crea nota: "María mostró gran mejora en uso de tildes, continuar reforzando"
3. is_private = true (no visible para estudiante)
4. Consulta historial de notas previas de María
5. Identifica patrón de mejora

---

## 🔗 Relaciones con Otros Schemas

### Con `educational_content`
- `assignment_exercises.exercise_id` → `educational_content.exercises.id`
- Reutiliza ejercicios existentes del catálogo

### Con `social_features`
- `assignment_classrooms.classroom_id` → `social_features.classrooms.id`
- Distribución masiva por classroom

### Con `auth_management`
- `assignments.teacher_id` → `auth.users.id` (role: teacher)
- `assignment_students.student_id` → `auth.users.id` (role: student)
- `assignment_submissions.student_id` → `auth.users.id`
- `assignment_submissions.graded_by` → `auth.users.id` (role: teacher)

---

## 🔒 Seguridad y RLS

**Políticas RLS requeridas:**

### `assignments`
- Maestros ven solo sus propios assignments
- Estudiantes ven solo assignments published asignados a ellos

### `assignment_submissions`
- Maestros ven submissions de sus assignments
- Estudiantes ven solo sus propias submissions
- Admin/coordinador puede ver todas

### `teacher_notes`
- Solo el teacher creador puede ver/editar sus notas
- Estudiantes NO pueden ver notas privadas
- Admin puede ver para auditoría

---

## 📈 Métricas y Analytics

### Por Maestro
- Total de assignments creados
- Submissions pendientes de calificar
- Promedio de tiempo de calificación
- Tasa de entrega a tiempo vs tarde

### Por Estudiante
- Assignments asignados vs completados
- Promedio de scores
- Tasa de entregas a tiempo
- Tendencia de desempeño

### Por Assignment
- Tasa de completitud (submitted/assigned)
- Score promedio
- Distribución de scores
- Tiempo promedio de completitud

---

## 🧪 Validaciones

### Al Crear Assignment
- ✅ teacher_id debe tener role 'teacher' o 'admin_teacher'
- ✅ assignment_type debe ser válido (practice/quiz/exam/homework)
- ✅ total_points > 0
- ✅ title no vacío

### Al Distribuir
- ✅ Assignment debe estar published (is_published = true)
- ✅ Classroom debe existir y estar activo
- ✅ Estudiante debe estar enrolled en classroom (si aplica)
- ✅ No duplicar asignación (UNIQUE constraints)

### Al Calificar
- ✅ Submission debe estar submitted
- ✅ graded_by debe ser maestro del assignment
- ✅ score debe estar entre 0 y total_points del assignment
- ✅ feedback opcional pero recomendado

---

## ⚙️ Configuración y Defaults

- **Default total_points:** 100
- **Default is_published:** false (draft)
- **Default status (submissions):** not_started
- **Default is_private (notes):** true
- **Cascade deletes:** ON DELETE CASCADE en todas las FKs (excepto graded_by)

---

## 🚀 Mejoras Futuras

1. **Auto-grading para ejercicios cerrados**
   - Calificación automática de multiple choice
   - Reducir carga de maestros

2. **Rúbricas de evaluación**
   - Tabla `assignment_rubrics` con criterios
   - Evaluación por dimensiones

3. **Extensiones de deadline**
   - Tabla `assignment_extensions` para casos especiales
   - Aprobación de maestro

4. **Notificaciones automáticas**
   - Assignment nuevo asignado
   - Deadline próximo (24h antes)
   - Submission calificada

5. **Análisis de plagio**
   - Integración con sistema anti-plagio
   - Comparación entre submissions

6. **Exportación masiva**
   - Export de calificaciones a CSV/Excel
   - Integración con sistemas escolares (SIS)

---

## 📝 Notas de Implementación

### Discrepancias con TRACEABILITY Inicial

El diseño inicial documentado en `TRACEABILITY.yml` especificaba:
- Tablas en schemas `educational_content` y `progress_tracking`
- Solo 3 tablas (assignments, assignment_submissions, teacher_notes)
- Columna `content_refs JSONB` en assignments

**Implementación real:**
- Tablas principales en schema `public` (assignments, assignment_exercises, assignment_students, assignment_submissions, teacher_notes)
- Tabla `assignment_classrooms` en schema `social_features` (movida 2025-11-29)
- 6 tablas total (assignments + 4 M2M + submissions + notes)
- M2M table `assignment_exercises` en vez de JSONB (mejor normalización)

**Ventajas del diseño implementado:**
- Mejor normalización (M2M vs JSONB)
- Separación clara de asignación por classroom vs individual
- Mayor flexibilidad para queries y reportes
- Indexes optimizados para búsquedas comunes

---

## 🔗 Referencias

- **Épica:** EXT-001 - Portal de Maestros
- **User Stories:** US-PM-002a, US-PM-002b, US-PM-002c, US-PM-003a, US-PM-003b, US-PM-004b
- **Schemas relacionados:**
  - `educational_content` (exercises)
  - `social_features` (classrooms)
  - `auth_management` (users, roles)

---

**Creado:** 2025-11-08
**Actualizado:** 2025-11-29 (schema assignment_classrooms → social_features)
**Tipo:** Documentación retroactiva (implementación ya existente)
**Estado:** ✅ Documentación completa de implementación real
