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

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)