Add 3-level role permissions, organismos operadores, and Histórico de Tomas page
Implements the full ADMIN → ORGANISMO_OPERADOR → OPERATOR permission hierarchy with scope-filtered data access across all backend services. Adds organismos operadores management (ADMIN only) and a new Histórico page for viewing per-meter reading history with chart, consumption stats, and CSV export. Key changes: - Backend: 3-level scope filtering on all services (meters, readings, projects, users) - Backend: Protect GET /meters routes with authenticateToken for role-based filtering - Backend: Pass requestingUser to reading service for scoped meter readings - Frontend: New HistoricoPage with meter selector, AreaChart, paginated table - Frontend: Consumption cards (Actual, Pasado, Diferencial) above date filters - Frontend: Meter search by name, serial, location, CESPT account, cadastral key - Frontend: OrganismosPage, updated Sidebar with 3-level visibility - SQL migrations for organismos_operadores table and FK columns Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
66
water-api/sql/add_organismos_operadores.sql
Normal file
66
water-api/sql/add_organismos_operadores.sql
Normal file
@@ -0,0 +1,66 @@
|
||||
-- ============================================
|
||||
-- Migration: Add Organismos Operadores (3-level hierarchy)
|
||||
-- Admin → Organismo Operador → Operador
|
||||
-- ============================================
|
||||
|
||||
-- 1. Add ORGANISMO_OPERADOR to role_name ENUM
|
||||
-- NOTE: ALTER TYPE ADD VALUE cannot run inside a transaction block
|
||||
ALTER TYPE role_name ADD VALUE IF NOT EXISTS 'ORGANISMO_OPERADOR';
|
||||
|
||||
-- 2. Create organismos_operadores table
|
||||
CREATE TABLE IF NOT EXISTS organismos_operadores (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
region VARCHAR(255),
|
||||
contact_name VARCHAR(255),
|
||||
contact_email VARCHAR(255),
|
||||
is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Add updated_at trigger
|
||||
CREATE TRIGGER set_organismos_operadores_updated_at
|
||||
BEFORE UPDATE ON organismos_operadores
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- Index for active organismos
|
||||
CREATE INDEX IF NOT EXISTS idx_organismos_operadores_active ON organismos_operadores (is_active);
|
||||
|
||||
-- 3. Add organismo_operador_id FK to projects table
|
||||
ALTER TABLE projects
|
||||
ADD COLUMN IF NOT EXISTS organismo_operador_id UUID REFERENCES organismos_operadores(id) ON DELETE SET NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_projects_organismo_operador_id ON projects (organismo_operador_id);
|
||||
|
||||
-- 4. Add organismo_operador_id FK to users table
|
||||
ALTER TABLE users
|
||||
ADD COLUMN IF NOT EXISTS organismo_operador_id UUID REFERENCES organismos_operadores(id) ON DELETE SET NULL;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_users_organismo_operador_id ON users (organismo_operador_id);
|
||||
|
||||
-- 5. Insert ORGANISMO_OPERADOR role with permissions
|
||||
INSERT INTO roles (name, description, permissions)
|
||||
SELECT
|
||||
'ORGANISMO_OPERADOR',
|
||||
'Organismo operador que gestiona proyectos y operadores dentro de su jurisdicción',
|
||||
'["projects:read", "projects:list", "concentrators:read", "concentrators:list", "meters:read", "meters:write", "meters:list", "readings:read", "readings:list", "users:read", "users:write", "users:list"]'::jsonb
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM roles WHERE name = 'ORGANISMO_OPERADOR'
|
||||
);
|
||||
|
||||
-- 6. Migrate VIEWER users to OPERATOR role
|
||||
UPDATE users
|
||||
SET role_id = (SELECT id FROM roles WHERE name = 'OPERATOR' LIMIT 1)
|
||||
WHERE role_id = (SELECT id FROM roles WHERE name = 'VIEWER' LIMIT 1);
|
||||
|
||||
-- 7. Seed example organismos operadores
|
||||
INSERT INTO organismos_operadores (name, description, region, contact_name, contact_email)
|
||||
SELECT 'CESPT', 'Comisión Estatal de Servicios Públicos de Tijuana', 'Tijuana, BC', 'Admin CESPT', 'admin@cespt.gob.mx'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM organismos_operadores WHERE name = 'CESPT');
|
||||
|
||||
INSERT INTO organismos_operadores (name, description, region, contact_name, contact_email)
|
||||
SELECT 'XICALI', 'Organismo Operador de Mexicali', 'Mexicali, BC', 'Admin XICALI', 'admin@xicali.gob.mx'
|
||||
WHERE NOT EXISTS (SELECT 1 FROM organismos_operadores WHERE name = 'XICALI');
|
||||
11
water-api/sql/add_user_meter_fields.sql
Normal file
11
water-api/sql/add_user_meter_fields.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
-- Add new fields to users table
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS phone VARCHAR(20);
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS street VARCHAR(255);
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS city VARCHAR(100);
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS state VARCHAR(100);
|
||||
ALTER TABLE users ADD COLUMN IF NOT EXISTS zip_code VARCHAR(10);
|
||||
|
||||
-- Add new fields to meters table
|
||||
ALTER TABLE meters ADD COLUMN IF NOT EXISTS address TEXT;
|
||||
ALTER TABLE meters ADD COLUMN IF NOT EXISTS cespt_account VARCHAR(50);
|
||||
ALTER TABLE meters ADD COLUMN IF NOT EXISTS cadastral_key VARCHAR(50);
|
||||
Reference in New Issue
Block a user