Changes include: - Updated architecture documentation - Enhanced module definitions (OQI-001 to OQI-008) - ML integration documentation updates - Trading strategies documentation - Orchestration and inventory updates - Docker configuration updates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
278 lines
6.1 KiB
Markdown
278 lines
6.1 KiB
Markdown
---
|
|
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<Course[]>([]);
|
|
const [categories, setCategories] = useState<Category[]>([]);
|
|
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<PaginatedResponse<Course>>,
|
|
getCourse(id: string): Promise<Course>,
|
|
getCategories(): Promise<Category[]>,
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## 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*
|