erp-construccion/docs/02-definicion-modulos/MAI-001-fundamentos/historias-usuario/US-FUND-003-dashboard-por-rol.md

570 lines
18 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:**
```typescript
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):**
```typescript
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:**
```typescript
[
{ 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:**
```typescript
[
{ 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:**
```typescript
[
{ 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:**
```typescript
[
{ 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:**
```typescript
[
{ 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:**
```typescript
[
{ 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:**
```typescript
[
{ 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
```typescript
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)