fixes-form: добавил новые статьи #164

Merged
tsygankoviva merged 1 commits from fixes-form into test 2026-09-16 15:44:06 +03:00
8 changed files with 3617 additions and 4628 deletions

View File

@ -0,0 +1,15 @@
from sql_migration import run_sql_file_migration
revision = "0028"
down_revision = "0027"
branch_labels = None
depends_on = None
def upgrade() -> None:
run_sql_file_migration("0028_summary2_cap_smeta_type.sql")
def downgrade() -> None:
pass

View File

@ -0,0 +1,15 @@
from sql_migration import run_sql_file_migration
revision = "0029"
down_revision = "0028"
branch_labels = None
depends_on = None
def upgrade() -> None:
run_sql_file_migration("0029_expense_items_fixes.sql")
def downgrade() -> None:
pass

View File

@ -0,0 +1,436 @@
CREATE OR REPLACE FUNCTION v3.v_svod2_go(
p_year integer,
p_org_unit_ids integer[] DEFAULT NULL,
p_offset integer DEFAULT NULL,
p_limit integer DEFAULT NULL,
p_sort_by varchar DEFAULT 'org_name',
p_sort_direction varchar DEFAULT 'asc'
)
RETURNS TABLE(
source_form varchar, source_id integer, source_org_unit_id integer,
org_name varchar, smeta_type varchar,
source_line_id integer, sort_order bigint, data jsonb
)
LANGUAGE sql STABLE SET search_path TO 'v3', 'pg_catalog'
AS $function$
WITH empty_sections AS MATERIALIZED (
SELECT
(to_jsonb(jsonb_populate_record(NULL::v3.plan, '{}'::jsonb)) - 'line_id')
|| jsonb_build_object('plan_year', NULL) AS plan,
(to_jsonb(jsonb_populate_record(NULL::v3.sequestration, '{}'::jsonb))
- 'id' - 'line_id' - 'actor') || jsonb_build_object('adj_year', NULL) AS sequestration,
(to_jsonb(jsonb_populate_record(NULL::v3.reserve, '{}'::jsonb)) - 'line_id')
|| jsonb_build_object('amount_year', NULL) AS reserve,
jsonb_build_object(
'approved_q1', NULL, 'approved_q2', NULL,
'approved_q3', NULL, 'approved_q4', NULL,
'approved_year', NULL
) AS approved,
to_jsonb(jsonb_populate_record(NULL::v3.contract_summary, '{}'::jsonb)) - 'line_id' AS contract_summary,
to_jsonb(jsonb_populate_record(NULL::v3.allocation, '{}'::jsonb)) - 'line_id' AS allocation,
to_jsonb(jsonb_populate_record(NULL::v3.collegial_approval, '{}'::jsonb)) - 'line_id' AS collegial,
to_jsonb(jsonb_populate_record(NULL::v3.ckk, '{}'::jsonb)) - 'line_id' AS ckk,
to_jsonb(jsonb_populate_record(NULL::v3.contract_detail, '{}'::jsonb)) - 'line_id' AS contract_detail,
to_jsonb(jsonb_populate_record(NULL::v3.booking, '{}'::jsonb)) - 'id' - 'line_id' AS booking,
to_jsonb(jsonb_populate_record(NULL::v3.budget_line_quarter, '{}'::jsonb))
- 'line_id' - 'quarter' AS quarter
), eligible_lines AS (
SELECT
bl.id AS line_id,
bf.form_type_code,
bf.id AS form_id,
bf.org_unit_id,
ou.title AS org_name,
ei.section_code,
ei.item_id,
CASE ei.sheet WHEN 'AHR' THEN 'АХР' WHEN 'CAP' THEN 'КВ'
WHEN 'OPER' THEN 'Операц' END::varchar AS smeta_type
FROM v3.budget_form bf
JOIN v3.budget_line bl ON bl.budget_form_id = bf.id
JOIN v3.expense_item ei ON ei.id = bl.expense_item_id
JOIN v3.contract_detail cd ON cd.line_id = bl.id
LEFT JOIN v3.org_unit ou ON ou.id = bf.org_unit_id
WHERE bf.year = p_year
AND bf.form_type_code IN ('FORM_1', 'FORM_4')
AND ei.sheet IN ('AHR', 'CAP', 'OPER')
AND (p_org_unit_ids IS NULL OR cardinality(p_org_unit_ids) = 0
OR bf.org_unit_id = ANY(p_org_unit_ids))
), numbered_lines AS (
SELECT el.*,
row_number() OVER (
ORDER BY
CASE WHEN p_sort_by = 'org_name' AND lower(p_sort_direction) = 'asc'
THEN el.org_name END ASC NULLS LAST,
CASE WHEN p_sort_by = 'org_name' AND lower(p_sort_direction) = 'desc'
THEN el.org_name END DESC NULLS LAST,
CASE WHEN p_sort_by = 'org_name' AND lower(p_sort_direction) = 'asc'
THEN el.item_id END ASC NULLS LAST,
CASE WHEN p_sort_by = 'org_name' AND lower(p_sort_direction) = 'desc'
THEN el.item_id END DESC NULLS LAST,
CASE WHEN p_sort_by = 'section_code' AND lower(p_sort_direction) = 'asc'
THEN el.section_code END ASC NULLS LAST,
CASE WHEN p_sort_by = 'section_code' AND lower(p_sort_direction) = 'desc'
THEN el.section_code END DESC NULLS LAST,
el.form_type_code, el.form_id, el.line_id
) AS sort_order
FROM eligible_lines el
), page AS MATERIALIZED (
SELECT * FROM numbered_lines
ORDER BY sort_order
LIMIT p_limit OFFSET COALESCE(p_offset, 0)
), booking_data AS (
SELECT b.line_id,
jsonb_agg(to_jsonb(b) - 'id' - 'line_id' ORDER BY b.quarter, b.source) AS booking
FROM page pg
JOIN v3.booking b ON b.line_id = pg.line_id
GROUP BY b.line_id
)
SELECT
pg.form_type_code,
pg.form_id,
pg.org_unit_id,
pg.org_name,
pg.smeta_type,
pg.line_id,
pg.sort_order,
jsonb_build_object(
'line_id', bl.id,
'header', jsonb_build_object(
'section_code', ei.section_code, 'item_id', ei.item_id,
'num_group', ei.num_group_id, 'name', COALESCE(bl.name, ei.name),
'expense_item_id', ei.id, 'justification', bl.justification,
'internal_order', bl.internal_order, 'vsp_id', bl.vsp_id,
'project_id', bl.project_id, 'direction', bl.direction,
'smeta_direction', CASE bl.direction
WHEN 'Support' THEN 'Поддержка'
WHEN 'Development' THEN 'Развитие'
ELSE NULL
END,
'source_form', pg.form_type_code, 'source_id', pg.form_id,
'source_org_unit_id', pg.org_unit_id, 'org_name', pg.org_name,
'smeta_type', pg.smeta_type),
'plan', COALESCE(
(to_jsonb(pl) - 'line_id') || jsonb_build_object(
'plan_year', COALESCE(pl.plan_q1, 0) + COALESCE(pl.plan_q2, 0)
+ COALESCE(pl.plan_q3, 0) + COALESCE(pl.plan_q4, 0)),
e.plan || jsonb_build_object('plan_year', NULL)),
'sequestration', jsonb_build_object(
'DFIP', COALESCE(
(to_jsonb(sd) - 'id' - 'line_id' - 'actor') || jsonb_build_object(
'adj_year', COALESCE(sd.adj_q1, 0) + COALESCE(sd.adj_q2, 0)
+ COALESCE(sd.adj_q3, 0) + COALESCE(sd.adj_q4, 0)),
e.sequestration || jsonb_build_object('adj_year', NULL)),
'SSP_GO', COALESCE(
(to_jsonb(ss) - 'id' - 'line_id' - 'actor') || jsonb_build_object(
'adj_year', COALESCE(ss.adj_q1, 0) + COALESCE(ss.adj_q2, 0)
+ COALESCE(ss.adj_q3, 0) + COALESCE(ss.adj_q4, 0)),
e.sequestration || jsonb_build_object('adj_year', NULL))),
'reserve', COALESCE(
(to_jsonb(rv) - 'line_id') || jsonb_build_object(
'amount_year', COALESCE(rv.amount_q1, 0) + COALESCE(rv.amount_q2, 0)
+ COALESCE(rv.amount_q3, 0) + COALESCE(rv.amount_q4, 0)),
e.reserve || jsonb_build_object('amount_year', NULL)),
'approved', CASE WHEN pl.line_id IS NULL AND sd.id IS NULL
AND rv.line_id IS NULL
THEN e.approved
ELSE jsonb_build_object(
'approved_q1', COALESCE(pl.plan_q1, 0) + COALESCE(sd.adj_q1, 0)
+ COALESCE(rv.amount_q1, 0),
'approved_q2', COALESCE(pl.plan_q2, 0) + COALESCE(sd.adj_q2, 0)
+ COALESCE(rv.amount_q2, 0),
'approved_q3', COALESCE(pl.plan_q3, 0) + COALESCE(sd.adj_q3, 0)
+ COALESCE(rv.amount_q3, 0),
'approved_q4', COALESCE(pl.plan_q4, 0) + COALESCE(sd.adj_q4, 0)
+ COALESCE(rv.amount_q4, 0),
'approved_year', COALESCE(pl.plan_q1, 0) + COALESCE(pl.plan_q2, 0)
+ COALESCE(pl.plan_q3, 0) + COALESCE(pl.plan_q4, 0)
+ COALESCE(sd.adj_q1, 0) + COALESCE(sd.adj_q2, 0)
+ COALESCE(sd.adj_q3, 0) + COALESCE(sd.adj_q4, 0)
+ COALESCE(rv.amount_q1, 0) + COALESCE(rv.amount_q2, 0)
+ COALESCE(rv.amount_q3, 0) + COALESCE(rv.amount_q4, 0)) END,
'contract_summary', COALESCE(to_jsonb(cs) - 'line_id', e.contract_summary),
'allocation', COALESCE(to_jsonb(al) - 'line_id', e.allocation),
'collegial', COALESCE(to_jsonb(ca) - 'line_id', e.collegial),
'ckk', COALESCE(to_jsonb(ck) - 'line_id', e.ckk),
'contract_detail', COALESCE(to_jsonb(cd) - 'line_id', e.contract_detail),
'booking', COALESCE(bk.booking, jsonb_build_array(e.booking)),
'q1', COALESCE(to_jsonb(q1) - 'line_id' - 'quarter', e.quarter),
'q2', COALESCE(to_jsonb(q2) - 'line_id' - 'quarter', e.quarter),
'q3', COALESCE(to_jsonb(q3) - 'line_id' - 'quarter', e.quarter),
'q4', COALESCE(to_jsonb(q4) - 'line_id' - 'quarter', e.quarter)
) AS data
FROM page pg
JOIN v3.budget_line bl ON bl.id = pg.line_id
JOIN v3.expense_item ei ON ei.id = bl.expense_item_id
JOIN v3.contract_detail cd ON cd.line_id = bl.id
CROSS JOIN empty_sections e
LEFT JOIN v3.plan pl ON pl.line_id = bl.id
LEFT JOIN v3.sequestration sd ON sd.line_id = bl.id AND sd.actor = 'DFIP'
LEFT JOIN v3.sequestration ss ON ss.line_id = bl.id AND ss.actor = 'SSP_GO'
LEFT JOIN v3.reserve rv ON rv.line_id = bl.id
LEFT JOIN v3.contract_summary cs ON cs.line_id = bl.id
LEFT JOIN v3.allocation al ON al.line_id = bl.id
LEFT JOIN v3.collegial_approval ca ON ca.line_id = bl.id
LEFT JOIN v3.ckk ck ON ck.line_id = bl.id
LEFT JOIN booking_data bk ON bk.line_id = bl.id
LEFT JOIN v3.budget_line_quarter q1 ON q1.line_id = bl.id AND q1.quarter = 1
LEFT JOIN v3.budget_line_quarter q2 ON q2.line_id = bl.id AND q2.quarter = 2
LEFT JOIN v3.budget_line_quarter q3 ON q3.line_id = bl.id AND q3.quarter = 3
LEFT JOIN v3.budget_line_quarter q4 ON q4.line_id = bl.id AND q4.quarter = 4
ORDER BY pg.sort_order;
$function$;
CREATE OR REPLACE FUNCTION v3.v_svod2_rf(
p_year integer,
p_org_unit_ids integer[] DEFAULT NULL,
p_offset integer DEFAULT NULL,
p_limit integer DEFAULT NULL,
p_sort_by varchar DEFAULT 'org_name',
p_sort_direction varchar DEFAULT 'asc'
)
RETURNS TABLE(
source_form varchar, source_id integer, source_org_unit_id integer,
org_name varchar, smeta_type varchar,
source_line_id integer, sort_order bigint, data jsonb
)
LANGUAGE sql STABLE SET search_path TO 'v3', 'pg_catalog'
AS $function$
WITH empty_sections AS MATERIALIZED (
SELECT
(to_jsonb(jsonb_populate_record(NULL::v3.plan, '{}'::jsonb)) - 'line_id')
|| jsonb_build_object('plan_year', NULL) AS plan,
(to_jsonb(jsonb_populate_record(NULL::v3.sequestration, '{}'::jsonb))
- 'id' - 'line_id' - 'actor') || jsonb_build_object('adj_year', NULL) AS sequestration,
(to_jsonb(jsonb_populate_record(NULL::v3.reserve, '{}'::jsonb)) - 'line_id')
|| jsonb_build_object('amount_year', NULL) AS reserve,
jsonb_build_object(
'approved_q1', NULL, 'approved_q2', NULL,
'approved_q3', NULL, 'approved_q4', NULL,
'approved_year', NULL
) AS approved,
to_jsonb(jsonb_populate_record(NULL::v3.contract_summary, '{}'::jsonb)) - 'line_id' AS contract_summary,
to_jsonb(jsonb_populate_record(NULL::v3.allocation, '{}'::jsonb)) - 'line_id' AS allocation,
to_jsonb(jsonb_populate_record(NULL::v3.collegial_approval, '{}'::jsonb)) - 'line_id' AS collegial,
to_jsonb(jsonb_populate_record(NULL::v3.ckk, '{}'::jsonb)) - 'line_id' AS ckk,
to_jsonb(jsonb_populate_record(NULL::v3.contract_detail, '{}'::jsonb)) - 'line_id' AS contract_detail,
to_jsonb(jsonb_populate_record(NULL::v3.booking, '{}'::jsonb)) - 'id' - 'line_id' AS booking,
to_jsonb(jsonb_populate_record(NULL::v3.budget_line_quarter, '{}'::jsonb))
- 'line_id' - 'quarter' AS budget_quarter,
to_jsonb(jsonb_populate_record(NULL::v3.rf_project_report_quarter, '{}'::jsonb))
- 'rf_project_report_line_id' - 'quarter' AS report_quarter
), eligible_lines AS (
SELECT
'FORM_2'::varchar AS form_type_code,
bl.id AS line_id,
bf.id AS source_id,
bf.org_unit_id,
ou.title AS org_name,
ei.section_code,
ei.item_id,
CASE ei.sheet WHEN 'AHR' THEN 'АХР' WHEN 'CAP' THEN 'КВ'
WHEN 'OPER' THEN 'Операц' END::varchar AS smeta_type
FROM v3.budget_form bf
JOIN v3.budget_line bl ON bl.budget_form_id = bf.id
JOIN v3.expense_item ei ON ei.id = bl.expense_item_id
JOIN v3.contract_detail cd ON cd.line_id = bl.id
LEFT JOIN v3.org_unit ou ON ou.id = bf.org_unit_id
WHERE bf.year = p_year AND bf.form_type_code = 'FORM_2'
AND ei.sheet IN ('AHR', 'CAP', 'OPER')
AND (p_org_unit_ids IS NULL OR cardinality(p_org_unit_ids) = 0
OR bf.org_unit_id = ANY(p_org_unit_ids))
UNION ALL
SELECT
'FORM_3'::varchar,
rrl.id,
rr.id,
p.org_unit_id,
ou.title,
ei.section_code,
ei.item_id,
CASE ei.sheet WHEN 'AHR' THEN 'АХР' WHEN 'CAP' THEN 'КВ'
WHEN 'OPER' THEN 'Операц' END::varchar
FROM v3.rf_project_report rr
JOIN v3.rf_project_year rpy ON rpy.id = rr.rf_project_year_id
JOIN v3.project p ON p.id = rr.project_id
JOIN v3.rf_project_report_line rrl ON rrl.rf_project_report_id = rr.id
JOIN v3.expense_item ei ON ei.id = rrl.expense_item_id
LEFT JOIN v3.org_unit ou ON ou.id = p.org_unit_id
WHERE rpy.year = p_year AND ei.sheet IN ('AHR', 'CAP', 'OPER')
AND (p_org_unit_ids IS NULL OR cardinality(p_org_unit_ids) = 0
OR p.org_unit_id = ANY(p_org_unit_ids))
), numbered_lines AS (
SELECT el.*,
row_number() OVER (
ORDER BY
CASE WHEN p_sort_by = 'org_name' AND lower(p_sort_direction) = 'asc'
THEN el.org_name END ASC NULLS LAST,
CASE WHEN p_sort_by = 'org_name' AND lower(p_sort_direction) = 'desc'
THEN el.org_name END DESC NULLS LAST,
CASE WHEN p_sort_by = 'org_name' AND lower(p_sort_direction) = 'asc'
THEN el.item_id END ASC NULLS LAST,
CASE WHEN p_sort_by = 'org_name' AND lower(p_sort_direction) = 'desc'
THEN el.item_id END DESC NULLS LAST,
CASE WHEN p_sort_by = 'section_code' AND lower(p_sort_direction) = 'asc'
THEN el.section_code END ASC NULLS LAST,
CASE WHEN p_sort_by = 'section_code' AND lower(p_sort_direction) = 'desc'
THEN el.section_code END DESC NULLS LAST,
el.form_type_code, el.source_id, el.line_id
) AS sort_order
FROM eligible_lines el
), page AS MATERIALIZED (
SELECT * FROM numbered_lines
ORDER BY sort_order
LIMIT p_limit OFFSET COALESCE(p_offset, 0)
), booking_data AS (
SELECT b.line_id,
jsonb_agg(to_jsonb(b) - 'id' - 'line_id' ORDER BY b.quarter, b.source) AS booking
FROM page pg
JOIN v3.booking b ON b.line_id = pg.line_id
WHERE pg.form_type_code = 'FORM_2'
GROUP BY b.line_id
), form2_data AS (
SELECT
pg.form_type_code AS source_form, pg.source_id,
pg.org_unit_id AS source_org_unit_id, pg.org_name, pg.smeta_type,
pg.line_id AS source_line_id, pg.sort_order,
jsonb_build_object(
'line_id', bl.id,
'header', jsonb_build_object(
'section_code', ei.section_code, 'item_id', ei.item_id,
'num_group', ei.num_group_id, 'name', COALESCE(bl.name, ei.name),
'expense_item_id', ei.id, 'justification', bl.justification,
'internal_order', bl.internal_order, 'vsp_id', bl.vsp_id,
'project_id', bl.project_id, 'direction', bl.direction,
'smeta_direction', CASE bl.direction
WHEN 'Support' THEN 'Поддержка'
WHEN 'Development' THEN 'Развитие'
ELSE NULL
END,
'source_form', pg.form_type_code, 'source_id', pg.source_id,
'source_org_unit_id', pg.org_unit_id, 'org_name', pg.org_name,
'smeta_type', pg.smeta_type),
'plan', COALESCE(
(to_jsonb(pl) - 'line_id') || jsonb_build_object(
'plan_year', COALESCE(pl.plan_q1, 0) + COALESCE(pl.plan_q2, 0)
+ COALESCE(pl.plan_q3, 0) + COALESCE(pl.plan_q4, 0)),
e.plan || jsonb_build_object('plan_year', NULL)),
'sequestration', jsonb_build_object(
'DFIP', COALESCE(
(to_jsonb(sd) - 'id' - 'line_id' - 'actor') || jsonb_build_object(
'adj_year', COALESCE(sd.adj_q1, 0) + COALESCE(sd.adj_q2, 0)
+ COALESCE(sd.adj_q3, 0) + COALESCE(sd.adj_q4, 0)),
e.sequestration || jsonb_build_object('adj_year', NULL)),
'SSP_GO', COALESCE(
(to_jsonb(ss) - 'id' - 'line_id' - 'actor') || jsonb_build_object(
'adj_year', COALESCE(ss.adj_q1, 0) + COALESCE(ss.adj_q2, 0)
+ COALESCE(ss.adj_q3, 0) + COALESCE(ss.adj_q4, 0)),
e.sequestration || jsonb_build_object('adj_year', NULL))),
'reserve', COALESCE(
(to_jsonb(rv) - 'line_id') || jsonb_build_object(
'amount_year', COALESCE(rv.amount_q1, 0) + COALESCE(rv.amount_q2, 0)
+ COALESCE(rv.amount_q3, 0) + COALESCE(rv.amount_q4, 0)),
e.reserve || jsonb_build_object('amount_year', NULL)),
'approved', CASE WHEN pl.line_id IS NULL AND sd.id IS NULL
AND ss.id IS NULL AND rv.line_id IS NULL
THEN e.approved
ELSE jsonb_build_object(
'approved_q1', COALESCE(pl.plan_q1, 0) + COALESCE(sd.adj_q1, 0)
+ COALESCE(ss.adj_q1, 0) + COALESCE(rv.amount_q1, 0),
'approved_q2', COALESCE(pl.plan_q2, 0) + COALESCE(sd.adj_q2, 0)
+ COALESCE(ss.adj_q2, 0) + COALESCE(rv.amount_q2, 0),
'approved_q3', COALESCE(pl.plan_q3, 0) + COALESCE(sd.adj_q3, 0)
+ COALESCE(ss.adj_q3, 0) + COALESCE(rv.amount_q3, 0),
'approved_q4', COALESCE(pl.plan_q4, 0) + COALESCE(sd.adj_q4, 0)
+ COALESCE(ss.adj_q4, 0) + COALESCE(rv.amount_q4, 0),
'approved_year', COALESCE(pl.plan_q1, 0) + COALESCE(pl.plan_q2, 0)
+ COALESCE(pl.plan_q3, 0) + COALESCE(pl.plan_q4, 0)
+ COALESCE(sd.adj_q1, 0) + COALESCE(sd.adj_q2, 0)
+ COALESCE(sd.adj_q3, 0) + COALESCE(sd.adj_q4, 0)
+ COALESCE(ss.adj_q1, 0) + COALESCE(ss.adj_q2, 0)
+ COALESCE(ss.adj_q3, 0) + COALESCE(ss.adj_q4, 0)
+ COALESCE(rv.amount_q1, 0) + COALESCE(rv.amount_q2, 0)
+ COALESCE(rv.amount_q3, 0) + COALESCE(rv.amount_q4, 0)) END,
'contract_summary', COALESCE(to_jsonb(cs) - 'line_id', e.contract_summary),
'allocation', COALESCE(to_jsonb(al) - 'line_id', e.allocation),
'collegial', COALESCE(to_jsonb(ca) - 'line_id', e.collegial),
'ckk', COALESCE(to_jsonb(ck) - 'line_id', e.ckk),
'contract_detail', COALESCE(to_jsonb(cd) - 'line_id', e.contract_detail),
'booking', COALESCE(bk.booking, jsonb_build_array(e.booking)),
'q1', COALESCE(to_jsonb(q1) - 'line_id' - 'quarter', e.budget_quarter),
'q2', COALESCE(to_jsonb(q2) - 'line_id' - 'quarter', e.budget_quarter),
'q3', COALESCE(to_jsonb(q3) - 'line_id' - 'quarter', e.budget_quarter),
'q4', COALESCE(to_jsonb(q4) - 'line_id' - 'quarter', e.budget_quarter)
) AS data
FROM page pg
JOIN v3.budget_line bl ON bl.id = pg.line_id
JOIN v3.expense_item ei ON ei.id = bl.expense_item_id
JOIN v3.contract_detail cd ON cd.line_id = bl.id
CROSS JOIN empty_sections e
LEFT JOIN v3.plan pl ON pl.line_id = bl.id
LEFT JOIN v3.sequestration sd ON sd.line_id = bl.id AND sd.actor = 'DFIP'
LEFT JOIN v3.sequestration ss ON ss.line_id = bl.id AND ss.actor = 'SSP_GO'
LEFT JOIN v3.reserve rv ON rv.line_id = bl.id
LEFT JOIN v3.contract_summary cs ON cs.line_id = bl.id
LEFT JOIN v3.allocation al ON al.line_id = bl.id
LEFT JOIN v3.collegial_approval ca ON ca.line_id = bl.id
LEFT JOIN v3.ckk ck ON ck.line_id = bl.id
LEFT JOIN booking_data bk ON bk.line_id = bl.id
LEFT JOIN v3.budget_line_quarter q1 ON q1.line_id = bl.id AND q1.quarter = 1
LEFT JOIN v3.budget_line_quarter q2 ON q2.line_id = bl.id AND q2.quarter = 2
LEFT JOIN v3.budget_line_quarter q3 ON q3.line_id = bl.id AND q3.quarter = 3
LEFT JOIN v3.budget_line_quarter q4 ON q4.line_id = bl.id AND q4.quarter = 4
WHERE pg.form_type_code = 'FORM_2'
), form3_data AS (
SELECT
pg.form_type_code AS source_form, pg.source_id,
pg.org_unit_id AS source_org_unit_id, pg.org_name, pg.smeta_type,
pg.line_id AS source_line_id, pg.sort_order,
jsonb_build_object(
'line_id', rrl.id,
'header', jsonb_build_object(
'section_code', ei.section_code, 'item_id', ei.item_id,
'num_group', ei.num_group_id, 'name', ei.name,
'expense_item_id', ei.id, 'project_id', rr.project_id,
'report_type', rr.report_type,
'smeta_direction', NULL,
'source_form', pg.form_type_code, 'source_id', pg.source_id,
'source_org_unit_id', pg.org_unit_id, 'org_name', pg.org_name,
'smeta_type', pg.smeta_type),
'plan', e.plan,
'sequestration', jsonb_build_object(
'DFIP', e.sequestration, 'SSP_GO', e.sequestration),
'reserve', e.reserve, 'contract_summary', e.contract_summary,
'approved', e.approved,
'allocation', e.allocation, 'collegial', e.collegial,
'ckk', e.ckk, 'contract_detail', e.contract_detail,
'booking', jsonb_build_array(e.booking),
'q1', COALESCE(to_jsonb(q1) - 'rf_project_report_line_id' - 'quarter', e.report_quarter),
'q2', COALESCE(to_jsonb(q2) - 'rf_project_report_line_id' - 'quarter', e.report_quarter),
'q3', COALESCE(to_jsonb(q3) - 'rf_project_report_line_id' - 'quarter', e.report_quarter),
'q4', COALESCE(to_jsonb(q4) - 'rf_project_report_line_id' - 'quarter', e.report_quarter)
) AS data
FROM page pg
JOIN v3.rf_project_report_line rrl ON rrl.id = pg.line_id
JOIN v3.rf_project_report rr ON rr.id = pg.source_id
AND rr.id = rrl.rf_project_report_id
JOIN v3.expense_item ei ON ei.id = rrl.expense_item_id
CROSS JOIN empty_sections e
LEFT JOIN v3.rf_project_report_quarter q1
ON q1.rf_project_report_line_id = rrl.id AND q1.quarter = 1
LEFT JOIN v3.rf_project_report_quarter q2
ON q2.rf_project_report_line_id = rrl.id AND q2.quarter = 2
LEFT JOIN v3.rf_project_report_quarter q3
ON q3.rf_project_report_line_id = rrl.id AND q3.quarter = 3
LEFT JOIN v3.rf_project_report_quarter q4
ON q4.rf_project_report_line_id = rrl.id AND q4.quarter = 4
WHERE pg.form_type_code = 'FORM_3'
), result_rows AS (
SELECT * FROM form2_data
UNION ALL
SELECT * FROM form3_data
)
SELECT rr.source_form, rr.source_id, rr.source_org_unit_id, rr.org_name, rr.smeta_type,
rr.source_line_id, rr.sort_order, rr.data
FROM result_rows rr
ORDER BY rr.sort_order;
$function$;

View File

@ -0,0 +1,128 @@
-- Исправления справочника статей расходов по файлу
-- "План_исправления_таблиц_статей_расходов.docx".
-- Правки, связанные с ГСМ, намеренно не включены.
-- Общие переименования.
update v3.expense_item
set name = 'Охр.инкассат перевоз'
where item_id = 'R061063000'
and num_group_id = '211320117';
update v3.expense_item
set name = 'Взносы в орг/ассоц'
where item_id = 'R061141000'
and num_group_id = '214920158';
update v3.expense_item
set name = 'Бланк ден/чек книжМЦ'
where item_id = 'R064040032'
and num_group_id = '402640197';
update v3.expense_item
set name = 'Другие операционные доходы'
where item_id = 'R014040037'
and num_group_id is null;
-- Перенос двух статей НВНОД в раздел 1.15.6.
update v3.expense_item
set parent_id = 81,
depth = 3
where (item_id, num_group_id) in (
('R061156019', '403540147'),
('R061159019', '216220174')
);
-- Раздел 1.14: коды по шаблону, включая добавление 1.14.7 для проектов.
update v3.expense_item set item_id = '1.14.4' where id = 71;
update v3.expense_item set item_id = '1.14.5' where id = 72;
update v3.expense_item set item_id = '1.14.6' where id = 73;
update v3.expense_item set item_id = '1.14.7' where id = 74;
insert into v3.expense_item_form_type (expense_item_id, form_type_code)
values (74, 'FORM_1'), (74, 'FORM_2')
on conflict (expense_item_id, form_type_code) do nothing;
-- Исправление ошибочного ID статьи по ПО информационной безопасности.
update v3.expense_item
set item_id = 'R061012024',
direction = coalesce(direction, 'Support')
where item_id = 'R061012025'
and name = 'Внедрение и доработка внешними контрагентами: ПО информационной безопасности';
-- Статья "Расходы по выбытию: ПО информационной безопасности" для раздела 1.17.2.
update v3.expense_item
set direction = coalesce(direction, 'Support'),
parent_id = 84,
depth = 3
where item_id = 'R061172024'
and name = 'Расходы по выбытию: ПО информационной безопасности';
insert into v3.expense_item_form_type (expense_item_id, form_type_code)
select id, form_type_code
from v3.expense_item
cross join (values ('FORM_1'), ('FORM_2')) as ft(form_type_code)
where item_id = 'R061172024'
and name = 'Расходы по выбытию: ПО информационной безопасности'
on conflict (expense_item_id, form_type_code) do nothing;
-- Девять статей Операц уже есть в справочнике. Настраиваем только доступность
-- для Сметы ССП, Сметы РФ и Проектной деятельности.
with source(expense_item_id, form_type_code) as (
values
(736, 'FORM_4'), (745, 'FORM_2'), (745, 'FORM_4'),
(800, 'FORM_1'), (800, 'FORM_2'), (800, 'FORM_4'),
(801, 'FORM_1'), (801, 'FORM_2'), (801, 'FORM_4'),
(802, 'FORM_1'), (802, 'FORM_2'), (802, 'FORM_4'),
(803, 'FORM_1'), (803, 'FORM_2'), (803, 'FORM_4'),
(804, 'FORM_1'), (804, 'FORM_2'), (804, 'FORM_4'),
(805, 'FORM_1'), (805, 'FORM_2'), (805, 'FORM_4'),
(806, 'FORM_1'), (806, 'FORM_2'), (806, 'FORM_4'),
(807, 'FORM_1'), (807, 'FORM_2'), (807, 'FORM_4'),
(808, 'FORM_1'), (808, 'FORM_2'), (808, 'FORM_4')
)
insert into v3.expense_item_form_type (expense_item_id, form_type_code)
select expense_item_id, form_type_code
from source
on conflict (expense_item_id, form_type_code) do nothing;
-- Налоговые статьи раздела 5.00.0 для Сметы РФ.
insert into v3.expense_item_form_type (expense_item_id, form_type_code)
select id, 'FORM_2'
from v3.expense_item
where item_id in (
'R065010000', 'R065020001', 'R065030012', 'R065040000',
'R065050005', 'R065070000', 'R065090000', 'R065100000'
)
on conflict (expense_item_id, form_type_code) do nothing;
-- Проектная деятельность: добавить недостающие статьи АХР в FORM_4, кроме ГСМ.
with form4_ahr(expense_item_id) as (
values
(777), (778), (779), (347), (780), (781), (782), (783),
(784), (785), (786), (787), (788), (789), (790), (791),
(461), (792), (793), (794), (795), (796), (797), (798),
(477), (478)
)
insert into v3.expense_item_form_type (expense_item_id, form_type_code)
select expense_item_id, 'FORM_4'
from form4_ahr
on conflict (expense_item_id, form_type_code) do nothing;
-- Проектная деятельность и проектные листы: исключить амортизацию и налоги
-- из FORM_4, не удаляя записи из справочника и не затрагивая FORM_2.
delete from v3.expense_item_form_type
where form_type_code = 'FORM_4'
and (
expense_item_id in (746, 747, 760, 766)
or expense_item_id between 748 and 759
or expense_item_id between 761 and 765
or expense_item_id between 767 and 774
);
-- Проектные таблицы: исключить дубль перевозки валютных ценностей из формы.
delete from v3.expense_item_form_type
where form_type_code = 'FORM_4'
and expense_item_id = 70;
select setval('v3.expense_item_id_seq', greatest((select max(id) from v3.expense_item), 808));
refresh materialized view v3.mv_expense_item_tree;

View File

@ -5,9 +5,10 @@ from sqlalchemy.ext.asyncio import AsyncSession
from src.db.models.org_unit import OrgUnit
from sqlalchemy.orm import joinedload
from sqlalchemy.orm import joinedload, with_loader_criteria
from src.db.models.app_user import AppUser
class OrgUnitRepository:
@ -42,7 +43,12 @@ class OrgUnitRepository:
query = query.where(*where)
if load_users:
query = query.options(
joinedload(OrgUnit.users)
joinedload(OrgUnit.users),
with_loader_criteria(
AppUser,
AppUser.is_active.is_(True),
include_aliases=True,
),
)
query = query.order_by(OrgUnit.id)
@ -75,7 +81,12 @@ class OrgUnitRepository:
query = select(OrgUnit).where(OrgUnit.id == org_unit_id)
if load_users:
query = query.options(
joinedload(OrgUnit.users)
joinedload(OrgUnit.users),
with_loader_criteria(
AppUser,
AppUser.is_active.is_(True),
include_aliases=True,
),
)
return (await self.db.execute(query)).scalars().first()

View File

@ -111,6 +111,8 @@ class UserRepository:
async def logical_delete(self, user_id: int) -> bool:
query = update(AppUser).where(AppUser.id == user_id).values(is_active=False)
result = await self.db.execute(query)
if result.rowcount > 0:
await self.db.execute(delete(UserOrg).where(UserOrg.user_id == user_id))
await self.db.commit()
return result.rowcount > 0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff