--liquibase formatted sql -- PANELS · core · fix ambigüedad de columnas en _cost_settings (RETURNS TABLE vs tenant_cost_settings) --changeset panel:core-028a-fix-cost-settings splitStatements:false CREATE OR REPLACE FUNCTION core._cost_settings(p_tenant_id integer) RETURNS TABLE ( budget_warn_pct numeric, budget_critical_pct numeric, default_iva_rate numeric ) LANGUAGE plpgsql STABLE SET search_path = core AS $$ BEGIN RETURN QUERY SELECT COALESCE(s.budget_warn_pct, 85::numeric), COALESCE(s.budget_critical_pct, 100::numeric), COALESCE(s.default_iva_rate, 0.16::numeric) FROM ( SELECT t.budget_warn_pct, t.budget_critical_pct, t.default_iva_rate FROM tenant_cost_settings t WHERE t.tenant_id = p_tenant_id ) s UNION ALL SELECT 85::numeric, 100::numeric, 0.16::numeric WHERE NOT EXISTS (SELECT 1 FROM tenant_cost_settings WHERE tenant_id = p_tenant_id) LIMIT 1; END; $$; --changeset panel:core-028b-fix-cost-budget-warning splitStatements:false CREATE OR REPLACE FUNCTION core._cost_budget_warning( p_tenant_id integer, p_budget_item_id bigint, p_add_subtotal numeric DEFAULT 0, p_add_qty numeric DEFAULT 0 ) RETURNS jsonb LANGUAGE plpgsql STABLE SET search_path = core AS $$ DECLARE v_item record; v_warn numeric; v_critical numeric; v_exec_amt numeric; v_exec_qty numeric; v_pct numeric; v_level text; BEGIN IF p_budget_item_id IS NULL THEN RETURN NULL; END IF; SELECT id, description, amount, quantity INTO v_item FROM budget_items WHERE id = p_budget_item_id; IF NOT FOUND OR COALESCE(v_item.amount, 0) <= 0 THEN RETURN NULL; END IF; SELECT cs.budget_warn_pct, cs.budget_critical_pct INTO v_warn, v_critical FROM core._cost_settings(p_tenant_id) cs; v_exec_amt := core._cost_executed_amount(p_budget_item_id) + COALESCE(p_add_subtotal, 0); v_exec_qty := core._cost_executed_qty(p_budget_item_id) + COALESCE(p_add_qty, 0); v_pct := round(v_exec_amt / v_item.amount * 100, 1); IF v_pct > v_critical THEN v_level := 'critical'; ELSIF v_pct > v_warn THEN v_level := 'warn'; ELSE RETURN NULL; END IF; RETURN jsonb_build_object( 'level', v_level, 'budget_item_id', p_budget_item_id, 'pct_after', v_pct, 'executed_amount', v_exec_amt, 'budget_amount', v_item.amount, 'executed_qty', v_exec_qty, 'budget_qty', v_item.quantity, 'message', format( 'Esta operación dejará el concepto "%s" al %s%% del presupuesto (importe)', left(v_item.description, 80), v_pct ) ); END; $$;