From 69fd329f78c73dd15b36b8b449c5a188a3fe5d62 Mon Sep 17 00:00:00 2001 From: Raykov-MS Date: Tue, 29 Sep 2026 18:07:17 +0300 Subject: [PATCH] Print code lists with the separator the reference report uses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verified our report against the Комита reference export by joining on the record id. Our report_20260923_5.xlsx covers the 114 files of 30.01.2023 and all 5266 of its records are inside the reference period, so the two can be compared row by row. Fifteen of the twenty-one shared columns already match exactly. The largest remaining gap was the separator in the code lists: the reference prints "1101,1106,1499" while the parser joins repeated tags with "; ", which put 336 of 5266 records out of step. Only the two code-list columns are brought to the reference's separator; "; " stays in the free-text columns, where it reads better and where the reference has no equivalent. What the comparison also showed, for the record: - The empty branch БИК and number on head-office records are correct. Those files carry no ИнфФилиал block at all and the reference leaves the cells empty too. - Of the 105 address differences, 94 are the column 141 leak fixed in cceee02, and the remaining 11 are values that contain a comma, such as Пункт = "Южно-Сахалинск г, Хомутово пл.р-н", which the reference cannot represent in one comma-joined cell. - Column 121 shows РегнНомер for people in private practice, where the reference's ОГРН column stays empty. That is the mapping table's fourth source for the column, not a defect: 3 records out of 13168. --- app/pipeline/mapping.py | 19 +++++++++++++++++++ tests/unit/test_mapping.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/app/pipeline/mapping.py b/app/pipeline/mapping.py index c4b4567..e21e1a9 100644 --- a/app/pipeline/mapping.py +++ b/app/pipeline/mapping.py @@ -41,6 +41,7 @@ from .column_constants import ( COL_RESIDENT_SIGN, COL_STAY_DOCUMENT_TYPE, COL_TRANSFER_TYPE, + COL_UNUSUAL_CODES, EMPLOYEE_ABSENT_CODE, EXPORT_SUBSIDIARY_COMMENT_CODES, PARTICIPANT_ADDRESS_COMPONENT_COLUMNS, @@ -855,6 +856,7 @@ def _apply_business_rules( # которые обнуляли колонку, если код операции, вид перевода или тип # участника не входил в разрешённый список, убраны — они выбрасывали # данные, реально присутствующие в файле. + _rule_code_list_separator(row) _rule_extra_info(row, codes, operation_lookup, participant_lookup) _rule_payer_account(row, transfer_type, codes) _rule_correspondent_accounts(row, operator_type, transfer_type, codes) @@ -870,6 +872,23 @@ def _apply_business_rules( _clear_columns(row, BLOCK_CP) +# Перечисления кодов эталонный отчёт АРМ «Комита» печатает через запятую без +# пробела ("1101,1106,1499"), а парсер склеивает повторяющиеся теги через +# "; " (см. _append_value в parser.py). Приводим к виду эталона только +# колонки-перечисления кодов: в текстовых полях "; " читается лучше. +_CODE_LIST_COLUMNS = (COL_EXTRA_CODES, COL_UNUSUAL_CODES) +_CODE_LIST_SEPARATOR = "," + + +def _rule_code_list_separator(row: dict[int, str]) -> None: + for column in _CODE_LIST_COLUMNS: + value = _get(row, column) + if "; " not in value: + continue + codes = [part.strip() for part in value.split(";") if part.strip()] + _set(row, column, _CODE_LIST_SEPARATOR.join(codes)) + + def _rule_extra_info( row: dict[int, str], codes: set[str], diff --git a/tests/unit/test_mapping.py b/tests/unit/test_mapping.py index b988c42..e4a4228 100644 --- a/tests/unit/test_mapping.py +++ b/tests/unit/test_mapping.py @@ -1968,3 +1968,33 @@ def test_col96_territory_code_card_belongs_to_foreign_card_group() -> None: groups = COLUMNS.report_groups() foreign_card_group = next(g for g in groups if g.start_index <= 97 <= g.end_index) assert foreign_card_group.start_index == 96 + + +def test_code_list_columns_use_reference_separator() -> None: + """Перечисления кодов должны совпадать с эталонным отчётом АРМ «Комита» + дословно: он печатает их через запятую без пробела, а парсер склеивает + повторяющиеся теги через "; " (см. _append_value в parser.py). На сверке + за 30.01.2023 это давало расхождение в 336 записях из 5266.""" + row = build_fixed_row_by_index( + file_name="f.xml", + record_id="R1", + operation_index=1, + operation_fields={ + "ДопКодОперации": "1; 2", + "ПризнНеобОперации": "1101; 1106; 1499", + }, + participant_fields={}, + ) + assert row[20] == "1,2" + assert row[21] == "1101,1106,1499" + + +def test_code_list_with_single_value_is_untouched() -> None: + row = build_fixed_row_by_index( + file_name="f.xml", + record_id="R1", + operation_index=1, + operation_fields={"ПризнНеобОперации": "1101"}, + participant_fields={}, + ) + assert row[21] == "1101"