From 341e8b393680480ddbc8522218cf9cc47ff1f59c Mon Sep 17 00:00:00 2001 From: tsygankoviva Date: Wed, 30 Sep 2026 14:02:41 +0300 Subject: [PATCH] =?UTF-8?q?last-column:=20=D0=9A=D0=BE=D0=BB=D0=BE=D0=BD?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=A1=D1=83=D0=BC=D0=BC=D0=B0=20=D0=BE=D0=BF?= =?UTF-8?q?=D0=BB=D0=B0=D1=82=D1=8B=20=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82?= =?UTF-8?q?=D1=83=D1=80=D1=8B=20=D1=84=D0=BE=D1=80=D0=BC=D1=8B=204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/alembic/versions/0042_form4_pay_year.py | 15 + .../versions/sql/0042_form4_pay_year.sql | 525 ++++++++++++++++++ .../constants/FORM_4/STRUCTURE.js | 17 + 3 files changed, 557 insertions(+) create mode 100644 api/alembic/versions/0042_form4_pay_year.py create mode 100644 api/alembic/versions/sql/0042_form4_pay_year.sql diff --git a/api/alembic/versions/0042_form4_pay_year.py b/api/alembic/versions/0042_form4_pay_year.py new file mode 100644 index 0000000..5a597cd --- /dev/null +++ b/api/alembic/versions/0042_form4_pay_year.py @@ -0,0 +1,15 @@ +from sql_migration import run_sql_file_migration + + +revision = "0042" +down_revision = "0041" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + run_sql_file_migration("0042_form4_pay_year.sql") + + +def downgrade() -> None: + pass diff --git a/api/alembic/versions/sql/0042_form4_pay_year.sql b/api/alembic/versions/sql/0042_form4_pay_year.sql new file mode 100644 index 0000000..e3b35ce --- /dev/null +++ b/api/alembic/versions/sql/0042_form4_pay_year.sql @@ -0,0 +1,525 @@ +-- DROP FUNCTION v3.v_project_summary_all_jsonb(integer, integer[], character varying); + +CREATE OR REPLACE FUNCTION v3.v_project_summary_all_jsonb( + p_year integer, + p_org_unit_ids integer[] DEFAULT NULL, + p_project_type character varying DEFAULT NULL +) +RETURNS TABLE(row_type character varying, depth integer, sort_order bigint, data jsonb) +LANGUAGE sql +STABLE +AS $function$ +WITH + filtered_projects AS ( + SELECT DISTINCT p.id + FROM v3.project p + JOIN v3.rf_project_year rpy + ON rpy.project_id = p.id + AND rpy.year = p_year + WHERE (p_org_unit_ids IS NULL OR p.org_unit_id = ANY(p_org_unit_ids)) + AND (p_project_type IS NULL OR p.project_type = p_project_type) + ), + form3_items AS ( + SELECT + t.id, + t.depth, + t.path, + t.parent_item_id, + t.desc_ids, + t.item_id, + t.num_group_id, + t.name + FROM v3.mv_expense_item_tree t + JOIN v3.expense_item_form_type eft + ON eft.expense_item_id = t.id + AND eft.form_type_code = 'FORM_3' + ), + matching_reports AS ( + SELECT r.id, r.report_type + FROM filtered_projects fp + JOIN v3.rf_project_report r + ON r.project_id = fp.id + JOIN v3.rf_project_year rpy + ON rpy.id = r.rf_project_year_id + AND rpy.year = p_year + ), + line_values AS ( + SELECT + l.expense_item_id, + mr.report_type, + q.quarter, + SUM(q.base_plan) AS base_plan, + SUM(q.corrected_plan) AS corrected_plan, + SUM(q.adj_by_items) AS adj_by_items, + SUM(q.adj_increase) AS adj_increase, + SUM(q.actual_m1) AS actual_m1, + SUM(q.actual_m2) AS actual_m2, + SUM(q.actual_m3) AS actual_m3, + SUM( + COALESCE(q.actual_m1, 0) + + COALESCE(q.actual_m2, 0) + + COALESCE(q.actual_m3, 0) + + CASE WHEN q.quarter = 4 THEN COALESCE(q.actual_spod, 0) ELSE 0 END + ) AS actual_amount + FROM matching_reports mr + JOIN v3.rf_project_report_line l + ON l.rf_project_report_id = mr.id + JOIN v3.rf_project_report_quarter q + ON q.rf_project_report_line_id = l.id + GROUP BY l.expense_item_id, mr.report_type, q.quarter + ), + aggregated AS ( + SELECT + fi.id AS expense_item_id, + CASE WHEN fi.depth < 3 THEN fi.item_id ELSE fi.parent_item_id END AS section_code, + CASE WHEN fi.depth = 3 THEN fi.item_id ELSE NULL END AS item_id, + fi.num_group_id, + fi.name, + fi.depth, + fi.path, + COALESCE(SUM(lv.base_plan) FILTER (WHERE lv.report_type = 'LIMIT' AND lv.quarter = 1), 0) AS base_limit_q1, + COALESCE(SUM(lv.base_plan) FILTER (WHERE lv.report_type = 'LIMIT' AND lv.quarter = 2), 0) AS base_limit_q2, + COALESCE(SUM(lv.base_plan) FILTER (WHERE lv.report_type = 'LIMIT' AND lv.quarter = 3), 0) AS base_limit_q3, + COALESCE(SUM(lv.base_plan) FILTER (WHERE lv.report_type = 'LIMIT' AND lv.quarter = 4), 0) AS base_limit_q4, + COALESCE(SUM(lv.base_plan) FILTER (WHERE lv.report_type = 'CURRENT_EXPENSES' AND lv.quarter = 1), 0) AS base_current_q1, + COALESCE(SUM(lv.base_plan) FILTER (WHERE lv.report_type = 'CURRENT_EXPENSES' AND lv.quarter = 2), 0) AS base_current_q2, + COALESCE(SUM(lv.base_plan) FILTER (WHERE lv.report_type = 'CURRENT_EXPENSES' AND lv.quarter = 3), 0) AS base_current_q3, + COALESCE(SUM(lv.base_plan) FILTER (WHERE lv.report_type = 'CURRENT_EXPENSES' AND lv.quarter = 4), 0) AS base_current_q4, + COALESCE(SUM(lv.corrected_plan) FILTER (WHERE lv.report_type = 'LIMIT' AND lv.quarter = 2), 0) AS correction_limit_q2, + COALESCE(SUM(lv.corrected_plan) FILTER (WHERE lv.report_type = 'LIMIT' AND lv.quarter = 3), 0) AS correction_limit_q3, + COALESCE(SUM(lv.corrected_plan) FILTER (WHERE lv.report_type = 'LIMIT' AND lv.quarter = 4), 0) AS correction_limit_q4, + COALESCE(SUM(lv.corrected_plan) FILTER (WHERE lv.report_type = 'CURRENT_EXPENSES' AND lv.quarter = 2), 0) AS correction_current_q2, + COALESCE(SUM(lv.corrected_plan) FILTER (WHERE lv.report_type = 'CURRENT_EXPENSES' AND lv.quarter = 3), 0) AS correction_current_q3, + COALESCE(SUM(lv.corrected_plan) FILTER (WHERE lv.report_type = 'CURRENT_EXPENSES' AND lv.quarter = 4), 0) AS correction_current_q4, + COALESCE(SUM(lv.actual_amount) FILTER (WHERE lv.report_type = 'LIMIT' AND lv.quarter = 1), 0) AS fact_limit_q1, + COALESCE(SUM(lv.actual_amount) FILTER (WHERE lv.report_type = 'LIMIT' AND lv.quarter = 2), 0) AS fact_limit_q2, + COALESCE(SUM(lv.actual_amount) FILTER (WHERE lv.report_type = 'LIMIT' AND lv.quarter = 3), 0) AS fact_limit_q3, + COALESCE(SUM(lv.actual_amount) FILTER (WHERE lv.report_type = 'LIMIT' AND lv.quarter = 4), 0) AS fact_limit_q4, + COALESCE(SUM(lv.actual_amount) FILTER (WHERE lv.report_type = 'CURRENT_EXPENSES' AND lv.quarter = 1), 0) AS fact_current_q1, + COALESCE(SUM(lv.actual_amount) FILTER (WHERE lv.report_type = 'CURRENT_EXPENSES' AND lv.quarter = 2), 0) AS fact_current_q2, + COALESCE(SUM(lv.actual_amount) FILTER (WHERE lv.report_type = 'CURRENT_EXPENSES' AND lv.quarter = 3), 0) AS fact_current_q3, + COALESCE(SUM(lv.actual_amount) FILTER (WHERE lv.report_type = 'CURRENT_EXPENSES' AND lv.quarter = 4), 0) AS fact_current_q4, + COALESCE(SUM(lv.adj_by_items) FILTER (WHERE lv.quarter = 1), 0) AS detail_adj_by_items_q1, + COALESCE(SUM(lv.adj_by_items) FILTER (WHERE lv.quarter = 2), 0) AS detail_adj_by_items_q2, + COALESCE(SUM(lv.adj_by_items) FILTER (WHERE lv.quarter = 3), 0) AS detail_adj_by_items_q3, + COALESCE(SUM(lv.adj_by_items) FILTER (WHERE lv.quarter = 4), 0) AS detail_adj_by_items_q4, + COALESCE(SUM(lv.adj_increase) FILTER (WHERE lv.quarter = 1), 0) AS detail_adj_increase_q1, + COALESCE(SUM(lv.adj_increase) FILTER (WHERE lv.quarter = 2), 0) AS detail_adj_increase_q2, + COALESCE(SUM(lv.adj_increase) FILTER (WHERE lv.quarter = 3), 0) AS detail_adj_increase_q3, + COALESCE(SUM(lv.adj_increase) FILTER (WHERE lv.quarter = 4), 0) AS detail_adj_increase_q4, + COALESCE(SUM(lv.actual_m1) FILTER (WHERE lv.quarter = 1), 0) AS detail_actual_m1_q1, + COALESCE(SUM(lv.actual_m1) FILTER (WHERE lv.quarter = 2), 0) AS detail_actual_m1_q2, + COALESCE(SUM(lv.actual_m1) FILTER (WHERE lv.quarter = 3), 0) AS detail_actual_m1_q3, + COALESCE(SUM(lv.actual_m1) FILTER (WHERE lv.quarter = 4), 0) AS detail_actual_m1_q4, + COALESCE(SUM(lv.actual_m2) FILTER (WHERE lv.quarter = 1), 0) AS detail_actual_m2_q1, + COALESCE(SUM(lv.actual_m2) FILTER (WHERE lv.quarter = 2), 0) AS detail_actual_m2_q2, + COALESCE(SUM(lv.actual_m2) FILTER (WHERE lv.quarter = 3), 0) AS detail_actual_m2_q3, + COALESCE(SUM(lv.actual_m2) FILTER (WHERE lv.quarter = 4), 0) AS detail_actual_m2_q4, + COALESCE(SUM(lv.actual_m3) FILTER (WHERE lv.quarter = 1), 0) AS detail_actual_m3_q1, + COALESCE(SUM(lv.actual_m3) FILTER (WHERE lv.quarter = 2), 0) AS detail_actual_m3_q2, + COALESCE(SUM(lv.actual_m3) FILTER (WHERE lv.quarter = 3), 0) AS detail_actual_m3_q3, + COALESCE(SUM(lv.actual_m3) FILTER (WHERE lv.quarter = 4), 0) AS detail_actual_m3_q4 + FROM form3_items fi + LEFT JOIN line_values lv + ON lv.expense_item_id = ANY(fi.desc_ids) + GROUP BY fi.id, fi.depth, fi.path, fi.parent_item_id, fi.item_id, fi.num_group_id, fi.name + ) +SELECT + CASE a.depth WHEN 0 THEN 'ROOT' WHEN 1 THEN 'GROUP' WHEN 2 THEN 'ITEM' ELSE 'SUB_ITEM' END::varchar AS row_type, + COALESCE(a.depth, 0)::integer AS depth, + ROW_NUMBER() OVER (ORDER BY a.path) AS sort_order, + jsonb_build_object( + 'header', jsonb_build_object( + 'expense_item_id', a.expense_item_id, + 'section_code', a.section_code, + 'item_id', a.item_id, + 'num_group_id', a.num_group_id, + 'name', a.name, + 'year', p_year + ), + 'base', jsonb_build_object( + 'limit', jsonb_build_object('q1', a.base_limit_q1, 'q2', a.base_limit_q2, 'q3', a.base_limit_q3, 'q4', a.base_limit_q4, 'year', a.base_limit_q1 + a.base_limit_q2 + a.base_limit_q3 + a.base_limit_q4), + 'current', jsonb_build_object('q1', a.base_current_q1, 'q2', a.base_current_q2, 'q3', a.base_current_q3, 'q4', a.base_current_q4, 'year', a.base_current_q1 + a.base_current_q2 + a.base_current_q3 + a.base_current_q4), + 'total', jsonb_build_object( + 'q1', a.base_limit_q1 + a.base_current_q1, + 'q2', a.base_limit_q2 + a.base_current_q2, + 'q3', a.base_limit_q3 + a.base_current_q3, + 'q4', a.base_limit_q4 + a.base_current_q4, + 'year', a.base_limit_q1 + a.base_limit_q2 + a.base_limit_q3 + a.base_limit_q4 + a.base_current_q1 + a.base_current_q2 + a.base_current_q3 + a.base_current_q4 + ) + ), + 'correction', jsonb_build_object( + 'limit', jsonb_build_object('q2', a.correction_limit_q2, 'q3', a.correction_limit_q3, 'q4', a.correction_limit_q4, 'year', a.correction_limit_q2 + a.correction_limit_q3 + a.correction_limit_q4), + 'current', jsonb_build_object('q2', a.correction_current_q2, 'q3', a.correction_current_q3, 'q4', a.correction_current_q4, 'year', a.correction_current_q2 + a.correction_current_q3 + a.correction_current_q4), + 'total', jsonb_build_object( + 'q2', a.correction_limit_q2 + a.correction_current_q2, + 'q3', a.correction_limit_q3 + a.correction_current_q3, + 'q4', a.correction_limit_q4 + a.correction_current_q4, + 'year', a.correction_limit_q2 + a.correction_limit_q3 + a.correction_limit_q4 + a.correction_current_q2 + a.correction_current_q3 + a.correction_current_q4 + ) + ), + 'fact', jsonb_build_object( + 'limit', jsonb_build_object('q1', a.fact_limit_q1, 'q2', a.fact_limit_q2, 'q3', a.fact_limit_q3, 'q4', a.fact_limit_q4, 'year', a.fact_limit_q1 + a.fact_limit_q2 + a.fact_limit_q3 + a.fact_limit_q4), + 'current', jsonb_build_object('q1', a.fact_current_q1, 'q2', a.fact_current_q2, 'q3', a.fact_current_q3, 'q4', a.fact_current_q4, 'year', a.fact_current_q1 + a.fact_current_q2 + a.fact_current_q3 + a.fact_current_q4), + 'total', jsonb_build_object( + 'q1', a.fact_limit_q1 + a.fact_current_q1, + 'q2', a.fact_limit_q2 + a.fact_current_q2, + 'q3', a.fact_limit_q3 + a.fact_current_q3, + 'q4', a.fact_limit_q4 + a.fact_current_q4, + 'year', a.fact_limit_q1 + a.fact_limit_q2 + a.fact_limit_q3 + a.fact_limit_q4 + a.fact_current_q1 + a.fact_current_q2 + a.fact_current_q3 + a.fact_current_q4 + ) + ), + 'detail', jsonb_build_object( + 'q1', jsonb_build_object('adj_by_items', a.detail_adj_by_items_q1, 'adj_increase', a.detail_adj_increase_q1, 'actual_m1', a.detail_actual_m1_q1, 'actual_m2', a.detail_actual_m2_q1, 'actual_m3', a.detail_actual_m3_q1, 'quarter', a.detail_actual_m1_q1 + a.detail_actual_m2_q1 + a.detail_actual_m3_q1, 'residual', a.detail_adj_by_items_q1 + a.detail_adj_increase_q1 - (a.detail_actual_m1_q1 + a.detail_actual_m2_q1 + a.detail_actual_m3_q1)), + 'q2', jsonb_build_object('adj_by_items', a.detail_adj_by_items_q2, 'adj_increase', a.detail_adj_increase_q2, 'actual_m1', a.detail_actual_m1_q2, 'actual_m2', a.detail_actual_m2_q2, 'actual_m3', a.detail_actual_m3_q2, 'quarter', a.detail_actual_m1_q2 + a.detail_actual_m2_q2 + a.detail_actual_m3_q2, 'residual', a.detail_adj_by_items_q2 + a.detail_adj_increase_q2 - (a.detail_actual_m1_q2 + a.detail_actual_m2_q2 + a.detail_actual_m3_q2)), + 'q3', jsonb_build_object('adj_by_items', a.detail_adj_by_items_q3, 'adj_increase', a.detail_adj_increase_q3, 'actual_m1', a.detail_actual_m1_q3, 'actual_m2', a.detail_actual_m2_q3, 'actual_m3', a.detail_actual_m3_q3, 'quarter', a.detail_actual_m1_q3 + a.detail_actual_m2_q3 + a.detail_actual_m3_q3, 'residual', a.detail_adj_by_items_q3 + a.detail_adj_increase_q3 - (a.detail_actual_m1_q3 + a.detail_actual_m2_q3 + a.detail_actual_m3_q3)), + 'q4', jsonb_build_object('adj_by_items', a.detail_adj_by_items_q4, 'adj_increase', a.detail_adj_increase_q4, 'actual_m1', a.detail_actual_m1_q4, 'actual_m2', a.detail_actual_m2_q4, 'actual_m3', a.detail_actual_m3_q4, 'quarter', a.detail_actual_m1_q4 + a.detail_actual_m2_q4 + a.detail_actual_m3_q4, 'residual', a.detail_adj_by_items_q4 + a.detail_adj_increase_q4 - (a.detail_actual_m1_q4 + a.detail_actual_m2_q4 + a.detail_actual_m3_q4)), + 'year', (a.detail_actual_m1_q1 + a.detail_actual_m2_q1 + a.detail_actual_m3_q1) + (a.detail_actual_m1_q2 + a.detail_actual_m2_q2 + a.detail_actual_m3_q2) + (a.detail_actual_m1_q3 + a.detail_actual_m2_q3 + a.detail_actual_m3_q3) + (a.detail_actual_m1_q4 + a.detail_actual_m2_q4 + a.detail_actual_m3_q4) + ) + ) AS data +FROM aggregated a +ORDER BY a.path; +$function$ +; + +-- DROP FUNCTION v3.v_form4_sheet_lines_jsonb(int4, varchar, _text); + +CREATE OR REPLACE FUNCTION v3.v_form4_sheet_lines_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, approved_data jsonb, contract_summary_data jsonb, allocation_data jsonb, reserve_data jsonb, collegial_data jsonb, ckk_data jsonb, contract_data jsonb, booking_data jsonb, q1_data jsonb, q2_data jsonb, q3_data jsonb, q4_data jsonb, totals_data jsonb, _sort_path integer[]) + LANGUAGE sql + STABLE +AS $function$ + WITH flags AS ( + SELECT + (p_sections IS NULL OR 'plan' = ANY(p_sections)) AS s_plan, + (p_sections IS NULL OR 'seq_dfip' = ANY(p_sections)) AS s_seq_d, + (p_sections IS NULL OR 'approved' = ANY(p_sections)) AS s_appr, + (p_sections IS NULL OR 'contract_summary' = ANY(p_sections)) AS s_cs, + (p_sections IS NULL OR 'allocation' = ANY(p_sections)) AS s_al, + (p_sections IS NULL OR 'reserve' = ANY(p_sections)) AS s_rsv, + (p_sections IS NULL OR 'collegial' = ANY(p_sections)) AS s_col, + (p_sections IS NULL OR 'ckk' = ANY(p_sections)) AS s_ckk, + (p_sections IS NULL OR 'contract' = ANY(p_sections)) AS s_cd, + (p_sections IS NULL OR 'booking' = ANY(p_sections)) AS s_book, + (p_sections IS NULL OR 'q1' = ANY(p_sections)) AS s_q1, + (p_sections IS NULL OR 'q2' = ANY(p_sections)) AS s_q2, + (p_sections IS NULL OR 'q3' = ANY(p_sections)) AS s_q3, + (p_sections IS NULL OR 'q4' = ANY(p_sections)) AS s_q4, + (p_sections IS NULL OR 'totals' = ANY(p_sections)) AS s_tot + ) + SELECT + s.row_type, s.depth, s.line_id, + + jsonb_build_object( + 'section_code', s.col_section_code, + 'item_id', s.col_item_id, + 'num_group', s.col_num_group_id, + 'name', s.col_name, + 'justification', s.col_justification, + 'internal_order', s.col_internal_order, + 'vsp_id', s.col_vsp_id, + 'vsp_address', s.col_vsp_address, + 'expense_item_id', 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 header, + + CASE WHEN f.s_plan THEN jsonb_build_object( + 'q1', s.col_plan_q1, 'q2', s.col_plan_q2, + 'q3', s.col_plan_q3, 'q4', s.col_plan_q4, + 'year', s.col_plan_year, 'comment', s.col_plan_comment + ) END AS plan_data, + + CASE WHEN f.s_seq_d THEN jsonb_build_object( + 'q1', s.col_seq_dfip_q1, 'q2', s.col_seq_dfip_q2, + 'q3', s.col_seq_dfip_q3, 'q4', s.col_seq_dfip_q4, + 'year', s.col_seq_dfip_year, + 'justification', s.col_seq_dfip_just + ) END AS seq_dfip_data, + + CASE WHEN f.s_appr THEN jsonb_build_object( + 'q1', s.col_appr_q1, 'q2', s.col_appr_q2, + 'q3', s.col_appr_q3, 'q4', s.col_appr_q4, + 'year', s.col_appr_year + ) END AS approved_data, + + CASE WHEN f.s_cs THEN jsonb_build_object( + 'total', s.col_cs_amount, + 'reference', s.col_cs_reference, + 'counterparty', s.col_cs_counterparty, + 'deadline', s.col_cs_deadline, + 'comment', s.col_cs_comment, + 'future_y1', s.col_cs_future_y1, + 'future_y2', s.col_cs_future_y2, + 'other_ssp', s.col_cs_other_ssp, + 'centralized_flag', s.col_cs_centralized_flag + ) END AS contract_summary_data, + + CASE WHEN f.s_al THEN jsonb_build_object( + 'contract_ref', s.col_al_contract_ref, + 'allocation_purpose', s.col_al_purpose + ) END AS allocation_data, + + CASE WHEN f.s_rsv THEN jsonb_build_object( + 'q1', s.col_rsv_q1, 'q2', s.col_rsv_q2, + 'q3', s.col_rsv_q3, 'q4', s.col_rsv_q4, + 'year', s.col_rsv_year, + 'justification', s.col_rsv_just + ) END AS reserve_data, + + CASE WHEN f.s_col THEN jsonb_build_object( + 'approved', s.col_col_amount, + 'protocol', s.col_col_protocol, + 'note', s.col_col_note + ) END AS collegial_data, + + CASE WHEN f.s_ckk THEN jsonb_build_object( + 'ceiling', s.col_ckk_ceiling, + 'q1', s.col_ckk_q1, + 'q2', s.col_ckk_q2, + 'q3', s.col_ckk_q3, + 'q4', s.col_ckk_q4, + 'rf_schedule', s.col_ckk_rf_schedule, + 'deadline', s.col_ckk_delivery_deadline, + 'proc_plan', s.col_ckk_procurement_plan, + 'proc_method', s.col_ckk_procurement_method, + 'comment', s.col_ckk_comment + ) END AS ckk_data, + + CASE WHEN f.s_cd THEN jsonb_build_object( + 'counterparty', s.col_cd_counterparty, + 'reference', s.col_cd_reference, + 'addenda', s.col_cd_addenda, + 'date', TO_CHAR(s.col_cd_date, 'DD.MM.YYYY'), + 'subject', s.col_cd_subject, + 'currency', s.col_cd_currency, + 'ceiling', s.col_cd_ceiling, + 'q1', s.col_cd_q1, + 'q2', s.col_cd_q2, + 'q3', s.col_cd_q3, + 'q4', s.col_cd_q4, + 'rf_schedule', s.col_cd_rf_schedule, + 'vat_rate', s.col_cd_vat_rate, + 'exchange_rate', s.col_cd_exchange_rate, + 'amount_foreign', s.col_cd_amount_foreign, + 'deadline', s.col_cd_deadline, + 'scheme', s.col_cd_scheme, + 'act', s.col_cd_act, + 'comment', s.col_cd_comment + ) END AS contract_data, + + CASE WHEN f.s_book THEN jsonb_build_object( + 'y2026', jsonb_build_object('q1', s.col_book_q1, 'q2', s.col_book_q2, 'q3', s.col_book_q3, 'q4', s.col_book_q4), + 'y2027', jsonb_build_object('q1', s.col_book_next_q1, 'q2', s.col_book_next_q2, 'q3', s.col_book_next_q3, 'q4', s.col_book_next_q4) + ) END AS booking_data, + + CASE WHEN f.s_q1 THEN jsonb_build_object( + 'adj_current', s.col_q1_adj_current, + 'adj_ssp', s.col_q1_adj_ssp, + 'adj_rf', s.col_q1_adj_rf, + 'adj_reserve', s.col_q1_adj_reserve, + 'adj_comment', s.col_q1_adj_comment, + 'corrected_plan', s.col_q1_corrected_plan, + 'pay_date', TO_CHAR(s.col_q1_pay_date, 'DD.MM.YYYY'), + 'pay_amount', s.col_q1_pay_amount, + 'pay_ho', s.col_q1_pay_ho, + 'pay_rf', s.col_q1_pay_rf, + 'pay_comment', s.col_q1_pay_comment, + 'pay_act', s.col_q1_pay_act, + 'booking', s.col_q1_booking, + 'actual_m1', s.col_q1_actual_m1, + 'actual_m2', s.col_q1_actual_m2, + 'actual_m3', s.col_q1_actual_m3, + 'actual_quarter', s.col_q1_actual_quarter, + 'residual_after_booking', s.col_q1_residual_after_booking, + 'residual_after_actual', s.col_q1_residual_after_actual, + 'transfer_q2', s.col_q1_transfer_q2, + 'transfer_q3', s.col_q1_transfer_q3, + 'transfer_q4', s.col_q1_transfer_q4, + 'transfer_econ', s.col_q1_transfer_econ, + 'total', s.col_q1_total + ) END AS q1_data, + + CASE WHEN f.s_q2 THEN jsonb_build_object( + 'target_change', s.col_q2_target_change, + 'base_correction', s.col_q2_base_correction, + 'base_correction_comment', s.col_q2_base_correction_comment, + 'revision_inc', s.col_q2_revision_inc, + 'revision_seq', s.col_q2_revision_seq, + 'revision_comment', s.col_q2_revision_comment, + 'new_plan', s.col_q2_new_plan, + 'adj_current', s.col_q2_adj_current, + 'adj_ssp', s.col_q2_adj_ssp, + 'adj_rf', s.col_q2_adj_rf, + 'adj_reserve', s.col_q2_adj_reserve, + 'adj_comment', s.col_q2_adj_comment, + 'corrected_plan', s.col_q2_corrected_plan, + 'pay_date', TO_CHAR(s.col_q2_pay_date, 'DD.MM.YYYY'), + 'pay_amount', s.col_q2_pay_amount, + 'pay_ho', s.col_q2_pay_ho, + 'pay_rf', s.col_q2_pay_rf, + 'pay_comment', s.col_q2_pay_comment, + 'pay_act', s.col_q2_pay_act, + 'booking', s.col_q2_booking, + 'actual_m1', s.col_q2_actual_m1, + 'actual_m2', s.col_q2_actual_m2, + 'actual_m3', s.col_q2_actual_m3, + 'actual_quarter', s.col_q2_actual_quarter, + 'residual_after_booking', s.col_q2_residual_after_booking, + 'residual_after_actual', s.col_q2_residual_after_actual, + 'transfer_q3', s.col_q2_transfer_q3, + 'transfer_q4', s.col_q2_transfer_q4, + 'transfer_econ', s.col_q2_transfer_econ, + 'total', s.col_q2_total + ) END AS q2_data, + + CASE WHEN f.s_q3 THEN jsonb_build_object( + 'target_change', s.col_q3_target_change, + 'base_correction', s.col_q3_base_correction, + 'base_correction_comment', s.col_q3_base_correction_comment, + 'revision_inc', s.col_q3_revision_inc, + 'revision_seq', s.col_q3_revision_seq, + 'revision_comment', s.col_q3_revision_comment, + 'new_plan', s.col_q3_new_plan, + 'adj_current', s.col_q3_adj_current, + 'adj_ssp', s.col_q3_adj_ssp, + 'adj_rf', s.col_q3_adj_rf, + 'adj_reserve', s.col_q3_adj_reserve, + 'adj_comment', s.col_q3_adj_comment, + 'corrected_plan', s.col_q3_corrected_plan, + 'pay_date', TO_CHAR(s.col_q3_pay_date, 'DD.MM.YYYY'), + 'pay_amount', s.col_q3_pay_amount, + 'pay_ho', s.col_q3_pay_ho, + 'pay_rf', s.col_q3_pay_rf, + 'pay_comment', s.col_q3_pay_comment, + 'pay_act', s.col_q3_pay_act, + 'booking', s.col_q3_booking, + 'actual_m1', s.col_q3_actual_m1, + 'actual_m2', s.col_q3_actual_m2, + 'actual_m3', s.col_q3_actual_m3, + 'actual_quarter', s.col_q3_actual_quarter, + 'residual_after_booking', s.col_q3_residual_after_booking, + 'residual_after_actual', s.col_q3_residual_after_actual, + 'transfer_q4', s.col_q3_transfer_q4, + 'transfer_econ', s.col_q3_transfer_econ, + 'total', s.col_q3_total + ) END AS q3_data, + + CASE WHEN f.s_q4 THEN jsonb_build_object( + 'target_change', s.col_q4_target_change, + 'base_correction', s.col_q4_base_correction, + 'base_correction_comment', s.col_q4_base_correction_comment, + 'revision_inc', s.col_q4_revision_inc, + 'revision_seq', s.col_q4_revision_seq, + 'revision_comment', s.col_q4_revision_comment, + 'new_plan', s.col_q4_new_plan, + 'adj_current', s.col_q4_adj_current, + 'adj_ssp', s.col_q4_adj_ssp, + 'adj_rf', s.col_q4_adj_rf, + 'adj_reserve', s.col_q4_adj_reserve, + 'adj_comment', s.col_q4_adj_comment, + 'corrected_plan', s.col_q4_corrected_plan, + 'pay_date', TO_CHAR(s.col_q4_pay_date, 'DD.MM.YYYY'), + 'pay_amount', s.col_q4_pay_amount, + 'pay_ho', s.col_q4_pay_ho, + 'pay_rf', s.col_q4_pay_rf, + 'pay_comment', s.col_q4_pay_comment, + 'pay_act', s.col_q4_pay_act, + 'booking', s.col_q4_booking, + 'actual_m1', s.col_q4_actual_m1, + 'actual_m2', s.col_q4_actual_m2, + 'actual_m3', s.col_q4_actual_m3, + 'actual_spod', s.col_q4_actual_spod, + 'actual_rsbu_spod', COALESCE(s.col_q4_actual_m1, 0) + COALESCE(s.col_q4_actual_m2, 0) + COALESCE(s.col_q4_actual_m3, 0) + COALESCE(s.col_q4_actual_spod, 0), + 'actual_quarter', COALESCE(s.col_q4_actual_m1, 0) + COALESCE(s.col_q4_actual_m2, 0) + COALESCE(s.col_q4_actual_m3, 0), + 'residual_after_booking', s.col_q4_residual_after_booking, + 'residual_after_actual', s.col_q4_residual_after_actual, + 'transfer_econ', s.col_q4_transfer_econ, + 'total', s.col_q4_total + ) END AS q4_data, + + CASE WHEN f.s_tot THEN jsonb_build_object( + 'fact_year', s.col_fact_year, + 'pay_year', COALESCE(s.col_q1_pay_amount, 0) + + COALESCE(s.col_q2_pay_amount, 0) + + COALESCE(s.col_q3_pay_amount, 0) + + COALESCE(s.col_q4_pay_amount, 0) + ) END AS totals_data, + + s._sort_path + FROM v3.v_form4_sheet_sections(p_form_id, p_sheet, p_sections) s + CROSS JOIN flags f + ORDER BY s._sort_path; +$function$ +; + + +-- DROP FUNCTION v3.v_project_plan_summary_jsonb(integer, integer[], character varying); + +CREATE OR REPLACE FUNCTION v3.v_project_plan_summary_jsonb( + p_year integer, + p_org_unit_ids integer[] DEFAULT NULL, + p_project_type character varying DEFAULT NULL +) +RETURNS TABLE(row_type character varying, depth integer, sort_order bigint, data jsonb) +LANGUAGE sql +STABLE +AS $function$ + SELECT + row_type, + depth, + sort_order, + jsonb_build_object( + 'header', data->'header', + 'base', data->'base', + 'correction', data->'correction' + ) AS data + FROM v3.v_project_summary_all_jsonb(p_year, p_org_unit_ids, p_project_type); +$function$ +; + +-- DROP FUNCTION v3.v_project_fact_summary_jsonb(integer, integer[], character varying); + +CREATE OR REPLACE FUNCTION v3.v_project_fact_summary_jsonb( + p_year integer, + p_org_unit_ids integer[] DEFAULT NULL, + p_project_type character varying DEFAULT NULL +) +RETURNS TABLE(row_type character varying, depth integer, sort_order bigint, data jsonb) +LANGUAGE sql +STABLE +AS $function$ + SELECT + row_type, + depth, + sort_order, + jsonb_build_object( + 'header', data->'header', + 'fact', data->'fact' + ) AS data + FROM v3.v_project_summary_all_jsonb(p_year, p_org_unit_ids, p_project_type); +$function$ +; + +-- DROP FUNCTION v3.v_project_detail_summary_jsonb(integer, integer[], character varying); + +CREATE OR REPLACE FUNCTION v3.v_project_detail_summary_jsonb( + p_year integer, + p_org_unit_ids integer[] DEFAULT NULL, + p_project_type character varying DEFAULT NULL +) +RETURNS TABLE(row_type character varying, depth integer, sort_order bigint, data jsonb) +LANGUAGE sql +STABLE +AS $function$ + SELECT + row_type, + depth, + sort_order, + jsonb_build_object( + 'header', data->'header', + 'detail', data->'detail' + ) AS data + FROM v3.v_project_summary_all_jsonb(p_year, p_org_unit_ids, p_project_type); +$function$ +; diff --git a/web/src/components/RealtimeTable/constants/FORM_4/STRUCTURE.js b/web/src/components/RealtimeTable/constants/FORM_4/STRUCTURE.js index 6fb7625..1f6f899 100644 --- a/web/src/components/RealtimeTable/constants/FORM_4/STRUCTURE.js +++ b/web/src/components/RealtimeTable/constants/FORM_4/STRUCTURE.js @@ -761,6 +761,10 @@ export const config = { color_type: greenColumn, accessorKey: 'data.totals.fact_year', }, + 'data.totals.pay_year': { + color_type: blueColumn, + accessorKey: 'data.totals.pay_year', + }, field_field_field_3: { color_type: whiteColumn, accessorKey: 'field_field_field_3', @@ -4028,6 +4032,19 @@ export const config = { size: 150, filterFn: "contains", }, + { + header: "Сумма оплаты", + accessorKey: "data.totals.pay_year", + columnLetter: "HG", + size: 150, + filterFn: "contains", + muiTableHeadCellProps: { + sx: { + backgroundColor: "#538DD4", + color: "#000000", + }, + }, + }, ], muiTableHeadCellProps: { sx: {