fix(svod2): фонд экономии FORM_2 в своде 2 «РФ» считается как на листе Сметы РФ (AURORA-1938, #335)
v_svod2_rf: q1..q4.transfer_to_economy вычисляется по формулам листа, сырое поле budget_line_quarter.transfer_to_economy игнорируется. Эталон RF обновлён: фонд экономии строк теперь расчётный (GO без изменений). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
9c8871139c
commit
1304be106a
@ -1967,3 +1967,239 @@ BEGIN
|
|||||||
END;
|
END;
|
||||||
$function$
|
$function$
|
||||||
;
|
;
|
||||||
|
|
||||||
|
-- 4) AURORA-1938 / #335: Свод 2 «РФ» (FORM_2). v3.v_svod2_rf (тело - версия 0057): q1..q4.transfer_to_economy
|
||||||
|
-- берётся не из budget_line_quarter.transfer_to_economy, а считается по формулам п. 1 из тех же
|
||||||
|
-- таблиц строки (план+секвестр+резерв, корректировки, пересмотры плана, входящие переносы, факт).
|
||||||
|
-- v_svod2_go / v_svod2_go_export / summary_repository: GO = FORM_1 и FORM_4, у FORM_1 своё поле,
|
||||||
|
-- у FORM_4 фонд сырой (откат 0055 в п. 3) - не менялись.
|
||||||
|
|
||||||
|
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',
|
||||||
|
p_search text DEFAULT NULL,
|
||||||
|
p_smeta_type text DEFAULT NULL,
|
||||||
|
p_smeta_direction text DEFAULT NULL,
|
||||||
|
p_org_name text DEFAULT NULL,
|
||||||
|
p_compact boolean DEFAULT false
|
||||||
|
)
|
||||||
|
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, total_count bigint
|
||||||
|
)
|
||||||
|
-- jit off: оценка стоимости большого плана включает JIT-компиляцию на сотни миллисекунд, а выигрыша нет.
|
||||||
|
LANGUAGE sql STABLE SET search_path TO 'v3', 'pg_catalog' SET jit TO off
|
||||||
|
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
|
||||||
|
), numbered_lines AS (
|
||||||
|
SELECT el.*,
|
||||||
|
count(*) OVER () AS total_count,
|
||||||
|
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 v3.svod2_lines('RF', p_year, p_org_unit_ids,
|
||||||
|
NULLIF(v3.svod2_casefold(v3.svod2_js_trim(p_search)), '')) el
|
||||||
|
WHERE (NULLIF(v3.svod2_js_trim(v3.svod2_casefold(p_smeta_type)), '') IS NULL
|
||||||
|
OR (el.smeta_type IS NOT NULL
|
||||||
|
AND v3.svod2_js_trim(v3.svod2_casefold(el.smeta_type))
|
||||||
|
= NULLIF(v3.svod2_js_trim(v3.svod2_casefold(p_smeta_type)), '')))
|
||||||
|
AND (NULLIF(v3.svod2_js_trim(v3.svod2_casefold(p_smeta_direction)), '') IS NULL
|
||||||
|
OR (el.smeta_direction IS NOT NULL
|
||||||
|
AND v3.svod2_js_trim(v3.svod2_casefold(el.smeta_direction))
|
||||||
|
= NULLIF(v3.svod2_js_trim(v3.svod2_casefold(p_smeta_direction)), '')))
|
||||||
|
AND (NULLIF(v3.svod2_js_trim(v3.svod2_casefold(p_org_name)), '') IS NULL
|
||||||
|
OR (el.org_name IS NOT NULL
|
||||||
|
AND v3.svod2_js_trim(v3.svod2_casefold(el.org_name))
|
||||||
|
= NULLIF(v3.svod2_js_trim(v3.svod2_casefold(p_org_name)), '')))
|
||||||
|
), 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 x.source_form, x.source_id, x.source_org_unit_id, x.org_name, x.smeta_type,
|
||||||
|
x.source_line_id, x.sort_order,
|
||||||
|
CASE WHEN p_compact THEN v3.svod2_compact(x.full_data) ELSE x.full_data END AS data,
|
||||||
|
x.total_count
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
pg.form_type_code AS source_form, pg.form_id AS 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.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 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) || jsonb_build_object(
|
||||||
|
'expenses_q1', COALESCE(cd.expenses_q1, ck.expenses_q1),
|
||||||
|
'expenses_q2', COALESCE(cd.expenses_q2, ck.expenses_q2),
|
||||||
|
'expenses_q3', COALESCE(cd.expenses_q3, ck.expenses_q3),
|
||||||
|
'expenses_q4', COALESCE(cd.expenses_q4, ck.expenses_q4)),
|
||||||
|
'booking', COALESCE(bk.booking, jsonb_build_array(e.booking)),
|
||||||
|
'q1', COALESCE(to_jsonb(q1) - 'line_id' - 'quarter', e.budget_quarter) || jsonb_build_object(
|
||||||
|
'transfer_to_economy', ec.econ_q1,
|
||||||
|
'booking_amount', COALESCE(q1.booking_amount,
|
||||||
|
CASE WHEN ei.sheet = 'AHR' THEN ck.expenses_q1
|
||||||
|
WHEN ck.expenses_q1 > 0 THEN ck.expenses_q1
|
||||||
|
ELSE cd.expenses_q1 END)),
|
||||||
|
'q2', COALESCE(to_jsonb(q2) - 'line_id' - 'quarter', e.budget_quarter) || jsonb_build_object(
|
||||||
|
'transfer_to_economy', ec.econ_q2,
|
||||||
|
'booking_amount', COALESCE(q2.booking_amount,
|
||||||
|
CASE WHEN ei.sheet = 'AHR' THEN ck.expenses_q2
|
||||||
|
WHEN ck.expenses_q2 > 0 THEN ck.expenses_q2
|
||||||
|
ELSE cd.expenses_q2 END),
|
||||||
|
'plan_revision_eco_change', COALESCE(q2.target_change, q2.plan_revision_eco_change),
|
||||||
|
'plan_revision_item_adj', COALESCE(q2.base_plan_correction, q2.plan_revision_item_adj)),
|
||||||
|
'q3', COALESCE(to_jsonb(q3) - 'line_id' - 'quarter', e.budget_quarter) || jsonb_build_object(
|
||||||
|
'transfer_to_economy', ec.econ_q3,
|
||||||
|
'booking_amount', COALESCE(q3.booking_amount,
|
||||||
|
CASE WHEN ei.sheet = 'AHR' THEN ck.expenses_q3
|
||||||
|
WHEN ck.expenses_q3 > 0 THEN ck.expenses_q3
|
||||||
|
ELSE cd.expenses_q3 END),
|
||||||
|
'plan_revision_eco_change', COALESCE(q3.target_change, q3.plan_revision_eco_change),
|
||||||
|
'plan_revision_item_adj', COALESCE(q3.base_plan_correction, q3.plan_revision_item_adj)),
|
||||||
|
'q4', COALESCE(to_jsonb(q4) - 'line_id' - 'quarter', e.budget_quarter) || jsonb_build_object(
|
||||||
|
'transfer_to_economy', ec.econ_q4,
|
||||||
|
'booking_amount', COALESCE(q4.booking_amount,
|
||||||
|
CASE WHEN ei.sheet = 'AHR' THEN ck.expenses_q4
|
||||||
|
WHEN ck.expenses_q4 > 0 THEN ck.expenses_q4
|
||||||
|
ELSE cd.expenses_q4 END),
|
||||||
|
'plan_revision_eco_change', COALESCE(q4.target_change, q4.plan_revision_eco_change),
|
||||||
|
'plan_revision_item_adj', COALESCE(q4.base_plan_correction, q4.plan_revision_item_adj))
|
||||||
|
) AS full_data,
|
||||||
|
pg.total_count
|
||||||
|
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
|
||||||
|
LEFT 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
|
||||||
|
-- AURORA-1938 / #335: фонд экономии FORM_2 считается, а не читается из transfer_to_economy
|
||||||
|
-- (формулы v_form2_sheet_sections: cp - скорректированный план, aq - факт квартала).
|
||||||
|
CROSS JOIN LATERAL (
|
||||||
|
SELECT
|
||||||
|
(COALESCE(pl.plan_q1,0)+COALESCE(sd.adj_q1,0)+COALESCE(ss.adj_q1,0)+COALESCE(rv.amount_q1,0)+COALESCE(q1.adj_current,0)+COALESCE(q1.adj_ssp,0)+COALESCE(q1.adj_reserve,0)-(COALESCE(q1.actual_m1,0)+COALESCE(q1.actual_m2,0)+COALESCE(q1.actual_m3,0))
|
||||||
|
-(COALESCE(q1.transfer_delay_acts,0)+COALESCE(q1.transfer_delay_procurement,0)+COALESCE(q1.transfer_economy_rf,0))-COALESCE(q1.transfer_to_q3,0)-COALESCE(q1.transfer_to_q4,0)) AS econ_q1,
|
||||||
|
(COALESCE(pl.plan_q2,0)+COALESCE(sd.adj_q2,0)+COALESCE(ss.adj_q2,0)+COALESCE(rv.amount_q2,0)+COALESCE(q1.transfer_to_q2,0)+COALESCE(q2.plan_revision_increase,0)+COALESCE(q2.plan_revision_sequester,0)+COALESCE(q2.base_plan_correction,0)+COALESCE(q2.adj_current,0)+COALESCE(q2.adj_ssp,0)+COALESCE(q2.adj_reserve,0)-(COALESCE(q2.actual_m1,0)+COALESCE(q2.actual_m2,0)+COALESCE(q2.actual_m3,0))
|
||||||
|
-(COALESCE(q2.transfer_delay_acts,0)+COALESCE(q2.transfer_delay_procurement,0)+COALESCE(q2.transfer_economy_rf,0))-COALESCE(q2.transfer_to_q4,0)) AS econ_q2,
|
||||||
|
(COALESCE(pl.plan_q3,0)+COALESCE(sd.adj_q3,0)+COALESCE(ss.adj_q3,0)+COALESCE(rv.amount_q3,0)+COALESCE(q1.transfer_to_q3,0)+COALESCE(q2.transfer_to_q3,0)+COALESCE(q3.plan_revision_increase,0)+COALESCE(q3.plan_revision_sequester,0)+COALESCE(q3.base_plan_correction,0)+COALESCE(q3.adj_current,0)+COALESCE(q3.adj_ssp,0)+COALESCE(q3.adj_reserve,0)-(COALESCE(q3.actual_m1,0)+COALESCE(q3.actual_m2,0)+COALESCE(q3.actual_m3,0))
|
||||||
|
-(COALESCE(q3.transfer_delay_acts,0)+COALESCE(q3.transfer_delay_procurement,0)+COALESCE(q3.transfer_economy_rf,0))) AS econ_q3,
|
||||||
|
(COALESCE(pl.plan_q4,0)+COALESCE(sd.adj_q4,0)+COALESCE(ss.adj_q4,0)+COALESCE(rv.amount_q4,0)+COALESCE(q1.transfer_to_q4,0)+COALESCE(q2.transfer_to_q4,0)+COALESCE(q3.transfer_to_q4,0)+COALESCE(q4.plan_revision_increase,0)+COALESCE(q4.plan_revision_sequester,0)+COALESCE(q4.base_plan_correction,0)+COALESCE(q4.adj_current,0)+COALESCE(q4.adj_ssp,0)+COALESCE(q4.adj_reserve,0)
|
||||||
|
-(COALESCE(q4.actual_m1,0)+COALESCE(q4.actual_m2,0)+COALESCE(q4.actual_m3,0)+COALESCE(q4.actual_spod,0))) AS econ_q4
|
||||||
|
) ec
|
||||||
|
) x
|
||||||
|
ORDER BY x.sort_order;
|
||||||
|
$function$;
|
||||||
|
|
||||||
|
|||||||
256
api/tests/fixtures/svod2_legacy_golden.json
vendored
256
api/tests/fixtures/svod2_legacy_golden.json
vendored
@ -1771,7 +1771,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"RF-admin_all": {
|
"RF-admin_all": {
|
||||||
"sha256": "16f6324ffdbd750f099cd7879ed15e8c968424cf65c9ad9e54ee4b529050ee49",
|
"sha256": "80833aca8a902058e030f77db86e24bd7592816e58dc669d7834abe5bef23cef",
|
||||||
"body": {
|
"body": {
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": null,
|
"message": null,
|
||||||
@ -1780,10 +1780,18 @@
|
|||||||
"row_type": "INPUT",
|
"row_type": "INPUT",
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {},
|
"q1": {
|
||||||
"q2": {},
|
"transfer_to_economy": 300
|
||||||
"q3": {},
|
},
|
||||||
"q4": {},
|
"q2": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
"ckk": {},
|
"ckk": {},
|
||||||
"plan": {
|
"plan": {
|
||||||
"plan_q1": 300,
|
"plan_q1": 300,
|
||||||
@ -1833,13 +1841,19 @@
|
|||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {
|
"q1": {
|
||||||
"booking_amount": 777.25
|
"booking_amount": 777.25,
|
||||||
|
"transfer_to_economy": 0
|
||||||
},
|
},
|
||||||
"q2": {
|
"q2": {
|
||||||
"booking_amount": 5
|
"booking_amount": 5,
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
},
|
},
|
||||||
"q3": {},
|
|
||||||
"q4": {},
|
|
||||||
"ckk": {
|
"ckk": {
|
||||||
"expenses_q1": 777.25,
|
"expenses_q1": 777.25,
|
||||||
"expenses_q2": 5,
|
"expenses_q2": 5,
|
||||||
@ -1884,10 +1898,18 @@
|
|||||||
"row_type": "INPUT",
|
"row_type": "INPUT",
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {},
|
"q1": {
|
||||||
"q2": {},
|
"transfer_to_economy": 42
|
||||||
"q3": {},
|
},
|
||||||
"q4": {},
|
"q2": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
"ckk": {},
|
"ckk": {},
|
||||||
"plan": {
|
"plan": {
|
||||||
"plan_q1": 42,
|
"plan_q1": 42,
|
||||||
@ -1934,10 +1956,18 @@
|
|||||||
"row_type": "INPUT",
|
"row_type": "INPUT",
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {},
|
"q1": {
|
||||||
"q2": {},
|
"transfer_to_economy": 9
|
||||||
"q3": {},
|
},
|
||||||
"q4": {},
|
"q2": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
"ckk": {},
|
"ckk": {},
|
||||||
"plan": {
|
"plan": {
|
||||||
"plan_q1": 9,
|
"plan_q1": 9,
|
||||||
@ -1987,7 +2017,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"RF-admin_one": {
|
"RF-admin_one": {
|
||||||
"sha256": "a463b0b1858f4333b27713987cef3ddfdf9eb207df84122c41f654f58620b504",
|
"sha256": "a9bf8e54d4aef2f7f2fe0e5951d762bb3f2dadc00cd689f3d257aac0465cd5e6",
|
||||||
"body": {
|
"body": {
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": null,
|
"message": null,
|
||||||
@ -1996,10 +2026,18 @@
|
|||||||
"row_type": "INPUT",
|
"row_type": "INPUT",
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {},
|
"q1": {
|
||||||
"q2": {},
|
"transfer_to_economy": 300
|
||||||
"q3": {},
|
},
|
||||||
"q4": {},
|
"q2": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
"ckk": {},
|
"ckk": {},
|
||||||
"plan": {
|
"plan": {
|
||||||
"plan_q1": 300,
|
"plan_q1": 300,
|
||||||
@ -2049,13 +2087,19 @@
|
|||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {
|
"q1": {
|
||||||
"booking_amount": 777.25
|
"booking_amount": 777.25,
|
||||||
|
"transfer_to_economy": 0
|
||||||
},
|
},
|
||||||
"q2": {
|
"q2": {
|
||||||
"booking_amount": 5
|
"booking_amount": 5,
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
},
|
},
|
||||||
"q3": {},
|
|
||||||
"q4": {},
|
|
||||||
"ckk": {
|
"ckk": {
|
||||||
"expenses_q1": 777.25,
|
"expenses_q1": 777.25,
|
||||||
"expenses_q2": 5,
|
"expenses_q2": 5,
|
||||||
@ -2100,10 +2144,18 @@
|
|||||||
"row_type": "INPUT",
|
"row_type": "INPUT",
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {},
|
"q1": {
|
||||||
"q2": {},
|
"transfer_to_economy": 42
|
||||||
"q3": {},
|
},
|
||||||
"q4": {},
|
"q2": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
"ckk": {},
|
"ckk": {},
|
||||||
"plan": {
|
"plan": {
|
||||||
"plan_q1": 42,
|
"plan_q1": 42,
|
||||||
@ -2151,7 +2203,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"RF-admin_page50": {
|
"RF-admin_page50": {
|
||||||
"sha256": "16f6324ffdbd750f099cd7879ed15e8c968424cf65c9ad9e54ee4b529050ee49",
|
"sha256": "80833aca8a902058e030f77db86e24bd7592816e58dc669d7834abe5bef23cef",
|
||||||
"body": {
|
"body": {
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": null,
|
"message": null,
|
||||||
@ -2160,10 +2212,18 @@
|
|||||||
"row_type": "INPUT",
|
"row_type": "INPUT",
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {},
|
"q1": {
|
||||||
"q2": {},
|
"transfer_to_economy": 300
|
||||||
"q3": {},
|
},
|
||||||
"q4": {},
|
"q2": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
"ckk": {},
|
"ckk": {},
|
||||||
"plan": {
|
"plan": {
|
||||||
"plan_q1": 300,
|
"plan_q1": 300,
|
||||||
@ -2213,13 +2273,19 @@
|
|||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {
|
"q1": {
|
||||||
"booking_amount": 777.25
|
"booking_amount": 777.25,
|
||||||
|
"transfer_to_economy": 0
|
||||||
},
|
},
|
||||||
"q2": {
|
"q2": {
|
||||||
"booking_amount": 5
|
"booking_amount": 5,
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
},
|
},
|
||||||
"q3": {},
|
|
||||||
"q4": {},
|
|
||||||
"ckk": {
|
"ckk": {
|
||||||
"expenses_q1": 777.25,
|
"expenses_q1": 777.25,
|
||||||
"expenses_q2": 5,
|
"expenses_q2": 5,
|
||||||
@ -2264,10 +2330,18 @@
|
|||||||
"row_type": "INPUT",
|
"row_type": "INPUT",
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {},
|
"q1": {
|
||||||
"q2": {},
|
"transfer_to_economy": 42
|
||||||
"q3": {},
|
},
|
||||||
"q4": {},
|
"q2": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
"ckk": {},
|
"ckk": {},
|
||||||
"plan": {
|
"plan": {
|
||||||
"plan_q1": 42,
|
"plan_q1": 42,
|
||||||
@ -2314,10 +2388,18 @@
|
|||||||
"row_type": "INPUT",
|
"row_type": "INPUT",
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {},
|
"q1": {
|
||||||
"q2": {},
|
"transfer_to_economy": 9
|
||||||
"q3": {},
|
},
|
||||||
"q4": {},
|
"q2": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
"ckk": {},
|
"ckk": {},
|
||||||
"plan": {
|
"plan": {
|
||||||
"plan_q1": 9,
|
"plan_q1": 9,
|
||||||
@ -2367,7 +2449,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"RF-admin_two": {
|
"RF-admin_two": {
|
||||||
"sha256": "f96f208a936ce1b609f7f940399152353aafc89953052ef9f312a3b7159a468f",
|
"sha256": "d3080fd50d726df99044450b08ecbc2a390b8627883d0cfca3b3f779227bc5b6",
|
||||||
"body": {
|
"body": {
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": null,
|
"message": null,
|
||||||
@ -2376,10 +2458,18 @@
|
|||||||
"row_type": "INPUT",
|
"row_type": "INPUT",
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {},
|
"q1": {
|
||||||
"q2": {},
|
"transfer_to_economy": 300
|
||||||
"q3": {},
|
},
|
||||||
"q4": {},
|
"q2": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
"ckk": {},
|
"ckk": {},
|
||||||
"plan": {
|
"plan": {
|
||||||
"plan_q1": 300,
|
"plan_q1": 300,
|
||||||
@ -2429,13 +2519,19 @@
|
|||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {
|
"q1": {
|
||||||
"booking_amount": 777.25
|
"booking_amount": 777.25,
|
||||||
|
"transfer_to_economy": 0
|
||||||
},
|
},
|
||||||
"q2": {
|
"q2": {
|
||||||
"booking_amount": 5
|
"booking_amount": 5,
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
},
|
},
|
||||||
"q3": {},
|
|
||||||
"q4": {},
|
|
||||||
"ckk": {
|
"ckk": {
|
||||||
"expenses_q1": 777.25,
|
"expenses_q1": 777.25,
|
||||||
"expenses_q2": 5,
|
"expenses_q2": 5,
|
||||||
@ -2481,7 +2577,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"RF-isp_all": {
|
"RF-isp_all": {
|
||||||
"sha256": "a463b0b1858f4333b27713987cef3ddfdf9eb207df84122c41f654f58620b504",
|
"sha256": "a9bf8e54d4aef2f7f2fe0e5951d762bb3f2dadc00cd689f3d257aac0465cd5e6",
|
||||||
"body": {
|
"body": {
|
||||||
"success": true,
|
"success": true,
|
||||||
"message": null,
|
"message": null,
|
||||||
@ -2490,10 +2586,18 @@
|
|||||||
"row_type": "INPUT",
|
"row_type": "INPUT",
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {},
|
"q1": {
|
||||||
"q2": {},
|
"transfer_to_economy": 300
|
||||||
"q3": {},
|
},
|
||||||
"q4": {},
|
"q2": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
"ckk": {},
|
"ckk": {},
|
||||||
"plan": {
|
"plan": {
|
||||||
"plan_q1": 300,
|
"plan_q1": 300,
|
||||||
@ -2543,13 +2647,19 @@
|
|||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {
|
"q1": {
|
||||||
"booking_amount": 777.25
|
"booking_amount": 777.25,
|
||||||
|
"transfer_to_economy": 0
|
||||||
},
|
},
|
||||||
"q2": {
|
"q2": {
|
||||||
"booking_amount": 5
|
"booking_amount": 5,
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
},
|
},
|
||||||
"q3": {},
|
|
||||||
"q4": {},
|
|
||||||
"ckk": {
|
"ckk": {
|
||||||
"expenses_q1": 777.25,
|
"expenses_q1": 777.25,
|
||||||
"expenses_q2": 5,
|
"expenses_q2": 5,
|
||||||
@ -2594,10 +2704,18 @@
|
|||||||
"row_type": "INPUT",
|
"row_type": "INPUT",
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"data": {
|
"data": {
|
||||||
"q1": {},
|
"q1": {
|
||||||
"q2": {},
|
"transfer_to_economy": 42
|
||||||
"q3": {},
|
},
|
||||||
"q4": {},
|
"q2": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"transfer_to_economy": 0
|
||||||
|
},
|
||||||
"ckk": {},
|
"ckk": {},
|
||||||
"plan": {
|
"plan": {
|
||||||
"plan_q1": 42,
|
"plan_q1": 42,
|
||||||
|
|||||||
@ -173,3 +173,62 @@ def test_form2_transfer_econ_cell_is_read_only(client, headers, svod2_sql, colum
|
|||||||
)
|
)
|
||||||
assert r.status_code in (400, 422), r.text
|
assert r.status_code in (400, 422), r.text
|
||||||
assert "computed_field" in r.json()["message"]
|
assert "computed_field" in r.json()["message"]
|
||||||
|
|
||||||
|
|
||||||
|
# --- Свод 2 («РФ» = FORM_2) показывает тот же расчётный фонд экономии, что лист ---
|
||||||
|
|
||||||
|
def _svod2_rf_quarters(svod2_sql, year, line_id):
|
||||||
|
rows = svod2_sql(
|
||||||
|
"SELECT data FROM v3.v_svod2_rf(:y, NULL, NULL, NULL, 'org_name', 'asc', "
|
||||||
|
"NULL, NULL, NULL, NULL, false) WHERE source_line_id = :l",
|
||||||
|
{"y": year, "l": line_id},
|
||||||
|
)
|
||||||
|
assert len(rows) == 1
|
||||||
|
data = rows[0][0]
|
||||||
|
return [data[q].get("transfer_to_economy") for q in ("q1", "q2", "q3", "q4")]
|
||||||
|
|
||||||
|
|
||||||
|
def _sheet_econ(client, headers, form_id, sheet, line_id):
|
||||||
|
d = _input(_rows(client, headers, form_id, sheet), line_id)
|
||||||
|
return [d[q].get("transfer_econ") for q in ("q1", "q2", "q3", "q4")]
|
||||||
|
|
||||||
|
|
||||||
|
def test_svod2_rf_transfer_econ_ticket_repro(client, headers, svod2_sql):
|
||||||
|
form_id = _new_form(client, headers, 91030)
|
||||||
|
line_id = _add_line(client, headers, form_id, "AHR", _leaf_items(svod2_sql, "AHR", 1)[0])
|
||||||
|
for col, val in [("plan.q1", 1000), ("plan.q2", 2000), ("plan.q3", 3000)]:
|
||||||
|
_set(client, headers, form_id, "AHR", line_id, col, val)
|
||||||
|
|
||||||
|
assert _svod2_rf_quarters(svod2_sql, 91030, line_id) == [1000, 2000, 3000, 0]
|
||||||
|
assert _svod2_rf_quarters(svod2_sql, 91030, line_id) == _sheet_econ(client, headers, form_id, "AHR", line_id)
|
||||||
|
|
||||||
|
|
||||||
|
def test_svod2_rf_transfer_econ_subcolumns_match_sheet(client, headers, svod2_sql):
|
||||||
|
form_id = _new_form(client, headers, 91031)
|
||||||
|
line_id = _add_line(client, headers, form_id, "AHR", _leaf_items(svod2_sql, "AHR", 1)[0])
|
||||||
|
for col, val in [
|
||||||
|
("plan.q1", 1000), ("plan.q2", 2000), ("plan.q3", 3000),
|
||||||
|
("q1.transfer_q2_delay_acts", 100), ("q1.transfer_q3", 200), ("q1.transfer_q4", 300),
|
||||||
|
("q2.transfer_q3_delay_acts", 400), ("q2.transfer_q4", 500),
|
||||||
|
("q3.transfer_q4_delay_acts", 600),
|
||||||
|
]:
|
||||||
|
_set(client, headers, form_id, "AHR", line_id, col, val)
|
||||||
|
|
||||||
|
assert _svod2_rf_quarters(svod2_sql, 91031, line_id) == [400, 1100, 2600, 800]
|
||||||
|
assert _svod2_rf_quarters(svod2_sql, 91031, line_id) == _sheet_econ(client, headers, form_id, "AHR", line_id)
|
||||||
|
|
||||||
|
|
||||||
|
def test_svod2_rf_ignores_raw_transfer_to_economy(client, headers, svod2_sql):
|
||||||
|
form_id = _new_form(client, headers, 91032)
|
||||||
|
line_id = _add_line(client, headers, form_id, "AHR", _leaf_items(svod2_sql, "AHR", 1)[0])
|
||||||
|
for col, val in [("plan.q1", 1000), ("plan.q2", 2000), ("plan.q3", 3000)]:
|
||||||
|
_set(client, headers, form_id, "AHR", line_id, col, val)
|
||||||
|
for quarter in (1, 2, 3, 4):
|
||||||
|
svod2_sql(
|
||||||
|
"INSERT INTO v3.budget_line_quarter (line_id, quarter, transfer_to_economy) "
|
||||||
|
"VALUES (:l, :q, 777) ON CONFLICT (line_id, quarter) "
|
||||||
|
"DO UPDATE SET transfer_to_economy = 777",
|
||||||
|
{"l": line_id, "q": quarter},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert _svod2_rf_quarters(svod2_sql, 91032, line_id) == [1000, 2000, 3000, 0]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user