1791 lines
84 KiB
Markdown
1791 lines
84 KiB
Markdown
# RF-BI-004: Exportacion y Distribucion Automatizada
|
|
|
|
**Epica:** MAI-006 - Reportes y Business Intelligence
|
|
**Modulo:** Exportacion y Distribucion
|
|
**Responsable:** Product Owner
|
|
**Fecha:** 2025-11-17
|
|
**Version:** 1.0
|
|
|
|
---
|
|
|
|
## 1. Objetivo
|
|
|
|
Proporcionar un sistema robusto de exportacion y distribucion automatizada de reportes que permita programar entregas recurrentes, gestionar suscripciones de usuarios, exportar datos masivamente y integrarse con herramientas externas de Business Intelligence como Power BI, Tableau y Google Data Studio.
|
|
|
|
---
|
|
|
|
## 2. Casos de Uso
|
|
|
|
### CU-BI-015: Programacion de Reportes Recurrentes
|
|
|
|
**Actor:** Director General, CFO, Gerente de Proyecto
|
|
**Precondiciones:**
|
|
- Usuario con permisos de configuracion de reportes
|
|
- Reporte o dashboard configurado
|
|
|
|
**Flujo Principal:**
|
|
|
|
1. Usuario accede a modulo de programacion de reportes
|
|
2. Usuario selecciona reporte "Dashboard Ejecutivo Semanal"
|
|
3. Usuario hace clic en "Programar Entrega Automatica"
|
|
4. Sistema muestra formulario de configuracion:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Programar Reporte Automatico │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Reporte: [Dashboard Ejecutivo Semanal ▼] │
|
|
│ │
|
|
│ ┌─ Frecuencia ────────────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ○ Diaria │ │
|
|
│ │ ● Semanal │ │
|
|
│ │ Dia: [▼ Lunes ] │ │
|
|
│ │ ○ Quincenal │ │
|
|
│ │ Dias: [ ] 1 [ ] 15 del mes │ │
|
|
│ │ ○ Mensual │ │
|
|
│ │ Dia: [▼ Primer dia del mes] │ │
|
|
│ │ ○ Trimestral │ │
|
|
│ │ ○ Personalizada │ │
|
|
│ │ Expresion cron: [________________] │ │
|
|
│ └──────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ Hora de Generacion: [08:00] AM │
|
|
│ Zona Horaria: [America/Mexico_City ▼] │
|
|
│ │
|
|
│ ┌─ Formato de Exportacion ────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ Formato Principal: [▼ PDF ] │ │
|
|
│ │ │ │
|
|
│ │ ☑ Incluir tambien en Excel (.xlsx) │ │
|
|
│ │ ☐ Incluir tambien en PowerPoint (.pptx) │ │
|
|
│ │ ☐ Incluir tambien en CSV (datos raw) │ │
|
|
│ └──────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Destinatarios ──────────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ Para: [director@constructora.com ] │ │
|
|
│ │ [+ Agregar] │ │
|
|
│ │ │ │
|
|
│ │ CC: [cfo@constructora.com ] │ │
|
|
│ │ [gerencia@constructora.com ] │ │
|
|
│ │ [+ Agregar] │ │
|
|
│ │ │ │
|
|
│ │ ☑ Solo enviar si hay cambios significativos │ │
|
|
│ │ (variacion > 5% en metricas principales) │ │
|
|
│ └──────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Contenido del Email ────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ Asunto: │ │
|
|
│ │ [Dashboard Ejecutivo - Semana {week_number} ] │ │
|
|
│ │ │ │
|
|
│ │ Mensaje: │ │
|
|
│ │ ┌──────────────────────────────────────────────┐ │ │
|
|
│ │ │Estimados colegas, │ │ │
|
|
│ │ │ │ │ │
|
|
│ │ │Adjunto encuentran el Dashboard Ejecutivo │ │ │
|
|
│ │ │correspondiente a la semana {week_number}. │ │ │
|
|
│ │ │ │ │ │
|
|
│ │ │Metricas destacadas: │ │ │
|
|
│ │ │- Proyectos Activos: {project_count} │ │ │
|
|
│ │ │- Avance Promedio: {avg_progress}% │ │ │
|
|
│ │ │- SPI Consolidado: {consolidated_spi} │ │ │
|
|
│ │ │ │ │ │
|
|
│ │ │Saludos, │ │ │
|
|
│ │ │Sistema de Reportes │ │ │
|
|
│ │ └──────────────────────────────────────────────┘ │ │
|
|
│ │ │ │
|
|
│ │ Variables disponibles: {date}, {week_number}, │ │
|
|
│ │ {project_count}, {avg_progress}, ... │ │
|
|
│ └──────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Opciones Avanzadas ─────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ☑ Aplicar filtros guardados: [Proyectos Activos] │ │
|
|
│ │ ☑ Incluir comparativo vs periodo anterior │ │
|
|
│ │ ☐ Incluir tendencia (ultimos 6 periodos) │ │
|
|
│ │ ☑ Generar solo si todos los datos estan actuales│ │
|
|
│ │ ☐ Comprimir archivos grandes (>10MB) en ZIP │ │
|
|
│ │ │ │
|
|
│ │ Fecha de inicio: [24/11/2025] │ │
|
|
│ │ Fecha de fin: ○ Sin fin ● Hasta [31/12/2026] │ │
|
|
│ └──────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ☑ Notificarme si falla la generacion del reporte │ │
|
|
│ │
|
|
│ [Cancelar] [Probar Ahora] [Programar] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
5. Usuario configura todos los parametros
|
|
6. Usuario hace clic en "Probar Ahora" para validar configuracion
|
|
7. Sistema genera reporte de prueba y lo envia al usuario
|
|
8. Usuario verifica reporte recibido
|
|
9. Usuario hace clic en "Programar"
|
|
10. Sistema crea job recurrente en scheduler
|
|
11. Sistema muestra confirmacion con proxima ejecucion:
|
|
```
|
|
✓ Reporte programado exitosamente
|
|
|
|
Proxima ejecucion: Lunes 24/11/2025 08:00 AM
|
|
Destinatarios: 3 personas
|
|
Formato: PDF + Excel
|
|
|
|
[Ver Calendario de Entregas] [Editar] [Desactivar]
|
|
```
|
|
|
|
**Flujo Alternativo - Modificar Programacion:**
|
|
|
|
1. Usuario accede a lista de reportes programados
|
|
2. Usuario ve tabla con programaciones activas:
|
|
```
|
|
┌────────────────────────────────────────────────────────────────┐
|
|
│ Reportes Programados [+ Nuevo Reporte]│
|
|
├────────────────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Nombre │Frecuencia│Destinos│Estado │Acciones │
|
|
│────────────────────────┼──────────┼────────┼───────┼──────────│
|
|
│ Dashboard Ejecutivo │Semanal │ 3 │🟢 Activo│[Editar]│
|
|
│ Semanal │(Lunes) │ │ │[Pausar] │
|
|
│ │ │ │ │[Eliminar]│
|
|
│ Ultima ejecucion: 17/11/2025 08:00 - ✓ Exitoso │
|
|
│ Proxima ejecucion: 24/11/2025 08:00 │
|
|
│────────────────────────┼──────────┼────────┼───────┼──────────│
|
|
│ Reporte de Costos │Mensual │ 5 │🟢 Activo│[Editar]│
|
|
│ Consolidado │(Dia 1) │ │ │[Pausar] │
|
|
│ │ │ │ │[Eliminar]│
|
|
│ Ultima ejecucion: 01/11/2025 09:00 - ✓ Exitoso │
|
|
│ Proxima ejecucion: 01/12/2025 09:00 │
|
|
│────────────────────────┼──────────┼────────┼───────┼──────────│
|
|
│ Flujo de Efectivo │Quincenal │ 2 │🟡 Pausado│[Editar]│
|
|
│ Proyectado │(1 y 15) │ │ │[Activar]│
|
|
│ │ │ │ │[Eliminar]│
|
|
│ Ultima ejecucion: 15/10/2025 10:00 - ✓ Exitoso │
|
|
│────────────────────────┼──────────┼────────┼───────┼──────────│
|
|
│ Analisis de Riesgos IA │Semanal │ 4 │🔴 Error│[Editar]│
|
|
│ │(Viernes) │ │ │[Reintentar]│
|
|
│ │ │ │ │[Eliminar]│
|
|
│ Ultima ejecucion: 15/11/2025 14:00 - ✗ Fallo │
|
|
│ Error: Timeout al generar predicciones │
|
|
└────────────────────────────────────────────────────────────────┘
|
|
```
|
|
3. Usuario puede editar, pausar o eliminar programaciones
|
|
|
|
**Postcondiciones:**
|
|
- Job programado creado en sistema de scheduler
|
|
- Proximas ejecuciones calculadas correctamente
|
|
- Usuario recibe reportes en horarios configurados
|
|
|
|
---
|
|
|
|
### CU-BI-016: Suscripciones a Reportes
|
|
|
|
**Actor:** Gerente de Proyecto, Analista, Stakeholder
|
|
**Precondiciones:**
|
|
- Reportes disponibles para suscripcion
|
|
- Usuario autenticado
|
|
|
|
**Flujo Principal:**
|
|
|
|
1. Usuario accede a catalogo de reportes disponibles
|
|
2. Sistema muestra galeria de reportes con opcion de suscripcion:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Catalogo de Reportes [Mis Suscripciones]│
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Filtar por: [▼ Todos] [▼ Categoria] [🔍 Buscar...] │
|
|
│ │
|
|
│ ┌─────────────────────┐ ┌─────────────────────┐ │
|
|
│ │ 📊 Dashboard │ │ 💰 Reporte de │ │
|
|
│ │ Ejecutivo │ │ Costos │ │
|
|
│ │ │ │ │ │
|
|
│ │ Vista consolidada │ │ Analisis detallado │ │
|
|
│ │ de todos los │ │ de costos por │ │
|
|
│ │ proyectos │ │ proyecto y partida │ │
|
|
│ │ │ │ │ │
|
|
│ │ 🔔 152 suscriptores │ │ 🔔 98 suscriptores │ │
|
|
│ │ │ │ │ │
|
|
│ │ [Suscribirse] │ │ ✓ Suscrito │ │
|
|
│ │ [Vista Previa] │ │ [Configurar] │ │
|
|
│ └─────────────────────┘ └─────────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────┐ ┌─────────────────────┐ │
|
|
│ │ 📈 Analisis de │ │ ⏱ Avance de │ │
|
|
│ │ Tendencias │ │ Obra │ │
|
|
│ │ │ │ │ │
|
|
│ │ Tendencias │ │ Seguimiento de │ │
|
|
│ │ historicas y │ │ avance fisico y │ │
|
|
│ │ proyecciones │ │ financiero │ │
|
|
│ │ │ │ │ │
|
|
│ │ 🔔 67 suscriptores │ │ 🔔 203 suscriptores │ │
|
|
│ │ │ │ │ │
|
|
│ │ [Suscribirse] │ │ [Suscribirse] │ │
|
|
│ │ [Vista Previa] │ │ [Vista Previa] │ │
|
|
│ └─────────────────────┘ └─────────────────────┘ │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
3. Usuario hace clic en "Suscribirse" en "Analisis de Tendencias"
|
|
4. Sistema muestra opciones de suscripcion:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Suscripcion: Analisis de Tendencias │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌─ Frecuencia de Entrega ──────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ○ Diaria (cada manana a las 7:00 AM) │ │
|
|
│ │ ● Semanal (Lunes a las 8:00 AM) │ │
|
|
│ │ ○ Mensual (Primer dia del mes a las 9:00 AM) │ │
|
|
│ │ ○ Cuando haya cambios significativos │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Formato Preferido ──────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ● PDF (documento) │ │
|
|
│ │ ○ Excel (datos y graficas) │ │
|
|
│ │ ○ Email HTML (sin adjuntos) │ │
|
|
│ │ ○ Link para visualizar online │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Filtros Personalizados ─────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ Proyectos: │ │
|
|
│ │ ☑ Todos mis proyectos (8) │ │
|
|
│ │ ☐ Solo proyectos que administro (3) │ │
|
|
│ │ ☐ Proyectos especificos: [▼ Seleccionar...] │ │
|
|
│ │ │ │
|
|
│ │ Periodo de analisis: │ │
|
|
│ │ [▼ Ultimos 6 meses] │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Metodo de Entrega ──────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ● Email: juan.perez@constructora.com │ │
|
|
│ │ ☐ Tambien notificar por: │ │
|
|
│ │ ☐ Slack (#reportes-semanales) │ │
|
|
│ │ ☐ Microsoft Teams (Canal Reportes) │ │
|
|
│ │ ☐ SMS (solo alertas criticas) │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ Proxima entrega: Lunes 24/11/2025 08:00 AM │
|
|
│ │
|
|
│ ☑ Notificarme si hay alertas criticas en el reporte │
|
|
│ │
|
|
│ [Cancelar] [Suscribirse] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
5. Usuario configura preferencias de suscripcion
|
|
6. Usuario hace clic en "Suscribirse"
|
|
7. Sistema confirma suscripcion y muestra en "Mis Suscripciones"
|
|
8. Usuario recibe primer reporte en proxima entrega programada
|
|
|
|
**Flujo Alternativo - Gestionar Suscripciones:**
|
|
|
|
1. Usuario accede a "Mis Suscripciones"
|
|
2. Sistema muestra lista de suscripciones activas:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Mis Suscripciones │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌─ Dashboard Ejecutivo ────────────────────────────┐ │
|
|
│ │ Frecuencia: Semanal (Lunes 8:00 AM) │ │
|
|
│ │ Formato: PDF │ │
|
|
│ │ Ultimo recibido: 17/11/2025 ✓ │ │
|
|
│ │ Proximo: 24/11/2025 │ │
|
|
│ │ │ │
|
|
│ │ [Modificar] [Pausar] [Cancelar Suscripcion] │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Reporte de Costos ──────────────────────────────┐ │
|
|
│ │ Frecuencia: Mensual (Dia 1, 9:00 AM) │ │
|
|
│ │ Formato: Excel │ │
|
|
│ │ Ultimo recibido: 01/11/2025 ✓ │ │
|
|
│ │ Proximo: 01/12/2025 │ │
|
|
│ │ Filtros: Solo Proyecto "Fracc. Del Valle" │ │
|
|
│ │ │ │
|
|
│ │ [Modificar] [Pausar] [Cancelar Suscripcion] │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Analisis de Tendencias ─────────────────────────┐ │
|
|
│ │ Frecuencia: Semanal (Lunes 8:00 AM) │ │
|
|
│ │ Formato: PDF │ │
|
|
│ │ Estado: 🟡 PAUSADO │ │
|
|
│ │ Ultimo recibido: 03/11/2025 ✓ │ │
|
|
│ │ │ │
|
|
│ │ [Modificar] [Reactivar] [Cancelar Suscripcion] │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ [Explorar Mas Reportes] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
3. Usuario puede modificar, pausar o cancelar suscripciones
|
|
|
|
**Postcondiciones:**
|
|
- Suscripcion registrada en sistema
|
|
- Usuario recibe reportes segun configuracion
|
|
- Historial de entregas registrado
|
|
|
|
---
|
|
|
|
### CU-BI-017: Exportacion Masiva de Datos
|
|
|
|
**Actor:** Analista de Datos, Director de TI, Auditor
|
|
**Precondiciones:**
|
|
- Usuario con permisos de exportacion masiva
|
|
- Datos disponibles en sistema
|
|
|
|
**Flujo Principal:**
|
|
|
|
1. Usuario accede a modulo de exportacion masiva
|
|
2. Sistema muestra wizard de exportacion:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Exportacion Masiva de Datos [1/4] │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Paso 1: Seleccionar Datos │
|
|
│ │
|
|
│ ┌─ Entidades a Exportar ───────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ☑ Proyectos (12 registros)│ │
|
|
│ │ ☑ Presupuestos (348 partidas) │ │
|
|
│ │ ☑ Estimaciones (96 estimaciones)│ │
|
|
│ │ ☑ Ordenes de Compra (1,245 OCs) │ │
|
|
│ │ ☑ Contratos (67 contratos)│ │
|
|
│ │ ☐ Nomina (2,340 registros)│ │
|
|
│ │ ☐ Asistencias (18,920 registros)│ │
|
|
│ │ ☐ Inventario (456 items) │ │
|
|
│ │ ☑ Avances de Obra (1,024 mediciones)│ │
|
|
│ │ ☐ Documentos (metadata only) (3,567 docs) │ │
|
|
│ │ │ │
|
|
│ │ [Seleccionar Todos] [Deseleccionar Todos] │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ Total estimado: ~8.5 MB de datos │
|
|
│ │
|
|
│ [Cancelar] [Siguiente →] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
3. Usuario selecciona entidades a exportar
|
|
4. Usuario hace clic en "Siguiente"
|
|
5. Sistema muestra paso 2 - Filtros:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Exportacion Masiva de Datos [2/4] │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Paso 2: Aplicar Filtros │
|
|
│ │
|
|
│ ┌─ Rango de Fechas ────────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ Desde: [01/01/2025] Hasta: [17/11/2025] │ │
|
|
│ │ │ │
|
|
│ │ ○ Todo el historico │ │
|
|
│ │ ● Rango personalizado │ │
|
|
│ │ ○ Ultimo ano │ │
|
|
│ │ ○ Ultimos 6 meses │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Filtros por Proyecto ───────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ● Todos los proyectos (12) │ │
|
|
│ │ ○ Proyectos seleccionados: │ │
|
|
│ │ [▼ Seleccionar proyectos...] │ │
|
|
│ │ ○ Proyectos por criterio: │ │
|
|
│ │ Estado: [▼ Todos] │ │
|
|
│ │ Tipo: [▼ Todos] │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Opciones Avanzadas ─────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ☑ Incluir registros eliminados (soft-deleted) │ │
|
|
│ │ ☑ Incluir datos de auditoria (quien/cuando) │ │
|
|
│ │ ☐ Solo registros modificados en rango de fechas │ │
|
|
│ │ ☑ Incluir relaciones (foreign keys) │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ Registros filtrados: ~7,245 │
|
|
│ │
|
|
│ [← Anterior] [Siguiente →] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
6. Usuario configura filtros
|
|
7. Usuario hace clic en "Siguiente"
|
|
8. Sistema muestra paso 3 - Formato:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Exportacion Masiva de Datos [3/4] │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Paso 3: Configurar Formato │
|
|
│ │
|
|
│ ┌─ Formato de Archivo ─────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ● Excel (.xlsx) │ │
|
|
│ │ ☑ Hoja separada por entidad │ │
|
|
│ │ ☑ Incluir formato (colores, bordes) │ │
|
|
│ │ ☐ Proteger con contrasena: [__________] │ │
|
|
│ │ │ │
|
|
│ │ ○ CSV (valores separados por coma) │ │
|
|
│ │ Separador: [▼ Coma (,)] │ │
|
|
│ │ Encoding: [▼ UTF-8] │ │
|
|
│ │ ☐ ZIP multiple files │ │
|
|
│ │ │ │
|
|
│ │ ○ JSON (formato estructurado) │ │
|
|
│ │ ☐ Pretty print (indentado) │ │
|
|
│ │ ☑ Incluir metadata │ │
|
|
│ │ │ │
|
|
│ │ ○ SQL (script de INSERT) │ │
|
|
│ │ Database: [▼ PostgreSQL] │ │
|
|
│ │ ☑ Incluir CREATE TABLE │ │
|
|
│ │ │ │
|
|
│ │ ○ Parquet (columnar, para Big Data) │ │
|
|
│ │ Compresion: [▼ Snappy] │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Opciones de Exportacion ────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ☑ Incluir cabeceras de columna │ │
|
|
│ │ ☑ Usar nombres descriptivos (vs IDs tecnicos) │ │
|
|
│ │ ☐ Anonimizar datos personales (GDPR) │ │
|
|
│ │ ☑ Comprimir archivo final (.zip) │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ Tamano estimado: ~6.2 MB comprimido │
|
|
│ │
|
|
│ [← Anterior] [Siguiente →] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
9. Usuario selecciona formato Excel
|
|
10. Usuario hace clic en "Siguiente"
|
|
11. Sistema muestra paso 4 - Confirmacion:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Exportacion Masiva de Datos [4/4] │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Paso 4: Confirmar y Exportar │
|
|
│ │
|
|
│ ┌─ Resumen ────────────────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ Entidades: 6 seleccionadas │ │
|
|
│ │ • Proyectos (12) │ │
|
|
│ │ • Presupuestos (348) │ │
|
|
│ │ • Estimaciones (96) │ │
|
|
│ │ • Ordenes de Compra (1,245) │ │
|
|
│ │ • Contratos (67) │ │
|
|
│ │ • Avances de Obra (1,024) │ │
|
|
│ │ │ │
|
|
│ │ Periodo: 01/01/2025 - 17/11/2025 │ │
|
|
│ │ Formato: Excel (.xlsx) comprimido │ │
|
|
│ │ Tamano estimado: ~6.2 MB │ │
|
|
│ │ Tiempo estimado: 45-60 segundos │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Metodo de Entrega ──────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ● Descarga directa │ │
|
|
│ │ (archivo estara listo en 1 minuto) │ │
|
|
│ │ │ │
|
|
│ │ ○ Enviar por email │ │
|
|
│ │ Email: [analista@constructora.com] │ │
|
|
│ │ │ │
|
|
│ │ ○ Guardar en servidor │ │
|
|
│ │ Ruta: [/exports/data_export_{date}.xlsx] │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ Nombre de archivo: │
|
|
│ [exportacion_masiva_2025-11-17.xlsx ] │
|
|
│ │
|
|
│ ☑ Registrar en log de auditoria │
|
|
│ ☑ Notificarme cuando la exportacion este lista │
|
|
│ │
|
|
│ [← Anterior] [Iniciar Exportacion] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
12. Usuario hace clic en "Iniciar Exportacion"
|
|
13. Sistema muestra progreso:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Exportando Datos... │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ████████████████░░░░░░░░░░░░░░░░░░ 65% │
|
|
│ │
|
|
│ Procesando: Ordenes de Compra (850/1245) │
|
|
│ │
|
|
│ Tiempo transcurrido: 38s │
|
|
│ Tiempo restante: ~22s │
|
|
│ │
|
|
│ [Cancelar Exportacion] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
14. Sistema completa exportacion y muestra descarga:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ ✓ Exportacion Completada │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Archivo: exportacion_masiva_2025-11-17.xlsx.zip │
|
|
│ Tamano: 5.8 MB │
|
|
│ Registros exportados: 2,792 │
|
|
│ Tiempo total: 58 segundos │
|
|
│ │
|
|
│ [📥 Descargar Archivo] │
|
|
│ │
|
|
│ El archivo estara disponible para descarga │
|
|
│ durante las proximas 24 horas. │
|
|
│ │
|
|
│ Contenido del archivo: │
|
|
│ • Hoja "Proyectos" - 12 registros │
|
|
│ • Hoja "Presupuestos" - 348 registros │
|
|
│ • Hoja "Estimaciones" - 96 registros │
|
|
│ • Hoja "Ordenes_Compra" - 1,245 registros │
|
|
│ • Hoja "Contratos" - 67 registros │
|
|
│ • Hoja "Avances_Obra" - 1,024 registros │
|
|
│ • Hoja "Metadata" - informacion de exportacion │
|
|
│ │
|
|
│ [Descargar] [Nueva Exportacion] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Postcondiciones:**
|
|
- Datos exportados en formato solicitado
|
|
- Archivo disponible para descarga
|
|
- Registro en log de auditoria
|
|
|
|
---
|
|
|
|
### CU-BI-018: Integracion con BI Externo (Power BI, Tableau)
|
|
|
|
**Actor:** Analista de BI, Director de TI
|
|
**Precondiciones:**
|
|
- Usuario con permisos de configuracion de integraciones
|
|
- Credenciales de herramienta externa
|
|
|
|
**Flujo Principal:**
|
|
|
|
1. Usuario accede a modulo de integraciones
|
|
2. Sistema muestra conectores disponibles:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Integraciones con BI Externo │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Conectores Disponibles: │
|
|
│ │
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
│ │ │ │ │ │ │ │
|
|
│ │ Power BI │ │ Tableau │ │ Google Data │ │
|
|
│ │ │ │ │ │ Studio │ │
|
|
│ │ │ │ │ │ │ │
|
|
│ │ [Configurar] │ │ [Configurar] │ │ [Configurar] │ │
|
|
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
│ │
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
│ │ │ │ │ │ │ │
|
|
│ │ Looker │ │ Qlik │ │ Metabase │ │
|
|
│ │ │ │ │ │ │ │
|
|
│ │ │ │ │ │ │ │
|
|
│ │ [Configurar] │ │ [Configurar] │ │ [Configurar] │ │
|
|
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
│ │
|
|
│ ┌─ Integraciones Activas ──────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ Power BI - Workspace "Construccion" │ │
|
|
│ │ Estado: 🟢 Conectado │ │
|
|
│ │ Ultima sincronizacion: 17/11/2025 14:30 │ │
|
|
│ │ Datasets: 3 │ │
|
|
│ │ [Ver Detalles] [Sincronizar Ahora] [Editar] │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ [+ Nueva Integracion] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
3. Usuario hace clic en "Configurar" en Tableau
|
|
4. Sistema muestra wizard de configuracion:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Configurar Integracion: Tableau │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ┌─ Metodo de Conexion ─────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ● API REST de Tableau Server │ │
|
|
│ │ ○ Tableau Cloud (Online) │ │
|
|
│ │ ○ Archivo Hyper (actualizacion manual) │ │
|
|
│ │ ○ Base de datos directa (Live Connection) │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Credenciales de Tableau Server ─────────────────┐ │
|
|
│ │ │ │
|
|
│ │ Server URL: │ │
|
|
│ │ [https://tableau.constructora.com ] │ │
|
|
│ │ │ │
|
|
│ │ Autenticacion: │ │
|
|
│ │ ● Token de Acceso Personal (PAT) │ │
|
|
│ │ ○ Usuario/Contrasena │ │
|
|
│ │ │ │
|
|
│ │ Token Name: [____________________________] │ │
|
|
│ │ Token Secret: [____________________________] │ │
|
|
│ │ │ │
|
|
│ │ Site: [Default] │ │
|
|
│ │ │ │
|
|
│ │ [Probar Conexion] │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Seleccionar Datasets ───────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ☑ Proyectos y KPIs │ │
|
|
│ │ Tablas: projects, kpis, milestones │ │
|
|
│ │ Frecuencia: Cada 15 minutos │ │
|
|
│ │ │ │
|
|
│ │ ☑ Costos y Presupuestos │ │
|
|
│ │ Tablas: budgets, costs, estimates │ │
|
|
│ │ Frecuencia: Cada hora │ │
|
|
│ │ │ │
|
|
│ │ ☐ Nomina y Recursos Humanos │ │
|
|
│ │ Tablas: payroll, attendance, employees │ │
|
|
│ │ Frecuencia: Diaria │ │
|
|
│ │ │ │
|
|
│ │ ☑ Avances de Obra │ │
|
|
│ │ Tablas: progress, work_breakdown │ │
|
|
│ │ Frecuencia: Cada 30 minutos │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Opciones de Sincronizacion ─────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ ● Incremental (solo cambios) │ │
|
|
│ │ ○ Full Refresh (todo el dataset) │ │
|
|
│ │ │ │
|
|
│ │ ☑ Habilitar sincronizacion automatica │ │
|
|
│ │ ☑ Notificar si sincronizacion falla │ │
|
|
│ │ ☐ Sincronizar solo en horario laboral │ │
|
|
│ │ (8:00 AM - 6:00 PM) │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ [Cancelar] [Guardar y Conectar] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
5. Usuario ingresa credenciales de Tableau
|
|
6. Usuario hace clic en "Probar Conexion"
|
|
7. Sistema valida credenciales exitosamente
|
|
8. Usuario selecciona datasets a sincronizar
|
|
9. Usuario hace clic en "Guardar y Conectar"
|
|
10. Sistema realiza sincronizacion inicial:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Sincronizacion Inicial con Tableau │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ ████████████████████████████░░░░ 87% │
|
|
│ │
|
|
│ Sincronizando: Avances de Obra (890/1024 registros) │
|
|
│ │
|
|
│ Completado: │
|
|
│ ✓ Proyectos y KPIs (12 registros) │
|
|
│ ✓ Costos y Presupuestos (1,593 registros) │
|
|
│ ⏳ Avances de Obra (en progreso...) │
|
|
│ │
|
|
│ Tiempo transcurrido: 2m 15s │
|
|
│ │
|
|
│ [Cancelar Sincronizacion] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
11. Sistema completa sincronizacion:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ ✓ Integracion Configurada Exitosamente │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Tableau Server conectado correctamente │
|
|
│ │
|
|
│ Datasets sincronizados: 3 │
|
|
│ Registros totales: 2,629 │
|
|
│ Tiempo de sincronizacion: 2m 48s │
|
|
│ │
|
|
│ Proxima sincronizacion: │
|
|
│ • Proyectos y KPIs: 17/11/2025 14:45 (15 min) │
|
|
│ • Costos y Presupuestos: 17/11/2025 15:30 (1 hora) │
|
|
│ • Avances de Obra: 17/11/2025 15:00 (30 min) │
|
|
│ │
|
|
│ Enlaces utiles: │
|
|
│ • [Abrir Tableau Server] │
|
|
│ • [Ver Documentacion de API] │
|
|
│ • [Configurar Dashboards en Tableau] │
|
|
│ │
|
|
│ [Cerrar] [Ir a Integraciones] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Flujo Alternativo - Monitoreo de Sincronizacion:**
|
|
|
|
1. Usuario accede a detalles de integracion con Power BI
|
|
2. Sistema muestra dashboard de monitoreo:
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Integracion: Power BI - Workspace "Construccion" │
|
|
├──────────────────────────────────────────────────────┤
|
|
│ │
|
|
│ Estado: 🟢 Activo │
|
|
│ Ultima sincronizacion: 17/11/2025 14:30 ✓ │
|
|
│ │
|
|
│ ┌─ Datasets Sincronizados ─────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ Dataset │Registros│Frecuencia│Estado │ │
|
|
│ │──────────────────────┼─────────┼──────────┼───────│ │
|
|
│ │ Proyectos y KPIs │ 12 │ 15 min │ ✓ │ │
|
|
│ │ Costos Presupuestos │ 1,593 │ 1 hora │ ✓ │ │
|
|
│ │ Avances de Obra │ 1,024 │ 30 min │ ✓ │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Historial de Sincronizaciones (ultimas 24h) ───┐ │
|
|
│ │ │ │
|
|
│ │ Fecha/Hora │Dataset │Resultado │ │
|
|
│ │──────────────────┼─────────────────┼──────────────│ │
|
|
│ │ 17/11 14:30 │Proyectos y KPIs │✓ Exitoso (8s)│ │
|
|
│ │ 17/11 14:15 │Proyectos y KPIs │✓ Exitoso (7s)│ │
|
|
│ │ 17/11 14:00 │Avances de Obra │✓ Exitoso (32s)│ │
|
|
│ │ 17/11 13:45 │Proyectos y KPIs │✓ Exitoso (9s)│ │
|
|
│ │ 17/11 13:30 │Costos Presup. │✓ Exitoso (45s)│ │
|
|
│ │ 17/11 13:30 │Avances de Obra │✗ Fallo │ │
|
|
│ │ │ │ (Timeout) │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─ Estadisticas ───────────────────────────────────┐ │
|
|
│ │ │ │
|
|
│ │ Sincronizaciones (24h): 96 │ │
|
|
│ │ Exitosas: 94 (97.9%) │ │
|
|
│ │ Fallidas: 2 (2.1%) │ │
|
|
│ │ Tiempo promedio: 18 segundos │ │
|
|
│ │ Datos transferidos (24h): 127 MB │ │
|
|
│ └───────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ [Sincronizar Ahora] [Editar Config] [Desconectar] │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Postcondiciones:**
|
|
- Integracion configurada y activa
|
|
- Datos sincronizandose automaticamente
|
|
- Dashboards de Tableau/Power BI alimentados con datos actualizados
|
|
|
|
---
|
|
|
|
## 3. Requerimientos Funcionales
|
|
|
|
### RF-BI-004.1: Programacion de Reportes Recurrentes
|
|
- El sistema DEBE permitir programar reportes con frecuencia: diaria, semanal, quincenal, mensual, trimestral, personalizada (cron)
|
|
- El sistema DEBE soportar multiples formatos simultaneos (PDF + Excel + CSV)
|
|
- El sistema DEBE permitir configurar destinatarios (To, CC, BCC)
|
|
- El sistema DEBE soportar plantillas de email con variables dinamicas
|
|
- El sistema DEBE permitir aplicar filtros guardados a reportes programados
|
|
- El sistema DEBE permitir definir condiciones de envio (ej: solo si hay cambios >5%)
|
|
- El sistema DEBE permitir configurar fecha de inicio y fin de programacion
|
|
- El sistema DEBE notificar si falla la generacion de reporte
|
|
- El sistema DEBE registrar historial de entregas (fecha, destinatarios, resultado)
|
|
|
|
### RF-BI-004.2: Gestion de Programaciones
|
|
- El sistema DEBE mostrar lista de reportes programados con estado
|
|
- El sistema DEBE permitir pausar/reactivar programaciones
|
|
- El sistema DEBE permitir editar configuracion de reportes activos
|
|
- El sistema DEBE permitir ejecutar reporte programado bajo demanda
|
|
- El sistema DEBE mostrar proxima fecha de ejecucion
|
|
- El sistema DEBE permitir duplicar programaciones existentes
|
|
- El sistema DEBE permitir eliminar programaciones con confirmacion
|
|
|
|
### RF-BI-004.3: Suscripciones de Usuarios
|
|
- El sistema DEBE proveer catalogo de reportes disponibles para suscripcion
|
|
- El sistema DEBE permitir a usuarios suscribirse a reportes
|
|
- El sistema DEBE permitir configurar frecuencia personalizada por suscripcion
|
|
- El sistema DEBE permitir configurar filtros personalizados por usuario
|
|
- El sistema DEBE permitir seleccionar formato preferido (PDF, Excel, HTML, link)
|
|
- El sistema DEBE permitir configurar metodo de entrega (email, Slack, Teams, SMS)
|
|
- El sistema DEBE permitir pausar temporalmente suscripciones
|
|
- El sistema DEBE permitir cancelar suscripciones en cualquier momento
|
|
- El sistema DEBE mostrar numero de suscriptores por reporte
|
|
|
|
### RF-BI-004.4: Exportacion Masiva de Datos
|
|
- El sistema DEBE ofrecer wizard paso a paso para exportacion masiva
|
|
- El sistema DEBE permitir seleccionar multiples entidades simultaneamente
|
|
- El sistema DEBE permitir aplicar filtros de fecha, proyecto, estado
|
|
- El sistema DEBE soportar formatos: Excel, CSV, JSON, SQL, Parquet
|
|
- El sistema DEBE estimar tamano de archivo antes de exportar
|
|
- El sistema DEBE mostrar progreso en tiempo real durante exportacion
|
|
- El sistema DEBE permitir comprimir archivos grandes (>10MB) automaticamente
|
|
- El sistema DEBE mantener archivos exportados disponibles 24-72 horas
|
|
- El sistema DEBE registrar exportaciones masivas en log de auditoria
|
|
- El sistema DEBE limitar tamano maximo de exportacion (ej: 100MB o 100K registros)
|
|
|
|
### RF-BI-004.5: Opciones de Formato de Exportacion
|
|
- El sistema DEBE generar Excel con hojas separadas por entidad
|
|
- El sistema DEBE incluir metadata en exportaciones (fecha, usuario, filtros)
|
|
- El sistema DEBE permitir proteger archivos Excel con contrasena
|
|
- El sistema DEBE permitir anonimizar datos personales (cumplimiento GDPR)
|
|
- El sistema DEBE usar nombres descriptivos de columnas (no solo IDs tecnicos)
|
|
- El sistema DEBE incluir cabeceras en CSV/Excel
|
|
- El sistema DEBE permitir configurar encoding (UTF-8, Latin1, etc.)
|
|
- El sistema DEBE generar SQL compatible con motor especificado (PostgreSQL, MySQL, etc.)
|
|
|
|
### RF-BI-004.6: Integracion con BI Externo
|
|
- El sistema DEBE proveer conectores para: Power BI, Tableau, Google Data Studio, Looker, Qlik, Metabase
|
|
- El sistema DEBE soportar autenticacion via API tokens, OAuth2, usuario/contrasena
|
|
- El sistema DEBE permitir configurar datasets a sincronizar
|
|
- El sistema DEBE permitir configurar frecuencia de sincronizacion por dataset
|
|
- El sistema DEBE soportar sincronizacion incremental (solo cambios)
|
|
- El sistema DEBE soportar sincronizacion completa (full refresh)
|
|
- El sistema DEBE validar credenciales antes de guardar configuracion
|
|
- El sistema DEBE realizar sincronizacion inicial al configurar integracion
|
|
|
|
### RF-BI-004.7: Monitoreo de Integraciones
|
|
- El sistema DEBE mostrar estado de integraciones (activo, error, pausado)
|
|
- El sistema DEBE mostrar ultima fecha de sincronizacion
|
|
- El sistema DEBE mostrar historial de sincronizaciones (ultimas 24-72h)
|
|
- El sistema DEBE calcular estadisticas: tasa de exito, tiempo promedio, datos transferidos
|
|
- El sistema DEBE notificar si sincronizacion falla
|
|
- El sistema DEBE reintentar automaticamente sincronizaciones fallidas (max 3 intentos)
|
|
- El sistema DEBE permitir sincronizacion manual bajo demanda
|
|
- El sistema DEBE permitir pausar/desconectar integraciones
|
|
|
|
### RF-BI-004.8: API REST para Datos
|
|
- El sistema DEBE exponer API REST para consulta de datos
|
|
- El sistema DEBE soportar autenticacion via API key o JWT
|
|
- El sistema DEBE implementar rate limiting (ej: 1000 req/hora)
|
|
- El sistema DEBE soportar paginacion en respuestas grandes
|
|
- El sistema DEBE soportar filtrado, ordenamiento y proyeccion de campos
|
|
- El sistema DEBE retornar datos en formato JSON por defecto
|
|
- El sistema DEBE proveer documentacion OpenAPI/Swagger
|
|
|
|
---
|
|
|
|
## 4. Modelo de Datos
|
|
|
|
```typescript
|
|
// Scheduled Report Job
|
|
interface ScheduledReport {
|
|
id: string;
|
|
reportId: string; // Dashboard or Report template
|
|
name: string;
|
|
description: string;
|
|
|
|
schedule: {
|
|
frequency: 'daily' | 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'custom';
|
|
dayOfWeek?: number; // 0-6 for weekly
|
|
daysOfMonth?: number[]; // [1, 15] for biweekly
|
|
time: string; // "HH:mm"
|
|
timezone: string; // "America/Mexico_City"
|
|
cronExpression?: string; // for custom
|
|
};
|
|
|
|
validity: {
|
|
startDate: Date;
|
|
endDate?: Date; // null = indefinite
|
|
};
|
|
|
|
formats: {
|
|
primary: 'pdf' | 'xlsx' | 'pptx' | 'csv';
|
|
additional: ('pdf' | 'xlsx' | 'pptx' | 'csv')[];
|
|
};
|
|
|
|
recipients: {
|
|
to: string[]; // email addresses
|
|
cc?: string[];
|
|
bcc?: string[];
|
|
};
|
|
|
|
emailTemplate: {
|
|
subject: string; // supports variables like {date}, {week_number}
|
|
body: string;
|
|
variables: Record<string, string>; // available variables
|
|
};
|
|
|
|
conditions: {
|
|
onlyIfChanges?: boolean;
|
|
changeThreshold?: number; // percentage
|
|
onlyIfComplete?: boolean; // all data is up-to-date
|
|
};
|
|
|
|
filters?: Record<string, any>; // saved filter configuration
|
|
|
|
options: {
|
|
includeComparison?: boolean; // vs previous period
|
|
includeTrend?: boolean; // last 6 periods
|
|
compressIfLarge?: boolean; // ZIP if >10MB
|
|
};
|
|
|
|
status: 'active' | 'paused' | 'ended';
|
|
createdBy: string;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
|
|
// Execution tracking
|
|
nextExecutionDate: Date;
|
|
lastExecutionDate?: Date;
|
|
lastExecutionStatus?: 'success' | 'failed';
|
|
lastExecutionError?: string;
|
|
}
|
|
|
|
// Execution History
|
|
interface ReportExecution {
|
|
id: string;
|
|
scheduledReportId: string;
|
|
executionDate: Date;
|
|
status: 'pending' | 'processing' | 'success' | 'failed';
|
|
|
|
generatedFiles: {
|
|
format: string;
|
|
filePath: string;
|
|
fileSize: number;
|
|
}[];
|
|
|
|
recipients: string[];
|
|
emailSent: boolean;
|
|
emailSentAt?: Date;
|
|
|
|
error?: string;
|
|
processingTime: number; // milliseconds
|
|
|
|
metadata: {
|
|
recordCount: number;
|
|
dataAsOf: Date; // latest data timestamp
|
|
filtersApplied: Record<string, any>;
|
|
};
|
|
|
|
createdAt: Date;
|
|
}
|
|
|
|
// User Subscription
|
|
interface ReportSubscription {
|
|
id: string;
|
|
userId: string;
|
|
reportId: string; // Dashboard or Report template
|
|
|
|
frequency: 'daily' | 'weekly' | 'monthly' | 'on_change';
|
|
deliveryTime?: string; // "HH:mm"
|
|
dayOfWeek?: number;
|
|
dayOfMonth?: number;
|
|
|
|
format: 'pdf' | 'xlsx' | 'html' | 'link';
|
|
|
|
deliveryMethod: {
|
|
email: boolean;
|
|
slack?: {
|
|
enabled: boolean;
|
|
channel: string;
|
|
};
|
|
teams?: {
|
|
enabled: boolean;
|
|
channel: string;
|
|
};
|
|
sms?: {
|
|
enabled: boolean;
|
|
phoneNumber: string;
|
|
onlyCriticalAlerts: boolean;
|
|
};
|
|
};
|
|
|
|
filters: Record<string, any>; // personalized filters
|
|
|
|
options: {
|
|
onlyIfChanges?: boolean;
|
|
notifyOnCriticalAlerts?: boolean;
|
|
};
|
|
|
|
status: 'active' | 'paused';
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
|
|
lastDeliveryDate?: Date;
|
|
deliveryCount: number;
|
|
}
|
|
|
|
// Bulk Export Job
|
|
interface BulkExportJob {
|
|
id: string;
|
|
name: string;
|
|
description?: string;
|
|
|
|
entities: {
|
|
name: string; // 'projects', 'budgets', etc.
|
|
tableName: string;
|
|
recordCount: number;
|
|
}[];
|
|
|
|
filters: {
|
|
dateRange?: { from: Date; to: Date };
|
|
projectIds?: string[];
|
|
includeDeleted?: boolean;
|
|
includeAudit?: boolean;
|
|
onlyModifiedInRange?: boolean;
|
|
};
|
|
|
|
format: 'xlsx' | 'csv' | 'json' | 'sql' | 'parquet';
|
|
|
|
formatOptions: {
|
|
// Excel options
|
|
separateSheets?: boolean;
|
|
includeFormatting?: boolean;
|
|
password?: string;
|
|
|
|
// CSV options
|
|
delimiter?: ',' | ';' | '\t' | '|';
|
|
encoding?: 'utf-8' | 'latin1' | 'utf-16';
|
|
zipMultipleFiles?: boolean;
|
|
|
|
// JSON options
|
|
prettyPrint?: boolean;
|
|
includeMetadata?: boolean;
|
|
|
|
// SQL options
|
|
targetDatabase?: 'postgresql' | 'mysql' | 'mssql';
|
|
includeCreateTable?: boolean;
|
|
|
|
// Parquet options
|
|
compression?: 'snappy' | 'gzip' | 'lzo';
|
|
};
|
|
|
|
exportOptions: {
|
|
includeHeaders?: boolean;
|
|
useDescriptiveNames?: boolean;
|
|
anonymizePersonalData?: boolean;
|
|
compressFile?: boolean;
|
|
};
|
|
|
|
deliveryMethod: 'download' | 'email' | 'server';
|
|
deliveryPath?: string;
|
|
deliveryEmail?: string;
|
|
|
|
status: 'pending' | 'processing' | 'completed' | 'failed';
|
|
progress: number; // 0-100
|
|
|
|
result?: {
|
|
filePath: string;
|
|
fileSize: number;
|
|
recordCount: number;
|
|
processingTime: number; // milliseconds
|
|
expiresAt: Date; // download availability
|
|
};
|
|
|
|
error?: string;
|
|
|
|
createdBy: string;
|
|
createdAt: Date;
|
|
completedAt?: Date;
|
|
}
|
|
|
|
// External BI Integration
|
|
interface BIIntegration {
|
|
id: string;
|
|
name: string;
|
|
provider: 'powerbi' | 'tableau' | 'google_data_studio' | 'looker' | 'qlik' | 'metabase';
|
|
|
|
connectionType: 'api' | 'database' | 'file';
|
|
|
|
credentials: {
|
|
// API connection
|
|
serverUrl?: string;
|
|
apiToken?: string;
|
|
apiSecret?: string;
|
|
oauth2?: {
|
|
clientId: string;
|
|
clientSecret: string;
|
|
refreshToken: string;
|
|
};
|
|
|
|
// Database connection
|
|
connectionString?: string;
|
|
|
|
// File-based
|
|
filePath?: string;
|
|
};
|
|
|
|
datasets: {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
tables: string[]; // source tables
|
|
syncFrequency: number; // minutes
|
|
syncType: 'incremental' | 'full';
|
|
lastSyncDate?: Date;
|
|
lastSyncStatus?: 'success' | 'failed';
|
|
recordCount?: number;
|
|
}[];
|
|
|
|
syncOptions: {
|
|
autoSync: boolean;
|
|
syncOnlyBusinessHours?: boolean;
|
|
businessHours?: { start: string; end: string }; // "08:00", "18:00"
|
|
notifyOnFailure: boolean;
|
|
maxRetries: number;
|
|
};
|
|
|
|
status: 'active' | 'paused' | 'error';
|
|
lastSyncDate?: Date;
|
|
|
|
createdBy: string;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
}
|
|
|
|
// Sync History
|
|
interface SyncHistory {
|
|
id: string;
|
|
integrationId: string;
|
|
datasetId: string;
|
|
|
|
syncDate: Date;
|
|
status: 'success' | 'failed';
|
|
|
|
recordsAdded: number;
|
|
recordsUpdated: number;
|
|
recordsDeleted: number;
|
|
totalRecords: number;
|
|
|
|
dataTransferred: number; // bytes
|
|
processingTime: number; // milliseconds
|
|
|
|
error?: string;
|
|
|
|
createdAt: Date;
|
|
}
|
|
|
|
// API Access Token
|
|
interface APIToken {
|
|
id: string;
|
|
name: string;
|
|
description?: string;
|
|
|
|
token: string; // hashed
|
|
userId: string;
|
|
|
|
permissions: {
|
|
resources: string[]; // ['projects', 'budgets', etc.]
|
|
actions: ('read' | 'write' | 'delete')[];
|
|
};
|
|
|
|
rateLimit: {
|
|
requestsPerHour: number;
|
|
requestsPerDay: number;
|
|
};
|
|
|
|
usage: {
|
|
lastUsedDate?: Date;
|
|
totalRequests: number;
|
|
requestsToday: number;
|
|
};
|
|
|
|
status: 'active' | 'revoked';
|
|
|
|
expiresAt?: Date;
|
|
createdAt: Date;
|
|
revokedAt?: Date;
|
|
}
|
|
```
|
|
|
|
### SQL Schema
|
|
|
|
```sql
|
|
-- Scheduled Reports
|
|
CREATE TABLE scheduled_reports (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
report_id UUID NOT NULL REFERENCES dashboards(id),
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
|
|
schedule JSONB NOT NULL,
|
|
validity JSONB NOT NULL,
|
|
formats JSONB NOT NULL,
|
|
recipients JSONB NOT NULL,
|
|
email_template JSONB NOT NULL,
|
|
conditions JSONB,
|
|
filters JSONB,
|
|
options JSONB,
|
|
|
|
status VARCHAR(20) DEFAULT 'active',
|
|
created_by UUID NOT NULL REFERENCES users(id),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
next_execution_date TIMESTAMP,
|
|
last_execution_date TIMESTAMP,
|
|
last_execution_status VARCHAR(20),
|
|
last_execution_error TEXT,
|
|
|
|
INDEX idx_scheduled_report_status (status),
|
|
INDEX idx_scheduled_report_next_exec (next_execution_date)
|
|
);
|
|
|
|
-- Report Executions
|
|
CREATE TABLE report_executions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
scheduled_report_id UUID NOT NULL REFERENCES scheduled_reports(id) ON DELETE CASCADE,
|
|
execution_date TIMESTAMP NOT NULL,
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
|
|
|
generated_files JSONB,
|
|
recipients JSONB,
|
|
email_sent BOOLEAN DEFAULT false,
|
|
email_sent_at TIMESTAMP,
|
|
|
|
error TEXT,
|
|
processing_time INTEGER, -- milliseconds
|
|
metadata JSONB,
|
|
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
INDEX idx_report_exec_scheduled (scheduled_report_id),
|
|
INDEX idx_report_exec_date (execution_date),
|
|
INDEX idx_report_exec_status (status)
|
|
);
|
|
|
|
-- Report Subscriptions
|
|
CREATE TABLE report_subscriptions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES users(id),
|
|
report_id UUID NOT NULL REFERENCES dashboards(id),
|
|
|
|
frequency VARCHAR(20) NOT NULL,
|
|
delivery_time VARCHAR(5),
|
|
day_of_week INTEGER,
|
|
day_of_month INTEGER,
|
|
|
|
format VARCHAR(10) NOT NULL,
|
|
delivery_method JSONB NOT NULL,
|
|
filters JSONB,
|
|
options JSONB,
|
|
|
|
status VARCHAR(20) DEFAULT 'active',
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
last_delivery_date TIMESTAMP,
|
|
delivery_count INTEGER DEFAULT 0,
|
|
|
|
UNIQUE(user_id, report_id),
|
|
INDEX idx_subscription_user (user_id),
|
|
INDEX idx_subscription_report (report_id),
|
|
INDEX idx_subscription_status (status)
|
|
);
|
|
|
|
-- Bulk Export Jobs
|
|
CREATE TABLE bulk_export_jobs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
|
|
entities JSONB NOT NULL,
|
|
filters JSONB,
|
|
format VARCHAR(10) NOT NULL,
|
|
format_options JSONB,
|
|
export_options JSONB,
|
|
|
|
delivery_method VARCHAR(20) NOT NULL,
|
|
delivery_path VARCHAR(500),
|
|
delivery_email VARCHAR(255),
|
|
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
|
progress INTEGER DEFAULT 0,
|
|
|
|
result JSONB,
|
|
error TEXT,
|
|
|
|
created_by UUID NOT NULL REFERENCES users(id),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
completed_at TIMESTAMP,
|
|
|
|
INDEX idx_bulk_export_status (status),
|
|
INDEX idx_bulk_export_creator (created_by),
|
|
INDEX idx_bulk_export_created (created_at)
|
|
);
|
|
|
|
-- BI Integrations
|
|
CREATE TABLE bi_integrations (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name VARCHAR(255) NOT NULL,
|
|
provider VARCHAR(50) NOT NULL,
|
|
|
|
connection_type VARCHAR(20) NOT NULL,
|
|
credentials JSONB NOT NULL,
|
|
datasets JSONB NOT NULL,
|
|
sync_options JSONB NOT NULL,
|
|
|
|
status VARCHAR(20) DEFAULT 'active',
|
|
last_sync_date TIMESTAMP,
|
|
|
|
created_by UUID NOT NULL REFERENCES users(id),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
INDEX idx_bi_integration_provider (provider),
|
|
INDEX idx_bi_integration_status (status)
|
|
);
|
|
|
|
-- Sync History
|
|
CREATE TABLE sync_history (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
integration_id UUID NOT NULL REFERENCES bi_integrations(id) ON DELETE CASCADE,
|
|
dataset_id VARCHAR(255) NOT NULL,
|
|
|
|
sync_date TIMESTAMP NOT NULL,
|
|
status VARCHAR(20) NOT NULL,
|
|
|
|
records_added INTEGER DEFAULT 0,
|
|
records_updated INTEGER DEFAULT 0,
|
|
records_deleted INTEGER DEFAULT 0,
|
|
total_records INTEGER DEFAULT 0,
|
|
|
|
data_transferred BIGINT, -- bytes
|
|
processing_time INTEGER, -- milliseconds
|
|
|
|
error TEXT,
|
|
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
INDEX idx_sync_history_integration (integration_id),
|
|
INDEX idx_sync_history_date (sync_date),
|
|
INDEX idx_sync_history_status (status)
|
|
);
|
|
|
|
-- API Tokens
|
|
CREATE TABLE api_tokens (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
|
|
token_hash VARCHAR(255) NOT NULL UNIQUE,
|
|
user_id UUID NOT NULL REFERENCES users(id),
|
|
|
|
permissions JSONB NOT NULL,
|
|
rate_limit JSONB NOT NULL,
|
|
usage JSONB DEFAULT '{"totalRequests": 0, "requestsToday": 0}',
|
|
|
|
status VARCHAR(20) DEFAULT 'active',
|
|
|
|
expires_at TIMESTAMP,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
revoked_at TIMESTAMP,
|
|
|
|
INDEX idx_api_token_hash (token_hash),
|
|
INDEX idx_api_token_user (user_id),
|
|
INDEX idx_api_token_status (status)
|
|
);
|
|
|
|
-- API Request Log (para rate limiting y analytics)
|
|
CREATE TABLE api_request_log (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
token_id UUID NOT NULL REFERENCES api_tokens(id),
|
|
endpoint VARCHAR(255) NOT NULL,
|
|
method VARCHAR(10) NOT NULL,
|
|
|
|
response_status INTEGER,
|
|
response_time INTEGER, -- milliseconds
|
|
|
|
ip_address INET,
|
|
user_agent TEXT,
|
|
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
INDEX idx_api_log_token (token_id),
|
|
INDEX idx_api_log_created (created_at)
|
|
);
|
|
|
|
-- Particion por fecha para performance
|
|
CREATE TABLE api_request_log_y2025m11 PARTITION OF api_request_log
|
|
FOR VALUES FROM ('2025-11-01') TO ('2025-12-01');
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Criterios de Aceptacion
|
|
|
|
### Programacion de Reportes
|
|
- [ ] Reportes se generan y envian en horario configurado (±2 min)
|
|
- [ ] Expresiones cron personalizadas funcionan correctamente
|
|
- [ ] Variables en template de email se reemplazan correctamente
|
|
- [ ] Condiciones de envio (solo si cambios >5%) se evaluan correctamente
|
|
- [ ] Multiples formatos se generan y adjuntan en mismo email
|
|
- [ ] Notificaciones de falla se envian al creador del reporte
|
|
- [ ] Reportes con fecha de fin se desactivan automaticamente
|
|
- [ ] Job programado se puede ejecutar manualmente bajo demanda
|
|
|
|
### Suscripciones
|
|
- [ ] Catalogo muestra todos los reportes disponibles
|
|
- [ ] Suscripcion se crea correctamente con preferencias de usuario
|
|
- [ ] Filtros personalizados se aplican solo a ese usuario
|
|
- [ ] Integracion con Slack/Teams envia notificaciones correctamente
|
|
- [ ] Opcion "solo si hay cambios" evita envios innecesarios
|
|
- [ ] Pausar suscripcion detiene entregas temporalmente
|
|
- [ ] Cancelar suscripcion elimina configuracion y detiene entregas
|
|
- [ ] Numero de suscriptores se actualiza en tiempo real
|
|
|
|
### Exportacion Masiva
|
|
- [ ] Wizard de 4 pasos funciona sin errores
|
|
- [ ] Estimacion de tamano es precisa (±15%)
|
|
- [ ] Barra de progreso refleja avance real
|
|
- [ ] Exportacion se completa en <5 minutos para dataset tipico (50K registros)
|
|
- [ ] Archivos Excel tienen hojas separadas por entidad
|
|
- [ ] Metadata incluye fecha, usuario, filtros aplicados
|
|
- [ ] Compresion ZIP reduce tamano >50% en archivos grandes
|
|
- [ ] Archivos exportados se eliminan automaticamente despues de 24h
|
|
- [ ] Log de auditoria registra exportaciones masivas
|
|
|
|
### Integracion BI Externo
|
|
- [ ] Conectores para Power BI, Tableau, Google Data Studio funcionan
|
|
- [ ] Validacion de credenciales detecta errores antes de guardar
|
|
- [ ] Sincronizacion incremental solo transfiere cambios
|
|
- [ ] Sincronizacion se ejecuta segun frecuencia configurada (±2 min)
|
|
- [ ] Historial muestra ultimas 48h de sincronizaciones
|
|
- [ ] Estadisticas calculan tasa de exito, tiempo promedio correctamente
|
|
- [ ] Notificaciones se envian si sincronizacion falla
|
|
- [ ] Reintento automatico funciona (max 3 intentos con exponential backoff)
|
|
- [ ] Sincronizacion manual bajo demanda funciona inmediatamente
|
|
|
|
### API REST
|
|
- [ ] Autenticacion via API key funciona correctamente
|
|
- [ ] Rate limiting bloquea requests sobre limite (ej: 1000/hora)
|
|
- [ ] Paginacion funciona correctamente (parametros page, limit)
|
|
- [ ] Filtrado, ordenamiento, proyeccion de campos funcionan
|
|
- [ ] Respuestas JSON tienen formato consistente
|
|
- [ ] Documentacion Swagger esta actualizada y funcional
|
|
- [ ] Errores retornan codigos HTTP apropiados (400, 401, 403, 404, 429, 500)
|
|
|
|
---
|
|
|
|
## 6. Notas Tecnicas
|
|
|
|
### Implementacion de Scheduler para Reportes
|
|
|
|
```typescript
|
|
import cron from 'node-cron';
|
|
import { Queue, Worker } from 'bullmq';
|
|
|
|
class ReportScheduler {
|
|
private queue: Queue;
|
|
|
|
constructor() {
|
|
this.queue = new Queue('scheduled-reports', {
|
|
connection: { host: 'redis', port: 6379 }
|
|
});
|
|
|
|
this.initializeScheduler();
|
|
this.initializeWorker();
|
|
}
|
|
|
|
private async initializeScheduler() {
|
|
// Run every minute to check for due reports
|
|
cron.schedule('* * * * *', async () => {
|
|
await this.checkDueReports();
|
|
});
|
|
}
|
|
|
|
private async checkDueReports() {
|
|
const now = new Date();
|
|
|
|
const dueReports = await db.scheduledReports.findMany({
|
|
where: {
|
|
status: 'active',
|
|
next_execution_date: {
|
|
lte: now
|
|
}
|
|
}
|
|
});
|
|
|
|
for (const report of dueReports) {
|
|
// Add to job queue
|
|
await this.queue.add('generate-report', {
|
|
scheduledReportId: report.id,
|
|
reportId: report.report_id,
|
|
formats: report.formats,
|
|
recipients: report.recipients,
|
|
filters: report.filters
|
|
});
|
|
|
|
// Calculate next execution
|
|
const nextExecution = this.calculateNextExecution(report.schedule);
|
|
await db.scheduledReports.update({
|
|
where: { id: report.id },
|
|
data: { next_execution_date: nextExecution }
|
|
});
|
|
}
|
|
}
|
|
|
|
private calculateNextExecution(schedule: any): Date {
|
|
const now = new Date();
|
|
|
|
switch (schedule.frequency) {
|
|
case 'daily':
|
|
const tomorrow = new Date(now);
|
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
tomorrow.setHours(parseInt(schedule.time.split(':')[0]));
|
|
tomorrow.setMinutes(parseInt(schedule.time.split(':')[1]));
|
|
return tomorrow;
|
|
|
|
case 'weekly':
|
|
const nextWeek = new Date(now);
|
|
const daysUntilNext = (schedule.dayOfWeek - now.getDay() + 7) % 7 || 7;
|
|
nextWeek.setDate(nextWeek.getDate() + daysUntilNext);
|
|
nextWeek.setHours(parseInt(schedule.time.split(':')[0]));
|
|
nextWeek.setMinutes(parseInt(schedule.time.split(':')[1]));
|
|
return nextWeek;
|
|
|
|
case 'monthly':
|
|
const nextMonth = new Date(now);
|
|
nextMonth.setMonth(nextMonth.getMonth() + 1);
|
|
nextMonth.setDate(schedule.dayOfMonth);
|
|
nextMonth.setHours(parseInt(schedule.time.split(':')[0]));
|
|
nextMonth.setMinutes(parseInt(schedule.time.split(':')[1]));
|
|
return nextMonth;
|
|
|
|
case 'custom':
|
|
// Parse cron expression
|
|
const cronParser = require('cron-parser');
|
|
const interval = cronParser.parseExpression(schedule.cronExpression);
|
|
return interval.next().toDate();
|
|
|
|
default:
|
|
throw new Error(`Unknown frequency: ${schedule.frequency}`);
|
|
}
|
|
}
|
|
|
|
private initializeWorker() {
|
|
const worker = new Worker('scheduled-reports', async (job) => {
|
|
const { scheduledReportId, reportId, formats, recipients, filters } = job.data;
|
|
|
|
try {
|
|
// Create execution record
|
|
const execution = await db.reportExecutions.create({
|
|
data: {
|
|
scheduled_report_id: scheduledReportId,
|
|
execution_date: new Date(),
|
|
status: 'processing',
|
|
recipients
|
|
}
|
|
});
|
|
|
|
// Generate report
|
|
const startTime = Date.now();
|
|
const files = await this.generateReportFiles(reportId, formats, filters);
|
|
const processingTime = Date.now() - startTime;
|
|
|
|
// Send email
|
|
await this.sendReportEmail(recipients, files);
|
|
|
|
// Update execution record
|
|
await db.reportExecutions.update({
|
|
where: { id: execution.id },
|
|
data: {
|
|
status: 'success',
|
|
generated_files: files,
|
|
email_sent: true,
|
|
email_sent_at: new Date(),
|
|
processing_time: processingTime
|
|
}
|
|
});
|
|
|
|
// Update scheduled report
|
|
await db.scheduledReports.update({
|
|
where: { id: scheduledReportId },
|
|
data: {
|
|
last_execution_date: new Date(),
|
|
last_execution_status: 'success'
|
|
}
|
|
});
|
|
|
|
} catch (error) {
|
|
// Update execution record with error
|
|
await db.reportExecutions.update({
|
|
where: { id: execution.id },
|
|
data: {
|
|
status: 'failed',
|
|
error: error.message
|
|
}
|
|
});
|
|
|
|
// Update scheduled report
|
|
await db.scheduledReports.update({
|
|
where: { id: scheduledReportId },
|
|
data: {
|
|
last_execution_date: new Date(),
|
|
last_execution_status: 'failed',
|
|
last_execution_error: error.message
|
|
}
|
|
});
|
|
|
|
// Send failure notification
|
|
const report = await db.scheduledReports.findUnique({
|
|
where: { id: scheduledReportId }
|
|
});
|
|
await this.sendFailureNotification(report.created_by, error);
|
|
}
|
|
}, {
|
|
connection: { host: 'redis', port: 6379 },
|
|
concurrency: 5
|
|
});
|
|
}
|
|
|
|
private async generateReportFiles(reportId: string, formats: any, filters: any) {
|
|
const files = [];
|
|
|
|
for (const format of [formats.primary, ...formats.additional]) {
|
|
const exporter = this.getExporter(format);
|
|
const filePath = await exporter.export(reportId, filters);
|
|
|
|
files.push({
|
|
format,
|
|
filePath,
|
|
fileSize: await this.getFileSize(filePath)
|
|
});
|
|
}
|
|
|
|
return files;
|
|
}
|
|
|
|
private async sendReportEmail(recipients: any, files: any[]) {
|
|
const attachments = files.map(f => ({
|
|
filename: path.basename(f.filePath),
|
|
path: f.filePath
|
|
}));
|
|
|
|
await emailService.send({
|
|
to: recipients.to,
|
|
cc: recipients.cc,
|
|
bcc: recipients.bcc,
|
|
subject: 'Dashboard Ejecutivo Semanal',
|
|
html: '<p>Adjunto encuentra el reporte solicitado.</p>',
|
|
attachments
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
### Implementacion de Sincronizacion con BI Externo
|
|
|
|
```typescript
|
|
import axios from 'axios';
|
|
|
|
class TableauSyncService {
|
|
private baseUrl: string;
|
|
private token: string;
|
|
|
|
constructor(integration: BIIntegration) {
|
|
this.baseUrl = integration.credentials.serverUrl;
|
|
this.token = integration.credentials.apiToken;
|
|
}
|
|
|
|
async authenticate() {
|
|
const response = await axios.post(`${this.baseUrl}/api/3.0/auth/signin`, {
|
|
credentials: {
|
|
personalAccessTokenName: this.token,
|
|
personalAccessTokenSecret: this.tokenSecret,
|
|
site: { contentUrl: this.site }
|
|
}
|
|
});
|
|
|
|
this.authToken = response.data.credentials.token;
|
|
}
|
|
|
|
async syncDataset(dataset: any) {
|
|
const syncStart = Date.now();
|
|
|
|
try {
|
|
// Extract data from source
|
|
const data = await this.extractData(dataset.tables);
|
|
|
|
// Transform to Tableau format
|
|
const hyperFile = await this.createHyperFile(data);
|
|
|
|
// Upload to Tableau Server
|
|
await this.uploadHyperFile(dataset.id, hyperFile);
|
|
|
|
// Refresh extract
|
|
await this.refreshExtract(dataset.id);
|
|
|
|
const syncTime = Date.now() - syncStart;
|
|
|
|
// Record sync history
|
|
await db.syncHistory.create({
|
|
data: {
|
|
integration_id: this.integrationId,
|
|
dataset_id: dataset.id,
|
|
sync_date: new Date(),
|
|
status: 'success',
|
|
total_records: data.length,
|
|
processing_time: syncTime
|
|
}
|
|
});
|
|
|
|
return { success: true, recordCount: data.length };
|
|
|
|
} catch (error) {
|
|
// Record failure
|
|
await db.syncHistory.create({
|
|
data: {
|
|
integration_id: this.integrationId,
|
|
dataset_id: dataset.id,
|
|
sync_date: new Date(),
|
|
status: 'failed',
|
|
error: error.message
|
|
}
|
|
});
|
|
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
private async extractData(tables: string[]) {
|
|
const data = {};
|
|
|
|
for (const table of tables) {
|
|
data[table] = await db[table].findMany();
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
private async createHyperFile(data: any) {
|
|
const { TableauHyperApi } = require('tableau-hyper-api');
|
|
const hyperFile = '/tmp/data.hyper';
|
|
|
|
// Create Hyper file and insert data
|
|
// ... (implementation details)
|
|
|
|
return hyperFile;
|
|
}
|
|
|
|
private async uploadHyperFile(datasetId: string, filePath: string) {
|
|
const formData = new FormData();
|
|
formData.append('file', fs.createReadStream(filePath));
|
|
|
|
await axios.post(
|
|
`${this.baseUrl}/api/3.0/sites/${this.siteId}/datasources/${datasetId}/data`,
|
|
formData,
|
|
{
|
|
headers: {
|
|
'X-Tableau-Auth': this.authToken,
|
|
...formData.getHeaders()
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
private async refreshExtract(datasetId: string) {
|
|
await axios.post(
|
|
`${this.baseUrl}/api/3.0/sites/${this.siteId}/datasources/${datasetId}/refresh`,
|
|
{},
|
|
{
|
|
headers: { 'X-Tableau-Auth': this.authToken }
|
|
}
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
**Fecha:** 2025-11-17
|
|
**Preparado por:** Equipo de Producto
|
|
**Version:** 1.0
|
|
**Estado:** Listo para Revision
|