Files
GRH/DOCUMENTATION.md
Exteban08 da976b9003 Update all documentation for 3-level roles, organismos, and Histórico
Reflect current project state across all 8 docs: ADMIN/ORGANISMO_OPERADOR/OPERATOR
role hierarchy, scope filtering, organismos_operadores table, Histórico de Tomas
page, new SQL migrations, and updated API endpoints with auth requirements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 10:44:16 +00:00

25 KiB
Raw Permalink Blame History

Documentacion Tecnica - GRH (Gestion de Recursos Hidricos)

Documentacion tecnica detallada de la arquitectura, componentes, API y patrones del sistema.


Tabla de Contenidos

  1. Arquitectura del Sistema
  2. Frontend - Componentes y Paginas
  3. Backend - API REST
  4. Base de Datos
  5. Autenticacion y Autorizacion
  6. Capa de API del Frontend
  7. Hooks Personalizados
  8. Sistema de Temas
  9. Conectores Externos
  10. Tareas Programadas
  11. Guia de Desarrollo

Arquitectura del Sistema

Vision General

El proyecto es una aplicacion full-stack con tres componentes principales:

┌─────────────────────────────────────────────────────────────┐
│                  Capa de Presentacion                        │
│  React SPA: Pages, Components, Layout                        │
├─────────────────────────────────────────────────────────────┤
│                  Capa de Logica (Frontend)                    │
│  Custom Hooks, API Client con JWT, Estado Local              │
├─────────────────────────────────────────────────────────────┤
│                  Capa de API (Backend)                        │
│  Express Routes → Controllers → Services → PostgreSQL        │
├─────────────────────────────────────────────────────────────┤
│                  Capa de Datos                                │
│  PostgreSQL: 11 tablas, 2 vistas, triggers, indices          │
├─────────────────────────────────────────────────────────────┤
│                  Integraciones Externas                       │
│  The Things Stack (LoRaWAN), SH-Meters, XMeters              │
└─────────────────────────────────────────────────────────────┘

Patrones de Diseno

  1. Container/Presentational - Paginas manejan logica, componentes renderizan UI
  2. Custom Hooks - Logica reutilizable en hooks (useMeters, useConcentrators, useNotifications)
  3. Module Pattern - Codigo organizado por dominio (meters/, concentrators/, analytics/)
  4. Service Layer (Backend) - Routes → Controllers → Services → Database
  5. Repository Pattern - Cada servicio encapsula las queries SQL de su dominio
  6. Middleware Pipeline - Auth, audit logging, webhook verification

Frontend - Componentes y Paginas

App.tsx - Componente Raiz

Maneja autenticacion global, routing por estado interno y modales globales.

export type Page =
  | "home" | "projects" | "meters" | "concentrators"
  | "consumption" | "auditoria" | "users" | "roles"
  | "sh-meters" | "xmeters" | "tts"
  | "analytics-map" | "analytics-reports" | "analytics-server"
  | "organismos" | "historico";

La navegacion es state-based (sin React Router). El estado currentPage determina que pagina se renderiza.

Paginas Principales

Pagina Archivo Descripcion
Dashboard Home.tsx KPIs, graficos Recharts, selector de organismos, alertas
Login LoginPage.tsx Formulario de autenticacion
Medidores meters/MeterPage.tsx CRUD con tabla, sidebar, filtros, carga masiva
Concentradores concentrators/ConcentratorsPage.tsx CRUD con tabla y sidebar
Proyectos projects/ProjectsPage.tsx Tabla de proyectos con estados
Consumo consumption/ConsumptionPage.tsx Lecturas con filtros y estadisticas
Usuarios UsersPage.tsx Gestion de usuarios (admin)
Roles RolesPage.tsx Gestion de roles y permisos
Auditoria AuditoriaPage.tsx Visor de logs de actividad
Mapa analytics/AnalyticsMapPage.tsx Mapa Leaflet con ubicaciones de medidores
Reportes analytics/AnalyticsReportsPage.tsx Reportes de consumo
Servidor analytics/AnalyticsServerPage.tsx Metricas CPU, memoria, requests
SH-Meters conectores/SHMetersPage.tsx Conector SH-Meters
XMeters conectores/XMetersPage.tsx Conector XMeters
TTS conectores/TTSPage.tsx Conector The Things Stack
Organismos OrganismosPage.tsx Gestion de organismos operadores (ADMIN)
Historico historico/HistoricoPage.tsx Historico de lecturas por medidor con grafica, estadisticas y tabla

Componentes de Layout

Sidebar.tsx

  • Menu lateral colapsable con hover expansion
  • Soporte para pin/unpin
  • Menu jerarquico con submenus (Analytics, Conectores)
  • Visibilidad por rol de 3 niveles:
    • ADMIN: ve todo (incluye Organismos, Conectores, Auditoria)
    • ORGANISMO_OPERADOR: ve Dashboard, Project Management, Users, Analytics
    • OPERATOR: ve Dashboard y Project Management

TopMenu.tsx

  • Breadcrumb de navegacion
  • Dropdown de notificaciones con conteo de no leidas
  • Menu de usuario: perfil, configuracion, logout

Componentes Comunes

  • ProfileModal.tsx - Edicion de perfil con avatar local
  • ConfirmModal.tsx - Confirmacion de acciones destructivas
  • Watermark.tsx - Marca de agua GRH
  • ProjectBadge.tsx - Badge visual de proyecto
  • SettingsModals.tsx - Configuracion de tema y modo compacto
  • NotificationDropdown.tsx - Panel de notificaciones

Backend - API REST

Estructura de Archivos

water-api/src/
├── index.ts                 # Setup Express: CORS, Helmet, body-parser, rutas
├── config/
│   ├── index.ts             # Variables de entorno centralizadas
│   └── database.ts          # Pool de conexiones pg
├── routes/                  # Definicion de rutas (18 archivos)
│   └── organismo-operador.routes.ts  # Rutas CRUD organismos
├── controllers/             # Controladores HTTP
│   └── organismo-operador.controller.ts
├── services/                # Logica de negocio (19 modulos)
│   └── organismo-operador.service.ts
├── middleware/
│   ├── auth.middleware.ts   # Verificacion JWT + extraccion de rol + requireRole
│   ├── audit.middleware.ts  # Auto-logging de acciones
│   └── ttsWebhook.middleware.ts  # Verificacion de secreto webhook
├── validators/              # Schemas de validacion Zod
├── utils/
│   ├── jwt.ts               # sign/verify de tokens (incluye organismoOperadorId)
│   ├── password.ts          # hash/compare con bcrypt
│   ├── logger.ts            # Winston con formato timestamp
│   └── scope.ts             # Filtrado por scope de rol (ADMIN/ORGANISMO/OPERATOR)
├── jobs/
│   └── negativeFlowDetection.ts  # Cron de deteccion de flujo negativo
└── types/                   # Interfaces TypeScript

Endpoints Detallados

Autenticacion (/api/auth)

Metodo Ruta Descripcion Auth
POST /login Autenticar usuario No
POST /refresh Renovar access token No (usa refresh token)
POST /logout Cerrar sesion Si
GET /me Obtener perfil actual Si
PATCH /me Actualizar perfil Si

Proyectos (/api/projects)

Metodo Ruta Descripcion Auth
GET / Listar proyectos Si
GET /:id Obtener proyecto Si
GET /:id/stats Estadisticas del proyecto Si
POST / Crear proyecto Si (ADMIN/OPERATOR)
PUT /:id Actualizar proyecto Si (ADMIN/OPERATOR)
DELETE /:id Eliminar proyecto Si (ADMIN)

Medidores (/api/meters)

Metodo Ruta Descripcion Auth
GET / Listar medidores (filtros: project, status, type) Si
GET /:id Obtener medidor Si
GET /:id/readings Historial de lecturas del medidor Si
POST / Crear medidor Si (ADMIN/OPERATOR)
PUT /:id Actualizar medidor Si (ADMIN/OPERATOR)
DELETE /:id Eliminar medidor Si (ADMIN)

Concentradores (/api/concentrators)

Metodo Ruta Descripcion Auth
GET / Listar concentradores Si
GET /:id Obtener concentrador Si
POST / Crear concentrador Si (ADMIN/OPERATOR)
PUT /:id Actualizar concentrador Si (ADMIN/OPERATOR)
DELETE /:id Eliminar concentrador Si (ADMIN)

Gateways (/api/gateways)

Metodo Ruta Descripcion Auth
GET / Listar gateways Si
GET /:id Obtener gateway Si
GET /:id/devices Dispositivos del gateway Si
POST / Crear gateway Si (ADMIN/OPERATOR)
PUT /:id Actualizar gateway Si (ADMIN/OPERATOR)
DELETE /:id Eliminar gateway Si (ADMIN)

Dispositivos (/api/devices)

Metodo Ruta Descripcion Auth
GET / Listar dispositivos Si
GET /:id Obtener dispositivo Si
GET /dev-eui/:devEui Buscar por DevEUI Si
POST / Crear dispositivo Si (ADMIN/OPERATOR)
PUT /:id Actualizar dispositivo Si (ADMIN/OPERATOR)
DELETE /:id Eliminar dispositivo Si (ADMIN)

Organismos Operadores (/api/organismos-operadores) - Solo ADMIN

Metodo Ruta Descripcion Auth
GET / Listar organismos operadores Si (ADMIN)
GET /:id Obtener organismo operador Si (ADMIN)
POST / Crear organismo operador Si (ADMIN)
PUT /:id Actualizar organismo operador Si (ADMIN)
DELETE /:id Eliminar organismo operador Si (ADMIN)

Usuarios (/api/users) - ADMIN y ORGANISMO_OPERADOR

Metodo Ruta Descripcion Auth
GET / Listar usuarios (filtrado por scope) Si (ADMIN/ORGANISMO_OPERADOR)
GET /:id Obtener usuario Si (ADMIN o self)
POST / Crear usuario Si (ADMIN/ORGANISMO_OPERADOR)
PUT /:id Actualizar usuario Si (ADMIN o self)
DELETE /:id Desactivar usuario Si (ADMIN)
PUT /:id/password Cambiar contrasena Si (self)

Roles (/api/roles)

Metodo Ruta Descripcion Auth
GET / Listar roles Si
GET /:id Obtener rol con conteo de usuarios Si
POST / Crear rol Si (ADMIN)
PUT /:id Actualizar rol Si (ADMIN)
DELETE /:id Eliminar rol Si (ADMIN)

Tipos de Medidor (/api/meter-types)

Metodo Ruta Descripcion Auth
GET / Listar tipos Si
GET /:id Obtener por ID Si
GET /code/:code Obtener por codigo Si
POST / Crear tipo Si (ADMIN)
PUT /:id Actualizar tipo Si (ADMIN)
DELETE /:id Eliminar tipo Si (ADMIN)

Lecturas (/api/readings)

Metodo Ruta Descripcion Auth
GET / Listar lecturas (filtros: proyecto, fecha, medidor) Si
GET /summary Resumen de consumo Si
GET /:id Obtener lectura Si
POST / Crear lectura Si
DELETE /:id Eliminar lectura Si (ADMIN)

Notificaciones (/api/notifications)

Metodo Ruta Descripcion Auth
GET / Listar notificaciones del usuario Si
GET /unread-count Conteo de no leidas Si
GET /:id Obtener notificacion Si
PATCH /:id/read Marcar como leida Si
PATCH /read-all Marcar todas como leidas Si
DELETE /:id Eliminar notificacion Si

Auditoria (/api/audit-logs) - Solo ADMIN

Metodo Ruta Descripcion Auth
GET / Listar logs Si (ADMIN)
GET /my-activity Actividad del usuario actual Si
GET /statistics Estadisticas de auditoria Si (ADMIN)
GET /:id Detalle de un log Si (ADMIN)
GET /record/:tableName/:recordId Logs de un registro especifico Si (ADMIN)

Carga Masiva

Metodo Ruta Descripcion Auth
POST /bulk-upload/meters Subir Excel de medidores Si
GET /bulk-upload/meters/template Descargar plantilla Excel Si
POST /csv-upload/meters Subir CSV de medidores (upsert) No
POST /csv-upload/readings Subir CSV de lecturas No
GET /csv-upload/meters/template Plantilla CSV medidores No
GET /csv-upload/readings/template Plantilla CSV lecturas No

TTS Webhooks (/api/webhooks/tts)

Metodo Ruta Descripcion Auth
GET /health Health check del webhook No
POST /uplink Recibir mensajes uplink Webhook secret
POST /join Recibir eventos de join Webhook secret
POST /downlink/ack Recibir acks de downlink Webhook secret

Sistema (/api/system) - Solo ADMIN

Metodo Ruta Descripcion Auth
GET /metrics Metricas del servidor (CPU, memoria, requests) Si (ADMIN)
GET /health Health check detallado Si (ADMIN)
GET /meters-locations Coordenadas de medidores para mapa Si (ADMIN)
GET /report-stats Estadisticas para reportes Si (ADMIN)

Base de Datos

Esquema Relacional

roles ←─── users ←─── refresh_tokens
              │
              ▼
           projects
             │  ╲
             │   ╲
         ▼    ▼    ▼
  concentrators gateways  meters ──→ meter_readings
                  │         │
                  ▼         │
               devices ─────┘
                  │
                  ▼
           tts_uplink_logs

ENUMs de PostgreSQL

  • role_name: ADMIN, ORGANISMO_OPERADOR, OPERATOR
  • project_status: ACTIVE, INACTIVE, COMPLETED
  • device_status: ACTIVE, INACTIVE, OFFLINE, MAINTENANCE, ERROR
  • meter_type: WATER, GAS, ELECTRIC
  • reading_type: AUTOMATIC, MANUAL, SCHEDULED

Migraciones SQL

Ejecutar en orden despues del schema principal:

  1. schema.sql - Schema principal con tablas base, 2 vistas, seed de roles y admin
  2. add_audit_logs.sql - Tabla de logs de auditoria
  3. add_notifications.sql - Tabla de notificaciones
  4. add_meter_extended_fields.sql - Campos extendidos para medidores
  5. create_meter_types.sql - Tabla de tipos de medidor
  6. add_meter_project_relation.sql - Relacion meter-proyecto
  7. add_user_project_relation.sql - Relacion user-proyecto
  8. add_organismos_operadores.sql - Tabla organismos_operadores, FK en projects y users, rol ORGANISMO_OPERADOR
  9. add_user_meter_fields.sql - Campos adicionales en users y meters (cespt_account, cadastral_key)

Autenticacion y Autorizacion

Flujo JWT

┌──────────┐   POST /auth/login    ┌──────────┐
│  Cliente  │ ───────────────────→  │  Backend  │
│           │ ←───────────────────  │           │
└──────────┘   {accessToken,        └──────────┘
                refreshToken}            │
       │                                 │ bcrypt.compare()
       │  Authorization: Bearer <token>  │ jwt.sign()
       │ ───────────────────────────→    │
       │                                 │ jwt.verify()
       │                                 │
       │   401 Unauthorized              │
       │ ←───────────────────────────    │
       │                                 │
       │  POST /auth/refresh             │
       │  {refreshToken}                 │
       │ ───────────────────────────→    │
       │ ←───────────────────────────    │
       │  {newAccessToken}               │

Tokens

  • Access Token - JWT con userId, roleId, roleName, projectId, organismoOperadorId. Expira en 15 minutos.
  • Refresh Token - JWT almacenado hasheado en BD. Expira en 7 dias. Revocable.

Token Refresh Automatico (Frontend)

El cliente HTTP (src/api/client.ts) intercepta respuestas 401 y automaticamente:

  1. Pone en cola las peticiones pendientes
  2. Llama a /auth/refresh con el refresh token
  3. Reintenta las peticiones con el nuevo access token

Almacenamiento en localStorage

grh_access_token    → JWT access token
grh_refresh_token   → JWT refresh token
water_project_settings_v1 → {theme, compactMode}
mock_avatar         → Avatar en base64

Control de Acceso por Rol (Jerarquia de 3 niveles)

Recurso ADMIN ORGANISMO_OPERADOR OPERATOR
Organismos CRUD completo Sin acceso Sin acceso
Usuarios CRUD completo CRUD (su organismo) Sin acceso
Proyectos CRUD completo Leer (su organismo) Leer (su proyecto)
Medidores CRUD completo Leer (su organismo) Leer (su proyecto)
Lecturas CRUD + eliminar Leer (su organismo) Leer (su proyecto)
Historico Todos los medidores Medidores de su organismo Medidores de su proyecto
Analytics Completo Completo Sin acceso
Conectores Completo Sin acceso Sin acceso
Auditoria Completa Sin acceso Sin acceso

Scope Filtering (Backend)

Todos los servicios aplican filtrado automatico basado en el rol del usuario:

ADMIN          → Sin filtro (ve todos los datos)
ORGANISMO_OP.  → project_id IN (SELECT id FROM projects WHERE organismo_operador_id = $N)
OPERATOR       → project_id = $N (solo su proyecto asignado)

El utility water-api/src/utils/scope.ts centraliza esta logica.

Helpers del Frontend

getCurrentUserRole()              // → "ADMIN" | "ORGANISMO_OPERADOR" | "OPERATOR"
getCurrentUserId()                // → UUID string
getCurrentUserProjectId()         // → UUID string | undefined
getCurrentUserOrganismoId()       // → UUID string | undefined
isCurrentUserAdmin()              // → boolean
isCurrentUserOrganismo()          // → boolean
isCurrentUserOperator()           // → boolean

Capa de API del Frontend

Cliente HTTP (src/api/client.ts)

Wrapper de fetch con:

  • Inyeccion automatica de Authorization: Bearer <token>
  • Refresh automatico de tokens en 401
  • Cola de peticiones durante el refresh (previene race conditions)
  • Buffer de 30 segundos antes de expirar
  • Transformacion de snake_case (backend) a camelCase (frontend)

Modulos de API

Archivo Descripcion
auth.ts Login, logout, refresh, getMe, helpers de roles (3 niveles)
client.ts Cliente HTTP base con JWT
meters.ts CRUD medidores + lecturas historicas paginadas
readings.ts Lecturas y resumen de consumo
projects.ts CRUD proyectos + nombres
concentrators.ts CRUD concentradores
users.ts CRUD usuarios
roles.ts CRUD roles
organismos.ts CRUD organismos operadores
analytics.ts Metricas, ubicaciones, reportes
notifications.ts Notificaciones del usuario
audit.ts Logs de auditoria
me.ts Perfil de usuario actual
meterTypes.ts Tipos de medidor
types.ts Interfaces compartidas

Hooks Personalizados

useMeters

Gestiona el estado completo del modulo de medidores.

interface UseMetersReturn {
  // Datos
  meters: Meter[];
  filteredMeters: Meter[];
  projectNames: string[];

  // Estado
  loading: boolean;
  selectedMeter: Meter | null;
  selectedProject: string | null;
  searchTerm: string;

  // Acciones
  setSelectedMeter: (meter: Meter | null) => void;
  setSelectedProject: (project: string | null) => void;
  setSearchTerm: (term: string) => void;
  refreshData: () => Promise<void>;
  loadMeters: () => Promise<void>;

  // CRUD
  handleCreate: (data: Partial<Meter>) => Promise<void>;
  handleUpdate: (id: string, data: Partial<Meter>) => Promise<void>;
  handleDelete: (id: string) => Promise<void>;
}

useConcentrators

Estructura equivalente a useMeters para el modulo de concentradores.

useNotifications

Gestiona notificaciones del usuario con polling periodico.

interface UseNotificationsReturn {
  notifications: Notification[];
  unreadCount: number;
  loading: boolean;
  markAsRead: (id: string) => Promise<void>;
  markAllAsRead: () => Promise<void>;
  deleteNotification: (id: string) => Promise<void>;
  refresh: () => Promise<void>;
}

Flujo de Datos

API Layer (fetch + JWT)
       │
       ▼
Custom Hook (useMeters, etc.)
       │
       ▼
Page Component (MeterPage, etc.)
       │
       ├──────────────┬──────────────┐
       ▼              ▼              ▼
   Sidebar        Table          Modal

Sistema de Temas

Configuracion

Tres modos disponibles: system, light, dark.

type Theme = "system" | "light" | "dark";

// Aplicacion del tema
document.documentElement.classList.toggle("dark", isDark);

Paleta de Colores (Dark Mode)

El dark mode usa la paleta Zinc de Tailwind:

  • Fondo principal: bg-zinc-900
  • Fondo de tarjetas: bg-zinc-800
  • Bordes: border-zinc-700
  • Texto primario: text-zinc-100
  • Texto secundario: text-zinc-400

Persistencia

const SETTINGS_KEY = "water_project_settings_v1";

interface Settings {
  theme: "system" | "light" | "dark";
  compactMode: boolean;
}

Conectores Externos

SH-Meters

Conector para sistema de medidores SH. Muestra estado de conexion, ultima sincronizacion y datos sincronizados.

XMeters

Conector para sistema XMeters con funcionalidad similar a SH-Meters.

The Things Stack (TTS)

Integracion con LoRaWAN via webhooks:

  • Uplink (POST /api/webhooks/tts/uplink): Recibe lecturas de sensores, decodifica payload, crea readings automaticamente
  • Join (POST /api/webhooks/tts/join): Registra eventos de conexion de dispositivos
  • Downlink Ack (POST /api/webhooks/tts/downlink/ack): Confirma envio de comandos a dispositivos

Los webhooks usan verificacion por secreto en lugar de JWT.

Sincronizacion

Los conectores tienen sincronizacion programada a las 9:00 AM.


Tareas Programadas

Deteccion de Flujo Negativo

Job de node-cron que:

  1. Revisa lecturas recientes de medidores
  2. Detecta valores negativos o anomalias
  3. Genera notificaciones automaticas para los usuarios

Guia de Desarrollo

Agregar una Nueva Pagina

  1. Crear el componente en src/pages/nueva/NuevaPage.tsx
  2. Agregar al tipo Page en App.tsx
  3. Agregar al Sidebar en Sidebar.tsx (menuItems)
  4. Agregar al renderizado en App.tsx (switch en renderPage())

Agregar un Nuevo Endpoint en el Backend

  1. Crear servicio en water-api/src/services/nuevo.service.ts
  2. Crear controlador en water-api/src/controllers/nuevo.controller.ts
  3. Crear validador (opcional) en water-api/src/validators/nuevo.validator.ts
  4. Crear rutas en water-api/src/routes/nuevo.routes.ts
  5. Registrar rutas en water-api/src/routes/index.ts

Agregar un Modulo de API en el Frontend

  1. Crear archivo en src/api/nuevo.ts
  2. Usar el cliente HTTP importando de ./client.ts
  3. Crear hook (opcional) en src/pages/nueva/useNuevo.ts

Convenciones de Codigo

Elemento Convencion Ejemplo
Componentes React PascalCase.tsx MeterPage.tsx
Hooks camelCase con prefijo use useMeters.ts
Servicios backend camelCase.service.ts meter.service.ts
Rutas backend camelCase.routes.ts meter.routes.ts
Constantes UPPER_SNAKE_CASE API_BASE_URL
DB columnas snake_case serial_number
API response → Frontend snake_case → camelCase serial_numberserialNumber
CSS Tailwind utility classes bg-zinc-800 dark:text-white

Seguridad

  • Helmet.js para headers HTTP seguros
  • CORS configurado para origenes especificos
  • Bcrypt (12 rounds) para hash de contrasenas
  • JWT con access + refresh tokens
  • Queries parametrizadas para prevenir SQL injection
  • Zod para validacion de inputs
  • Audit logging automatico de acciones

Testing

El proyecto actualmente no tiene suite de tests. Para agregar:

# Frontend
npm install -D vitest @testing-library/react @testing-library/jest-dom

# Backend
cd water-api
npm install -D vitest supertest @types/supertest