[REMEDIATION] feat: Database schema updates and recreate script enhancement

Major overhaul of drop-and-recreate-database.sh, DDL schema updates,
seed data cleanup. Add utility scripts for auth table fixes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Adrian Flores Cortes 2026-02-05 23:18:19 -06:00
parent a05f7595b4
commit 5f009673aa
8 changed files with 1011 additions and 298 deletions

File diff suppressed because it is too large Load Diff

70
fix_auth_tables.sql Normal file
View File

@ -0,0 +1,70 @@
-- Fix auth tables for erp_construccion_demo
-- 1. Add missing columns to auth.users
ALTER TABLE auth.users ADD COLUMN IF NOT EXISTS roles VARCHAR[] DEFAULT ARRAY['viewer']::VARCHAR[];
ALTER TABLE auth.users ADD COLUMN IF NOT EXISTS default_tenant_id UUID;
ALTER TABLE auth.users ADD COLUMN IF NOT EXISTS last_login_at TIMESTAMPTZ;
ALTER TABLE auth.users ADD COLUMN IF NOT EXISTS username VARCHAR(100);
-- 2. Add missing columns to auth.tenants
ALTER TABLE auth.tenants ADD COLUMN IF NOT EXISTS code VARCHAR(50) UNIQUE;
ALTER TABLE auth.tenants ADD COLUMN IF NOT EXISTS settings JSONB DEFAULT '{}';
ALTER TABLE auth.tenants ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMPTZ;
-- Update tenants code from slug
UPDATE auth.tenants SET code = slug WHERE code IS NULL;
-- 3. Create refresh_tokens table
CREATE TABLE IF NOT EXISTS auth.refresh_tokens (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
token TEXT NOT NULL UNIQUE,
expires_at TIMESTAMPTZ NOT NULL,
revoked_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
user_agent VARCHAR(500),
ip_address VARCHAR(45)
);
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user ON auth.refresh_tokens(user_id);
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_token ON auth.refresh_tokens(token);
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_expires ON auth.refresh_tokens(expires_at);
-- 4. Create test tenant if not exists
INSERT INTO auth.tenants (id, name, slug, code, is_active, created_at, updated_at)
VALUES (
'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
'Test Company',
'test-company',
'test-company',
true,
NOW(),
NOW()
) ON CONFLICT (id) DO NOTHING;
-- 5. Create admin user with password 'Admin123!'
INSERT INTO auth.users (
id, tenant_id, email, password_hash, first_name, last_name,
is_active, email_verified, roles, default_tenant_id, created_at, updated_at
)
VALUES (
'b0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22',
'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
'admin@test.com',
'$2a$10$4M7jT3YmH14xyx3L7uojmuRFyggZcM/qb8A/54B2XXDtYBmVI7/J2',
'Admin',
'User',
true,
true,
ARRAY['admin']::VARCHAR[],
'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
NOW(),
NOW()
) ON CONFLICT (id) DO UPDATE SET
password_hash = '$2a$10$4M7jT3YmH14xyx3L7uojmuRFyggZcM/qb8A/54B2XXDtYBmVI7/J2',
roles = ARRAY['admin']::VARCHAR[],
default_tenant_id = 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11';
-- 6. Verify
SELECT 'Tenant created:', id, name FROM auth.tenants WHERE id = 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11';
SELECT 'User created:', id, email, roles FROM auth.users WHERE email = 'admin@test.com';

21
insert_admin_user.sql Normal file
View File

@ -0,0 +1,21 @@
INSERT INTO auth.users (
id, tenant_id, email, password_hash, first_name, last_name,
is_active, email_verified, roles, default_tenant_id, created_at, updated_at
)
VALUES (
'b0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22',
'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
'admin@test.com',
'$2a$10$4M7jT3YmH14xyx3L7uojmuRFyggZcM/qb8A/54B2XXDtYBmVI7/J2',
'Admin',
'User',
true,
true,
ARRAY['admin']::VARCHAR[],
'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
NOW(),
NOW()
) ON CONFLICT (id) DO UPDATE SET
password_hash = EXCLUDED.password_hash,
roles = EXCLUDED.roles,
default_tenant_id = EXCLUDED.default_tenant_id;

View File

@ -75,10 +75,34 @@ EXCEPTION WHEN duplicate_object THEN NULL; END $$;
-- TABLES - ESTRUCTURA DE PROYECTO -- TABLES - ESTRUCTURA DE PROYECTO
-- ============================================================================ -- ============================================================================
-- Tabla: proyectos (proyectos de desarrollo inmobiliario)
CREATE TABLE IF NOT EXISTS construction.proyectos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
codigo VARCHAR(20) NOT NULL,
nombre VARCHAR(200) NOT NULL,
descripcion TEXT,
direccion TEXT,
ciudad VARCHAR(100),
estado VARCHAR(100),
fecha_inicio DATE,
fecha_fin_estimada DATE,
estado_proyecto VARCHAR(20) NOT NULL DEFAULT 'activo',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_by UUID REFERENCES auth.users(id),
updated_at TIMESTAMPTZ,
updated_by UUID REFERENCES auth.users(id),
deleted_at TIMESTAMPTZ,
deleted_by UUID REFERENCES auth.users(id),
CONSTRAINT uq_proyectos_codigo_tenant UNIQUE (tenant_id, codigo),
CONSTRAINT chk_proyectos_estado CHECK (estado_proyecto IN ('activo', 'pausado', 'completado', 'cancelado'))
);
-- Tabla: fraccionamientos (desarrollo inmobiliario) -- Tabla: fraccionamientos (desarrollo inmobiliario)
CREATE TABLE IF NOT EXISTS construction.fraccionamientos ( CREATE TABLE IF NOT EXISTS construction.fraccionamientos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(), id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE, tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
proyecto_id UUID NOT NULL REFERENCES construction.proyectos(id) ON DELETE CASCADE,
code VARCHAR(20) NOT NULL, code VARCHAR(20) NOT NULL,
name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL,
description TEXT, description TEXT,
@ -739,8 +763,14 @@ CREATE TABLE IF NOT EXISTS construction.contrato_addendas (
-- INDICES -- INDICES
-- ============================================================================ -- ============================================================================
-- Proyectos
CREATE INDEX IF NOT EXISTS idx_proyectos_tenant_id ON construction.proyectos(tenant_id);
CREATE INDEX IF NOT EXISTS idx_proyectos_estado ON construction.proyectos(estado_proyecto);
CREATE INDEX IF NOT EXISTS idx_proyectos_codigo ON construction.proyectos(codigo);
-- Fraccionamientos -- Fraccionamientos
CREATE INDEX IF NOT EXISTS idx_fraccionamientos_tenant_id ON construction.fraccionamientos(tenant_id); CREATE INDEX IF NOT EXISTS idx_fraccionamientos_tenant_id ON construction.fraccionamientos(tenant_id);
CREATE INDEX IF NOT EXISTS idx_fraccionamientos_proyecto_id ON construction.fraccionamientos(proyecto_id);
CREATE INDEX IF NOT EXISTS idx_fraccionamientos_status ON construction.fraccionamientos(status); CREATE INDEX IF NOT EXISTS idx_fraccionamientos_status ON construction.fraccionamientos(status);
CREATE INDEX IF NOT EXISTS idx_fraccionamientos_code ON construction.fraccionamientos(code); CREATE INDEX IF NOT EXISTS idx_fraccionamientos_code ON construction.fraccionamientos(code);
@ -814,6 +844,7 @@ CREATE INDEX IF NOT EXISTS idx_contratos_fraccionamiento_id ON construction.cont
-- ROW LEVEL SECURITY (RLS) -- ROW LEVEL SECURITY (RLS)
-- ============================================================================ -- ============================================================================
ALTER TABLE construction.proyectos ENABLE ROW LEVEL SECURITY;
ALTER TABLE construction.fraccionamientos ENABLE ROW LEVEL SECURITY; ALTER TABLE construction.fraccionamientos ENABLE ROW LEVEL SECURITY;
ALTER TABLE construction.etapas ENABLE ROW LEVEL SECURITY; ALTER TABLE construction.etapas ENABLE ROW LEVEL SECURITY;
ALTER TABLE construction.manzanas ENABLE ROW LEVEL SECURITY; ALTER TABLE construction.manzanas ENABLE ROW LEVEL SECURITY;
@ -840,6 +871,12 @@ ALTER TABLE construction.contratos ENABLE ROW LEVEL SECURITY;
ALTER TABLE construction.contrato_partidas ENABLE ROW LEVEL SECURITY; ALTER TABLE construction.contrato_partidas ENABLE ROW LEVEL SECURITY;
-- Policies de tenant isolation usando current_setting -- Policies de tenant isolation usando current_setting
DO $$ BEGIN
DROP POLICY IF EXISTS tenant_isolation_proyectos ON construction.proyectos;
CREATE POLICY tenant_isolation_proyectos ON construction.proyectos
FOR ALL USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
EXCEPTION WHEN undefined_object THEN NULL; END $$;
DO $$ BEGIN DO $$ BEGIN
DROP POLICY IF EXISTS tenant_isolation_fraccionamientos ON construction.fraccionamientos; DROP POLICY IF EXISTS tenant_isolation_fraccionamientos ON construction.fraccionamientos;
CREATE POLICY tenant_isolation_fraccionamientos ON construction.fraccionamientos CREATE POLICY tenant_isolation_fraccionamientos ON construction.fraccionamientos
@ -989,7 +1026,8 @@ EXCEPTION WHEN undefined_object THEN NULL; END $$;
-- ============================================================================ -- ============================================================================
COMMENT ON SCHEMA construction IS 'Schema de construcción: obras, lotes, avances, calidad, contratos'; COMMENT ON SCHEMA construction IS 'Schema de construcción: obras, lotes, avances, calidad, contratos';
COMMENT ON TABLE construction.fraccionamientos IS 'Desarrollos inmobiliarios/fraccionamientos'; COMMENT ON TABLE construction.proyectos IS 'Proyectos de desarrollo inmobiliario';
COMMENT ON TABLE construction.fraccionamientos IS 'Fraccionamientos/obras dentro de un proyecto';
COMMENT ON TABLE construction.etapas IS 'Etapas/fases de un fraccionamiento'; COMMENT ON TABLE construction.etapas IS 'Etapas/fases de un fraccionamiento';
COMMENT ON TABLE construction.manzanas IS 'Manzanas dentro de una etapa'; COMMENT ON TABLE construction.manzanas IS 'Manzanas dentro de una etapa';
COMMENT ON TABLE construction.lotes IS 'Lotes/terrenos vendibles (horizontal)'; COMMENT ON TABLE construction.lotes IS 'Lotes/terrenos vendibles (horizontal)';
@ -1009,5 +1047,5 @@ COMMENT ON TABLE construction.contratos IS 'Contratos con subcontratistas';
-- ============================================================================ -- ============================================================================
-- FIN DEL SCHEMA CONSTRUCTION -- FIN DEL SCHEMA CONSTRUCTION
-- Total tablas: 24 -- Total tablas: 25 (agregada proyectos)
-- ============================================================================ -- ============================================================================

View File

@ -4,7 +4,7 @@
-- Proyecto: ERP Construcción -- Proyecto: ERP Construcción
-- Autor: Claude Opus 4.5 -- Autor: Claude Opus 4.5
-- Fecha: 2026-02-03 -- Fecha: 2026-02-03
-- Descripción: Tenant demo, sucursales, almacenes, configuración -- Descripción: Tenant demo, sucursales, configuración
-- Dependencias: 01-core-catalogs.sql, 02-users-profiles.sql -- Dependencias: 01-core-catalogs.sql, 02-users-profiles.sql
-- ═══════════════════════════════════════════════════════════════════════════════ -- ═══════════════════════════════════════════════════════════════════════════════
@ -14,7 +14,15 @@
BEGIN; BEGIN;
-- ───────────────────────────────────────────────────────────────────────────────── -- ─────────────────────────────────────────────────────────────────────────────────
-- 1. TENANT (EMPRESA) PRINCIPAL -- 1. TENANT EN auth.tenants (requerido para FK en otros schemas)
-- ─────────────────────────────────────────────────────────────────────────────────
INSERT INTO auth.tenants (id, code, name, is_active, created_at) VALUES
('00000000-0000-0000-0003-000000000001', 'DEMO001', 'Constructora Demo', true, NOW())
ON CONFLICT (id) DO NOTHING;
-- ─────────────────────────────────────────────────────────────────────────────────
-- 2. TENANT (EMPRESA) PRINCIPAL - Datos extendidos en tenants.tenants
-- ───────────────────────────────────────────────────────────────────────────────── -- ─────────────────────────────────────────────────────────────────────────────────
INSERT INTO tenants.tenants ( INSERT INTO tenants.tenants (
@ -53,19 +61,19 @@ INSERT INTO tenants.tenants (
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
-- ───────────────────────────────────────────────────────────────────────────────── -- ─────────────────────────────────────────────────────────────────────────────────
-- 2. CONFIGURACIÓN DEL TENANT -- 3. CONFIGURACIÓN DEL TENANT
-- ───────────────────────────────────────────────────────────────────────────────── -- ─────────────────────────────────────────────────────────────────────────────────
INSERT INTO tenants.tenant_settings (id, tenant_id, setting_key, setting_value, setting_type, created_at) VALUES INSERT INTO tenants.tenant_settings (id, tenant_id, setting_key, setting_value, setting_type, created_at) VALUES
-- General -- General (setting_value es JSONB, strings deben estar entre comillas dobles)
('00000000-0000-0000-0003-000000000101', '00000000-0000-0000-0003-000000000001', ('00000000-0000-0000-0003-000000000101', '00000000-0000-0000-0003-000000000001',
'timezone', 'America/Mexico_City', 'string', NOW()), 'timezone', '"America/Mexico_City"', 'string', NOW()),
('00000000-0000-0000-0003-000000000102', '00000000-0000-0000-0003-000000000001', ('00000000-0000-0000-0003-000000000102', '00000000-0000-0000-0003-000000000001',
'locale', 'es-MX', 'string', NOW()), 'locale', '"es-MX"', 'string', NOW()),
('00000000-0000-0000-0003-000000000103', '00000000-0000-0000-0003-000000000001', ('00000000-0000-0000-0003-000000000103', '00000000-0000-0000-0003-000000000001',
'currency', 'MXN', 'string', NOW()), 'currency', '"MXN"', 'string', NOW()),
('00000000-0000-0000-0003-000000000104', '00000000-0000-0000-0003-000000000001', ('00000000-0000-0000-0003-000000000104', '00000000-0000-0000-0003-000000000001',
'date_format', 'DD/MM/YYYY', 'string', NOW()), 'date_format', '"DD/MM/YYYY"', 'string', NOW()),
-- Construcción -- Construcción
('00000000-0000-0000-0003-000000000110', '00000000-0000-0000-0003-000000000001', ('00000000-0000-0000-0003-000000000110', '00000000-0000-0000-0003-000000000001',
@ -97,193 +105,53 @@ INSERT INTO tenants.tenant_settings (id, tenant_id, setting_key, setting_value,
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
-- ───────────────────────────────────────────────────────────────────────────────── -- ─────────────────────────────────────────────────────────────────────────────────
-- 3. SUCURSALES / BRANCHES -- 4. SUCURSALES / BRANCHES (schema simplificado)
-- ───────────────────────────────────────────────────────────────────────────────── -- ─────────────────────────────────────────────────────────────────────────────────
INSERT INTO tenants.branches ( INSERT INTO tenants.branches (
id, tenant_id, code, name, branch_type, id, tenant_id, code, name,
address_street, address_city, address_state, address_zip, address, city, state,
phone, email, phone,
manager_id, is_main, is_active, created_at
is_headquarters, is_active, created_at
) VALUES ) VALUES
-- Matriz -- Matriz
('00000000-0000-0000-0003-000000000201', '00000000-0000-0000-0003-000000000001', ('00000000-0000-0000-0003-000000000201', '00000000-0000-0000-0003-000000000001',
'MATRIZ', 'Oficinas Corporativas', 'headquarters', 'MATRIZ', 'Oficinas Corporativas',
'Av. Tecnológico 1500, Parque Industrial', 'Aguascalientes', 'Aguascalientes', '20290', 'Av. Tecnológico 1500, Parque Industrial', 'Aguascalientes', 'Aguascalientes',
'+52 449 123 4567', 'matriz@constructorademo.com', '+52 449 123 4567',
'00000000-0000-0000-0002-000000000102', -- director
true, true, NOW()), true, true, NOW()),
-- Sucursal Obra Norte -- Sucursal Obra Norte
('00000000-0000-0000-0003-000000000202', '00000000-0000-0000-0003-000000000001', ('00000000-0000-0000-0003-000000000202', '00000000-0000-0000-0003-000000000001',
'OBRA-NORTE', 'Oficina de Obra - Zona Norte', 'field_office', 'OBRA-NORTE', 'Oficina de Obra - Zona Norte',
'Carr. Panamericana Km 15', 'Aguascalientes', 'Aguascalientes', '20340', 'Carr. Panamericana Km 15', 'Aguascalientes', 'Aguascalientes',
'+52 449 234 5678', 'obranorte@constructorademo.com', '+52 449 234 5678',
'00000000-0000-0000-0002-000000000103', -- gerente1
false, true, NOW()) false, true, NOW())
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
-- ─────────────────────────────────────────────────────────────────────────────────
-- 4. ALMACENES
-- ─────────────────────────────────────────────────────────────────────────────────
INSERT INTO inventory.warehouses (
id, tenant_id, branch_id, code, name, warehouse_type,
address_street, address_city, address_state,
manager_id,
is_default, is_active, created_at
) VALUES
-- Almacén Central (Matriz)
('00000000-0000-0000-0003-000000000301', '00000000-0000-0000-0003-000000000001',
'00000000-0000-0000-0003-000000000201',
'ALM-CENTRAL', 'Almacén Central', 'central',
'Av. Tecnológico 1500', 'Aguascalientes', 'Aguascalientes',
'00000000-0000-0000-0002-000000000106', -- almacenista
true, true, NOW()),
-- Almacén de Obra (Palmas)
('00000000-0000-0000-0003-000000000302', '00000000-0000-0000-0003-000000000001',
'00000000-0000-0000-0003-000000000202',
'ALM-PALMAS', 'Almacén Residencial Las Palmas', 'field',
'Dentro del fraccionamiento Las Palmas', 'Aguascalientes', 'Aguascalientes',
NULL,
false, true, NOW()),
-- Almacén de Obra (Diamante)
('00000000-0000-0000-0003-000000000303', '00000000-0000-0000-0003-000000000001',
'00000000-0000-0000-0003-000000000202',
'ALM-DIAMANTE', 'Almacén Torre Diamante', 'field',
'Torre Diamante, Zona Centro', 'Aguascalientes', 'Aguascalientes',
NULL,
false, true, NOW()),
-- Almacén de Tránsito
('00000000-0000-0000-0003-000000000304', '00000000-0000-0000-0003-000000000001',
'00000000-0000-0000-0003-000000000201',
'ALM-TRANSITO', 'Almacén de Tránsito', 'transit',
'Av. Tecnológico 1500', 'Aguascalientes', 'Aguascalientes',
NULL,
false, true, NOW())
ON CONFLICT (id) DO NOTHING;
-- ─────────────────────────────────────────────────────────────────────────────────
-- 5. ASIGNAR USUARIOS AL TENANT
-- ─────────────────────────────────────────────────────────────────────────────────
INSERT INTO auth.user_tenants (user_id, tenant_id, is_default, is_active, created_at) VALUES
('00000000-0000-0000-0002-000000000101', '00000000-0000-0000-0003-000000000001', true, true, NOW()),
('00000000-0000-0000-0002-000000000102', '00000000-0000-0000-0003-000000000001', true, true, NOW()),
('00000000-0000-0000-0002-000000000103', '00000000-0000-0000-0003-000000000001', true, true, NOW()),
('00000000-0000-0000-0002-000000000104', '00000000-0000-0000-0003-000000000001', true, true, NOW()),
('00000000-0000-0000-0002-000000000105', '00000000-0000-0000-0003-000000000001', true, true, NOW()),
('00000000-0000-0000-0002-000000000106', '00000000-0000-0000-0003-000000000001', true, true, NOW()),
('00000000-0000-0000-0002-000000000107', '00000000-0000-0000-0003-000000000001', true, true, NOW()),
('00000000-0000-0000-0002-000000000108', '00000000-0000-0000-0003-000000000001', true, true, NOW()),
('00000000-0000-0000-0002-000000000109', '00000000-0000-0000-0003-000000000001', true, true, NOW()),
('00000000-0000-0000-0002-000000000110', '00000000-0000-0000-0003-000000000001', true, true, NOW()),
('00000000-0000-0000-0002-000000000111', '00000000-0000-0000-0003-000000000001', true, true, NOW()),
('00000000-0000-0000-0002-000000000112', '00000000-0000-0000-0003-000000000001', true, true, NOW())
ON CONFLICT DO NOTHING;
-- ─────────────────────────────────────────────────────────────────────────────────
-- 6. PERFILES DE USUARIO (Datos adicionales)
-- ─────────────────────────────────────────────────────────────────────────────────
INSERT INTO profiles.user_profiles (
id, user_id, tenant_id,
phone, mobile, job_title, department,
avatar_url, bio,
preferences,
created_at
) VALUES
('00000000-0000-0000-0003-000000000401', '00000000-0000-0000-0002-000000000101', '00000000-0000-0000-0003-000000000001',
'+52 449 100 0001', '+52 449 200 0001', 'Administrador del Sistema', 'TI',
'/avatars/admin.png', 'Administrador general del sistema ERP',
'{"theme": "light", "notifications": true}'::jsonb, NOW()),
('00000000-0000-0000-0003-000000000402', '00000000-0000-0000-0002-000000000102', '00000000-0000-0000-0003-000000000001',
'+52 449 100 0002', '+52 449 200 0002', 'Director General', 'Dirección',
'/avatars/director.png', 'Director General de Constructora Demo',
'{"theme": "light", "notifications": true}'::jsonb, NOW()),
('00000000-0000-0000-0003-000000000403', '00000000-0000-0000-0002-000000000103', '00000000-0000-0000-0003-000000000001',
'+52 449 100 0003', '+52 449 200 0003', 'Gerente de Proyectos', 'Construcción',
'/avatars/gerente.png', 'Gerente de proyectos con 15 años de experiencia',
'{"theme": "light", "notifications": true}'::jsonb, NOW()),
('00000000-0000-0000-0003-000000000404', '00000000-0000-0000-0002-000000000104', '00000000-0000-0000-0003-000000000001',
'+52 449 100 0004', '+52 449 200 0004', 'Residente de Obra', 'Construcción',
'/avatars/residente.png', 'Residente de obra certificado CMIC',
'{"theme": "dark", "notifications": true}'::jsonb, NOW()),
('00000000-0000-0000-0003-000000000405', '00000000-0000-0000-0002-000000000105', '00000000-0000-0000-0003-000000000001',
'+52 449 100 0005', '+52 449 200 0005', 'Supervisor de Campo', 'Construcción',
'/avatars/supervisor.png', 'Supervisor con experiencia en obra residencial',
'{"theme": "dark", "notifications": true}'::jsonb, NOW()),
('00000000-0000-0000-0003-000000000406', '00000000-0000-0000-0002-000000000106', '00000000-0000-0000-0003-000000000001',
'+52 449 100 0006', '+52 449 200 0006', 'Jefe de Almacén', 'Logística',
'/avatars/almacen.png', 'Responsable de control de inventarios',
'{"theme": "light", "notifications": true}'::jsonb, NOW()),
('00000000-0000-0000-0003-000000000407', '00000000-0000-0000-0002-000000000107', '00000000-0000-0000-0003-000000000001',
'+52 449 100 0007', '+52 449 200 0007', 'Contador General', 'Finanzas',
'/avatars/contador.png', 'CPA con especialidad en construcción',
'{"theme": "light", "notifications": true}'::jsonb, NOW()),
('00000000-0000-0000-0003-000000000408', '00000000-0000-0000-0002-000000000108', '00000000-0000-0000-0003-000000000001',
'+52 449 100 0008', '+52 449 200 0008', 'Coordinador de RRHH', 'Recursos Humanos',
'/avatars/rrhh.png', 'Especialista en gestión de personal de construcción',
'{"theme": "light", "notifications": true}'::jsonb, NOW()),
('00000000-0000-0000-0003-000000000409', '00000000-0000-0000-0002-000000000109', '00000000-0000-0000-0003-000000000001',
'+52 449 100 0009', '+52 449 200 0009', 'Coordinador HSE', 'Seguridad',
'/avatars/hse.png', 'Certificado STPS en seguridad industrial',
'{"theme": "light", "notifications": true}'::jsonb, NOW()),
('00000000-0000-0000-0003-000000000410', '00000000-0000-0000-0002-000000000110', '00000000-0000-0000-0003-000000000001',
'+52 449 100 0010', '+52 449 200 0010', 'Inspector de Calidad', 'Calidad',
'/avatars/calidad.png', 'Inspector certificado ISO 9001',
'{"theme": "light", "notifications": true}'::jsonb, NOW()),
('00000000-0000-0000-0003-000000000411', '00000000-0000-0000-0002-000000000111', '00000000-0000-0000-0003-000000000001',
'+52 449 100 0011', '+52 449 200 0011', 'Comprador', 'Compras',
'/avatars/compras.png', 'Especialista en compras de construcción',
'{"theme": "light", "notifications": true}'::jsonb, NOW()),
('00000000-0000-0000-0003-000000000412', '00000000-0000-0000-0002-000000000112', '00000000-0000-0000-0003-000000000001',
'+52 449 100 0012', '+52 449 200 0012', 'Cliente', 'Externo',
'/avatars/cliente.png', 'Cliente del fraccionamiento Las Palmas',
'{"theme": "light", "notifications": true}'::jsonb, NOW())
ON CONFLICT (id) DO NOTHING;
-- ───────────────────────────────────────────────────────────────────────────────── -- ─────────────────────────────────────────────────────────────────────────────────
-- VERIFICACIÓN -- VERIFICACIÓN
-- ───────────────────────────────────────────────────────────────────────────────── -- ─────────────────────────────────────────────────────────────────────────────────
DO $$ DO $$
DECLARE DECLARE
v_auth_tenants INTEGER;
v_tenants INTEGER; v_tenants INTEGER;
v_settings INTEGER;
v_branches INTEGER; v_branches INTEGER;
v_warehouses INTEGER;
v_user_tenants INTEGER;
v_profiles INTEGER;
BEGIN BEGIN
SELECT COUNT(*) INTO v_auth_tenants FROM auth.tenants;
SELECT COUNT(*) INTO v_tenants FROM tenants.tenants; SELECT COUNT(*) INTO v_tenants FROM tenants.tenants;
SELECT COUNT(*) INTO v_settings FROM tenants.tenant_settings;
SELECT COUNT(*) INTO v_branches FROM tenants.branches; SELECT COUNT(*) INTO v_branches FROM tenants.branches;
SELECT COUNT(*) INTO v_warehouses FROM inventory.warehouses;
SELECT COUNT(*) INTO v_user_tenants FROM auth.user_tenants;
SELECT COUNT(*) INTO v_profiles FROM profiles.user_profiles;
RAISE NOTICE '══════════════════════════════════════════════════════════════'; RAISE NOTICE '══════════════════════════════════════════════════════════════';
RAISE NOTICE 'SEED 03 - EMPRESA Y ESTRUCTURA - COMPLETADO'; RAISE NOTICE 'SEED 03 - EMPRESA Y ESTRUCTURA - COMPLETADO';
RAISE NOTICE '══════════════════════════════════════════════════════════════'; RAISE NOTICE '══════════════════════════════════════════════════════════════';
RAISE NOTICE 'Tenants (empresas): %', v_tenants; RAISE NOTICE 'Tenants (auth): %', v_auth_tenants;
RAISE NOTICE 'Tenants (extendido): %', v_tenants;
RAISE NOTICE 'Configuraciones: %', v_settings;
RAISE NOTICE 'Sucursales: %', v_branches; RAISE NOTICE 'Sucursales: %', v_branches;
RAISE NOTICE 'Almacenes: %', v_warehouses;
RAISE NOTICE 'Usuarios asignados a tenant: %', v_user_tenants;
RAISE NOTICE 'Perfiles de usuario: %', v_profiles;
RAISE NOTICE '══════════════════════════════════════════════════════════════'; RAISE NOTICE '══════════════════════════════════════════════════════════════';
END $$; END $$;

View File

@ -103,7 +103,7 @@ ON CONFLICT (id) DO NOTHING;
INSERT INTO construction.etapas ( INSERT INTO construction.etapas (
id, tenant_id, fraccionamiento_id, code, name, sequence, status, id, tenant_id, fraccionamiento_id, code, name, sequence, status,
total_lots, start_date, end_date, total_lots, start_date, expected_end_date,
created_at, created_by created_at, created_by
) VALUES ) VALUES
-- Las Palmas - 3 etapas -- Las Palmas - 3 etapas

1
temp_update_hash.sql Normal file
View File

@ -0,0 +1 @@
UPDATE auth.users SET password_hash = '$2a$10$4M7jT3YmH14xyx3L7uojmuRFyggZcM/qb8A/54B2XXDtYBmVI7/J2' WHERE email = 'admin@test.com';

1
update_password.sql Normal file
View File

@ -0,0 +1 @@
UPDATE auth.users SET password_hash = '$2a$10$VLsmoNy6WLdlTGuW1WESFeLDEm2aspa52651R8oJfhRfpNkF/70ii' WHERE email = 'admin@test.com';