diff --git a/api/src/services/export_service/export_mappings.py b/api/src/services/export_service/export_mappings.py index 98344c7..2398a18 100644 --- a/api/src/services/export_service/export_mappings.py +++ b/api/src/services/export_service/export_mappings.py @@ -49,19 +49,19 @@ FORM1_DEPTH_COLUMNS: dict = { "key": None, "children": { "plan": { - "name": "План 2024(тыс. руб.) с учетом НДС", + "name": "План {year}(тыс. руб.) с учетом НДС", "children": { "q1": { - "name": "1 кв. 24", + "name": "1 кв. {year_short}", }, "q2": { - "name": "2 кв. 24", + "name": "2 кв. {year_short}", }, "q3": { - "name": "3 кв. 24", + "name": "3 кв. {year_short}", }, "q4": { - "name": "4 кв. 24", + "name": "4 кв. {year_short}", }, "year": { "name": "Год", @@ -88,7 +88,7 @@ FORM1_DEPTH_COLUMNS: dict = { "name": "Комментарии", }, "future_y1": { - "name": "Платежи в 2025 году", + "name": "Платежи в {next_year} году", }, "other_ssp": { "name": "Сумма в других ССП", @@ -116,16 +116,16 @@ FORM1_DEPTH_COLUMNS: dict = { "key": None, "children": { "q1": { - "name": "1 кв. 24", + "name": "1 кв. {year_short}", }, "q2": { - "name": "2 кв. 24", + "name": "2 кв. {year_short}", }, "q3": { - "name": "3 кв. 24", + "name": "3 кв. {year_short}", }, "q4": { - "name": "4 кв. 24", + "name": "4 кв. {year_short}", }, "year": { "name": "Год", @@ -145,16 +145,16 @@ FORM1_DEPTH_COLUMNS: dict = { "key": None, "children": { "q1": { - "name": "1 кв. 24", + "name": "1 кв. {year_short}", }, "q2": { - "name": "2 кв. 24", + "name": "2 кв. {year_short}", }, "q3": { - "name": "3 кв. 24", + "name": "3 кв. {year_short}", }, "q4": { - "name": "4 кв. 24", + "name": "4 кв. {year_short}", }, "year": { "name": "Год", @@ -174,16 +174,16 @@ FORM1_DEPTH_COLUMNS: dict = { "key": None, "children": { "q1": { - "name": "1 кв. 24", + "name": "1 кв. {year_short}", }, "q2": { - "name": "2 кв. 24", + "name": "2 кв. {year_short}", }, "q3": { - "name": "3 кв. 24", + "name": "3 кв. {year_short}", }, "q4": { - "name": "4 кв. 24", + "name": "4 кв. {year_short}", }, "year": { "name": "Год", @@ -220,16 +220,16 @@ FORM1_DEPTH_COLUMNS: dict = { "name": "Предельная ст-ть, тыс. руб. (с учетом НДC)", }, "q1": { - "name": "Расходы 1 кв. 2024 г. тыс. руб. (с учетом НДC)", + "name": "Расходы 1 кв. {year} г. тыс. руб. (с учетом НДC)", }, "q2": { - "name": "Расходы 2 кв. 2024 г. тыс. руб. (с учетом НДC)", + "name": "Расходы 2 кв. {year} г. тыс. руб. (с учетом НДC)", }, "q3": { - "name": "Расходы 3 кв. 2024 г. тыс. руб. (с учетом НДC)", + "name": "Расходы 3 кв. {year} г. тыс. руб. (с учетом НДC)", }, "q4": { - "name": "Расходы 4 кв. 2024 г. тыс. руб. (с учетом НДC)", + "name": "Расходы 4 кв. {year} г. тыс. руб. (с учетом НДC)", }, "rf_schedule": { "name": "по сметам РФ (1 кв, 2 кв, 3 кв, 4 кв)", @@ -270,16 +270,16 @@ FORM1_DEPTH_COLUMNS: dict = { "name": "Предельная ст-ть, тыс. руб. (с учетом НДC)", }, "q1": { - "name": "Расходы 1 кв. 2024 г. тыс. руб. (с учетом НДC)", + "name": "Расходы 1 кв. {year} г. тыс. руб. (с учетом НДC)", }, "q2": { - "name": "Расходы 2 кв. 2024 г. тыс. руб. (с учетом НДC)", + "name": "Расходы 2 кв. {year} г. тыс. руб. (с учетом НДC)", }, "q3": { - "name": "Расходы 3 кв. 2024 г. тыс. руб. (с учетом НДC)", + "name": "Расходы 3 кв. {year} г. тыс. руб. (с учетом НДC)", }, "q4": { - "name": "Расходы 4 кв. 2024 г. тыс. руб. (с учетом НДC)", + "name": "Расходы 4 кв. {year} г. тыс. руб. (с учетом НДC)", }, "rf_schedule": { "name": "по сметам РФ (1 кв, 2 кв, 3 кв, 4 кв)", @@ -314,7 +314,7 @@ FORM1_DEPTH_COLUMNS: dict = { "q1": { - "name": "1 квартал 2024", + "name": "1 квартал {year}", "children": { "cur_correct": { "name": "Текущие корректировки( = 0)", @@ -353,7 +353,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "shift": { - "name": "Перенос во 2 кв 24", + "name": "Перенос во 2 кв {year_short}", "key": None, "children": { "sum": { @@ -371,7 +371,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "plan_correct": { - "name": "Скорр. план 1 кв. 24", + "name": "Скорр. план 1 кв. {year_short}", "key": None, "children": { "corrected_plan": { @@ -410,7 +410,7 @@ FORM1_DEPTH_COLUMNS: dict = { # "name": "", # }, "booking_correct": { - "name": "Бронь 1 кв 24", + "name": "Бронь 1 кв {year_short}", "key": None, "children": { "booking": { @@ -419,7 +419,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "m1_correct": { - "name": "Факт РСБУ Январь 24", + "name": "Факт РСБУ Январь {year_short}", "key": None, "children": { "actual_m1": { @@ -428,7 +428,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "m2_correct": { - "name": "Факт РСБУ Февраль 24", + "name": "Факт РСБУ Февраль {year_short}", "key": None, "children": { "actual_m2": { @@ -437,7 +437,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "m3_correct": { - "name": "Факт РСБУ Март 24", + "name": "Факт РСБУ Март {year_short}", "key": None, "children": { "actual_m3": { @@ -446,7 +446,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "quarter_correct": { - "name": "Факт РСБУ 1 кв 24", + "name": "Факт РСБУ 1 кв {year_short}", "key": None, "children": { "actual_quarter": { @@ -455,7 +455,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "rem_correct": { - "name": "Остаток после брони 1 кв. 24", + "name": "Остаток после брони 1 кв. {year_short}", "key": None, "children": { "rem_booking": { @@ -464,7 +464,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "rem_actual_correct": { - "name": "Остаток после факта 1 кв. 24", + "name": "Остаток после факта 1 кв. {year_short}", "key": None, "children": { "rem_actual": { @@ -477,13 +477,13 @@ FORM1_DEPTH_COLUMNS: dict = { "key": None, "children": { "transfer_q2": { - "name": "Перенос во 2 кв.24" + "name": "Перенос во 2 кв.{year_short}" }, "transfer_q3": { - "name": "Перенос в 3 кв.24" + "name": "Перенос в 3 кв.{year_short}" }, "transfer_q4": { - "name": "Перенос в 4 кв.24" + "name": "Перенос в 4 кв.{year_short}" }, "economy": { "name": "Перенос в фонд экономии" @@ -498,7 +498,7 @@ FORM1_DEPTH_COLUMNS: dict = { }, "q2": { - "name": "2 квартал 2024", + "name": "2 квартал {year}", "children": { "rev_eco_correct": { "name": "Изменение целевого назначения перенесенной экономии ( =0)", @@ -546,7 +546,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "new_plan_correct": { - "name": "Новый план 2 кв 24", + "name": "Новый план 2 кв {year_short}", "key": None, "children": { "new_plan": { @@ -596,7 +596,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "shift": { - "name": "Перенос в 3 кв 24", + "name": "Перенос в 3 кв {year_short}", "key": None, "children": { "sum": { @@ -605,7 +605,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "plan_correct": { - "name": "Скорр. план 2 кв. 24", + "name": "Скорр. план 2 кв. {year_short}", "key": None, "children": { "corrected_plan": { @@ -641,7 +641,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "booking_correct": { - "name": "Бронь 2 кв 24", + "name": "Бронь 2 кв {year_short}", "key": None, "children": { "booking": { @@ -650,7 +650,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "m1_correct": { - "name": "Факт РСБУ Апрель 24", + "name": "Факт РСБУ Апрель {year_short}", "key": None, "children": { "actual_m1": { @@ -659,7 +659,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "m2_correct": { - "name": "Факт РСБУ Май 24", + "name": "Факт РСБУ Май {year_short}", "key": None, "children": { "actual_m2": { @@ -668,7 +668,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "m3_correct": { - "name": "Факт РСБУ Июнь 24", + "name": "Факт РСБУ Июнь {year_short}", "key": None, "children": { "actual_m3": { @@ -677,7 +677,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "quarter_correct": { - "name": "Факт РСБУ 2 кв 24", + "name": "Факт РСБУ 2 кв {year_short}", "key": None, "children": { "actual_quarter": { @@ -686,7 +686,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "rem_correct": { - "name": "Остаток после брони 2 кв. 24", + "name": "Остаток после брони 2 кв. {year_short}", "key": None, "children": { "rem_booking": { @@ -695,7 +695,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "rem_actual_correct": { - "name": "Остаток после факта 2 кв. 24", + "name": "Остаток после факта 2 кв. {year_short}", "key": None, "children": { "rem_actual": { @@ -708,10 +708,10 @@ FORM1_DEPTH_COLUMNS: dict = { "key": None, "children": { "transfer_q3": { - "name": "Перенос в 3 кв.24" + "name": "Перенос в 3 кв.{year_short}" }, "transfer_q4": { - "name": "Перенос в 4 кв.24" + "name": "Перенос в 4 кв.{year_short}" }, "economy": { "name": "Перенос в фонд экономии" @@ -725,7 +725,7 @@ FORM1_DEPTH_COLUMNS: dict = { }, "q3": { - "name": "3 квартал 2024", + "name": "3 квартал {year}", "children": { "rev_eco_correct": { "name": "Изменение целевого назначения перенесенной экономии ( =0)", @@ -773,7 +773,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "new_plan_correct": { - "name": "Новый план 3 кв 24", + "name": "Новый план 3 кв {year_short}", "key": None, "children": { "new_plan": { @@ -823,7 +823,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "shift": { - "name": "Перенос в 4 кв 24", + "name": "Перенос в 4 кв {year_short}", "key": None, "children": { "sum": { @@ -832,7 +832,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "plan_correct": { - "name": "Скорр. план 3 кв. 24", + "name": "Скорр. план 3 кв. {year_short}", "key": None, "children": { "corrected_plan": { @@ -868,7 +868,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "booking_correct": { - "name": "Бронь 3 кв 24", + "name": "Бронь 3 кв {year_short}", "key": None, "children": { "booking": { @@ -877,7 +877,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "m1_correct": { - "name": "Факт РСБУ июль 24", + "name": "Факт РСБУ июль {year_short}", "key": None, "children": { "actual_m1": { @@ -886,7 +886,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "m2_correct": { - "name": "Факт РСБУ август 24", + "name": "Факт РСБУ август {year_short}", "key": None, "children": { "actual_m2": { @@ -895,7 +895,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "m3_correct": { - "name": "Факт РСБУ сентябрь 24", + "name": "Факт РСБУ сентябрь {year_short}", "key": None, "children": { "actual_m3": { @@ -904,7 +904,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "quarter_correct": { - "name": "Факт РСБУ 3 кв 24", + "name": "Факт РСБУ 3 кв {year_short}", "key": None, "children": { "actual_quarter": { @@ -913,7 +913,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "rem_correct": { - "name": "Остаток после брони 3 кв. 24", + "name": "Остаток после брони 3 кв. {year_short}", "key": None, "children": { "rem_booking": { @@ -922,7 +922,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "rem_actual_correct": { - "name": "Остаток после факта 3 кв. 24", + "name": "Остаток после факта 3 кв. {year_short}", "key": None, "children": { "rem_actual": { @@ -935,7 +935,7 @@ FORM1_DEPTH_COLUMNS: dict = { "key": None, "children": { "transfer_q4": { - "name": "Перенос в 4 кв.24" + "name": "Перенос в 4 кв.{year_short}" }, "economy": { "name": "Перенос в фонд экономии" @@ -949,7 +949,7 @@ FORM1_DEPTH_COLUMNS: dict = { }, "q4": { - "name": "4 квартал 2024", + "name": "4 квартал {year}", "children": { "rev_eco_correct": { "name": "Изменение целевого назначения перенесенной экономии ( =0)", @@ -1000,7 +1000,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "new_plan_correct": { - "name": "Новый план 4 кв 24", + "name": "Новый план 4 кв {year_short}", "key": None, "children": { "new_plan": { @@ -1050,7 +1050,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "plan_correct": { - "name": "Скорр. план 4 кв. 24", + "name": "Скорр. план 4 кв. {year_short}", "key": None, "children": { "corrected_plan": { @@ -1086,7 +1086,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "booking_correct": { - "name": "Бронь 4 кв 24", + "name": "Бронь 4 кв {year_short}", "key": None, "children": { "booking": { @@ -1095,7 +1095,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "m1_correct": { - "name": "Факт РСБУ октябрь 24", + "name": "Факт РСБУ октябрь {year_short}", "key": None, "children": { "actual_m1": { @@ -1104,7 +1104,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "m2_correct": { - "name": "Факт РСБУ ноябрь 24", + "name": "Факт РСБУ ноябрь {year_short}", "key": None, "children": { "actual_m2": { @@ -1113,7 +1113,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "m3_correct": { - "name": "Факт РСБУ декабрь 24", + "name": "Факт РСБУ декабрь {year_short}", "key": None, "children": { "actual_m3": { @@ -1122,7 +1122,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "quarter_correct": { - "name": "Факт РСБУ 3 кв 24", + "name": "Факт РСБУ 3 кв {year_short}", "key": None, "children": { "actual_quarter": { @@ -1140,7 +1140,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "rem_correct": { - "name": "Остаток после брони 4 кв. 24", + "name": "Остаток после брони 4 кв. {year_short}", "key": None, "children": { "rem_booking": { @@ -1149,7 +1149,7 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "rem_actual_correct": { - "name": "Остаток после факта 4 кв. 24", + "name": "Остаток после факта 4 кв. {year_short}", "key": None, "children": { "rem_actual": { @@ -1172,10 +1172,10 @@ FORM1_DEPTH_COLUMNS: dict = { } }, "totals": { - "name": "Факт 24", + "name": "Факт {year_short}", "children": { "fact_year": { - "name": "Факт 24", + "name": "Факт {year_short}", }, # "empty": { # "name": "", @@ -1230,7 +1230,7 @@ FORM2_DEPTH_AHR_SUB_COLUMNS: dict = { }, "plan": { # "key": None, - "name": "Планируемая сумма расходов на 2026 год", + "name": "Планируемая сумма расходов на {next_year} год", "children": { "q1": { "name": "I квартал" @@ -1251,7 +1251,7 @@ FORM2_DEPTH_AHR_SUB_COLUMNS: dict = { }, "fact_q1": { # "key": None, - "name": "Фактические расходы за I кв 2026 года", + "name": "Фактические расходы за I кв {next_year} года", "children": { "up_jan": { "key": None, @@ -3326,7 +3326,7 @@ def _patch_form4_contract_summary_columns() -> None: summary_parent = FORM4_DEPTH_COLUMNS["upper_ssp_smeta"]["children"]["contract_summary"] summary = summary_parent["children"] summary["reference"] = {"name": "Реквизиты договора"} - summary["future_y2"] = {"name": "Платежи в 2026 году"} + summary["future_y2"] = {"name": "Платежи в {next_year} году"} summary["centralized_flag"] = {"name": "Централизованный договор"} summary_parent["children"] = _reorder_children( summary, @@ -3338,7 +3338,7 @@ def _patch_form4_contract_summary_columns() -> None: structure_summary_parent = FORM4_STRUCTURE_DEPTH_COLUMNS["upper_ssp_smeta"]["children"]["contract_summary"] structure_summary = structure_summary_parent["children"] - structure_summary["future_payments_y2"] = {"name": "Платежи в 2026 году"} + structure_summary["future_payments_y2"] = {"name": "Платежи в {next_year} году"} structure_summary_parent["children"] = _reorder_children( structure_summary, ( @@ -3985,3 +3985,26 @@ def build_summary2_columns(sheet: str) -> dict: } columns.update(_quarter_columns()) return columns + + +def _replace_column_year_placeholders(columns: dict, year_values: dict[str, str]) -> None: + for column in columns.values(): + if "name" in column: + for placeholder, value in year_values.items(): + column["name"] = column["name"].replace("{" + placeholder + "}", value) + if "children" in column: + _replace_column_year_placeholders(column["children"], year_values) + + +def render_column_years(columns: dict, year: int) -> dict: + """Resolve year placeholders in header names without changing shared templates.""" + rendered = copy.deepcopy(columns) + values = { + "year": str(year), + "year_short": f"{year % 100:02d}", + "next_year": str(year + 1), + "next_year_short": f"{(year + 1) % 100:02d}", + } + + _replace_column_year_placeholders(rendered, values) + return rendered diff --git a/api/src/services/export_service/export_service.py b/api/src/services/export_service/export_service.py index fe0a638..00fe243 100644 --- a/api/src/services/export_service/export_service.py +++ b/api/src/services/export_service/export_service.py @@ -47,6 +47,7 @@ from src.services.export_service.export_mappings import ( SMETA_COLUMNS, build_summary1_columns, build_summary2_columns, + render_column_years, ) from src.services.export_service.export_writers import ( DepthSheetWriter, @@ -419,7 +420,7 @@ class ExportService: }, ) self._write_xlsxwriter_metadata(workbook.add_worksheet("metadata"), form) - sheet_writers = self._create_xlsxwriter_sheet_writers(workbook, form.form_type.code) + sheet_writers = self._create_xlsxwriter_sheet_writers(workbook, form.form_type.code, form.year) exported_sheets = 0 for plan in plans: if not plan.validation_direction and plan.sheet_name in SKIP_SHEETS: @@ -713,7 +714,7 @@ class ExportService: ) writer = XlsxDepthSheetWriter( workbook=workbook, - columns_dict=columns, + columns_dict=render_column_years(columns, year), row_normalizer=( self._identity_row if summary_number == 2 and sheet == "GO" @@ -899,11 +900,12 @@ class ExportService: def _create_xlsxwriter_sheet_writers( self, workbook: XlsxWorkbook, - form_type_code: str | None = None, + form_type_code: str | None, + year: int, ) -> dict[str, Any]: default_writer = XlsxDepthSheetWriter( workbook=workbook, - columns_dict=FORM1_DEPTH_COLUMNS, + columns_dict=render_column_years(FORM1_DEPTH_COLUMNS, year), row_normalizer=self.form1_row_normalizer.normalize, value_serializer=self.value_serializer.to_excel_value, ) @@ -936,7 +938,7 @@ class ExportService: for sheet_name, (columns, colors) in writer_configs.items(): writers[sheet_name] = XlsxDepthSheetWriter( workbook=workbook, - columns_dict=columns, + columns_dict=render_column_years(columns, year), row_normalizer=self.form1_row_normalizer.normalize, value_serializer=self.value_serializer.to_excel_value, colors_config=colors,