mirror of
https://origin.cursor.com/mrdevmx/panels.git
synced 2026-10-09 13:23:17 +00:00
<!-- CURSOR_AGENT_PR_BODY_BEGIN --> ## Problema Tras cargar el programa, la pantalla pide en paralelo get / concepts / partidas / **vs-cost**. El vs-cost fallaba: `fn_work_program_vs_cost (sqlstate=42703): column m.project_id does not exist` `warehouse_movements` no tiene `project_id`. El proyecto está en `warehouses.project_id`. ## Cambio (changeset 038) - Salidas de almacén por `JOIN warehouses w ON w.id = m.warehouse_id WHERE w.project_id = …` - Ejecutado por partida **sin duplicar** al cruzar varias semanas (el join anterior multiplicaba el monto) ## Prueba local (hecha antes de pedir merge) En Postgres 16 corrí las **4 RPCs** que usa la página, con presupuesto, 2 semanas, gasto $50 y salida de almacén $25: - `fn_work_program_get` — curva 400 / 600 - `fn_work_program_list_concepts` — items - `fn_work_program_list_partidas` — A001 - `fn_work_program_vs_cost` — ejecutado semanal **75**, por partida **75** (no 150) Script: `scripts/verify-work-program-load.sh` ## Cómo probar en tu ambiente 1. Mergear y aplicar Liquibase (038). 2. Recargar Programa de obra en la obra ya importada. Sin toast rojo. 3. La pestaña / bloque de programado vs costo debe abrir. <!-- 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>
114 lines
4.5 KiB
PL/PgSQL
114 lines
4.5 KiB
PL/PgSQL
-- Verifica las 4 lecturas que carga Programa de obra (get, concepts, partidas, vs-cost).
|
|
-- Esquema mínimo con las columnas reales. No es Liquibase.
|
|
|
|
DROP SCHEMA IF EXISTS core CASCADE;
|
|
CREATE SCHEMA core;
|
|
SET search_path = core;
|
|
|
|
CREATE FUNCTION rpc_generic_messages() RETURNS text[] LANGUAGE sql IMMUTABLE AS $$
|
|
SELECT ARRAY['OK']::text[];
|
|
$$;
|
|
CREATE FUNCTION rpc_assert_message(p_message text) RETURNS void LANGUAGE plpgsql IMMUTABLE AS $$
|
|
BEGIN
|
|
IF p_message IS NULL OR btrim(p_message) = '' THEN RAISE EXCEPTION 'empty'; END IF;
|
|
END;
|
|
$$;
|
|
CREATE FUNCTION rpc_ok(p_data jsonb, p_message text, p_ctx jsonb DEFAULT '{}'::jsonb) RETURNS jsonb
|
|
LANGUAGE plpgsql IMMUTABLE AS $$
|
|
BEGIN
|
|
PERFORM rpc_assert_message(p_message);
|
|
RETURN jsonb_build_object('ok', true, 'code', 'OK', 'message', p_message, 'data', p_data);
|
|
END;
|
|
$$;
|
|
CREATE FUNCTION rpc_err(p_code text, p_message text, p_ctx jsonb DEFAULT '{}'::jsonb, p_errors jsonb DEFAULT NULL) RETURNS jsonb
|
|
LANGUAGE plpgsql IMMUTABLE AS $$
|
|
BEGIN
|
|
PERFORM rpc_assert_message(p_message);
|
|
RETURN jsonb_build_object('ok', false, 'code', p_code, 'message', p_message, 'data', NULL);
|
|
END;
|
|
$$;
|
|
CREATE FUNCTION rpc_from_exception(p_fn text, p_sqlstate text, p_message text, p_detail text DEFAULT NULL) RETURNS jsonb
|
|
LANGUAGE plpgsql IMMUTABLE AS $$
|
|
BEGIN
|
|
RETURN rpc_err('INTERNAL', format('Error inesperado en %s (sqlstate=%s): %s', p_fn, p_sqlstate, p_message),
|
|
jsonb_build_object('fn', p_fn, 'sqlstate', p_sqlstate));
|
|
END;
|
|
$$;
|
|
|
|
CREATE TABLE companies (id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name text);
|
|
CREATE TABLE projects (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
name text, status text DEFAULT 'activo', tenant_id int, start_date date, end_date date
|
|
);
|
|
CREATE TABLE budget_chapters (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
project_id BIGINT REFERENCES projects(id),
|
|
code text, name text, sort_order int DEFAULT 0
|
|
);
|
|
CREATE TABLE budget_items (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
project_id BIGINT REFERENCES projects(id),
|
|
chapter_id BIGINT REFERENCES budget_chapters(id),
|
|
code text, description text, unit text DEFAULT '', amount numeric(14,2) DEFAULT 0, sort_order int DEFAULT 0
|
|
);
|
|
CREATE TABLE work_programs (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
project_id BIGINT UNIQUE REFERENCES projects(id),
|
|
start_date date, end_date date, duration_days int, source text, status text
|
|
);
|
|
CREATE TABLE work_program_periods (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
program_id BIGINT REFERENCES work_programs(id),
|
|
period_index int, label text, start_date date, end_date date
|
|
);
|
|
CREATE TABLE work_program_partida_amounts (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
program_id BIGINT REFERENCES work_programs(id),
|
|
budget_chapter_id BIGINT REFERENCES budget_chapters(id),
|
|
period_id BIGINT REFERENCES work_program_periods(id),
|
|
amount numeric(14,2)
|
|
);
|
|
CREATE TABLE work_program_concept_slots (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
program_id BIGINT, budget_item_id BIGINT, period_id BIGINT, start_pct numeric, end_pct numeric
|
|
);
|
|
CREATE TABLE work_program_progress (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
program_id BIGINT, budget_item_id BIGINT, period_id BIGINT, pct_complete numeric
|
|
);
|
|
CREATE TABLE expense_entries (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
project_id BIGINT, expense_date date, subtotal numeric(14,2),
|
|
status text, counts_toward_budget boolean, budget_item_id BIGINT
|
|
);
|
|
CREATE TABLE warehouses (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
tenant_id int, kind text, project_id BIGINT
|
|
);
|
|
CREATE TABLE warehouse_materials (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, tenant_id int, code text, name text
|
|
);
|
|
CREATE TABLE warehouse_movements (
|
|
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
tenant_id int,
|
|
warehouse_id BIGINT REFERENCES warehouses(id),
|
|
material_id BIGINT,
|
|
movement_type text,
|
|
movement_date date,
|
|
quantity numeric,
|
|
total_cost numeric(14,2),
|
|
budget_item_id BIGINT
|
|
);
|
|
|
|
CREATE FUNCTION _cost_executed_amount(p_budget_item_id bigint) RETURNS numeric
|
|
LANGUAGE sql STABLE SET search_path = core AS $$
|
|
SELECT round(COALESCE(
|
|
(SELECT SUM(e.subtotal) FROM expense_entries e
|
|
WHERE e.budget_item_id = p_budget_item_id AND e.status = 'confirmed' AND e.counts_toward_budget = true),
|
|
0
|
|
) + COALESCE(
|
|
(SELECT SUM(m.total_cost) FROM warehouse_movements m
|
|
WHERE m.budget_item_id = p_budget_item_id AND m.movement_type = 'exit'),
|
|
0
|
|
), 2);
|
|
$$;
|