DFiP_Budget_planing/api/alembic/versions/0007_form_constraints.py

181 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from alembic import op
import sqlalchemy as sa
revision = "0007"
down_revision = "0006"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.execute("""
CREATE OR REPLACE FUNCTION v3.v_form1_smeta(p_year integer, p_org_unit_id integer)
RETURNS TABLE(row_type character varying, depth integer, section_code character varying, name character varying, supp_plan_q1 numeric, supp_plan_q2 numeric, supp_plan_q3 numeric, supp_plan_q4 numeric, supp_plan_year numeric, dev_plan_q1 numeric, dev_plan_q2 numeric, dev_plan_q3 numeric, dev_plan_q4 numeric, dev_plan_year numeric, total_plan_year numeric, supp_appr_q1 numeric, supp_appr_q2 numeric, supp_appr_q3 numeric, supp_appr_q4 numeric, supp_appr_year numeric, dev_appr_q1 numeric, dev_appr_q2 numeric, dev_appr_q3 numeric, dev_appr_q4 numeric, dev_appr_year numeric, total_appr_year numeric, supp_act_q1 numeric, supp_act_q2 numeric, supp_act_q3 numeric, supp_act_q4 numeric, supp_act_year numeric, dev_act_q1 numeric, dev_act_q2 numeric, dev_act_q3 numeric, dev_act_q4 numeric, dev_act_year numeric, total_act_year numeric, supp_corr_q2 numeric, supp_corr_q3 numeric, supp_corr_q4 numeric, dev_corr_q2 numeric, dev_corr_q3 numeric, dev_corr_q4 numeric)
LANGUAGE plpgsql
STABLE
SET search_path TO 'v3', 'pg_catalog'
AS $function$
#variable_conflict use_column
DECLARE
v_ahr INT; v_cap INT; v_oper INT;
v_sections TEXT[] := ARRAY['plan','approved','q1','q2','q3','q4'];
BEGIN
-- Одна budget_form на лист содержит ОБА направления (budget_line.direction).
-- Support/Development различаются параметром p_direction, а не отдельной формой.
WITH ranked AS (
SELECT bf.id AS fid, ei.sheet AS sh
FROM budget_form bf
JOIN budget_line bl ON bl.budget_form_id = bf.id
JOIN expense_item ei ON ei.id = bl.expense_item_id
WHERE bf.year = p_year AND bf.org_unit_id = p_org_unit_id AND bf.form_type_code = 'FORM_1'
GROUP BY bf.id, ei.sheet
)
SELECT
MAX(CASE WHEN sh='AHR' THEN fid END),
MAX(CASE WHEN sh='CAP' THEN fid END),
MAX(CASE WHEN sh='OPER' THEN fid END)
INTO v_ahr, v_cap, v_oper
FROM ranked;
RETURN QUERY
WITH
ahr_s AS (
SELECT col_C_section AS sc, col_F_name AS nm, depth, row_type,
col_H_plan_q1 AS pq1, col_I_plan_q2 AS pq2, col_J_plan_q3 AS pq3, col_K_plan_q4 AS pq4, col_L_plan_year AS pyr,
col_AM_approved_q1 AS aq1, col_AN_approved_q2 AS aq2, col_AO_approved_q3 AS aq3, col_AP_approved_q4 AS aq4, col_AQ_approved_year AS ayr,
col_CS_q1_actual_quarter AS fq1, col_EB_q2_actual_quarter AS fq2, col_FJ_q3_actual_quarter AS fq3,
COALESCE(col_GQ_q4_actual_quarter,0) + COALESCE(col_GR_q4_actual_spod,0) AS fq4,
col_DH_q2_new_plan AS np2, col_EP_q3_new_plan AS np3, col_FW_q4_new_plan AS np4
FROM v_form1_sheet_sections(v_ahr, 'AHR', 'Support', v_sections)
WHERE row_type IN ('ROOT','GROUP','ITEM')
),
ahr_d AS (
SELECT col_C_section AS sc, col_F_name AS nm, depth, row_type,
col_H_plan_q1 AS pq1, col_I_plan_q2 AS pq2, col_J_plan_q3 AS pq3, col_K_plan_q4 AS pq4, col_L_plan_year AS pyr,
col_AM_approved_q1 AS aq1, col_AN_approved_q2 AS aq2, col_AO_approved_q3 AS aq3, col_AP_approved_q4 AS aq4, col_AQ_approved_year AS ayr,
col_CS_q1_actual_quarter AS fq1, col_EB_q2_actual_quarter AS fq2, col_FJ_q3_actual_quarter AS fq3,
COALESCE(col_GQ_q4_actual_quarter,0) + COALESCE(col_GR_q4_actual_spod,0) AS fq4,
col_DH_q2_new_plan AS np2, col_EP_q3_new_plan AS np3, col_FW_q4_new_plan AS np4
FROM v_form1_sheet_sections(v_ahr, 'AHR', 'Development', v_sections)
WHERE row_type IN ('ROOT','GROUP','ITEM')
),
cap_s AS (
SELECT col_C_section AS sc, col_F_name AS nm, depth, row_type,
col_H_plan_q1 AS pq1, col_I_plan_q2 AS pq2, col_J_plan_q3 AS pq3, col_K_plan_q4 AS pq4, col_L_plan_year AS pyr,
col_AM_approved_q1 AS aq1, col_AN_approved_q2 AS aq2, col_AO_approved_q3 AS aq3, col_AP_approved_q4 AS aq4, col_AQ_approved_year AS ayr,
col_CS_q1_actual_quarter AS fq1, col_EB_q2_actual_quarter AS fq2, col_FJ_q3_actual_quarter AS fq3,
COALESCE(col_GQ_q4_actual_quarter,0) + COALESCE(col_GR_q4_actual_spod,0) AS fq4,
col_DH_q2_new_plan AS np2, col_EP_q3_new_plan AS np3, col_FW_q4_new_plan AS np4
FROM v_form1_sheet_sections(v_cap, 'CAP', 'Support', v_sections)
WHERE row_type IN ('ROOT','GROUP','ITEM')
),
cap_d AS (
SELECT col_C_section AS sc, col_F_name AS nm, depth, row_type,
col_H_plan_q1 AS pq1, col_I_plan_q2 AS pq2, col_J_plan_q3 AS pq3, col_K_plan_q4 AS pq4, col_L_plan_year AS pyr,
col_AM_approved_q1 AS aq1, col_AN_approved_q2 AS aq2, col_AO_approved_q3 AS aq3, col_AP_approved_q4 AS aq4, col_AQ_approved_year AS ayr,
col_CS_q1_actual_quarter AS fq1, col_EB_q2_actual_quarter AS fq2, col_FJ_q3_actual_quarter AS fq3,
COALESCE(col_GQ_q4_actual_quarter,0) + COALESCE(col_GR_q4_actual_spod,0) AS fq4,
col_DH_q2_new_plan AS np2, col_EP_q3_new_plan AS np3, col_FW_q4_new_plan AS np4
FROM v_form1_sheet_sections(v_cap, 'CAP', 'Development', v_sections)
WHERE row_type IN ('ROOT','GROUP','ITEM')
),
oper_s AS (
SELECT col_C_section AS sc, col_F_name AS nm, depth, row_type,
col_H_plan_q1 AS pq1, col_I_plan_q2 AS pq2, col_J_plan_q3 AS pq3, col_K_plan_q4 AS pq4, col_L_plan_year AS pyr,
col_AM_approved_q1 AS aq1, col_AN_approved_q2 AS aq2, col_AO_approved_q3 AS aq3, col_AP_approved_q4 AS aq4, col_AQ_approved_year AS ayr,
col_CS_q1_actual_quarter AS fq1, col_EB_q2_actual_quarter AS fq2, col_FJ_q3_actual_quarter AS fq3,
COALESCE(col_GQ_q4_actual_quarter,0) + COALESCE(col_GR_q4_actual_spod,0) AS fq4,
col_DH_q2_new_plan AS np2, col_EP_q3_new_plan AS np3, col_FW_q4_new_plan AS np4
FROM v_form1_sheet_sections(v_oper, 'OPER', 'Support', v_sections)
WHERE row_type IN ('ROOT','GROUP','ITEM')
),
merged AS (
SELECT COALESCE(s.row_type, d.row_type) AS row_type,
COALESCE(s.depth, d.depth) AS depth,
COALESCE(s.sc, d.sc) AS sc,
COALESCE(s.nm, d.nm) AS nm,
s.pq1, s.pq2, s.pq3, s.pq4, s.pyr,
d.pq1 AS d_pq1, d.pq2 AS d_pq2, d.pq3 AS d_pq3, d.pq4 AS d_pq4, d.pyr AS d_pyr,
s.aq1, s.aq2, s.aq3, s.aq4, s.ayr,
d.aq1 AS d_aq1, d.aq2 AS d_aq2, d.aq3 AS d_aq3, d.aq4 AS d_aq4, d.ayr AS d_ayr,
s.fq1, s.fq2, s.fq3, s.fq4,
d.fq1 AS d_fq1, d.fq2 AS d_fq2, d.fq3 AS d_fq3, d.fq4 AS d_fq4,
s.np2, s.np3, s.np4,
d.np2 AS d_np2, d.np3 AS d_np3, d.np4 AS d_np4
FROM ahr_s s FULL OUTER JOIN ahr_d d ON s.sc = d.sc
UNION ALL
SELECT COALESCE(s.row_type, d.row_type), COALESCE(s.depth, d.depth),
COALESCE(s.sc, d.sc), COALESCE(s.nm, d.nm),
s.pq1, s.pq2, s.pq3, s.pq4, s.pyr,
d.pq1, d.pq2, d.pq3, d.pq4, d.pyr,
s.aq1, s.aq2, s.aq3, s.aq4, s.ayr,
d.aq1, d.aq2, d.aq3, d.aq4, d.ayr,
s.fq1, s.fq2, s.fq3, s.fq4,
d.fq1, d.fq2, d.fq3, d.fq4,
s.np2, s.np3, s.np4,
d.np2, d.np3, d.np4
FROM cap_s s FULL OUTER JOIN cap_d d ON s.sc = d.sc
UNION ALL
SELECT s.row_type, s.depth, s.sc, s.nm,
s.pq1, s.pq2, s.pq3, s.pq4, s.pyr,
NULL::NUMERIC, NULL::NUMERIC, NULL::NUMERIC, NULL::NUMERIC, NULL::NUMERIC,
s.aq1, s.aq2, s.aq3, s.aq4, s.ayr,
NULL::NUMERIC, NULL::NUMERIC, NULL::NUMERIC, NULL::NUMERIC, NULL::NUMERIC,
s.fq1, s.fq2, s.fq3, s.fq4,
NULL::NUMERIC, NULL::NUMERIC, NULL::NUMERIC, NULL::NUMERIC,
s.np2, s.np3, s.np4,
NULL::NUMERIC, NULL::NUMERIC, NULL::NUMERIC
FROM oper_s s
)
SELECT
m.row_type, m.depth, m.sc, m.nm,
m.pq1, m.pq2, m.pq3, m.pq4, m.pyr,
m.d_pq1, m.d_pq2, m.d_pq3, m.d_pq4, m.d_pyr,
COALESCE(m.pyr,0) + COALESCE(m.d_pyr,0) AS total_plan_year,
m.aq1, m.aq2, m.aq3, m.aq4, m.ayr,
m.d_aq1, m.d_aq2, m.d_aq3, m.d_aq4, m.d_ayr,
COALESCE(m.ayr,0) + COALESCE(m.d_ayr,0) AS total_appr_year,
m.fq1, m.fq2, m.fq3, m.fq4, COALESCE(m.fq1,0)+COALESCE(m.fq2,0)+COALESCE(m.fq3,0)+COALESCE(m.fq4,0),
m.d_fq1, m.d_fq2, m.d_fq3, m.d_fq4, COALESCE(m.d_fq1,0)+COALESCE(m.d_fq2,0)+COALESCE(m.d_fq3,0)+COALESCE(m.d_fq4,0),
COALESCE(m.fq1,0)+COALESCE(m.fq2,0)+COALESCE(m.fq3,0)+COALESCE(m.fq4,0)
+ COALESCE(m.d_fq1,0)+COALESCE(m.d_fq2,0)+COALESCE(m.d_fq3,0)+COALESCE(m.d_fq4,0),
m.np2, m.np3, m.np4,
m.d_np2, m.d_np3, m.d_np4
FROM merged m
ORDER BY m.sc;
END;
$function$
;
""")
for t_name in (
"reserve", "contract_detail", "ckk", "allocation", "sequestration", "contract_summary",
"collegial_approval", "rent_detail", "utility_detail", "plan", "budget_line_quarter"
):
op.execute(f"""
delete from v3.{t_name} where line_id in (
select id from v3.budget_line where budget_form_id not in (select min(fid) from (
SELECT bf.id AS fid, bf.year as yr, bf.form_type_code as ftc, bf.org_unit_id as oui
FROM v3.budget_form bf
) ranked
group by yr, ftc, oui));
""")
op.execute("""
delete from v3.budget_line where budget_form_id not in (select min(fid) from (
SELECT bf.id AS fid, bf.year as yr, bf.form_type_code as ftc, bf.org_unit_id as oui
FROM v3.budget_form bf
) ranked
group by yr, ftc, oui);
""")
op.execute("""
delete from v3.budget_form where id not in (select min(fid) from (
SELECT bf.id AS fid, bf.year as yr, bf.form_type_code as ftc, bf.org_unit_id as oui
FROM v3.budget_form bf
) ranked
group by yr, ftc, oui);
""")
op.execute("ALTER TABLE v3.budget_form ADD CONSTRAINT uq_ftype_org_year UNIQUE (form_type_code, org_unit_id, year)")
def downgrade() -> None:
pass