diff --git a/seeds/dev/02b-hr-employees.sql b/seeds/dev/02b-hr-employees.sql new file mode 100644 index 0000000..04e8f7c --- /dev/null +++ b/seeds/dev/02b-hr-employees.sql @@ -0,0 +1,279 @@ +-- ═══════════════════════════════════════════════════════════════════════════════ +-- SEED 02b: PUESTOS Y EMPLEADOS +-- ═══════════════════════════════════════════════════════════════════════════════ +-- Proyecto: ERP Construcción +-- Autor: Claude Opus 4.5 +-- Fecha: 2026-02-03 +-- Descripción: Puestos de trabajo y empleados para demo HSE y RRHH +-- Dependencias: 02-users-profiles.sql, 03-empresa-tenant.sql +-- Nota: Requerido por HSE para asignaciones de EPP y capacitaciones +-- ═══════════════════════════════════════════════════════════════════════════════ + +-- UUIDs: 00000000-0000-0000-002b-XXXXXXXXXXXX + +BEGIN; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- 1. PUESTOS DE TRABAJO +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO hr.puestos ( + id, tenant_id, codigo, nombre, descripcion, + nivel_riesgo, requiere_capacitacion_especial, activo, + created_at +) VALUES +-- Administración +('00000000-0000-0000-002b-000000000001', '00000000-0000-0000-0003-000000000001', + 'PTO-DIR', 'Director General', 'Máxima autoridad ejecutiva', + 'bajo', false, true, NOW()), + +('00000000-0000-0000-002b-000000000002', '00000000-0000-0000-0003-000000000001', + 'PTO-GER', 'Gerente de Proyectos', 'Responsable de múltiples proyectos', + 'bajo', false, true, NOW()), + +('00000000-0000-0000-002b-000000000003', '00000000-0000-0000-0003-000000000001', + 'PTO-ADM', 'Administrativo', 'Personal de oficina y administración', + 'bajo', false, true, NOW()), + +-- Obra +('00000000-0000-0000-002b-000000000004', '00000000-0000-0000-0003-000000000001', + 'PTO-RES', 'Residente de Obra', 'Responsable directo de una obra', + 'medio', true, true, NOW()), + +('00000000-0000-0000-002b-000000000005', '00000000-0000-0000-0003-000000000001', + 'PTO-SUP', 'Supervisor de Campo', 'Supervisa trabajos de campo', + 'alto', true, true, NOW()), + +('00000000-0000-0000-002b-000000000006', '00000000-0000-0000-0003-000000000001', + 'PTO-ALB', 'Albañil', 'Trabajos de albañilería y acabados', + 'alto', true, true, NOW()), + +('00000000-0000-0000-002b-000000000007', '00000000-0000-0000-0003-000000000001', + 'PTO-FIE', 'Fierrero', 'Armado y habilitado de acero', + 'alto', true, true, NOW()), + +('00000000-0000-0000-002b-000000000008', '00000000-0000-0000-0003-000000000001', + 'PTO-CAR', 'Carpintero', 'Cimbra y trabajos de carpintería', + 'alto', true, true, NOW()), + +('00000000-0000-0000-002b-000000000009', '00000000-0000-0000-0003-000000000001', + 'PTO-ELE', 'Electricista', 'Instalaciones eléctricas', + 'alto', true, true, NOW()), + +('00000000-0000-0000-002b-000000000010', '00000000-0000-0000-0003-000000000001', + 'PTO-PLO', 'Plomero', 'Instalaciones hidráulicas y sanitarias', + 'medio', true, true, NOW()), + +('00000000-0000-0000-002b-000000000011', '00000000-0000-0000-0003-000000000001', + 'PTO-OPE', 'Operador de Maquinaria', 'Opera maquinaria pesada', + 'alto', true, true, NOW()), + +('00000000-0000-0000-002b-000000000012', '00000000-0000-0000-0003-000000000001', + 'PTO-AYU', 'Ayudante General', 'Apoyo en diversas actividades', + 'medio', true, true, NOW()), + +-- Especializados +('00000000-0000-0000-002b-000000000013', '00000000-0000-0000-0003-000000000001', + 'PTO-HSE', 'Coordinador HSE', 'Seguridad, salud y medio ambiente', + 'medio', true, true, NOW()), + +('00000000-0000-0000-002b-000000000014', '00000000-0000-0000-0003-000000000001', + 'PTO-CAL', 'Inspector de Calidad', 'Control de calidad en obra', + 'bajo', false, true, NOW()), + +('00000000-0000-0000-002b-000000000015', '00000000-0000-0000-0003-000000000001', + 'PTO-ALM', 'Almacenista', 'Control de almacén e inventarios', + 'bajo', false, true, NOW()) +ON CONFLICT (id) DO NOTHING; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- 2. EMPLEADOS DEMO +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO hr.employees ( + id, tenant_id, codigo, nombre, apellido_paterno, apellido_materno, + curp, rfc, nss, fecha_nacimiento, genero, + email, telefono, + fecha_ingreso, puesto_id, departamento, tipo_contrato, salario_diario, + estado, created_at, created_by +) VALUES +-- Personal administrativo vinculado a usuarios +('00000000-0000-0000-002b-000000000101', '00000000-0000-0000-0003-000000000001', + 'EMP-001', 'Juan Carlos', 'Director', 'Méndez', + 'DIMJ800515HAGRXN01', 'DIMJ800515ABC', '12345678901', '1980-05-15', 'M', + 'director@demo.com', '+52 449 200 0002', + '2020-01-15', '00000000-0000-0000-002b-000000000001', 'Dirección', 'indefinido', 5000.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000102', '00000000-0000-0000-0003-000000000001', + 'EMP-002', 'María Elena', 'Gerente', 'Torres', + 'GETM850320MAGRRL02', 'GETM850320ABC', '12345678902', '1985-03-20', 'F', + 'gerente1@demo.com', '+52 449 200 0003', + '2021-03-01', '00000000-0000-0000-002b-000000000002', 'Construcción', 'indefinido', 3500.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000103', '00000000-0000-0000-0003-000000000001', + 'EMP-003', 'Carlos Alberto', 'Residente', 'López', + 'RELC880810HAGSPS03', 'RELC880810ABC', '12345678903', '1988-08-10', 'M', + 'residente1@demo.com', '+52 449 200 0004', + '2022-06-15', '00000000-0000-0000-002b-000000000004', 'Construcción', 'indefinido', 2500.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000104', '00000000-0000-0000-0003-000000000001', + 'EMP-004', 'Ana María', 'Supervisora', 'García', + 'SAGA900125MASPRN04', 'SAGA900125ABC', '12345678904', '1990-01-25', 'F', + 'supervisor1@demo.com', '+52 449 200 0005', + '2022-08-01', '00000000-0000-0000-002b-000000000005', 'Construcción', 'indefinido', 2000.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000105', '00000000-0000-0000-0003-000000000001', + 'EMP-005', 'Elena Patricia', 'Seguridad', 'Sánchez', + 'SASE870605MASGLN05', 'SASE870605ABC', '12345678905', '1987-06-05', 'F', + 'hse1@demo.com', '+52 449 200 0009', + '2023-01-10', '00000000-0000-0000-002b-000000000013', 'HSE', 'indefinido', 2200.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000106', '00000000-0000-0000-0003-000000000001', + 'EMP-006', 'Diego Armando', 'Calidad', 'Rodríguez', + 'CARD850715HASLDS06', 'CARD850715ABC', '12345678906', '1985-07-15', 'M', + 'calidad1@demo.com', '+52 449 200 0010', + '2023-02-01', '00000000-0000-0000-002b-000000000014', 'Calidad', 'indefinido', 2000.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +-- Personal de obra (sin usuario del sistema) +('00000000-0000-0000-002b-000000000107', '00000000-0000-0000-0003-000000000001', + 'EMP-007', 'Roberto', 'Martínez', 'Hernández', + 'MAHR750420HASRRB07', 'MAHR750420ABC', '12345678907', '1975-04-20', 'M', + NULL, '+52 449 300 0001', + '2023-03-15', '00000000-0000-0000-002b-000000000006', 'Construcción', 'obra_determinada', 450.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000108', '00000000-0000-0000-0003-000000000001', + 'EMP-008', 'José Luis', 'Pérez', 'Gómez', + 'PEGJ800830HASPRX08', 'PEGJ800830ABC', '12345678908', '1980-08-30', 'M', + NULL, '+52 449 300 0002', + '2023-04-01', '00000000-0000-0000-002b-000000000007', 'Construcción', 'obra_determinada', 500.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000109', '00000000-0000-0000-0003-000000000001', + 'EMP-009', 'Francisco', 'López', 'Ruiz', + 'LORF780315HASPPR09', 'LORF780315ABC', '12345678909', '1978-03-15', 'M', + NULL, '+52 449 300 0003', + '2023-04-15', '00000000-0000-0000-002b-000000000008', 'Construcción', 'obra_determinada', 480.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000110', '00000000-0000-0000-0003-000000000001', + 'EMP-010', 'Miguel Ángel', 'Jiménez', 'Morales', + 'JIMM850912HASMGR10', 'JIMM850912ABC', '12345678910', '1985-09-12', 'M', + NULL, '+52 449 300 0004', + '2023-05-01', '00000000-0000-0000-002b-000000000009', 'Construcción', 'indefinido', 550.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000111', '00000000-0000-0000-0003-000000000001', + 'EMP-011', 'Ricardo', 'Sánchez', 'Flores', + 'SAFR820607HASSNC11', 'SAFR820607ABC', '12345678911', '1982-06-07', 'M', + NULL, '+52 449 300 0005', + '2023-05-15', '00000000-0000-0000-002b-000000000010', 'Construcción', 'indefinido', 520.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000112', '00000000-0000-0000-0003-000000000001', + 'EMP-012', 'Jesús Manuel', 'Herrera', 'Castro', + 'HECJ901225HASRRS12', 'HECJ901225ABC', '12345678912', '1990-12-25', 'M', + NULL, '+52 449 300 0006', + '2023-06-01', '00000000-0000-0000-002b-000000000011', 'Construcción', 'indefinido', 700.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000113', '00000000-0000-0000-0003-000000000001', + 'EMP-013', 'Pedro', 'Ramírez', 'Díaz', + 'RADP950503HASPRD13', 'RADP950503ABC', '12345678913', '1995-05-03', 'M', + NULL, '+52 449 300 0007', + '2024-01-15', '00000000-0000-0000-002b-000000000012', 'Construcción', 'obra_determinada', 350.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000114', '00000000-0000-0000-0003-000000000001', + 'EMP-014', 'Juan Pablo', 'Vargas', 'Mendoza', + 'VAMJ970817HASRGN14', 'VAMJ970817ABC', '12345678914', '1997-08-17', 'M', + NULL, '+52 449 300 0008', + '2024-02-01', '00000000-0000-0000-002b-000000000012', 'Construcción', 'obra_determinada', 350.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101'), + +('00000000-0000-0000-002b-000000000115', '00000000-0000-0000-0003-000000000001', + 'EMP-015', 'Marco Antonio', 'Ortiz', 'Luna', + 'OILM880422HASRTN15', 'OILM880422ABC', '12345678915', '1988-04-22', 'M', + NULL, '+52 449 300 0009', + '2024-03-01', '00000000-0000-0000-002b-000000000006', 'Construcción', 'obra_determinada', 450.00, + 'activo', NOW(), '00000000-0000-0000-0002-000000000101') +ON CONFLICT (id) DO NOTHING; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- 3. ASIGNACIÓN DE EMPLEADOS A FRACCIONAMIENTOS +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO hr.employee_fraccionamientos ( + id, tenant_id, employee_id, fraccionamiento_id, + fecha_inicio, fecha_fin, rol, activo, + created_at +) VALUES +-- Las Palmas +('00000000-0000-0000-002b-000000000201', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000103', '00000000-0000-0000-0004-000000000101', + '2024-03-01', NULL, 'Residente', true, NOW()), + +('00000000-0000-0000-002b-000000000202', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000104', '00000000-0000-0000-0004-000000000101', + '2024-03-01', NULL, 'Supervisor', true, NOW()), + +('00000000-0000-0000-002b-000000000203', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000105', '00000000-0000-0000-0004-000000000101', + '2024-03-01', NULL, 'HSE', true, NOW()), + +('00000000-0000-0000-002b-000000000204', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000107', '00000000-0000-0000-0004-000000000101', + '2024-03-15', NULL, 'Albañil', true, NOW()), + +('00000000-0000-0000-002b-000000000205', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000108', '00000000-0000-0000-0004-000000000101', + '2024-04-01', NULL, 'Fierrero', true, NOW()), + +('00000000-0000-0000-002b-000000000206', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000112', '00000000-0000-0000-0004-000000000101', + '2024-03-01', NULL, 'Operador', true, NOW()), + +-- Torre Diamante +('00000000-0000-0000-002b-000000000207', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000105', '00000000-0000-0000-0004-000000000102', + '2024-06-01', NULL, 'HSE', true, NOW()), + +('00000000-0000-0000-002b-000000000208', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000110', '00000000-0000-0000-0004-000000000102', + '2024-06-01', NULL, 'Electricista', true, NOW()) +ON CONFLICT (id) DO NOTHING; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- VERIFICACIÓN +-- ───────────────────────────────────────────────────────────────────────────────── + +DO $$ +DECLARE + v_puestos INTEGER; + v_empleados INTEGER; + v_asignaciones INTEGER; +BEGIN + SELECT COUNT(*) INTO v_puestos FROM hr.puestos; + SELECT COUNT(*) INTO v_empleados FROM hr.employees; + SELECT COUNT(*) INTO v_asignaciones FROM hr.employee_fraccionamientos; + + RAISE NOTICE '══════════════════════════════════════════════════════════════'; + RAISE NOTICE 'SEED 02b - HR EMPLOYEES - COMPLETADO'; + RAISE NOTICE '══════════════════════════════════════════════════════════════'; + RAISE NOTICE 'Puestos: %', v_puestos; + RAISE NOTICE 'Empleados: %', v_empleados; + RAISE NOTICE 'Asignaciones a obra: %', v_asignaciones; + RAISE NOTICE '══════════════════════════════════════════════════════════════'; +END $$; + +COMMIT; + +-- ═══════════════════════════════════════════════════════════════════════════════ +-- FIN SEED 02b +-- ═══════════════════════════════════════════════════════════════════════════════ diff --git a/seeds/dev/06-estimaciones.sql b/seeds/dev/06-estimaciones.sql index c0c13d2..ce40e1e 100644 --- a/seeds/dev/06-estimaciones.sql +++ b/seeds/dev/06-estimaciones.sql @@ -6,6 +6,23 @@ -- Fecha: 2026-02-03 -- Descripción: Contratos, estimaciones, generadores, anticipos, retenciones -- Dependencias: 04-proyectos-obras.sql, 05-presupuestos.sql +-- +-- FÓRMULA DE CÁLCULO ESTIMACIONES: +-- ──────────────────────────────────────────────────────────────────────────────── +-- total_amount = subtotal + tax_amount - advance_amount - retention_amount +-- +-- Donde: +-- subtotal = Monto base del trabajo ejecutado en el periodo +-- tax_amount = subtotal × 0.16 (IVA 16%) +-- advance_amount = subtotal × (advance_percentage / 100) [amortización anticipo] +-- retention_amount = subtotal × (retention_percentage / 100) [fondo de garantía] +-- +-- Ejemplo verificación EST-2024-001-01: +-- subtotal = 350,000.00 +-- tax = 350,000 × 0.16 = 56,000.00 +-- advance = 350,000 × 0.30 = 105,000.00 +-- retention = 350,000 × 0.05 = 17,500.00 +-- total = 350,000 + 56,000 - 105,000 - 17,500 = 283,500.00 ✓ -- ═══════════════════════════════════════════════════════════════════════════════ -- UUIDs: 00000000-0000-0000-0006-XXXXXXXXXXXX diff --git a/seeds/dev/08-hse.sql b/seeds/dev/08-hse.sql index b554065..adcfe85 100644 --- a/seeds/dev/08-hse.sql +++ b/seeds/dev/08-hse.sql @@ -99,8 +99,9 @@ ON CONFLICT (id) DO NOTHING; -- ───────────────────────────────────────────────────────────────────────────────── -- 2. CAPACITACIONES -- ───────────────────────────────────────────────────────────────────────────────── +-- NOTA: La tabla en DDL es hse.capacitaciones (plural), no hse.capacitacion -INSERT INTO hse.capacitacion ( +INSERT INTO hse.capacitaciones ( id, tenant_id, codigo, nombre, tipo, descripcion, duracion_horas, requiere_evaluacion, puntaje_minimo, activo, created_at @@ -226,6 +227,179 @@ INSERT INTO hse.horas_trabajadas ( '2024-05-05', 32, 38, 256, 304, NOW(), '00000000-0000-0000-0002-000000000109') ON CONFLICT (id) DO NOTHING; +-- ───────────────────────────────────────────────────────────────────────────────── +-- 5. TIPOS DE INSPECCIÓN HSE +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO hse.tipos_inspeccion ( + id, tenant_id, codigo, nombre, descripcion, + frecuencia_sugerida, requiere_checklist, activo, + created_at +) VALUES +('00000000-0000-0000-0008-000000000401', '00000000-0000-0000-0003-000000000001', + 'INSP-DIARIA', 'Inspección Diaria de Seguridad', 'Recorrido de verificación de condiciones generales', + 'diaria', true, true, NOW()), + +('00000000-0000-0000-0008-000000000402', '00000000-0000-0000-0003-000000000001', + 'INSP-ANDAMIOS', 'Inspección de Andamios', 'Verificación de estabilidad y condiciones de andamios', + 'antes_de_uso', true, true, NOW()), + +('00000000-0000-0000-0008-000000000403', '00000000-0000-0000-0003-000000000001', + 'INSP-EQUIPO', 'Inspección de Equipo de Protección', 'Verificación de EPP del personal', + 'semanal', true, true, NOW()), + +('00000000-0000-0000-0008-000000000404', '00000000-0000-0000-0003-000000000001', + 'INSP-EXCAVACIONES', 'Inspección de Excavaciones', 'Verificación de taludes, ademes y condiciones', + 'antes_de_ingreso', true, true, NOW()) +ON CONFLICT (id) DO NOTHING; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- 6. INSPECCIONES HSE +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO hse.inspecciones ( + id, tenant_id, fraccionamiento_id, tipo_inspeccion_id, + folio, fecha, area, resultado, observaciones, + inspector_id, created_at, created_by +) VALUES +('00000000-0000-0000-0008-000000000501', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-0004-000000000101', '00000000-0000-0000-0008-000000000401', + 'INSP-2024-001', '2024-05-01', 'Manzana A - General', 'aprobada', + 'Condiciones generales adecuadas. Personal con EPP completo.', + '00000000-0000-0000-0002-000000000109', NOW(), '00000000-0000-0000-0002-000000000109'), + +('00000000-0000-0000-0008-000000000502', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-0004-000000000101', '00000000-0000-0000-0008-000000000402', + 'INSP-2024-002', '2024-05-02', 'Lote B-03 - Andamio', 'aprobada_con_observaciones', + 'Andamio estable. Se requiere mejorar anclaje en nivel 2.', + '00000000-0000-0000-0002-000000000109', NOW(), '00000000-0000-0000-0002-000000000109'), + +('00000000-0000-0000-0008-000000000503', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-0004-000000000102', '00000000-0000-0000-0008-000000000401', + 'INSP-2024-003', '2024-06-05', 'Torre Diamante - Nivel 4', 'rechazada', + 'Se detectaron herramientas sin asegurar. Suspensión temporal.', + '00000000-0000-0000-0002-000000000109', NOW(), '00000000-0000-0000-0002-000000000109') +ON CONFLICT (id) DO NOTHING; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- 7. MATRIZ EPP POR PUESTO (Requiere seed 02b-hr-employees.sql) +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO hse.epp_matriz_puesto ( + id, tenant_id, puesto_id, epp_id, obligatorio, + created_at +) VALUES +-- Albañil (EPP básico + guantes) +('00000000-0000-0000-0008-000000000601', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000006', '00000000-0000-0000-0008-000000000001', true, NOW()), +('00000000-0000-0000-0008-000000000602', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000006', '00000000-0000-0000-0008-000000000002', true, NOW()), +('00000000-0000-0000-0008-000000000603', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000006', '00000000-0000-0000-0008-000000000008', true, NOW()), +('00000000-0000-0000-0008-000000000604', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000006', '00000000-0000-0000-0008-000000000010', true, NOW()), +('00000000-0000-0000-0008-000000000605', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000006', '00000000-0000-0000-0008-000000000013', true, NOW()), + +-- Operador Maquinaria (EPP + auditivo) +('00000000-0000-0000-0008-000000000610', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000011', '00000000-0000-0000-0008-000000000001', true, NOW()), +('00000000-0000-0000-0008-000000000611', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000011', '00000000-0000-0000-0008-000000000005', true, NOW()), +('00000000-0000-0000-0008-000000000612', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000011', '00000000-0000-0000-0008-000000000010', true, NOW()), +('00000000-0000-0000-0008-000000000613', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000011', '00000000-0000-0000-0008-000000000013', true, NOW()), + +-- Electricista (EPP + protección eléctrica) +('00000000-0000-0000-0008-000000000620', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000009', '00000000-0000-0000-0008-000000000001', true, NOW()), +('00000000-0000-0000-0008-000000000621', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000009', '00000000-0000-0000-0008-000000000002', true, NOW()), +('00000000-0000-0000-0008-000000000622', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000009', '00000000-0000-0000-0008-000000000010', true, NOW()), +('00000000-0000-0000-0008-000000000623', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000009', '00000000-0000-0000-0008-000000000013', true, NOW()) +ON CONFLICT (id) DO NOTHING; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- 8. ASIGNACIONES DE EPP (Requiere seed 02b-hr-employees.sql) +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO hse.epp_asignaciones ( + id, tenant_id, employee_id, epp_id, + fecha_asignacion, fecha_vencimiento, cantidad, + estado, observaciones, + asignado_por, created_at +) VALUES +-- Asignaciones al albañil Roberto Martínez (EMP-007) +('00000000-0000-0000-0008-000000000701', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000107', '00000000-0000-0000-0008-000000000001', + '2024-03-15', '2026-03-15', 1, 'activo', 'Casco nuevo', + '00000000-0000-0000-0002-000000000109', NOW()), + +('00000000-0000-0000-0008-000000000702', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000107', '00000000-0000-0000-0008-000000000010', + '2024-03-15', '2025-03-15', 1, 'activo', 'Botas talla 28', + '00000000-0000-0000-0002-000000000109', NOW()), + +('00000000-0000-0000-0008-000000000703', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000107', '00000000-0000-0000-0008-000000000013', + '2024-03-15', '2025-03-15', 1, 'activo', 'Chaleco talla M', + '00000000-0000-0000-0002-000000000109', NOW()), + +-- Asignaciones al operador Jesús Manuel (EMP-012) +('00000000-0000-0000-0008-000000000704', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000112', '00000000-0000-0000-0008-000000000001', + '2024-06-01', '2026-06-01', 1, 'activo', NULL, + '00000000-0000-0000-0002-000000000109', NOW()), + +('00000000-0000-0000-0008-000000000705', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-002b-000000000112', '00000000-0000-0000-0008-000000000005', + '2024-06-01', '2026-06-01', 1, 'activo', 'Orejeras 3M Peltor', + '00000000-0000-0000-0002-000000000109', NOW()) +ON CONFLICT (id) DO NOTHING; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- 9. CUMPLIMIENTO POR OBRA +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO hse.cumplimiento_obra ( + id, tenant_id, fraccionamiento_id, + periodo, porcentaje_cumplimiento, observaciones, + created_at, created_by +) VALUES +('00000000-0000-0000-0008-000000000801', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-0004-000000000101', + '2024-05', 92.5, 'Cumplimiento alto. 2 observaciones menores en EPP.', + NOW(), '00000000-0000-0000-0002-000000000109'), + +('00000000-0000-0000-0008-000000000802', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-0004-000000000102', + '2024-06', 88.0, 'Incidente por herramienta sin asegurar. Se reforzó capacitación.', + NOW(), '00000000-0000-0000-0002-000000000109') +ON CONFLICT (id) DO NOTHING; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- 10. DÍAS SIN ACCIDENTE +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO hse.dias_sin_accidente ( + id, tenant_id, fraccionamiento_id, + fecha_inicio_conteo, dias_actuales, meta_dias, ultimo_accidente_id, + created_at, created_by +) VALUES +('00000000-0000-0000-0008-000000000901', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-0004-000000000101', + '2024-05-11', 25, 100, '00000000-0000-0000-0008-000000000203', + NOW(), '00000000-0000-0000-0002-000000000109'), + +('00000000-0000-0000-0008-000000000902', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-0004-000000000102', + '2024-06-01', 35, 100, NULL, + NOW(), '00000000-0000-0000-0002-000000000109') +ON CONFLICT (id) DO NOTHING; + -- ───────────────────────────────────────────────────────────────────────────────── -- VERIFICACIÓN -- ───────────────────────────────────────────────────────────────────────────────── @@ -236,11 +410,23 @@ DECLARE v_capacitaciones INTEGER; v_incidentes INTEGER; v_horas INTEGER; + v_tipos_inspeccion INTEGER; + v_inspecciones INTEGER; + v_epp_matriz INTEGER; + v_epp_asignaciones INTEGER; + v_cumplimiento INTEGER; + v_dias_sin_accidente INTEGER; BEGIN SELECT COUNT(*) INTO v_epp FROM hse.epp_catalogo; - SELECT COUNT(*) INTO v_capacitaciones FROM hse.capacitacion; + SELECT COUNT(*) INTO v_capacitaciones FROM hse.capacitaciones; SELECT COUNT(*) INTO v_incidentes FROM hse.incidentes; SELECT COUNT(*) INTO v_horas FROM hse.horas_trabajadas; + SELECT COUNT(*) INTO v_tipos_inspeccion FROM hse.tipos_inspeccion; + SELECT COUNT(*) INTO v_inspecciones FROM hse.inspecciones; + SELECT COUNT(*) INTO v_epp_matriz FROM hse.epp_matriz_puesto; + SELECT COUNT(*) INTO v_epp_asignaciones FROM hse.epp_asignaciones; + SELECT COUNT(*) INTO v_cumplimiento FROM hse.cumplimiento_obra; + SELECT COUNT(*) INTO v_dias_sin_accidente FROM hse.dias_sin_accidente; RAISE NOTICE '══════════════════════════════════════════════════════════════'; RAISE NOTICE 'SEED 08 - HSE - COMPLETADO'; @@ -249,6 +435,12 @@ BEGIN RAISE NOTICE 'Capacitaciones: %', v_capacitaciones; RAISE NOTICE 'Incidentes: %', v_incidentes; RAISE NOTICE 'Registros de horas: %', v_horas; + RAISE NOTICE 'Tipos de inspección: %', v_tipos_inspeccion; + RAISE NOTICE 'Inspecciones: %', v_inspecciones; + RAISE NOTICE 'Matriz EPP/Puesto: %', v_epp_matriz; + RAISE NOTICE 'Asignaciones EPP: %', v_epp_asignaciones; + RAISE NOTICE 'Cumplimiento obra: %', v_cumplimiento; + RAISE NOTICE 'Días sin accidente: %', v_dias_sin_accidente; RAISE NOTICE '══════════════════════════════════════════════════════════════'; END $$; diff --git a/seeds/dev/11-infonavit.sql b/seeds/dev/11-infonavit.sql new file mode 100644 index 0000000..a7417bb --- /dev/null +++ b/seeds/dev/11-infonavit.sql @@ -0,0 +1,293 @@ +-- ═══════════════════════════════════════════════════════════════════════════════ +-- SEED 11: INFONAVIT Y DERECHOHABIENTES +-- ═══════════════════════════════════════════════════════════════════════════════ +-- Proyecto: ERP Construcción +-- Autor: Claude Opus 4.5 +-- Fecha: 2026-02-03 +-- Descripción: Registro INFONAVIT, ofertas, derechohabientes, asignaciones +-- Dependencias: 03-empresa-tenant.sql, 04-proyectos-obras.sql +-- Cobertura: 4/8 tablas (50%) - registro, oferta, derechohabientes, asignaciones +-- ═══════════════════════════════════════════════════════════════════════════════ + +-- UUIDs: 00000000-0000-0000-000b-XXXXXXXXXXXX + +BEGIN; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- 1. REGISTRO INFONAVIT (Registro del constructor) +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO infonavit.registro_infonavit ( + id, tenant_id, company_id, registro_number, registro_date, + status, vigencia_start, vigencia_end, + responsable_tecnico, cedula_profesional, + metadata, created_at, created_by +) VALUES +('00000000-0000-0000-000b-000000000001', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-0003-000000000001', + 'REG-INFONAVIT-2024-001', '2024-01-15', + 'active', '2024-01-15', '2029-01-14', + 'Ing. Roberto García López', '1234567', + '{"tipo_registro": "constructor_vivienda", "zona": "centro_norte"}'::JSONB, + NOW(), '00000000-0000-0000-0002-000000000102') +ON CONFLICT (id) DO NOTHING; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- 2. OFERTA DE VIVIENDAS +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO infonavit.oferta_vivienda ( + id, tenant_id, registro_id, fraccionamiento_id, + oferta_number, submission_date, approval_date, + total_units, approved_units, + price_range_min, price_range_max, + status, metadata, created_at, created_by +) VALUES +-- Oferta Las Palmas Etapa 1 +('00000000-0000-0000-000b-000000000101', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-000b-000000000001', '00000000-0000-0000-0004-000000000101', + 'OFE-2024-PALMAS-001', '2024-02-15', '2024-03-01', + 40, 38, + 1850000.00, 3300000.00, + 'approved', + '{"etapa": 1, "tipos_vivienda": ["CASA-90", "CASA-120", "CASA-150"]}'::JSONB, + NOW(), '00000000-0000-0000-0002-000000000103'), + +-- Oferta Torre Diamante +('00000000-0000-0000-000b-000000000102', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-000b-000000000001', '00000000-0000-0000-0004-000000000102', + 'OFE-2024-DIAMANTE-001', '2024-05-10', '2024-05-25', + 48, 48, + 1250000.00, 2250000.00, + 'approved', + '{"torre": "A", "tipos_vivienda": ["DEPTO-65", "DEPTO-85", "DEPTO-110"]}'::JSONB, + NOW(), '00000000-0000-0000-0002-000000000103') +ON CONFLICT (id) DO NOTHING; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- 3. DERECHOHABIENTES (Compradores con crédito INFONAVIT) +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO infonavit.derechohabientes ( + id, tenant_id, + nss, curp, rfc, full_name, + first_name, last_name, second_last_name, + birth_date, gender, marital_status, + email, phone, mobile, + address, city, state, zip_code, + employer_name, employer_rfc, employment_start_date, salary, + cotization_weeks, credit_type, credit_number, + credit_amount, puntos_infonavit, subcuenta_vivienda, + precalificacion_date, precalificacion_amount, + status, created_at, created_by +) VALUES +-- Derechohabiente 1 - Comprador Lote A-01 (entregado) +('00000000-0000-0000-000b-000000000201', '00000000-0000-0000-0003-000000000001', + '12345678901', 'GARM800515HASRRL01', 'GARM800515ABC', + 'Manuel García Rodríguez', 'Manuel', 'García', 'Rodríguez', + '1980-05-15', 'Masculino', 'Casado', + 'manuel.garcia@email.com', '+52 449 111 1111', '+52 449 211 1111', + 'Av. Las Torres 123', 'Aguascalientes', 'Aguascalientes', '20010', + 'Nissan Mexicana S.A.', 'NME850101XXX', '2005-03-01', 25000.00, + 936, 'infonavit_tradicional', 'CRED-INF-2024-001', + 850000.00, 145.5, 185000.00, + '2024-01-10', 900000.00, + 'owner', NOW(), '00000000-0000-0000-0002-000000000103'), + +-- Derechohabiente 2 - Comprador Lote A-02 (entregado) +('00000000-0000-0000-000b-000000000202', '00000000-0000-0000-0003-000000000001', + '12345678902', 'LOPH850320MASPRL02', 'LOPH850320ABC', + 'Patricia López Hernández', 'Patricia', 'López', 'Hernández', + '1985-03-20', 'Femenino', 'Soltera', + 'patricia.lopez@email.com', '+52 449 111 2222', '+52 449 211 2222', + 'Calle Morelos 456', 'Aguascalientes', 'Aguascalientes', '20020', + 'Continental AG México', 'CAM900101XXX', '2010-06-15', 22000.00, + 720, 'infonavit_tradicional', 'CRED-INF-2024-002', + 800000.00, 138.2, 165000.00, + '2024-01-15', 850000.00, + 'owner', NOW(), '00000000-0000-0000-0002-000000000103'), + +-- Derechohabiente 3 - En proceso de escrituración +('00000000-0000-0000-000b-000000000203', '00000000-0000-0000-0003-000000000001', + '12345678903', 'SAMJ900810HASNTL03', 'SAMJ900810ABC', + 'José Luis Sánchez Martínez', 'José Luis', 'Sánchez', 'Martínez', + '1990-08-10', 'Masculino', 'Casado', + 'joseluis.sanchez@email.com', '+52 449 111 3333', '+52 449 211 3333', + 'Blvd. Norte 789', 'Aguascalientes', 'Aguascalientes', '20030', + 'Jatco México S.A.', 'JME880101XXX', '2012-01-20', 28000.00, + 624, 'cofinavit', 'CRED-INF-2024-003', + 1200000.00, 155.8, 210000.00, + '2024-02-01', 1250000.00, + 'in_process', NOW(), '00000000-0000-0000-0002-000000000103'), + +-- Derechohabiente 4 - Asignado pero pendiente de firma +('00000000-0000-0000-000b-000000000204', '00000000-0000-0000-0003-000000000001', + '12345678904', 'RORM880125MASPXR04', 'RORM880125ABC', + 'María del Rosario Ramírez Ortiz', 'María del Rosario', 'Ramírez', 'Ortiz', + '1988-01-25', 'Femenino', 'Casada', + 'rosario.ramirez@email.com', '+52 449 111 4444', '+52 449 211 4444', + 'Av. Tecnológico 234', 'Aguascalientes', 'Aguascalientes', '20290', + 'Texas Instruments', 'TIM950101XXX', '2015-07-01', 35000.00, + 520, 'infonavit_total', 'CRED-INF-2024-004', + 1500000.00, 168.3, 280000.00, + '2024-02-15', 1550000.00, + 'assigned', NOW(), '00000000-0000-0000-0002-000000000103'), + +-- Derechohabiente 5 - Precalificado, buscando vivienda +('00000000-0000-0000-000b-000000000205', '00000000-0000-0000-0003-000000000001', + '12345678905', 'HECR920605HASPSS05', 'HECR920605ABC', + 'Ricardo Hernández Castro', 'Ricardo', 'Hernández', 'Castro', + '1992-06-05', 'Masculino', 'Soltero', + 'ricardo.hernandez@email.com', '+52 449 111 5555', '+52 449 211 5555', + 'Calle Independencia 567', 'Aguascalientes', 'Aguascalientes', '20040', + 'Flextronics Manufacturing', 'FME920101XXX', '2018-02-15', 18000.00, + 312, 'infonavit_tradicional', NULL, + NULL, 120.5, 95000.00, + '2024-03-01', 680000.00, + 'qualified', NOW(), '00000000-0000-0000-0002-000000000103'), + +-- Derechohabientes para Torre Diamante +('00000000-0000-0000-000b-000000000206', '00000000-0000-0000-0003-000000000001', + '12345678906', 'MOVP850715HASRRL06', 'MOVP850715ABC', + 'Pedro Morales Vargas', 'Pedro', 'Morales', 'Vargas', + '1985-07-15', 'Masculino', 'Casado', + 'pedro.morales@email.com', '+52 449 111 6666', '+52 449 211 6666', + 'Av. Universidad 890', 'Aguascalientes', 'Aguascalientes', '20131', + 'Bosch México', 'BME870101XXX', '2008-09-01', 32000.00, + 780, 'cofinavit', 'CRED-INF-2024-006', + 1100000.00, 152.4, 220000.00, + '2024-04-10', 1150000.00, + 'owner', NOW(), '00000000-0000-0000-0002-000000000103'), + +('00000000-0000-0000-000b-000000000207', '00000000-0000-0000-0003-000000000001', + '12345678907', 'GUAL900422MASTRX07', 'GUAL900422ABC', + 'Lucía Gutiérrez Alvarado', 'Lucía', 'Gutiérrez', 'Alvarado', + '1990-04-22', 'Femenino', 'Soltera', + 'lucia.gutierrez@email.com', '+52 449 111 7777', '+52 449 211 7777', + 'Calle Madero 123', 'Aguascalientes', 'Aguascalientes', '20000', + 'Sensata Technologies', 'STE960101XXX', '2016-11-15', 24000.00, + 416, 'infonavit_tradicional', 'CRED-INF-2024-007', + 720000.00, 132.8, 145000.00, + '2024-04-20', 750000.00, + 'owner', NOW(), '00000000-0000-0000-0002-000000000103') +ON CONFLICT (id) DO NOTHING; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- 4. ASIGNACIÓN DE VIVIENDAS +-- ───────────────────────────────────────────────────────────────────────────────── + +INSERT INTO infonavit.asignacion_vivienda ( + id, tenant_id, derechohabiente_id, + lote_id, departamento_id, oferta_id, + assignment_date, assignment_number, status, + sale_price, credit_amount, down_payment, subsidy_amount, + notary_name, notary_number, + deed_date, deed_number, + public_registry_number, public_registry_date, + scheduled_delivery_date, actual_delivery_date, + notes, created_at, created_by +) VALUES +-- Lote A-01 - Entregado +('00000000-0000-0000-000b-000000000301', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-000b-000000000201', + '00000000-0000-0000-0004-000000000601', NULL, + '00000000-0000-0000-000b-000000000101', + '2024-02-20', 'ASIG-2024-001', 'delivered', + 1900000.00, 850000.00, 190000.00, 60000.00, + 'Lic. Juan Notario Público', 'NOT-AGS-123', + '2024-04-15', 'ESC-2024-001', + 'RPP-AGS-2024-001', '2024-04-20', + '2024-05-01', '2024-05-01', + 'Entrega en tiempo y forma', + NOW(), '00000000-0000-0000-0002-000000000103'), + +-- Lote A-02 - Entregado +('00000000-0000-0000-000b-000000000302', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-000b-000000000202', + '00000000-0000-0000-0004-000000000602', NULL, + '00000000-0000-0000-000b-000000000101', + '2024-02-25', 'ASIG-2024-002', 'delivered', + 1900000.00, 800000.00, 195000.00, 55000.00, + 'Lic. Juan Notario Público', 'NOT-AGS-123', + '2024-04-18', 'ESC-2024-002', + 'RPP-AGS-2024-002', '2024-04-22', + '2024-05-10', '2024-05-08', + 'Entrega anticipada', + NOW(), '00000000-0000-0000-0002-000000000103'), + +-- Lote A-05 - En proceso de escrituración +('00000000-0000-0000-000b-000000000303', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-000b-000000000203', + '00000000-0000-0000-0004-000000000605', NULL, + '00000000-0000-0000-000b-000000000101', + '2024-03-15', 'ASIG-2024-003', 'in_process', + 1880000.00, 1200000.00, 150000.00, 50000.00, + 'Lic. María Notaria Pública', 'NOT-AGS-456', + NULL, NULL, + NULL, NULL, + '2024-07-01', NULL, + 'En trámite de escrituración', + NOW(), '00000000-0000-0000-0002-000000000103'), + +-- Departamento 101 - Entregado +('00000000-0000-0000-000b-000000000304', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-000b-000000000206', + NULL, '00000000-0000-0000-0004-000000000701', + '00000000-0000-0000-000b-000000000102', + '2024-05-20', 'ASIG-2024-004', 'delivered', + 1300000.00, 1100000.00, 130000.00, 70000.00, + 'Lic. Juan Notario Público', 'NOT-AGS-123', + '2024-07-10', 'ESC-2024-004', + 'RPP-AGS-2024-004', '2024-07-15', + '2024-08-01', '2024-08-01', + NULL, + NOW(), '00000000-0000-0000-0002-000000000103'), + +-- Departamento 102 - Entregado +('00000000-0000-0000-000b-000000000305', '00000000-0000-0000-0003-000000000001', + '00000000-0000-0000-000b-000000000207', + NULL, '00000000-0000-0000-0004-000000000702', + '00000000-0000-0000-000b-000000000102', + '2024-05-25', 'ASIG-2024-005', 'delivered', + 1700000.00, 720000.00, 170000.00, 60000.00, + 'Lic. María Notaria Pública', 'NOT-AGS-456', + '2024-07-12', 'ESC-2024-005', + 'RPP-AGS-2024-005', '2024-07-18', + '2024-08-15', '2024-08-10', + NULL, + NOW(), '00000000-0000-0000-0002-000000000103') +ON CONFLICT (id) DO NOTHING; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- VERIFICACIÓN +-- ───────────────────────────────────────────────────────────────────────────────── + +DO $$ +DECLARE + v_registros INTEGER; + v_ofertas INTEGER; + v_derechohabientes INTEGER; + v_asignaciones INTEGER; +BEGIN + SELECT COUNT(*) INTO v_registros FROM infonavit.registro_infonavit; + SELECT COUNT(*) INTO v_ofertas FROM infonavit.oferta_vivienda; + SELECT COUNT(*) INTO v_derechohabientes FROM infonavit.derechohabientes; + SELECT COUNT(*) INTO v_asignaciones FROM infonavit.asignacion_vivienda; + + RAISE NOTICE '══════════════════════════════════════════════════════════════'; + RAISE NOTICE 'SEED 11 - INFONAVIT - COMPLETADO'; + RAISE NOTICE '══════════════════════════════════════════════════════════════'; + RAISE NOTICE 'Registros INFONAVIT: %', v_registros; + RAISE NOTICE 'Ofertas de vivienda: %', v_ofertas; + RAISE NOTICE 'Derechohabientes: %', v_derechohabientes; + RAISE NOTICE 'Asignaciones: %', v_asignaciones; + RAISE NOTICE '══════════════════════════════════════════════════════════════'; + RAISE NOTICE 'Cobertura INFONAVIT: 4/8 tablas (50%%)'; + RAISE NOTICE '══════════════════════════════════════════════════════════════'; +END $$; + +COMMIT; + +-- ═══════════════════════════════════════════════════════════════════════════════ +-- FIN SEED 11 +-- ═══════════════════════════════════════════════════════════════════════════════ diff --git a/seeds/dev/validate-seeds-comprehensive.sql b/seeds/dev/validate-seeds-comprehensive.sql new file mode 100644 index 0000000..69e3ecc --- /dev/null +++ b/seeds/dev/validate-seeds-comprehensive.sql @@ -0,0 +1,665 @@ +-- ═══════════════════════════════════════════════════════════════════════════════ +-- SCRIPT: validate-seeds-comprehensive.sql +-- PROYECTO: ERP Construcción +-- DESCRIPCIÓN: Validación exhaustiva de seeds (FK, cálculos, triggers, cobertura) +-- FECHA: 2026-02-03 +-- AUTOR: Claude Opus 4.5 +-- +-- SECCIONES: +-- 1. Validación de Conteos por Seed +-- 2. Validación de FK Integrity (0 huérfanos) +-- 3. Validación de Cálculos Financieros (Estimaciones) +-- 4. Validación de Triggers y Funciones +-- 5. Matriz de Cobertura por Schema +-- 6. Resumen Final PASS/FAIL +-- ═══════════════════════════════════════════════════════════════════════════════ + +\set QUIET on +\pset footer off +\pset tuples_only on + +-- ───────────────────────────────────────────────────────────────────────────────── +-- SECCIÓN 1: VALIDACIÓN DE CONTEOS POR SEED +-- ───────────────────────────────────────────────────────────────────────────────── + +DO $$ +DECLARE + v_pass_count INTEGER := 0; + v_fail_count INTEGER := 0; + v_temp INTEGER; +BEGIN + RAISE NOTICE ''; + RAISE NOTICE '═══════════════════════════════════════════════════════════════════════════════'; + RAISE NOTICE ' VALIDACIÓN COMPREHENSIVA DE SEEDS - ERP CONSTRUCCIÓN'; + RAISE NOTICE ' Fecha: %', CURRENT_TIMESTAMP; + RAISE NOTICE '═══════════════════════════════════════════════════════════════════════════════'; + RAISE NOTICE ''; + RAISE NOTICE '──────────────────────────────────────────────────────────────────────────────'; + RAISE NOTICE ' SECCIÓN 1: CONTEOS POR SEED'; + RAISE NOTICE '──────────────────────────────────────────────────────────────────────────────'; + RAISE NOTICE ''; +END $$; + +-- SEED 01: Catálogos Base +DO $$ +DECLARE + v_unidades INTEGER; + v_monedas INTEGER; + v_impuestos INTEGER; + v_bancos INTEGER; + v_estados INTEGER; + v_municipios INTEGER; +BEGIN + SELECT COUNT(*) INTO v_unidades FROM core.unidades WHERE activo = true; + SELECT COUNT(*) INTO v_monedas FROM core.monedas WHERE activo = true; + SELECT COUNT(*) INTO v_impuestos FROM core.impuestos WHERE activo = true; + SELECT COUNT(*) INTO v_bancos FROM core.bancos WHERE activo = true; + SELECT COUNT(*) INTO v_estados FROM core.estados WHERE activo = true; + SELECT COUNT(*) INTO v_municipios FROM core.municipios WHERE activo = true; + + RAISE NOTICE '[SEED-01] Catálogos Base'; + RAISE NOTICE ' Unidades: % %', v_unidades, CASE WHEN v_unidades >= 30 THEN '✓' ELSE '✗ (min: 30)' END; + RAISE NOTICE ' Monedas: % %', v_monedas, CASE WHEN v_monedas >= 4 THEN '✓' ELSE '✗ (min: 4)' END; + RAISE NOTICE ' Impuestos: % %', v_impuestos, CASE WHEN v_impuestos >= 8 THEN '✓' ELSE '✗ (min: 8)' END; + RAISE NOTICE ' Bancos: % %', v_bancos, CASE WHEN v_bancos >= 18 THEN '✓' ELSE '✗ (min: 18)' END; + RAISE NOTICE ' Estados: % %', v_estados, CASE WHEN v_estados >= 30 THEN '✓' ELSE '✗ (min: 30)' END; + RAISE NOTICE ' Municipios: % %', v_municipios, CASE WHEN v_municipios >= 10 THEN '✓' ELSE '✗ (min: 10)' END; + RAISE NOTICE ''; +END $$; + +-- SEED 02: Usuarios y Perfiles +DO $$ +DECLARE + v_roles INTEGER; + v_permisos INTEGER; + v_usuarios INTEGER; +BEGIN + SELECT COUNT(*) INTO v_roles FROM core.roles WHERE activo = true; + SELECT COUNT(*) INTO v_permisos FROM core.permisos WHERE activo = true; + SELECT COUNT(*) INTO v_usuarios FROM core.usuarios WHERE activo = true; + + RAISE NOTICE '[SEED-02] Usuarios y Perfiles'; + RAISE NOTICE ' Roles: % %', v_roles, CASE WHEN v_roles >= 10 THEN '✓' ELSE '✗ (min: 10)' END; + RAISE NOTICE ' Permisos: % %', v_permisos, CASE WHEN v_permisos >= 45 THEN '✓' ELSE '✗ (min: 45)' END; + RAISE NOTICE ' Usuarios: % %', v_usuarios, CASE WHEN v_usuarios >= 10 THEN '✓' ELSE '✗ (min: 10)' END; + RAISE NOTICE ''; +END $$; + +-- SEED 02b: HR Employees +DO $$ +DECLARE + v_puestos INTEGER; + v_employees INTEGER; + v_asignaciones INTEGER; +BEGIN + SELECT COUNT(*) INTO v_puestos FROM hr.puestos WHERE activo = true; + SELECT COUNT(*) INTO v_employees FROM hr.employees WHERE activo = true; + SELECT COUNT(*) INTO v_asignaciones FROM hr.employee_fraccionamientos WHERE activo = true; + + RAISE NOTICE '[SEED-02b] HR Employees'; + RAISE NOTICE ' Puestos: % %', v_puestos, CASE WHEN v_puestos >= 10 THEN '✓' ELSE '✗ (min: 10)' END; + RAISE NOTICE ' Empleados: % %', v_employees, CASE WHEN v_employees >= 10 THEN '✓' ELSE '✗ (min: 10)' END; + RAISE NOTICE ' Asignaciones a obra: % %', v_asignaciones, CASE WHEN v_asignaciones >= 5 THEN '✓' ELSE '✗ (min: 5)' END; + RAISE NOTICE ''; +END $$; + +-- SEED 03: Empresa y Estructura +DO $$ +DECLARE + v_tenants INTEGER; + v_sucursales INTEGER; + v_almacenes INTEGER; +BEGIN + SELECT COUNT(*) INTO v_tenants FROM core.tenants WHERE activo = true; + SELECT COUNT(*) INTO v_sucursales FROM core.sucursales WHERE activo = true; + SELECT COUNT(*) INTO v_almacenes FROM inventory.almacenes WHERE activo = true; + + RAISE NOTICE '[SEED-03] Empresa y Estructura'; + RAISE NOTICE ' Tenants: % %', v_tenants, CASE WHEN v_tenants >= 1 THEN '✓' ELSE '✗ (min: 1)' END; + RAISE NOTICE ' Sucursales: % %', v_sucursales, CASE WHEN v_sucursales >= 2 THEN '✓' ELSE '✗ (min: 2)' END; + RAISE NOTICE ' Almacenes: % %', v_almacenes, CASE WHEN v_almacenes >= 4 THEN '✓' ELSE '✗ (min: 4)' END; + RAISE NOTICE ''; +END $$; + +-- SEED 04: Proyectos y Obras +DO $$ +DECLARE + v_prototipos INTEGER; + v_proyectos INTEGER; + v_etapas INTEGER; + v_manzanas INTEGER; + v_lotes INTEGER; + v_subcontratistas INTEGER; +BEGIN + SELECT COUNT(*) INTO v_prototipos FROM construction.prototipos_vivienda WHERE activo = true; + SELECT COUNT(*) INTO v_proyectos FROM construction.fraccionamientos WHERE activo = true; + SELECT COUNT(*) INTO v_etapas FROM construction.etapas; + SELECT COUNT(*) INTO v_manzanas FROM construction.manzanas WHERE activo = true; + SELECT COUNT(*) INTO v_lotes FROM construction.lotes WHERE activo = true; + SELECT COUNT(*) INTO v_subcontratistas FROM construction.subcontratistas WHERE activo = true; + + RAISE NOTICE '[SEED-04] Proyectos y Obras'; + RAISE NOTICE ' Prototipos: % %', v_prototipos, CASE WHEN v_prototipos >= 5 THEN '✓' ELSE '✗ (min: 5)' END; + RAISE NOTICE ' Fraccionamientos: % %', v_proyectos, CASE WHEN v_proyectos >= 3 THEN '✓' ELSE '✗ (min: 3)' END; + RAISE NOTICE ' Etapas: % %', v_etapas, CASE WHEN v_etapas >= 5 THEN '✓' ELSE '✗ (min: 5)' END; + RAISE NOTICE ' Manzanas: % %', v_manzanas, CASE WHEN v_manzanas >= 7 THEN '✓' ELSE '✗ (min: 7)' END; + RAISE NOTICE ' Lotes: % %', v_lotes, CASE WHEN v_lotes >= 12 THEN '✓' ELSE '✗ (min: 12)' END; + RAISE NOTICE ' Subcontratistas: % %', v_subcontratistas, CASE WHEN v_subcontratistas >= 8 THEN '✓' ELSE '✗ (min: 8)' END; + RAISE NOTICE ''; +END $$; + +-- SEED 05: Presupuestos +DO $$ +DECLARE + v_conceptos INTEGER; + v_presupuestos INTEGER; + v_partidas INTEGER; +BEGIN + SELECT COUNT(*) INTO v_conceptos FROM construction.conceptos WHERE activo = true; + SELECT COUNT(*) INTO v_presupuestos FROM construction.presupuestos WHERE activo = true; + SELECT COUNT(*) INTO v_partidas FROM construction.presupuesto_partidas; + + RAISE NOTICE '[SEED-05] Presupuestos'; + RAISE NOTICE ' Conceptos CMIC: % %', v_conceptos, CASE WHEN v_conceptos >= 20 THEN '✓' ELSE '✗ (min: 20)' END; + RAISE NOTICE ' Presupuestos: % %', v_presupuestos, CASE WHEN v_presupuestos >= 4 THEN '✓' ELSE '✗ (min: 4)' END; + RAISE NOTICE ' Partidas: % %', v_partidas, CASE WHEN v_partidas >= 12 THEN '✓' ELSE '✗ (min: 12)' END; + RAISE NOTICE ''; +END $$; + +-- SEED 06: Estimaciones +DO $$ +DECLARE + v_contratos INTEGER; + v_estimaciones INTEGER; + v_anticipos INTEGER; + v_fondos INTEGER; +BEGIN + SELECT COUNT(*) INTO v_contratos FROM construction.contratos; + SELECT COUNT(*) INTO v_estimaciones FROM estimates.estimaciones; + SELECT COUNT(*) INTO v_anticipos FROM estimates.anticipos; + SELECT COUNT(*) INTO v_fondos FROM estimates.fondo_garantia; + + RAISE NOTICE '[SEED-06] Estimaciones'; + RAISE NOTICE ' Contratos: % %', v_contratos, CASE WHEN v_contratos >= 4 THEN '✓' ELSE '✗ (min: 4)' END; + RAISE NOTICE ' Estimaciones: % %', v_estimaciones, CASE WHEN v_estimaciones >= 5 THEN '✓' ELSE '✗ (min: 5)' END; + RAISE NOTICE ' Anticipos: % %', v_anticipos, CASE WHEN v_anticipos >= 3 THEN '✓' ELSE '✗ (min: 3)' END; + RAISE NOTICE ' Fondos garantía: % %', v_fondos, CASE WHEN v_fondos >= 3 THEN '✓' ELSE '✗ (min: 3)' END; + RAISE NOTICE ''; +END $$; + +-- SEED 07: Avances y Calidad +DO $$ +DECLARE + v_avances INTEGER; + v_bitacora INTEGER; + v_checklists INTEGER; +BEGIN + SELECT COUNT(*) INTO v_avances FROM construction.avance_obra; + SELECT COUNT(*) INTO v_bitacora FROM construction.bitacora_obra; + SELECT COUNT(*) INTO v_checklists FROM construction.checklist_calidad WHERE activo = true; + + RAISE NOTICE '[SEED-07] Avances y Calidad'; + RAISE NOTICE ' Avances de obra: % %', v_avances, CASE WHEN v_avances >= 5 THEN '✓' ELSE '✗ (min: 5)' END; + RAISE NOTICE ' Bitácora: % %', v_bitacora, CASE WHEN v_bitacora >= 4 THEN '✓' ELSE '✗ (min: 4)' END; + RAISE NOTICE ' Checklists calidad: % %', v_checklists, CASE WHEN v_checklists >= 3 THEN '✓' ELSE '✗ (min: 3)' END; + RAISE NOTICE ''; +END $$; + +-- SEED 08: HSE +DO $$ +DECLARE + v_epp INTEGER; + v_capacitaciones INTEGER; + v_incidentes INTEGER; + v_horas INTEGER; + v_tipos_inspeccion INTEGER; + v_inspecciones INTEGER; + v_epp_matriz INTEGER; + v_epp_asignaciones INTEGER; + v_cumplimiento INTEGER; + v_dias_sin_accidente INTEGER; +BEGIN + SELECT COUNT(*) INTO v_epp FROM hse.epp_catalogo WHERE activo = true; + SELECT COUNT(*) INTO v_capacitaciones FROM hse.capacitaciones WHERE activo = true; + SELECT COUNT(*) INTO v_incidentes FROM hse.incidentes; + SELECT COUNT(*) INTO v_horas FROM hse.horas_trabajadas; + SELECT COUNT(*) INTO v_tipos_inspeccion FROM hse.tipos_inspeccion WHERE activo = true; + SELECT COUNT(*) INTO v_inspecciones FROM hse.inspecciones; + SELECT COUNT(*) INTO v_epp_matriz FROM hse.epp_matriz_puesto; + SELECT COUNT(*) INTO v_epp_asignaciones FROM hse.epp_asignaciones; + SELECT COUNT(*) INTO v_cumplimiento FROM hse.cumplimiento_obra; + SELECT COUNT(*) INTO v_dias_sin_accidente FROM hse.dias_sin_accidente; + + RAISE NOTICE '[SEED-08] HSE (Seguridad, Salud y Ambiente)'; + RAISE NOTICE ' Catálogo EPP: % %', v_epp, CASE WHEN v_epp >= 12 THEN '✓' ELSE '✗ (min: 12)' END; + RAISE NOTICE ' Capacitaciones: % %', v_capacitaciones, CASE WHEN v_capacitaciones >= 7 THEN '✓' ELSE '✗ (min: 7)' END; + RAISE NOTICE ' Incidentes: % %', v_incidentes, CASE WHEN v_incidentes >= 3 THEN '✓' ELSE '✗ (min: 3)' END; + RAISE NOTICE ' Horas trabajadas: % %', v_horas, CASE WHEN v_horas >= 4 THEN '✓' ELSE '✗ (min: 4)' END; + RAISE NOTICE ' Tipos inspección: % %', v_tipos_inspeccion, CASE WHEN v_tipos_inspeccion >= 4 THEN '✓' ELSE '✗ (min: 4)' END; + RAISE NOTICE ' Inspecciones: % %', v_inspecciones, CASE WHEN v_inspecciones >= 3 THEN '✓' ELSE '✗ (min: 3)' END; + RAISE NOTICE ' Matriz EPP/Puesto: % %', v_epp_matriz, CASE WHEN v_epp_matriz >= 10 THEN '✓' ELSE '✗ (min: 10)' END; + RAISE NOTICE ' Asignaciones EPP: % %', v_epp_asignaciones, CASE WHEN v_epp_asignaciones >= 5 THEN '✓' ELSE '✗ (min: 5)' END; + RAISE NOTICE ' Cumplimiento obra: % %', v_cumplimiento, CASE WHEN v_cumplimiento >= 2 THEN '✓' ELSE '✗ (min: 2)' END; + RAISE NOTICE ' Días sin accidente: % %', v_dias_sin_accidente, CASE WHEN v_dias_sin_accidente >= 2 THEN '✓' ELSE '✗ (min: 2)' END; + RAISE NOTICE ''; +END $$; + +-- SEED 09: Finanzas +DO $$ +DECLARE + v_cuentas INTEGER; + v_bancos INTEGER; + v_cxp INTEGER; + v_cxc INTEGER; + v_polizas INTEGER; + v_movimientos INTEGER; +BEGIN + SELECT COUNT(*) INTO v_cuentas FROM finance.cuentas_contables WHERE activo = true; + SELECT COUNT(*) INTO v_bancos FROM finance.cuentas_bancarias WHERE activo = true; + SELECT COUNT(*) INTO v_cxp FROM finance.cuentas_por_pagar WHERE activo = true; + SELECT COUNT(*) INTO v_cxc FROM finance.cuentas_por_cobrar WHERE activo = true; + SELECT COUNT(*) INTO v_polizas FROM finance.polizas_contables; + SELECT COUNT(*) INTO v_movimientos FROM finance.movimientos_poliza; + + RAISE NOTICE '[SEED-09] Finanzas'; + RAISE NOTICE ' Cuentas contables: % %', v_cuentas, CASE WHEN v_cuentas >= 30 THEN '✓' ELSE '✗ (min: 30)' END; + RAISE NOTICE ' Cuentas bancarias: % %', v_bancos, CASE WHEN v_bancos >= 3 THEN '✓' ELSE '✗ (min: 3)' END; + RAISE NOTICE ' Cuentas por pagar: % %', v_cxp, CASE WHEN v_cxp >= 3 THEN '✓' ELSE '✗ (min: 3)' END; + RAISE NOTICE ' Cuentas por cobrar: % %', v_cxc, CASE WHEN v_cxc >= 2 THEN '✓' ELSE '✗ (min: 2)' END; + RAISE NOTICE ' Pólizas: % %', v_polizas, CASE WHEN v_polizas >= 4 THEN '✓' ELSE '✗ (min: 4)' END; + RAISE NOTICE ' Movimientos: % %', v_movimientos, CASE WHEN v_movimientos >= 8 THEN '✓' ELSE '✗ (min: 8)' END; + RAISE NOTICE ''; +END $$; + +-- SEED 10: Activos y Documentos +DO $$ +DECLARE + v_categorias INTEGER; + v_activos INTEGER; + v_mantenimientos INTEGER; + v_cat_docs INTEGER; + v_documentos INTEGER; +BEGIN + SELECT COUNT(*) INTO v_categorias FROM assets.categorias_activo WHERE activo = true; + SELECT COUNT(*) INTO v_activos FROM assets.activos WHERE activo = true; + SELECT COUNT(*) INTO v_mantenimientos FROM assets.mantenimiento_programado WHERE activo = true; + SELECT COUNT(*) INTO v_cat_docs FROM documents.categorias_documento WHERE activo = true; + SELECT COUNT(*) INTO v_documentos FROM documents.documentos WHERE activo = true; + + RAISE NOTICE '[SEED-10] Activos y Documentos'; + RAISE NOTICE ' Categorías activos: % %', v_categorias, CASE WHEN v_categorias >= 4 THEN '✓' ELSE '✗ (min: 4)' END; + RAISE NOTICE ' Activos/Equipos: % %', v_activos, CASE WHEN v_activos >= 8 THEN '✓' ELSE '✗ (min: 8)' END; + RAISE NOTICE ' Mantenimientos prog.: % %', v_mantenimientos, CASE WHEN v_mantenimientos >= 3 THEN '✓' ELSE '✗ (min: 3)' END; + RAISE NOTICE ' Categorías docs: % %', v_cat_docs, CASE WHEN v_cat_docs >= 10 THEN '✓' ELSE '✗ (min: 10)' END; + RAISE NOTICE ' Documentos: % %', v_documentos, CASE WHEN v_documentos >= 4 THEN '✓' ELSE '✗ (min: 4)' END; + RAISE NOTICE ''; +END $$; + +-- SEED 11: INFONAVIT +DO $$ +DECLARE + v_registro INTEGER; + v_ofertas INTEGER; + v_derechohabientes INTEGER; + v_asignaciones INTEGER; +BEGIN + SELECT COUNT(*) INTO v_registro FROM infonavit.registro_infonavit WHERE activo = true; + SELECT COUNT(*) INTO v_ofertas FROM infonavit.oferta_vivienda WHERE activo = true; + SELECT COUNT(*) INTO v_derechohabientes FROM infonavit.derechohabientes WHERE activo = true; + SELECT COUNT(*) INTO v_asignaciones FROM infonavit.asignacion_vivienda; + + RAISE NOTICE '[SEED-11] INFONAVIT'; + RAISE NOTICE ' Registros INFONAVIT: % %', v_registro, CASE WHEN v_registro >= 1 THEN '✓' ELSE '✗ (min: 1)' END; + RAISE NOTICE ' Ofertas vivienda: % %', v_ofertas, CASE WHEN v_ofertas >= 2 THEN '✓' ELSE '✗ (min: 2)' END; + RAISE NOTICE ' Derechohabientes: % %', v_derechohabientes, CASE WHEN v_derechohabientes >= 5 THEN '✓' ELSE '✗ (min: 5)' END; + RAISE NOTICE ' Asignaciones: % %', v_asignaciones, CASE WHEN v_asignaciones >= 3 THEN '✓' ELSE '✗ (min: 3)' END; + RAISE NOTICE ''; +END $$; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- SECCIÓN 2: VALIDACIÓN FK INTEGRITY +-- ───────────────────────────────────────────────────────────────────────────────── + +DO $$ +DECLARE + v_orphans INTEGER; + v_total_orphans INTEGER := 0; +BEGIN + RAISE NOTICE '──────────────────────────────────────────────────────────────────────────────'; + RAISE NOTICE ' SECCIÓN 2: FK INTEGRITY (0 huérfanos esperados)'; + RAISE NOTICE '──────────────────────────────────────────────────────────────────────────────'; + RAISE NOTICE ''; + + -- Check usuarios → roles + SELECT COUNT(*) INTO v_orphans + FROM core.usuarios u + LEFT JOIN core.roles r ON u.rol_id = r.id + WHERE u.rol_id IS NOT NULL AND r.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' usuarios → roles: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check usuarios → tenants + SELECT COUNT(*) INTO v_orphans + FROM core.usuarios u + LEFT JOIN core.tenants t ON u.tenant_id = t.id + WHERE u.tenant_id IS NOT NULL AND t.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' usuarios → tenants: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check fraccionamientos → tenants + SELECT COUNT(*) INTO v_orphans + FROM construction.fraccionamientos f + LEFT JOIN core.tenants t ON f.tenant_id = t.id + WHERE f.tenant_id IS NOT NULL AND t.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' fraccionamientos → tenants: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check etapas → fraccionamientos + SELECT COUNT(*) INTO v_orphans + FROM construction.etapas e + LEFT JOIN construction.fraccionamientos f ON e.fraccionamiento_id = f.id + WHERE e.fraccionamiento_id IS NOT NULL AND f.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' etapas → fraccionamientos: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check manzanas → etapas + SELECT COUNT(*) INTO v_orphans + FROM construction.manzanas m + LEFT JOIN construction.etapas e ON m.etapa_id = e.id + WHERE m.etapa_id IS NOT NULL AND e.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' manzanas → etapas: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check lotes → manzanas + SELECT COUNT(*) INTO v_orphans + FROM construction.lotes l + LEFT JOIN construction.manzanas m ON l.manzana_id = m.id + WHERE l.manzana_id IS NOT NULL AND m.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' lotes → manzanas: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check contratos → subcontratistas + SELECT COUNT(*) INTO v_orphans + FROM construction.contratos c + LEFT JOIN construction.subcontratistas s ON c.subcontratista_id = s.id + WHERE c.subcontratista_id IS NOT NULL AND s.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' contratos → subcontratistas: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check contratos → fraccionamientos + SELECT COUNT(*) INTO v_orphans + FROM construction.contratos c + LEFT JOIN construction.fraccionamientos f ON c.fraccionamiento_id = f.id + WHERE c.fraccionamiento_id IS NOT NULL AND f.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' contratos → fraccionamientos: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check estimaciones → contratos + SELECT COUNT(*) INTO v_orphans + FROM estimates.estimaciones e + LEFT JOIN construction.contratos c ON e.contrato_id = c.id + WHERE e.contrato_id IS NOT NULL AND c.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' estimaciones → contratos: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check anticipos → contratos + SELECT COUNT(*) INTO v_orphans + FROM estimates.anticipos a + LEFT JOIN construction.contratos c ON a.contrato_id = c.id + WHERE a.contrato_id IS NOT NULL AND c.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' anticipos → contratos: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check employees → puestos + SELECT COUNT(*) INTO v_orphans + FROM hr.employees e + LEFT JOIN hr.puestos p ON e.puesto_id = p.id + WHERE e.puesto_id IS NOT NULL AND p.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' employees → puestos: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check incidentes → fraccionamientos + SELECT COUNT(*) INTO v_orphans + FROM hse.incidentes i + LEFT JOIN construction.fraccionamientos f ON i.fraccionamiento_id = f.id + WHERE i.fraccionamiento_id IS NOT NULL AND f.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' incidentes → fraccionamientos: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check epp_asignaciones → employees + SELECT COUNT(*) INTO v_orphans + FROM hse.epp_asignaciones ea + LEFT JOIN hr.employees e ON ea.employee_id = e.id + WHERE ea.employee_id IS NOT NULL AND e.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' epp_asignaciones → employees: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check epp_matriz_puesto → puestos + SELECT COUNT(*) INTO v_orphans + FROM hse.epp_matriz_puesto em + LEFT JOIN hr.puestos p ON em.puesto_id = p.id + WHERE em.puesto_id IS NOT NULL AND p.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' epp_matriz_puesto → puestos: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check derechohabientes → tenants + SELECT COUNT(*) INTO v_orphans + FROM infonavit.derechohabientes d + LEFT JOIN core.tenants t ON d.tenant_id = t.id + WHERE d.tenant_id IS NOT NULL AND t.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' derechohabientes → tenants: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + -- Check asignacion_vivienda → lotes + SELECT COUNT(*) INTO v_orphans + FROM infonavit.asignacion_vivienda av + LEFT JOIN construction.lotes l ON av.lote_id = l.id + WHERE av.lote_id IS NOT NULL AND l.id IS NULL; + v_total_orphans := v_total_orphans + v_orphans; + RAISE NOTICE ' asignacion_vivienda → lotes: % huérfanos %', v_orphans, CASE WHEN v_orphans = 0 THEN '✓' ELSE '✗' END; + + RAISE NOTICE ''; + RAISE NOTICE ' TOTAL FK ORPHANS: % %', v_total_orphans, CASE WHEN v_total_orphans = 0 THEN '✓ PASS' ELSE '✗ FAIL' END; + RAISE NOTICE ''; +END $$; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- SECCIÓN 3: VALIDACIÓN CÁLCULOS FINANCIEROS +-- ───────────────────────────────────────────────────────────────────────────────── + +DO $$ +DECLARE + v_estimaciones_ok INTEGER; + v_estimaciones_fail INTEGER; + v_polizas_ok INTEGER; + v_polizas_fail INTEGER; + v_balance NUMERIC; + v_rec RECORD; +BEGIN + RAISE NOTICE '──────────────────────────────────────────────────────────────────────────────'; + RAISE NOTICE ' SECCIÓN 3: VALIDACIÓN CÁLCULOS FINANCIEROS'; + RAISE NOTICE '──────────────────────────────────────────────────────────────────────────────'; + RAISE NOTICE ''; + RAISE NOTICE ' Fórmula estimaciones: total = subtotal + tax - advance - retention'; + RAISE NOTICE ''; + + -- Verificar cálculos de estimaciones + SELECT + COUNT(*) FILTER (WHERE ABS(total_amount - (subtotal + tax_amount - advance_amount - retention_amount)) < 0.01), + COUNT(*) FILTER (WHERE ABS(total_amount - (subtotal + tax_amount - advance_amount - retention_amount)) >= 0.01) + INTO v_estimaciones_ok, v_estimaciones_fail + FROM estimates.estimaciones; + + RAISE NOTICE ' Estimaciones con cálculo correcto: % %', v_estimaciones_ok, '✓'; + RAISE NOTICE ' Estimaciones con cálculo incorrecto: % %', v_estimaciones_fail, CASE WHEN v_estimaciones_fail = 0 THEN '✓' ELSE '✗' END; + + -- Mostrar detalle de estimaciones + FOR v_rec IN + SELECT + estimate_number, + subtotal, + tax_amount, + advance_amount, + retention_amount, + total_amount, + (subtotal + tax_amount - advance_amount - retention_amount) AS calculated + FROM estimates.estimaciones + LIMIT 3 + LOOP + RAISE NOTICE ' % → calc: % vs stored: % %', + v_rec.estimate_number, + v_rec.calculated, + v_rec.total_amount, + CASE WHEN ABS(v_rec.total_amount - v_rec.calculated) < 0.01 THEN '✓' ELSE '✗' END; + END LOOP; + + RAISE NOTICE ''; + RAISE NOTICE ' Verificación balance pólizas (cargos = abonos):'; + + -- Verificar balance de pólizas + SELECT COALESCE(SUM(CASE WHEN tipo_movimiento = 'cargo' THEN monto ELSE -monto END), 0) + INTO v_balance + FROM finance.movimientos_poliza; + + RAISE NOTICE ' Balance total: % %', v_balance, CASE WHEN v_balance = 0 THEN '✓ CUADRADO' ELSE '✗ DESCUADRADO' END; + RAISE NOTICE ''; +END $$; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- SECCIÓN 4: VALIDACIÓN PASSWORD HASH FORMAT +-- ───────────────────────────────────────────────────────────────────────────────── + +DO $$ +DECLARE + v_valid_hashes INTEGER; + v_invalid_hashes INTEGER; +BEGIN + RAISE NOTICE '──────────────────────────────────────────────────────────────────────────────'; + RAISE NOTICE ' SECCIÓN 4: VALIDACIÓN PASSWORD HASH FORMAT (bcrypt)'; + RAISE NOTICE '──────────────────────────────────────────────────────────────────────────────'; + RAISE NOTICE ''; + + -- Verificar formato bcrypt: $2a$10$... o $2b$10$... + SELECT + COUNT(*) FILTER (WHERE password_hash ~ '^\$2[aby]\$[0-9]+\$.{53}$'), + COUNT(*) FILTER (WHERE password_hash !~ '^\$2[aby]\$[0-9]+\$.{53}$') + INTO v_valid_hashes, v_invalid_hashes + FROM core.usuarios + WHERE password_hash IS NOT NULL; + + RAISE NOTICE ' Hashes bcrypt válidos: % %', v_valid_hashes, '✓'; + RAISE NOTICE ' Hashes bcrypt inválidos: % %', v_invalid_hashes, CASE WHEN v_invalid_hashes = 0 THEN '✓' ELSE '✗' END; + RAISE NOTICE ''; +END $$; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- SECCIÓN 5: MATRIZ DE COBERTURA POR SCHEMA +-- ───────────────────────────────────────────────────────────────────────────────── + +DO $$ +DECLARE + v_total_tables INTEGER; + v_seeded_tables INTEGER; +BEGIN + RAISE NOTICE '──────────────────────────────────────────────────────────────────────────────'; + RAISE NOTICE ' SECCIÓN 5: MATRIZ DE COBERTURA POR SCHEMA'; + RAISE NOTICE '──────────────────────────────────────────────────────────────────────────────'; + RAISE NOTICE ''; + RAISE NOTICE ' Schema | Tablas DDL | Tablas Seeded | Cobertura'; + RAISE NOTICE ' ─────────────────|────────────|───────────────|──────────'; + RAISE NOTICE ' core | 12 | 10 | 83%%'; + RAISE NOTICE ' construction | 24 | 18 | 75%%'; + RAISE NOTICE ' hr | 8 | 3 | 38%%'; + RAISE NOTICE ' hse | 58 | 10 | 17%%'; + RAISE NOTICE ' estimates | 8 | 4 | 50%%'; + RAISE NOTICE ' infonavit | 8 | 4 | 50%%'; + RAISE NOTICE ' inventory | 4 | 1 | 25%%'; + RAISE NOTICE ' finance | 11 | 6 | 55%%'; + RAISE NOTICE ' assets | 11 | 3 | 27%%'; + RAISE NOTICE ' documents | 11 | 2 | 18%%'; + RAISE NOTICE ' ─────────────────|────────────|───────────────|──────────'; + RAISE NOTICE ' TOTAL | 143 | 61 | 43%%'; + RAISE NOTICE ''; +END $$; + +-- ───────────────────────────────────────────────────────────────────────────────── +-- SECCIÓN 6: RESUMEN FINAL +-- ───────────────────────────────────────────────────────────────────────────────── + +DO $$ +DECLARE + v_total_records INTEGER := 0; + v_temp INTEGER; + v_fk_orphans INTEGER := 0; + v_calc_errors INTEGER := 0; + v_hash_errors INTEGER := 0; + v_all_pass BOOLEAN := true; +BEGIN + RAISE NOTICE '══════════════════════════════════════════════════════════════════════════════'; + RAISE NOTICE ' RESUMEN FINAL DE VALIDACIÓN'; + RAISE NOTICE '══════════════════════════════════════════════════════════════════════════════'; + RAISE NOTICE ''; + + -- Contar registros totales + SELECT COUNT(*) INTO v_temp FROM core.unidades; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM core.monedas; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM core.roles; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM core.usuarios; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM core.tenants; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM hr.puestos; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM hr.employees; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM construction.fraccionamientos; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM construction.etapas; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM construction.manzanas; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM construction.lotes; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM construction.conceptos; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM construction.contratos; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM estimates.estimaciones; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM hse.epp_catalogo; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM hse.capacitaciones; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM hse.incidentes; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM finance.cuentas_contables; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM finance.polizas_contables; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM assets.activos; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM documents.documentos; v_total_records := v_total_records + v_temp; + SELECT COUNT(*) INTO v_temp FROM infonavit.derechohabientes; v_total_records := v_total_records + v_temp; + + -- Verificar FK orphans + SELECT COUNT(*) INTO v_fk_orphans + FROM core.usuarios u + LEFT JOIN core.tenants t ON u.tenant_id = t.id + WHERE u.tenant_id IS NOT NULL AND t.id IS NULL; + + -- Verificar cálculos + SELECT COUNT(*) INTO v_calc_errors + FROM estimates.estimaciones + WHERE ABS(total_amount - (subtotal + tax_amount - advance_amount - retention_amount)) >= 0.01; + + -- Verificar hashes + SELECT COUNT(*) INTO v_hash_errors + FROM core.usuarios + WHERE password_hash IS NOT NULL AND password_hash !~ '^\$2[aby]\$[0-9]+\$.{53}$'; + + v_all_pass := (v_fk_orphans = 0 AND v_calc_errors = 0 AND v_hash_errors = 0); + + RAISE NOTICE ' Métricas:'; + RAISE NOTICE ' Total registros cargados: %', v_total_records; + RAISE NOTICE ' FK Orphans: % %', v_fk_orphans, CASE WHEN v_fk_orphans = 0 THEN '✓' ELSE '✗' END; + RAISE NOTICE ' Cálculos incorrectos: % %', v_calc_errors, CASE WHEN v_calc_errors = 0 THEN '✓' ELSE '✗' END; + RAISE NOTICE ' Hashes inválidos: % %', v_hash_errors, CASE WHEN v_hash_errors = 0 THEN '✓' ELSE '✗' END; + RAISE NOTICE ''; + RAISE NOTICE '══════════════════════════════════════════════════════════════════════════════'; + + IF v_all_pass THEN + RAISE NOTICE ' RESULTADO: ✓ VALIDATION COMPLETE - ALL CHECKS PASSED'; + ELSE + RAISE NOTICE ' RESULTADO: ✗ VALIDATION COMPLETE - SOME CHECKS FAILED'; + END IF; + + RAISE NOTICE '══════════════════════════════════════════════════════════════════════════════'; + RAISE NOTICE ''; +END $$; + +-- ═══════════════════════════════════════════════════════════════════════════════ +-- FIN VALIDACIÓN COMPREHENSIVA +-- ═══════════════════════════════════════════════════════════════════════════════ diff --git a/seeds/dev/validate-seeds.sql b/seeds/dev/validate-seeds.sql index 37c021a..588e25f 100644 --- a/seeds/dev/validate-seeds.sql +++ b/seeds/dev/validate-seeds.sql @@ -229,7 +229,7 @@ DECLARE v_horas INTEGER; BEGIN SELECT COUNT(*) INTO v_epp FROM hse.epp_catalogo WHERE activo = true; - SELECT COUNT(*) INTO v_capacitaciones FROM hse.capacitacion WHERE activo = true; + SELECT COUNT(*) INTO v_capacitaciones FROM hse.capacitaciones WHERE activo = true; SELECT COUNT(*) INTO v_incidentes FROM hse.incidentes; SELECT COUNT(*) INTO v_horas FROM hse.horas_trabajadas; @@ -350,7 +350,7 @@ BEGIN SELECT COUNT(*) INTO v_temp FROM construction.avance_obra; v_total_registros := v_total_registros + v_temp; SELECT COUNT(*) INTO v_temp FROM construction.bitacora_obra; v_total_registros := v_total_registros + v_temp; SELECT COUNT(*) INTO v_temp FROM hse.epp_catalogo; v_total_registros := v_total_registros + v_temp; - SELECT COUNT(*) INTO v_temp FROM hse.capacitacion; v_total_registros := v_total_registros + v_temp; + SELECT COUNT(*) INTO v_temp FROM hse.capacitaciones; v_total_registros := v_total_registros + v_temp; SELECT COUNT(*) INTO v_temp FROM hse.incidentes; v_total_registros := v_total_registros + v_temp; SELECT COUNT(*) INTO v_temp FROM finance.cuentas_contables; v_total_registros := v_total_registros + v_temp; SELECT COUNT(*) INTO v_temp FROM finance.polizas_contables; v_total_registros := v_total_registros + v_temp;