# Integracion Student Portal → Teacher Portal **Fecha de creacion:** 2025-11-29 **Version:** 1.0.0 **Estado:** ESPECIFICACION PARA DESARROLLO **Relacionado:** PORTAL-TEACHER-GUIDE.md, PORTAL-STUDENT-GUIDE.md, PORTAL-TEACHER-FLOWS.md --- ## 1. Vision General ### 1.1 Proposito de este Documento Este documento especifica **como el Portal de Students genera datos que el Portal de Teacher necesita consumir**. Sirve como guia para: 1. **Desarrolladores Student Portal**: Que datos deben guardarse correctamente 2. **Desarrolladores Teacher Portal**: Que datos pueden consumir y de donde 3. **Desarrolladores Backend**: Que endpoints, triggers y funciones son necesarios 4. **Desarrolladores Database**: Que estructuras de BD soportan la integracion ### 1.2 Principio Fundamental ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ FLUJO DE DATOS UNIDIRECCIONAL │ │ │ │ STUDENT genera datos ──► BACKEND procesa ──► TEACHER consume │ │ │ │ - Respuestas ejercicios - Valida - Visualiza progreso │ │ - Progreso modulos - Almacena - Califica │ │ - Actividad gamificacion - Calcula metricas - Genera reportes │ │ - Misiones completadas - Dispara triggers - Recibe alertas │ └─────────────────────────────────────────────────────────────────────────────┘ ``` --- ## 2. Arquitectura de Datos ### 2.1 Schemas de Base de Datos Involucrados | Schema | Proposito | Tablas Principales | |--------|-----------|-------------------| | `auth_management` | Usuarios y perfiles | users, profiles | | `progress_tracking` | Progreso educativo | module_progress, exercise_submissions, exercise_attempts | | `gamification_system` | Recompensas | user_stats, ml_coins_transactions, user_achievements | | `educational_content` | Contenido | modules, exercises | | `social_features` | Aulas | classrooms, classroom_members, teacher_classrooms | ### 2.2 Diagrama de Relaciones Criticas ``` ┌──────────────────────┐ │ auth_management │ │ ┌───────────────┐ │ │ │ users │ │ │ │ (auth.users) │ │ │ └───────┬───────┘ │ │ │ 1:1 │ │ ┌───────▼───────┐ │ │ │ profiles │ │ │ │ (profiles.id) │◄──┼────────────────────────────────┐ │ └───────────────┘ │ │ └──────────────────────┘ │ │ ┌──────────────────────────────────────────────────────────────────────────┐│ │ progress_tracking ││ │ ││ │ ┌─────────────────────┐ ┌─────────────────────┐ ││ │ │ module_progress │ │ exercise_submissions │ ││ │ ├─────────────────────┤ ├─────────────────────┤ ││ │ │ user_id (FK)────────┼──────┼► user_id (FK)───────┼────────────────────┘│ │ │ module_id (FK) │ │ exercise_id (FK) │ │ │ │ classroom_id (FK) │ │ answer_data (JSONB) │ ◄── RESPUESTAS │ │ │ progress_percentage │ │ score │ │ │ │ exercises_completed │ │ feedback │ │ │ │ last_activity_at │ │ graded_at │ │ │ │ status │ │ status │ │ │ └─────────────────────┘ └─────────────────────┘ │ │ │ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │ exercise_attempts │ │ learning_sessions │ │ │ ├─────────────────────┤ ├─────────────────────┤ │ │ │ user_id (FK) │ │ user_id (FK) │ │ │ │ exercise_id (FK) │ │ module_id (FK) │ │ │ │ attempt_number │ │ duration_minutes │ │ │ │ answers (JSONB) │ │ activities_count │ │ │ │ score │ │ started_at │ │ │ │ time_spent_seconds │ │ ended_at │ │ │ │ hints_used │ └─────────────────────┘ │ │ │ powerups_used │ │ │ └─────────────────────┘ │ └───────────────────────────────────────────────────────────────────────────┘ ┌───────────────────────────────────────────────────────────────────────────┐ │ gamification_system │ │ │ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │ user_stats │ │ml_coins_transactions│ │ │ ├─────────────────────┤ ├─────────────────────┤ │ │ │ user_id (FK) │ │ user_id (FK) │ │ │ │ level │ │ amount │ │ │ │ total_xp │ │ type (earned/spent) │ │ │ │ ml_coins │ │ source │ │ │ │ current_rank │ │ created_at │ │ │ │ current_streak │ └─────────────────────┘ │ │ │ exercises_completed │ │ │ │ modules_completed │ ┌─────────────────────┐ │ │ │ perfect_scores │ │ user_achievements │ │ │ └─────────────────────┘ ├─────────────────────┤ │ │ │ user_id (FK) │ │ │ │ achievement_id (FK) │ │ │ │ unlocked_at │ │ │ │ progress │ │ │ └─────────────────────┘ │ └───────────────────────────────────────────────────────────────────────────┘ ``` --- ## 3. Especificacion de Respuestas de Ejercicios ### 3.1 Estructura de Almacenamiento Las respuestas de ejercicios se almacenan en dos tablas principales: #### Tabla: `progress_tracking.exercise_attempts` **Proposito:** Registrar cada intento individual (incluyendo incompletos) ```sql CREATE TABLE progress_tracking.exercise_attempts ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES auth_management.profiles(id), exercise_id UUID NOT NULL REFERENCES educational_content.exercises(id), attempt_number INTEGER NOT NULL DEFAULT 1, -- RESPUESTAS DEL ESTUDIANTE (JSONB flexible por tipo de ejercicio) answers JSONB NOT NULL DEFAULT '{}', -- METRICAS DEL INTENTO score DECIMAL(5,2), time_spent_seconds INTEGER DEFAULT 0, hints_used INTEGER DEFAULT 0, powerups_used JSONB DEFAULT '[]', -- ESTADO status VARCHAR(20) DEFAULT 'in_progress', -- Valores: 'in_progress', 'submitted', 'abandoned' -- TIMESTAMPS started_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), submitted_at TIMESTAMP WITH TIME ZONE, -- CONSTRAINT para unicidad UNIQUE(user_id, exercise_id, attempt_number) ); ``` #### Tabla: `progress_tracking.exercise_submissions` **Proposito:** Registrar envios finales con calificacion ```sql CREATE TABLE progress_tracking.exercise_submissions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES auth_management.profiles(id), exercise_id UUID NOT NULL REFERENCES educational_content.exercises(id), attempt_id UUID REFERENCES progress_tracking.exercise_attempts(id), -- RESPUESTAS ENVIADAS (copia final de lo que envio el estudiante) answer_data JSONB NOT NULL, -- CALIFICACION score DECIMAL(5,2), max_score DECIMAL(5,2) DEFAULT 100, is_correct BOOLEAN, partial_scores JSONB, -- Puntuacion por pregunta/seccion -- FEEDBACK auto_feedback TEXT, -- Generado por sistema teacher_feedback TEXT, -- Agregado por profesor -- ESTADO status VARCHAR(20) DEFAULT 'submitted', -- Valores: 'submitted', 'graded', 'pending_review', 'late' -- AUDITORIA graded_by UUID REFERENCES auth_management.profiles(id), graded_at TIMESTAMP WITH TIME ZONE, submitted_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), -- METADATA client_metadata JSONB DEFAULT '{}' -- navegador, IP, etc. ); ``` ### 3.2 Formato de `answer_data` por Tipo de Ejercicio Cada tipo de ejercicio tiene una estructura especifica de respuestas. El Teacher Portal debe poder interpretar estas estructuras. #### Crucigrama ```json { "clues": { "h1": { "answer": "SORBONA", "isCorrect": true }, "h2": { "answer": "NOBEL", "isCorrect": true }, "v1": { "answer": "PARIS", "isCorrect": true } }, "completedAt": "2025-11-29T10:30:00Z", "hintsUsed": ["h1"] } ``` #### Linea de Tiempo ```json { "events": [ { "eventId": "evt-1", "position": 1, "isCorrect": true }, { "eventId": "evt-2", "position": 2, "isCorrect": false }, { "eventId": "evt-3", "position": 3, "isCorrect": true } ], "totalCorrect": 2, "totalEvents": 3 } ``` #### Detective Textual ```json { "selections": [ { "paragraphId": 1, "selectedText": "Marie Curie descubrio...", "isCorrect": true }, { "paragraphId": 3, "selectedText": "en 1903", "isCorrect": true } ], "totalSelections": 2, "correctSelections": 2 } ``` #### Fill in the Blank ```json { "blanks": { "blank_1": { "answer": "polonio", "isCorrect": true }, "blank_2": { "answer": "radio", "isCorrect": true } }, "correctCount": 2, "totalBlanks": 2 } ``` #### True/False ```json { "statements": { "stmt_1": { "answer": true, "isCorrect": true }, "stmt_2": { "answer": false, "isCorrect": false } }, "correctCount": 1, "totalStatements": 2 } ``` ### 3.3 Acceso del Teacher a las Respuestas **Endpoint existente:** GET `/teacher/exercise-responses` **Datos que debe retornar:** ```typescript interface ExerciseResponseForTeacher { // Identificacion submissionId: string; studentId: string; studentName: string; exerciseId: string; exerciseTitle: string; exerciseType: string; // 'crucigrama', 'linea_tiempo', etc. // Respuestas del estudiante answerData: Record; // Estructura especifica del tipo // Calificacion score: number; maxScore: number; isCorrect: boolean; partialScores: Record; // Por pregunta // Feedback autoFeedback: string | null; teacherFeedback: string | null; // Estado status: 'submitted' | 'graded' | 'pending_review'; // Metricas del intento attemptNumber: number; timeSpentSeconds: number; hintsUsed: number; powerupsUsed: string[]; // Timestamps submittedAt: string; gradedAt: string | null; gradedBy: string | null; } ``` --- ## 4. Triggers y Funciones de Base de Datos ### 4.1 Triggers Necesarios para Sincronizacion Automatica #### Trigger 1: Actualizar ModuleProgress cuando se completa ejercicio ```sql -- Funcion: Actualizar module_progress al completar ejercicio CREATE OR REPLACE FUNCTION progress_tracking.update_module_progress_on_submission() RETURNS TRIGGER AS $$ DECLARE v_module_id UUID; v_classroom_id UUID; v_total_exercises INTEGER; v_completed_exercises INTEGER; v_progress_pct DECIMAL(5,2); BEGIN -- Obtener module_id del ejercicio SELECT module_id INTO v_module_id FROM educational_content.exercises WHERE id = NEW.exercise_id; -- Obtener classroom_id del estudiante (primary classroom) SELECT cm.classroom_id INTO v_classroom_id FROM social_features.classroom_members cm WHERE cm.user_id = NEW.user_id AND cm.is_primary = true LIMIT 1; -- Contar ejercicios totales y completados SELECT COUNT(*) INTO v_total_exercises FROM educational_content.exercises WHERE module_id = v_module_id AND is_active = true; SELECT COUNT(DISTINCT es.exercise_id) INTO v_completed_exercises FROM progress_tracking.exercise_submissions es JOIN educational_content.exercises e ON e.id = es.exercise_id WHERE es.user_id = NEW.user_id AND e.module_id = v_module_id AND es.score >= 60; -- Minimo para considerar "completado" -- Calcular porcentaje v_progress_pct := CASE WHEN v_total_exercises > 0 THEN (v_completed_exercises::DECIMAL / v_total_exercises * 100) ELSE 0 END; -- Upsert module_progress INSERT INTO progress_tracking.module_progress ( user_id, module_id, classroom_id, exercises_completed, total_exercises, progress_percentage, status, last_activity_at ) VALUES ( NEW.user_id, v_module_id, v_classroom_id, v_completed_exercises, v_total_exercises, v_progress_pct, CASE WHEN v_progress_pct >= 100 THEN 'completed' ELSE 'in_progress' END, NOW() ) ON CONFLICT (user_id, module_id) DO UPDATE SET exercises_completed = EXCLUDED.exercises_completed, progress_percentage = EXCLUDED.progress_percentage, status = EXCLUDED.status, last_activity_at = NOW(), completed_at = CASE WHEN EXCLUDED.progress_percentage >= 100 AND module_progress.completed_at IS NULL THEN NOW() ELSE module_progress.completed_at END; RETURN NEW; END; $$ LANGUAGE plpgsql; -- Trigger CREATE TRIGGER trg_update_module_progress AFTER INSERT ON progress_tracking.exercise_submissions FOR EACH ROW EXECUTE FUNCTION progress_tracking.update_module_progress_on_submission(); ``` #### Trigger 2: Actualizar UserStats cuando se completa ejercicio ```sql -- Funcion: Actualizar user_stats al completar ejercicio CREATE OR REPLACE FUNCTION gamification_system.update_user_stats_on_submission() RETURNS TRIGGER AS $$ DECLARE v_xp_to_add INTEGER; v_coins_to_add INTEGER; v_is_perfect BOOLEAN; BEGIN -- Calcular XP (basado en score) v_xp_to_add := FLOOR(NEW.score * 0.1); -- 10 XP por cada 100 puntos -- Calcular ML Coins (solo si score >= 60) v_coins_to_add := CASE WHEN NEW.score >= 90 THEN 15 WHEN NEW.score >= 70 THEN 10 WHEN NEW.score >= 60 THEN 5 ELSE 0 END; -- Es puntuacion perfecta? v_is_perfect := (NEW.score = NEW.max_score); -- Actualizar user_stats UPDATE gamification_system.user_stats SET total_xp = total_xp + v_xp_to_add, ml_coins = ml_coins + v_coins_to_add, exercises_completed = exercises_completed + 1, perfect_scores = perfect_scores + CASE WHEN v_is_perfect THEN 1 ELSE 0 END, last_activity_at = NOW(), updated_at = NOW() WHERE user_id = NEW.user_id; -- Registrar transaccion de ML Coins si aplica IF v_coins_to_add > 0 THEN INSERT INTO gamification_system.ml_coins_transactions ( user_id, amount, type, source, description, created_at ) VALUES ( NEW.user_id, v_coins_to_add, 'earned', 'exercise_completion', 'Ejercicio completado con ' || NEW.score || '% de score', NOW() ); END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; -- Trigger CREATE TRIGGER trg_update_user_stats AFTER INSERT ON progress_tracking.exercise_submissions FOR EACH ROW WHEN (NEW.status = 'graded' OR NEW.score IS NOT NULL) EXECUTE FUNCTION gamification_system.update_user_stats_on_submission(); ``` #### Trigger 3: Generar Alerta de Intervencion por bajo rendimiento ```sql -- Funcion: Crear alerta cuando estudiante falla multiples veces CREATE OR REPLACE FUNCTION progress_tracking.check_student_failures() RETURNS TRIGGER AS $$ DECLARE v_failure_count INTEGER; v_teacher_id UUID; BEGIN -- Solo procesar si es un fallo (score < 60) IF NEW.score >= 60 THEN RETURN NEW; END IF; -- Contar fallos consecutivos en ultimas 5 submissions SELECT COUNT(*) INTO v_failure_count FROM ( SELECT score FROM progress_tracking.exercise_submissions WHERE user_id = NEW.user_id ORDER BY submitted_at DESC LIMIT 5 ) recent WHERE recent.score < 60; -- Si hay 3+ fallos consecutivos, crear alerta IF v_failure_count >= 3 THEN -- Obtener teacher del classroom del estudiante SELECT tc.teacher_id INTO v_teacher_id FROM social_features.classroom_members cm JOIN social_features.teacher_classrooms tc ON tc.classroom_id = cm.classroom_id WHERE cm.user_id = NEW.user_id AND cm.is_primary = true LIMIT 1; IF v_teacher_id IS NOT NULL THEN INSERT INTO progress_tracking.student_intervention_alerts ( teacher_id, student_id, alert_type, priority, message, details, created_at ) VALUES ( v_teacher_id, NEW.user_id, 'repeated_failures', 'high', 'Estudiante con multiples ejercicios fallidos consecutivos', jsonb_build_object( 'failure_count', v_failure_count, 'last_exercise_id', NEW.exercise_id, 'last_score', NEW.score ), NOW() ) ON CONFLICT DO NOTHING; -- Evitar duplicados END IF; END IF; RETURN NEW; END; $$ LANGUAGE plpgsql; -- Trigger CREATE TRIGGER trg_check_student_failures AFTER INSERT ON progress_tracking.exercise_submissions FOR EACH ROW EXECUTE FUNCTION progress_tracking.check_student_failures(); ``` ### 4.2 Funcion de Validacion y Auditoria Ya existe la funcion `educational_content.validate_and_audit()` que: 1. Recibe las respuestas del estudiante 2. Compara con respuestas correctas del ejercicio 3. Calcula score 4. Registra intento 5. Retorna resultado **Ver:** `docs/90-transversal/archivos-historicos/2025-11/DIAGRAMA-FLUJO-SUBMISSIONS-2025-11-19.md` --- ## 5. Endpoints de Integracion ### 5.1 Endpoints que Student Portal DEBE usar correctamente | Endpoint | Metodo | Descripcion | Datos Guardados | |----------|--------|-------------|-----------------| | `/progress/submissions` | POST | Enviar respuesta de ejercicio | exercise_submissions | | `/progress/attempts` | POST | Iniciar intento | exercise_attempts | | `/progress/attempts/:id` | PATCH | Actualizar intento (autosave) | exercise_attempts | | `/gamification/missions/:id/claim` | POST | Reclamar recompensa mision | ml_coins_transactions | ### 5.2 Endpoints que Teacher Portal CONSUME | Endpoint | Metodo | Descripcion | Origen de Datos | |----------|--------|-------------|-----------------| | `/teacher/dashboard/stats` | GET | Estadisticas generales | Agregacion multiple | | `/teacher/students/:id/progress` | GET | Progreso del estudiante | module_progress | | `/teacher/exercise-responses` | GET | Respuestas de ejercicios | exercise_submissions | | `/teacher/alerts` | GET | Alertas de intervencion | student_intervention_alerts | | `/teacher/classrooms/:id/students` | GET | Estudiantes del aula | classroom_members + user_stats | | `/gamification/users/:id/stats` | GET | Stats de gamificacion | user_stats | | `/gamification/users/:id/achievements` | GET | Logros del estudiante | user_achievements | ### 5.3 Endpoints NUEVOS Requeridos | Endpoint | Metodo | Descripcion | Prioridad | |----------|--------|-------------|-----------| | `/teacher/students/:id/attempts/:exerciseId` | GET | Historial de intentos | P0 | | `/teacher/students/:id/pending-activities` | GET | Actividades pendientes | P1 | | `/teacher/students/:id/recent-activities` | GET | Actividades recientes | P1 | | `/teacher/classrooms/:id/exercise-stats` | GET | Stats por tipo de ejercicio | P1 | | `/teacher/classrooms/:id/problematic-exercises` | GET | Ejercicios con mas fallos | P1 | --- ## 6. Dependencias entre Objetos ### 6.1 Mapa de Dependencias ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ MAPA DE DEPENDENCIAS │ └─────────────────────────────────────────────────────────────────────────────┘ Frontend Student (genera) Backend (procesa) Frontend Teacher (consume) ───────────────────────── ──────────────────── ──────────────────────────── ExercisePage.tsx ExerciseSubmissionService TeacherExerciseResponsesPage │ │ ▲ ├── useExerciseState() ├── submitAndGrade() │ │ └── answers JSONB │ ├── validate() │ │ │ ├── autoGrade() │ └── handleSubmit() │ ├── saveSubmission() ───────┼── GET /exercise-responses │ │ └── distributeRewards() │ │ │ │ ▼ ▼ │ POST /submissions ─────────────► exercise_submissions ──────────────────┘ │ ├── TRIGGER: update_module_progress │ │ │ ▼ │ module_progress ────────► GET /students/:id/progress │ │ │ ▼ │ TeacherProgressPage │ ├── TRIGGER: update_user_stats │ │ │ ▼ │ user_stats ─────────────► GET /gamification/stats │ ml_coins_transactions │ │ ▼ │ TeacherGamificationPage │ └── TRIGGER: check_student_failures │ ▼ student_intervention_alerts ─► GET /alerts │ ▼ TeacherAlertsPage ``` ### 6.2 Impacto de Cambios | Si cambias... | Afecta a... | |---------------|-------------| | Estructura de `answer_data` en Student | DTOs de respuesta en Teacher, Funcion de validacion en BD | | Schema de `exercise_submissions` | Triggers de BD, Queries de Teacher, DTOs de ambos portales | | Logica de `autoGrade()` en Backend | Scores que ve el Teacher, Triggers de gamificacion | | Trigger de `update_module_progress` | Datos de progreso en Teacher Dashboard | | Trigger de `update_user_stats` | Datos de gamificacion en Teacher | --- ## 7. Checklist de Desarrollo ### 7.1 Para Desarrollo en Student Portal Antes de modificar cualquier funcionalidad que genere datos: - [ ] Verificar que el endpoint correcto se esta usando (ver seccion 5.1) - [ ] Verificar que la estructura de `answer_data` sigue el formato documentado (seccion 3.2) - [ ] Verificar que los triggers de BD estan activos (seccion 4) - [ ] Probar que Teacher Portal puede ver los datos generados - [ ] Actualizar esta documentacion si hay cambios en estructuras ### 7.2 Para Desarrollo en Teacher Portal Antes de consumir nuevos datos: - [ ] Verificar que el endpoint existe (ver seccion 5.2) - [ ] Verificar que el Student Portal esta generando los datos correctamente - [ ] Verificar tipos de datos en TypeScript coinciden con respuesta real - [ ] Probar con datos reales de estudiantes - [ ] Documentar cualquier endpoint nuevo necesario ### 7.3 Para Desarrollo en Backend Antes de modificar servicios o triggers: - [ ] Evaluar impacto en ambos portales (ver seccion 6.2) - [ ] Verificar que no se rompen triggers existentes - [ ] Probar flujo completo: Student envía → Backend procesa → Teacher ve - [ ] Actualizar DTOs si hay cambios en estructuras - [ ] Actualizar esta documentacion ### 7.4 Para Desarrollo en Database Antes de modificar schemas o triggers: - [ ] Consultar impacto en tabla de dependencias (seccion 6.2) - [ ] Actualizar scripts DDL en `apps/database/ddl/` - [ ] Verificar que recreacion de BD funciona - [ ] Probar triggers con datos de prueba - [ ] Actualizar DATABASE_INVENTORY.yml --- ## 8. Validaciones Obligatorias ### 8.1 Antes de Merge a Main 1. **Build exitoso** ```bash cd apps/backend && npm run build cd apps/frontend && npm run build ``` 2. **Lint sin errores** ```bash cd apps/backend && npm run lint cd apps/frontend && npm run lint ``` 3. **Test de integracion Student→Teacher** - Student puede enviar ejercicio - Backend procesa y guarda correctamente - Triggers se ejecutan - Teacher puede ver los datos ### 8.2 Datos Minimos que Teacher DEBE poder ver Para cada estudiante de su aula: | Dato | Origen | Criticidad | |------|--------|------------| | Nombre y email | profiles | CRITICO | | Modulos completados | module_progress | CRITICO | | Porcentaje de progreso | module_progress | CRITICO | | Puntuacion promedio | Agregacion de submissions | CRITICO | | Ultima actividad | module_progress.last_activity_at | CRITICO | | Respuestas de ejercicios | exercise_submissions | CRITICO | | ML Coins | user_stats | ALTA | | Rango Maya | user_stats | ALTA | | Logros | user_achievements | MEDIA | | Misiones activas | user_missions | MEDIA | --- ## 9. Referencias ### Documentos Relacionados - [PORTAL-TEACHER-GUIDE.md](./PORTAL-TEACHER-GUIDE.md) - Guia completa del Teacher Portal - [PORTAL-TEACHER-API-REFERENCE.md](./PORTAL-TEACHER-API-REFERENCE.md) - Referencia de APIs - [PORTAL-TEACHER-FLOWS.md](./PORTAL-TEACHER-FLOWS.md) - Flujos de datos Teacher - [PORTAL-STUDENT-GUIDE.md](./PORTAL-STUDENT-GUIDE.md) - Guia del Student Portal - [../student-portal/README.md](../student-portal/README.md) - Documentacion de gaps Student - [DIAGRAMA-FLUJO-SUBMISSIONS](../90-transversal/archivos-historicos/2025-11/DIAGRAMA-FLUJO-SUBMISSIONS-2025-11-19.md) - Flujo detallado de submissions ### Inventarios - [DATABASE_INVENTORY.yml](../../orchestration/inventarios/DATABASE_INVENTORY.yml) - [BACKEND_INVENTORY.yml](../../orchestration/inventarios/BACKEND_INVENTORY.yml) - [FRONTEND_INVENTORY.yml](../../orchestration/inventarios/FRONTEND_INVENTORY.yml) --- **Documento creado por:** Architecture-Analyst **Fecha:** 2025-11-29 **Estado:** ESPECIFICACION LISTA PARA DESARROLLO