--liquibase formatted sql -- PANELS · core · reporte de nómina por periodo --changeset panel:core-049a-fn-payroll-report splitStatements:false CREATE OR REPLACE FUNCTION core.fn_payroll_report(payload jsonb) RETURNS jsonb LANGUAGE plpgsql SECURITY INVOKER SET search_path = core AS $$ DECLARE v_tid integer := core._payroll_tenant_id(payload); v_from date := NULLIF(payload->>'date_from', '')::date; v_to date := NULLIF(payload->>'date_to', '')::date; v_worker_id bigint := NULLIF(payload->>'worker_id', '')::bigint; v_project_id bigint := NULLIF(payload->>'project_id', '')::bigint; v_lines jsonb; v_adjustments jsonb; v_loans jsonb; v_settlements jsonb; v_total numeric; BEGIN IF v_from IS NULL OR v_to IS NULL THEN RETURN core.rpc_err('VALIDATION', 'fn_payroll_report: date_from y date_to son obligatorios', jsonb_build_object('fn', 'fn_payroll_report')); END IF; SELECT COALESCE(jsonb_agg(to_jsonb(x) ORDER BY x.week_start, x.last_name_p), '[]'::jsonb), COALESCE(SUM(x.payable_net), 0) INTO v_lines, v_total FROM ( SELECT l.id, l.worker_id, w.first_name, w.last_name_p, s.kind, s.project_id, p.name AS project_name, wk.week_start, wk.week_end, l.days, l.daily_wage, l.gross, l.discounts, l.loan_discount, l.payable_net FROM payroll_week_lines l JOIN payroll_sheets s ON s.id = l.sheet_id JOIN payroll_weeks wk ON wk.id = s.week_id JOIN workers w ON w.id = l.worker_id LEFT JOIN projects p ON p.id = COALESCE(s.project_id, l.project_id) WHERE wk.tenant_id = v_tid AND wk.week_start BETWEEN v_from AND v_to AND (v_worker_id IS NULL OR l.worker_id = v_worker_id) AND (v_project_id IS NULL OR s.project_id = v_project_id OR l.project_id = v_project_id) ) x; SELECT COALESCE(jsonb_agg(to_jsonb(a) ORDER BY a.adjustment_date), '[]'::jsonb) INTO v_adjustments FROM payroll_adjustments a JOIN payroll_weeks wk ON wk.id = a.week_id WHERE a.tenant_id = v_tid AND wk.week_start BETWEEN v_from AND v_to AND (v_worker_id IS NULL OR a.worker_id = v_worker_id) AND (v_project_id IS NULL OR a.project_id = v_project_id); SELECT COALESCE(jsonb_agg(to_jsonb(p) ORDER BY p.created_at), '[]'::jsonb) INTO v_loans FROM ( SELECT lp.amount, lp.label, lp.loan_id, l.worker_id, wk.week_start FROM loan_payments lp JOIN loans l ON l.id = lp.loan_id JOIN payroll_weeks wk ON wk.id = lp.week_id WHERE wk.tenant_id = v_tid AND wk.week_start BETWEEN v_from AND v_to AND (v_worker_id IS NULL OR l.worker_id = v_worker_id) ) p; SELECT COALESCE(jsonb_agg(to_jsonb(s) ORDER BY s.termination_date), '[]'::jsonb) INTO v_settlements FROM settlements s WHERE s.tenant_id = v_tid AND s.status = 'pagado' AND s.termination_date BETWEEN v_from AND v_to AND (v_worker_id IS NULL OR s.worker_id = v_worker_id) AND (v_project_id IS NULL OR s.project_id = v_project_id); RETURN core.rpc_ok( jsonb_build_object( 'lines', v_lines, 'adjustments', v_adjustments, 'loan_payments', v_loans, 'settlements', v_settlements, 'payable_total', core.round_money(v_total) ), format('Reporte de nómina %s a %s', v_from, v_to), jsonb_build_object('fn', 'fn_payroll_report', 'date_from', v_from, 'date_to', v_to) ); EXCEPTION WHEN OTHERS THEN RETURN core.rpc_from_exception('fn_payroll_report', SQLSTATE, SQLERRM); END; $$; --changeset panel:core-049b-grants endDelimiter:; splitStatements:true GRANT EXECUTE ON FUNCTION core.fn_payroll_report(jsonb) TO panels_core_app;