Update all project documentation to reflect current state
Rewrite README.md, DOCUMENTATION.md, ESTADO_ACTUAL.md and CAMBIOS_SESION.md to accurately document the full-stack architecture, all modules, API endpoints, JWT auth, database schema, and features added in February 2026. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,171 +1,143 @@
|
||||
# Cambios Realizados - Sesión 2026-01-23
|
||||
# Historial de Cambios - Proyecto GRH
|
||||
|
||||
## Resumen
|
||||
Corrección de errores críticos que causaban pantalla blanca y mejoras en el sistema de carga masiva.
|
||||
Registro cronologico de cambios significativos realizados al proyecto.
|
||||
|
||||
---
|
||||
|
||||
## Problema 1: Pantalla Blanca en Water Meters y Consumo
|
||||
## 2026-02-09: Actualizacion de documentacion
|
||||
|
||||
### Síntoma
|
||||
Al navegar a "Water Meters" o "Consumo", la página se quedaba en blanco.
|
||||
|
||||
### Causa
|
||||
PostgreSQL devuelve valores DECIMAL como strings (ej: `"300.0000"`). El código llamaba `.toFixed()` directamente sobre estos strings, pero `.toFixed()` es un método de números, no de strings.
|
||||
|
||||
### Solución
|
||||
Convertir los valores a número con `Number()` antes de llamar `.toFixed()`.
|
||||
### Resumen
|
||||
Actualizacion completa de los 4 archivos de documentacion para reflejar el estado real del proyecto.
|
||||
|
||||
### Archivos Modificados
|
||||
| Archivo | Cambio |
|
||||
|---------|--------|
|
||||
| `README.md` | Reescrito completamente: arquitectura full-stack, backend Express, PostgreSQL, todos los modulos, endpoints API, variables de entorno, estructura de directorios actualizada |
|
||||
| `DOCUMENTATION.md` | Reescrito completamente: documentacion tecnica con JWT real, todos los endpoints del backend, esquema relacional, hooks, sistema de temas, conectores, guia de desarrollo actualizada |
|
||||
| `ESTADO_ACTUAL.md` | Actualizado con todas las funcionalidades implementadas en febrero 2026: Analytics, Conectores, Dark mode, Notificaciones, Auditoria, Upload Panel, historial de correcciones |
|
||||
| `CAMBIOS_SESION.md` | Convertido a historial cronologico completo de cambios |
|
||||
|
||||
**`src/pages/meters/MetersTable.tsx` (línea 75)**
|
||||
```typescript
|
||||
// ANTES:
|
||||
r.lastReadingValue?.toFixed(2)
|
||||
|
||||
// DESPUÉS:
|
||||
r.lastReadingValue != null ? Number(r.lastReadingValue).toFixed(2) : "-"
|
||||
```
|
||||
|
||||
**`src/pages/consumption/ConsumptionPage.tsx` (líneas 133, 213, 432)**
|
||||
```typescript
|
||||
// ANTES:
|
||||
r.readingValue.toFixed(2)
|
||||
summary?.avgReading.toFixed(1)
|
||||
reading.readingValue.toFixed(2)
|
||||
|
||||
// DESPUÉS:
|
||||
Number(r.readingValue).toFixed(2)
|
||||
summary?.avgReading != null ? Number(summary.avgReading).toFixed(1) : "0"
|
||||
Number(reading.readingValue).toFixed(2)
|
||||
```
|
||||
### Motivo
|
||||
La documentacion previa describia una version temprana del proyecto (solo frontend, API externa NocoDB, auth con token simple) y no reflejaba el backend Express propio, JWT con refresh tokens, ni los modulos agregados en febrero 2026.
|
||||
|
||||
---
|
||||
|
||||
## Problema 2: Modal de Carga Masiva se Cerraba sin Mostrar Resultados
|
||||
## 2026-02-05: Sincronizacion de conectores
|
||||
|
||||
### Síntoma
|
||||
Al subir un archivo Excel para carga masiva, el modal se cerraba inmediatamente sin mostrar cuántos registros se insertaron o qué errores hubo.
|
||||
### Cambio
|
||||
Cambio de hora de sincronizacion de conectores de 2:00 AM a 9:00 AM.
|
||||
|
||||
### Causa
|
||||
El callback `onSuccess` cerraba el modal automáticamente:
|
||||
```typescript
|
||||
onSuccess={() => {
|
||||
m.loadMeters();
|
||||
setShowBulkUpload(false); // ← Cerraba antes de ver resultados
|
||||
}}
|
||||
```
|
||||
|
||||
### Solución
|
||||
Separar la recarga de datos del cierre del modal. Ahora el modal solo se cierra cuando el usuario hace clic en "Cerrar".
|
||||
|
||||
### Archivo Modificado
|
||||
|
||||
**`src/pages/meters/MeterPage.tsx` (líneas 332-340)**
|
||||
```typescript
|
||||
// ANTES:
|
||||
<MetersBulkUploadModal
|
||||
onClose={() => setShowBulkUpload(false)}
|
||||
onSuccess={() => {
|
||||
m.loadMeters();
|
||||
setShowBulkUpload(false);
|
||||
}}
|
||||
/>
|
||||
|
||||
// DESPUÉS:
|
||||
<MetersBulkUploadModal
|
||||
onClose={() => {
|
||||
m.loadMeters();
|
||||
setShowBulkUpload(false);
|
||||
}}
|
||||
onSuccess={() => {
|
||||
m.loadMeters();
|
||||
}}
|
||||
/>
|
||||
```
|
||||
### Archivos Modificados (2)
|
||||
- `src/pages/conectores/SHMetersPage.tsx`
|
||||
- `src/pages/conectores/XMetersPage.tsx`
|
||||
|
||||
---
|
||||
|
||||
## Problema 3: Error de Fecha Inválida en Carga Masiva
|
||||
## 2026-02-04: Favicon y conectores
|
||||
|
||||
### Síntoma
|
||||
Al subir medidores, aparecía el error:
|
||||
```
|
||||
Fila X: invalid input syntax for type date: "Installed"
|
||||
```
|
||||
### Cambios
|
||||
- Actualizacion de favicon del sistema
|
||||
- Mejoras en la visualizacion de tiempo de ultima conexion en paginas de conectores
|
||||
- Agregado plan de implementacion para rol ORGANISMOS_OPERADORES
|
||||
|
||||
### Causa
|
||||
El archivo Excel tenía columnas con valores como "Installed" o "New_LoRa" que el sistema interpretaba como fechas porque no estaban mapeadas correctamente.
|
||||
|
||||
### Solución
|
||||
1. **Validar fechas**: Verificar que `installation_date` sea realmente una fecha válida antes de usarla.
|
||||
2. **Más mapeos de columnas**: Agregar mapeos para columnas comunes como `device_status`, `device_name`, etc.
|
||||
3. **Normalizar status**: Convertir valores como "Installed", "New_LoRa" a "ACTIVE".
|
||||
|
||||
### Archivo Modificado
|
||||
|
||||
**`water-api/src/services/bulk-upload.service.ts`**
|
||||
|
||||
Validación de fechas (líneas 183-195):
|
||||
```typescript
|
||||
let installationDate: string | undefined = undefined;
|
||||
if (row.installation_date) {
|
||||
const dateStr = String(row.installation_date).trim();
|
||||
if (/^\d{4}[-/]\d{1,2}[-/]\d{1,2}/.test(dateStr) || /^\d{1,2}[-/]\d{1,2}[-/]\d{2,4}/.test(dateStr)) {
|
||||
const parsed = new Date(dateStr);
|
||||
if (!isNaN(parsed.getTime())) {
|
||||
installationDate = parsed.toISOString().split('T')[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Mapeos de columnas adicionales (líneas 65-90):
|
||||
```typescript
|
||||
const mappings: Record<string, string> = {
|
||||
// Serial number
|
||||
'device_s/n': 'serial_number',
|
||||
'device_sn': 'serial_number',
|
||||
// Name
|
||||
'device_name': 'name',
|
||||
'meter_name': 'name',
|
||||
// Status
|
||||
'device_status': 'status',
|
||||
// ... más mapeos
|
||||
};
|
||||
```
|
||||
|
||||
Normalización de status (líneas 210-225):
|
||||
```typescript
|
||||
const statusMappings: Record<string, string> = {
|
||||
'INSTALLED': 'ACTIVE',
|
||||
'NEW_LORA': 'ACTIVE',
|
||||
'NEW': 'ACTIVE',
|
||||
'ENABLED': 'ACTIVE',
|
||||
'DISABLED': 'INACTIVE',
|
||||
// ...
|
||||
};
|
||||
```
|
||||
### Archivos Modificados (4+1)
|
||||
- Favicon actualizado
|
||||
- Paginas de conectores actualizadas
|
||||
- `PLAN_ORGANISMOS_OPERADORES.md` (plan de implementacion)
|
||||
|
||||
---
|
||||
|
||||
## Archivos Modificados en Esta Sesión
|
||||
## 2026-02-03: Dark mode, Analytics, Conectores y CSV Upload
|
||||
|
||||
### Resumen
|
||||
Sesion mayor con multiples funcionalidades nuevas implementadas en una serie de 12 commits.
|
||||
|
||||
### Nuevas Funcionalidades
|
||||
|
||||
**Dark Mode Completo**
|
||||
- Toggle dark/light/system en configuracion
|
||||
- Paleta Zinc de Tailwind aplicada a todas las paginas
|
||||
- Soporte en tablas, modales, formularios, sidebars
|
||||
- Cards de ConsumptionPage y tabla de AuditoriaPage
|
||||
|
||||
**Seccion Analytics (3 paginas)**
|
||||
- `AnalyticsMapPage.tsx` - Mapa Leaflet con ubicaciones de medidores
|
||||
- `AnalyticsReportsPage.tsx` - Dashboard de reportes y estadisticas
|
||||
- `AnalyticsServerPage.tsx` - Metricas del servidor (CPU, memoria, requests)
|
||||
- `MapComponents.tsx` - Componentes auxiliares del mapa
|
||||
|
||||
**Seccion Conectores (3 paginas)**
|
||||
- `SHMetersPage.tsx` - Conector para sistema SH-Meters
|
||||
- `XMetersPage.tsx` - Conector para sistema XMeters
|
||||
- `TTSPage.tsx` - Conector para The Things Stack (LoRaWAN)
|
||||
|
||||
**Upload Panel (app separada)**
|
||||
- Nueva aplicacion en `upload-panel/` con React + Vite + Tailwind
|
||||
- `MetersUpload.tsx` - Carga de medidores via CSV (upsert)
|
||||
- `ReadingsUpload.tsx` - Carga de lecturas via CSV
|
||||
- `FileDropzone.tsx` - Componente de dropzone para archivos
|
||||
- `ResultsDisplay.tsx` - Visualizacion de resultados
|
||||
|
||||
**Otros**
|
||||
- Nuevos tipos de medidor: LORA, LORAWAN, GRANDES CONSUMIDORES
|
||||
- Documentacion completa del proyecto (6 archivos)
|
||||
|
||||
### Archivos Modificados
|
||||
Aproximadamente 50+ archivos en 12 commits.
|
||||
|
||||
---
|
||||
|
||||
## 2026-01-23: Fix pantalla blanca y carga masiva
|
||||
|
||||
### Resumen
|
||||
Correccion de errores criticos que causaban pantalla blanca y mejoras en el sistema de carga masiva.
|
||||
|
||||
### Problema 1: Pantalla Blanca en Water Meters y Consumo
|
||||
|
||||
**Sintoma:** Al navegar a "Water Meters" o "Consumo", la pagina se quedaba en blanco.
|
||||
|
||||
**Causa:** PostgreSQL devuelve valores DECIMAL como strings (ej: `"300.0000"`). El codigo llamaba `.toFixed()` directamente sobre estos strings.
|
||||
|
||||
**Solucion:** Convertir a numero con `Number()` antes de `.toFixed()`.
|
||||
|
||||
**Archivos:**
|
||||
- `src/pages/meters/MetersTable.tsx:75`
|
||||
- `src/pages/consumption/ConsumptionPage.tsx:133, 213, 432`
|
||||
|
||||
### Problema 2: Modal de Carga Masiva se Cerraba sin Resultados
|
||||
|
||||
**Sintoma:** El modal se cerraba automaticamente despues de la carga sin mostrar resultados.
|
||||
|
||||
**Causa:** El callback `onSuccess` cerraba el modal automaticamente.
|
||||
|
||||
**Solucion:** Separar recarga de datos (`onSuccess`) del cierre del modal (`onClose`).
|
||||
|
||||
**Archivo:** `src/pages/meters/MeterPage.tsx:332-340`
|
||||
|
||||
### Problema 3: Error de Fecha Invalida en Carga Masiva
|
||||
|
||||
**Sintoma:** Error `invalid input syntax for type date: "Installed"` al subir medidores.
|
||||
|
||||
**Causa:** Columnas con valores como "Installed" o "New_LoRa" se interpretaban como fechas.
|
||||
|
||||
**Solucion:**
|
||||
1. Validar formato de fecha con regex antes de usarla
|
||||
2. Agregar mapeos de columnas comunes (`device_s/n` → `serial_number`, etc.)
|
||||
3. Normalizar status ("Installed" → ACTIVE, "New_LoRa" → ACTIVE, etc.)
|
||||
|
||||
**Archivo:** `water-api/src/services/bulk-upload.service.ts`
|
||||
|
||||
### Archivos Modificados
|
||||
| Archivo | Cambio |
|
||||
|---------|--------|
|
||||
| `src/pages/meters/MetersTable.tsx` | Fix `.toFixed()` en lastReadingValue |
|
||||
| `src/pages/consumption/ConsumptionPage.tsx` | Fix `.toFixed()` en readingValue y avgReading |
|
||||
| `src/pages/meters/MeterPage.tsx` | Fix modal de carga masiva |
|
||||
| `water-api/src/services/bulk-upload.service.ts` | Validación de fechas, mapeos de columnas, normalización de status |
|
||||
| `ESTADO_ACTUAL.md` | Documentación actualizada |
|
||||
| `CAMBIOS_SESION.md` | Este archivo |
|
||||
| `water-api/src/services/bulk-upload.service.ts` | Validacion de fechas, mapeos, normalizacion |
|
||||
|
||||
---
|
||||
|
||||
## Verificación
|
||||
|
||||
1. ✅ La página de Water Meters carga correctamente
|
||||
2. ✅ La página de Consumo carga correctamente
|
||||
3. ✅ El modal de carga masiva muestra resultados
|
||||
4. ✅ Errores de carga masiva se muestran claramente
|
||||
5. ✅ Valores como "Installed" no causan error de fecha
|
||||
### Verificacion
|
||||
- La pagina de Water Meters carga correctamente
|
||||
- La pagina de Consumo carga correctamente
|
||||
- El modal de carga masiva muestra resultados
|
||||
- Errores de carga masiva se muestran claramente
|
||||
- Valores como "Installed" no causan error de fecha
|
||||
|
||||
963
DOCUMENTATION.md
963
DOCUMENTATION.md
File diff suppressed because it is too large
Load Diff
315
ESTADO_ACTUAL.md
315
ESTADO_ACTUAL.md
@@ -1,55 +1,72 @@
|
||||
# Estado Actual del Proyecto Water Project GRH
|
||||
# Estado Actual del Proyecto GRH
|
||||
|
||||
**Fecha:** 2026-01-23
|
||||
**Última actualización:** Corrección de errores y mejoras en carga masiva
|
||||
**Fecha:** 2026-02-09
|
||||
**Ultima actualizacion:** Documentacion actualizada para reflejar el estado completo del proyecto
|
||||
|
||||
---
|
||||
|
||||
## Resumen del Proyecto
|
||||
|
||||
Sistema de gestión de medidores de agua con:
|
||||
- **Frontend:** React + TypeScript + Vite (puerto 5173)
|
||||
Sistema full-stack de gestion de medidores de agua con:
|
||||
- **Frontend:** React 18 + TypeScript + Vite (puerto 5173)
|
||||
- **Backend:** Node.js + Express + TypeScript (puerto 3000)
|
||||
- **Base de datos:** PostgreSQL
|
||||
- **Upload Panel:** App separada para carga CSV masiva
|
||||
|
||||
### Jerarquía de datos:
|
||||
### Jerarquia de datos:
|
||||
```
|
||||
Projects → Concentrators → Meters → Readings
|
||||
→ Gateways → Devices ↗
|
||||
```
|
||||
|
||||
### URLs de produccion:
|
||||
- **Frontend:** https://sistema.gestionrecursoshidricos.com
|
||||
- **Backend:** https://api.gestionrecursoshidricos.com
|
||||
|
||||
### Repositorios:
|
||||
- **Gitea:** https://git.consultoria-as.com/consultoria-as/GRH
|
||||
- **GitHub:** git@github.com:luanngel/water-project.git
|
||||
|
||||
---
|
||||
|
||||
## Arquitectura del Sistema
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ FRONTEND (React) │
|
||||
│ FRONTEND (React SPA) │
|
||||
│ http://localhost:5173 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ - React 18 + TypeScript + Vite │
|
||||
│ - Tailwind CSS + Material-UI │
|
||||
│ - Recharts para gráficos │
|
||||
│ - Cliente API con JWT automático │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ React 18 + TypeScript + Vite │
|
||||
│ Tailwind CSS (paleta Zinc) + Material-UI 7 │
|
||||
│ Recharts (graficos) + Leaflet (mapas) │
|
||||
│ Cliente API con JWT + refresh automatico │
|
||||
│ Dark mode / Light mode / System │
|
||||
└──────────────────────────┬──────────────────────────────────┘
|
||||
│ REST API + JWT Bearer
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ BACKEND (Node.js) │
|
||||
│ BACKEND (Express) │
|
||||
│ http://localhost:3000 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ - Express + TypeScript │
|
||||
│ - Autenticación JWT con refresh tokens │
|
||||
│ - CRUD completo para todas las entidades │
|
||||
│ - Carga masiva via Excel (xlsx) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│ Express + TypeScript + Zod (validacion) │
|
||||
│ JWT access (15m) + refresh (7d) tokens │
|
||||
│ 17 archivos de rutas, 18 servicios │
|
||||
│ Helmet, CORS, Bcrypt, Winston logging │
|
||||
│ node-cron (deteccion flujo negativo) │
|
||||
│ Multer + XLSX (carga masiva) │
|
||||
│ Webhooks TTS (The Things Stack / LoRaWAN) │
|
||||
└──────────────────────────┬──────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ BASE DE DATOS │
|
||||
│ PostgreSQL │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Tablas: users, roles, projects, concentrators, │
|
||||
│ meters, meter_readings, refresh_tokens │
|
||||
│ 10 tablas: roles, users, projects, concentrators, │
|
||||
│ gateways, devices, meters, meter_readings, │
|
||||
│ tts_uplink_logs, refresh_tokens │
|
||||
│ 2 vistas: meter_stats_by_project, device_status_summary │
|
||||
│ 7 archivos SQL (schema + 6 migraciones) │
|
||||
│ Triggers de updated_at, indices compuestos, JSONB │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
@@ -57,58 +74,128 @@ Projects → Concentrators → Meters → Readings
|
||||
|
||||
## Funcionalidades Implementadas
|
||||
|
||||
### 1. Autenticación
|
||||
- Login con JWT + refresh tokens
|
||||
- Manejo automático de renovación de tokens
|
||||
- Roles: ADMIN, USER
|
||||
### 1. Autenticacion y Autorizacion
|
||||
- Login con JWT: access token (15 min) + refresh token (7 dias)
|
||||
- Refresh automatico de tokens en el cliente (cola de peticiones)
|
||||
- 3 roles con permisos JSONB: ADMIN, OPERATOR, VIEWER
|
||||
- Relacion usuario-proyecto para acceso por scope
|
||||
- Hash de contrasenas con bcrypt (12 rounds)
|
||||
- Proteccion de rutas por rol en backend y frontend
|
||||
|
||||
### 2. Gestión de Proyectos
|
||||
### 2. Dashboard (Home)
|
||||
- KPIs: Total medidores, medidores activos, consumo promedio, alertas
|
||||
- Grafico de barras: Medidores por proyecto (Recharts)
|
||||
- Selector de organismos operadores (CESPT Tijuana, Tecate, Mexicali)
|
||||
- Historial reciente de actividades
|
||||
- Panel de ultimas alertas
|
||||
- Soporte por rol (ADMIN, OPERATOR, VIEWER)
|
||||
|
||||
### 3. Gestion de Proyectos
|
||||
- CRUD completo
|
||||
- Estados: ACTIVE/INACTIVE
|
||||
- Estados: ACTIVE, INACTIVE, COMPLETED
|
||||
- Estadisticas por proyecto (medidores, lecturas, areas)
|
||||
|
||||
### 3. Gestión de Concentradores
|
||||
### 4. Gestion de Concentradores
|
||||
- CRUD completo
|
||||
- Vinculados a proyectos
|
||||
- Tipos: Gateway LoRa/LoRaWAN
|
||||
- Estado: ACTIVE, INACTIVE, OFFLINE, MAINTENANCE, ERROR
|
||||
- IP, firmware, ultima comunicacion
|
||||
|
||||
### 4. Gestión de Medidores
|
||||
- CRUD completo
|
||||
- Tipos: LORA, LORAWAN, GRANDES
|
||||
- Estados: ACTIVE, INACTIVE, MAINTENANCE, FAULTY, REPLACED
|
||||
- **Carga masiva via Excel**
|
||||
- Última lectura visible en tabla
|
||||
### 5. Gestion de Medidores
|
||||
- CRUD completo con tabla, sidebar de detalle y modal de edicion
|
||||
- Tipos de medidor: WATER, GAS, ELECTRIC
|
||||
- Protocolos: GENERAL, LORA, LORAWAN
|
||||
- Estados: ACTIVE, INACTIVE, OFFLINE, MAINTENANCE, ERROR
|
||||
- Carga masiva via Excel y CSV
|
||||
- Busqueda, filtros por proyecto/tipo/estado
|
||||
- Ultima lectura visible en tabla
|
||||
- Campos extendidos: protocolo, MAC, gateway, voltaje, senal, flujo, coordenadas
|
||||
- Tipos adicionales: LORA, LORAWAN, GRANDES CONSUMIDORES
|
||||
|
||||
### 5. Gestión de Lecturas (Consumo)
|
||||
- CRUD completo
|
||||
### 6. Consumo y Lecturas
|
||||
- CRUD de lecturas
|
||||
- Tipos: AUTOMATIC, MANUAL, SCHEDULED
|
||||
- **Carga masiva via Excel**
|
||||
- Filtros por proyecto, fecha
|
||||
- Exportación a CSV
|
||||
- Indicadores de batería y señal
|
||||
- Carga masiva via Excel y CSV
|
||||
- Filtros por proyecto, medidor, rango de fechas
|
||||
- Resumen de consumo (total, promedio, min, max)
|
||||
- Indicadores de bateria y senal
|
||||
- Exportacion
|
||||
|
||||
### 6. Dashboard
|
||||
- KPIs: Total lecturas, medidores activos, consumo promedio
|
||||
- Gráficos por proyecto
|
||||
- Últimas alertas
|
||||
### 7. Analytics
|
||||
- **Mapa:** Visualizacion de medidores con coordenadas en mapa Leaflet interactivo
|
||||
- **Reportes:** Dashboard de estadisticas y reportes de consumo
|
||||
- **Servidor:** Metricas del sistema (CPU, memoria, uptime, requests)
|
||||
|
||||
### 8. Conectores Externos
|
||||
- **SH-Meters:** Integracion con sistema de medidores SH
|
||||
- **XMeters:** Integracion con sistema XMeters
|
||||
- **The Things Stack (TTS):** Webhooks LoRaWAN para uplink, join y downlink/ack
|
||||
- Sincronizacion programada a las 9:00 AM
|
||||
- Seguimiento de ultima conexion y estado
|
||||
|
||||
### 9. Gestion de Usuarios
|
||||
- CRUD completo (solo ADMIN)
|
||||
- Asignacion de roles
|
||||
- Asignacion de proyecto
|
||||
- Estados: activo/inactivo
|
||||
- Cambio de contrasena
|
||||
|
||||
### 10. Gestion de Roles
|
||||
- 3 roles predefinidos: ADMIN, OPERATOR, VIEWER
|
||||
- Permisos granulares JSONB por recurso
|
||||
- CRUD de roles (solo ADMIN)
|
||||
- Conteo de usuarios por rol
|
||||
|
||||
### 11. Auditoria
|
||||
- Registro automatico de todas las acciones via middleware
|
||||
- Visor de logs con filtros (solo ADMIN)
|
||||
- Actividad del usuario actual (todos los roles)
|
||||
- Estadisticas de auditoria
|
||||
- Busqueda por registro especifico
|
||||
|
||||
### 12. Notificaciones
|
||||
- Notificaciones in-app
|
||||
- Conteo de no leidas en tiempo real
|
||||
- Marcar como leida (individual y masiva)
|
||||
- Generacion automatica por flujo negativo (cron job)
|
||||
- Dropdown en TopMenu
|
||||
|
||||
### 13. Dark Mode
|
||||
- Soporte completo: Dark / Light / System
|
||||
- Paleta Zinc de Tailwind
|
||||
- Aplicado a todas las paginas, modales, tablas, formularios
|
||||
- Persistencia en localStorage
|
||||
|
||||
### 14. Upload Panel
|
||||
- Aplicacion separada (`upload-panel/`) para carga CSV
|
||||
- Dropzone para archivos
|
||||
- Carga de medidores (upsert)
|
||||
- Carga de lecturas
|
||||
- Descarga de plantillas
|
||||
- Visualizacion de resultados y errores
|
||||
|
||||
---
|
||||
|
||||
## Carga Masiva
|
||||
|
||||
### Medidores (Excel)
|
||||
### Medidores (Excel / CSV)
|
||||
Columnas requeridas:
|
||||
- `serial_number` - Número de serie del medidor (único)
|
||||
- `serial_number` - Numero de serie del medidor (unico)
|
||||
- `name` - Nombre del medidor
|
||||
- `concentrator_serial` - Serial del concentrador existente
|
||||
|
||||
Columnas opcionales:
|
||||
- `meter_id` - ID del medidor
|
||||
- `location` - Ubicación
|
||||
- `location` - Ubicacion
|
||||
- `type` - LORA, LORAWAN, GRANDES (default: LORA)
|
||||
- `status` - ACTIVE, INACTIVE, etc. (default: ACTIVE)
|
||||
- `installation_date` - Fecha de instalación (YYYY-MM-DD)
|
||||
- `installation_date` - Fecha de instalacion (YYYY-MM-DD)
|
||||
|
||||
### Lecturas (Excel)
|
||||
Mapeos automaticos de columnas: `device_s/n` → `serial_number`, `device_name` → `name`, `device_status` → `status`, etc.
|
||||
|
||||
Normalizacion de status: "Installed" → ACTIVE, "New_LoRa" → ACTIVE, "Enabled" → ACTIVE, "Disabled" → INACTIVE.
|
||||
|
||||
### Lecturas (Excel / CSV)
|
||||
Columnas requeridas:
|
||||
- `meter_serial` - Serial del medidor existente
|
||||
- `reading_value` - Valor de la lectura
|
||||
@@ -116,21 +203,12 @@ Columnas requeridas:
|
||||
Columnas opcionales:
|
||||
- `reading_type` - AUTOMATIC, MANUAL, SCHEDULED (default: MANUAL)
|
||||
- `received_at` - Fecha/hora (default: ahora)
|
||||
- `battery_level` - Nivel de batería (%)
|
||||
- `signal_strength` - Intensidad de señal (dBm)
|
||||
- `battery_level` - Nivel de bateria (%)
|
||||
- `signal_strength` - Intensidad de senal (dBm)
|
||||
|
||||
---
|
||||
|
||||
## Credenciales
|
||||
|
||||
### Usuario Admin
|
||||
- **Nombre:** Ivan Alcaraz
|
||||
- **Email:** ialcarazsalazar@consultoria-as.com
|
||||
- **Password:** Aasi940812
|
||||
|
||||
---
|
||||
|
||||
## Datos Actuales en BD
|
||||
## Datos en Base de Datos
|
||||
|
||||
### Proyectos
|
||||
- ADAMANT
|
||||
@@ -152,98 +230,65 @@ Columnas opcionales:
|
||||
|
||||
---
|
||||
|
||||
## Correcciones Recientes (2026-01-23)
|
||||
## Historial de Correcciones
|
||||
|
||||
### 1. Error `.toFixed()` con valores string
|
||||
**Problema:** PostgreSQL devuelve DECIMAL como string, causando error al llamar `.toFixed()`.
|
||||
**Solución:** Convertir a número con `Number()` antes de llamar `.toFixed()`.
|
||||
**Archivos:**
|
||||
- `src/pages/meters/MetersTable.tsx:75`
|
||||
- `src/pages/consumption/ConsumptionPage.tsx:133, 213, 432`
|
||||
### 2026-01-23: Fix pantalla blanca y carga masiva
|
||||
1. **Fix `.toFixed()` con strings** - PostgreSQL devuelve DECIMAL como string. Se envuelve con `Number()`.
|
||||
2. **Fix modal de carga masiva** - Separar recarga de datos del cierre del modal.
|
||||
3. **Fix fechas invalidas en carga masiva** - Validacion de formato con regex + mapeos de columnas + normalizacion de status.
|
||||
|
||||
### 2. Modal de carga masiva se cerraba sin mostrar resultados
|
||||
**Problema:** El modal se cerraba automáticamente después de la carga.
|
||||
**Solución:** El modal ahora permanece abierto para mostrar resultados y errores.
|
||||
**Archivo:** `src/pages/meters/MeterPage.tsx:332-340`
|
||||
### 2026-02-03: Dark mode, Analytics, Conectores, CSV Upload
|
||||
- Implementacion completa de dark mode con paleta Zinc
|
||||
- Seccion Analytics: mapa, reportes, servidor
|
||||
- Seccion Conectores: SH-Meters, XMeters, TTS
|
||||
- Toggle dark/light theme
|
||||
- Panel CSV para carga masiva
|
||||
- Nuevos tipos de medidor: LORA, LORAWAN, GRANDES CONSUMIDORES
|
||||
- Documentacion completa del proyecto
|
||||
|
||||
### 3. Validación de fechas en carga masiva
|
||||
**Problema:** Valores como "Installed" en columnas no mapeadas causaban error de fecha inválida.
|
||||
**Solución:** Validar que `installation_date` sea realmente una fecha antes de insertarla.
|
||||
**Archivo:** `water-api/src/services/bulk-upload.service.ts:183-195`
|
||||
### 2026-02-04: Favicon y conectores
|
||||
- Actualizacion de favicon
|
||||
- Mejoras en tiempo de ultima conexion de conectores
|
||||
- Plan de implementacion para rol ORGANISMOS_OPERADORES
|
||||
|
||||
### 4. Mapeo de columnas mejorado
|
||||
**Mejora:** Agregados más mapeos de columnas comunes (device_status, device_name, etc.)
|
||||
**Archivo:** `water-api/src/services/bulk-upload.service.ts:65-90`
|
||||
|
||||
### 5. Normalización de status
|
||||
**Mejora:** Valores como "Installed", "New_LoRa" se convierten automáticamente a "ACTIVE".
|
||||
**Archivo:** `water-api/src/services/bulk-upload.service.ts:210-225`
|
||||
### 2026-02-05: Sincronizacion de conectores
|
||||
- Cambio de hora de sincronizacion de 2:00 AM a 9:00 AM
|
||||
|
||||
---
|
||||
|
||||
## Comandos Útiles
|
||||
## Comandos Utiles
|
||||
|
||||
```bash
|
||||
# Iniciar backend
|
||||
# Iniciar backend (desarrollo)
|
||||
cd /home/GRH/water-project/water-api
|
||||
npm run dev
|
||||
|
||||
# Iniciar frontend
|
||||
# Iniciar frontend (desarrollo)
|
||||
cd /home/GRH/water-project
|
||||
npm run dev
|
||||
|
||||
# Compilar backend
|
||||
# Iniciar upload panel (desarrollo)
|
||||
cd /home/GRH/water-project/upload-panel
|
||||
npm run dev
|
||||
|
||||
# Compilar backend para produccion
|
||||
cd /home/GRH/water-project/water-api
|
||||
npm run build && npm run start
|
||||
|
||||
# Compilar frontend para produccion
|
||||
cd /home/GRH/water-project
|
||||
npm run build
|
||||
|
||||
# Ver logs del backend
|
||||
tail -f /tmp/water-api.log
|
||||
# Ejecutar schema de base de datos
|
||||
psql -d water_project -f water-api/sql/schema.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Estructura de Archivos
|
||||
## Proximos Pasos Sugeridos
|
||||
|
||||
```
|
||||
water-project/
|
||||
├── src/ # Frontend React
|
||||
│ ├── api/ # Cliente API
|
||||
│ │ ├── client.ts # Cliente HTTP con JWT
|
||||
│ │ ├── meters.ts # API de medidores
|
||||
│ │ ├── readings.ts # API de lecturas
|
||||
│ │ ├── projects.ts # API de proyectos
|
||||
│ │ └── concentrators.ts # API de concentradores
|
||||
│ ├── pages/ # Páginas
|
||||
│ │ ├── meters/ # Módulo de medidores
|
||||
│ │ │ ├── MeterPage.tsx
|
||||
│ │ │ ├── MetersTable.tsx
|
||||
│ │ │ ├── MetersModal.tsx
|
||||
│ │ │ ├── MetersSidebar.tsx
|
||||
│ │ │ ├── MetersBulkUploadModal.tsx
|
||||
│ │ │ └── useMeters.ts
|
||||
│ │ ├── consumption/ # Módulo de consumo
|
||||
│ │ │ ├── ConsumptionPage.tsx
|
||||
│ │ │ └── ReadingsBulkUploadModal.tsx
|
||||
│ │ └── ...
|
||||
│ └── components/ # Componentes reutilizables
|
||||
│
|
||||
└── water-api/ # Backend Node.js
|
||||
├── src/
|
||||
│ ├── controllers/ # Controladores REST
|
||||
│ ├── services/ # Lógica de negocio
|
||||
│ │ ├── bulk-upload.service.ts
|
||||
│ │ └── ...
|
||||
│ ├── routes/ # Definición de rutas
|
||||
│ ├── middleware/ # Middlewares (auth, etc.)
|
||||
│ └── config/ # Configuración (DB, etc.)
|
||||
└── sql/ # Scripts SQL
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Próximos Pasos Sugeridos
|
||||
|
||||
1. **Integración TTS** - Webhooks para The Things Stack
|
||||
2. **Alertas automáticas** - Notificaciones por consumo anormal
|
||||
3. **Reportes** - Generación de reportes PDF
|
||||
4. **Despliegue** - Configurar para producción
|
||||
1. **Rol ORGANISMOS_OPERADORES** - Implementar nuevo rol segun plan existente
|
||||
2. **Reportes PDF** - Generacion y descarga de reportes en PDF
|
||||
3. **Tests** - Suite de tests con Vitest (frontend) y Supertest (backend)
|
||||
4. **CI/CD** - Pipeline de integracion continua
|
||||
5. **Docker** - Containerizacion del proyecto completo
|
||||
|
||||
590
README.md
590
README.md
@@ -1,23 +1,55 @@
|
||||
# Water Project - Sistema de Gestion de Recursos Hidricos (GRH)
|
||||
# GRH - Sistema de Gestion de Recursos Hidricos
|
||||
|
||||
Sistema de gestion y monitoreo de infraestructura hidrica desarrollado con React, TypeScript y Vite.
|
||||
Sistema full-stack de gestion y monitoreo de infraestructura hidrica. Permite administrar medidores de agua, concentradores, proyectos, consumo, lecturas y conectarse con sistemas IoT (LoRaWAN / The Things Stack).
|
||||
|
||||
---
|
||||
|
||||
## Descripcion General
|
||||
|
||||
El **Sistema de Gestion de Recursos Hidricos (GRH)** es una aplicacion web frontend disenada para el monitoreo, administracion y control de infraestructura de toma de agua. Permite gestionar medidores, concentradores, proyectos, usuarios y roles a traves de una interfaz moderna y responsiva.
|
||||
El **Sistema GRH** es una aplicacion web completa para organismos operadores de agua (CESPT Tijuana, Tecate, Mexicali, etc.) que incluye:
|
||||
|
||||
### Caracteristicas Principales
|
||||
|
||||
- **Dashboard interactivo** con KPIs, alertas e historial de actividades
|
||||
- **Gestion de Medidores (Tomas de Agua)** - CRUD completo con filtros por proyecto
|
||||
- **Dashboard interactivo** con KPIs, graficos y alertas
|
||||
- **Gestion de Medidores** - CRUD completo con carga masiva Excel/CSV
|
||||
- **Gestion de Concentradores** - Configuracion de gateways LoRa/LoRaWAN
|
||||
- **Gestion de Proyectos** - Administracion de proyectos de infraestructura
|
||||
- **Gestion de Usuarios y Roles** - Control de acceso al sistema
|
||||
- **Consumo y Lecturas** - Seguimiento historico de lecturas con filtros y exportacion
|
||||
- **Analytics** - Mapa de medidores, reportes y metricas del servidor
|
||||
- **Conectores** - Integracion con SH-Meters, XMeters y The Things Stack
|
||||
- **Usuarios y Roles** - Control de acceso basado en roles (ADMIN, OPERATOR, VIEWER)
|
||||
- **Auditoria** - Registro completo de actividad del sistema
|
||||
- **Notificaciones** - Alertas en tiempo real (flujo negativo, etc.)
|
||||
- **Tema claro/oscuro** - Personalizacion de la interfaz
|
||||
- **Diseno responsive** - Compatible con desktop, tablet y movil
|
||||
|
||||
---
|
||||
|
||||
## Arquitectura
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ FRONTEND (React SPA) │
|
||||
│ http://localhost:5173 │
|
||||
│ React 18 + TypeScript + Vite + Tailwind CSS + MUI │
|
||||
└──────────────────────────┬──────────────────────────────────┘
|
||||
│ REST API (JWT)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ BACKEND (Express API) │
|
||||
│ http://localhost:3000 │
|
||||
│ Express + TypeScript + Zod + Winston + node-cron │
|
||||
└──────────────────────────┬──────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PostgreSQL │
|
||||
│ 10 tablas + 2 vistas + triggers + indices │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Adicionalmente existe un **Upload Panel** (`upload-panel/`) como aplicacion separada para carga masiva de datos via CSV.
|
||||
|
||||
---
|
||||
|
||||
## Stack Tecnologico
|
||||
|
||||
### Frontend
|
||||
@@ -27,13 +59,26 @@ El **Sistema de Gestion de Recursos Hidricos (GRH)** es una aplicacion web front
|
||||
| TypeScript | 5.2.2 | Type safety |
|
||||
| Vite | 5.2.0 | Build tool y dev server |
|
||||
| Tailwind CSS | 4.1.18 | Estilos utility-first |
|
||||
| Material-UI | 7.3.6 | Componentes UI |
|
||||
| Material-UI (MUI) | 7.3.6 | Componentes UI |
|
||||
| MUI X Data Grid | 8.21.0 | Tablas de datos avanzadas |
|
||||
| Recharts | 3.6.0 | Visualizacion de datos |
|
||||
| Leaflet / React-Leaflet | 1.9.4 / 4.2.1 | Mapas interactivos |
|
||||
| Lucide React | 0.559.0 | Iconos SVG |
|
||||
|
||||
### Herramientas de Desarrollo
|
||||
- **ESLint** - Linting de codigo
|
||||
- **TypeScript ESLint** - Analisis estatico
|
||||
### Backend
|
||||
| Tecnologia | Version | Proposito |
|
||||
|------------|---------|-----------|
|
||||
| Express.js | 4.18.2 | Framework HTTP |
|
||||
| TypeScript | 5.3.3 | Type safety |
|
||||
| PostgreSQL (pg) | 8.11.3 | Driver de base de datos |
|
||||
| JWT (jsonwebtoken) | 9.0.2 | Autenticacion con tokens |
|
||||
| Bcrypt | 5.1.1 | Hash de contrasenas |
|
||||
| Zod | 3.22.4 | Validacion de datos |
|
||||
| Helmet | 7.1.0 | Headers de seguridad |
|
||||
| Winston | 3.11.0 | Logging |
|
||||
| Multer | 2.0.2 | Subida de archivos |
|
||||
| XLSX | 0.18.5 | Parseo de archivos Excel |
|
||||
| node-cron | 3.0.3 | Tareas programadas |
|
||||
|
||||
---
|
||||
|
||||
@@ -42,334 +87,357 @@ El **Sistema de Gestion de Recursos Hidricos (GRH)** es una aplicacion web front
|
||||
### Prerrequisitos
|
||||
|
||||
- Node.js >= 18.x
|
||||
- npm >= 9.x o yarn >= 1.22
|
||||
- npm >= 9.x
|
||||
- PostgreSQL >= 14.x
|
||||
|
||||
### Pasos de Instalacion
|
||||
### 1. Clonar el repositorio
|
||||
|
||||
1. **Clonar el repositorio**
|
||||
```bash
|
||||
git clone <url-del-repositorio>
|
||||
cd water-project
|
||||
git clone https://git.consultoria-as.com/consultoria-as/GRH.git
|
||||
cd GRH
|
||||
```
|
||||
|
||||
2. **Instalar dependencias**
|
||||
### 2. Configurar la base de datos
|
||||
|
||||
```bash
|
||||
# Crear la base de datos
|
||||
createdb water_project
|
||||
|
||||
# Ejecutar el schema principal
|
||||
psql -d water_project -f water-api/sql/schema.sql
|
||||
|
||||
# Ejecutar migraciones adicionales
|
||||
psql -d water_project -f water-api/sql/add_audit_logs.sql
|
||||
psql -d water_project -f water-api/sql/add_notifications.sql
|
||||
psql -d water_project -f water-api/sql/add_meter_extended_fields.sql
|
||||
psql -d water_project -f water-api/sql/create_meter_types.sql
|
||||
psql -d water_project -f water-api/sql/add_meter_project_relation.sql
|
||||
psql -d water_project -f water-api/sql/add_user_project_relation.sql
|
||||
```
|
||||
|
||||
### 3. Configurar el backend
|
||||
|
||||
```bash
|
||||
cd water-api
|
||||
cp .env.example .env
|
||||
# Editar .env con las credenciales de PostgreSQL y secretos JWT
|
||||
npm install
|
||||
```
|
||||
|
||||
3. **Configurar variables de entorno**
|
||||
### 4. Configurar el frontend
|
||||
|
||||
```bash
|
||||
cd ..
|
||||
cp .env.example .env
|
||||
# Editar .env con la URL del backend
|
||||
npm install
|
||||
```
|
||||
|
||||
Editar el archivo `.env`:
|
||||
```env
|
||||
VITE_API_BASE_URL=https://tu-api-url.com
|
||||
VITE_API_TOKEN=tu-token-de-api
|
||||
```
|
||||
### 5. Iniciar en desarrollo
|
||||
|
||||
4. **Iniciar servidor de desarrollo**
|
||||
```bash
|
||||
# Terminal 1 - Backend
|
||||
cd water-api
|
||||
npm run dev
|
||||
|
||||
# Terminal 2 - Frontend
|
||||
cd ..
|
||||
npm run dev
|
||||
```
|
||||
|
||||
La aplicacion estara disponible en `http://localhost:5173`
|
||||
El frontend estara disponible en `http://localhost:5173` y el backend en `http://localhost:3000`.
|
||||
|
||||
---
|
||||
|
||||
## Variables de Entorno
|
||||
|
||||
### Frontend (`.env`)
|
||||
| Variable | Descripcion | Ejemplo |
|
||||
|----------|-------------|---------|
|
||||
| `VITE_API_BASE_URL` | URL base del backend | `http://localhost:3000` |
|
||||
|
||||
### Backend (`water-api/.env`)
|
||||
| Variable | Descripcion | Ejemplo |
|
||||
|----------|-------------|---------|
|
||||
| `PORT` | Puerto del servidor | `3000` |
|
||||
| `NODE_ENV` | Entorno | `development` |
|
||||
| `DB_HOST` | Host de PostgreSQL | `localhost` |
|
||||
| `DB_PORT` | Puerto de PostgreSQL | `5432` |
|
||||
| `DB_NAME` | Nombre de la base de datos | `water_project` |
|
||||
| `DB_USER` | Usuario de PostgreSQL | `postgres` |
|
||||
| `DB_PASSWORD` | Contrasena de PostgreSQL | `your_password` |
|
||||
| `JWT_ACCESS_SECRET` | Secreto para access tokens | `random_string` |
|
||||
| `JWT_REFRESH_SECRET` | Secreto para refresh tokens | `random_string` |
|
||||
| `JWT_ACCESS_EXPIRES` | Expiracion access token | `15m` |
|
||||
| `JWT_REFRESH_EXPIRES` | Expiracion refresh token | `7d` |
|
||||
| `CORS_ORIGIN` | Origenes permitidos | `http://localhost:5173` |
|
||||
| `TTS_ENABLED` | Habilitar The Things Stack | `false` |
|
||||
| `TTS_BASE_URL` | URL de TTS | `https://...` |
|
||||
| `TTS_WEBHOOK_SECRET` | Secreto para webhooks TTS | `random_string` |
|
||||
|
||||
---
|
||||
|
||||
## Scripts Disponibles
|
||||
|
||||
### Frontend
|
||||
| Comando | Descripcion |
|
||||
|---------|-------------|
|
||||
| `npm run dev` | Inicia el servidor de desarrollo |
|
||||
| `npm run build` | Compila TypeScript y genera build de produccion |
|
||||
| `npm run preview` | Previsualiza el build de produccion |
|
||||
| `npm run lint` | Ejecuta ESLint en el codigo |
|
||||
| `npm run dev` | Servidor de desarrollo (puerto 5173) |
|
||||
| `npm run build` | Compilar TypeScript + build de produccion |
|
||||
| `npm run preview` | Previsualizar build de produccion |
|
||||
| `npm run lint` | Ejecutar ESLint |
|
||||
|
||||
### Backend (`water-api/`)
|
||||
| Comando | Descripcion |
|
||||
|---------|-------------|
|
||||
| `npm run dev` | Servidor de desarrollo con hot-reload |
|
||||
| `npm run build` | Compilar TypeScript |
|
||||
| `npm run start` | Ejecutar build compilado |
|
||||
| `npm run watch` | Desarrollo con nodemon |
|
||||
|
||||
### Upload Panel (`upload-panel/`)
|
||||
| Comando | Descripcion |
|
||||
|---------|-------------|
|
||||
| `npm run dev` | Servidor de desarrollo |
|
||||
| `npm run build` | Build de produccion |
|
||||
|
||||
---
|
||||
|
||||
## Estructura del Proyecto
|
||||
|
||||
```
|
||||
water-project/
|
||||
├── public/ # Assets estaticos
|
||||
│ └── grhWatermark.jpg
|
||||
│
|
||||
├── src/
|
||||
│ ├── api/ # Capa de comunicacion con API
|
||||
│ │ ├── me.ts # Endpoints de perfil
|
||||
GRH/
|
||||
├── src/ # Frontend React SPA
|
||||
│ ├── api/ # Cliente API (14 modulos)
|
||||
│ │ ├── client.ts # Cliente HTTP con JWT y refresh automatico
|
||||
│ │ ├── auth.ts # Autenticacion y gestion de tokens
|
||||
│ │ ├── meters.ts # CRUD de medidores
|
||||
│ │ ├── concentrators.ts # CRUD de concentradores
|
||||
│ │ └── projects.ts # CRUD de proyectos
|
||||
│ │ ├── readings.ts # Lecturas de consumo
|
||||
│ │ ├── projects.ts # Proyectos
|
||||
│ │ ├── concentrators.ts # Concentradores
|
||||
│ │ ├── users.ts # Usuarios
|
||||
│ │ ├── roles.ts # Roles
|
||||
│ │ ├── analytics.ts # Analytics y metricas
|
||||
│ │ ├── notifications.ts # Notificaciones
|
||||
│ │ ├── audit.ts # Auditoria
|
||||
│ │ ├── me.ts # Perfil de usuario
|
||||
│ │ ├── meterTypes.ts # Tipos de medidor
|
||||
│ │ └── types.ts # Tipos compartidos
|
||||
│ │
|
||||
│ ├── components/
|
||||
│ │ ├── layout/ # Componentes de layout
|
||||
│ │ │ ├── Sidebar.tsx # Menu lateral
|
||||
│ │ │ ├── TopMenu.tsx # Barra superior
|
||||
│ │ │ └── common/ # Componentes reutilizables
|
||||
│ │ │ ├── ProfileModal.tsx
|
||||
│ │ │ ├── ConfirmModal.tsx
|
||||
│ │ │ └── Watermark.tsx
|
||||
│ │ └── SettingsModals.tsx
|
||||
│ ├── components/ # Componentes reutilizables
|
||||
│ │ ├── layout/
|
||||
│ │ │ ├── Sidebar.tsx # Menu lateral (colapsable, pin)
|
||||
│ │ │ ├── TopMenu.tsx # Barra superior con breadcrumb
|
||||
│ │ │ └── common/
|
||||
│ │ │ ├── ProfileModal.tsx # Editar perfil y avatar
|
||||
│ │ │ ├── ConfirmModal.tsx # Confirmacion de acciones
|
||||
│ │ │ ├── Watermark.tsx # Marca de agua GRH
|
||||
│ │ │ └── ProjectBadge.tsx # Badge de proyecto
|
||||
│ │ ├── SettingsModals.tsx # Configuracion de tema/UI
|
||||
│ │ └── NotificationDropdown.tsx # Panel de notificaciones
|
||||
│ │
|
||||
│ ├── pages/ # Paginas principales
|
||||
│ │ ├── Home.tsx # Dashboard
|
||||
│ │ ├── LoginPage.tsx # Login
|
||||
│ ├── pages/
|
||||
│ │ ├── Home.tsx # Dashboard con KPIs y graficos
|
||||
│ │ ├── LoginPage.tsx # Inicio de sesion
|
||||
│ │ ├── UsersPage.tsx # Gestion de usuarios
|
||||
│ │ ├── RolesPage.tsx # Gestion de roles
|
||||
│ │ ├── AuditoriaPage.tsx # Visor de logs de auditoria
|
||||
│ │ ├── projects/
|
||||
│ │ │ └── ProjectsPage.tsx
|
||||
│ │ ├── meters/ # Modulo de medidores
|
||||
│ │ │ ├── MeterPage.tsx
|
||||
│ │ │ ├── useMeters.ts # Hook personalizado
|
||||
│ │ │ ├── MetersTable.tsx
|
||||
│ │ │ ├── MetersModal.tsx
|
||||
│ │ │ └── MetersSidebar.tsx
|
||||
│ │ └── concentrators/ # Modulo de concentradores
|
||||
│ │ ├── ConcentratorsPage.tsx
|
||||
│ │ ├── useConcentrators.ts
|
||||
│ │ ├── ConcentratorsTable.tsx
|
||||
│ │ ├── ConcentratorsModal.tsx
|
||||
│ │ └── ConcentratorsSidebar.tsx
|
||||
│ │ │ ├── MetersSidebar.tsx
|
||||
│ │ │ ├── MetersBulkUploadModal.tsx
|
||||
│ │ │ └── useMeters.ts
|
||||
│ │ ├── concentrators/ # Modulo de concentradores
|
||||
│ │ │ ├── ConcentratorsPage.tsx
|
||||
│ │ │ ├── ConcentratorsTable.tsx
|
||||
│ │ │ ├── ConcentratorsModal.tsx
|
||||
│ │ │ ├── ConcentratorsSidebar.tsx
|
||||
│ │ │ └── useConcentrators.ts
|
||||
│ │ ├── consumption/ # Modulo de consumo
|
||||
│ │ │ ├── ConsumptionPage.tsx
|
||||
│ │ │ └── ReadingsBulkUploadModal.tsx
|
||||
│ │ ├── analytics/ # Modulo de analytics
|
||||
│ │ │ ├── AnalyticsMapPage.tsx
|
||||
│ │ │ ├── AnalyticsReportsPage.tsx
|
||||
│ │ │ ├── AnalyticsServerPage.tsx
|
||||
│ │ │ └── MapComponents.tsx
|
||||
│ │ └── conectores/ # Conectores externos
|
||||
│ │ ├── SHMetersPage.tsx
|
||||
│ │ ├── XMetersPage.tsx
|
||||
│ │ └── TTSPage.tsx
|
||||
│ │
|
||||
│ ├── assets/
|
||||
│ │ └── images/
|
||||
│ │
|
||||
│ ├── App.tsx # Componente raiz
|
||||
│ ├── main.tsx # Punto de entrada
|
||||
│ └── index.css # Estilos globales
|
||||
│ ├── hooks/
|
||||
│ │ └── useNotifications.ts
|
||||
│ ├── App.tsx # Componente raiz (routing + auth)
|
||||
│ ├── main.tsx # Punto de entrada React
|
||||
│ └── index.css # Estilos globales (Tailwind)
|
||||
│
|
||||
├── index.html
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
├── vite.config.ts
|
||||
└── .env.example
|
||||
├── water-api/ # Backend Express API
|
||||
│ ├── src/
|
||||
│ │ ├── index.ts # Setup del servidor Express
|
||||
│ │ ├── config/
|
||||
│ │ │ ├── index.ts # Carga de configuracion
|
||||
│ │ │ └── database.ts # Pool de conexiones PostgreSQL
|
||||
│ │ ├── routes/ # 17 archivos de rutas
|
||||
│ │ ├── controllers/ # Controladores REST
|
||||
│ │ ├── services/ # Logica de negocio (18 modulos)
|
||||
│ │ ├── middleware/
|
||||
│ │ │ ├── auth.middleware.ts # Verificacion JWT
|
||||
│ │ │ ├── audit.middleware.ts # Logging de actividad
|
||||
│ │ │ └── ttsWebhook.middleware.ts
|
||||
│ │ ├── validators/ # Validacion con Zod
|
||||
│ │ ├── utils/
|
||||
│ │ │ ├── jwt.ts # Generacion/verificacion de tokens
|
||||
│ │ │ ├── password.ts # Wrappers de bcrypt
|
||||
│ │ │ └── logger.ts # Configuracion Winston
|
||||
│ │ ├── jobs/
|
||||
│ │ │ └── negativeFlowDetection.ts # Tarea programada
|
||||
│ │ └── types/ # Interfaces TypeScript
|
||||
│ │
|
||||
│ ├── sql/ # Schema y migraciones
|
||||
│ │ ├── schema.sql # Schema principal (10 tablas + 2 vistas)
|
||||
│ │ ├── add_audit_logs.sql
|
||||
│ │ ├── add_notifications.sql
|
||||
│ │ ├── add_meter_extended_fields.sql
|
||||
│ │ ├── create_meter_types.sql
|
||||
│ │ ├── add_meter_project_relation.sql
|
||||
│ │ └── add_user_project_relation.sql
|
||||
│ │
|
||||
│ ├── package.json
|
||||
│ ├── tsconfig.json
|
||||
│ └── .env.example
|
||||
│
|
||||
├── upload-panel/ # App separada para carga CSV
|
||||
│ ├── src/
|
||||
│ │ ├── App.tsx
|
||||
│ │ ├── components/
|
||||
│ │ │ ├── MetersUpload.tsx
|
||||
│ │ │ ├── ReadingsUpload.tsx
|
||||
│ │ │ ├── FileDropzone.tsx
|
||||
│ │ │ └── ResultsDisplay.tsx
|
||||
│ │ └── api/upload.ts
|
||||
│ ├── package.json
|
||||
│ └── vite.config.ts
|
||||
│
|
||||
├── package.json # Dependencias frontend
|
||||
├── vite.config.ts # Configuracion Vite
|
||||
├── tsconfig.json # Configuracion TypeScript
|
||||
├── index.html # HTML de entrada
|
||||
├── DOCUMENTATION.md # Documentacion tecnica
|
||||
├── ESTADO_ACTUAL.md # Estado actual del proyecto
|
||||
└── CAMBIOS_SESION.md # Historial de cambios
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Modulos Funcionales
|
||||
## Base de Datos
|
||||
|
||||
### 1. Dashboard (Home)
|
||||
### Jerarquia de datos
|
||||
```
|
||||
Projects → Concentrators → Meters → Readings
|
||||
→ Gateways → Devices ↗
|
||||
```
|
||||
|
||||
El dashboard principal ofrece:
|
||||
- Selector de organismos operadores (CESPT TIJUANA, TECATE, MEXICALI)
|
||||
- Grafico de barras: "Numero de Medidores por Proyecto"
|
||||
- Tarjetas de acceso rapido: Tomas, Alertas, Mantenimiento, Reportes
|
||||
- Historial reciente de actividades
|
||||
- Panel de ultimas alertas
|
||||
### Tablas principales
|
||||
|
||||
### 2. Gestion de Medidores
|
||||
| Tabla | Descripcion |
|
||||
|-------|-------------|
|
||||
| `roles` | Roles del sistema (ADMIN, OPERATOR, VIEWER) con permisos JSONB |
|
||||
| `users` | Usuarios con email, password hash, rol y estado |
|
||||
| `projects` | Proyectos de infraestructura hidrica |
|
||||
| `concentrators` | Concentradores de datos vinculados a proyectos |
|
||||
| `gateways` | Gateways LoRaWAN con integracion TTS |
|
||||
| `devices` | Dispositivos LoRaWAN (sensores/transmisores) |
|
||||
| `meters` | Medidores de agua con ubicacion y ultima lectura |
|
||||
| `meter_readings` | Historial de lecturas con bateria y senal |
|
||||
| `tts_uplink_logs` | Logs de mensajes uplink de The Things Stack |
|
||||
| `refresh_tokens` | Tokens de refresco JWT para sesiones |
|
||||
|
||||
Modulo completo para administrar medidores/tomas de agua:
|
||||
|
||||
**Funcionalidades:**
|
||||
- Listado con busqueda y filtros
|
||||
- Filtrado por proyecto
|
||||
- Tipos de toma: GENERAL, LORA, LORAWAN, GRANDES
|
||||
- CRUD completo (Crear, Leer, Actualizar, Eliminar)
|
||||
|
||||
**Campos principales:**
|
||||
- Area, Numero de cuenta, Usuario, Direccion
|
||||
- Serial del medidor, Nombre, Estado
|
||||
- Tipo de protocolo, Particion DMA
|
||||
- Configuracion de dispositivo (Device EUI, AppKey, etc.)
|
||||
|
||||
### 3. Gestion de Concentradores
|
||||
|
||||
Administracion de concentradores y gateways:
|
||||
|
||||
**Funcionalidades:**
|
||||
- Listado con filtros por proyecto
|
||||
- Configuracion de Gateway (ID, EUI, Nombre)
|
||||
- Seleccion de ubicacion de antena (Indoor/Outdoor)
|
||||
- CRUD completo
|
||||
|
||||
### 4. Gestion de Proyectos
|
||||
|
||||
Administracion de proyectos de infraestructura:
|
||||
- Tabla con busqueda integrada
|
||||
- Estados: ACTIVE/INACTIVE
|
||||
- Informacion de operador y tiempos
|
||||
|
||||
### 5. Gestion de Usuarios
|
||||
|
||||
Control de usuarios del sistema:
|
||||
- Listado de usuarios
|
||||
- Asignacion de roles
|
||||
- Estados: ACTIVE/INACTIVE
|
||||
|
||||
### 6. Gestion de Roles
|
||||
|
||||
Administracion de roles de acceso:
|
||||
- Roles predefinidos: SUPER_ADMIN, USER
|
||||
- Descripcion de permisos
|
||||
### Vistas
|
||||
- `meter_stats_by_project` - Estadisticas agregadas de medidores por proyecto
|
||||
- `device_status_summary` - Resumen de estados de dispositivos por proyecto
|
||||
|
||||
---
|
||||
|
||||
## API y Comunicacion
|
||||
## API Endpoints
|
||||
|
||||
### Configuracion
|
||||
Todos los endpoints estan bajo el prefijo `/api/`. La mayoria requieren autenticacion JWT.
|
||||
|
||||
La aplicacion se conecta a una API REST externa. Configurar en `.env`:
|
||||
|
||||
```env
|
||||
VITE_API_BASE_URL=https://tu-api.com
|
||||
VITE_API_TOKEN=tu-token
|
||||
```
|
||||
|
||||
### Endpoints Principales
|
||||
|
||||
| Recurso | Endpoint Base |
|
||||
|---------|---------------|
|
||||
| Medidores | `/api/v3/data/.../m4hzpnopjkppaav/records` |
|
||||
| Concentradores | `/api/v3/data/.../mheif1vdgnyt8x2/records` |
|
||||
| Proyectos | `/api/v3/data/.../m9882vn3xb31e29/records` |
|
||||
|
||||
### Estructura de Respuesta
|
||||
|
||||
```typescript
|
||||
interface ApiResponse<T> {
|
||||
records: Array<{
|
||||
id: string;
|
||||
fields: T;
|
||||
}>;
|
||||
next?: string;
|
||||
prev?: string;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Modelos de Datos
|
||||
|
||||
### Meter (Medidor)
|
||||
|
||||
```typescript
|
||||
interface Meter {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
areaName: string;
|
||||
accountNumber: string | null;
|
||||
userName: string | null;
|
||||
userAddress: string | null;
|
||||
meterSerialNumber: string;
|
||||
meterName: string;
|
||||
meterStatus: string;
|
||||
protocolType: string;
|
||||
priceNo: string | null;
|
||||
priceName: string | null;
|
||||
dmaPartition: string | null;
|
||||
supplyTypes: string;
|
||||
deviceId: string;
|
||||
deviceName: string;
|
||||
deviceType: string;
|
||||
usageAnalysisType: string;
|
||||
installedTime: string;
|
||||
}
|
||||
```
|
||||
|
||||
### Concentrator
|
||||
|
||||
```typescript
|
||||
interface Concentrator {
|
||||
id: string;
|
||||
"Area Name": string;
|
||||
"Device S/N": string;
|
||||
"Device Name": string;
|
||||
"Device Time": string;
|
||||
"Device Status": string;
|
||||
"Operator": string;
|
||||
"Installed Time": string;
|
||||
"Communication Time": string;
|
||||
"Instruction Manual": string;
|
||||
}
|
||||
```
|
||||
|
||||
### Project
|
||||
|
||||
```typescript
|
||||
interface Project {
|
||||
id: string;
|
||||
areaName: string;
|
||||
deviceSN: string;
|
||||
deviceName: string;
|
||||
deviceType: string;
|
||||
deviceStatus: "ACTIVE" | "INACTIVE";
|
||||
operator: string;
|
||||
installedTime: string;
|
||||
communicationTime: string;
|
||||
}
|
||||
```
|
||||
| Grupo | Prefijo | Descripcion |
|
||||
|-------|---------|-------------|
|
||||
| Auth | `/api/auth` | Login, refresh, logout, perfil |
|
||||
| Projects | `/api/projects` | CRUD de proyectos + estadisticas |
|
||||
| Meters | `/api/meters` | CRUD de medidores + lecturas |
|
||||
| Meter Types | `/api/meter-types` | Tipos de medidor |
|
||||
| Concentrators | `/api/concentrators` | CRUD de concentradores |
|
||||
| Gateways | `/api/gateways` | CRUD de gateways + dispositivos |
|
||||
| Devices | `/api/devices` | CRUD de dispositivos LoRaWAN |
|
||||
| Users | `/api/users` | Gestion de usuarios (admin) |
|
||||
| Roles | `/api/roles` | Gestion de roles |
|
||||
| Readings | `/api/readings` | Lecturas y resumen de consumo |
|
||||
| Notifications | `/api/notifications` | Notificaciones del usuario |
|
||||
| Audit | `/api/audit-logs` | Logs de auditoria (admin) |
|
||||
| Bulk Upload | `/api/bulk-upload` | Carga masiva Excel |
|
||||
| CSV Upload | `/api/csv-upload` | Carga masiva CSV |
|
||||
| TTS Webhooks | `/api/webhooks/tts` | Webhooks The Things Stack |
|
||||
| System | `/api/system` | Metricas y salud del servidor (admin) |
|
||||
|
||||
---
|
||||
|
||||
## Autenticacion
|
||||
|
||||
### Flujo de Login
|
||||
El sistema usa **JWT con refresh tokens**:
|
||||
|
||||
1. Usuario ingresa credenciales
|
||||
2. Validacion del checkbox "No soy un robot"
|
||||
3. Token almacenado en `localStorage` (`grh_auth`)
|
||||
4. Redireccion al Dashboard
|
||||
1. El usuario envia email/password a `POST /api/auth/login`
|
||||
2. El backend valida credenciales con bcrypt y genera:
|
||||
- **Access token** (15 minutos)
|
||||
- **Refresh token** (7 dias)
|
||||
3. Los tokens se almacenan en `localStorage`
|
||||
4. El cliente HTTP envia el access token en `Authorization: Bearer <token>`
|
||||
5. Al expirar, el cliente automaticamente llama a `POST /api/auth/refresh`
|
||||
|
||||
### Almacenamiento
|
||||
|
||||
```javascript
|
||||
// localStorage keys
|
||||
grh_auth: { token: string, ts: number }
|
||||
water_project_settings_v1: { theme: string, compactMode: boolean }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuracion de Temas
|
||||
|
||||
El sistema soporta tres modos de tema:
|
||||
- **Sistema** - Detecta preferencia del OS
|
||||
- **Claro** - Tema light
|
||||
- **Oscuro** - Tema dark
|
||||
|
||||
Configuracion persistida en `localStorage` bajo `water_project_settings_v1`.
|
||||
### Roles y permisos
|
||||
| Rol | Descripcion |
|
||||
|-----|-------------|
|
||||
| `ADMIN` | Acceso completo al sistema |
|
||||
| `OPERATOR` | Gestiona proyectos, dispositivos, medidores (sin configuracion del sistema) |
|
||||
| `VIEWER` | Solo lectura de datos y reportes |
|
||||
|
||||
---
|
||||
|
||||
## Despliegue
|
||||
|
||||
### Build de Produccion
|
||||
### Build de produccion
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
# Frontend
|
||||
npm run build # Genera dist/
|
||||
|
||||
# Backend
|
||||
cd water-api
|
||||
npm run build # Genera dist/
|
||||
npm run start # Ejecuta el build
|
||||
```
|
||||
|
||||
Los archivos compilados se generan en la carpeta `dist/`.
|
||||
|
||||
### Configuracion de Vite
|
||||
|
||||
El servidor de desarrollo esta configurado para:
|
||||
- Puerto: 5173
|
||||
- Host: habilitado para acceso remoto
|
||||
- Hosts permitidos: localhost, 127.0.0.1, dominios personalizados
|
||||
### URLs de produccion
|
||||
- **Frontend:** `https://sistema.gestionrecursoshidricos.com`
|
||||
- **Backend:** `https://api.gestionrecursoshidricos.com`
|
||||
|
||||
---
|
||||
|
||||
## Contribucion
|
||||
## Repositorios
|
||||
|
||||
1. Fork del repositorio
|
||||
2. Crear rama feature (`git checkout -b feature/nueva-funcionalidad`)
|
||||
3. Commit de cambios (`git commit -m 'Agregar nueva funcionalidad'`)
|
||||
4. Push a la rama (`git push origin feature/nueva-funcionalidad`)
|
||||
5. Crear Pull Request
|
||||
| Remote | URL |
|
||||
|--------|-----|
|
||||
| Gitea | `https://git.consultoria-as.com/consultoria-as/GRH` |
|
||||
| GitHub | `git@github.com:luanngel/water-project.git` |
|
||||
|
||||
---
|
||||
|
||||
## Licencia
|
||||
|
||||
Este proyecto es privado y pertenece a GRH - Gestion de Recursos Hidricos.
|
||||
|
||||
---
|
||||
|
||||
## Contacto
|
||||
|
||||
Para soporte o consultas sobre el sistema, contactar al equipo de desarrollo.
|
||||
Este proyecto es privado y pertenece a GRH - Gestion de Recursos Hidricos / Consultoria AS.
|
||||
|
||||
Reference in New Issue
Block a user