[EPIC-001-FK-DEBILES] feat(ddl): Add conditional FK constraints to fix weak references
Add 19 conditional FK constraints to 4 schema files: - 06-inventory-ext: 7 FKs (warehouses, products, uom, stock_moves) - 07-purchase-ext: 5 FKs (purchase_orders, partners, products) - 03-hse: 3 FKs (almacen_temporal for EPP) - 10-documents: 4 FKs (documents, users) Features: - Constraints are conditional (only created if target tables exist) - Idempotent (can be re-run without errors) - Added 6 new indexes for FK fields Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
2cd5a1cce2
commit
2b69098fd4
@ -1264,5 +1264,65 @@ COMMENT ON TABLE hse.permisos_trabajo IS 'Permisos para trabajos de alto riesgo'
|
||||
COMMENT ON TABLE hse.indicadores_valores IS 'Valores calculados de indicadores HSE';
|
||||
|
||||
-- ============================================================================
|
||||
-- FIN DEL DDL
|
||||
-- FK CONSTRAINTS (Condicionales)
|
||||
-- NOTA: Los campos almacen_* pueden referenciar hse.almacen_temporal o
|
||||
-- inventory.warehouses del ERP-Core.
|
||||
-- ============================================================================
|
||||
|
||||
-- FK: epp_inventario.almacen_id → hse.almacen_temporal (preferido para HSE)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_epp_inventario_almacen'
|
||||
) THEN
|
||||
ALTER TABLE hse.epp_inventario
|
||||
ADD CONSTRAINT fk_epp_inventario_almacen
|
||||
FOREIGN KEY (almacen_id) REFERENCES hse.almacen_temporal(id)
|
||||
ON DELETE SET NULL;
|
||||
RAISE NOTICE 'FK creada: epp_inventario.almacen_id → hse.almacen_temporal';
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE NOTICE 'FK epp_inventario.almacen_id no creada: %', SQLERRM;
|
||||
END $$;
|
||||
|
||||
-- FK: epp_movimientos.almacen_origen_id → hse.almacen_temporal
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_epp_movimientos_almacen_origen'
|
||||
) THEN
|
||||
ALTER TABLE hse.epp_movimientos
|
||||
ADD CONSTRAINT fk_epp_movimientos_almacen_origen
|
||||
FOREIGN KEY (almacen_origen_id) REFERENCES hse.almacen_temporal(id)
|
||||
ON DELETE SET NULL;
|
||||
RAISE NOTICE 'FK creada: epp_movimientos.almacen_origen_id → hse.almacen_temporal';
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE NOTICE 'FK epp_movimientos.almacen_origen_id no creada: %', SQLERRM;
|
||||
END $$;
|
||||
|
||||
-- FK: epp_movimientos.almacen_destino_id → hse.almacen_temporal
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_epp_movimientos_almacen_destino'
|
||||
) THEN
|
||||
ALTER TABLE hse.epp_movimientos
|
||||
ADD CONSTRAINT fk_epp_movimientos_almacen_destino
|
||||
FOREIGN KEY (almacen_destino_id) REFERENCES hse.almacen_temporal(id)
|
||||
ON DELETE SET NULL;
|
||||
RAISE NOTICE 'FK creada: epp_movimientos.almacen_destino_id → hse.almacen_temporal';
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE NOTICE 'FK epp_movimientos.almacen_destino_id no creada: %', SQLERRM;
|
||||
END $$;
|
||||
|
||||
-- Índices para campos de almacén
|
||||
CREATE INDEX IF NOT EXISTS idx_epp_inventario_almacen_id ON hse.epp_inventario(almacen_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_epp_movimientos_almacen_origen ON hse.epp_movimientos(almacen_origen_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_epp_movimientos_almacen_destino ON hse.epp_movimientos(almacen_destino_id);
|
||||
|
||||
-- ============================================================================
|
||||
-- FIN DEL DDL
|
||||
-- FK constraints condicionales: 3
|
||||
-- ============================================================================
|
||||
|
||||
@ -207,7 +207,132 @@ COMMENT ON TABLE inventory.requisiciones_obra IS 'Extensión: requisiciones de m
|
||||
COMMENT ON TABLE inventory.requisicion_lineas IS 'Extensión: líneas de requisición de obra';
|
||||
COMMENT ON TABLE inventory.consumos_obra IS 'Extensión: consumos de materiales por obra/lote';
|
||||
|
||||
-- ============================================================================
|
||||
-- FK CONSTRAINTS A TABLAS ERP-CORE (Condicionales)
|
||||
-- NOTA: Estos constraints solo se crean si las tablas del ERP-Core existen.
|
||||
-- Si ERP-Core no está instalado, los campos quedan sin FK formal.
|
||||
-- ============================================================================
|
||||
|
||||
-- FK: almacenes_proyecto.warehouse_id → inventory.warehouses
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'inventory' AND tablename = 'warehouses') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_almacenes_proyecto_warehouse'
|
||||
) THEN
|
||||
ALTER TABLE inventory.almacenes_proyecto
|
||||
ADD CONSTRAINT fk_almacenes_proyecto_warehouse
|
||||
FOREIGN KEY (warehouse_id) REFERENCES inventory.warehouses(id)
|
||||
ON DELETE RESTRICT;
|
||||
RAISE NOTICE 'FK creada: almacenes_proyecto.warehouse_id → inventory.warehouses';
|
||||
END IF;
|
||||
ELSE
|
||||
RAISE NOTICE 'AVISO: inventory.warehouses no existe. FK warehouse_id pendiente.';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- FK: requisicion_lineas.product_id → products.products
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'products' AND tablename = 'products') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_requisicion_lineas_product'
|
||||
) THEN
|
||||
ALTER TABLE inventory.requisicion_lineas
|
||||
ADD CONSTRAINT fk_requisicion_lineas_product
|
||||
FOREIGN KEY (product_id) REFERENCES products.products(id)
|
||||
ON DELETE RESTRICT;
|
||||
RAISE NOTICE 'FK creada: requisicion_lineas.product_id → products.products';
|
||||
END IF;
|
||||
ELSE
|
||||
RAISE NOTICE 'AVISO: products.products no existe. FK product_id pendiente.';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- FK: requisicion_lineas.unit_id → core.uom (opcional porque es NULLABLE)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'core' AND tablename = 'uom') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_requisicion_lineas_unit'
|
||||
) THEN
|
||||
ALTER TABLE inventory.requisicion_lineas
|
||||
ADD CONSTRAINT fk_requisicion_lineas_unit
|
||||
FOREIGN KEY (unit_id) REFERENCES core.uom(id)
|
||||
ON DELETE SET NULL;
|
||||
RAISE NOTICE 'FK creada: requisicion_lineas.unit_id → core.uom';
|
||||
END IF;
|
||||
ELSE
|
||||
RAISE NOTICE 'AVISO: core.uom no existe. FK unit_id pendiente.';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- FK: requisiciones_obra.destination_warehouse_id → inventory.warehouses
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'inventory' AND tablename = 'warehouses') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_requisiciones_obra_dest_warehouse'
|
||||
) THEN
|
||||
ALTER TABLE inventory.requisiciones_obra
|
||||
ADD CONSTRAINT fk_requisiciones_obra_dest_warehouse
|
||||
FOREIGN KEY (destination_warehouse_id) REFERENCES inventory.warehouses(id)
|
||||
ON DELETE SET NULL;
|
||||
RAISE NOTICE 'FK creada: requisiciones_obra.destination_warehouse_id → inventory.warehouses';
|
||||
END IF;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- FK: requisiciones_obra.purchase_order_id → purchases.purchase_orders
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'purchases' AND tablename = 'purchase_orders') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_requisiciones_obra_purchase_order'
|
||||
) THEN
|
||||
ALTER TABLE inventory.requisiciones_obra
|
||||
ADD CONSTRAINT fk_requisiciones_obra_purchase_order
|
||||
FOREIGN KEY (purchase_order_id) REFERENCES purchases.purchase_orders(id)
|
||||
ON DELETE SET NULL;
|
||||
RAISE NOTICE 'FK creada: requisiciones_obra.purchase_order_id → purchases.purchase_orders';
|
||||
END IF;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- FK: consumos_obra.product_id → products.products
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'products' AND tablename = 'products') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_consumos_obra_product'
|
||||
) THEN
|
||||
ALTER TABLE inventory.consumos_obra
|
||||
ADD CONSTRAINT fk_consumos_obra_product
|
||||
FOREIGN KEY (product_id) REFERENCES products.products(id)
|
||||
ON DELETE RESTRICT;
|
||||
RAISE NOTICE 'FK creada: consumos_obra.product_id → products.products';
|
||||
END IF;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- FK: consumos_obra.stock_move_id → inventory.stock_moves
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'inventory' AND tablename = 'stock_moves') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_consumos_obra_stock_move'
|
||||
) THEN
|
||||
ALTER TABLE inventory.consumos_obra
|
||||
ADD CONSTRAINT fk_consumos_obra_stock_move
|
||||
FOREIGN KEY (stock_move_id) REFERENCES inventory.stock_moves(id)
|
||||
ON DELETE SET NULL;
|
||||
RAISE NOTICE 'FK creada: consumos_obra.stock_move_id → inventory.stock_moves';
|
||||
END IF;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- ============================================================================
|
||||
-- FIN DE EXTENSIONES INVENTORY
|
||||
-- Total tablas: 4
|
||||
-- FK constraints condicionales: 7
|
||||
-- ============================================================================
|
||||
|
||||
@ -221,7 +221,100 @@ COMMENT ON TABLE purchase.comparativo_cotizaciones IS 'Extensión: cuadro compar
|
||||
COMMENT ON TABLE purchase.comparativo_proveedores IS 'Extensión: proveedores participantes en comparativo';
|
||||
COMMENT ON TABLE purchase.comparativo_productos IS 'Extensión: productos cotizados por proveedor';
|
||||
|
||||
-- ============================================================================
|
||||
-- FK CONSTRAINTS A TABLAS ERP-CORE (Condicionales)
|
||||
-- NOTA: Estos constraints solo se crean si las tablas del ERP-Core existen.
|
||||
-- ============================================================================
|
||||
|
||||
-- FK: purchase_order_construction.purchase_order_id → purchases.purchase_orders
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'purchases' AND tablename = 'purchase_orders') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_po_construction_purchase_order'
|
||||
) THEN
|
||||
ALTER TABLE purchase.purchase_order_construction
|
||||
ADD CONSTRAINT fk_po_construction_purchase_order
|
||||
FOREIGN KEY (purchase_order_id) REFERENCES purchases.purchase_orders(id)
|
||||
ON DELETE CASCADE;
|
||||
RAISE NOTICE 'FK creada: purchase_order_construction.purchase_order_id → purchases.purchase_orders';
|
||||
END IF;
|
||||
ELSE
|
||||
RAISE NOTICE 'AVISO: purchases.purchase_orders no existe. FK purchase_order_id pendiente.';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- FK: supplier_construction.supplier_id → partners.partners
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'partners' AND tablename = 'partners') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_supplier_construction_partner'
|
||||
) THEN
|
||||
ALTER TABLE purchase.supplier_construction
|
||||
ADD CONSTRAINT fk_supplier_construction_partner
|
||||
FOREIGN KEY (supplier_id) REFERENCES partners.partners(id)
|
||||
ON DELETE RESTRICT;
|
||||
RAISE NOTICE 'FK creada: supplier_construction.supplier_id → partners.partners';
|
||||
END IF;
|
||||
ELSE
|
||||
RAISE NOTICE 'AVISO: partners.partners no existe. FK supplier_id pendiente.';
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- FK: comparativo_cotizaciones.winner_supplier_id → partners.partners
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'partners' AND tablename = 'partners') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_comparativo_winner_supplier'
|
||||
) THEN
|
||||
ALTER TABLE purchase.comparativo_cotizaciones
|
||||
ADD CONSTRAINT fk_comparativo_winner_supplier
|
||||
FOREIGN KEY (winner_supplier_id) REFERENCES partners.partners(id)
|
||||
ON DELETE SET NULL;
|
||||
RAISE NOTICE 'FK creada: comparativo_cotizaciones.winner_supplier_id → partners.partners';
|
||||
END IF;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- FK: comparativo_proveedores.supplier_id → partners.partners
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'partners' AND tablename = 'partners') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_comparativo_prov_supplier'
|
||||
) THEN
|
||||
ALTER TABLE purchase.comparativo_proveedores
|
||||
ADD CONSTRAINT fk_comparativo_prov_supplier
|
||||
FOREIGN KEY (supplier_id) REFERENCES partners.partners(id)
|
||||
ON DELETE RESTRICT;
|
||||
RAISE NOTICE 'FK creada: comparativo_proveedores.supplier_id → partners.partners';
|
||||
END IF;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- FK: comparativo_productos.product_id → products.products
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'products' AND tablename = 'products') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_comparativo_prod_product'
|
||||
) THEN
|
||||
ALTER TABLE purchase.comparativo_productos
|
||||
ADD CONSTRAINT fk_comparativo_prod_product
|
||||
FOREIGN KEY (product_id) REFERENCES products.products(id)
|
||||
ON DELETE RESTRICT;
|
||||
RAISE NOTICE 'FK creada: comparativo_productos.product_id → products.products';
|
||||
END IF;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Índice adicional para product_id (faltaba)
|
||||
CREATE INDEX IF NOT EXISTS idx_comparativo_prod_product_id ON purchase.comparativo_productos(product_id);
|
||||
|
||||
-- ============================================================================
|
||||
-- FIN DE EXTENSIONES PURCHASE
|
||||
-- Total tablas: 5
|
||||
-- FK constraints condicionales: 5
|
||||
-- ============================================================================
|
||||
|
||||
@ -828,5 +828,83 @@ COMMENT ON TABLE documents.access_logs IS 'Historial de acceso a documentos';
|
||||
COMMENT ON TABLE documents.document_shares IS 'Links de compartido externo';
|
||||
|
||||
-- ============================================================================
|
||||
-- FIN DEL SCRIPT
|
||||
-- FK CONSTRAINTS ADICIONALES
|
||||
-- NOTA: Fortalecer referencias internas y externas del schema documents.
|
||||
-- ============================================================================
|
||||
|
||||
-- FK: documents.parent_document_id → documents.documents (auto-referencia)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_documents_parent'
|
||||
) THEN
|
||||
ALTER TABLE documents.documents
|
||||
ADD CONSTRAINT fk_documents_parent
|
||||
FOREIGN KEY (parent_document_id) REFERENCES documents.documents(id)
|
||||
ON DELETE SET NULL;
|
||||
RAISE NOTICE 'FK creada: documents.parent_document_id → documents.documents';
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE NOTICE 'FK documents.parent_document_id no creada: %', SQLERRM;
|
||||
END $$;
|
||||
|
||||
-- FK: access_logs.document_id → documents.documents (para mantener logs aunque doc se elimine)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_access_logs_document'
|
||||
) THEN
|
||||
ALTER TABLE documents.access_logs
|
||||
ADD CONSTRAINT fk_access_logs_document
|
||||
FOREIGN KEY (document_id) REFERENCES documents.documents(id)
|
||||
ON DELETE CASCADE;
|
||||
RAISE NOTICE 'FK creada: access_logs.document_id → documents.documents';
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE NOTICE 'FK access_logs.document_id no creada: %', SQLERRM;
|
||||
END $$;
|
||||
|
||||
-- FK: access_logs.user_id → auth.users
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'auth' AND tablename = 'users') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_access_logs_user'
|
||||
) THEN
|
||||
ALTER TABLE documents.access_logs
|
||||
ADD CONSTRAINT fk_access_logs_user
|
||||
FOREIGN KEY (user_id) REFERENCES auth.users(id)
|
||||
ON DELETE SET NULL;
|
||||
RAISE NOTICE 'FK creada: access_logs.user_id → auth.users';
|
||||
END IF;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE NOTICE 'FK access_logs.user_id no creada: %', SQLERRM;
|
||||
END $$;
|
||||
|
||||
-- FK: document_shares.shared_by_id → auth.users
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'auth' AND tablename = 'users') THEN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'fk_document_shares_shared_by'
|
||||
) THEN
|
||||
ALTER TABLE documents.document_shares
|
||||
ADD CONSTRAINT fk_document_shares_shared_by
|
||||
FOREIGN KEY (shared_by_id) REFERENCES auth.users(id)
|
||||
ON DELETE SET NULL;
|
||||
RAISE NOTICE 'FK creada: document_shares.shared_by_id → auth.users';
|
||||
END IF;
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE NOTICE 'FK document_shares.shared_by_id no creada: %', SQLERRM;
|
||||
END $$;
|
||||
|
||||
-- Índices adicionales para campos sin índice
|
||||
CREATE INDEX IF NOT EXISTS idx_documents_parent ON documents.documents(parent_document_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_document_shares_shared_by ON documents.document_shares(shared_by_id);
|
||||
|
||||
-- ============================================================================
|
||||
-- FIN DEL SCRIPT
|
||||
-- FK constraints adicionales: 4
|
||||
-- ============================================================================
|
||||
|
||||
Loading…
Reference in New Issue
Block a user