149 lines
5.8 KiB
PL/PgSQL
149 lines
5.8 KiB
PL/PgSQL
-- ============================================================================
|
|
-- PURCHASE EXTENSIONS - FASE 8 ERP-Core
|
|
-- ERP Clínicas (Base Genérica)
|
|
-- ============================================================================
|
|
-- Fecha: 2026-01-04
|
|
-- Versión: 1.0
|
|
-- ============================================================================
|
|
|
|
-- Schema
|
|
CREATE SCHEMA IF NOT EXISTS purchase;
|
|
|
|
-- ============================================================================
|
|
-- TABLAS
|
|
-- ============================================================================
|
|
|
|
-- Información de proveedores por producto
|
|
CREATE TABLE IF NOT EXISTS purchase.product_supplierinfo (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL,
|
|
partner_id UUID,
|
|
product_id UUID,
|
|
product_name VARCHAR(200),
|
|
product_code VARCHAR(50),
|
|
-- Precios y cantidades
|
|
min_qty NUMERIC(10,2) DEFAULT 1,
|
|
price NUMERIC(12,4) NOT NULL,
|
|
currency_id UUID,
|
|
-- Tiempos
|
|
delay INTEGER DEFAULT 1,
|
|
date_start DATE,
|
|
date_end DATE,
|
|
-- Extensiones clínica
|
|
aplica_iva BOOLEAN DEFAULT true,
|
|
requiere_receta BOOLEAN DEFAULT false,
|
|
tiempo_entrega_dias INTEGER DEFAULT 1,
|
|
-- Control
|
|
sequence INTEGER DEFAULT 10,
|
|
active BOOLEAN DEFAULT true,
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
COMMENT ON TABLE purchase.product_supplierinfo IS 'Información de productos por proveedor - FASE 8';
|
|
COMMENT ON COLUMN purchase.product_supplierinfo.requiere_receta IS 'El producto requiere receta médica';
|
|
COMMENT ON COLUMN purchase.product_supplierinfo.tiempo_entrega_dias IS 'Días estimados de entrega';
|
|
|
|
-- ============================================================================
|
|
-- CAMPOS ADICIONALES A PURCHASE_ORDERS (si existe)
|
|
-- ============================================================================
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF EXISTS (SELECT 1 FROM information_schema.tables
|
|
WHERE table_schema = 'purchase' AND table_name = 'purchase_orders') THEN
|
|
|
|
-- origin
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_schema = 'purchase' AND table_name = 'purchase_orders'
|
|
AND column_name = 'origin') THEN
|
|
ALTER TABLE purchase.purchase_orders ADD COLUMN origin VARCHAR(100);
|
|
END IF;
|
|
|
|
-- partner_ref
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_schema = 'purchase' AND table_name = 'purchase_orders'
|
|
AND column_name = 'partner_ref') THEN
|
|
ALTER TABLE purchase.purchase_orders ADD COLUMN partner_ref VARCHAR(100);
|
|
END IF;
|
|
|
|
-- date_approve
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_schema = 'purchase' AND table_name = 'purchase_orders'
|
|
AND column_name = 'date_approve') THEN
|
|
ALTER TABLE purchase.purchase_orders ADD COLUMN date_approve TIMESTAMPTZ;
|
|
END IF;
|
|
|
|
-- receipt_status
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
WHERE table_schema = 'purchase' AND table_name = 'purchase_orders'
|
|
AND column_name = 'receipt_status') THEN
|
|
ALTER TABLE purchase.purchase_orders ADD COLUMN receipt_status VARCHAR(20);
|
|
END IF;
|
|
|
|
END IF;
|
|
END $$;
|
|
|
|
-- ============================================================================
|
|
-- FUNCIONES
|
|
-- ============================================================================
|
|
|
|
-- Función para crear movimientos de stock
|
|
CREATE OR REPLACE FUNCTION purchase.action_create_stock_moves(p_order_id UUID)
|
|
RETURNS JSONB
|
|
LANGUAGE plpgsql
|
|
SECURITY DEFINER
|
|
AS $$
|
|
DECLARE
|
|
v_result JSONB := '{"moves_created": 0, "errors": []}'::JSONB;
|
|
v_move_count INTEGER := 0;
|
|
BEGIN
|
|
-- Verificar que la orden existe
|
|
IF NOT EXISTS (
|
|
SELECT 1 FROM purchase.purchase_orders
|
|
WHERE id = p_order_id
|
|
) THEN
|
|
v_result := jsonb_set(v_result, '{errors}',
|
|
v_result->'errors' || '["Orden de compra no encontrada"]'::JSONB);
|
|
RETURN v_result;
|
|
END IF;
|
|
|
|
-- Aquí se crearían los movimientos de stock
|
|
-- La implementación depende de la estructura de inventory.stock_moves
|
|
|
|
v_result := jsonb_set(v_result, '{moves_created}', to_jsonb(v_move_count));
|
|
v_result := jsonb_set(v_result, '{status}', '"success"'::JSONB);
|
|
|
|
RETURN v_result;
|
|
END;
|
|
$$;
|
|
|
|
COMMENT ON FUNCTION purchase.action_create_stock_moves IS 'Crea movimientos de stock desde orden de compra - FASE 8';
|
|
|
|
-- ============================================================================
|
|
-- ÍNDICES
|
|
-- ============================================================================
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_product_supplierinfo_tenant
|
|
ON purchase.product_supplierinfo(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_product_supplierinfo_partner
|
|
ON purchase.product_supplierinfo(partner_id);
|
|
CREATE INDEX IF NOT EXISTS idx_product_supplierinfo_product
|
|
ON purchase.product_supplierinfo(product_id);
|
|
CREATE INDEX IF NOT EXISTS idx_product_supplierinfo_dates
|
|
ON purchase.product_supplierinfo(tenant_id, date_start, date_end);
|
|
|
|
-- ============================================================================
|
|
-- RLS
|
|
-- ============================================================================
|
|
|
|
ALTER TABLE purchase.product_supplierinfo ENABLE ROW LEVEL SECURITY;
|
|
|
|
DROP POLICY IF EXISTS tenant_isolation_supplierinfo ON purchase.product_supplierinfo;
|
|
CREATE POLICY tenant_isolation_supplierinfo ON purchase.product_supplierinfo
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
-- ============================================================================
|
|
-- FIN PURCHASE EXTENSIONS
|
|
-- ============================================================================
|