Print code lists with the separator the reference report uses

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.
This commit is contained in:
Raykov-MS 2026-09-29 18:07:17 +03:00
parent cceee02243
commit 69fd329f78
2 changed files with 49 additions and 0 deletions

View File

@ -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],

View File

@ -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"