Фикс: задвоенное v_form2_view/v_form2_sheet_jsonb после PR #292 #295

Merged
tsygankoviva merged 1 commits from feat/294-fix-0052-duplicate-v-form2-view into test 2026-11-03 18:10:18 +03:00
3 changed files with 123 additions and 433 deletions
Showing only changes of commit 049da41b0b - Show all commits

View File

@ -5,7 +5,7 @@
-- 3) план лимитных строк в АХР переводится в тыс. руб. (как аренда/
-- коммуналка/охрана/Смета), а не остаётся в рублях.
--
-- CREATE OR REPLACE для v3.v_form2_view, v3.sync_form2_ahr_satellite_lines и
-- CREATE OR REPLACE для v3.sync_form2_ahr_satellite_lines и
-- v3.sync_form2_ahr_satellite_line ниже воспроизводят тело функций, актуальное
-- на голове миграций этой ветки (0051): сами функции последний раз целиком
-- переопределены в 0050_form2_ahr_spod_column.sql (ради колонки СПОД),
@ -13,6 +13,20 @@
-- он редактирует только v3.add_budget_line). Правится только ветка
-- AHR_LIMIT; ветки AHR/CAP/OPER/AHR_RENT/AHR_UTILITY/AHR_SECURITY/OTCH9F/SMETA
-- и переносы аренды/коммуналки/охраны копируются из 0050 без изменений.
--
-- Issue #294 (fix после PR #292): v3.v_form2_view здесь определяется только
-- один раз, ниже, в теле, унаследованном от независимой ветки AURORA-1850
-- (upd_form_cells_subtree, DROP+CREATE с 4-м параметром p_focus_lines для
-- частичного пересчёта поддерева — его использует v3._form_affected_rows
-- 4-арг. вызовом, а v3.v_form_view — 3-арг. вызовом с дефолтом NULL, см.
-- ниже). PR #292 слил эту ветку с данной конкатенацией SQL-файлов и внёс
-- вторую, более старую (3-арг., без p_focus_lines) CREATE v3.v_form2_view
-- выше DROP на той же сигнатуре — без неё DROP не находит жертву, а раз
-- итоговая копия в 4-арг. теле не содержала правок AURORA-1897/1906, они
-- исчезали целиком. Вторая CREATE удалена, фикс AURORA-1897 (period/
-- limit_without_vat/amount_year/строка «Итого») и AURORA-1906 (fact_q4.spod
-- в AHR_RENT/AHR_UTILITY/AHR_SECURITY) перенесены в ветки ниже, внутри уже
-- имеющегося 4-арг. тела, с сохранением фильтра p_focus_lines.
-- 1. Справочник: period — YEAR / QUARTER / MONTH, по умолчанию QUARTER.
@ -111,389 +125,6 @@ AS $function$
$function$;
-- 4а. v3.v_form2_view: ветка AHR_LIMIT — amount от limit_without_vat,
-- amount_year, period в data, последняя строка «Итого» (row_type ROOT).
CREATE OR REPLACE FUNCTION v3.v_form2_view(
p_form_id INT,
p_sheet VARCHAR,
p_sections TEXT[] DEFAULT NULL
)
RETURNS TABLE (
row_type VARCHAR,
depth INT,
sort_order BIGINT,
data JSONB
)
AS $function$
BEGIN
IF p_sheet IN ('AHR','CAP','OPER') THEN
RETURN QUERY
SELECT
j.row_type,
j.depth,
ROW_NUMBER() OVER (ORDER BY j._sort_path) AS sort_order,
jsonb_build_object(
'line_id', j.line_id,
'header', j.header,
'plan', j.plan_data,
'seq_dfip', j.seq_dfip_data,
'seq_ssp', j.seq_ssp_data,
'approved', j.approved_data,
'contract', j.contract_data,
'booking', j.booking_data,
'q1', j.q1_data,
'q2', j.q2_data,
'q3', j.q3_data,
'q4', j.q4_data,
'totals', j.totals_data
) AS data
FROM v3.v_form2_sheet_jsonb(p_form_id, p_sheet, p_sections) j
ORDER BY j._sort_path;
RETURN;
END IF;
IF p_sheet = 'AHR_LIMIT' THEN
RETURN QUERY
WITH RECURSIVE tree AS (
SELECT id AS root_id, id AS desc_id FROM v3.limit_template
UNION
SELECT t.root_id, child.id
FROM tree t
JOIN v3.limit_template child ON child.parent_id = t.desc_id
),
leaf_amt AS (
SELECT lt.id,
fl.qty_q1, fl.qty_q2, fl.qty_q3, fl.qty_q4,
v3._form2_ahr_limit_amount(lt.period, lt.limit_without_vat, fl.qty_q1) AS amount_q1,
v3._form2_ahr_limit_amount(lt.period, lt.limit_without_vat, fl.qty_q2) AS amount_q2,
v3._form2_ahr_limit_amount(lt.period, lt.limit_without_vat, fl.qty_q3) AS amount_q3,
v3._form2_ahr_limit_amount(lt.period, lt.limit_without_vat, fl.qty_q4) AS amount_q4
FROM v3.limit_template lt
LEFT JOIN v3.form_limit fl
ON fl.template_id = lt.id AND fl.budget_form_id = p_form_id
WHERE lt.row_type = 'LEAF'
),
leaf_amt_year AS (
SELECT la.*,
(COALESCE(la.amount_q1,0)+COALESCE(la.amount_q2,0)
+COALESCE(la.amount_q3,0)+COALESCE(la.amount_q4,0)) AS amount_year
FROM leaf_amt la
),
agg AS (
SELECT t.root_id,
SUM(la.qty_q1) AS qty_q1, SUM(la.amount_q1) AS amount_q1,
SUM(la.qty_q2) AS qty_q2, SUM(la.amount_q2) AS amount_q2,
SUM(la.qty_q3) AS qty_q3, SUM(la.amount_q3) AS amount_q3,
SUM(la.qty_q4) AS qty_q4, SUM(la.amount_q4) AS amount_q4,
SUM(la.amount_year) AS amount_year
FROM tree t
JOIN leaf_amt_year la ON la.id = t.desc_id
GROUP BY t.root_id
),
rows AS (
SELECT
CASE lt.row_type WHEN 'SECTION' THEN 'ROOT'
WHEN 'GROUP' THEN 'GROUP'
WHEN 'LEAF' THEN 'INPUT' END::VARCHAR AS row_type,
CASE lt.row_type WHEN 'SECTION' THEN 0 WHEN 'GROUP' THEN 1 ELSE 2 END AS depth,
lt.sort_order::BIGINT AS sort_order,
jsonb_build_object(
'id', lt.id,
'section_no', lt.section_no,
'expense_item_code',lt.expense_item_code,
'name', lt.name,
'unit', lt.unit,
'period', lt.period,
'limit_with_vat', lt.limit_with_vat,
'limit_without_vat',lt.limit_without_vat,
'qty_q1', a.qty_q1, 'amount_q1', a.amount_q1,
'qty_q2', a.qty_q2, 'amount_q2', a.amount_q2,
'qty_q3', a.qty_q3, 'amount_q3', a.amount_q3,
'qty_q4', a.qty_q4, 'amount_q4', a.amount_q4,
'amount_year', a.amount_year,
'comment', fl.comment
) AS data
FROM v3.limit_template lt
LEFT JOIN agg a ON a.root_id = lt.id
LEFT JOIN v3.form_limit fl
ON fl.template_id = lt.id AND fl.budget_form_id = p_form_id
UNION ALL
SELECT
'ROOT'::VARCHAR AS row_type,
0 AS depth,
999999::BIGINT AS sort_order,
jsonb_build_object(
'id', 0,
'name', 'Итого',
'amount_q1', totals.amount_q1,
'amount_q2', totals.amount_q2,
'amount_q3', totals.amount_q3,
'amount_q4', totals.amount_q4,
'amount_year', totals.amount_year
) AS data
FROM (
SELECT
SUM(la.amount_q1) AS amount_q1,
SUM(la.amount_q2) AS amount_q2,
SUM(la.amount_q3) AS amount_q3,
SUM(la.amount_q4) AS amount_q4,
SUM(la.amount_year) AS amount_year
FROM leaf_amt_year la
) totals
)
SELECT rows.row_type, rows.depth, rows.sort_order, rows.data
FROM rows
ORDER BY rows.sort_order;
RETURN;
END IF;
IF p_sheet = 'AHR_RENT' THEN
RETURN QUERY
SELECT
'INPUT'::VARCHAR,
0,
ROW_NUMBER() OVER (ORDER BY rd.id) AS sort_order,
jsonb_build_object(
'id', rd.id,
'line_id', rd.line_id,
'vsp_id', rd.vsp_id,
'address', v.address,
'object_type', v.format,
'rented_area', v.total_area,
'contract_number', rd.contract_number,
'contract_end_date',rd.contract_end_date,
'plan', jsonb_build_object('q1', rd.plan_q1, 'q2', rd.plan_q2, 'q3', rd.plan_q3, 'q4', rd.plan_q4,
'year', COALESCE(rd.plan_q1,0)+COALESCE(rd.plan_q2,0)+COALESCE(rd.plan_q3,0)+COALESCE(rd.plan_q4,0)),
'fact_q1', jsonb_build_object('jan', rd.actual_jan, 'feb', rd.actual_feb, 'mar', rd.actual_mar,
'total', COALESCE(rd.actual_jan,0)+COALESCE(rd.actual_feb,0)+COALESCE(rd.actual_mar,0)),
'fact_q2', jsonb_build_object('apr', rd.actual_apr, 'may', rd.actual_may, 'jun', rd.actual_jun,
'total', COALESCE(rd.actual_apr,0)+COALESCE(rd.actual_may,0)+COALESCE(rd.actual_jun,0)),
'fact_q3', jsonb_build_object('jul', rd.actual_jul, 'aug', rd.actual_aug, 'sep', rd.actual_sep,
'total', COALESCE(rd.actual_jul,0)+COALESCE(rd.actual_aug,0)+COALESCE(rd.actual_sep,0)),
'fact_q4', jsonb_build_object('oct', rd.actual_oct, 'nov', rd.actual_nov, 'dec', rd.actual_dec, 'spod', rd.actual_spod,
'total', COALESCE(rd.actual_oct,0)+COALESCE(rd.actual_nov,0)+COALESCE(rd.actual_dec,0)+COALESCE(rd.actual_spod,0)),
'comment', rd.comment
)
FROM v3.rent_detail rd
JOIN v3.budget_line bl ON bl.id = rd.line_id
JOIN v3.vsp v ON v.id = rd.vsp_id
WHERE bl.budget_form_id = p_form_id
ORDER BY rd.id;
RETURN;
END IF;
IF p_sheet = 'AHR_UTILITY' THEN
RETURN QUERY
SELECT
'INPUT'::VARCHAR,
0,
ROW_NUMBER() OVER (ORDER BY ud.id) AS sort_order,
jsonb_build_object(
'id', ud.id,
'line_id', ud.line_id,
'vsp_id', ud.vsp_id,
'address', v.address,
'object_type', v.format,
'object_area', v.total_area,
'contract_number', ud.contract_number,
'contract_end_date',ud.contract_end_date,
'plan', jsonb_build_object('q1', ud.plan_q1, 'q2', ud.plan_q2, 'q3', ud.plan_q3, 'q4', ud.plan_q4,
'year', COALESCE(ud.plan_q1,0)+COALESCE(ud.plan_q2,0)+COALESCE(ud.plan_q3,0)+COALESCE(ud.plan_q4,0)),
'fact_q1', jsonb_build_object('jan', ud.actual_jan, 'feb', ud.actual_feb, 'mar', ud.actual_mar,
'total', COALESCE(ud.actual_jan,0)+COALESCE(ud.actual_feb,0)+COALESCE(ud.actual_mar,0)),
'fact_q2', jsonb_build_object('apr', ud.actual_apr, 'may', ud.actual_may, 'jun', ud.actual_jun,
'total', COALESCE(ud.actual_apr,0)+COALESCE(ud.actual_may,0)+COALESCE(ud.actual_jun,0)),
'fact_q3', jsonb_build_object('jul', ud.actual_jul, 'aug', ud.actual_aug, 'sep', ud.actual_sep,
'total', COALESCE(ud.actual_jul,0)+COALESCE(ud.actual_aug,0)+COALESCE(ud.actual_sep,0)),
'fact_q4', jsonb_build_object('oct', ud.actual_oct, 'nov', ud.actual_nov, 'dec', ud.actual_dec, 'spod', ud.actual_spod,
'total', COALESCE(ud.actual_oct,0)+COALESCE(ud.actual_nov,0)+COALESCE(ud.actual_dec,0)+COALESCE(ud.actual_spod,0)),
'comment', ud.comment
)
FROM v3.utility_detail ud
JOIN v3.budget_line bl ON bl.id = ud.line_id
JOIN v3.vsp v ON v.id = ud.vsp_id
WHERE bl.budget_form_id = p_form_id
ORDER BY ud.id;
RETURN;
END IF;
IF p_sheet = 'AHR_SECURITY' THEN
RETURN QUERY
SELECT
'INPUT'::VARCHAR,
0,
ROW_NUMBER() OVER (ORDER BY sd.id) AS sort_order,
jsonb_build_object(
'id', sd.id,
'line_id', sd.line_id,
'vsp_id', sd.vsp_id,
'address', v.address,
'object_type', v.format,
'object_area', v.total_area,
'contract_number', sd.contract_number,
'contract_end_date',sd.contract_end_date,
'plan', jsonb_build_object('q1', sd.plan_q1, 'q2', sd.plan_q2, 'q3', sd.plan_q3, 'q4', sd.plan_q4,
'year', COALESCE(sd.plan_q1,0)+COALESCE(sd.plan_q2,0)+COALESCE(sd.plan_q3,0)+COALESCE(sd.plan_q4,0)),
'fact_q1', jsonb_build_object('jan', sd.actual_jan, 'feb', sd.actual_feb, 'mar', sd.actual_mar,
'total', COALESCE(sd.actual_jan,0)+COALESCE(sd.actual_feb,0)+COALESCE(sd.actual_mar,0)),
'fact_q2', jsonb_build_object('apr', sd.actual_apr, 'may', sd.actual_may, 'jun', sd.actual_jun,
'total', COALESCE(sd.actual_apr,0)+COALESCE(sd.actual_may,0)+COALESCE(sd.actual_jun,0)),
'fact_q3', jsonb_build_object('jul', sd.actual_jul, 'aug', sd.actual_aug, 'sep', sd.actual_sep,
'total', COALESCE(sd.actual_jul,0)+COALESCE(sd.actual_aug,0)+COALESCE(sd.actual_sep,0)),
'fact_q4', jsonb_build_object('oct', sd.actual_oct, 'nov', sd.actual_nov, 'dec', sd.actual_dec, 'spod', sd.actual_spod,
'total', COALESCE(sd.actual_oct,0)+COALESCE(sd.actual_nov,0)+COALESCE(sd.actual_dec,0)+COALESCE(sd.actual_spod,0)),
'comment', sd.comment
)
FROM v3.security_detail sd
JOIN v3.budget_line bl ON bl.id = sd.line_id
JOIN v3.vsp v ON v.id = sd.vsp_id
WHERE bl.budget_form_id = p_form_id
ORDER BY sd.id;
RETURN;
END IF;
IF p_sheet = 'OTCH9F' THEN
RETURN QUERY
WITH base AS (
SELECT far.id, far.budget_form_id, far.expense_item_id,
far.equipment_name, far.month,
far.acquired_qty_604, far.acquired_amt_604,
far.disposed_qty_604, far.disposed_amt_604,
far.acquired_qty_60415, far.acquired_amt_60415,
far.transferred_qty_60415, far.transferred_amt_60415,
far.go_balance_only_amt,
FIRST_VALUE(COALESCE(far.opening_qty_604,0))
OVER w AS base_qty_604,
FIRST_VALUE(COALESCE(far.opening_amt_604,0))
OVER w AS base_amt_604,
FIRST_VALUE(COALESCE(far.opening_qty_60415,0))
OVER w AS base_qty_60415,
FIRST_VALUE(COALESCE(far.opening_amt_60415,0))
OVER w AS base_amt_60415,
COALESCE(SUM(COALESCE(far.acquired_qty_604,0) - COALESCE(far.disposed_qty_604,0))
OVER w_prev, 0) AS cum_dq_604,
COALESCE(SUM(COALESCE(far.acquired_amt_604,0) - COALESCE(far.disposed_amt_604,0))
OVER w_prev, 0) AS cum_da_604,
COALESCE(SUM(COALESCE(far.acquired_qty_60415,0) - COALESCE(far.transferred_qty_60415,0))
OVER w_prev, 0) AS cum_dq_60415,
COALESCE(SUM(COALESCE(far.acquired_amt_60415,0) - COALESCE(far.transferred_amt_60415,0))
OVER w_prev, 0) AS cum_da_60415
FROM v3.fixed_asset_report far
WHERE far.budget_form_id = p_form_id
WINDOW w AS (PARTITION BY far.budget_form_id, far.expense_item_id, far.equipment_name
ORDER BY far.month),
w_prev AS (PARTITION BY far.budget_form_id, far.expense_item_id, far.equipment_name
ORDER BY far.month
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)
),
eff AS (
SELECT b.*,
(b.base_qty_604 + b.cum_dq_604) AS opening_qty_604_eff,
(b.base_amt_604 + b.cum_da_604) AS opening_amt_604_eff,
(b.base_qty_60415 + b.cum_dq_60415) AS opening_qty_60415_eff,
(b.base_amt_60415 + b.cum_da_60415) AS opening_amt_60415_eff
FROM base b
)
SELECT
'INPUT'::VARCHAR,
0,
ROW_NUMBER() OVER (ORDER BY eff.expense_item_id, eff.month) AS sort_order,
jsonb_build_object(
'id', eff.id,
'expense_item_id', ei.id,
'item_id', ei.item_id,
'section_code', ei.section_code,
'equipment_name', eff.equipment_name,
'month', eff.month,
'b_604', jsonb_build_object(
'opening_qty', eff.opening_qty_604_eff,
'opening_amt', eff.opening_amt_604_eff,
'acquired_qty', eff.acquired_qty_604,
'acquired_amt', eff.acquired_amt_604,
'disposed_qty', eff.disposed_qty_604,
'disposed_amt', eff.disposed_amt_604
),
'b_60415', jsonb_build_object(
'opening_qty', eff.opening_qty_60415_eff,
'opening_amt', eff.opening_amt_60415_eff,
'acquired_qty', eff.acquired_qty_60415,
'acquired_amt', eff.acquired_amt_60415,
'transferred_qty',eff.transferred_qty_60415,
'transferred_amt',eff.transferred_amt_60415
),
'totals', jsonb_build_object(
'acquired_total', COALESCE(eff.acquired_amt_604,0)+COALESCE(eff.acquired_amt_60415,0)
+COALESCE(eff.go_balance_only_amt,0)-COALESCE(eff.transferred_amt_60415,0),
'go_balance_only',eff.go_balance_only_amt,
'disposed_total', COALESCE(eff.disposed_amt_604,0),
'balance_qty', (eff.opening_qty_604_eff + COALESCE(eff.acquired_qty_604,0) - COALESCE(eff.disposed_qty_604,0))
+ (eff.opening_qty_60415_eff + COALESCE(eff.acquired_qty_60415,0) - COALESCE(eff.transferred_qty_60415,0)),
'balance_amt', (eff.opening_amt_604_eff + COALESCE(eff.acquired_amt_604,0) - COALESCE(eff.disposed_amt_604,0))
+ (eff.opening_amt_60415_eff + COALESCE(eff.acquired_amt_60415,0) - COALESCE(eff.transferred_amt_60415,0))
)
)
FROM eff
JOIN v3.expense_item ei ON ei.id = eff.expense_item_id
ORDER BY eff.expense_item_id, eff.month;
RETURN;
END IF;
IF p_sheet = 'SMETA' THEN
RETURN QUERY
SELECT
sm.row_type,
sm.depth,
ROW_NUMBER() OVER (ORDER BY sm.section_code) AS sort_order,
jsonb_build_object(
'section_code', sm.section_code,
'name', sm.name,
'plan', jsonb_build_object(
'support', jsonb_build_object('q1', sm.plan_supp_q1, 'q2', sm.plan_supp_q2, 'q3', sm.plan_supp_q3, 'q4', sm.plan_supp_q4, 'year', sm.plan_supp_year),
'development', jsonb_build_object('q1', sm.plan_dev_q1, 'q2', sm.plan_dev_q2, 'q3', sm.plan_dev_q3, 'q4', sm.plan_dev_q4, 'year', sm.plan_dev_year)
),
'approved', jsonb_build_object(
'support', jsonb_build_object('q1', sm.appr_supp_q1, 'q2', sm.appr_supp_q2, 'q3', sm.appr_supp_q3, 'q4', sm.appr_supp_q4, 'year', sm.appr_supp_year),
'development', jsonb_build_object('q1', sm.appr_dev_q1, 'q2', sm.appr_dev_q2, 'q3', sm.appr_dev_q3, 'q4', sm.appr_dev_q4, 'year', sm.appr_dev_year)
),
'fact', jsonb_build_object(
'support', jsonb_build_object('q1', sm.fact_supp_q1, 'q2', sm.fact_supp_q2, 'q3', sm.fact_supp_q3, 'q4', sm.fact_supp_q4, 'year', sm.fact_supp_year),
'development', jsonb_build_object('q1', sm.fact_dev_q1, 'q2', sm.fact_dev_q2, 'q3', sm.fact_dev_q3, 'q4', sm.fact_dev_q4, 'year', sm.fact_dev_year)
),
'corrected', jsonb_build_object(
'support', jsonb_build_object('q2', sm.corr_supp_q2, 'q3', sm.corr_supp_q3, 'q4', sm.corr_supp_q4),
'development', jsonb_build_object('q2', sm.corr_dev_q2, 'q3', sm.corr_dev_q3, 'q4', sm.corr_dev_q4)
)
)
FROM v3.v_form2_smeta(p_form_id) sm
ORDER BY sm.section_code;
RETURN;
END IF;
RAISE EXCEPTION 'Unknown sheet: %', p_sheet
USING HINT = 'Use AHR / CAP / OPER / AHR_LIMIT / AHR_RENT / AHR_UTILITY / AHR_SECURITY / OTCH9F / SMETA';
END;
$function$
LANGUAGE plpgsql STABLE;
-- 4б. v3.sync_form2_ahr_satellite_lines: лимитная ветка — amount от
-- limit_without_vat, деление на 1000 при переносе в план АХР. Ветки
@ -3063,54 +2694,95 @@ BEGIN
SELECT lt.id,
fl.qty_q1, fl.qty_q2, fl.qty_q3, fl.qty_q4,
v3._form2_ahr_limit_amount(lt.name, lt.unit, lt.limit_with_vat, fl.qty_q1)AS amount_q1,
v3._form2_ahr_limit_amount(lt.name, lt.unit, lt.limit_with_vat, fl.qty_q2)AS amount_q2,
v3._form2_ahr_limit_amount(lt.name, lt.unit, lt.limit_with_vat, fl.qty_q3)AS amount_q3,
v3._form2_ahr_limit_amount(lt.name, lt.unit, lt.limit_with_vat, fl.qty_q4)AS amount_q4
v3._form2_ahr_limit_amount(lt.period, lt.limit_without_vat, fl.qty_q1) AS amount_q1,
v3._form2_ahr_limit_amount(lt.period, lt.limit_without_vat, fl.qty_q2) AS amount_q2,
v3._form2_ahr_limit_amount(lt.period, lt.limit_without_vat, fl.qty_q3) AS amount_q3,
v3._form2_ahr_limit_amount(lt.period, lt.limit_without_vat, fl.qty_q4) AS amount_q4
FROM v3.limit_template lt
LEFT JOIN v3.form_limit fl
ON fl.template_id = lt.id AND fl.budget_form_id = p_form_id
WHERE lt.row_type = 'LEAF'
),
leaf_amt_year AS (
SELECT la.*,
(COALESCE(la.amount_q1,0)+COALESCE(la.amount_q2,0)
+COALESCE(la.amount_q3,0)+COALESCE(la.amount_q4,0)) AS amount_year
FROM leaf_amt la
),
agg AS (
SELECT t.root_id,
SUM(la.qty_q1) AS qty_q1, SUM(la.amount_q1) AS amount_q1,
SUM(la.qty_q2) AS qty_q2, SUM(la.amount_q2) AS amount_q2,
SUM(la.qty_q3) AS qty_q3, SUM(la.amount_q3) AS amount_q3,
SUM(la.qty_q4) AS qty_q4, SUM(la.amount_q4) AS amount_q4
SUM(la.qty_q1) AS qty_q1, SUM(la.amount_q1) AS amount_q1,
SUM(la.qty_q2) AS qty_q2, SUM(la.amount_q2) AS amount_q2,
SUM(la.qty_q3) AS qty_q3, SUM(la.amount_q3) AS amount_q3,
SUM(la.qty_q4) AS qty_q4, SUM(la.amount_q4) AS amount_q4,
SUM(la.amount_year) AS amount_year
FROM tree t
JOIN leaf_amt la ON la.id = t.desc_id
JOIN leaf_amt_year la ON la.id = t.desc_id
GROUP BY t.root_id
),
rows AS (
SELECT
CASE lt.row_type WHEN 'SECTION' THEN 'ROOT'
WHEN 'GROUP' THEN 'GROUP'
WHEN 'LEAF' THEN 'INPUT' END::VARCHAR AS row_type,
CASE lt.row_type WHEN 'SECTION' THEN 0 WHEN 'GROUP' THEN 1 ELSE 2 END AS depth,
lt.sort_order::BIGINT AS sort_order,
jsonb_build_object(
'id', lt.id,
'section_no', lt.section_no,
'expense_item_code',lt.expense_item_code,
'name', lt.name,
'unit', lt.unit,
'period', lt.period,
'limit_with_vat', lt.limit_with_vat,
'limit_without_vat',lt.limit_without_vat,
'qty_q1', a.qty_q1, 'amount_q1', a.amount_q1,
'qty_q2', a.qty_q2, 'amount_q2', a.amount_q2,
'qty_q3', a.qty_q3, 'amount_q3', a.amount_q3,
'qty_q4', a.qty_q4, 'amount_q4', a.amount_q4,
'amount_year', a.amount_year,
'comment', fl.comment
) AS data
FROM v3.limit_template lt
LEFT JOIN agg a ON a.root_id = lt.id
LEFT JOIN v3.form_limit fl
ON fl.template_id = lt.id AND fl.budget_form_id = p_form_id
WHERE p_focus_lines IS NULL
OR lt.id = ANY(v3._limit_template_path_set(p_focus_lines))
UNION ALL
SELECT
'ROOT'::VARCHAR AS row_type,
0 AS depth,
999999::BIGINT AS sort_order,
jsonb_build_object(
'id', 0,
'name', 'Итого',
'amount_q1', totals.amount_q1,
'amount_q2', totals.amount_q2,
'amount_q3', totals.amount_q3,
'amount_q4', totals.amount_q4,
'amount_year', totals.amount_year
) AS data
FROM (
SELECT
SUM(la.amount_q1) AS amount_q1,
SUM(la.amount_q2) AS amount_q2,
SUM(la.amount_q3) AS amount_q3,
SUM(la.amount_q4) AS amount_q4,
SUM(la.amount_year) AS amount_year
FROM leaf_amt_year la
) totals
WHERE p_focus_lines IS NULL
OR EXISTS (
SELECT 1 FROM leaf_amt_year la2
WHERE la2.id = ANY(v3._limit_template_path_set(p_focus_lines))
)
)
SELECT
CASE lt.row_type WHEN 'SECTION' THEN 'ROOT'
WHEN 'GROUP' THEN 'GROUP'
WHEN 'LEAF' THEN 'INPUT' END::VARCHAR,
CASE lt.row_type WHEN 'SECTION' THEN 0 WHEN 'GROUP' THEN 1 ELSE 2 END,
lt.sort_order::BIGINT,
jsonb_build_object(
'id', lt.id,
'section_no', lt.section_no,
'expense_item_code',lt.expense_item_code,
'name', lt.name,
'unit', lt.unit,
'limit_with_vat', lt.limit_with_vat,
'limit_without_vat',lt.limit_without_vat,
'qty_q1', a.qty_q1, 'amount_q1', a.amount_q1,
'qty_q2', a.qty_q2, 'amount_q2', a.amount_q2,
'qty_q3', a.qty_q3, 'amount_q3', a.amount_q3,
'qty_q4', a.qty_q4, 'amount_q4', a.amount_q4,
'comment', fl.comment
)
FROM v3.limit_template lt
LEFT JOIN agg a ON a.root_id = lt.id
LEFT JOIN v3.form_limit fl
ON fl.template_id = lt.id AND fl.budget_form_id = p_form_id
WHERE p_focus_lines IS NULL
OR lt.id = ANY(v3._limit_template_path_set(p_focus_lines))
ORDER BY lt.sort_order;
SELECT rows.row_type, rows.depth, rows.sort_order, rows.data
FROM rows
ORDER BY rows.sort_order;
RETURN;
END IF;
@ -3138,8 +2810,8 @@ BEGIN
'total', COALESCE(rd.actual_apr,0)+COALESCE(rd.actual_may,0)+COALESCE(rd.actual_jun,0)),
'fact_q3', jsonb_build_object('jul', rd.actual_jul, 'aug', rd.actual_aug, 'sep', rd.actual_sep,
'total', COALESCE(rd.actual_jul,0)+COALESCE(rd.actual_aug,0)+COALESCE(rd.actual_sep,0)),
'fact_q4', jsonb_build_object('oct', rd.actual_oct, 'nov', rd.actual_nov, 'dec', rd.actual_dec,
'total', COALESCE(rd.actual_oct,0)+COALESCE(rd.actual_nov,0)+COALESCE(rd.actual_dec,0)),
'fact_q4', jsonb_build_object('oct', rd.actual_oct, 'nov', rd.actual_nov, 'dec', rd.actual_dec, 'spod', rd.actual_spod,
'total', COALESCE(rd.actual_oct,0)+COALESCE(rd.actual_nov,0)+COALESCE(rd.actual_dec,0)+COALESCE(rd.actual_spod,0)),
'comment', rd.comment
)
FROM (
@ -3180,8 +2852,8 @@ BEGIN
'total', COALESCE(ud.actual_apr,0)+COALESCE(ud.actual_may,0)+COALESCE(ud.actual_jun,0)),
'fact_q3', jsonb_build_object('jul', ud.actual_jul, 'aug', ud.actual_aug, 'sep', ud.actual_sep,
'total', COALESCE(ud.actual_jul,0)+COALESCE(ud.actual_aug,0)+COALESCE(ud.actual_sep,0)),
'fact_q4', jsonb_build_object('oct', ud.actual_oct, 'nov', ud.actual_nov, 'dec', ud.actual_dec,
'total', COALESCE(ud.actual_oct,0)+COALESCE(ud.actual_nov,0)+COALESCE(ud.actual_dec,0)),
'fact_q4', jsonb_build_object('oct', ud.actual_oct, 'nov', ud.actual_nov, 'dec', ud.actual_dec, 'spod', ud.actual_spod,
'total', COALESCE(ud.actual_oct,0)+COALESCE(ud.actual_nov,0)+COALESCE(ud.actual_dec,0)+COALESCE(ud.actual_spod,0)),
'comment', ud.comment
)
FROM (
@ -3222,8 +2894,8 @@ BEGIN
'total', COALESCE(sd.actual_apr,0)+COALESCE(sd.actual_may,0)+COALESCE(sd.actual_jun,0)),
'fact_q3', jsonb_build_object('jul', sd.actual_jul, 'aug', sd.actual_aug, 'sep', sd.actual_sep,
'total', COALESCE(sd.actual_jul,0)+COALESCE(sd.actual_aug,0)+COALESCE(sd.actual_sep,0)),
'fact_q4', jsonb_build_object('oct', sd.actual_oct, 'nov', sd.actual_nov, 'dec', sd.actual_dec,
'total', COALESCE(sd.actual_oct,0)+COALESCE(sd.actual_nov,0)+COALESCE(sd.actual_dec,0)),
'fact_q4', jsonb_build_object('oct', sd.actual_oct, 'nov', sd.actual_nov, 'dec', sd.actual_dec, 'spod', sd.actual_spod,
'total', COALESCE(sd.actual_oct,0)+COALESCE(sd.actual_nov,0)+COALESCE(sd.actual_dec,0)+COALESCE(sd.actual_spod,0)),
'comment', sd.comment
)
FROM (

View File

@ -398,6 +398,12 @@ $function$;
-- сателлитов (аренда/коммуналка/охрана) не трогается — там уже однозначное
-- сопоставление по v3.form2_ahr_satellite_line_source (source_id). Тело —
-- актуальное (0031, не менялось с тех пор) + один доп. AND.
--
-- Issue #294 (находка при фиксе 0052): добавлен 'SUB_SUB_ITEM' в список
-- допустимых row_type заголовков. Без него дельта по статьям глубины 4
-- (принтеры/МФУ/копировальные аппараты — AURORA-1897) была пустой: после
-- AURORA-1887 исходная INPUT-строка на листе AHR скрыта, а её единственный
-- заголовок — SUB_SUB_ITEM (глубина 4), который сюда не попадал.
CREATE OR REPLACE FUNCTION v3.get_form2_ahr_satellite_delta(
p_form_id integer,
p_source_sheet character varying,
@ -458,7 +464,7 @@ AS $function$
SELECT v.row_type, v.depth, v.sort_order, v.data
FROM v3.v_form_view(p_form_id, 'AHR', NULL, 'Support') v
WHERE (
v.row_type IN ('ROOT', 'GROUP', 'ITEM', 'SUB_ITEM')
v.row_type IN ('ROOT', 'GROUP', 'ITEM', 'SUB_ITEM', 'SUB_SUB_ITEM')
AND (v.data->'header'->>'expense_item_id')::INT IN (
SELECT expense_item_id FROM target_path
)

View File

@ -83,8 +83,19 @@ AS $function$
$function$;
CREATE OR REPLACE FUNCTION v3.v_form2_sheet_jsonb(p_form_id integer, p_sheet character varying, p_sections text[] DEFAULT NULL::text[])
RETURNS TABLE(row_type character varying, depth integer, line_id integer, header jsonb, plan_data jsonb, seq_dfip_data jsonb, seq_ssp_data jsonb, approved_data jsonb, contract_data jsonb, booking_data jsonb, contract_summary jsonb, allocation_data jsonb, collegial_data jsonb, ckk_data jsonb, q1_data jsonb, q2_data jsonb, q3_data jsonb, q4_data jsonb, totals_data jsonb, _sort_path integer[])
-- Issue #294: v3.v_form2_sheet_jsonb вызывается из v3.v_form2_view (0052,
-- ветка AURORA-1850/upd_form_cells_subtree) четырьмя позиционными
-- аргументами (с p_focus_lines) — без этой сигнатуры здесь совпадение по
-- количеству аргументов разрешилось бы в сторону версии БЕЗ правок ниже
-- (PR #292 слил независимо развивавшуюся ветку focus_lines с этой; см.
-- аналогичный фикс в 0052 для v3.v_form2_view). DROP старой 3-арг. версии
-- (из этого же файла до правки, и из 0053) обязателен — иначе она остаётся
-- висеть второй перегрузкой и 4-арг. вызов из v_form2_view так и получает
-- тело без AURORA-1887/1907.
DROP FUNCTION IF EXISTS v3.v_form2_sheet_jsonb(integer, character varying, text[]);
CREATE OR REPLACE FUNCTION v3.v_form2_sheet_jsonb(p_form_id integer, p_sheet character varying, p_sections text[] DEFAULT NULL::text[], p_focus_lines integer[] DEFAULT NULL::integer[])
RETURNS TABLE(row_type character varying, depth integer, line_id integer, header jsonb, plan_data jsonb, seq_dfip_data jsonb, seq_ssp_data jsonb, approved_data jsonb, contract_data jsonb, booking_data jsonb, contract_summary jsonb, allocation_data jsonb, collegial_data jsonb, ckk_data jsonb, q1_data jsonb, q2_data jsonb, q3_data jsonb, q4_data jsonb, totals_data jsonb, _sort_path integer[], _sort_rank bigint)
LANGUAGE sql
STABLE
AS $function$
@ -111,7 +122,7 @@ AS $function$
CASE WHEN s.row_type = 'INPUT'
THEN s._sort_path[array_upper(s._sort_path,1)-1]
ELSE s._sort_path[array_upper(s._sort_path,1)] END AS eid
FROM v3.v_form2_sheet_sections(p_form_id, p_sheet, p_sections) s
FROM v3.v_form2_sheet_sections(p_form_id, p_sheet, p_sections, p_focus_lines) s
),
limit_tree AS (
SELECT
@ -401,7 +412,8 @@ AS $function$
'economy_year', s.col_economy_year
) END AS totals_data,
s._sort_path
s._sort_path,
s._sort_rank
FROM sheet_rows s
CROSS JOIN flags f
CROSS JOIN sat