From 049da41b0b050c60db60aef097052c916bc825f7 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Tue, 3 Nov 2026 18:10:30 +0400 Subject: [PATCH] =?UTF-8?q?fix(migrations):=20=D0=B7=D0=B0=D0=B4=D0=B2?= =?UTF-8?q?=D0=BE=D0=B5=D0=BD=D0=BD=D0=BE=D0=B5=20v=5Fform2=5Fview/v=5Ffor?= =?UTF-8?q?m2=5Fsheet=5Fjsonb=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20PR=20#292?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #292 слил два независимо развивавшихся набора миграций 0050-0053 (цепочка Фомичева и ветка AURORA-1850/upd_form_cells_subtree) простой конкатенацией SQL. Для 0052 это дало ВТОРОЕ, более старое определение v3.v_form2_view (без СПОД и без правок лимитов AURORA-1897/1906) ниже первого в том же файле — оно и остаётся финальным телом функции. Аналогичная проблема в 0054: v3.v_form2_sheet_jsonb там 3-аргументная, без p_focus_lines, поэтому реальный вызов из v_form2_view (4 аргумента) резолвился в версию из 0052 без AURORA-1887/1907. - 0052: убрано второе определение v_form2_view; AHR_LIMIT-ветка и fact_q4.spod в AHR_RENT/AHR_UTILITY/AHR_SECURITY перенесены в единственное (4-арг.) тело функции; строка «Итого» теперь не возвращается при непустом p_focus_lines без совпадений (пустая дельта остаётся пустой). - 0054: v_form2_sheet_jsonb переведена на 4-арг. сигнатуру с DROP старой 3-арг. перегрузки. - 0053: get_form2_ahr_satellite_delta — добавлен SUB_SUB_ITEM в список заголовков (без него дельта по статьям глубины 4 пуста). Closes issue #294. Co-Authored-By: Claude Sonnet 5 --- .../0052_form2_ahr_limit_period_vat_units.sql | 528 ++++-------------- .../sql/0053_form2_ahr_source_sheet.sql | 8 +- .../0054_form2_ahr_hide_satellite_rows.sql | 20 +- 3 files changed, 123 insertions(+), 433 deletions(-) diff --git a/api/alembic/versions/sql/0052_form2_ahr_limit_period_vat_units.sql b/api/alembic/versions/sql/0052_form2_ahr_limit_period_vat_units.sql index c8a4ccd..7500ea3 100644 --- a/api/alembic/versions/sql/0052_form2_ahr_limit_period_vat_units.sql +++ b/api/alembic/versions/sql/0052_form2_ahr_limit_period_vat_units.sql @@ -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 ( diff --git a/api/alembic/versions/sql/0053_form2_ahr_source_sheet.sql b/api/alembic/versions/sql/0053_form2_ahr_source_sheet.sql index 62f2218..c0b2ede 100644 --- a/api/alembic/versions/sql/0053_form2_ahr_source_sheet.sql +++ b/api/alembic/versions/sql/0053_form2_ahr_source_sheet.sql @@ -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 ) diff --git a/api/alembic/versions/sql/0054_form2_ahr_hide_satellite_rows.sql b/api/alembic/versions/sql/0054_form2_ahr_hide_satellite_rows.sql index 96283e8..888aec1 100644 --- a/api/alembic/versions/sql/0054_form2_ahr_hide_satellite_rows.sql +++ b/api/alembic/versions/sql/0054_form2_ahr_hide_satellite_rows.sql @@ -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 -- 2.47.2