Manual Técnico

Arquitectura, Base de Datos, Servicios y Despliegue

Lectura: 25-30 minutos
Versión 2.0 — Abril 2026

1. Stack Tecnológico

Frontend

Tecnología Versión
React 19.2.3
Vite 7.2.4
TypeScript 5.9.3
Tailwind CSS 4.1.17
Recharts 3.7.0
Lucide React 0.563.0
SheetJS (xlsx) 0.18.5

Backend / Infraestructura

Tecnología Detalle
Supabase @supabase/supabase-js 2.95
PostgreSQL 14+ (Supabase managed)
Auth Supabase Auth + RLS
Edge Functions Deno (alertas email)
Deploy Vercel (rama main)
Build vite-plugin-singlefile

2. Arquitectura del Sistema

Diagrama de capas:

┌─────────────────────────────────────────────────────────┐
│                    FRONTEND (SPA)                       │
│  React 19 + TypeScript + Tailwind + Recharts            │
│  ┌──────────┐ ┌───────────┐ ┌──────────┐ ┌───────────┐ │
│  │Components│ │   Hooks   │ │  Types   │ │   Utils   │ │
│  └─────┬────┘ └─────┬─────┘ └──────────┘ └───────────┘ │
│        │            │                                    │
│  ┌─────▼────────────▼─────────────────────────────────┐ │
│  │          Service Layer (services.ts)                │ │
│  │  vpService │ valorService │ periodoService │ ...    │ │
│  └────────────────────┬───────────────────────────────┘ │
│                       │                                  │
│  ┌────────────────────▼───────────────────────────────┐ │
│  │       Supabase Client (supabase.ts + auth.ts)      │ │
│  └────────────────────┬───────────────────────────────┘ │
└───────────────────────┼─────────────────────────────────┘
                        │ HTTPS / WebSocket
┌───────────────────────▼─────────────────────────────────┐
│                  SUPABASE CLOUD                          │
│  ┌──────────┐ ┌───────────┐ ┌────────────────────────┐  │
│  │   Auth   │ │  PostgREST│ │   Edge Functions       │  │
│  │  (JWT)   │ │  (API)    │ │  (send-alert-email)    │  │
│  └────┬─────┘ └─────┬─────┘ └────────────────────────┘  │
│       │             │                                    │
│  ┌────▼─────────────▼────────────────────────────────┐  │
│  │              PostgreSQL 14+                        │  │
│  │  21 tablas │ 3 vistas │ 4 funciones │ RLS activo  │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘

Patrón arquitectónico: SPA client-side con backend serverless (BaaS). Toda la lógica de negocio vive en la capa de servicios del frontend y en triggers/funciones de PostgreSQL. No hay servidor de aplicaciones intermedio.

3. Estructura del Proyecto

src/
├── App.tsx                 # Componente raíz, navegación state-driven
├── main.tsx                # Punto de entrada React
├── index.css               # Estilos globales + Tailwind
├── components/             # 27 pantallas/vistas
│   ├── LoginScreen.tsx     # Login + conexión Supabase/Demo
│   ├── DashboardGlobal.tsx # Vista presidencia
│   ├── VPView.tsx          # Vista vicepresidencia
│   ├── GerenciaView.tsx    # Vista gerencia + carga datos
│   ├── CorporateScorecard  # BSC con 4 perspectivas
│   ├── AnalisisHistorico   # Gráficas de evolución
│   ├── AnalisisPredictivo  # Proyecciones ML
│   ├── AlertasEmail.tsx    # Configuración alertas email
│   ├── AlertasGestion.tsx  # Notificaciones en pantalla
│   ├── AdminUsuarios.tsx   # CRUD usuarios
│   ├── ReporteEjecutivo    # Reportes consolidados
│   ├── GestionRiesgos      # Matriz de riesgos
│   ├── ImportadorDatos     # Importación CSV global
│   ├── CargaMasiva.tsx     # Carga CSV por gerencia
│   └── ...                 # 12 componentes más
├── lib/
│   ├── supabase.ts         # Cliente Supabase + tipos DB
│   ├── auth.ts             # Servicio autenticación
│   └── services.ts         # 18 servicios de negocio
├── types/
│   └── index.ts            # Tipos TypeScript frontend
├── data/
│   ├── organizacion.ts     # Estructura VP/Gerencias hardcoded (demo)
│   └── corporateScorecard  # Datos BSC demo
├── hooks/
│   └── useSupabase.ts      # Hook conexión Supabase
├── config/
│   └── navigation.ts       # Configuración menú lateral
└── utils/
    └── cn.ts               # Utilidad clases Tailwind condicionales

database/
├── schema.sql              # DDL completo (21 tablas, 3 vistas, triggers)
├── functions/
│   └── is_admin.sql        # Función SECURITY DEFINER
├── policies/
│   ├── base_multitenant_policies.sql  # RLS todas las tablas
│   └── usuarios_prod.sql  # RLS tabla usuarios
├── seeds/                  # Datos iniciales
├── migrations/             # Migraciones históricas
└── maintenance/            # Scripts de limpieza

4. Base de Datos (PostgreSQL)

4.1 Tablas Principales

Tabla Columnas Clave Relaciones
vicepresidencias id, codigo UNIQUE, nombre, icono, color, orden, activo → gerencias (1:N)
gerencias id, vicepresidencia_id FK CASCADE, codigo UNIQUE, nombre → vicepresidencias (N:1)
roles id, nombre UNIQUE, permisos JSONB → usuarios (1:N)
usuarios email UNIQUE, rol_id FK, vicepresidencia_id FK, gerencia_id FK, auth_user_id → roles, vicepresidencias, gerencias
perspectivas_bsc codigo UNIQUE (FIN/CLI/PRO/APR), nombre, color, orden → indicadores_definicion (1:N)
indicadores_definicion codigo UNIQUE, perspectiva_id, gerencia_id, meta_* DECIMAL(15,4), umbral_rojo/amarillo, tendencia, nivel → perspectivas, gerencias, VP
periodos año+mes UNIQUE, estado CHECK(abierto/cerrado/bloqueado/pendiente) → indicadores_valores (1:N)
indicadores_valores indicador_id+periodo_id UNIQUE, valor_meta/real, porcentaje_cumplimiento, estado, estado_validacion → indicadores_definicion, periodos
planes_accion indicador_id+periodo_id UNIQUE, gerencia_id, prioridad, estado, progreso 0-100 → indicadores, periodos, gerencias
riesgos codigo UNIQUE, probabilidad/impacto 1-5, nivel GENERATED, indicadores_asociados UUID[] → vicepresidencias
alertas severidad, titulo, leida, reconocida → VP, gerencia, indicador_valor
correlaciones indicador_causa_id+efecto_id UNIQUE, tipo_relacion, fuerza, validada → indicadores_definicion (2x)

4.2 Vistas Materializadas

v_indicadores_actual — KPIs con valores del período abierto + joins a todas las tablas de lookup.
v_resumen_vp — Conteo de indicadores por estado (verde/amarillo/rojo) y promedio de cumplimiento por VP.
v_alertas_pendientes — Alertas no leídas ordenadas por severidad.

4.3 Índices (16)

-- Principales índices para rendimiento
idx_gerencias_vp_id             ON gerencias(vicepresidencia_id)
idx_usuarios_email              ON usuarios(email)
idx_usuarios_rol                ON usuarios(rol_id)
idx_ind_def_perspectiva         ON indicadores_definicion(perspectiva_id)
idx_ind_def_gerencia            ON indicadores_definicion(gerencia_id)
idx_ind_val_indicador           ON indicadores_valores(indicador_id)
idx_ind_val_periodo             ON indicadores_valores(periodo_id)
idx_ind_val_estado              ON indicadores_valores(estado)
idx_alertas_severidad           ON alertas(severidad)
idx_alertas_leida               ON alertas(leida)
idx_planes_gerencia_periodo     ON planes_accion(gerencia_id, periodo_id)

5. Seguridad — Row-Level Security

5.1 Funciones Helper (SECURITY DEFINER)

-- Determina si el usuario actual es admin
is_admin(p_uid uuid) → boolean

-- Obtiene el rol del usuario autenticado
get_rol_actual() → text

-- Obtiene la VP asignada al usuario
get_vp_actual() → uuid

-- Obtiene la gerencia asignada al usuario
get_gerencia_actual() → uuid

5.2 Políticas por Tabla

Tabla SELECT INSERT UPDATE DELETE
vicepresidencias Todos Admin Admin Admin
gerencias Todos Admin Admin
indicadores_definicion Según rol/área Admin Admin
indicadores_valores Según rol/área Admin + Gerencia propia Según rol + estado_validacion
periodos Todos Admin Admin Admin
usuarios Admin ∨ propio Admin Admin ∨ propio

Importante: admin_gerencia solo puede actualizar valores cuando estado_validacion IN ('pendiente','rechazado'). Esto impide modificar datos ya validados o en proceso de aprobación.

6. Autenticación

El sistema usa Supabase Auth con JWT. El flujo de login:

1. Usuario ingresa email + password
2. supabase.auth.signInWithPassword() → JWT + Session
3. authService.login() busca en tabla 'usuarios' por email
4. Si auth_user_id es NULL → auto-vincula auth.uid() al registro
5. Verifica usuario.activo === true
6. Carga joins: rol, vicepresidencia, gerencia
7. Retorna { auth: AuthResponse, usuario: DBUsuario }

Métodos del authService

Método Descripción
login(email, password) Autenticar + vincular + cargar usuario completo
logout() Cerrar sesión Supabase Auth
getSession() Obtener sesión activa (JWT)
restoreUser() Restaurar usuario desde sesión persistida
requestPasswordReset(email) Enviar enlace de reset por email
updatePassword(newPassword) Actualizar contraseña post-reset

7. Capa de Servicios

Todos los servicios están en src/lib/services.ts. Cada entidad del dominio tiene su propio objeto de servicio con métodos CRUD y operaciones especializadas.

Servicios Disponibles (18)

vpService

CRUD Vicepresidencias (soft-delete)

gerenciaService

CRUD Gerencias con joins a VP

indicadorService

CRUD definiciones de KPIs

valorService

CRUD valores + validación + aprobación

periodoService

Gestión períodos de medición

usuarioService

CRUD usuarios + último acceso

planAccionService

Planes correctivos con progreso

riesgoService

Matriz de riesgos CRUD

alertaService

Alertas en pantalla + reconocimiento

alertaEmailService

Plantillas + configs + Edge Function

correlacionService

Correlaciones cruzadas entre KPIs

dashboardService

Queries agregadas para dashboards

bscService

Perspectivas + objetivos estratégicos

cargaMasivaService

Procesamiento CSV → indicadores + valores

auditService

Consulta audit_log con filtros

calidadDatosService

Resumen calidad + anomalías

rolService

Catálogo de roles

perspectivaService

Catálogo perspectivas BSC

valorService — Métodos Clave

El servicio más complejo, maneja el ciclo de vida completo de los valores:

// Flujo de validación
valorService.enviarAValidacion(gerenciaId, periodoId)  // pendiente → en_validacion
valorService.aprobarGerencia(gerenciaId, periodoId, validadoPorId) // → validado
valorService.rechazarValor(valorId, motivoRechazo, rechazadoPorId) // → rechazado

// Bulk operations
valorService.upsert(valores[])       // Conflict on indicador_id+periodo_id
valorService.deleteByPeriodo(periodoId, gerenciaId?)  // Returns count

// Queries especializadas
valorService.getAllHistorico(limit=5000) // Para análisis de tendencias
valorService.getPendientesAprobacionPorVP(vpId, periodoId) // Para VP

8. Sistema de Tipos

Dos capas de tipos: DB types en supabase.ts (prefijo DB*) para comunicación con Supabase, y frontend types en types/index.ts para lógica de presentación.

Tipos Clave

// Estado del semáforo
type EstadoSemaforo = 'verde' | 'amarillo' | 'rojo'

// Perspectivas BSC
type PerspectivaBSC = 'financiera' | 'clientes' | 'procesos' | 'aprendizaje'

// Roles de usuario
type RolUsuario = 'presidencia' | 'vicepresidencia' | 'gerencia'
                | 'admin_global' | 'admin_vp' | 'admin_gerencia' | 'visualizador'

// Tendencia de indicador (DB)
type Tendencia = 'mayor_mejor' | 'menor_mejor' | 'objetivo'

// Estado de período (DB)
type EstadoPeriodo = 'abierto' | 'cerrado' | 'bloqueado' | 'pendiente'

// Estado de validación (DB)
type EstadoValidacion = 'pendiente' | 'en_validacion' | 'validado' | 'rechazado'

9. Triggers y Funciones PostgreSQL

Función: calcular_estado_indicador

calcular_estado_indicador(
    p_valor_real  DECIMAL,
    p_meta        DECIMAL,
    p_umbral_rojo INT,
    p_umbral_amarillo INT,
    p_tendencia   TEXT
) → TEXT

-- Lógica:
-- Si valor_real IS NULL → 'sin_dato'
-- Si tendencia = 'mayor_mejor':  cumplimiento = (real / meta) * 100
-- Si tendencia = 'menor_mejor':  cumplimiento = LEAST(100, (meta / real) * 100)
-- cumplimiento >= umbral_amarillo → 'verde'
-- cumplimiento >= umbral_rojo    → 'amarillo'
-- else                           → 'rojo'

Triggers Automáticos

Trigger Tabla Evento Acción
tr_calcular_estado indicadores_valores BEFORE INSERT/UPDATE Calcula porcentaje_cumplimiento, desviacion, estado
tr_crear_alerta indicadores_valores AFTER INSERT/UPDATE Crea alerta automática cuando estado = 'rojo'
tr_updated_at_* 5 tablas BEFORE UPDATE Actualiza updated_at = NOW()

10. Edge Functions (Supabase)

send-alert-email

Función Deno desplegada en Supabase Edge Functions. Gestiona el envío de correos electrónicos de alerta.

// Modos de invocación:

// 1. Envío de prueba
{ configId: "uuid", test: true }

// 2. Evaluación masiva de todas las reglas configuradas
{ evalAll: true }

// 3. Envío directo ad-hoc
{ direct: true, to: ["email@..."], subject: "...", html: "..." }

Las plantillas de email se configuran desde la pantalla "Alertas Email" con variables dinámicas como {{indicador}}, {{valor}}, {{meta}}, etc.

11. Caché y Rendimiento

El sistema implementa un caché en memoria con TTL de 30 segundos para reducir llamadas redundantes a Supabase.

// Implementación en services.ts
const cache = new Map<string, { data: any, timestamp: number }>()
const CACHE_TTL = 30_000 // 30 segundos

function getCached<T>(key: string): T | null
function setCache(key: string, data: any): void
function invalidateCache(prefix?: string): void  // Limpia por prefijo

Servicios con caché: valorService.getByPeriodo, valorService.getAllHistorico. Las mutaciones (create/update/delete) invalidan el caché automáticamente.

12. Variables de Entorno

Variable Requerida Descripción
VITE_SUPABASE_URL URL del proyecto Supabase (https://xxx.supabase.co)
VITE_SUPABASE_ANON_KEY Clave pública (anon key) del proyecto Supabase

Las variables con prefijo VITE_ se exponen al cliente. La seguridad real la proporciona RLS en PostgreSQL, no la ocultación de la anon key.

13. Despliegue

Vercel (Producción)

# Build command
npm run build

# Output: dist/ → single HTML file (vite-plugin-singlefile)

# Rama de deploy: main
# Repo: hermeshs34/Indicadores_Empresariales

Desarrollo Local

# Instalar dependencias
npm install

# Crear .env con las variables de Supabase
echo "VITE_SUPABASE_URL=https://fciaudxeuycqtuzyurnb.supabase.co" > .env
echo "VITE_SUPABASE_ANON_KEY=tu-anon-key" >> .env

# Iniciar servidor de desarrollo
npm run dev

# Verificar tipos TypeScript
npm run typecheck

# Ejecutar tests
npm test

14. Testing

El proyecto usa Vitest como framework de testing con @testing-library/react para componentes.

# Ejecutar tests
npm test

# Tests con coverage
npx vitest --coverage

# Archivo de tests: tests/smoke.test.ts

Estrategia de testing:

  • Smoke tests para verificar que la app renderiza sin errores
  • Tests de servicios mockeanodo el cliente Supabase
  • Validación de tipos con tsc --noEmit

15. Migraciones

Las migraciones se aplican manualmente en el SQL Editor de Supabase. Se mantienen en database/migrations/.

Migración Descripción
2026-03-28-add-auth-user-id.sql Agrega columna auth_user_id a tabla usuarios para vincular con Supabase Auth

Procedimiento de migración:

  1. Crear archivo SQL en database/migrations/ con fecha en nombre
  2. Probar en Supabase Dashboard → SQL Editor
  3. Verificar que no rompe RLS policies existentes
  4. Actualizar schema.sql para reflejar el estado final