workspace/projects/gamilit/docs/95-guias-desarrollo/PORTAL-TEACHER-API-REFERENCE.md
rckrdmrd ea1879f4ad feat: Initial workspace structure with multi-level Git configuration
- Configure workspace Git repository with comprehensive .gitignore
- Add Odoo as submodule for ERP reference code
- Include documentation: SETUP.md, GIT-STRUCTURE.md
- Add gitignore templates for projects (backend, frontend, database)
- Structure supports independent repos per project/subproject level

Workspace includes:
- core/ - Reusable patterns, modules, orchestration system
- projects/ - Active projects (erp-suite, gamilit, trading-platform, etc.)
- knowledge-base/ - Reference code and patterns (includes Odoo submodule)
- devtools/ - Development tools and templates
- customers/ - Client implementations template

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 10:44:23 -06:00

21 KiB

Portal Teacher - API Reference

Fecha de creacion: 2025-11-29 Version: 1.0.0 Estado: VIGENTE Complementa: PORTAL-TEACHER-GUIDE.md


1. Resumen de Endpoints

El Portal Teacher expone 45+ endpoints organizados en 7 controladores:

Controller Base Path Endpoints Descripcion
TeacherController /teacher 20 Dashboard, progress, analytics, grading
TeacherClassroomsController /teacher/classrooms 12 CRUD de aulas, estudiantes
InterventionAlertsController /teacher/alerts 5 Alertas de intervencion
TeacherCommunicationController /teacher/messages 6 Mensajes y comunicacion
TeacherContentController /teacher/content 5 Contenido personalizado
ExerciseResponsesController /teacher/exercise-responses 4 Respuestas de ejercicios
TeacherGradesController /teacher/grades 3 Calificaciones

2. Dashboard APIs

2.1 GET /teacher/dashboard/stats

Obtiene estadisticas generales del dashboard del teacher.

Request:

GET /api/teacher/dashboard/stats
Authorization: Bearer {token}

Response (200):

{
  "total_classrooms": 5,
  "total_students": 127,
  "active_students": 98,
  "pending_submissions": 23,
  "average_completion": 72.5,
  "average_score": 85.3,
  "alerts_count": 4,
  "recent_activity_count": 15
}

Frontend Hook:

// hooks/useTeacherDashboard.ts
export function useTeacherDashboard() {
  const { data: stats } = useQuery({
    queryKey: ['teacher', 'dashboard', 'stats'],
    queryFn: () => teacherApi.getDashboardStats(),
    staleTime: 60_000, // 1 minuto
  });

  return { stats };
}

2.2 GET /teacher/dashboard/activities

Obtiene actividades recientes.

Request:

GET /api/teacher/dashboard/activities?limit=10
Authorization: Bearer {token}

Response (200):

{
  "activities": [
    {
      "id": "uuid",
      "type": "submission",
      "student_id": "uuid",
      "student_name": "Juan Perez",
      "action": "submitted_exercise",
      "exercise_name": "Timeline - Marie Curie",
      "classroom_name": "5to A - Matematicas",
      "timestamp": "2025-11-29T10:30:00Z"
    }
  ]
}

2.3 GET /teacher/dashboard/alerts

Obtiene alertas de estudiantes en riesgo.

Response (200):

{
  "alerts": [
    {
      "id": "uuid",
      "student_id": "uuid",
      "student_name": "Maria Garcia",
      "type": "declining_trend",
      "severity": "high",
      "message": "Desempeno en declive en ultimas 2 semanas",
      "classroom_name": "5to A",
      "created_at": "2025-11-28T15:00:00Z"
    }
  ]
}

2.4 GET /teacher/dashboard/top-performers

Obtiene top estudiantes por desempeno.

Request:

GET /api/teacher/dashboard/top-performers?limit=5

Response (200):

{
  "students": [
    {
      "id": "uuid",
      "name": "Ana Lopez",
      "avatar_url": "https://...",
      "classroom_name": "5to A",
      "total_xp": 15000,
      "maya_rank": "Arquitecto Maya",
      "completion_rate": 95.5,
      "average_score": 92.3
    }
  ]
}

3. Classrooms APIs

3.1 GET /teacher/classrooms

Lista todas las aulas del teacher.

Request:

GET /api/teacher/classrooms?page=1&limit=10&status=active&search=matematicas

Query Parameters:

Param Type Required Description
page number No Pagina (default: 1)
limit number No Items por pagina (default: 10)
search string No Buscar por nombre
status string No active, inactive, archived, all
grade_level string No Filtrar por nivel
subject string No Filtrar por materia

Response (200):

{
  "data": [
    {
      "id": "uuid",
      "name": "5to A - Matematicas",
      "code": "5A-MAT-2025",
      "grade_level": "5to",
      "subject": "Matematicas",
      "student_count": 28,
      "active_students": 25,
      "average_progress": 72.5,
      "status": "active",
      "is_owner": true,
      "created_at": "2025-01-15T10:00:00Z"
    }
  ],
  "total": 5,
  "page": 1,
  "limit": 10,
  "total_pages": 1
}

Frontend Hook:

// hooks/useClassrooms.ts
export function useClassrooms(filters?: GetClassroomsQueryDto) {
  const query = useQuery({
    queryKey: ['teacher', 'classrooms', filters],
    queryFn: () => classroomsApi.getAll(filters),
  });

  const createMutation = useMutation({
    mutationFn: classroomsApi.create,
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['teacher', 'classrooms'] });
    },
  });

  return {
    classrooms: query.data?.data ?? [],
    isLoading: query.isLoading,
    createClassroom: createMutation.mutate,
    isCreating: createMutation.isPending,
  };
}

3.2 POST /teacher/classrooms

Crea una nueva aula.

Request:

POST /api/teacher/classrooms
Content-Type: application/json
Authorization: Bearer {token}

{
  "name": "6to B - Ciencias",
  "grade_level": "6to",
  "subject": "Ciencias",
  "description": "Clase de ciencias naturales",
  "max_students": 35,
  "settings": {
    "allow_late_submissions": true,
    "auto_grade_enabled": false
  }
}

Response (201):

{
  "id": "uuid",
  "name": "6to B - Ciencias",
  "code": "6B-CIE-2025-ABC123",
  "grade_level": "6to",
  "subject": "Ciencias",
  "student_count": 0,
  "status": "active",
  "is_owner": true,
  "created_at": "2025-11-29T10:00:00Z"
}

3.3 GET /teacher/classrooms/:id/students

Obtiene estudiantes de un aula.

Request:

GET /api/teacher/classrooms/uuid/students?page=1&limit=20&sort_by=progress&sort_order=desc

Response (200):

{
  "data": [
    {
      "id": "uuid",
      "user_id": "uuid",
      "name": "Juan Perez",
      "email": "juan@example.com",
      "avatar_url": "https://...",
      "status": "active",
      "enrolled_at": "2025-02-01T10:00:00Z",
      "progress": {
        "completion_percentage": 75.5,
        "average_score": 85.3,
        "total_xp": 12500,
        "maya_rank": "Constructor Maya",
        "exercises_completed": 45,
        "exercises_total": 60
      },
      "last_activity": "2025-11-28T15:30:00Z",
      "is_blocked": false
    }
  ],
  "total": 28,
  "page": 1,
  "limit": 20,
  "total_pages": 2
}

3.4 GET /teacher/classrooms/:id/progress

Obtiene progreso detallado del aula por modulo.

Response (200):

{
  "classroomData": {
    "id": "uuid",
    "name": "5to A - Matematicas",
    "student_count": 28,
    "active_students": 25,
    "average_completion": 72.5,
    "average_score": 85.3,
    "total_exercises": 60,
    "completed_exercises": 45
  },
  "moduleProgress": [
    {
      "module_id": "uuid",
      "module_name": "Modulo 1: Marie Curie - Primera Exploracion",
      "module_order": 1,
      "completion_percentage": 85.5,
      "average_score": 88.3,
      "students_completed": 22,
      "students_in_progress": 4,
      "students_not_started": 2,
      "average_time_minutes": 120.5,
      "exercises": [
        {
          "exercise_id": "uuid",
          "exercise_name": "Timeline - Vida de Marie Curie",
          "mechanic_type": "timeline",
          "completion_rate": 92.0,
          "average_score": 87.5,
          "average_attempts": 1.3
        }
      ]
    }
  ]
}

4. Student Progress APIs

4.1 GET /teacher/students/:studentId/progress

Obtiene progreso completo de un estudiante.

Request:

GET /api/teacher/students/uuid/progress?include_exercises=true&date_from=2025-01-01

Response (200):

{
  "student": {
    "id": "uuid",
    "name": "Juan Perez",
    "email": "juan@example.com"
  },
  "summary": {
    "total_xp": 15000,
    "ml_coins_balance": 2500,
    "maya_rank": "Arquitecto Maya",
    "level": 12,
    "completion_percentage": 78.5,
    "average_score": 86.2,
    "total_time_minutes": 1250,
    "streak_days": 15
  },
  "modules": [
    {
      "module_id": "uuid",
      "module_name": "Modulo 1",
      "status": "completed",
      "completion_percentage": 100,
      "average_score": 92.5,
      "time_spent_minutes": 180,
      "completed_at": "2025-11-15T10:00:00Z"
    }
  ],
  "achievements": [
    {
      "id": "uuid",
      "name": "Primera Victoria",
      "description": "Completar primer ejercicio",
      "icon_url": "https://...",
      "unlocked_at": "2025-02-01T15:00:00Z"
    }
  ],
  "activity_timeline": [
    {
      "date": "2025-11-28",
      "exercises_completed": 3,
      "xp_earned": 450,
      "time_spent_minutes": 45
    }
  ]
}

4.2 GET /teacher/students/:studentId/insights

Obtiene insights AI del estudiante.

Response (200):

{
  "student_id": "uuid",
  "generated_at": "2025-11-29T10:00:00Z",
  "risk_level": "low",
  "strengths": [
    "Excelente en ejercicios de comprension literal",
    "Alta consistencia en entregas",
    "Buen manejo del tiempo"
  ],
  "weaknesses": [
    "Dificultad en inferencias complejas",
    "Tendencia a respuestas apresuradas en critica"
  ],
  "predictions": {
    "completion_probability": 0.92,
    "estimated_completion_date": "2025-12-15",
    "risk_of_dropout": 0.05
  },
  "recommendations": [
    {
      "type": "exercise",
      "priority": "high",
      "message": "Recomendar mas ejercicios de inferencia",
      "suggested_exercises": ["uuid1", "uuid2"]
    },
    {
      "type": "intervention",
      "priority": "medium",
      "message": "Programar sesion de retroalimentacion"
    }
  ]
}

4.3 POST /teacher/students/:studentId/note

Agrega nota de teacher sobre estudiante.

Request:

POST /api/teacher/students/uuid/note
Content-Type: application/json

{
  "classroom_id": "uuid",
  "content": "Estudiante muestra mejora notable en ultimas semanas",
  "is_private": true,
  "tags": ["mejora", "seguimiento"]
}

5. Grading APIs

5.1 GET /teacher/submissions

Obtiene submissions pendientes de calificar.

Request:

GET /api/teacher/submissions?status=pending&classroom_id=uuid&page=1&limit=20

Query Parameters:

Param Type Description
status string pending, graded, all
classroom_id string Filtrar por aula
assignment_id string Filtrar por tarea
student_id string Filtrar por estudiante
module_id string Filtrar por modulo
date_from string Fecha desde (ISO)
date_to string Fecha hasta (ISO)
sort_by string submitted_at, score, student_name
sort_order string asc, desc

Response (200):

{
  "data": [
    {
      "id": "uuid",
      "student": {
        "id": "uuid",
        "name": "Juan Perez",
        "avatar_url": "https://..."
      },
      "exercise": {
        "id": "uuid",
        "name": "Timeline - Marie Curie",
        "mechanic_type": "timeline"
      },
      "classroom": {
        "id": "uuid",
        "name": "5to A"
      },
      "submitted_at": "2025-11-28T15:30:00Z",
      "auto_score": 85.5,
      "final_score": null,
      "status": "pending",
      "attempt_number": 1,
      "time_spent_seconds": 320,
      "answers": { /* respuestas del estudiante */ }
    }
  ],
  "total": 23,
  "page": 1,
  "limit": 20
}

5.2 POST /teacher/submissions/:id/feedback

Califica y proporciona feedback.

Request:

POST /api/teacher/submissions/uuid/feedback
Content-Type: application/json

{
  "score": 90,
  "feedback": "Excelente trabajo en la organizacion cronologica",
  "strengths": ["Precision en fechas", "Conexiones logicas"],
  "areas_to_improve": ["Agregar mas contexto historico"],
  "xp_bonus": 50,
  "requires_revision": false
}

Response (200):

{
  "id": "uuid",
  "status": "graded",
  "final_score": 90,
  "feedback": "Excelente trabajo...",
  "graded_at": "2025-11-29T10:30:00Z",
  "graded_by": "uuid",
  "xp_awarded": 150
}

5.3 POST /teacher/submissions/bulk-grade

Califica multiples submissions.

Request:

POST /api/teacher/submissions/bulk-grade
Content-Type: application/json

{
  "submissions": [
    { "id": "uuid1", "score": 85, "feedback": "Buen trabajo" },
    { "id": "uuid2", "score": 92, "feedback": "Excelente" },
    { "id": "uuid3", "score": 78, "feedback": "Puede mejorar" }
  ],
  "apply_auto_xp": true
}

Response (200):

{
  "processed": 3,
  "successful": 3,
  "failed": 0,
  "results": [
    { "id": "uuid1", "status": "success" },
    { "id": "uuid2", "status": "success" },
    { "id": "uuid3", "status": "success" }
  ]
}

6. Analytics APIs

6.1 GET /teacher/analytics/classroom/:id

Analiticas detalladas de un aula.

Response (200):

{
  "classroom_id": "uuid",
  "period": {
    "from": "2025-01-01",
    "to": "2025-11-29"
  },
  "overview": {
    "total_students": 28,
    "active_students": 25,
    "average_completion": 72.5,
    "average_score": 85.3,
    "total_submissions": 1250,
    "total_time_hours": 450
  },
  "performance_distribution": {
    "excellent": 8,    // 90-100
    "good": 12,        // 80-89
    "average": 5,      // 70-79
    "below_average": 2, // 60-69
    "struggling": 1    // <60
  },
  "completion_trend": [
    { "week": "2025-W45", "completion_rate": 68.5 },
    { "week": "2025-W46", "completion_rate": 71.2 },
    { "week": "2025-W47", "completion_rate": 72.5 }
  ],
  "engagement_metrics": {
    "average_sessions_per_week": 3.5,
    "average_session_duration_minutes": 35,
    "peak_activity_hour": 16,
    "most_active_day": "Tuesday"
  },
  "at_risk_students": [
    {
      "student_id": "uuid",
      "name": "Maria Garcia",
      "risk_level": "high",
      "reason": "No activity in 7 days"
    }
  ]
}

6.2 GET /teacher/analytics/economy

Analiticas de economia ML Coins.

Response (200):

{
  "overview": {
    "total_circulation": 125000,
    "average_balance": 980,
    "median_balance": 850,
    "gini_coefficient": 0.32
  },
  "distribution": {
    "ranges": [
      { "range": "0-500", "count": 15, "percentage": 12.0 },
      { "range": "501-1000", "count": 45, "percentage": 36.0 },
      { "range": "1001-2000", "count": 40, "percentage": 32.0 },
      { "range": "2001-5000", "count": 20, "percentage": 16.0 },
      { "range": "5001+", "count": 5, "percentage": 4.0 }
    ]
  },
  "top_earners": [
    {
      "student_id": "uuid",
      "name": "Ana Lopez",
      "balance": 8500,
      "weekly_earnings": 450,
      "maya_rank": "Arquitecto Maya"
    }
  ],
  "spending_patterns": {
    "comodines": 35000,
    "customizations": 15000,
    "power_ups": 8000
  }
}

6.3 GET /teacher/analytics/achievements

Estadisticas de logros por aula.

Response (200):

{
  "classroom_id": "uuid",
  "total_achievements": 45,
  "total_unlocks": 892,
  "achievements": [
    {
      "id": "uuid",
      "name": "Primera Victoria",
      "description": "Completar primer ejercicio",
      "category": "progress",
      "unlock_count": 28,
      "unlock_percentage": 100,
      "average_unlock_time_days": 2.5
    },
    {
      "id": "uuid",
      "name": "Maestro del Tiempo",
      "description": "Completar Timeline perfecto",
      "category": "mastery",
      "unlock_count": 12,
      "unlock_percentage": 42.8,
      "average_unlock_time_days": 15.3
    }
  ],
  "rarest_achievements": [
    {
      "id": "uuid",
      "name": "Leyenda Maya",
      "unlock_count": 2,
      "unlock_percentage": 7.1
    }
  ]
}

7. Intervention Alerts APIs

7.1 GET /teacher/alerts

Lista alertas de intervencion.

Request:

GET /api/teacher/alerts?status=active&severity=high&classroom_id=uuid

Response (200):

{
  "data": [
    {
      "id": "uuid",
      "student": {
        "id": "uuid",
        "name": "Carlos Mendez",
        "avatar_url": "https://..."
      },
      "classroom": {
        "id": "uuid",
        "name": "5to A"
      },
      "type": "declining_trend",
      "severity": "high",
      "status": "active",
      "message": "Desempeno en declive: -15% en ultimas 2 semanas",
      "details": {
        "previous_average": 85.5,
        "current_average": 70.2,
        "trend_period_days": 14
      },
      "suggested_actions": [
        "Programar reunion con estudiante",
        "Revisar ejercicios con dificultad",
        "Contactar a padres si persiste"
      ],
      "created_at": "2025-11-27T10:00:00Z"
    }
  ],
  "total": 4,
  "by_severity": {
    "critical": 1,
    "high": 2,
    "medium": 1,
    "low": 0
  }
}

7.2 PATCH /teacher/alerts/:id/resolve

Resuelve una alerta.

Request:

PATCH /api/teacher/alerts/uuid/resolve
Content-Type: application/json

{
  "resolution_notes": "Reunion realizada, estudiante comprometido a mejorar",
  "actions_taken": ["Reunion con estudiante", "Plan de recuperacion"],
  "follow_up_date": "2025-12-05"
}

8. Bonus Coins APIs

8.1 POST /teacher/students/:studentId/bonus

Otorga bonificacion de ML Coins.

Request:

POST /api/teacher/students/uuid/bonus
Content-Type: application/json

{
  "amount": 100,
  "reason": "Excelente participacion en clase",
  "category": "participation",
  "notify_student": true
}

Response (201):

{
  "success": true,
  "transaction": {
    "id": "uuid",
    "amount": 100,
    "type": "teacher_bonus",
    "reason": "Excelente participacion en clase",
    "granted_by": "uuid",
    "granted_at": "2025-11-29T10:30:00Z"
  },
  "student_new_balance": 1850
}

Frontend Hook:

// hooks/useGrantBonus.ts
export function useGrantBonus() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({ studentId, data }: { studentId: string; data: GrantBonusDto }) =>
      bonusCoinsApi.grantBonus(studentId, data),
    onSuccess: (_, { studentId }) => {
      // Invalidar queries relacionadas
      queryClient.invalidateQueries({ queryKey: ['teacher', 'students', studentId] });
      queryClient.invalidateQueries({ queryKey: ['teacher', 'analytics', 'economy'] });
      toast.success('Bonificacion otorgada exitosamente');
    },
  });
}

9. Reports APIs

9.1 POST /teacher/reports/generate

Genera reporte PDF/Excel.

Request:

POST /api/teacher/reports/generate
Content-Type: application/json

{
  "format": "pdf",
  "report_type": "student_insights",
  "classroom_id": "uuid",
  "student_ids": ["uuid1", "uuid2"],
  "include_sections": [
    "summary",
    "progress",
    "achievements",
    "insights",
    "recommendations"
  ],
  "date_range": {
    "from": "2025-01-01",
    "to": "2025-11-29"
  }
}

Response (200):

  • Content-Type: application/pdf
  • Content-Disposition: attachment; filename="student-insights-report.pdf"
  • Binary PDF content

10. Error Handling

10.1 Codigos de Error Comunes

Code Description Resolution
400 Bad Request Validar datos de entrada
401 Unauthorized Token invalido o expirado
403 Forbidden Sin acceso al recurso
404 Not Found Recurso no existe
409 Conflict Duplicado o conflicto
429 Too Many Requests Rate limit excedido
500 Internal Error Contactar soporte

10.2 Formato de Error

{
  "statusCode": 403,
  "message": "Teacher does not have access to this classroom",
  "error": "Forbidden",
  "timestamp": "2025-11-29T10:30:00Z",
  "path": "/api/teacher/classrooms/uuid"
}

10.3 Manejo en Frontend

// hooks/useErrorHandler.ts
export function useApiError() {
  const handleError = useCallback((error: AxiosError) => {
    const status = error.response?.status;
    const message = (error.response?.data as any)?.message;

    switch (status) {
      case 401:
        // Redirigir a login
        window.location.href = '/login';
        break;
      case 403:
        toast.error('No tienes acceso a este recurso');
        break;
      case 404:
        toast.error('Recurso no encontrado');
        break;
      case 429:
        toast.error('Demasiadas solicitudes. Intenta de nuevo en un momento.');
        break;
      default:
        toast.error(message || 'Error inesperado');
    }
  }, []);

  return { handleError };
}

11. Rate Limiting

Endpoint Category Rate Limit Window
Dashboard 60 req 1 min
Analytics 30 req 1 min
Grading 100 req 1 min
Reports 10 req 1 min
Bonus Coins 20 req 1 min

12. Websocket Events

El Portal Teacher puede suscribirse a eventos en tiempo real:

// Suscribirse a eventos
socket.on('student:submission', (data) => {
  // Nueva submission recibida
  queryClient.invalidateQueries({ queryKey: ['teacher', 'submissions'] });
});

socket.on('student:alert', (data) => {
  // Nueva alerta de estudiante
  queryClient.invalidateQueries({ queryKey: ['teacher', 'alerts'] });
  toast.warning(`Alerta: ${data.message}`);
});

socket.on('student:progress', (data) => {
  // Estudiante completo ejercicio
  queryClient.invalidateQueries({
    queryKey: ['teacher', 'classrooms', data.classroom_id, 'progress']
  });
});

Changelog

Version Fecha Cambios
1.0.0 2025-11-29 Creacion inicial