18 KiB
US-FUND-003: Dashboard Principal por Rol
Épica: MAI-001 - Fundamentos Sprint: Sprint 2-3 (Semanas 2-3) Story Points: 8 SP Presupuesto: $2,900 MXN Prioridad: Alta Estado: 🚧 Planificado
Descripción
Como usuario del sistema de gestión de obra, quiero ver un dashboard personalizado según mi rol para visualizar la información y métricas relevantes a mis responsabilidades en la constructora.
Contexto del Alcance Inicial: El MVP incluye 7 dashboards diferentes (uno por rol de construcción), cada uno mostrando KPIs y widgets relevantes. Los datos son reales de la base de datos (proyectos, presupuestos, empleados). No incluye gráficas avanzadas interactivas ni personalización de widgets, que se agregarán en extensiones futuras.
Diferencias con GAMILIT:
- 7 variantes de dashboard vs 2 (estudiante/profesor)
- Sin gamificación (no hay niveles, XP, coins, badges)
- KPIs de construcción (presupuestos, avances de obra, compras, nómina)
- Dashboard varía por constructora activa (multi-tenancy)
Criterios de Aceptación Generales
Para Todos los Roles
- CA-01: El dashboard muestra un saludo personalizado con nombre del usuario y rol actual
- CA-02: Se indica la constructora activa (nombre y logo) con selector para cambiar
- CA-03: El dashboard es responsive (mobile, tablet, desktop)
- CA-04: Se muestran widgets relevantes según el rol del usuario
- CA-05: Cada widget tiene un título claro y acción rápida (ver más)
- CA-06: Los números y métricas se actualizan en tiempo real
- CA-07: Se muestran alertas y notificaciones importantes en un panel lateral
- CA-08: El layout se adapta automáticamente al cambiar de rol o constructora
- CA-09: Skeleton loaders mientras carga la información
- CA-10: Manejo de estado vacío ("No hay proyectos activos")
Especificaciones Técnicas
Backend (NestJS)
Endpoints por Rol:
GET /api/dashboard/director
GET /api/dashboard/engineer
GET /api/dashboard/resident
GET /api/dashboard/purchases
GET /api/dashboard/finance
GET /api/dashboard/hr
GET /api/dashboard/post-sales
Todos comparten estructura base:
- Headers: Authorization: Bearer {token}
- Response: {
user: { id, fullName, photoUrl, role },
constructora: { id, nombre, logoUrl },
widgets: [...], // Específico por rol
alerts: [...], // Alertas importantes
recentActivity: [...], // Actividad reciente
quickActions: [...] // Acciones rápidas
}
Servicios:
- DashboardService: Factory que delega a service específico por rol
- DirectorDashboardService: KPIs para director
- EngineerDashboardService: KPIs para ingeniero
- ResidentDashboardService: KPIs para residente
- ... (uno por cada rol)
Optimización:
- Queries SQL optimizadas con agregaciones
- Caching de datos que cambian poco (configuración, logos)
- Índices en columnas de filtrado frecuente
- Lazy loading de widgets secundarios
Frontend (React + Vite)
Arquitectura de Componentes:
components/
├── dashboards/
│ ├── DashboardContainer.tsx // Container principal
│ ├── DirectorDashboard.tsx // Dashboard específico
│ ├── EngineerDashboard.tsx
│ ├── ResidentDashboard.tsx
│ ├── PurchasesDashboard.tsx
│ ├── FinanceDashboard.tsx
│ ├── HRDashboard.tsx
│ └── PostSalesDashboard.tsx
├── widgets/
│ ├── WidgetCard.tsx // Base card reutilizable
│ ├── StatWidget.tsx // Número + icono + trend
│ ├── ChartWidget.tsx // Gráfica simple
│ ├── ListWidget.tsx // Lista de items
│ └── TableWidget.tsx // Tabla básica
└── shared/
├── DashboardHeader.tsx // Saludo + selector de constructora
├── AlertsPanel.tsx // Panel lateral de alertas
├── QuickActionsBar.tsx // Barra de acciones rápidas
└── EmptyState.tsx // Estado vacío genérico
Estado (Zustand):
interface DashboardStore {
dashboardData: DashboardData | null;
loading: boolean;
error: string | null;
fetchDashboard: (role: ConstructionRole) => Promise<void>;
refreshDashboard: () => Promise<void>;
}
Dashboards por Rol
1. Dashboard Director
KPIs Principales:
- Total de proyectos activos
- Valor total de cartera (suma de presupuestos)
- Margen de utilidad promedio
- Proyectos con retraso
- Flujo de efectivo del mes
Widgets:
[
{ type: 'stat', title: 'Proyectos Activos', value: 12, trend: +2 },
{ type: 'stat', title: 'Cartera Total', value: '$45.2M', trend: +8.5 },
{ type: 'stat', title: 'Margen Promedio', value: '18.5%', trend: -1.2 },
{ type: 'chart', title: 'Avance de Proyectos', data: [...] },
{ type: 'list', title: 'Proyectos en Riesgo', items: [...] },
{ type: 'table', title: 'Top 5 Proyectos por Margen', rows: [...] },
]
Alertas Típicas:
- "Proyecto Residencial Valle: presupuesto al 95%, avance físico 78%"
- "3 órdenes de compra pendientes de aprobación"
- "Flujo de efectivo negativo proyectado para próximo mes"
Acciones Rápidas:
- Crear nuevo proyecto
- Ver reportes ejecutivos
- Aprobar presupuestos pendientes
- Ver flujo de efectivo
2. Dashboard Engineer (Ingeniero)
KPIs Principales:
- Proyectos asignados
- Presupuestos en revisión
- Avance promedio de proyectos
- Requisiciones pendientes de validar
Widgets:
[
{ type: 'stat', title: 'Mis Proyectos', value: 5 },
{ type: 'stat', title: 'Presupuestos Activos', value: 8 },
{ type: 'chart', title: 'Avance vs Programado', data: [...] },
{ type: 'list', title: 'Requisiciones Pendientes', items: [...] },
{ type: 'table', title: 'Proyectos con Desviación', rows: [...] },
]
Alertas Típicas:
- "Proyecto Torre Norte: avance 5% por debajo de lo programado"
- "Presupuesto Plaza Comercial requiere revisión"
- "Nueva requisición de materiales en Proyecto Residencial"
Acciones Rápidas:
- Ver programación de obra
- Revisar presupuestos
- Validar requisiciones
- Actualizar avances
3. Dashboard Resident (Residente de Obra)
KPIs Principales:
- Obra(s) asignada(s)
- Avance físico esta semana
- Empleados activos en obra
- Incidencias abiertas
Widgets:
[
{ type: 'stat', title: 'Mi Obra', value: 'Torre Norte' },
{ type: 'stat', title: 'Avance Hoy', value: '+2.5%' },
{ type: 'stat', title: 'Personal en Obra', value: 45 },
{ type: 'list', title: 'Checklists Pendientes', items: [...] },
{ type: 'list', title: 'Incidencias Abiertas', items: [...] },
]
Alertas Típicas:
- "Checklist de seguridad pendiente para hoy"
- "Entrega de material programada para mañana 8 AM"
- "2 empleados sin registro de asistencia hoy"
Acciones Rápidas:
- Capturar avance de obra
- Registrar asistencia (móvil)
- Reportar incidencia
- Ver programación semanal
4. Dashboard Purchases (Compras)
KPIs Principales:
- Órdenes de compra activas
- Presupuesto de compras del mes
- Órdenes pendientes de recepción
- Inventario bajo en stock
Widgets:
[
{ type: 'stat', title: 'OC Activas', value: 28 },
{ type: 'stat', title: 'Presupuesto Mes', value: '$1.2M', trend: -15 },
{ type: 'list', title: 'OC Pendientes de Aprobar', items: [...] },
{ type: 'list', title: 'Recepciones Pendientes', items: [...] },
{ type: 'table', title: 'Materiales en Stock Bajo', rows: [...] },
]
5. Dashboard Finance (Finanzas)
KPIs Principales:
- Flujo de efectivo del mes
- Cuentas por pagar vencidas
- Presupuesto vs Real
- Pagos programados esta semana
Widgets:
[
{ type: 'stat', title: 'Flujo Mes', value: '$2.3M', trend: +12 },
{ type: 'stat', title: 'Pagos Vencidos', value: 5, alert: true },
{ type: 'chart', title: 'Presupuesto vs Real', data: [...] },
{ type: 'list', title: 'Pagos Esta Semana', items: [...] },
{ type: 'table', title: 'CxP Vencidas', rows: [...] },
]
6. Dashboard HR (Recursos Humanos)
KPIs Principales:
- Empleados activos
- Asistencias registradas hoy
- Nómina del periodo
- Incidencias laborales
Widgets:
[
{ type: 'stat', title: 'Empleados Activos', value: 156 },
{ type: 'stat', title: 'Asistencias Hoy', value: 142, percent: 91 },
{ type: 'stat', title: 'Nómina Periodo', value: '$456K' },
{ type: 'list', title: 'Faltas Sin Justificar', items: [...] },
{ type: 'list', title: 'Altas Pendientes IMSS', items: [...] },
]
7. Dashboard Post Sales (Postventa)
KPIs Principales:
- Incidencias abiertas
- Garantías activas
- Tiempo promedio de respuesta
- Clientes satisfechos (NPS)
Widgets:
[
{ type: 'stat', title: 'Incidencias Abiertas', value: 12 },
{ type: 'stat', title: 'Garantías Activas', value: 34 },
{ type: 'stat', title: 'Tiempo Respuesta', value: '2.3 días' },
{ type: 'list', title: 'Incidencias Urgentes', items: [...] },
{ type: 'table', title: 'Garantías por Vencer', rows: [...] },
]
Dependencias
Antes:
- ✅ US-FUND-001 (Autenticación JWT - requiere usuario autenticado)
- ✅ US-FUND-002 (Perfil - usa foto y nombre)
- ✅ RF-AUTH-001 (Sistema de roles - necesita roles definidos)
- ✅ RF-AUTH-003 (Multi-tenancy - dashboard por constructora)
Después:
- Punto de entrada principal del sistema después del login
- Base para navegación a módulos específicos
- Todos los módulos se acceden desde widgets del dashboard
Definición de Hecho (DoD)
- 7 endpoints de dashboard implementados (uno por rol)
- Services específicos por rol con lógica de KPIs
- Queries SQL optimizadas (máx 5 queries por dashboard)
- 7 componentes de dashboard frontend
- Widgets reutilizables (StatWidget, ChartWidget, ListWidget, TableWidget)
- Responsive design probado en 3 breakpoints
- Loading states con skeletons
- Error handling y empty states
- Tests unitarios backend (>80% coverage)
- Tests E2E para carga de dashboard por rol
- Performance: dashboard carga en <2 segundos
- Documentación Swagger de endpoints
- Code review aprobado
Notas del Alcance Inicial
Incluido en MVP ✅
- ✅ 7 dashboards específicos por rol
- ✅ KPIs y métricas en tiempo real
- ✅ Widgets básicos (stat, list, table)
- ✅ Alertas y notificaciones inline
- ✅ Acciones rápidas por rol
- ✅ Selector de constructora en header
- ✅ Responsive design
NO Incluido en MVP ❌
- ❌ Gráficas interactivas avanzadas (solo barras/líneas simples)
- ❌ Filtros de tiempo (última semana, mes, año)
- ❌ Exportación de datos
- ❌ Personalización de widgets (drag & drop)
- ❌ Comparativas entre proyectos/períodos
- ❌ Drill-down en gráficas
- ❌ Notificaciones push en tiempo real
- ❌ Dashboard multi-constructora (vista consolidada)
Extensiones Futuras ⚠️
- ⚠️ Fase 2: Gráficas avanzadas con Chart.js o Recharts
- ⚠️ Fase 2: Dashboard personalizable (agregar/quitar widgets)
- ⚠️ Fase 2: Exportar dashboards a PDF/Excel
- ⚠️ Fase 2: Comparativas y análisis históricos
- ⚠️ Fase 2: Vista consolidada multi-constructora (para directores)
Tareas de Implementación
Backend (Estimado: 18h)
Total Backend: 18h (~4.5 SP)
-
Tarea B.1: Services de dashboard por rol - Estimado: 10h
- Subtarea B.1.1: DirectorDashboardService con KPIs principales - 1.5h
- Subtarea B.1.2: EngineerDashboardService con presupuestos y programación - 1.5h
- Subtarea B.1.3: ResidentDashboardService con avances y asistencias - 1.5h
- Subtarea B.1.4: PurchasesDashboardService con OC e inventario - 1.5h
- Subtarea B.1.5: FinanceDashboardService con flujo y CxP - 1.5h
- Subtarea B.1.6: HRDashboardService con nómina y asistencias - 1h
- Subtarea B.1.7: PostSalesDashboardService con incidencias - 1h
-
Tarea B.2: Endpoints REST - Estimado: 5h
- Subtarea B.2.1: DashboardController con 7 endpoints (GET por rol) - 2h
- Subtarea B.2.2: Guard para validar que usuario tenga el rol - 1h
- Subtarea B.2.3: Serialización de respuesta consistente - 1h
- Subtarea B.2.4: Documentación Swagger completa - 1h
-
Tarea B.3: Optimización y queries - Estimado: 3h
- Subtarea B.3.1: Queries SQL optimizadas con agregaciones - 1.5h
- Subtarea B.3.2: Índices en base de datos - 0.5h
- Subtarea B.3.3: Caching de datos estáticos (logos, configuración) - 1h
Frontend (Estimado: 12h)
Total Frontend: 12h (~3 SP)
-
Tarea F.1: Widgets reutilizables - Estimado: 4h
- Subtarea F.1.1: WidgetCard base con header y body - 0.5h
- Subtarea F.1.2: StatWidget (número, icono, trend) - 1h
- Subtarea F.1.3: ListWidget (lista con iconos y badges) - 1h
- Subtarea F.1.4: TableWidget (tabla básica responsive) - 1h
- Subtarea F.1.5: ChartWidget con Recharts (barras/líneas simples) - 0.5h
-
Tarea F.2: Dashboards específicos - Estimado: 6h
- Subtarea F.2.1: DashboardContainer con lógica de routing por rol - 1h
- Subtarea F.2.2: DirectorDashboard con 6 widgets - 1h
- Subtarea F.2.3: EngineerDashboard con 5 widgets - 0.75h
- Subtarea F.2.4: ResidentDashboard con 5 widgets - 0.75h
- Subtarea F.2.5: PurchasesDashboard con 5 widgets - 0.75h
- Subtarea F.2.6: FinanceDashboard con 5 widgets - 0.75h
- Subtarea F.2.7: HR y PostSales Dashboards - 1h
-
Tarea F.3: Layout y componentes compartidos - Estimado: 2h
- Subtarea F.3.1: DashboardHeader con saludo y selector - 0.75h
- Subtarea F.3.2: AlertsPanel lateral - 0.5h
- Subtarea F.3.3: QuickActionsBar - 0.5h
- Subtarea F.3.4: EmptyState genérico - 0.25h
Testing (Estimado: 4h)
Total Testing: 4h (~1 SP)
-
Tarea T.1: Tests unitarios backend - Estimado: 2h
- Subtarea T.1.1: Tests de DirectorDashboardService (KPIs) - 0.5h
- Subtarea T.1.2: Tests de otros services (sampling) - 1h
- Subtarea T.1.3: Tests de DashboardController - 0.5h
-
Tarea T.2: Tests E2E - Estimado: 1.5h
- Subtarea T.2.1: Tests de carga de dashboard por rol - 1h
- Subtarea T.2.2: Tests de cambio de constructora (recarga dashboard) - 0.5h
-
Tarea T.3: Tests frontend - Estimado: 0.5h
- Subtarea T.3.1: Tests de widgets reutilizables - 0.25h
- Subtarea T.3.2: Tests de DashboardContainer - 0.25h
Resumen de Horas
| Categoría | Estimado | Story Points |
|---|---|---|
| Backend | 18h | 4.5 SP |
| Frontend | 12h | 3 SP |
| Testing | 4h | 1 SP |
| TOTAL | 34h | 8.5 SP ≈ 8 SP |
Ajuste: Se redondea a 8 SP considerando reutilización de componentes.
Cronograma Propuesto
Sprint: Sprint 2-3 (Semanas 2-3) Duración: 4.5 días Equipo:
- 1 Backend developer (18h)
- 1 Frontend developer (12h)
- QA compartido (4h)
Hitos:
- Días 1-2: Services backend + endpoints
- Días 3-4: Widgets y dashboards frontend
- Día 4.5: Testing + ajustes
Testing
Tests E2E
describe('Dashboard API (E2E)', () => {
describe('Director Dashboard', () => {
it('should return KPIs for director role', async () => {
const director = await createUser({ role: 'director' });
const token = await getAuthToken(director);
const response = await request(app.getHttpServer())
.get('/dashboard/director')
.set('Authorization', `Bearer ${token}`)
.expect(200);
expect(response.body.widgets).toBeArray();
expect(response.body.widgets[0]).toHaveProperty('type', 'stat');
expect(response.body.widgets[0]).toHaveProperty('title', 'Proyectos Activos');
});
it('should reject non-director users', async () => {
const engineer = await createUser({ role: 'engineer' });
const token = await getAuthToken(engineer);
await request(app.getHttpServer())
.get('/dashboard/director')
.set('Authorization', `Bearer ${token}`)
.expect(403); // Forbidden
});
});
describe('Multi-tenancy', () => {
it('should show different data when switching constructora', async () => {
const user = await createUser();
await assignToConstructora(user.id, 'constructora-a');
await assignToConstructora(user.id, 'constructora-b');
// Dashboard en constructora A
const tokenA = await getAuthToken(user, 'constructora-a');
const responseA = await request(app.getHttpServer())
.get('/dashboard/director')
.set('Authorization', `Bearer ${tokenA}`)
.expect(200);
// Dashboard en constructora B
const tokenB = await getAuthToken(user, 'constructora-b');
const responseB = await request(app.getHttpServer())
.get('/dashboard/director')
.set('Authorization', `Bearer ${tokenB}`)
.expect(200);
// Datos deben ser diferentes
expect(responseA.body.constructora.id).toBe('constructora-a');
expect(responseB.body.constructora.id).toBe('constructora-b');
expect(responseA.body.widgets[0].value).not.toBe(responseB.body.widgets[0].value);
});
});
});
Estimación
Desglose de Esfuerzo (8 SP = ~4 días = 32h):
- Backend services (7 roles): 2.5 días (18h)
- Frontend widgets + dashboards: 1.5 días (12h)
- Testing: 0.5 días (4h)
- Ajustes: -0.5 días (reutilización)
Riesgos:
- ⚠️ Complejidad de queries SQL para KPIs (múltiples joins, agregaciones)
- ⚠️ Performance en constructoras con muchos proyectos (>100)
- ⚠️ Mantenimiento de 7 dashboards diferentes (DRY)
Mitigaciones:
- ✅ Reutilizar widgets entre dashboards
- ✅ Optimizar queries con índices y caching
- ✅ Lazy loading de widgets no críticos
- ✅ Tests de performance con datos de producción simulados
Recursos Externos
Librerías Frontend:
recharts(gráficas simples - barras, líneas, áreas)react-icons(iconos para widgets)date-fns(formateo de fechas)
Referencias de Diseño:
- Tailwind UI Dashboard components
- Material-UI Dashboard examples
Creado: 2025-11-17 Actualizado: 2025-11-17 Responsable: Equipo Fullstack Reutilización GAMILIT: 50% (estructura de dashboard, adaptado a 7 roles vs 2)