---
id: "RF-EDU-001"
title: "Catalogo de Cursos"
type: "Requirement"
status: "Done"
priority: "Alta"
module: "education"
epic: "OQI-002"
version: "1.0"
created_date: "2025-12-05"
updated_date: "2026-01-04"
---

# RF-EDU-001: Catálogo de Cursos

**Versión:** 1.0.0
**Fecha:** 2025-12-05
**Épica:** OQI-002 - Módulo Educativo
**Prioridad:** P0
**Story Points:** 8

---

## Descripción

El sistema debe proporcionar un catálogo completo de cursos educativos sobre trading e inversiones, con capacidades avanzadas de filtrado, búsqueda y categorización que permitan a los usuarios descubrir contenido relevante según su nivel de experiencia y áreas de interés.

---

## Requisitos Funcionales

### RF-EDU-001.1: Listado de Cursos

El sistema debe:
- Mostrar todos los cursos activos en formato de tarjetas (cards)
- Incluir para cada curso: título, descripción breve, imagen, nivel, duración, módulos, progreso
- Mostrar badge de "Nuevo" para cursos publicados en últimos 30 días
- Mostrar badge de "En curso" para cursos iniciados por el usuario
- Mostrar badge de "Completado" con porcentaje para cursos en progreso
- Implementar paginación (12 cursos por página)

### RF-EDU-001.2: Categorías

El sistema debe soportar las siguientes categorías:

| Categoría | Slug | Descripción |
|-----------|------|-------------|
| Fundamentos | fundamentals | Conceptos básicos de trading |
| Análisis Técnico | technical-analysis | Indicadores y patrones |
| Análisis Fundamental | fundamental-analysis | Valoración de activos |
| Gestión de Riesgo | risk-management | Money management |
| Psicología del Trading | trading-psychology | Control emocional |
| Estrategias Avanzadas | advanced-strategies | Sistemas complejos |
| Criptomonedas | crypto | Trading de cripto |
| IA y Trading | ai-trading | Machine Learning aplicado |

### RF-EDU-001.3: Niveles de Dificultad

El sistema debe clasificar cursos en:
- **Principiante:** Sin conocimientos previos requeridos
- **Intermedio:** Requiere conocimientos básicos
- **Avanzado:** Para traders experimentados
- **Experto:** Contenido especializado

### RF-EDU-001.4: Filtros

El sistema debe permitir filtrar por:
- Categoría (múltiple selección)
- Nivel de dificultad (múltiple selección)
- Duración (rangos: <2h, 2-5h, 5-10h, >10h)
- Estado: Nuevos, En curso, Completados, No iniciados
- Instructor
- Gratuitos vs Premium

### RF-EDU-001.5: Búsqueda

El sistema debe:
- Implementar barra de búsqueda en tiempo real
- Buscar en: título, descripción, tags, nombre de instructor
- Mostrar resultados mientras el usuario escribe (debounce 300ms)
- Resaltar términos coincidentes en resultados
- Mostrar sugerencias de búsqueda basadas en términos populares
- Guardar historial de búsquedas del usuario

### RF-EDU-001.6: Ordenamiento

El sistema debe permitir ordenar por:
- Más recientes
- Más populares (por número de estudiantes)
- Mejor valorados (rating)
- Duración (ascendente/descendente)
- Alfabético (A-Z, Z-A)
- Progreso del usuario (para cursos iniciados)

### RF-EDU-001.7: Recomendaciones

El sistema debe:
- Mostrar sección "Recomendado para ti" basado en:
  - Cursos en progreso del usuario
  - Nivel de experiencia del perfil
  - Cursos completados previamente
  - Categorías de interés
- Mostrar sección "Continuar aprendiendo" con cursos incompletos
- Mostrar "Cursos relacionados" al ver detalle de curso

---

## Datos de Entrada

| Campo | Tipo | Descripción |
|-------|------|-------------|
| page | number | Número de página (default: 1) |
| limit | number | Elementos por página (default: 12, max: 50) |
| category | string[] | IDs de categorías a filtrar |
| level | string[] | Niveles de dificultad |
| search | string | Término de búsqueda |
| sortBy | string | Campo de ordenamiento |
| sortOrder | asc/desc | Dirección del ordenamiento |

---

## Datos de Salida

```typescript
interface Course {
  id: string;
  title: string;
  slug: string;
  description: string;
  shortDescription: string;
  thumbnail: string;
  category: {
    id: string;
    name: string;
    slug: string;
    icon: string;
  };
  level: 'beginner' | 'intermediate' | 'advanced' | 'expert';
  duration: number; // minutos
  moduleCount: number;
  lessonCount: number;
  studentCount: number;
  rating: number; // 0-5
  reviewCount: number;
  instructor: {
    id: string;
    name: string;
    avatar: string;
    title: string;
  };
  tags: string[];
  isPremium: boolean;
  publishedAt: string;
  userProgress?: {
    enrolledAt: string;
    progressPercent: number;
    lastAccessedAt: string;
    isCompleted: boolean;
  };
}

interface CatalogResponse {
  courses: Course[];
  pagination: {
    page: number;
    limit: number;
    total: number;
    totalPages: number;
  };
  filters: {
    categories: Category[];
    levels: string[];
  };
}
```

---

## Reglas de Negocio

1. **Cursos activos:** Solo mostrar cursos con status 'published'
2. **Acceso Premium:** Cursos premium requieren suscripción activa
3. **Visibilidad:** Cursos draft solo visibles para instructores y admins
4. **Límite de paginación:** Máximo 50 cursos por página
5. **Caché:** Catálogo se cachea por 5 minutos
6. **Búsqueda mínima:** Al menos 2 caracteres para búsqueda
7. **Recomendaciones:** Máximo 6 cursos en sección recomendados
8. **Orden por defecto:** Más recientes primero para usuarios nuevos

---

## Criterios de Aceptación

```gherkin
Escenario: Usuario visualiza catálogo de cursos
  DADO que el usuario está autenticado
  Y está en la página de educación
  CUANDO accede a /education/courses
  ENTONCES se muestra un listado de cursos
  Y se muestran 12 cursos por página
  Y cada curso muestra: título, imagen, nivel, duración, rating
  Y se muestran filtros en sidebar izquierdo
  Y se muestra barra de búsqueda en header

Escenario: Usuario filtra por categoría
  DADO que el usuario está en el catálogo
  CUANDO selecciona la categoría "Análisis Técnico"
  ENTONCES se muestran solo cursos de esa categoría
  Y el filtro se marca como activo
  Y la URL se actualiza con ?category=technical-analysis
  Y se mantienen otros filtros activos

Escenario: Usuario busca curso
  DADO que el usuario está en el catálogo
  CUANDO escribe "fibonacci" en la búsqueda
  ENTONCES se muestran resultados en tiempo real
  Y se resalta el término "fibonacci" en resultados
  Y se muestra contador "X resultados para 'fibonacci'"

Escenario: Usuario sin resultados
  DADO que el usuario busca "xyz123"
  Y no hay cursos que coincidan
  ENTONCES se muestra mensaje "No se encontraron cursos"
  Y se sugieren búsquedas alternativas
  Y se muestran cursos populares como alternativa

Escenario: Ver cursos recomendados
  DADO que el usuario tiene cursos en progreso
  CUANDO accede al catálogo
  ENTONCES se muestra sección "Recomendado para ti"
  Y aparecen máximo 6 cursos relacionados
  Y se muestra sección "Continuar aprendiendo"
```

---

## Dependencias

- Education API para datos de cursos
- PostgreSQL schema education
- Redis para caché de catálogo
- Elasticsearch para búsqueda (opcional, mejora performance)

---

## Notas Técnicas

- Implementar virtual scrolling para listas largas
- Usar React Query para caché de frontend
- Implementar skeleton loading durante carga
- Optimizar imágenes con lazy loading
- Considerar SSR para mejor SEO
- Implementar analytics de búsquedas para mejorar recomendaciones

---

## Referencias

- Schema database: `/backend/src/database/schemas/education.sql`
- API endpoints: `/backend/src/modules/courses/courses.routes.ts`
- Frontend: `/frontend/src/pages/Courses.tsx`

---

## Tareas Técnicas

**Database:**
- [ ] Verificar índices en education.courses (title, category_id, level, published_at)
- [ ] Crear vista courses_catalog con joins pre-calculados
- [ ] Implementar full-text search en PostgreSQL

**Backend:**
- [ ] Endpoint GET /education/courses con paginación y filtros
- [ ] Endpoint GET /education/categories
- [ ] Implementar CourseService.getCatalog()
- [ ] Implementar sistema de recomendaciones básico
- [ ] Agregar rate limiting a búsqueda
- [ ] Implementar caché Redis para catálogo

**Frontend:**
- [ ] Crear página CoursesPage.tsx
- [ ] Crear componente CourseCard.tsx
- [ ] Crear componente CourseFilters.tsx
- [ ] Crear componente SearchBar.tsx
- [ ] Implementar coursesStore (Zustand)
- [ ] Implementar infinite scroll opcional
- [ ] Agregar analytics de búsqueda

**Tests:**
- [ ] Test unitario CourseService
- [ ] Test integración GET /courses con filtros
- [ ] Test E2E navegación y búsqueda

---

**Creado por:** Requirements-Analyst
**Fecha:** 2025-12-05
**Última actualización:** 2025-12-05
