--- id: "README" title: "Modulo Educativo" type: "Documentation" project: "trading-platform" version: "1.0.0" updated_date: "2026-01-04" --- # OQI-002: Modulo Educativo **Estado:** ✅ Implementado **Fecha:** 2025-12-05 **Modulo:** `apps/backend/src/modules/courses` --- ## Descripcion Sistema de cursos educativos con: - Categorias de cursos - Cursos con niveles de dificultad - Modulos dentro de cada curso - Lecciones con contenido multimedia - Sistema de progreso del usuario --- ## Arquitectura ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Frontend │────▶│ NestJS API │────▶│ PostgreSQL │ │ /courses/* │ │ /courses/* │ │ education schema│ └─────────────────┘ └─────────────────┘ └─────────────────┘ ``` --- ## Endpoints | Metodo | Ruta | Descripcion | Auth | |--------|------|-------------|------| | GET | `/courses` | Listar cursos (paginado) | - | | GET | `/courses/:id` | Detalle de curso | - | | POST | `/courses` | Crear curso | Admin | | PATCH | `/courses/:id` | Actualizar curso | Admin | | DELETE | `/courses/:id` | Eliminar curso | Admin | | GET | `/courses/categories` | Listar categorias | - | | POST | `/courses/categories` | Crear categoria | Admin | --- ## Entidades ### Category ```typescript @Entity({ name: 'categories', schema: 'education' }) class Category { id: string; // UUID name: string; // "Trading Basico" slug: string; // "trading-basico" description?: string; color?: string; // "#3B82F6" iconName?: string; // "chart-line" sortOrder: number; // Para ordenar isActive: boolean; createdAt: Date; updatedAt: Date; } ``` ### Course ```typescript @Entity({ name: 'courses', schema: 'education' }) class Course { id: string; categoryId: string; title: string; // "Introduccion al Trading" slug: string; // "introduccion-trading" subtitle?: string; description: string; thumbnailUrl?: string; level: DifficultyLevel; // beginner | intermediate | advanced | expert status: PublishStatus; // draft | published | archived price?: number; // null = gratis discountPrice?: number; isFree: boolean; isFeatured: boolean; durationMinutes?: number; sortOrder: number; publishedAt?: Date; createdAt: Date; updatedAt: Date; } ``` ### Module ```typescript @Entity({ name: 'modules', schema: 'education' }) class Module { id: string; courseId: string; title: string; // "Fundamentos del Mercado" description?: string; sortOrder: number; isActive: boolean; createdAt: Date; updatedAt: Date; } ``` ### Lesson ```typescript @Entity({ name: 'lessons', schema: 'education' }) class Lesson { id: string; moduleId: string; title: string; // "Que es el Trading" slug: string; type: LessonType; // video | article | quiz | exercise content?: string; // Contenido markdown/HTML videoUrl?: string; durationMinutes?: number; sortOrder: number; isFree: boolean; // Preview gratuito isActive: boolean; createdAt: Date; updatedAt: Date; } ``` --- ## Niveles de Dificultad | Nivel | Label ES | Color | |-------|----------|-------| | beginner | Principiante | Verde | | intermediate | Intermedio | Azul | | advanced | Avanzado | Naranja | | expert | Experto | Rojo | --- ## Query Parameters ### GET /courses | Param | Tipo | Descripcion | |-------|------|-------------| | page | number | Pagina (default: 1) | | limit | number | Items por pagina (default: 10, max: 100) | | categoryId | uuid | Filtrar por categoria | | level | string | Filtrar por nivel | | isFree | boolean | Solo cursos gratuitos | | isFeatured | boolean | Solo destacados | | status | string | Estado de publicacion | | search | string | Buscar en titulo/descripcion | | sortBy | string | Campo para ordenar | | sortOrder | asc/desc | Direccion de orden | --- ## Respuesta Paginada ```json { "data": [ { "id": "uuid", "title": "Introduccion al Trading", "level": "beginner", "price": 29.99, "isFree": false, "thumbnailUrl": "https://...", "durationMinutes": 180, "category": { "id": "uuid", "name": "Trading Basico" } } ], "meta": { "page": 1, "limit": 10, "total": 45, "totalPages": 5 } } ``` --- ## Flujo de Compra ``` 1. Usuario ve catalogo de cursos 2. Selecciona curso de pago 3. Redirige a checkout (Stripe) 4. Pago exitoso -> webhook actualiza acceso 5. Usuario puede ver contenido completo ``` --- ## Frontend ### Pagina de Cursos ```typescript // apps/frontend/src/pages/Courses.tsx function Courses() { const [courses, setCourses] = useState([]); const [categories, setCategories] = useState([]); const [selectedCategory, setSelectedCategory] = useState(''); // Carga cursos con filtros // Muestra grid de cards // Paginacion } ``` ### Servicio ```typescript // apps/frontend/src/services/courses.ts export const coursesService = { getCourses(params: CourseQueryParams): Promise>, getCourse(id: string): Promise, getCategories(): Promise, }; ``` --- ## Archivos ``` apps/backend/src/modules/courses/ ├── dto/ │ ├── course.dto.ts │ ├── module.dto.ts │ └── lesson.dto.ts ├── entities/ │ ├── category.entity.ts │ ├── course.entity.ts │ ├── module.entity.ts │ └── lesson.entity.ts ├── courses.controller.ts ├── courses.service.ts └── courses.module.ts apps/frontend/src/ ├── pages/ │ └── Courses.tsx └── services/ └── courses.ts ``` --- ## Proximas Mejoras - [ ] Progreso del usuario por leccion - [ ] Sistema de quizzes - [ ] Certificados de finalizacion - [ ] Reviews y ratings - [ ] Busqueda full-text --- *Documentacion generada: 2025-12-05*