RF48: Usuario busca cursos con filtros
Descripción
Como usuario autenticado, quiero buscar cursos por texto y filtrarlos (categoría, nivel, duración) para encontrar rápido el contenido que me interesa.
Extiende RF47 con búsqueda por término y filtros, sobre los metadatos de cursos en Finnova DB.
| Campo | Valor |
|---|---|
| Módulo | Courses Module |
| Actor | Usuario autenticado |
| Endpoint | GET /courses?search=&category=&level=&duration= |
| Precondiciones | Sesión activa |
| Prioridad | Baja (MVP/post-MVP) |
| Etapa | MBI 1 |
| Requisitos relacionados | RF47, RF52 |
Reglas de negocio
- RN-48.1 — La búsqueda por texto considera título y descripción; es insensible a mayúsculas y acentos.
- RN-48.2 — Los filtros se combinan (AND) y aceptan valores de catálogo.
- RN-48.3 — Solo se buscan cursos publicados.
- RN-48.4 — La búsqueda usa consultas parametrizadas / búsqueda full-text segura.
Validaciones de entrada
| Campo | Reglas | Mensaje de error |
|---|---|---|
search | Opcional. Máx. 100 caracteres. | "El término de búsqueda es demasiado largo." |
category | Opcional. Valor de catálogo. | "Categoría no válida." |
level | Opcional. Enum (basic, intermediate, advanced). | "Nivel no válido." |
El término de búsqueda se sanitiza y se usa parametrizado; no se aceptan inyecciones SQL.
Criterios de aceptación
Escenario 1: Búsqueda con resultados
Dado que escribo "ahorro" y filtro por nivel básico,
Cuando ejecuto la búsqueda,
Entonces el sistema devuelve los cursos publicados que coinciden,
Y responde 200 OK.
Escenario 2: Búsqueda sin resultados
Dado que busco un término sin coincidencias, Cuando ejecuto la búsqueda, Entonces se muestra un estado vacío con sugerencia de ajustar filtros.
Escenario 3: Filtro inválido
Dado que envío una categoría o nivel fuera de catálogo,
Cuando el backend valida,
Entonces responde 400 con el mensaje correspondiente.
Escenario 4: Entrada maliciosa (seguridad)
Dado que el término de búsqueda contiene una inyección SQL, Cuando el backend procesa, Entonces la entrada se sanitiza/parametriza y no se ejecuta.
Criterios no funcionales
- Respuesta < 1.5 s; índice/búsqueda full-text apropiada.
- Comunicación TLS 1.2+.