From c6fb3ef403715e4f0d2fe8c88dc0ac63c06a61c6 Mon Sep 17 00:00:00 2001 From: tsygankoviva Date: Tue, 22 Sep 2026 12:25:40 +0300 Subject: [PATCH] =?UTF-8?q?form1-sub=5Fsub-fix:=20=D1=84=D0=B8=D0=BA=D1=81?= =?UTF-8?q?=204=20=D1=83=D1=80=D0=BE=D0=B2=D0=BD=D1=8F=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=B5=D1=80=D0=B2=D0=BE=D0=B9=20=D1=84=D0=BE?= =?UTF-8?q?=D1=80=D0=BC=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../versions/sql/0033_form2_old_sort.sql | 1402 +++++++++++++++++ 1 file changed, 1402 insertions(+) diff --git a/api/alembic/versions/sql/0033_form2_old_sort.sql b/api/alembic/versions/sql/0033_form2_old_sort.sql index ca9c255..71ac2e1 100644 --- a/api/alembic/versions/sql/0033_form2_old_sort.sql +++ b/api/alembic/versions/sql/0033_form2_old_sort.sql @@ -1719,3 +1719,1405 @@ SELECT count(*) AS updated_children_count FROM updated_children; REFRESH MATERIALIZED VIEW v3.mv_expense_item_tree; + +CREATE OR REPLACE FUNCTION v3.v_form1_sheet_sections(p_form_id integer, p_sheet character varying, p_direction character varying DEFAULT NULL::character varying, p_sections text[] DEFAULT NULL::text[]) + RETURNS TABLE(row_type character varying, depth integer, line_id integer, col_b_year integer, col_c_section character varying, col_d_item_id character varying, col_e_num_group character varying, col_f_name character varying, col_g_internal_order character varying, col_h_plan_q1 numeric, col_i_plan_q2 numeric, col_j_plan_q3 numeric, col_k_plan_q4 numeric, col_l_plan_year numeric, col_m_plan_comment character varying, col_n_cs_total numeric, col_o_cs_counterparty character varying, col_p_cs_deadline character varying, col_q_cs_comment character varying, col_r_cs_future_y1 numeric, col_s_cs_future_y2 numeric, col_t_cs_other_ssp numeric, col_v_al_order character varying, col_w_al_property character varying, col_y_seq_q1 numeric, col_z_seq_q2 numeric, col_aa_seq_q3 numeric, col_ab_seq_q4 numeric, col_ac_seq_year numeric, col_ad_seq_justification character varying, col_af_res_q1 numeric, col_ag_res_q2 numeric, col_ah_res_q3 numeric, col_ai_res_q4 numeric, col_aj_res_year numeric, col_ak_res_justification character varying, col_am_approved_q1 numeric, col_an_approved_q2 numeric, col_ao_approved_q3 numeric, col_ap_approved_q4 numeric, col_aq_approved_year numeric, col_as_ca_approved numeric, col_at_ca_protocol character varying, col_au_ca_note character varying, col_aw_ckk_ceiling numeric, col_ax_ckk_exp_q1 numeric, col_ay_ckk_exp_q2 numeric, col_az_ckk_exp_q3 numeric, col_ba_ckk_exp_q4 numeric, col_bb_ckk_rf_sched character varying, col_bc_ckk_deadline character varying, col_bd_ckk_proc_plan character varying, col_be_ckk_proc_meth character varying, col_bf_ckk_comment character varying, col_bh_cd_counterparty character varying, col_bi_cd_reference character varying, col_bj_cd_addenda character varying, col_bk_cd_subject character varying, col_bl_cd_currency character varying, col_bm_cd_ceiling numeric, col_bn_cd_exp_q1 numeric, col_bo_cd_exp_q2 numeric, col_bp_cd_exp_q3 numeric, col_bq_cd_exp_q4 numeric, col_br_cd_rf_sched character varying, col_bs_cd_vat character varying, col_bt_cd_rate numeric, col_bu_cd_amount_fx numeric, col_bv_cd_deadline character varying, col_bw_cd_scheme character varying, col_bx_cd_act character varying, col_by_cd_comment character varying, col_ca_q1_adj_current numeric, col_cb_q1_adj_ssp numeric, col_cc_q1_adj_rf numeric, col_cd_q1_adj_reserve numeric, col_ce_q1_adj_comment character varying, col_cf_q1_corrected_plan numeric, col_ch_q1_pay_date date, col_ci_q1_pay_amount numeric, col_cj_q1_pay_ho numeric, col_ck_q1_pay_rf numeric, col_cl_q1_pay_comment character varying, col_cm_q1_pay_act character varying, col_co_q1_booking numeric, col_cp_q1_actual_m1 numeric, col_cq_q1_actual_m2 numeric, col_cr_q1_actual_m3 numeric, col_cs_q1_actual_quarter numeric, col_ct_q1_rem_booking numeric, col_cu_q1_rem_actual numeric, col_cw_q1_trans_q2 numeric, col_cx_q1_trans_q3 numeric, col_cy_q1_trans_q4 numeric, col_cz_q1_economy numeric, col_da_q1_total numeric, col_dc_q2_rev_eco numeric, col_dd_q2_rev_item numeric, col_de_q2_rev_inc numeric, col_df_q2_rev_seq numeric, col_dg_q2_rev_comment character varying, col_dh_q2_new_plan numeric, col_dj_q2_adj_current numeric, col_dk_q2_adj_ssp numeric, col_dl_q2_adj_rf numeric, col_dm_q2_adj_reserve numeric, col_dn_q2_adj_comment character varying, col_do_q2_corrected_plan numeric, col_dq_q2_pay_date date, col_dr_q2_pay_amount numeric, col_ds_q2_pay_ho numeric, col_dt_q2_pay_rf numeric, col_du_q2_pay_comment character varying, col_dv_q2_pay_act character varying, col_dx_q2_booking numeric, col_dy_q2_actual_m1 numeric, col_dz_q2_actual_m2 numeric, col_ea_q2_actual_m3 numeric, col_eb_q2_actual_quarter numeric, col_ec_q2_rem_booking numeric, col_ed_q2_rem_actual numeric, col_ef_q2_trans_q3 numeric, col_eg_q2_trans_q4 numeric, col_eh_q2_economy numeric, col_ei_q2_total numeric, col_ek_q3_rev_eco numeric, col_el_q3_rev_item numeric, col_em_q3_rev_inc numeric, col_en_q3_rev_seq numeric, col_eo_q3_rev_comment character varying, col_ep_q3_new_plan numeric, col_er_q3_adj_current numeric, col_es_q3_adj_ssp numeric, col_et_q3_adj_rf numeric, col_eu_q3_adj_reserve numeric, col_ev_q3_adj_comment character varying, col_ew_q3_corrected_plan numeric, col_ey_q3_pay_date date, col_ez_q3_pay_amount numeric, col_fa_q3_pay_ho numeric, col_fb_q3_pay_rf numeric, col_fc_q3_pay_comment character varying, col_fd_q3_pay_act character varying, col_ff_q3_booking numeric, col_fg_q3_actual_m1 numeric, col_fh_q3_actual_m2 numeric, col_fi_q3_actual_m3 numeric, col_fj_q3_actual_quarter numeric, col_fk_q3_rem_booking numeric, col_fl_q3_rem_actual numeric, col_fn_q3_trans_q4 numeric, col_fo_q3_economy numeric, col_fp_q3_total numeric, col_fr_q4_rev_eco numeric, col_fs_q4_rev_item numeric, col_ft_q4_rev_inc numeric, col_fu_q4_rev_seq numeric, col_fv_q4_rev_comment character varying, col_fw_q4_new_plan numeric, col_fy_q4_adj_current numeric, col_fz_q4_adj_ssp numeric, col_ga_q4_adj_rf numeric, col_gb_q4_adj_reserve numeric, col_gc_q4_adj_comment character varying, col_gd_q4_corrected_plan numeric, col_gf_q4_pay_date date, col_gg_q4_pay_amount numeric, col_gh_q4_pay_ho numeric, col_gi_q4_pay_rf numeric, col_gj_q4_pay_comment character varying, col_gk_q4_pay_act character varying, col_gm_q4_booking numeric, col_gn_q4_actual_m1 numeric, col_go_q4_actual_m2 numeric, col_gp_q4_actual_m3 numeric, col_gq_q4_actual_quarter numeric, col_gr_q4_actual_spod numeric, col_gs_q4_rem_booking numeric, col_gt_q4_rem_actual numeric, col_gv_q4_economy numeric, col_gw_q4_total numeric, col_gz_fact_year numeric, col_hb_pay_year numeric, _sort_path integer[]) + LANGUAGE plpgsql + STABLE + SET search_path TO 'v3', 'pg_catalog' +AS $function$ +#variable_conflict use_column +DECLARE + v_year INT; + s_plan BOOL; s_cs BOOL; s_al BOOL; s_seq BOOL; s_res BOOL; + s_appr BOOL; s_ca BOOL; s_ckk BOOL; s_cd BOOL; + s_q1 BOOL; s_q2 BOOL; s_q3 BOOL; s_q4 BOOL; s_tot BOOL; + s_any_q BOOL; + s_need_ap BOOL; + s_need_bk BOOL; +BEGIN + SELECT bf.year INTO v_year FROM budget_form bf WHERE bf.id = p_form_id; + + s_plan := p_sections IS NULL OR 'plan' = ANY(p_sections); + s_cs := p_sections IS NULL OR 'contract_summary' = ANY(p_sections); + s_al := p_sections IS NULL OR 'allocation' = ANY(p_sections); + s_seq := p_sections IS NULL OR 'sequestration' = ANY(p_sections); + s_res := p_sections IS NULL OR 'reserve' = ANY(p_sections); + s_appr := p_sections IS NULL OR 'approved' = ANY(p_sections); + s_ca := p_sections IS NULL OR 'collegial' = ANY(p_sections); + s_ckk := p_sections IS NULL OR 'ckk' = ANY(p_sections); + s_cd := p_sections IS NULL OR 'contract_detail' = ANY(p_sections); + s_q1 := p_sections IS NULL OR 'q1' = ANY(p_sections); + s_q2 := p_sections IS NULL OR 'q2' = ANY(p_sections); + s_q3 := p_sections IS NULL OR 'q3' = ANY(p_sections); + s_q4 := p_sections IS NULL OR 'q4' = ANY(p_sections); + s_tot := p_sections IS NULL OR 'totals' = ANY(p_sections); + s_any_q := s_q1 OR s_q2 OR s_q3 OR s_q4 OR s_tot; + s_need_ap := s_plan OR s_appr OR s_q1 OR s_q2 OR s_q3 OR s_q4; + s_need_bk := s_q1 OR s_q2 OR s_q3 OR s_q4; + + RETURN QUERY + WITH + tw AS ( + SELECT t.id, t.section_code, t.item_id, t.num_group_id, t.name, + t.depth, t.path, t.parent_id, t.parent_item_id, t.desc_ids, + p.parent_item_id AS grandparent_item_id + FROM mv_expense_item_tree t + LEFT JOIN mv_expense_item_tree p ON p.id = t.parent_id + JOIN expense_item_form_type eft ON eft.expense_item_id = t.id + JOIN budget_form bf ON bf.id = p_form_id AND bf.form_type_code = eft.form_type_code + WHERE t.sheet = p_sheet + ), + + page AS ( + SELECT bl.id AS lid, bl.expense_item_id AS eid, bl.internal_order AS io, + bl.name AS bname + FROM budget_line bl + JOIN expense_item ei ON ei.id = bl.expense_item_id + WHERE bl.budget_form_id = p_form_id AND ei.sheet = p_sheet + AND (p_direction IS NULL OR bl.direction IS NULL OR bl.direction = p_direction) + ), + + jp AS (SELECT p.* FROM plan p JOIN page pg ON p.line_id = pg.lid WHERE s_plan), + jcs AS (SELECT cs.* FROM contract_summary cs JOIN page pg ON cs.line_id = pg.lid WHERE s_cs), + jal AS (SELECT al.* FROM allocation al JOIN page pg ON al.line_id = pg.lid WHERE s_al), + jsd AS (SELECT sd.* FROM sequestration sd JOIN page pg ON sd.line_id = pg.lid WHERE s_seq AND sd.actor='DFIP'), + jr AS (SELECT r.* FROM reserve r JOIN page pg ON r.line_id = pg.lid WHERE s_res), + jca AS (SELECT ca.* FROM collegial_approval ca JOIN page pg ON ca.line_id = pg.lid WHERE s_ca), + jck AS (SELECT ck.* FROM ckk ck JOIN page pg ON ck.line_id = pg.lid WHERE s_ckk), + jcd AS (SELECT cd.* FROM contract_detail cd JOIN page pg ON cd.line_id = pg.lid WHERE s_cd), + jq1 AS (SELECT blq.* FROM budget_line_quarter blq JOIN page pg ON blq.line_id = pg.lid WHERE s_q1 AND blq.quarter = 1), + jq2 AS (SELECT blq.* FROM budget_line_quarter blq JOIN page pg ON blq.line_id = pg.lid WHERE s_q2 AND blq.quarter = 2), + jq3 AS (SELECT blq.* FROM budget_line_quarter blq JOIN page pg ON blq.line_id = pg.lid WHERE s_q3 AND blq.quarter = 3), + jq4 AS (SELECT blq.* FROM budget_line_quarter blq JOIN page pg ON blq.line_id = pg.lid WHERE (s_q4 OR s_tot) AND blq.quarter = 4), + jtot AS ( + SELECT blq.line_id AS tlid, + SUM(CASE WHEN blq.quarter=1 THEN COALESCE(blq.actual_m1,0)+COALESCE(blq.actual_m2,0)+COALESCE(blq.actual_m3,0) END) AS tot_aq1, + SUM(CASE WHEN blq.quarter=2 THEN COALESCE(blq.actual_m1,0)+COALESCE(blq.actual_m2,0)+COALESCE(blq.actual_m3,0) END) AS tot_aq2, + SUM(CASE WHEN blq.quarter=3 THEN COALESCE(blq.actual_m1,0)+COALESCE(blq.actual_m2,0)+COALESCE(blq.actual_m3,0) END) AS tot_aq3, + SUM(CASE WHEN blq.quarter=4 THEN COALESCE(blq.actual_m1,0)+COALESCE(blq.actual_m2,0)+COALESCE(blq.actual_m3,0)+COALESCE(blq.actual_spod,0) END) AS tot_aq4, + SUM(CASE WHEN blq.quarter=1 THEN blq.payment_amount END) AS tot_pa1, + SUM(CASE WHEN blq.quarter=2 THEN blq.payment_amount END) AS tot_pa2, + SUM(CASE WHEN blq.quarter=3 THEN blq.payment_amount END) AS tot_pa3, + SUM(CASE WHEN blq.quarter=4 THEN blq.payment_amount END) AS tot_pa4 + FROM budget_line_quarter blq JOIN page pg ON blq.line_id = pg.lid + WHERE s_tot + GROUP BY blq.line_id + ), + + input_base AS ( + SELECT + pg.lid, pg.eid, pg.io, pg.bname, + CASE + WHEN t.depth < 3 THEN t.item_id + WHEN t.depth = 3 THEN t.parent_item_id + WHEN t.depth = 4 THEN t.grandparent_item_id + END AS sc, + t.item_id AS ic, + t.num_group_id AS ng, t.name AS ename, + COALESCE(p.plan_q1,0) AS pq1, COALESCE(p.plan_q2,0) AS pq2, + COALESCE(p.plan_q3,0) AS pq3, COALESCE(p.plan_q4,0) AS pq4, + p.comment AS pcmt, + COALESCE(sd.adj_q1,0) AS sq1, COALESCE(sd.adj_q2,0) AS sq2, + COALESCE(sd.adj_q3,0) AS sq3, COALESCE(sd.adj_q4,0) AS sq4, + sd.justification AS sjust, + COALESCE(r.amount_q1,0) AS rq1, COALESCE(r.amount_q2,0) AS rq2, + COALESCE(r.amount_q3,0) AS rq3, COALESCE(r.amount_q4,0) AS rq4, + r.justification AS rjust, + cs.*, al.internal_order AS al_io, al.property_object AS al_po, + ca.approved_amount AS ca_amt, ca.protocol_reference AS ca_prot, ca.note AS ca_note, + ck.ceiling_amount AS ckk_ceil, + COALESCE(ck.expenses_q1,0) AS ckk1, COALESCE(ck.expenses_q2,0) AS ckk2, + COALESCE(ck.expenses_q3,0) AS ckk3, COALESCE(ck.expenses_q4,0) AS ckk4, + ck.rf_schedule AS ckk_rf, ck.delivery_deadline AS ckk_dl, + ck.procurement_plan AS ckk_pp, ck.procurement_method AS ckk_pm, ck.comment AS ckk_cmt, + cd.counterparty AS cd_cp, cd.reference AS cd_ref, cd.addenda AS cd_add, + cd.subject AS cd_subj, cd.currency AS cd_cur, cd.ceiling_amount AS cd_ceil, + COALESCE(cd.expenses_q1,0) AS cdq1, COALESCE(cd.expenses_q2,0) AS cdq2, + COALESCE(cd.expenses_q3,0) AS cdq3, COALESCE(cd.expenses_q4,0) AS cdq4, + cd.rf_schedule AS cd_rf, cd.vat_rate AS cd_vat, cd.exchange_rate AS cd_rate, + cd.amount_foreign AS cd_fx, cd.deadline AS cd_dl, cd.payment_scheme AS cd_sch, + cd.act AS cd_act, cd.comment AS cd_cmt2, + q1.adj_current AS q1_ac, q1.adj_ssp AS q1_as, q1.adj_rf AS q1_ar, q1.adj_reserve AS q1_arv, + q1.adj_comment AS q1_acmt, q1.payment_date AS q1_pd, q1.payment_amount AS q1_pa, + q1.payment_amount_ho AS q1_pho, q1.payment_amount_rf AS q1_prf, + q1.payment_comment AS q1_pcmt, q1.payment_act AS q1_pact, + q1.actual_m1 AS q1_m1, q1.actual_m2 AS q1_m2, q1.actual_m3 AS q1_m3, + q1.transfer_to_q2 AS q1_tq2, q1.transfer_to_q3 AS q1_tq3, q1.transfer_to_q4 AS q1_tq4, + q2.plan_revision_eco_change AS q2_reco, q2.plan_revision_item_adj AS q2_ritm, + q2.plan_revision_increase AS q2_rinc, q2.plan_revision_sequester AS q2_rseq, + q2.plan_revision_comment AS q2_rcmt, + q2.adj_current AS q2_ac, q2.adj_ssp AS q2_as, q2.adj_rf AS q2_ar, q2.adj_reserve AS q2_arv, + q2.adj_comment AS q2_acmt, q2.payment_date AS q2_pd, q2.payment_amount AS q2_pa, + q2.payment_amount_ho AS q2_pho, q2.payment_amount_rf AS q2_prf, + q2.payment_comment AS q2_pcmt, q2.payment_act AS q2_pact, + q2.actual_m1 AS q2_m1, q2.actual_m2 AS q2_m2, q2.actual_m3 AS q2_m3, + q2.transfer_to_q3 AS q2_tq3, q2.transfer_to_q4 AS q2_tq4, + q3.plan_revision_eco_change AS q3_reco, q3.plan_revision_item_adj AS q3_ritm, + q3.plan_revision_increase AS q3_rinc, q3.plan_revision_sequester AS q3_rseq, + q3.plan_revision_comment AS q3_rcmt, + q3.adj_current AS q3_ac, q3.adj_ssp AS q3_as, q3.adj_rf AS q3_ar, q3.adj_reserve AS q3_arv, + q3.adj_comment AS q3_acmt, q3.payment_date AS q3_pd, q3.payment_amount AS q3_pa, + q3.payment_amount_ho AS q3_pho, q3.payment_amount_rf AS q3_prf, + q3.payment_comment AS q3_pcmt, q3.payment_act AS q3_pact, + q3.actual_m1 AS q3_m1, q3.actual_m2 AS q3_m2, q3.actual_m3 AS q3_m3, + q3.transfer_to_q4 AS q3_tq4, + q4.plan_revision_eco_change AS q4_reco, q4.plan_revision_item_adj AS q4_ritm, + q4.plan_revision_increase AS q4_rinc, q4.plan_revision_sequester AS q4_rseq, + q4.plan_revision_comment AS q4_rcmt, + q4.adj_current AS q4_ac, q4.adj_ssp AS q4_as, q4.adj_rf AS q4_ar, q4.adj_reserve AS q4_arv, + q4.adj_comment AS q4_acmt, q4.payment_date AS q4_pd, q4.payment_amount AS q4_pa, + q4.payment_amount_ho AS q4_pho, q4.payment_amount_rf AS q4_prf, + q4.payment_comment AS q4_pcmt, q4.payment_act AS q4_pact, + q4.actual_m1 AS q4_m1, q4.actual_m2 AS q4_m2, q4.actual_m3 AS q4_m3, + q4.actual_spod AS q4_spod, + tot.tot_aq1, tot.tot_aq2, tot.tot_aq3, tot.tot_aq4, + tot.tot_pa1, tot.tot_pa2, tot.tot_pa3, tot.tot_pa4, + CASE WHEN COALESCE(cd.expenses_q1,0)>0 THEN cd.expenses_q1 ELSE ck.expenses_q1 END AS bk1, + CASE WHEN COALESCE(cd.expenses_q2,0)>0 THEN cd.expenses_q2 ELSE ck.expenses_q2 END AS bk2, + CASE WHEN COALESCE(cd.expenses_q3,0)>0 THEN cd.expenses_q3 ELSE ck.expenses_q3 END AS bk3, + CASE WHEN COALESCE(cd.expenses_q4,0)>0 THEN cd.expenses_q4 ELSE ck.expenses_q4 END AS bk4, + COALESCE(p.plan_q1,0)+COALESCE(sd.adj_q1,0)+COALESCE(r.amount_q1,0) AS ap1, + COALESCE(p.plan_q2,0)+COALESCE(sd.adj_q2,0)+COALESCE(r.amount_q2,0) AS ap2, + COALESCE(p.plan_q3,0)+COALESCE(sd.adj_q3,0)+COALESCE(r.amount_q3,0) AS ap3, + COALESCE(p.plan_q4,0)+COALESCE(sd.adj_q4,0)+COALESCE(r.amount_q4,0) AS ap4, + t.path AS tree_path + FROM page pg + JOIN tw t ON t.id = pg.eid + LEFT JOIN jp p ON p.line_id = pg.lid + LEFT JOIN jcs cs ON cs.line_id = pg.lid + LEFT JOIN jal al ON al.line_id = pg.lid + LEFT JOIN jsd sd ON sd.line_id = pg.lid + LEFT JOIN jr r ON r.line_id = pg.lid + LEFT JOIN jca ca ON ca.line_id = pg.lid + LEFT JOIN jck ck ON ck.line_id = pg.lid + LEFT JOIN jcd cd ON cd.line_id = pg.lid + LEFT JOIN jq1 q1 ON q1.line_id = pg.lid + LEFT JOIN jq2 q2 ON q2.line_id = pg.lid + LEFT JOIN jq3 q3 ON q3.line_id = pg.lid + LEFT JOIN jq4 q4 ON q4.line_id = pg.lid + LEFT JOIN jtot tot ON tot.tlid = pg.lid + ), + enriched AS ( + SELECT b.*, + b.ap1 + COALESCE(b.q1_ac,0)+COALESCE(b.q1_as,0)+COALESCE(b.q1_ar,0)+COALESCE(b.q1_arv,0) AS cp1, + COALESCE(b.q1_m1,0)+COALESCE(b.q1_m2,0)+COALESCE(b.q1_m3,0) AS aq1, + b.ap2 + COALESCE(b.q1_tq2,0) + COALESCE(b.q2_reco,0)+COALESCE(b.q2_ritm,0)+COALESCE(b.q2_rinc,0)+COALESCE(b.q2_rseq,0) AS np2, + COALESCE(b.q2_m1,0)+COALESCE(b.q2_m2,0)+COALESCE(b.q2_m3,0) AS aq2, + b.ap3 + COALESCE(b.q1_tq3,0)+COALESCE(b.q2_tq3,0) + COALESCE(b.q3_reco,0)+COALESCE(b.q3_ritm,0)+COALESCE(b.q3_rinc,0)+COALESCE(b.q3_rseq,0) AS np3, + COALESCE(b.q3_m1,0)+COALESCE(b.q3_m2,0)+COALESCE(b.q3_m3,0) AS aq3, + b.ap4 + COALESCE(b.q1_tq4,0)+COALESCE(b.q2_tq4,0)+COALESCE(b.q3_tq4,0) + COALESCE(b.q4_reco,0)+COALESCE(b.q4_ritm,0)+COALESCE(b.q4_rinc,0)+COALESCE(b.q4_rseq,0) AS np4, + COALESCE(b.q4_m1,0)+COALESCE(b.q4_m2,0)+COALESCE(b.q4_m3,0) AS aq4_no_spod, + COALESCE(b.q4_m1,0)+COALESCE(b.q4_m2,0)+COALESCE(b.q4_m3,0)+COALESCE(b.q4_spod,0) AS aq4 + FROM input_base b + ), + final_input AS ( + SELECT e.*, + e.np2 + COALESCE(e.q2_ac,0)+COALESCE(e.q2_as,0)+COALESCE(e.q2_ar,0)+COALESCE(e.q2_arv,0) AS cp2, + e.np3 + COALESCE(e.q3_ac,0)+COALESCE(e.q3_as,0)+COALESCE(e.q3_ar,0)+COALESCE(e.q3_arv,0) AS cp3, + e.np4 + COALESCE(e.q4_ac,0)+COALESCE(e.q4_as,0)+COALESCE(e.q4_ar,0)+COALESCE(e.q4_arv,0) AS cp4 + FROM enriched e + ), + + agg AS ( + SELECT bl.expense_item_id AS eid, + SUM(p.plan_q1) AS sp1, SUM(p.plan_q2) AS sp2, SUM(p.plan_q3) AS sp3, SUM(p.plan_q4) AS sp4, + SUM(sd.adj_q1) AS ss1, SUM(sd.adj_q2) AS ss2, SUM(sd.adj_q3) AS ss3, SUM(sd.adj_q4) AS ss4, + SUM(r.amount_q1) AS sr1, SUM(r.amount_q2) AS sr2, SUM(r.amount_q3) AS sr3, SUM(r.amount_q4) AS sr4, + SUM(ca.approved_amount) AS sca, + SUM(ck.ceiling_amount) AS sckc, + SUM(ck.expenses_q1) AS sck1, SUM(ck.expenses_q2) AS sck2, SUM(ck.expenses_q3) AS sck3, SUM(ck.expenses_q4) AS sck4, + SUM(cd.ceiling_amount) AS scdc, + SUM(cd.expenses_q1) AS scd1, SUM(cd.expenses_q2) AS scd2, SUM(cd.expenses_q3) AS scd3, SUM(cd.expenses_q4) AS scd4, + SUM(cs.total_amount) AS scst, SUM(cs.future_payments_y1) AS sfy1, SUM(cs.future_payments_y2) AS sfy2, + SUM(cs.other_ssp_amount) AS sossp + FROM budget_line bl + JOIN expense_item ei ON ei.id = bl.expense_item_id + LEFT JOIN plan p ON p.line_id = bl.id AND s_need_ap + LEFT JOIN contract_summary cs ON cs.line_id = bl.id AND s_cs + LEFT JOIN sequestration sd ON sd.line_id = bl.id AND sd.actor = 'DFIP' AND s_need_ap + LEFT JOIN reserve r ON r.line_id = bl.id AND s_need_ap + LEFT JOIN collegial_approval ca ON ca.line_id = bl.id AND s_ca + LEFT JOIN ckk ck ON ck.line_id = bl.id AND (s_ckk OR s_need_bk) + LEFT JOIN contract_detail cd ON cd.line_id = bl.id AND (s_cd OR s_need_bk) + WHERE bl.budget_form_id = p_form_id AND ei.sheet = p_sheet AND (p_direction is null OR bl.direction is null or bl.direction = p_direction) + AND (s_need_ap OR s_cs OR s_ca OR s_ckk OR s_cd OR s_need_bk) + GROUP BY bl.expense_item_id + ), + aq1 AS ( + SELECT bl.expense_item_id AS eid, + SUM(blq.adj_current) AS ac, SUM(blq.adj_ssp) AS as2, SUM(blq.adj_rf) AS ar, SUM(blq.adj_reserve) AS arv, + SUM(blq.payment_amount) AS pa, SUM(blq.payment_amount_ho) AS pho, SUM(blq.payment_amount_rf) AS prf, + SUM(blq.actual_m1) AS m1, SUM(blq.actual_m2) AS m2, SUM(blq.actual_m3) AS m3, + SUM(blq.transfer_to_q2) AS tq2, SUM(blq.transfer_to_q3) AS tq3, SUM(blq.transfer_to_q4) AS tq4 + FROM budget_line bl JOIN expense_item ei ON ei.id = bl.expense_item_id + LEFT JOIN budget_line_quarter blq ON blq.line_id = bl.id AND blq.quarter = 1 + WHERE bl.budget_form_id = p_form_id AND ei.sheet = p_sheet AND s_q1 AND (p_direction is null OR bl.direction is null or bl.direction = p_direction) + GROUP BY bl.expense_item_id + ), + aq2 AS ( + SELECT bl.expense_item_id AS eid, + SUM(blq.plan_revision_eco_change) AS reco, SUM(blq.plan_revision_item_adj) AS ritm, + SUM(blq.plan_revision_increase) AS rinc, SUM(blq.plan_revision_sequester) AS rseq, + SUM(blq.adj_current) AS ac, SUM(blq.adj_ssp) AS as2, SUM(blq.adj_rf) AS ar, SUM(blq.adj_reserve) AS arv, + SUM(blq.payment_amount) AS pa, SUM(blq.payment_amount_ho) AS pho, SUM(blq.payment_amount_rf) AS prf, + SUM(blq.actual_m1) AS m1, SUM(blq.actual_m2) AS m2, SUM(blq.actual_m3) AS m3, + SUM(blq.transfer_to_q3) AS tq3, SUM(blq.transfer_to_q4) AS tq4 + FROM budget_line bl JOIN expense_item ei ON ei.id = bl.expense_item_id + LEFT JOIN budget_line_quarter blq ON blq.line_id = bl.id AND blq.quarter = 2 + WHERE bl.budget_form_id = p_form_id AND ei.sheet = p_sheet AND s_q2 AND (p_direction is null OR bl.direction is null or bl.direction = p_direction) + GROUP BY bl.expense_item_id + ), + aq3 AS ( + SELECT bl.expense_item_id AS eid, + SUM(blq.plan_revision_eco_change) AS reco, SUM(blq.plan_revision_item_adj) AS ritm, + SUM(blq.plan_revision_increase) AS rinc, SUM(blq.plan_revision_sequester) AS rseq, + SUM(blq.adj_current) AS ac, SUM(blq.adj_ssp) AS as2, SUM(blq.adj_rf) AS ar, SUM(blq.adj_reserve) AS arv, + SUM(blq.payment_amount) AS pa, SUM(blq.payment_amount_ho) AS pho, SUM(blq.payment_amount_rf) AS prf, + SUM(blq.actual_m1) AS m1, SUM(blq.actual_m2) AS m2, SUM(blq.actual_m3) AS m3, + SUM(blq.transfer_to_q4) AS tq4 + FROM budget_line bl JOIN expense_item ei ON ei.id = bl.expense_item_id + LEFT JOIN budget_line_quarter blq ON blq.line_id = bl.id AND blq.quarter = 3 + WHERE bl.budget_form_id = p_form_id AND ei.sheet = p_sheet AND s_q3 AND (p_direction is null OR bl.direction is null or bl.direction = p_direction) + GROUP BY bl.expense_item_id + ), + aq4 AS ( + SELECT bl.expense_item_id AS eid, + SUM(blq.plan_revision_eco_change) AS reco, SUM(blq.plan_revision_item_adj) AS ritm, + SUM(blq.plan_revision_increase) AS rinc, SUM(blq.plan_revision_sequester) AS rseq, + SUM(blq.adj_current) AS ac, SUM(blq.adj_ssp) AS as2, SUM(blq.adj_rf) AS ar, SUM(blq.adj_reserve) AS arv, + SUM(blq.payment_amount) AS pa, SUM(blq.payment_amount_ho) AS pho, SUM(blq.payment_amount_rf) AS prf, + SUM(blq.actual_m1) AS m1, SUM(blq.actual_m2) AS m2, SUM(blq.actual_m3) AS m3, + SUM(blq.actual_spod) AS spod + FROM budget_line bl JOIN expense_item ei ON ei.id = bl.expense_item_id + LEFT JOIN budget_line_quarter blq ON blq.line_id = bl.id AND blq.quarter = 4 + WHERE bl.budget_form_id = p_form_id AND ei.sheet = p_sheet AND (s_q4 OR s_tot) AND (p_direction is null OR bl.direction is null or bl.direction = p_direction) + GROUP BY bl.expense_item_id + ), + atot AS ( + SELECT bl.expense_item_id AS eid, + SUM(CASE WHEN blq.quarter=1 THEN COALESCE(blq.actual_m1,0)+COALESCE(blq.actual_m2,0)+COALESCE(blq.actual_m3,0) END) AS fq1, + SUM(CASE WHEN blq.quarter=2 THEN COALESCE(blq.actual_m1,0)+COALESCE(blq.actual_m2,0)+COALESCE(blq.actual_m3,0) END) AS fq2, + SUM(CASE WHEN blq.quarter=3 THEN COALESCE(blq.actual_m1,0)+COALESCE(blq.actual_m2,0)+COALESCE(blq.actual_m3,0) END) AS fq3, + SUM(CASE WHEN blq.quarter=4 THEN COALESCE(blq.actual_m1,0)+COALESCE(blq.actual_m2,0)+COALESCE(blq.actual_m3,0)+COALESCE(blq.actual_spod,0) END) AS fq4, + SUM(blq.payment_amount) AS pay + FROM budget_line bl JOIN expense_item ei ON ei.id = bl.expense_item_id + LEFT JOIN budget_line_quarter blq ON blq.line_id = bl.id + WHERE bl.budget_form_id = p_form_id AND ei.sheet = p_sheet AND s_tot AND (p_direction is null OR bl.direction is null or bl.direction = p_direction) + GROUP BY bl.expense_item_id + ), + tw_agg AS ( + SELECT tw.id, + SUM(a.sp1) AS sp1, SUM(a.sp2) AS sp2, SUM(a.sp3) AS sp3, SUM(a.sp4) AS sp4, + SUM(a.ss1) AS ss1, SUM(a.ss2) AS ss2, SUM(a.ss3) AS ss3, SUM(a.ss4) AS ss4, + SUM(a.sr1) AS sr1, SUM(a.sr2) AS sr2, SUM(a.sr3) AS sr3, SUM(a.sr4) AS sr4, + SUM(a.sca) AS sca, + SUM(a.sckc) AS sckc, SUM(a.sck1) AS sck1, SUM(a.sck2) AS sck2, SUM(a.sck3) AS sck3, SUM(a.sck4) AS sck4, + SUM(a.scdc) AS scdc, SUM(a.scd1) AS scd1, SUM(a.scd2) AS scd2, SUM(a.scd3) AS scd3, SUM(a.scd4) AS scd4, + SUM(a.scst) AS scst, SUM(a.sfy1) AS sfy1, SUM(a.sfy2) AS sfy2, SUM(a.sossp) AS sossp, + SUM(CASE WHEN COALESCE(a.scd1,0)>0 THEN a.scd1 ELSE a.sck1 END) AS bk1, + SUM(CASE WHEN COALESCE(a.scd2,0)>0 THEN a.scd2 ELSE a.sck2 END) AS bk2, + SUM(CASE WHEN COALESCE(a.scd3,0)>0 THEN a.scd3 ELSE a.sck3 END) AS bk3, + SUM(CASE WHEN COALESCE(a.scd4,0)>0 THEN a.scd4 ELSE a.sck4 END) AS bk4 + FROM tw LEFT JOIN agg a ON a.eid = ANY(tw.desc_ids) + GROUP BY tw.id + ), + tw_aq1 AS ( + SELECT tw.id, SUM(b.ac) AS ac, SUM(b.as2) AS as2, SUM(b.ar) AS ar, SUM(b.arv) AS arv, + SUM(b.pa) AS pa, SUM(b.pho) AS pho, SUM(b.prf) AS prf, + SUM(b.m1) AS m1, SUM(b.m2) AS m2, SUM(b.m3) AS m3, + SUM(b.tq2) AS tq2, SUM(b.tq3) AS tq3, SUM(b.tq4) AS tq4 + FROM tw LEFT JOIN aq1 b ON b.eid = ANY(tw.desc_ids) GROUP BY tw.id + ), + tw_aq2 AS ( + SELECT tw.id, SUM(b.reco) AS reco, SUM(b.ritm) AS ritm, SUM(b.rinc) AS rinc, SUM(b.rseq) AS rseq, + SUM(b.ac) AS ac, SUM(b.as2) AS as2, SUM(b.ar) AS ar, SUM(b.arv) AS arv, + SUM(b.pa) AS pa, SUM(b.pho) AS pho, SUM(b.prf) AS prf, + SUM(b.m1) AS m1, SUM(b.m2) AS m2, SUM(b.m3) AS m3, + SUM(b.tq3) AS tq3, SUM(b.tq4) AS tq4 + FROM tw LEFT JOIN aq2 b ON b.eid = ANY(tw.desc_ids) GROUP BY tw.id + ), + tw_aq3 AS ( + SELECT tw.id, SUM(b.reco) AS reco, SUM(b.ritm) AS ritm, SUM(b.rinc) AS rinc, SUM(b.rseq) AS rseq, + SUM(b.ac) AS ac, SUM(b.as2) AS as2, SUM(b.ar) AS ar, SUM(b.arv) AS arv, + SUM(b.pa) AS pa, SUM(b.pho) AS pho, SUM(b.prf) AS prf, + SUM(b.m1) AS m1, SUM(b.m2) AS m2, SUM(b.m3) AS m3, + SUM(b.tq4) AS tq4 + FROM tw LEFT JOIN aq3 b ON b.eid = ANY(tw.desc_ids) GROUP BY tw.id + ), + tw_aq4 AS ( + SELECT tw.id, SUM(b.reco) AS reco, SUM(b.ritm) AS ritm, SUM(b.rinc) AS rinc, SUM(b.rseq) AS rseq, + SUM(b.ac) AS ac, SUM(b.as2) AS as2, SUM(b.ar) AS ar, SUM(b.arv) AS arv, + SUM(b.pa) AS pa, SUM(b.pho) AS pho, SUM(b.prf) AS prf, + SUM(b.m1) AS m1, SUM(b.m2) AS m2, SUM(b.m3) AS m3, + SUM(b.spod) AS spod + FROM tw LEFT JOIN aq4 b ON b.eid = ANY(tw.desc_ids) GROUP BY tw.id + ), + tw_atot AS ( + SELECT tw.id, SUM(b.fq1) AS fq1, SUM(b.fq2) AS fq2, SUM(b.fq3) AS fq3, SUM(b.fq4) AS fq4, + SUM(b.pay) AS pay + FROM tw LEFT JOIN atot b ON b.eid = ANY(tw.desc_ids) GROUP BY tw.id + ) + + SELECT * FROM ( + SELECT + 'INPUT'::VARCHAR, array_length(f.tree_path, 1)::INT, f.lid, + v_year, f.sc, f.ic, f.ng, COALESCE(f.bname, f.ename), f.io, + CASE WHEN s_plan THEN f.pq1 END, CASE WHEN s_plan THEN f.pq2 END, + CASE WHEN s_plan THEN f.pq3 END, CASE WHEN s_plan THEN f.pq4 END, + CASE WHEN s_plan THEN f.pq1+f.pq2+f.pq3+f.pq4 END, CASE WHEN s_plan THEN f.pcmt END, + CASE WHEN s_cs THEN f.total_amount END, CASE WHEN s_cs THEN f.counterparty END, + CASE WHEN s_cs THEN f.deadline END, CASE WHEN s_cs THEN f.comment END, + CASE WHEN s_cs THEN f.future_payments_y1 END, CASE WHEN s_cs THEN f.future_payments_y2 END, + CASE WHEN s_cs THEN f.other_ssp_amount END, + CASE WHEN s_al THEN f.al_io END, CASE WHEN s_al THEN f.al_po END, + CASE WHEN s_seq THEN f.sq1 END, CASE WHEN s_seq THEN f.sq2 END, + CASE WHEN s_seq THEN f.sq3 END, CASE WHEN s_seq THEN f.sq4 END, + CASE WHEN s_seq THEN f.sq1+f.sq2+f.sq3+f.sq4 END, CASE WHEN s_seq THEN f.sjust END, + CASE WHEN s_res THEN f.rq1 END, CASE WHEN s_res THEN f.rq2 END, + CASE WHEN s_res THEN f.rq3 END, CASE WHEN s_res THEN f.rq4 END, + CASE WHEN s_res THEN f.rq1+f.rq2+f.rq3+f.rq4 END, CASE WHEN s_res THEN f.rjust END, + CASE WHEN s_appr THEN f.ap1 END, CASE WHEN s_appr THEN f.ap2 END, + CASE WHEN s_appr THEN f.ap3 END, CASE WHEN s_appr THEN f.ap4 END, + CASE WHEN s_appr THEN f.ap1+f.ap2+f.ap3+f.ap4 END, + CASE WHEN s_ca THEN f.ca_amt END, CASE WHEN s_ca THEN f.ca_prot END, CASE WHEN s_ca THEN f.ca_note END, + CASE WHEN s_ckk THEN f.ckk_ceil END, CASE WHEN s_ckk THEN f.ckk1 END, CASE WHEN s_ckk THEN f.ckk2 END, + CASE WHEN s_ckk THEN f.ckk3 END, CASE WHEN s_ckk THEN f.ckk4 END, + CASE WHEN s_ckk THEN f.ckk_rf END, CASE WHEN s_ckk THEN f.ckk_dl END, + CASE WHEN s_ckk THEN f.ckk_pp END, CASE WHEN s_ckk THEN f.ckk_pm END, CASE WHEN s_ckk THEN f.ckk_cmt END, + CASE WHEN s_cd THEN f.cd_cp END, CASE WHEN s_cd THEN f.cd_ref END, CASE WHEN s_cd THEN f.cd_add END, + CASE WHEN s_cd THEN f.cd_subj END, CASE WHEN s_cd THEN f.cd_cur END, CASE WHEN s_cd THEN f.cd_ceil END, + CASE WHEN s_cd THEN f.cdq1 END, CASE WHEN s_cd THEN f.cdq2 END, + CASE WHEN s_cd THEN f.cdq3 END, CASE WHEN s_cd THEN f.cdq4 END, + CASE WHEN s_cd THEN f.cd_rf END, CASE WHEN s_cd THEN f.cd_vat END, + CASE WHEN s_cd THEN f.cd_rate END, CASE WHEN s_cd THEN f.cd_fx END, + CASE WHEN s_cd THEN f.cd_dl END, CASE WHEN s_cd THEN f.cd_sch END, + CASE WHEN s_cd THEN f.cd_act END, CASE WHEN s_cd THEN f.cd_cmt2 END, + CASE WHEN s_q1 THEN f.q1_ac END, CASE WHEN s_q1 THEN f.q1_as END, + CASE WHEN s_q1 THEN f.q1_ar END, CASE WHEN s_q1 THEN f.q1_arv END, + CASE WHEN s_q1 THEN f.q1_acmt END, CASE WHEN s_q1 THEN f.cp1 END, + CASE WHEN s_q1 THEN f.q1_pd END, CASE WHEN s_q1 THEN f.q1_pa END, + CASE WHEN s_q1 THEN f.q1_pho END, CASE WHEN s_q1 THEN f.q1_prf END, + CASE WHEN s_q1 THEN f.q1_pcmt END, CASE WHEN s_q1 THEN f.q1_pact END, + CASE WHEN s_q1 THEN COALESCE(f.bk1,0) END, + CASE WHEN s_q1 THEN f.q1_m1 END, CASE WHEN s_q1 THEN f.q1_m2 END, CASE WHEN s_q1 THEN f.q1_m3 END, + CASE WHEN s_q1 THEN f.aq1 END, + CASE WHEN s_q1 THEN f.cp1 - COALESCE(f.bk1,0) END, + CASE WHEN s_q1 THEN f.cp1 - f.aq1 END, + CASE WHEN s_q1 THEN f.q1_tq2 END, CASE WHEN s_q1 THEN f.q1_tq3 END, CASE WHEN s_q1 THEN f.q1_tq4 END, + CASE WHEN s_q1 THEN f.cp1 - f.aq1 - COALESCE(f.q1_tq2,0) - COALESCE(f.q1_tq3,0) - COALESCE(f.q1_tq4,0) END, + CASE WHEN s_q1 THEN f.cp1 - f.aq1 END, + CASE WHEN s_q2 THEN f.q2_reco END, CASE WHEN s_q2 THEN f.q2_ritm END, + CASE WHEN s_q2 THEN f.q2_rinc END, CASE WHEN s_q2 THEN f.q2_rseq END, + CASE WHEN s_q2 THEN f.q2_rcmt END, CASE WHEN s_q2 THEN f.np2 END, + CASE WHEN s_q2 THEN f.q2_ac END, CASE WHEN s_q2 THEN f.q2_as END, + CASE WHEN s_q2 THEN f.q2_ar END, CASE WHEN s_q2 THEN f.q2_arv END, + CASE WHEN s_q2 THEN f.q2_acmt END, CASE WHEN s_q2 THEN f.cp2 END, + CASE WHEN s_q2 THEN f.q2_pd END, CASE WHEN s_q2 THEN f.q2_pa END, + CASE WHEN s_q2 THEN f.q2_pho END, CASE WHEN s_q2 THEN f.q2_prf END, + CASE WHEN s_q2 THEN f.q2_pcmt END, CASE WHEN s_q2 THEN f.q2_pact END, + CASE WHEN s_q2 THEN COALESCE(f.bk2,0) END, + CASE WHEN s_q2 THEN f.q2_m1 END, CASE WHEN s_q2 THEN f.q2_m2 END, CASE WHEN s_q2 THEN f.q2_m3 END, + CASE WHEN s_q2 THEN f.aq2 END, + CASE WHEN s_q2 THEN f.cp2 - COALESCE(f.bk2,0) END, + CASE WHEN s_q2 THEN f.cp2 - f.aq2 END, + CASE WHEN s_q2 THEN f.q2_tq3 END, CASE WHEN s_q2 THEN f.q2_tq4 END, + CASE WHEN s_q2 THEN f.cp2 - f.aq2 - COALESCE(f.q2_tq3,0) - COALESCE(f.q2_tq4,0) END, + CASE WHEN s_q2 THEN f.cp2 - f.aq2 END, + CASE WHEN s_q3 THEN f.q3_reco END, CASE WHEN s_q3 THEN f.q3_ritm END, + CASE WHEN s_q3 THEN f.q3_rinc END, CASE WHEN s_q3 THEN f.q3_rseq END, + CASE WHEN s_q3 THEN f.q3_rcmt END, CASE WHEN s_q3 THEN f.np3 END, + CASE WHEN s_q3 THEN f.q3_ac END, CASE WHEN s_q3 THEN f.q3_as END, + CASE WHEN s_q3 THEN f.q3_ar END, CASE WHEN s_q3 THEN f.q3_arv END, + CASE WHEN s_q3 THEN f.q3_acmt END, CASE WHEN s_q3 THEN f.cp3 END, + CASE WHEN s_q3 THEN f.q3_pd END, CASE WHEN s_q3 THEN f.q3_pa END, + CASE WHEN s_q3 THEN f.q3_pho END, CASE WHEN s_q3 THEN f.q3_prf END, + CASE WHEN s_q3 THEN f.q3_pcmt END, CASE WHEN s_q3 THEN f.q3_pact END, + CASE WHEN s_q3 THEN COALESCE(f.bk3,0) END, + CASE WHEN s_q3 THEN f.q3_m1 END, CASE WHEN s_q3 THEN f.q3_m2 END, CASE WHEN s_q3 THEN f.q3_m3 END, + CASE WHEN s_q3 THEN f.aq3 END, + CASE WHEN s_q3 THEN f.cp3 - COALESCE(f.bk3,0) END, + CASE WHEN s_q3 THEN f.cp3 - f.aq3 END, + CASE WHEN s_q3 THEN f.q3_tq4 END, + CASE WHEN s_q3 THEN f.cp3 - f.aq3 - COALESCE(f.q3_tq4,0) END, + CASE WHEN s_q3 THEN f.cp3 - f.aq3 END, + CASE WHEN s_q4 THEN f.q4_reco END, CASE WHEN s_q4 THEN f.q4_ritm END, + CASE WHEN s_q4 THEN f.q4_rinc END, CASE WHEN s_q4 THEN f.q4_rseq END, + CASE WHEN s_q4 THEN f.q4_rcmt END, CASE WHEN s_q4 THEN f.np4 END, + CASE WHEN s_q4 THEN f.q4_ac END, CASE WHEN s_q4 THEN f.q4_as END, + CASE WHEN s_q4 THEN f.q4_ar END, CASE WHEN s_q4 THEN f.q4_arv END, + CASE WHEN s_q4 THEN f.q4_acmt END, CASE WHEN s_q4 THEN f.cp4 END, + CASE WHEN s_q4 THEN f.q4_pd END, CASE WHEN s_q4 THEN f.q4_pa END, + CASE WHEN s_q4 THEN f.q4_pho END, CASE WHEN s_q4 THEN f.q4_prf END, + CASE WHEN s_q4 THEN f.q4_pcmt END, CASE WHEN s_q4 THEN f.q4_pact END, + CASE WHEN s_q4 THEN COALESCE(f.bk4,0) END, + CASE WHEN s_q4 THEN f.q4_m1 END, CASE WHEN s_q4 THEN f.q4_m2 END, CASE WHEN s_q4 THEN f.q4_m3 END, + CASE WHEN s_q4 THEN f.aq4_no_spod END, + CASE WHEN s_q4 THEN f.q4_spod END, + CASE WHEN s_q4 THEN f.cp4 - COALESCE(f.bk4,0) END, + CASE WHEN s_q4 THEN f.cp4 - f.aq4 END, + CASE WHEN s_q4 THEN f.cp4 - f.aq4 END, + CASE WHEN s_q4 THEN f.cp4 - f.aq4 END, + CASE WHEN s_tot THEN COALESCE(f.tot_aq1,0)+COALESCE(f.tot_aq2,0)+COALESCE(f.tot_aq3,0)+COALESCE(f.tot_aq4,0) END, + CASE WHEN s_tot THEN COALESCE(f.tot_pa1,0)+COALESCE(f.tot_pa2,0)+COALESCE(f.tot_pa3,0)+COALESCE(f.tot_pa4,0) END, + f.tree_path || ARRAY[f.lid] AS _sort + FROM final_input f + + UNION ALL + + SELECT + CASE t.depth WHEN 0 THEN 'ROOT' WHEN 1 THEN 'GROUP' WHEN 2 THEN 'ITEM' WHEN 3 THEN 'SUB_ITEM' WHEN 4 THEN 'SUB_SUB_ITEM' END::VARCHAR, + t.depth, NULL::INT, + v_year, + CASE + WHEN t.depth < 3 THEN t.item_id + WHEN t.depth = 3 THEN t.parent_item_id + WHEN t.depth = 4 THEN t.grandparent_item_id + END, + CASE WHEN t.depth >= 3 THEN t.item_id ELSE NULL::VARCHAR END, + t.num_group_id, t.name, NULL::VARCHAR, + CASE WHEN s_plan THEN ta.sp1 END, + CASE WHEN s_plan THEN ta.sp2 END, + CASE WHEN s_plan THEN ta.sp3 END, + CASE WHEN s_plan THEN ta.sp4 END, + CASE WHEN s_plan THEN (COALESCE(ta.sp1,0)+COALESCE(ta.sp2,0)+COALESCE(ta.sp3,0)+COALESCE(ta.sp4,0)) END, + NULL::VARCHAR, + CASE WHEN s_cs THEN ta.scst END, + NULL::VARCHAR, NULL::VARCHAR, NULL::VARCHAR, + CASE WHEN s_cs THEN ta.sfy1 END, + CASE WHEN s_cs THEN ta.sfy2 END, + CASE WHEN s_cs THEN ta.sossp END, + NULL::VARCHAR, NULL::VARCHAR, + CASE WHEN s_seq THEN ta.ss1 END, + CASE WHEN s_seq THEN ta.ss2 END, + CASE WHEN s_seq THEN ta.ss3 END, + CASE WHEN s_seq THEN ta.ss4 END, + CASE WHEN s_seq THEN (COALESCE(ta.ss1,0)+COALESCE(ta.ss2,0)+COALESCE(ta.ss3,0)+COALESCE(ta.ss4,0)) END, + NULL::VARCHAR, + CASE WHEN s_res THEN ta.sr1 END, + CASE WHEN s_res THEN ta.sr2 END, + CASE WHEN s_res THEN ta.sr3 END, + CASE WHEN s_res THEN ta.sr4 END, + CASE WHEN s_res THEN (COALESCE(ta.sr1,0)+COALESCE(ta.sr2,0)+COALESCE(ta.sr3,0)+COALESCE(ta.sr4,0)) END, + NULL::VARCHAR, + CASE WHEN s_appr THEN (COALESCE(ta.sp1,0)+COALESCE(ta.ss1,0)+COALESCE(ta.sr1,0)) END, + CASE WHEN s_appr THEN (COALESCE(ta.sp2,0)+COALESCE(ta.ss2,0)+COALESCE(ta.sr2,0)) END, + CASE WHEN s_appr THEN (COALESCE(ta.sp3,0)+COALESCE(ta.ss3,0)+COALESCE(ta.sr3,0)) END, + CASE WHEN s_appr THEN (COALESCE(ta.sp4,0)+COALESCE(ta.ss4,0)+COALESCE(ta.sr4,0)) END, + CASE WHEN s_appr THEN (COALESCE(ta.sp1,0)+COALESCE(ta.sp2,0)+COALESCE(ta.sp3,0)+COALESCE(ta.sp4,0) + +COALESCE(ta.ss1,0)+COALESCE(ta.ss2,0)+COALESCE(ta.ss3,0)+COALESCE(ta.ss4,0) + +COALESCE(ta.sr1,0)+COALESCE(ta.sr2,0)+COALESCE(ta.sr3,0)+COALESCE(ta.sr4,0)) END, + CASE WHEN s_ca THEN ta.sca END, + NULL::VARCHAR, NULL::VARCHAR, + CASE WHEN s_ckk THEN ta.sckc END, + CASE WHEN s_ckk THEN ta.sck1 END, + CASE WHEN s_ckk THEN ta.sck2 END, + CASE WHEN s_ckk THEN ta.sck3 END, + CASE WHEN s_ckk THEN ta.sck4 END, + NULL::VARCHAR, NULL::VARCHAR, NULL::VARCHAR, NULL::VARCHAR, NULL::VARCHAR, + NULL::VARCHAR, NULL::VARCHAR, NULL::VARCHAR, NULL::VARCHAR, NULL::VARCHAR, + CASE WHEN s_cd THEN ta.scdc END, + CASE WHEN s_cd THEN ta.scd1 END, + CASE WHEN s_cd THEN ta.scd2 END, + CASE WHEN s_cd THEN ta.scd3 END, + CASE WHEN s_cd THEN ta.scd4 END, + NULL::VARCHAR, NULL::VARCHAR, NULL::NUMERIC, NULL::NUMERIC, NULL::VARCHAR, NULL::VARCHAR, NULL::VARCHAR, NULL::VARCHAR, + CASE WHEN s_q1 THEN tb1.ac END, + CASE WHEN s_q1 THEN tb1.as2 END, + CASE WHEN s_q1 THEN tb1.ar END, + CASE WHEN s_q1 THEN tb1.arv END, + NULL::VARCHAR, + CASE WHEN s_q1 THEN + (COALESCE(ta.sp1,0)+COALESCE(ta.ss1,0)+COALESCE(ta.sr1,0)) + + COALESCE((COALESCE(tb1.ac,0)+COALESCE(tb1.as2,0)+COALESCE(tb1.ar,0)+COALESCE(tb1.arv,0)), 0) + END, + NULL::DATE, + CASE WHEN s_q1 THEN tb1.pa END, + CASE WHEN s_q1 THEN tb1.pho END, + CASE WHEN s_q1 THEN tb1.prf END, + NULL::VARCHAR, NULL::VARCHAR, + CASE WHEN s_q1 THEN ta.bk1 END, + CASE WHEN s_q1 THEN tb1.m1 END, + CASE WHEN s_q1 THEN tb1.m2 END, + CASE WHEN s_q1 THEN tb1.m3 END, + CASE WHEN s_q1 THEN (COALESCE(tb1.m1,0)+COALESCE(tb1.m2,0)+COALESCE(tb1.m3,0)) END, + CASE WHEN s_q1 THEN + (COALESCE(ta.sp1,0)+COALESCE(ta.ss1,0)+COALESCE(ta.sr1,0)) + + COALESCE((COALESCE(tb1.ac,0)+COALESCE(tb1.as2,0)+COALESCE(tb1.ar,0)+COALESCE(tb1.arv,0)),0) + - COALESCE(ta.bk1,0) + END, + CASE WHEN s_q1 THEN + (COALESCE(ta.sp1,0)+COALESCE(ta.ss1,0)+COALESCE(ta.sr1,0)) + + COALESCE((COALESCE(tb1.ac,0)+COALESCE(tb1.as2,0)+COALESCE(tb1.ar,0)+COALESCE(tb1.arv,0)),0) + - COALESCE((COALESCE(tb1.m1,0)+COALESCE(tb1.m2,0)+COALESCE(tb1.m3,0)),0) + END, + CASE WHEN s_q1 THEN tb1.tq2 END, + CASE WHEN s_q1 THEN tb1.tq3 END, + CASE WHEN s_q1 THEN tb1.tq4 END, + CASE WHEN s_q1 THEN + (COALESCE(ta.sp1,0)+COALESCE(ta.ss1,0)+COALESCE(ta.sr1,0)) + + COALESCE((COALESCE(tb1.ac,0)+COALESCE(tb1.as2,0)+COALESCE(tb1.ar,0)+COALESCE(tb1.arv,0)),0) + - COALESCE((COALESCE(tb1.m1,0)+COALESCE(tb1.m2,0)+COALESCE(tb1.m3,0)),0) + - COALESCE((COALESCE(tb1.tq2,0)+COALESCE(tb1.tq3,0)+COALESCE(tb1.tq4,0)),0) + END, + CASE WHEN s_q1 THEN + (COALESCE(ta.sp1,0)+COALESCE(ta.ss1,0)+COALESCE(ta.sr1,0)) + + COALESCE((COALESCE(tb1.ac,0)+COALESCE(tb1.as2,0)+COALESCE(tb1.ar,0)+COALESCE(tb1.arv,0)),0) + - COALESCE((COALESCE(tb1.m1,0)+COALESCE(tb1.m2,0)+COALESCE(tb1.m3,0)),0) + END, + CASE WHEN s_q2 THEN tb2.reco END, + CASE WHEN s_q2 THEN tb2.ritm END, + CASE WHEN s_q2 THEN tb2.rinc END, + CASE WHEN s_q2 THEN tb2.rseq END, + NULL::VARCHAR, + CASE WHEN s_q2 THEN + (COALESCE(ta.sp2,0)+COALESCE(ta.ss2,0)+COALESCE(ta.sr2,0)) + + COALESCE(tb1.tq2, 0) + + COALESCE((COALESCE(tb2.reco,0)+COALESCE(tb2.ritm,0)+COALESCE(tb2.rinc,0)+COALESCE(tb2.rseq,0)), 0) + END, + CASE WHEN s_q2 THEN tb2.ac END, + CASE WHEN s_q2 THEN tb2.as2 END, + CASE WHEN s_q2 THEN tb2.ar END, + CASE WHEN s_q2 THEN tb2.arv END, + NULL::VARCHAR, + CASE WHEN s_q2 THEN + (COALESCE(ta.sp2,0)+COALESCE(ta.ss2,0)+COALESCE(ta.sr2,0)) + + COALESCE(tb1.tq2, 0) + + COALESCE((COALESCE(tb2.reco,0)+COALESCE(tb2.ritm,0)+COALESCE(tb2.rinc,0)+COALESCE(tb2.rseq,0)+COALESCE(tb2.ac,0)+COALESCE(tb2.as2,0)+COALESCE(tb2.ar,0)+COALESCE(tb2.arv,0)), 0) + END, + NULL::DATE, + CASE WHEN s_q2 THEN tb2.pa END, + CASE WHEN s_q2 THEN tb2.pho END, + CASE WHEN s_q2 THEN tb2.prf END, + NULL::VARCHAR, NULL::VARCHAR, + CASE WHEN s_q2 THEN ta.bk2 END, + CASE WHEN s_q2 THEN tb2.m1 END, + CASE WHEN s_q2 THEN tb2.m2 END, + CASE WHEN s_q2 THEN tb2.m3 END, + CASE WHEN s_q2 THEN (COALESCE(tb2.m1,0)+COALESCE(tb2.m2,0)+COALESCE(tb2.m3,0)) END, + CASE WHEN s_q2 THEN + (COALESCE(ta.sp2,0)+COALESCE(ta.ss2,0)+COALESCE(ta.sr2,0)) + + COALESCE(tb1.tq2,0) + + COALESCE((COALESCE(tb2.reco,0)+COALESCE(tb2.ritm,0)+COALESCE(tb2.rinc,0)+COALESCE(tb2.rseq,0)+COALESCE(tb2.ac,0)+COALESCE(tb2.as2,0)+COALESCE(tb2.ar,0)+COALESCE(tb2.arv,0)),0) + - COALESCE(ta.bk2,0) + END, + CASE WHEN s_q2 THEN + (COALESCE(ta.sp2,0)+COALESCE(ta.ss2,0)+COALESCE(ta.sr2,0)) + + COALESCE(tb1.tq2,0) + + COALESCE((COALESCE(tb2.reco,0)+COALESCE(tb2.ritm,0)+COALESCE(tb2.rinc,0)+COALESCE(tb2.rseq,0)+COALESCE(tb2.ac,0)+COALESCE(tb2.as2,0)+COALESCE(tb2.ar,0)+COALESCE(tb2.arv,0)),0) + - COALESCE((COALESCE(tb2.m1,0)+COALESCE(tb2.m2,0)+COALESCE(tb2.m3,0)),0) + END, + CASE WHEN s_q2 THEN tb2.tq3 END, + CASE WHEN s_q2 THEN tb2.tq4 END, + CASE WHEN s_q2 THEN + (COALESCE(ta.sp2,0)+COALESCE(ta.ss2,0)+COALESCE(ta.sr2,0)) + + COALESCE(tb1.tq2,0) + + COALESCE((COALESCE(tb2.reco,0)+COALESCE(tb2.ritm,0)+COALESCE(tb2.rinc,0)+COALESCE(tb2.rseq,0)+COALESCE(tb2.ac,0)+COALESCE(tb2.as2,0)+COALESCE(tb2.ar,0)+COALESCE(tb2.arv,0)),0) + - COALESCE((COALESCE(tb2.m1,0)+COALESCE(tb2.m2,0)+COALESCE(tb2.m3,0)),0) + - COALESCE((COALESCE(tb2.tq3,0)+COALESCE(tb2.tq4,0)),0) + END, + CASE WHEN s_q2 THEN + (COALESCE(ta.sp2,0)+COALESCE(ta.ss2,0)+COALESCE(ta.sr2,0)) + + COALESCE(tb1.tq2,0) + + COALESCE((COALESCE(tb2.reco,0)+COALESCE(tb2.ritm,0)+COALESCE(tb2.rinc,0)+COALESCE(tb2.rseq,0)+COALESCE(tb2.ac,0)+COALESCE(tb2.as2,0)+COALESCE(tb2.ar,0)+COALESCE(tb2.arv,0)),0) + - COALESCE((COALESCE(tb2.m1,0)+COALESCE(tb2.m2,0)+COALESCE(tb2.m3,0)),0) + END, + CASE WHEN s_q3 THEN tb3.reco END, + CASE WHEN s_q3 THEN tb3.ritm END, + CASE WHEN s_q3 THEN tb3.rinc END, + CASE WHEN s_q3 THEN tb3.rseq END, + NULL::VARCHAR, + CASE WHEN s_q3 THEN + (COALESCE(ta.sp3,0)+COALESCE(ta.ss3,0)+COALESCE(ta.sr3,0)) + + COALESCE(tb1.tq3, 0) + + COALESCE(tb2.tq3, 0) + + COALESCE((COALESCE(tb3.reco,0)+COALESCE(tb3.ritm,0)+COALESCE(tb3.rinc,0)+COALESCE(tb3.rseq,0)), 0) + END, + CASE WHEN s_q3 THEN tb3.ac END, + CASE WHEN s_q3 THEN tb3.as2 END, + CASE WHEN s_q3 THEN tb3.ar END, + CASE WHEN s_q3 THEN tb3.arv END, + NULL::VARCHAR, + CASE WHEN s_q3 THEN + (COALESCE(ta.sp3,0)+COALESCE(ta.ss3,0)+COALESCE(ta.sr3,0)) + + COALESCE(tb1.tq3, 0) + + COALESCE(tb2.tq3, 0) + + COALESCE((COALESCE(tb3.reco,0)+COALESCE(tb3.ritm,0)+COALESCE(tb3.rinc,0)+COALESCE(tb3.rseq,0)+COALESCE(tb3.ac,0)+COALESCE(tb3.as2,0)+COALESCE(tb3.ar,0)+COALESCE(tb3.arv,0)), 0) + END, + NULL::DATE, + CASE WHEN s_q3 THEN tb3.pa END, + CASE WHEN s_q3 THEN tb3.pho END, + CASE WHEN s_q3 THEN tb3.prf END, + NULL::VARCHAR, NULL::VARCHAR, + CASE WHEN s_q3 THEN ta.bk3 END, + CASE WHEN s_q3 THEN tb3.m1 END, + CASE WHEN s_q3 THEN tb3.m2 END, + CASE WHEN s_q3 THEN tb3.m3 END, + CASE WHEN s_q3 THEN (COALESCE(tb3.m1,0)+COALESCE(tb3.m2,0)+COALESCE(tb3.m3,0)) END, + CASE WHEN s_q3 THEN + (COALESCE(ta.sp3,0)+COALESCE(ta.ss3,0)+COALESCE(ta.sr3,0)) + + COALESCE(tb1.tq3,0) + + COALESCE(tb2.tq3,0) + + COALESCE((COALESCE(tb3.reco,0)+COALESCE(tb3.ritm,0)+COALESCE(tb3.rinc,0)+COALESCE(tb3.rseq,0)+COALESCE(tb3.ac,0)+COALESCE(tb3.as2,0)+COALESCE(tb3.ar,0)+COALESCE(tb3.arv,0)),0) + - COALESCE(ta.bk3,0) + END, + CASE WHEN s_q3 THEN + (COALESCE(ta.sp3,0)+COALESCE(ta.ss3,0)+COALESCE(ta.sr3,0)) + + COALESCE(tb1.tq3,0) + + COALESCE(tb2.tq3,0) + + COALESCE((COALESCE(tb3.reco,0)+COALESCE(tb3.ritm,0)+COALESCE(tb3.rinc,0)+COALESCE(tb3.rseq,0)+COALESCE(tb3.ac,0)+COALESCE(tb3.as2,0)+COALESCE(tb3.ar,0)+COALESCE(tb3.arv,0)),0) + - COALESCE((COALESCE(tb3.m1,0)+COALESCE(tb3.m2,0)+COALESCE(tb3.m3,0)),0) + END, + CASE WHEN s_q3 THEN tb3.tq4 END, + CASE WHEN s_q3 THEN + (COALESCE(ta.sp3,0)+COALESCE(ta.ss3,0)+COALESCE(ta.sr3,0)) + + COALESCE(tb1.tq3,0) + + COALESCE(tb2.tq3,0) + + COALESCE((COALESCE(tb3.reco,0)+COALESCE(tb3.ritm,0)+COALESCE(tb3.rinc,0)+COALESCE(tb3.rseq,0)+COALESCE(tb3.ac,0)+COALESCE(tb3.as2,0)+COALESCE(tb3.ar,0)+COALESCE(tb3.arv,0)),0) + - COALESCE((COALESCE(tb3.m1,0)+COALESCE(tb3.m2,0)+COALESCE(tb3.m3,0)),0) + - COALESCE(COALESCE(tb3.tq4,0),0) + END, + CASE WHEN s_q3 THEN + (COALESCE(ta.sp3,0)+COALESCE(ta.ss3,0)+COALESCE(ta.sr3,0)) + + COALESCE(tb1.tq3,0) + + COALESCE(tb2.tq3,0) + + COALESCE((COALESCE(tb3.reco,0)+COALESCE(tb3.ritm,0)+COALESCE(tb3.rinc,0)+COALESCE(tb3.rseq,0)+COALESCE(tb3.ac,0)+COALESCE(tb3.as2,0)+COALESCE(tb3.ar,0)+COALESCE(tb3.arv,0)),0) + - COALESCE((COALESCE(tb3.m1,0)+COALESCE(tb3.m2,0)+COALESCE(tb3.m3,0)),0) + END, + CASE WHEN s_q4 THEN tb4.reco END, + CASE WHEN s_q4 THEN tb4.ritm END, + CASE WHEN s_q4 THEN tb4.rinc END, + CASE WHEN s_q4 THEN tb4.rseq END, + NULL::VARCHAR, + CASE WHEN s_q4 THEN + (COALESCE(ta.sp4,0)+COALESCE(ta.ss4,0)+COALESCE(ta.sr4,0)) + + COALESCE(tb1.tq4, 0) + + COALESCE(tb2.tq4, 0) + + COALESCE(tb3.tq4, 0) + + COALESCE((COALESCE(tb4.reco,0)+COALESCE(tb4.ritm,0)+COALESCE(tb4.rinc,0)+COALESCE(tb4.rseq,0)), 0) + END, + CASE WHEN s_q4 THEN tb4.ac END, + CASE WHEN s_q4 THEN tb4.as2 END, + CASE WHEN s_q4 THEN tb4.ar END, + CASE WHEN s_q4 THEN tb4.arv END, + NULL::VARCHAR, + CASE WHEN s_q4 THEN + (COALESCE(ta.sp4,0)+COALESCE(ta.ss4,0)+COALESCE(ta.sr4,0)) + + COALESCE(tb1.tq4, 0) + + COALESCE(tb2.tq4, 0) + + COALESCE(tb3.tq4, 0) + + COALESCE((COALESCE(tb4.reco,0)+COALESCE(tb4.ritm,0)+COALESCE(tb4.rinc,0)+COALESCE(tb4.rseq,0)+COALESCE(tb4.ac,0)+COALESCE(tb4.as2,0)+COALESCE(tb4.ar,0)+COALESCE(tb4.arv,0)), 0) + END, + NULL::DATE, + CASE WHEN s_q4 THEN tb4.pa END, + CASE WHEN s_q4 THEN tb4.pho END, + CASE WHEN s_q4 THEN tb4.prf END, + NULL::VARCHAR, NULL::VARCHAR, + CASE WHEN s_q4 THEN ta.bk4 END, + CASE WHEN s_q4 THEN tb4.m1 END, + CASE WHEN s_q4 THEN tb4.m2 END, + CASE WHEN s_q4 THEN tb4.m3 END, + CASE WHEN s_q4 THEN (COALESCE(tb4.m1,0)+COALESCE(tb4.m2,0)+COALESCE(tb4.m3,0)) END, + CASE WHEN s_q4 THEN tb4.spod END, + CASE WHEN s_q4 THEN + (COALESCE(ta.sp4,0)+COALESCE(ta.ss4,0)+COALESCE(ta.sr4,0)) + + COALESCE(tb1.tq4,0) + + COALESCE(tb2.tq4,0) + + COALESCE(tb3.tq4,0) + + COALESCE((COALESCE(tb4.reco,0)+COALESCE(tb4.ritm,0)+COALESCE(tb4.rinc,0)+COALESCE(tb4.rseq,0)+COALESCE(tb4.ac,0)+COALESCE(tb4.as2,0)+COALESCE(tb4.ar,0)+COALESCE(tb4.arv,0)),0) + - COALESCE(ta.bk4,0) + END, + CASE WHEN s_q4 THEN + (COALESCE(ta.sp4,0)+COALESCE(ta.ss4,0)+COALESCE(ta.sr4,0)) + + COALESCE(tb1.tq4,0) + + COALESCE(tb2.tq4,0) + + COALESCE(tb3.tq4,0) + + COALESCE((COALESCE(tb4.reco,0)+COALESCE(tb4.ritm,0)+COALESCE(tb4.rinc,0)+COALESCE(tb4.rseq,0)+COALESCE(tb4.ac,0)+COALESCE(tb4.as2,0)+COALESCE(tb4.ar,0)+COALESCE(tb4.arv,0)),0) + - COALESCE((COALESCE(tb4.m1,0)+COALESCE(tb4.m2,0)+COALESCE(tb4.m3,0)+COALESCE(tb4.spod,0)),0) + END, + CASE WHEN s_q4 THEN + (COALESCE(ta.sp4,0)+COALESCE(ta.ss4,0)+COALESCE(ta.sr4,0)) + + COALESCE(tb1.tq4,0) + + COALESCE(tb2.tq4,0) + + COALESCE(tb3.tq4,0) + + COALESCE((COALESCE(tb4.reco,0)+COALESCE(tb4.ritm,0)+COALESCE(tb4.rinc,0)+COALESCE(tb4.rseq,0)+COALESCE(tb4.ac,0)+COALESCE(tb4.as2,0)+COALESCE(tb4.ar,0)+COALESCE(tb4.arv,0)),0) + - COALESCE((COALESCE(tb4.m1,0)+COALESCE(tb4.m2,0)+COALESCE(tb4.m3,0)+COALESCE(tb4.spod,0)),0) + END, + CASE WHEN s_q4 THEN + (COALESCE(ta.sp4,0)+COALESCE(ta.ss4,0)+COALESCE(ta.sr4,0)) + + COALESCE(tb1.tq4,0) + + COALESCE(tb2.tq4,0) + + COALESCE(tb3.tq4,0) + + COALESCE((COALESCE(tb4.reco,0)+COALESCE(tb4.ritm,0)+COALESCE(tb4.rinc,0)+COALESCE(tb4.rseq,0)+COALESCE(tb4.ac,0)+COALESCE(tb4.as2,0)+COALESCE(tb4.ar,0)+COALESCE(tb4.arv,0)),0) + - COALESCE((COALESCE(tb4.m1,0)+COALESCE(tb4.m2,0)+COALESCE(tb4.m3,0)+COALESCE(tb4.spod,0)),0) + END, + CASE WHEN s_tot THEN (COALESCE(tt.fq1,0)+COALESCE(tt.fq2,0)+COALESCE(tt.fq3,0)+COALESCE(tt.fq4,0)) END, + CASE WHEN s_tot THEN tt.pay END, + t.path AS _sort + + FROM tw t + LEFT JOIN tw_agg ta ON ta.id = t.id + LEFT JOIN tw_aq1 tb1 ON tb1.id = t.id + LEFT JOIN tw_aq2 tb2 ON tb2.id = t.id + LEFT JOIN tw_aq3 tb3 ON tb3.id = t.id + LEFT JOIN tw_aq4 tb4 ON tb4.id = t.id + LEFT JOIN tw_atot tt ON tt.id = t.id + ) sub + ORDER BY sub._sort; + +END; +$function$ +; + +CREATE OR REPLACE FUNCTION v3.v_form3_report_sections(p_report_id integer, p_sections text[] DEFAULT NULL::text[]) + RETURNS TABLE(row_type character varying, depth integer, line_id integer, col_section_code character varying, col_item_id character varying, col_num_group_id character varying, col_name character varying, col_q1_adj_by_items numeric, col_q1_adj_increase numeric, col_q1_total_corr numeric, col_q1_m1 numeric, col_q1_m2 numeric, col_q1_m3 numeric, col_q1_quarter_actual numeric, col_q1_economy numeric, col_q2_carryover numeric, col_q2_adj_by_items numeric, col_q2_adj_increase numeric, col_q2_total_corr numeric, col_q2_m1 numeric, col_q2_m2 numeric, col_q2_m3 numeric, col_q2_quarter_actual numeric, col_q2_economy numeric, col_q3_carryover numeric, col_q3_adj_by_items numeric, col_q3_adj_increase numeric, col_q3_total_corr numeric, col_q3_m1 numeric, col_q3_m2 numeric, col_q3_m3 numeric, col_q3_quarter_actual numeric, col_q3_economy numeric, col_q4_carryover numeric, col_q4_adj_by_items numeric, col_q4_adj_increase numeric, col_q4_total_corr numeric, col_q4_m1 numeric, col_q4_m2 numeric, col_q4_m3 numeric, col_q4_spod numeric, col_q4_quarter_actual numeric, col_q4_economy numeric, col_year_total_corr numeric, col_year_total_actual numeric, col_year_economy numeric, col_q1_base_plan numeric, col_q2_base_plan numeric, col_q3_base_plan numeric, col_q4_base_plan numeric, col_year_base_plan numeric, col_q2_corrected_plan numeric, col_q3_corrected_plan numeric, col_q4_corrected_plan numeric, _sort_path integer[]) + LANGUAGE plpgsql + STABLE +AS $function$ +DECLARE + s_q1 BOOLEAN := p_sections IS NULL OR 'q1' = ANY(p_sections); + s_q2 BOOLEAN := p_sections IS NULL OR 'q2' = ANY(p_sections); + s_q3 BOOLEAN := p_sections IS NULL OR 'q3' = ANY(p_sections); + s_q4 BOOLEAN := p_sections IS NULL OR 'q4' = ANY(p_sections); + s_year BOOLEAN := p_sections IS NULL OR 'year' = ANY(p_sections); +BEGIN + IF NOT EXISTS (SELECT 1 FROM v3.rf_project_report WHERE id = p_report_id) THEN + RAISE EXCEPTION 'rf_project_report id=% не существует', p_report_id; + END IF; + + RETURN QUERY + WITH + -- Дерево expense_item, ограниченное FORM_3 (через junction) + tw AS ( + SELECT t.*, p.parent_item_id AS grandparent_item_id + FROM v3.mv_expense_item_tree t + LEFT JOIN v3.mv_expense_item_tree p ON p.id = t.parent_id + JOIN v3.expense_item_form_type eft + ON eft.expense_item_id = t.id AND eft.form_type_code = 'FORM_3' + ), + -- INPUT строки: одна на v3.rf_project_report_line + page AS ( + SELECT l.id AS lid, l.expense_item_id AS eid, + CASE + WHEN t.depth < 3 THEN t.item_id + WHEN t.depth = 3 THEN t.parent_item_id + WHEN t.depth = 4 THEN t.grandparent_item_id + END AS sc, + ei.item_id AS ic, + ei.num_group_id AS ng, ei.name AS ename, + t.path AS tree_path + FROM v3.rf_project_report_line l + JOIN v3.expense_item ei ON ei.id = l.expense_item_id + JOIN tw t ON t.id = l.expense_item_id + WHERE l.rf_project_report_id = p_report_id + ), + -- Поквартальные данные + jq AS ( + SELECT q.rf_project_report_line_id AS lid, q.quarter, + q.adj_by_items, q.adj_increase, + q.actual_m1, q.actual_m2, q.actual_m3, q.actual_spod, + q.base_plan, q.corrected_plan, q.carryover + FROM v3.rf_project_report_quarter q + JOIN v3.rf_project_report_line l ON l.id = q.rf_project_report_line_id + WHERE l.rf_project_report_id = p_report_id + ), + -- INPUT base: соединяем page + 4 квартала + input_base AS ( + SELECT + pg.lid, pg.eid, pg.sc, pg.ic, pg.ng, pg.ename, pg.tree_path, + q1.adj_by_items AS q1_abi, q1.adj_increase AS q1_ai, + q1.actual_m1 AS q1_m1, q1.actual_m2 AS q1_m2, q1.actual_m3 AS q1_m3, + q2.carryover as q2_co, + q2.adj_by_items AS q2_abi, q2.adj_increase AS q2_ai, + q2.actual_m1 AS q2_m1, q2.actual_m2 AS q2_m2, q2.actual_m3 AS q2_m3, + q3.carryover as q3_co, + q3.adj_by_items AS q3_abi, q3.adj_increase AS q3_ai, + q3.actual_m1 AS q3_m1, q3.actual_m2 AS q3_m2, q3.actual_m3 AS q3_m3, + q4.carryover as q4_co, + q4.adj_by_items AS q4_abi, q4.adj_increase AS q4_ai, + q4.actual_m1 AS q4_m1, q4.actual_m2 AS q4_m2, q4.actual_m3 AS q4_m3, + q4.actual_spod AS q4_spod, + q1.base_plan AS q1_bp, q2.base_plan AS q2_bp, + q3.base_plan AS q3_bp, q4.base_plan AS q4_bp, + q2.corrected_plan AS q2_cp, q3.corrected_plan AS q3_cp, q4.corrected_plan AS q4_cp + FROM page pg + LEFT JOIN jq q1 ON q1.lid = pg.lid AND q1.quarter = 1 + LEFT JOIN jq q2 ON q2.lid = pg.lid AND q2.quarter = 2 + LEFT JOIN jq q3 ON q3.lid = pg.lid AND q3.quarter = 3 + LEFT JOIN jq q4 ON q4.lid = pg.lid AND q4.quarter = 4 + ), + -- Computed totals per row + enriched AS ( + SELECT b.*, + COALESCE(b.q1_abi,0) + COALESCE(b.q1_ai,0) AS q1_tc, + COALESCE(b.q1_m1,0) + COALESCE(b.q1_m2,0) + COALESCE(b.q1_m3,0) AS q1_qa, + COALESCE(b.q2_abi,0) + COALESCE(b.q2_ai,0) AS q2_tc, + COALESCE(b.q2_m1,0) + COALESCE(b.q2_m2,0) + COALESCE(b.q2_m3,0) AS q2_qa, + COALESCE(b.q3_abi,0) + COALESCE(b.q3_ai,0) AS q3_tc, + COALESCE(b.q3_m1,0) + COALESCE(b.q3_m2,0) + COALESCE(b.q3_m3,0) AS q3_qa, + COALESCE(b.q4_abi,0) + COALESCE(b.q4_ai,0) AS q4_tc, + COALESCE(b.q4_m1,0) + COALESCE(b.q4_m2,0) + COALESCE(b.q4_m3,0) + COALESCE(b.q4_spod,0) AS q4_qa + FROM input_base b + ), + -- Per-line aggregates for tree rollup + agg_q AS ( + SELECT l.expense_item_id AS eid, q.quarter, + SUM(q.adj_by_items) AS abi, SUM(q.adj_increase) AS ai, + SUM(q.actual_m1) AS m1, SUM(q.actual_m2) AS m2, SUM(q.actual_m3) AS m3, + SUM(q.actual_spod) AS spod, + SUM(q.base_plan) AS bp, SUM(q.corrected_plan) AS cp, SUM(q.carryover) as co + FROM v3.rf_project_report_line l + JOIN v3.rf_project_report_quarter q ON q.rf_project_report_line_id = l.id + WHERE l.rf_project_report_id = p_report_id + GROUP BY l.expense_item_id, q.quarter + ), + tw_aq1 AS ( + SELECT tw.id, SUM(a.abi) AS abi, SUM(a.ai) AS ai, + SUM(a.m1) AS m1, SUM(a.m2) AS m2, SUM(a.m3) AS m3, + SUM(a.bp) AS bp + FROM tw LEFT JOIN agg_q a ON a.eid = ANY(tw.desc_ids) AND a.quarter = 1 + GROUP BY tw.id + ), + tw_aq2 AS ( + SELECT tw.id, SUM(a.abi) AS abi, SUM(a.ai) AS ai, + SUM(a.m1) AS m1, SUM(a.m2) AS m2, SUM(a.m3) AS m3, + SUM(a.bp) AS bp, SUM(a.cp) AS cp, SUM(a.co) AS co + FROM tw LEFT JOIN agg_q a ON a.eid = ANY(tw.desc_ids) AND a.quarter = 2 + GROUP BY tw.id + ), + tw_aq3 AS ( + SELECT tw.id, SUM(a.abi) AS abi, SUM(a.ai) AS ai, + SUM(a.m1) AS m1, SUM(a.m2) AS m2, SUM(a.m3) AS m3, + SUM(a.bp) AS bp, SUM(a.cp) AS cp, SUM(a.co) AS co + FROM tw LEFT JOIN agg_q a ON a.eid = ANY(tw.desc_ids) AND a.quarter = 3 + GROUP BY tw.id + ), + tw_aq4 AS ( + SELECT tw.id, SUM(a.abi) AS abi, SUM(a.ai) AS ai, + SUM(a.m1) AS m1, SUM(a.m2) AS m2, SUM(a.m3) AS m3, + SUM(a.spod) AS spod, + SUM(a.bp) AS bp, SUM(a.cp) AS cp, SUM(a.co) AS co + FROM tw LEFT JOIN agg_q a ON a.eid = ANY(tw.desc_ids) AND a.quarter = 4 + GROUP BY tw.id + ) + + -- ═══ Часть A: INPUT строки ════════════════════════════════════════════════ + SELECT * FROM ( + SELECT + 'INPUT'::VARCHAR AS row_type, array_length(e.tree_path, 1)::INT AS depth, e.lid::INT AS line_id, + e.sc, e.ic, e.ng, e.ename, + -- Q1 + CASE WHEN s_q1 THEN e.q1_abi END, + CASE WHEN s_q1 THEN e.q1_ai END, + CASE WHEN s_q1 THEN e.q1_tc END, + CASE WHEN s_q1 THEN e.q1_m1 END, + CASE WHEN s_q1 THEN e.q1_m2 END, + CASE WHEN s_q1 THEN e.q1_m3 END, + CASE WHEN s_q1 THEN e.q1_qa END, + CASE WHEN s_q1 THEN ROUND(e.q1_tc - e.q1_qa, 1) END, + -- Q2 (carryover пока NULL — нет столбца в _quarter; задел на будущее) + CASE WHEN s_q2 THEN e.q2_co END, + CASE WHEN s_q2 THEN e.q2_abi END, + CASE WHEN s_q2 THEN e.q2_ai END, + CASE WHEN s_q2 THEN e.q2_tc END, + CASE WHEN s_q2 THEN e.q2_m1 END, + CASE WHEN s_q2 THEN e.q2_m2 END, + CASE WHEN s_q2 THEN e.q2_m3 END, + CASE WHEN s_q2 THEN e.q2_qa END, + CASE WHEN s_q2 THEN ROUND(e.q2_tc - e.q2_qa, 1) END, + -- Q3 + CASE WHEN s_q3 THEN e.q3_co END, + CASE WHEN s_q3 THEN e.q3_abi END, + CASE WHEN s_q3 THEN e.q3_ai END, + CASE WHEN s_q3 THEN e.q3_tc END, + CASE WHEN s_q3 THEN e.q3_m1 END, + CASE WHEN s_q3 THEN e.q3_m2 END, + CASE WHEN s_q3 THEN e.q3_m3 END, + CASE WHEN s_q3 THEN e.q3_qa END, + CASE WHEN s_q3 THEN ROUND(e.q3_tc - e.q3_qa, 1) END, + -- Q4 + CASE WHEN s_q4 THEN e.q4_co END, + CASE WHEN s_q4 THEN e.q4_abi END, + CASE WHEN s_q4 THEN e.q4_ai END, + CASE WHEN s_q4 THEN e.q4_tc END, + CASE WHEN s_q4 THEN e.q4_m1 END, + CASE WHEN s_q4 THEN e.q4_m2 END, + CASE WHEN s_q4 THEN e.q4_m3 END, + CASE WHEN s_q4 THEN e.q4_spod END, + CASE WHEN s_q4 THEN e.q4_qa END, + CASE WHEN s_q4 THEN ROUND(e.q4_tc - e.q4_qa, 1) END, + -- year + CASE WHEN s_year THEN e.q1_tc + e.q2_tc + e.q3_tc + e.q4_tc END, + CASE WHEN s_year THEN e.q1_qa + e.q2_qa + e.q3_qa + e.q4_qa END, + CASE WHEN s_year THEN ROUND((e.q1_tc + e.q2_tc + e.q3_tc + e.q4_tc) - + (e.q1_qa + e.q2_qa + e.q3_qa + e.q4_qa), 1) END, + -- план-блоки + CASE WHEN s_q1 THEN e.q1_bp END, + CASE WHEN s_q2 THEN e.q2_bp END, + CASE WHEN s_q3 THEN e.q3_bp END, + CASE WHEN s_q4 THEN e.q4_bp END, + CASE WHEN s_year THEN COALESCE(e.q1_bp,0)+COALESCE(e.q2_bp,0)+ + COALESCE(e.q3_bp,0)+COALESCE(e.q4_bp,0) END, + CASE WHEN s_q2 THEN e.q2_cp END, + CASE WHEN s_q3 THEN e.q3_cp END, + CASE WHEN s_q4 THEN e.q4_cp END, + e.tree_path || ARRAY[e.lid::INT] AS _sort_path + FROM enriched e + + UNION ALL + + -- ═══ Часть B: Иерархия (ROOT / GROUP / ITEM / SUB_ITEM) ═════════════════ + SELECT + CASE t.depth WHEN 0 THEN 'ROOT' WHEN 1 THEN 'GROUP' + WHEN 2 THEN 'ITEM' WHEN 3 THEN 'SUB_ITEM' WHEN 4 THEN 'SUB_SUB_ITEM' END::VARCHAR, + t.depth, NULL::INT, + CASE + WHEN t.depth < 3 THEN t.item_id + WHEN t.depth = 3 THEN t.parent_item_id + WHEN t.depth = 4 THEN t.grandparent_item_id + END, + CASE WHEN t.depth >= 3 THEN t.item_id ELSE NULL END, + t.num_group_id, t.name, + -- Q1 + CASE WHEN s_q1 THEN a1.abi END, + CASE WHEN s_q1 THEN a1.ai END, + CASE WHEN s_q1 THEN COALESCE(a1.abi,0)+COALESCE(a1.ai,0) END, + CASE WHEN s_q1 THEN a1.m1 END, + CASE WHEN s_q1 THEN a1.m2 END, + CASE WHEN s_q1 THEN a1.m3 END, + CASE WHEN s_q1 THEN COALESCE(a1.m1,0)+COALESCE(a1.m2,0)+COALESCE(a1.m3,0) END, + CASE WHEN s_q1 THEN ROUND((COALESCE(a1.abi,0)+COALESCE(a1.ai,0)) - + (COALESCE(a1.m1,0)+COALESCE(a1.m2,0)+COALESCE(a1.m3,0)), 1) END, + -- Q2 + CASE WHEN s_q2 THEN a2.co END, + CASE WHEN s_q2 THEN a2.abi END, + CASE WHEN s_q2 THEN a2.ai END, + CASE WHEN s_q2 THEN COALESCE(a2.abi,0)+COALESCE(a2.ai,0) END, + CASE WHEN s_q2 THEN a2.m1 END, + CASE WHEN s_q2 THEN a2.m2 END, + CASE WHEN s_q2 THEN a2.m3 END, + CASE WHEN s_q2 THEN COALESCE(a2.m1,0)+COALESCE(a2.m2,0)+COALESCE(a2.m3,0) END, + CASE WHEN s_q2 THEN ROUND((COALESCE(a2.abi,0)+COALESCE(a2.ai,0)) - + (COALESCE(a2.m1,0)+COALESCE(a2.m2,0)+COALESCE(a2.m3,0)), 1) END, + -- Q3 + CASE WHEN s_q3 THEN a3.co END, + CASE WHEN s_q3 THEN a3.abi END, + CASE WHEN s_q3 THEN a3.ai END, + CASE WHEN s_q3 THEN COALESCE(a3.abi,0)+COALESCE(a3.ai,0) END, + CASE WHEN s_q3 THEN a3.m1 END, + CASE WHEN s_q3 THEN a3.m2 END, + CASE WHEN s_q3 THEN a3.m3 END, + CASE WHEN s_q3 THEN COALESCE(a3.m1,0)+COALESCE(a3.m2,0)+COALESCE(a3.m3,0) END, + CASE WHEN s_q3 THEN ROUND((COALESCE(a3.abi,0)+COALESCE(a3.ai,0)) - + (COALESCE(a3.m1,0)+COALESCE(a3.m2,0)+COALESCE(a3.m3,0)), 1) END, + -- Q4 + CASE WHEN s_q4 THEN a4.co END, + CASE WHEN s_q4 THEN a4.abi END, + CASE WHEN s_q4 THEN a4.ai END, + CASE WHEN s_q4 THEN COALESCE(a4.abi,0)+COALESCE(a4.ai,0) END, + CASE WHEN s_q4 THEN a4.m1 END, + CASE WHEN s_q4 THEN a4.m2 END, + CASE WHEN s_q4 THEN a4.m3 END, + CASE WHEN s_q4 THEN a4.spod END, + CASE WHEN s_q4 THEN COALESCE(a4.m1,0)+COALESCE(a4.m2,0)+COALESCE(a4.m3,0)+COALESCE(a4.spod,0) END, + CASE WHEN s_q4 THEN ROUND((COALESCE(a4.abi,0)+COALESCE(a4.ai,0)) - + (COALESCE(a4.m1,0)+COALESCE(a4.m2,0)+COALESCE(a4.m3,0)+COALESCE(a4.spod,0)), 1) END, + -- year + CASE WHEN s_year THEN COALESCE(a1.abi,0)+COALESCE(a1.ai,0)+ + COALESCE(a2.abi,0)+COALESCE(a2.ai,0)+ + COALESCE(a3.abi,0)+COALESCE(a3.ai,0)+ + COALESCE(a4.abi,0)+COALESCE(a4.ai,0) END, + CASE WHEN s_year THEN COALESCE(a1.m1,0)+COALESCE(a1.m2,0)+COALESCE(a1.m3,0)+ + COALESCE(a2.m1,0)+COALESCE(a2.m2,0)+COALESCE(a2.m3,0)+ + COALESCE(a3.m1,0)+COALESCE(a3.m2,0)+COALESCE(a3.m3,0)+ + COALESCE(a4.m1,0)+COALESCE(a4.m2,0)+COALESCE(a4.m3,0)+COALESCE(a4.spod,0) END, + CASE WHEN s_year THEN + ROUND( + (COALESCE(a1.abi,0)+COALESCE(a1.ai,0)+COALESCE(a2.abi,0)+COALESCE(a2.ai,0)+ + COALESCE(a3.abi,0)+COALESCE(a3.ai,0)+COALESCE(a4.abi,0)+COALESCE(a4.ai,0)) + - + (COALESCE(a1.m1,0)+COALESCE(a1.m2,0)+COALESCE(a1.m3,0)+ + COALESCE(a2.m1,0)+COALESCE(a2.m2,0)+COALESCE(a2.m3,0)+ + COALESCE(a3.m1,0)+COALESCE(a3.m2,0)+COALESCE(a3.m3,0)+ + COALESCE(a4.m1,0)+COALESCE(a4.m2,0)+COALESCE(a4.m3,0)+COALESCE(a4.spod,0)), + 1) + END, + -- план-блоки (rollup) + CASE WHEN s_q1 THEN a1.bp END, + CASE WHEN s_q2 THEN a2.bp END, + CASE WHEN s_q3 THEN a3.bp END, + CASE WHEN s_q4 THEN a4.bp END, + CASE WHEN s_year THEN COALESCE(a1.bp,0)+COALESCE(a2.bp,0)+ + COALESCE(a3.bp,0)+COALESCE(a4.bp,0) END, + CASE WHEN s_q2 THEN a2.cp END, + CASE WHEN s_q3 THEN a3.cp END, + CASE WHEN s_q4 THEN a4.cp END, + t.path + FROM tw t + LEFT JOIN tw_aq1 a1 ON a1.id = t.id + LEFT JOIN tw_aq2 a2 ON a2.id = t.id + LEFT JOIN tw_aq3 a3 ON a3.id = t.id + LEFT JOIN tw_aq4 a4 ON a4.id = t.id + ) sub + ORDER BY sub._sort_path; + +END; +$function$ +; + + +CREATE OR REPLACE FUNCTION v3.v_form3_rf_rollup_sections(p_branch_id integer, p_year integer, p_sections text[] DEFAULT NULL::text[]) + RETURNS TABLE(row_type character varying, depth integer, col_section_code character varying, col_item_id character varying, col_num_group_id character varying, col_name character varying, col_q1_adj_by_items numeric, col_q1_adj_increase numeric, col_q1_total_corr numeric, col_q1_m1 numeric, col_q1_m2 numeric, col_q1_m3 numeric, col_q1_quarter_actual numeric, col_q1_economy numeric, col_q2_adj_by_items numeric, col_q2_adj_increase numeric, col_q2_total_corr numeric, col_q2_m1 numeric, col_q2_m2 numeric, col_q2_m3 numeric, col_q2_quarter_actual numeric, col_q2_economy numeric, col_q3_adj_by_items numeric, col_q3_adj_increase numeric, col_q3_total_corr numeric, col_q3_m1 numeric, col_q3_m2 numeric, col_q3_m3 numeric, col_q3_quarter_actual numeric, col_q3_economy numeric, col_q4_adj_by_items numeric, col_q4_adj_increase numeric, col_q4_total_corr numeric, col_q4_m1 numeric, col_q4_m2 numeric, col_q4_m3 numeric, col_q4_spod numeric, col_q4_quarter_actual numeric, col_q4_economy numeric, col_year_total_corr numeric, col_year_total_actual numeric, col_year_economy numeric, _sort_path integer[]) + LANGUAGE plpgsql + STABLE +AS $function$ +DECLARE + s_q1 BOOLEAN := p_sections IS NULL OR 'q1' = ANY(p_sections); + s_q2 BOOLEAN := p_sections IS NULL OR 'q2' = ANY(p_sections); + s_q3 BOOLEAN := p_sections IS NULL OR 'q3' = ANY(p_sections); + s_q4 BOOLEAN := p_sections IS NULL OR 'q4' = ANY(p_sections); + s_year BOOLEAN := p_sections IS NULL OR 'year' = ANY(p_sections); +BEGIN + RETURN QUERY + WITH + tw AS ( + SELECT t.*, p.parent_item_id AS grandparent_item_id + FROM v3.mv_expense_item_tree t + LEFT JOIN v3.mv_expense_item_tree p ON p.id = t.parent_id + JOIN v3.expense_item_form_type eft + ON eft.expense_item_id = t.id AND eft.form_type_code = 'FORM_3' + ), + -- Агрегаты per (expense_item_id, quarter) — sum по обоим трекам всех проектов РФ × год + agg_q AS ( + SELECT l.expense_item_id AS eid, q.quarter, + SUM(q.adj_by_items) AS abi, SUM(q.adj_increase) AS ai, + SUM(q.actual_m1) AS m1, SUM(q.actual_m2) AS m2, SUM(q.actual_m3) AS m3, + SUM(q.actual_spod) AS spod + FROM v3.rf_project_report r + JOIN v3.project p ON p.id = r.project_id + JOIN v3.rf_project_report_line l ON l.rf_project_report_id = r.id + JOIN v3.rf_project_report_quarter q ON q.rf_project_report_line_id = l.id + WHERE p.org_unit_id = p_branch_id AND r.year = p_year + GROUP BY l.expense_item_id, q.quarter + ), + tw_aq1 AS (SELECT tw.id, SUM(a.abi) AS abi, SUM(a.ai) AS ai, + SUM(a.m1) AS m1, SUM(a.m2) AS m2, SUM(a.m3) AS m3 + FROM tw LEFT JOIN agg_q a ON a.eid = ANY(tw.desc_ids) AND a.quarter=1 + GROUP BY tw.id), + tw_aq2 AS (SELECT tw.id, SUM(a.abi) AS abi, SUM(a.ai) AS ai, + SUM(a.m1) AS m1, SUM(a.m2) AS m2, SUM(a.m3) AS m3 + FROM tw LEFT JOIN agg_q a ON a.eid = ANY(tw.desc_ids) AND a.quarter=2 + GROUP BY tw.id), + tw_aq3 AS (SELECT tw.id, SUM(a.abi) AS abi, SUM(a.ai) AS ai, + SUM(a.m1) AS m1, SUM(a.m2) AS m2, SUM(a.m3) AS m3 + FROM tw LEFT JOIN agg_q a ON a.eid = ANY(tw.desc_ids) AND a.quarter=3 + GROUP BY tw.id), + tw_aq4 AS (SELECT tw.id, SUM(a.abi) AS abi, SUM(a.ai) AS ai, + SUM(a.m1) AS m1, SUM(a.m2) AS m2, SUM(a.m3) AS m3, + SUM(a.spod) AS spod + FROM tw LEFT JOIN agg_q a ON a.eid = ANY(tw.desc_ids) AND a.quarter=4 + GROUP BY tw.id) + + SELECT + CASE t.depth WHEN 0 THEN 'ROOT' WHEN 1 THEN 'GROUP' + WHEN 2 THEN 'ITEM' WHEN 3 THEN 'SUB_ITEM' WHEN 4 THEN 'SUB_SUB_ITEM' END::VARCHAR, + t.depth, + CASE + WHEN t.depth < 3 THEN t.item_id + WHEN t.depth = 3 THEN t.parent_item_id + WHEN t.depth = 4 THEN t.grandparent_item_id + END, + CASE WHEN t.depth >= 3 THEN t.item_id ELSE NULL END, + t.num_group_id, t.name, + -- Q1 + CASE WHEN s_q1 THEN a1.abi END, + CASE WHEN s_q1 THEN a1.ai END, + CASE WHEN s_q1 THEN COALESCE(a1.abi,0)+COALESCE(a1.ai,0) END, + CASE WHEN s_q1 THEN a1.m1 END, + CASE WHEN s_q1 THEN a1.m2 END, + CASE WHEN s_q1 THEN a1.m3 END, + CASE WHEN s_q1 THEN COALESCE(a1.m1,0)+COALESCE(a1.m2,0)+COALESCE(a1.m3,0) END, + CASE WHEN s_q1 THEN ROUND((COALESCE(a1.abi,0)+COALESCE(a1.ai,0)) + -(COALESCE(a1.m1,0)+COALESCE(a1.m2,0)+COALESCE(a1.m3,0)), 1) END, + -- Q2 + CASE WHEN s_q2 THEN a2.abi END, + CASE WHEN s_q2 THEN a2.ai END, + CASE WHEN s_q2 THEN COALESCE(a2.abi,0)+COALESCE(a2.ai,0) END, + CASE WHEN s_q2 THEN a2.m1 END, + CASE WHEN s_q2 THEN a2.m2 END, + CASE WHEN s_q2 THEN a2.m3 END, + CASE WHEN s_q2 THEN COALESCE(a2.m1,0)+COALESCE(a2.m2,0)+COALESCE(a2.m3,0) END, + CASE WHEN s_q2 THEN ROUND((COALESCE(a2.abi,0)+COALESCE(a2.ai,0)) + -(COALESCE(a2.m1,0)+COALESCE(a2.m2,0)+COALESCE(a2.m3,0)), 1) END, + -- Q3 + CASE WHEN s_q3 THEN a3.abi END, + CASE WHEN s_q3 THEN a3.ai END, + CASE WHEN s_q3 THEN COALESCE(a3.abi,0)+COALESCE(a3.ai,0) END, + CASE WHEN s_q3 THEN a3.m1 END, + CASE WHEN s_q3 THEN a3.m2 END, + CASE WHEN s_q3 THEN a3.m3 END, + CASE WHEN s_q3 THEN COALESCE(a3.m1,0)+COALESCE(a3.m2,0)+COALESCE(a3.m3,0) END, + CASE WHEN s_q3 THEN ROUND((COALESCE(a3.abi,0)+COALESCE(a3.ai,0)) + -(COALESCE(a3.m1,0)+COALESCE(a3.m2,0)+COALESCE(a3.m3,0)), 1) END, + -- Q4 + CASE WHEN s_q4 THEN a4.abi END, + CASE WHEN s_q4 THEN a4.ai END, + CASE WHEN s_q4 THEN COALESCE(a4.abi,0)+COALESCE(a4.ai,0) END, + CASE WHEN s_q4 THEN a4.m1 END, + CASE WHEN s_q4 THEN a4.m2 END, + CASE WHEN s_q4 THEN a4.m3 END, + CASE WHEN s_q4 THEN a4.spod END, + CASE WHEN s_q4 THEN COALESCE(a4.m1,0)+COALESCE(a4.m2,0)+COALESCE(a4.m3,0)+COALESCE(a4.spod,0) END, + CASE WHEN s_q4 THEN ROUND((COALESCE(a4.abi,0)+COALESCE(a4.ai,0)) + -(COALESCE(a4.m1,0)+COALESCE(a4.m2,0)+COALESCE(a4.m3,0)+COALESCE(a4.spod,0)), 1) END, + -- year + CASE WHEN s_year THEN COALESCE(a1.abi,0)+COALESCE(a1.ai,0)+COALESCE(a2.abi,0)+COALESCE(a2.ai,0)+ + COALESCE(a3.abi,0)+COALESCE(a3.ai,0)+COALESCE(a4.abi,0)+COALESCE(a4.ai,0) END, + CASE WHEN s_year THEN COALESCE(a1.m1,0)+COALESCE(a1.m2,0)+COALESCE(a1.m3,0)+ + COALESCE(a2.m1,0)+COALESCE(a2.m2,0)+COALESCE(a2.m3,0)+ + COALESCE(a3.m1,0)+COALESCE(a3.m2,0)+COALESCE(a3.m3,0)+ + COALESCE(a4.m1,0)+COALESCE(a4.m2,0)+COALESCE(a4.m3,0)+COALESCE(a4.spod,0) END, + CASE WHEN s_year THEN + ROUND( + (COALESCE(a1.abi,0)+COALESCE(a1.ai,0)+COALESCE(a2.abi,0)+COALESCE(a2.ai,0)+ + COALESCE(a3.abi,0)+COALESCE(a3.ai,0)+COALESCE(a4.abi,0)+COALESCE(a4.ai,0)) + -(COALESCE(a1.m1,0)+COALESCE(a1.m2,0)+COALESCE(a1.m3,0)+ + COALESCE(a2.m1,0)+COALESCE(a2.m2,0)+COALESCE(a2.m3,0)+ + COALESCE(a3.m1,0)+COALESCE(a3.m2,0)+COALESCE(a3.m3,0)+ + COALESCE(a4.m1,0)+COALESCE(a4.m2,0)+COALESCE(a4.m3,0)+COALESCE(a4.spod,0)), + 1) + END, + t.path + FROM tw t + LEFT JOIN tw_aq1 a1 ON a1.id = t.id + LEFT JOIN tw_aq2 a2 ON a2.id = t.id + LEFT JOIN tw_aq3 a3 ON a3.id = t.id + LEFT JOIN tw_aq4 a4 ON a4.id = t.id + ORDER BY t.path; +END; +$function$ +; + + +CREATE OR REPLACE FUNCTION v3.add_form3_line(p_report_id integer, p_expense_item_id integer) + RETURNS TABLE(row_type character varying, depth integer, sort_order bigint, data jsonb) + LANGUAGE plpgsql +AS $function$ +DECLARE + v_new_id INT; + v_user_id INT; + v_decision JSONB; + v_msg TEXT; +BEGIN + IF NOT EXISTS (SELECT 1 FROM v3.rf_project_report WHERE id = p_report_id) THEN + RAISE EXCEPTION 'rf_project_report id=% не существует', p_report_id; + END IF; + IF NOT EXISTS (SELECT 1 FROM v3.expense_item WHERE id = p_expense_item_id) THEN + RAISE EXCEPTION 'expense_item id=% не существует', p_expense_item_id; + END IF; + IF NOT EXISTS (SELECT 1 FROM v3.expense_item_form_type + WHERE expense_item_id = p_expense_item_id AND form_type_code = 'FORM_3') THEN + RAISE EXCEPTION 'expense_item id=% не привязан к form_type FORM_3', p_expense_item_id; + END IF; + v_user_id := v3.current_user_id(); + v_decision := v3.can_edit3(p_report_id, NULL, v_user_id); + + IF NOT (v_decision->>'ok')::boolean THEN + IF v_decision->>'code' = 'role_not_allowed' THEN + RAISE EXCEPTION 'role_not_allowed: Невозможно вставить строку'; + + ELSIF v_decision->>'code' = 'org_not_assigned' THEN + RAISE EXCEPTION 'org_not_assigned: Невозможно вставить строку'; + + ELSIF v_decision->>'code' = 'window_closed' THEN + IF v_decision ? 'opens_at' THEN + v_msg := format('window_closed: opens %s', v_decision->>'opens_at'); + ELSIF v_decision->>'closes_at' IS NOT NULL THEN + v_msg := format('window_closed: closed %s', v_decision->>'closes_at'); + ELSE + v_msg := 'window_closed: no phase'; + END IF; + RAISE EXCEPTION '%', v_msg; + + ELSE + RAISE EXCEPTION '%', v_decision->>'code'; + END IF; + END IF; + + + INSERT INTO v3.rf_project_report_line (rf_project_report_id, expense_item_id) + VALUES (p_report_id, p_expense_item_id) + RETURNING id INTO v_new_id; + + PERFORM v3.log_event( + 'ROW_CREATE', 'ROW_CREATE', + jsonb_build_object( + 'sheet', 'FORM_3', + 'line_id', v_new_id, + 'report_id', p_report_id, + 'expense_item_id', p_expense_item_id + ) + ); + + DECLARE v_ei_path INT[]; + BEGIN + v_ei_path := v3._expense_item_path_set(ARRAY[p_expense_item_id]); + RETURN QUERY + SELECT v.row_type, v.depth, v.sort_order, v.data + FROM v3.v_form3_report_jsonb(p_report_id, NULL) v + WHERE (v.row_type IN ('ROOT','GROUP','ITEM','SUB_ITEM','SUB_SUB_ITEM') + AND (v.data->'header'->>'expense_item_id')::INT = ANY(v_ei_path)) + OR (v.row_type = 'INPUT' AND (v.data->>'line_id')::INT = v_new_id) + ORDER BY v.sort_order; + END; +END; +$function$ +; + +CREATE OR REPLACE FUNCTION v3.upd_form3_cells( + p_report_id INT, + p_changes JSONB +) +RETURNS TABLE ( + row_type VARCHAR, + depth INT, + sort_order BIGINT, + data JSONB +) +AS $function$ +DECLARE + v_change JSONB; + v_line_id INT; + v_column TEXT; + v_value JSONB; + v_changed_lines INT[] := ARRAY[]::INT[]; +BEGIN + IF p_changes IS NULL OR jsonb_typeof(p_changes) <> 'array' THEN + RAISE EXCEPTION 'p_changes must be a JSONB array'; + END IF; + + IF NOT EXISTS (SELECT 1 FROM v3.rf_project_report WHERE id = p_report_id) THEN + RAISE EXCEPTION 'rf_project_report id=% не существует', p_report_id; + END IF; + + FOR v_change IN SELECT * FROM jsonb_array_elements(p_changes) + LOOP + v_line_id := (v_change->>'line_id')::INT; + v_column := v_change->>'column'; + v_value := v_change->'value'; + + IF v_line_id IS NULL OR v_column IS NULL THEN + RAISE EXCEPTION 'change must have line_id and column: %', v_change; + END IF; + + IF NOT EXISTS ( + SELECT 1 FROM v3.rf_project_report_line + WHERE id = v_line_id AND rf_project_report_id = p_report_id + ) THEN + RAISE EXCEPTION 'rf_project_report_line id=% не принадлежит report id=%', + v_line_id, p_report_id; + END IF; + + PERFORM v3._apply_form3_cell(v_line_id, v_column, v_value); + + IF NOT (v_line_id = ANY(v_changed_lines)) THEN + v_changed_lines := v_changed_lines || v_line_id; + END IF; + END LOOP; + + -- Возврат: иерархия по пути изменённых rfprl + изменённые INPUT по line_id + DECLARE + v_eid_set INT[]; + v_ei_path INT[]; + BEGIN + SELECT array_agg(DISTINCT rfprl.expense_item_id) + INTO v_eid_set + FROM v3.rf_project_report_line rfprl + WHERE rfprl.id = ANY(v_changed_lines); + v_ei_path := v3._expense_item_path_set(v_eid_set); + + RETURN QUERY + SELECT v.row_type, v.depth, v.sort_order, v.data + FROM v3.v_form3_report_jsonb(p_report_id, NULL) v + WHERE (v.row_type IN ('ROOT','GROUP','ITEM','SUB_ITEM','SUB_SUB_ITEM') + AND (v.data->'header'->>'expense_item_id')::INT = ANY(v_ei_path)) + OR (v.row_type = 'INPUT' AND (v.data->>'line_id')::INT = ANY(v_changed_lines)) + ORDER BY v.sort_order; + END; +END; +$function$ +LANGUAGE plpgsql VOLATILE; + +CREATE OR REPLACE FUNCTION v3.upd_form3_cells( + p_report_id INT, + p_changes JSONB, + p_user_id INT +) +RETURNS TABLE ( + row_type VARCHAR, + depth INT, + sort_order BIGINT, + data JSONB +) +AS $function$ +DECLARE + v_change JSONB; + v_column TEXT; + v_decision JSONB; + v_msg TEXT; +BEGIN + IF p_user_id IS NULL THEN + RAISE EXCEPTION 'role_not_allowed: '; + END IF; + + IF NOT EXISTS (SELECT 1 FROM v3.app_user WHERE id = p_user_id AND is_active) THEN + RAISE EXCEPTION 'role_not_allowed: unknown or inactive user %', p_user_id; + END IF; + + IF p_changes IS NULL OR jsonb_typeof(p_changes) <> 'array' THEN + RAISE EXCEPTION 'p_changes must be a JSONB array'; + END IF; + + -- Проверяем КАЖДУЮ ячейку до начала записи. Падаем на первой запрещённой — + -- транзакция целиком откатится, частичной записи не будет. + FOR v_change IN SELECT * FROM jsonb_array_elements(p_changes) + LOOP + v_column := v_change->>'column'; + IF v_column IS NULL THEN + RAISE EXCEPTION 'change must have column: %', v_change; + END IF; + + v_decision := v3.can_edit3(p_report_id, v_column, p_user_id); + + IF NOT (v_decision->>'ok')::boolean THEN + IF v_decision->>'code' = 'role_not_allowed' THEN + RAISE EXCEPTION 'role_not_allowed: %', v_column; + + ELSIF v_decision->>'code' = 'org_not_assigned' THEN + RAISE EXCEPTION 'org_not_assigned: %', v_column; + + ELSIF v_decision->>'code' = 'window_closed' THEN + IF v_decision ? 'opens_at' THEN + v_msg := format('window_closed: %s (opens %s)', + v_column, v_decision->>'opens_at'); + ELSIF v_decision->>'closes_at' IS NOT NULL THEN + v_msg := format('window_closed: %s (closed %s)', + v_column, v_decision->>'closes_at'); + ELSE + v_msg := format('window_closed: %s (no phase)', v_column); + END IF; + RAISE EXCEPTION '%', v_msg; + + ELSE + RAISE EXCEPTION '%: %', v_decision->>'code', v_column; + END IF; + END IF; + END LOOP; + + -- Все ячейки разрешены — делегируем в low-level (2-арг). ROW_UPDATE не + -- логируем (см. logging_events.md): cell-edit'ы слишком частые. + RETURN QUERY + SELECT * FROM v3.upd_form3_cells(p_report_id, p_changes); +END; +$function$ +LANGUAGE plpgsql VOLATILE;