- Add 02b-hr-employees.sql: 15 puestos, 15 employees for HSE EPP assignments - Add 11-infonavit.sql: registro, ofertas, derechohabientes, asignaciones - Add validate-seeds-comprehensive.sql: FK integrity, calculations, coverage - Update 06-estimaciones.sql: Document formula in header - Update 08-hse.sql: Fix hse.capacitacion → hse.capacitaciones, add 6 new tables - Update validate-seeds.sql: Fix table name reference New tables seeded: tipos_inspeccion, inspecciones, epp_matriz_puesto, epp_asignaciones, cumplimiento_obra, dias_sin_accidente Coverage increased: HSE 7%→17%, INFONAVIT 0%→50% Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
666 lines
37 KiB
SQL
666 lines
37 KiB
SQL
-- ═══════════════════════════════════════════════════════════════════════════════
|
|
-- 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
|
|
-- ═══════════════════════════════════════════════════════════════════════════════
|