mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 14:53:18 +00:00
fix: recargar programa de obra (v_row no es una tabla)
<!-- CURSOR_AGENT_PR_BODY_BEGIN --> ## Problema Tras el #21 el GET ya no choca por agregados anidados, pero al recargar aparece: `fn_work_program_get (sqlstate=42P01): missing FROM-clause entry for table "v_row"` `v_row` es `jsonb`. Escribir `v_row.value` lo toma Postgres como `tabla.columna`, no como campo del JSON. El #21 destapó este bug: el 42803 cortaba antes de llegar al loop. ## Cambio Changeset **037** (no se edita el 036, ya corrido). La curva se arma en SQL (subquery + `SUM() OVER`) sin el `FOR` ni `v_row.value`. ## Cómo probar 1. Mergear este PR y aplicar Liquibase (037). 2. Abrir Programa de obra en la obra que ya importaste. Debe cargar sin toast rojo. 3. Recargar la página: igual. 4. Si hace falta, volver a Importar el Excel por partida y confirmar que se ve el programa. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-d8a5d34a-ead9-4912-8296-322cff799783?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-d8a5d34a-ead9-4912-8296-322cff799783&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div>
This commit is contained in:
parent
1a3fb49272
commit
7ffdd9f7bf
2 changed files with 86 additions and 0 deletions
|
|
@ -46,5 +46,6 @@
|
|||
<include file="changesets/034-fn-expense-update-reclassify.sql" relativeToChangelogFile="true"/>
|
||||
<include file="changesets/035-warehouse-materials-catalog.sql" relativeToChangelogFile="true"/>
|
||||
<include file="changesets/036-fn-work-program-get-curve.sql" relativeToChangelogFile="true"/>
|
||||
<include file="changesets/037-fn-work-program-get-curve-vrow.sql" relativeToChangelogFile="true"/>
|
||||
|
||||
</databaseChangeLog>
|
||||
|
|
|
|||
85
db/core/changesets/037-fn-work-program-get-curve-vrow.sql
Normal file
85
db/core/changesets/037-fn-work-program-get-curve-vrow.sql
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
--liquibase formatted sql
|
||||
-- PANELS · core · fn_work_program_get: v_row es jsonb, no un record (.value = 42P01)
|
||||
|
||||
--changeset panel:core-037-fn-work-program-get-curve-vrow splitStatements:false
|
||||
CREATE OR REPLACE FUNCTION core.fn_work_program_get(payload jsonb)
|
||||
RETURNS jsonb
|
||||
LANGUAGE plpgsql
|
||||
SECURITY INVOKER
|
||||
SET search_path = core
|
||||
AS $$
|
||||
DECLARE
|
||||
v_project_id bigint := NULLIF(payload->>'project_id', '')::bigint;
|
||||
v_program jsonb;
|
||||
v_periods jsonb;
|
||||
v_budget_total numeric(14,2);
|
||||
v_curve jsonb;
|
||||
BEGIN
|
||||
IF v_project_id IS NULL THEN
|
||||
RETURN core.rpc_err('VALIDATION', 'fn_work_program_get: project_id es obligatorio',
|
||||
jsonb_build_object('fn', 'fn_work_program_get'));
|
||||
END IF;
|
||||
|
||||
SELECT to_jsonb(wp) INTO v_program
|
||||
FROM work_programs wp WHERE wp.project_id = v_project_id;
|
||||
|
||||
IF v_program IS NULL THEN
|
||||
SELECT COALESCE(SUM(amount), 0) INTO v_budget_total FROM budget_items WHERE project_id = v_project_id;
|
||||
RETURN core.rpc_ok(
|
||||
jsonb_build_object(
|
||||
'program', NULL,
|
||||
'periods', '[]'::jsonb,
|
||||
'budget_subtotal', v_budget_total,
|
||||
'curve', '[]'::jsonb
|
||||
),
|
||||
format('Proyecto %s sin programa de obra', v_project_id),
|
||||
jsonb_build_object('fn', 'fn_work_program_get', 'project_id', v_project_id)
|
||||
);
|
||||
END IF;
|
||||
|
||||
SELECT COALESCE(jsonb_agg(to_jsonb(p) ORDER BY p.period_index), '[]'::jsonb) INTO v_periods
|
||||
FROM work_program_periods p WHERE p.program_id = (v_program->>'id')::bigint;
|
||||
|
||||
SELECT COALESCE(SUM(amount), 0) INTO v_budget_total FROM budget_items WHERE project_id = v_project_id;
|
||||
|
||||
-- Sin FOR + v_row.value (eso lo toma Postgres como tabla.columna → 42P01).
|
||||
-- SUM de montos en subquery; jsonb_agg y el acumulado van en capas distintas
|
||||
-- para no anidar agregados (42803).
|
||||
SELECT COALESCE(jsonb_agg(to_jsonb(y) ORDER BY y.period_index), '[]'::jsonb)
|
||||
INTO v_curve
|
||||
FROM (
|
||||
SELECT
|
||||
x.period_index,
|
||||
x.label,
|
||||
x.amount,
|
||||
CASE WHEN v_budget_total > 0 THEN round(x.amount / v_budget_total, 6) ELSE 0 END AS pct_period,
|
||||
CASE WHEN v_budget_total > 0
|
||||
THEN round(SUM(x.amount) OVER (ORDER BY x.period_index) / v_budget_total, 6)
|
||||
ELSE 0
|
||||
END AS pct_cumulative
|
||||
FROM (
|
||||
SELECT
|
||||
pr.period_index,
|
||||
pr.label,
|
||||
round(COALESCE(SUM(pa.amount), 0), 2) AS amount
|
||||
FROM work_program_periods pr
|
||||
LEFT JOIN work_program_partida_amounts pa ON pa.period_id = pr.id
|
||||
WHERE pr.program_id = (v_program->>'id')::bigint
|
||||
GROUP BY pr.period_index, pr.label
|
||||
) x
|
||||
) y;
|
||||
|
||||
RETURN core.rpc_ok(
|
||||
jsonb_build_object(
|
||||
'program', v_program,
|
||||
'periods', v_periods,
|
||||
'budget_subtotal', v_budget_total,
|
||||
'curve', v_curve
|
||||
),
|
||||
format('Programa de obra del proyecto %s', v_project_id),
|
||||
jsonb_build_object('fn', 'fn_work_program_get', 'project_id', v_project_id)
|
||||
);
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RETURN core.rpc_from_exception('fn_work_program_get', SQLSTATE, SQLERRM);
|
||||
END;
|
||||
$$;
|
||||
Loading…
Reference in a new issue