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

668 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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](#arquitectura-del-sistema)
2. [Frontend - Componentes y Paginas](#frontend---componentes-y-paginas)
3. [Backend - API REST](#backend---api-rest)
4. [Base de Datos](#base-de-datos)
5. [Autenticacion y Autorizacion](#autenticacion-y-autorizacion)
6. [Capa de API del Frontend](#capa-de-api-del-frontend)
7. [Hooks Personalizados](#hooks-personalizados)
8. [Sistema de Temas](#sistema-de-temas)
9. [Conectores Externos](#conectores-externos)
10. [Tareas Programadas](#tareas-programadas)
11. [Guia de Desarrollo](#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.
```typescript
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
```typescript
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.
```typescript
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.
```typescript
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`.
```typescript
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
```typescript
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_number``serialNumber` |
| 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:
```bash
# Frontend
npm install -D vitest @testing-library/react @testing-library/jest-dom
# Backend
cd water-api
npm install -D vitest supertest @types/supertest
```