ML Engine Updates: - Updated BTCUSD with Polygon API data (2024-2025): 215,699 new records - Re-trained all ML models: Attention (R²: 0.223), Base, Metamodel (87.3% confidence) - Backtest results: +176.71R profit with aggressive_filter strategy Documentation Consolidation: - Created docs/99-analisis/_MAP.md index with 13 new analysis documents - Consolidated inventories: removed duplicates from orchestration/inventarios/ - Updated ML_INVENTORY.yml with BTCUSD metrics and training results - Added execution reports: FASE11-BTCUSD, correction issues, alignment validation Architecture & Integration: - Updated all module documentation with NEXUS v3.4 frontmatter - Fixed _MAP.md indexes across all folders - Updated orchestration plans and traces Files: 229 changed, 5064 insertions(+), 1872 deletions(-) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
18 KiB
| id | title | type | status | priority | epic | story_points | created_date | updated_date |
|---|---|---|---|---|---|---|---|---|
| US-EDU-008 | Obtener Certificado | User Story | Done | Media | OQI-002 | 3 | 2025-12-05 | 2026-01-04 |
US-EDU-008: Obtener Certificado
Metadata
| Campo | Valor |
|---|---|
| ID | US-EDU-008 |
| Épica | OQI-002 - Módulo Educativo |
| Módulo | education |
| Prioridad | P2 |
| Story Points | 3 |
| Sprint | Sprint 5 |
| Estado | Pendiente |
| Asignado a | Por asignar |
Historia de Usuario
Como usuario que completó un curso, quiero obtener un certificado digital verificable, para validar mi logro, agregarlo a mi perfil profesional y compartirlo en redes sociales.
Descripción Detallada
El usuario debe recibir automáticamente un certificado digital en formato PDF al completar el 100% de un curso. El certificado debe tener diseño profesional con logo de Trading Platform, nombre del usuario, título del curso, fecha de finalización, ID único de verificación, y QR code. El usuario debe poder descargar el PDF, compartir en LinkedIn, y el certificado debe ser verificable públicamente.
Mockups/Wireframes
[MODAL DE CURSO COMPLETADO]
┌─────────────────────────────────────────────────────────────────┐
│ ✨ 🎓 ✨ │
│ │
│ ¡FELICIDADES! CURSO COMPLETADO │
│ │
│ Fibonacci Retracement Básico │
│ │
│ +200 XP ganados │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ [PREVIEW DEL CERTIFICADO] │ │
│ │ │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ [LOGO ORBIQUANT] │ │ │
│ │ │ CERTIFICADO DE FINALIZACIÓN │ │ │
│ │ │ │ │ │
│ │ │ Se certifica que │ │ │
│ │ │ JUAN PÉREZ │ │ │
│ │ │ Ha completado exitosamente │ │ │
│ │ │ "Fibonacci Retracement Básico" │ │ │
│ │ │ │ │ │
│ │ │ 05/12/2025 │ │ │
│ │ │ OQI-EDU-A3F8D291 │ │ │
│ │ │ │ │ │
│ │ │ [Firma Instructor] [Firma OQI] │ │ │
│ │ │ [QR CODE] │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ │ │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
│ [📥 Descargar PDF] [💼 Compartir en LinkedIn] [✕ Cerrar] │
│ │
└─────────────────────────────────────────────────────────────────┘
[PÁGINA DE CERTIFICADOS]
┌─────────────────────────────────────────────────────────────────┐
│ MIS CERTIFICADOS [🔍] │
│ │
│ Has obtenido 12 certificados │
│ │
│ Filtros: [Todos ▼] [Más recientes ▼] │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ [THUMBNAIL] │ │ [THUMBNAIL] │ │ [THUMBNAIL] │ │
│ │ │ │ │ │ │ │
│ │ Fibonacci │ │ Day Trading │ │ Candlestick │ │
│ │ Básico │ │ Pro │ │ Patterns │ │
│ │ │ │ │ │ │ │
│ │ 05/12/2025 │ │ 28/11/2025 │ │ 15/11/2025 │ │
│ │ OQI-...-291 │ │ OQI-...-8F2 │ │ OQI-...-4A1 │ │
│ │ │ │ │ │ │ │
│ │ [Ver] [📥] │ │ [Ver] [📥] │ │ [Ver] [📥] │ │
│ │ [💼 LinkedIn]│ │ [💼 LinkedIn]│ │ [💼 LinkedIn]│ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ [1] 2 3 4 │
│ │
└─────────────────────────────────────────────────────────────────┘
[PÁGINA DE VERIFICACIÓN PÚBLICA]
┌─────────────────────────────────────────────────────────────────┐
│ [LOGO] Trading Platform │
│ │
│ VERIFICACIÓN DE CERTIFICADO │
│ │
│ Certificado: OQI-EDU-A3F8D291 │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ ✓ CERTIFICADO VÁLIDO │ │
│ │ │ │
│ │ Otorgado a: Juan Pérez │ │
│ │ Curso: Fibonacci Retracement Básico │ │
│ │ Categoría: Análisis Técnico │ │
│ │ Fecha de finalización: 05/12/2025 │ │
│ │ Duración del curso: 2.5 horas │ │
│ │ Módulos: 5 | Lecciones: 23 │ │
│ │ │ │
│ │ Instructor: Carlos Mendoza │ │
│ │ Institución: Trading Platform │ │
│ │ │ │
│ │ Estado: ✅ Activo │ │
│ │ Emitido: 05/12/2025 15:45:00 UTC │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
│ Este certificado puede ser verificado en cualquier momento en: │
│ trading.com/verify/OQI-EDU-A3F8D291 │
│ │
└─────────────────────────────────────────────────────────────────┘
Criterios de Aceptación
Escenario 1: Completar curso genera certificado
DADO que el usuario completó todas las lecciones de un curso
Y aprobó todos los quizzes obligatorios
CUANDO se marca la última lección como completada
ENTONCES se genera automáticamente un certificado
Y se registra en backend con ID único (OQI-EDU-XXXXXXXX)
Y se genera PDF con diseño profesional
Y se almacena PDF en S3 o CDN
Y se muestra modal de felicitación
Y se envía email con certificado adjunto
Escenario 2: Ver certificado en modal
DADO que se generó el certificado
CUANDO se muestra el modal de curso completado
ENTONCES se muestra preview del certificado
Y se muestra botón "Descargar PDF"
Y se muestra botón "Compartir en LinkedIn"
Y se muestra "Ver todos mis certificados"
Escenario 3: Descargar certificado en PDF
DADO que el usuario tiene un certificado
CUANDO hace click en "Descargar PDF"
ENTONCES se descarga archivo PDF
Y el PDF contiene:
- Logo de Trading Platform
- Título "Certificado de Finalización"
- Nombre completo del usuario
- Título del curso
- Fecha de finalización
- ID único del certificado
- Firmas digitales (instructor + plataforma)
- QR code para verificación
- Footer con URL de verificación
Escenario 4: Compartir en LinkedIn
DADO que el usuario quiere compartir su certificado
CUANDO hace click en "Compartir en LinkedIn"
ENTONCES se abre nueva pestaña de LinkedIn
Y el formulario de certificación está pre-llenado con:
- Nombre: "Fibonacci Retracement Básico"
- Organización: "Trading Platform"
- Fecha de emisión: "Diciembre 2025"
- ID de certificado: "OQI-EDU-A3F8D291"
- URL de verificación: "trading.com/verify/..."
Escenario 5: Ver galería de certificados
DADO que el usuario tiene 12 certificados
CUANDO accede a /education/certificates
ENTONCES se muestra galería de todos los certificados
Y cada certificado muestra: thumbnail, título del curso, fecha
Y se muestra contador "Has obtenido 12 certificados"
Y se pueden filtrar por: categoría, fecha
Y se pueden ordenar por: más reciente, alfabético
Escenario 6: Verificar certificado públicamente
DADO que alguien tiene el ID de un certificado
CUANDO accede a trading.com/verify/OQI-EDU-A3F8D291
ENTONCES se muestra página de verificación pública
Y NO requiere login
Y se muestra:
- Estado: ✅ Válido
- Nombre del usuario
- Título del curso
- Fecha de finalización
- Detalles del curso
Y se confirma autenticidad del certificado
Escenario 7: Verificar certificado inválido
DADO que alguien accede con ID inválido
CUANDO accede a /verify/INVALID-ID-123
ENTONCES se muestra "Certificado no encontrado"
Y se muestra sugerencia "Verifica el ID ingresado"
Y se muestra link "¿Cómo verificar un certificado?"
Escenario 8: Email de certificado
DADO que se generó un certificado
CUANDO se envía el email
ENTONCES el email contiene:
- Asunto: "¡Felicidades! Certificado de [Curso]"
- Mensaje de felicitación personalizado
- Estadísticas: duración, lecciones completadas
- PDF adjunto del certificado
- Botones: Ver certificado, Compartir en LinkedIn
- Sugerencias de próximos cursos relacionados
Escenario 9: Curso sin certificado disponible
DADO que un curso está marcado como "no certifiable"
CUANDO el usuario completa el curso
ENTONCES NO se genera certificado
Y se muestra "Curso completado" sin opción de certificado
Y se explica "Este curso no otorga certificado"
Escenario 10: Certificado con requisitos adicionales
DADO que un curso requiere quiz final aprobado
Y el usuario completó todas las lecciones
PERO no aprobó el quiz final
CUANDO intenta obtener certificado
ENTONCES se muestra "Debes aprobar el quiz final"
Y se muestra score actual del quiz
Y se muestra "Intentos restantes: X"
Y el certificado NO se genera hasta aprobar
Criterios Adicionales
- Watermark en PDF para evitar falsificación
- Blockchain verification (opcional, fase 2)
- Traducción del certificado a inglés
- Certificado físico por correo (premium)
- Badge de LinkedIn auto-agregado via API
- Opción de hacer certificado público/privado
- Perfil público con todos los certificados del usuario
Tareas Técnicas
Database:
- DB-EDU-022: Tabla education.certificates
- DB-EDU-023: Campos: id, certificate_number, user_id, course_id, issued_at, pdf_url, status
- DB-EDU-024: Tabla certificate_verifications (log de verificaciones)
- DB-EDU-025: Índice único en certificate_number
Backend:
- BE-EDU-057: Endpoint POST /education/certificates/generate
- BE-EDU-058: Endpoint GET /education/certificates (del usuario)
- BE-EDU-059: Endpoint GET /education/certificates/:id
- BE-EDU-060: Endpoint GET /api/public/certificates/verify/:number
- BE-EDU-061: Implementar CertificateService.generate()
- BE-EDU-062: Generar PDF con Puppeteer o PDFKit
- BE-EDU-063: Generar QR code con qrcode library
- BE-EDU-064: Upload de PDF a S3 con signed URL
- BE-EDU-065: Event handler en course completion
- BE-EDU-066: Email service para enviar certificado
- BE-EDU-067: Rate limiting en verificación (100/hora por IP)
Frontend:
- FE-EDU-070: Modal CourseCompletedModal.tsx con preview
- FE-EDU-071: Crear CertificatesPage.tsx
- FE-EDU-072: Crear componente CertificateCard.tsx
- FE-EDU-073: Crear VerifyCertificatePage.tsx (pública)
- FE-EDU-074: Botón "Compartir en LinkedIn" con pre-fill
- FE-EDU-075: Preview de PDF en modal
- FE-EDU-076: Galería con filtros y búsqueda
- FE-EDU-077: Implementar certificatesStore
Tests:
- TEST-EDU-030: Test generación de certificado
- TEST-EDU-031: Test validación de certificado válido
- TEST-EDU-032: Test verificación de certificado inválido
- TEST-EDU-033: Test E2E completar curso y obtener certificado
Dependencias
Depende de:
- US-EDU-005: Completar lección - Estado: Pendiente
- RF-EDU-005: Sistema de certificados
- PDF generation library (Puppeteer/PDFKit)
- S3 bucket para almacenar PDFs
- Email service
Bloquea:
- Ninguna (es funcionalidad final)
Notas Técnicas
Generación del certificado:
// Triggered on course completion
async function onCourseCompleted(userId, courseId) {
// 1. Validar requisitos
const isEligible = await validateCertificateEligibility(userId, courseId);
if (!isEligible) return;
// 2. Generar ID único
const certificateNumber = generateCertificateId(); // OQI-EDU-A3F8D291
// 3. Generar PDF
const pdfBuffer = await generateCertificatePDF({
userName,
courseName,
completedDate,
certificateNumber
});
// 4. Upload a S3
const pdfUrl = await uploadToS3(pdfBuffer, certificateNumber);
// 5. Guardar en DB
await saveCertificate({
userId,
courseId,
certificateNumber,
pdfUrl
});
// 6. Enviar email
await sendCertificateEmail(userId, pdfUrl);
// 7. Otorgar XP bonus
await awardXP(userId, 100, 'certificate_earned');
}
Endpoint GET /api/public/certificates/verify/:number:
// Response para certificado válido
{
valid: true,
certificate: {
certificateNumber: "OQI-EDU-A3F8D291",
recipientName: "Juan Pérez",
courseTitle: "Fibonacci Retracement Básico",
courseCategory: "Análisis Técnico",
completedAt: "2025-12-05T15:45:00Z",
issuedAt: "2025-12-05T15:45:00Z",
courseDuration: 150, // minutos
moduleCount: 5,
lessonCount: 23,
instructor: "Carlos Mendoza",
status: "active"
}
}
// Response para certificado inválido
{
valid: false,
error: "Certificate not found"
}
Template del PDF:
- Usar HTML + CSS para diseño
- Puppeteer para generar PDF desde HTML
- Incluir logo en base64 para evitar carga externa
- QR code generado con library qrcode.js
- Firmas como imágenes PNG embebidas
LinkedIn pre-fill URL:
const linkedInUrl = `https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME&name=${encodeURIComponent(courseTitle)}&organizationName=Trading Platform%20IA&issueYear=${year}&issueMonth=${month}&certUrl=${encodeURIComponent(verifyUrl)}&certId=${certificateNumber}`;
Seguridad:
- Rate limiting en endpoint de verificación
- Signed URLs de S3 con expiración de 1 hora para descargas
- No exponer lista de todos los certificados (solo del usuario logueado)
- Validar que usuario solo puede descargar sus propios certificados
Entidades/Tablas:
education.certificateseducation.certificate_verifications(log)
Definition of Ready (DoR)
- Historia claramente escrita
- Criterios de aceptación definidos
- Story points estimados
- Dependencias identificadas
- Sin bloqueadores
- Diseño/mockup disponible
- API spec disponible
Definition of Done (DoD)
- Código implementado según criterios
- Tests unitarios escritos y pasando
- Tests de integración pasando
- Code review aprobado
- Documentación actualizada
- QA aprobado
- Desplegado en ambiente de pruebas
Historial de Cambios
| Fecha | Cambio | Autor |
|---|---|---|
| 2025-12-05 | Creación | Requirements-Analyst |
Creada por: Requirements-Analyst Fecha: 2025-12-05 Última actualización: 2025-12-05