From 6229fe7814b2f96f3c2f44517517b434fb5241eb Mon Sep 17 00:00:00 2001 From: Raykov-MS Date: Tue, 29 Sep 2026 19:41:50 +0300 Subject: [PATCH] Match the reference export on the card number and document prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compared our report against the customer's own new-format export for 10.08.2026 (121 columns) over the 124 source files that produced it. Records and participant rows line up exactly: 11393 records and 22839 rows on both sides, no record with a different participant count. 90 of the 104 comparable columns already matched value for value. Two differences were ours to fix: - Column 102, the card number in the foreign bank card block, took its value from СведенияВнесениеПолучениеНалДС/НомерКарта whenever the foreign card block was missing, because short lookup matches the tag НомерКарта in both blocks. The reference leaves the column empty there and shows the number in column 81 only, which is what we now do. 63 records on this export. - The operation-document aggregate numbered its entries "1. ", the reference uses "1, ". That was 11377 rows out of 11393. The remaining differences are the reference's own presentation of aggregate cells and need the customer's word before touching them: it joins ФИО with ", " and keeps a trailing comma for a missing patronymic, spells the document that proves identity as labelled lines ("Вид документа: 21\nСерия…") where we use a comma list, and inserts the name of the region decoded from the ОКАТО code into address cells, which the schema does not carry at all. Two columns the reference fills and our form has no place for: the reporting bank's own registration number, БИК and ОКАТО, and the authorised officer's name, position, phone and e-mail. Both come from ИнфБанк and СлужЧасть. --- app/pipeline/mapping.py | 5 ++++- app/pipeline/mapping_table.json | 2 +- tests/unit/test_mapping.py | 34 ++++++++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/app/pipeline/mapping.py b/app/pipeline/mapping.py index e21e1a9..e549c29 100644 --- a/app/pipeline/mapping.py +++ b/app/pipeline/mapping.py @@ -693,7 +693,10 @@ def _format_operation_documents(lookup: _PayloadLookup) -> str: document.get(field_name, "") for field_name in _OPERATION_DOCUMENT_FIELDS ] fields.insert(1, "") - formatted_documents.append(f"{position}. {', '.join(fields)};") + # Эталонный отчёт отделяет номер документа запятой, а не точкой: + # "1, 13, , , 05/08/2026, ...". Расхождение затрагивало почти каждую + # строку отчёта, поэтому приводим к виду эталона. + formatted_documents.append(f"{position}, {', '.join(fields)};") return "\n".join(formatted_documents) diff --git a/app/pipeline/mapping_table.json b/app/pipeline/mapping_table.json index fdb481d..e1cdb92 100644 --- a/app/pipeline/mapping_table.json +++ b/app/pipeline/mapping_table.json @@ -2028,7 +2028,7 @@ "xml_tag": "НомерКарта", "xml_path": "СообщОперКО/ИнформЧасть/СведКО/Операция/СведенияКартаИнБанк/НомерКарта", "source_scope": "any", - "allow_short_lookup": true, + "allow_short_lookup": false, "allow_direct_mapping": true, "structured_value": false, "structured_group": "", diff --git a/tests/unit/test_mapping.py b/tests/unit/test_mapping.py index e4a4228..1f157cf 100644 --- a/tests/unit/test_mapping.py +++ b/tests/unit/test_mapping.py @@ -933,9 +933,9 @@ def test_operation_documents_keep_positions_and_join_multiple_documents() -> Non ) assert row[107] == ( - "1. 13, , , 29/01/2026, 253, Размещение денежных средств;\n" - "2. 99, , Депозитный договор, 29/01/2026, Р202307/0001/93/Э, ;\n" - "3. 99, , Общие условия размещения депозитов, 17/11/2020, Р202307/0001, ;" + "1, 13, , , 29/01/2026, 253, Размещение денежных средств;\n" + "2, 99, , Депозитный договор, 29/01/2026, Р202307/0001/93/Э, ;\n" + "3, 99, , Общие условия размещения депозитов, 17/11/2020, Р202307/0001, ;" ) @@ -1998,3 +1998,31 @@ def test_code_list_with_single_value_is_untouched() -> None: participant_fields={}, ) assert row[21] == "1101" + + +def test_card_number_stays_in_its_own_block() -> None: + """Тег НомерКарта есть и в блоке внесения/получения наличных (колонка 81), + и в блоке карты иностранного банка (колонка 102). Короткий поиск по имени + тега уводил карту из первого блока во второй: на сверке с эталоном за + 10.08.2026 это давало 63 лишних значения в колонке 102.""" + own_account = build_fixed_row_by_index( + file_name="f.xml", + record_id="R1", + operation_index=1, + operation_fields={ + "СведенияВнесениеПолучениеНалДС.НомерКарта": "2200380368847984" + }, + participant_fields={}, + ) + assert own_account[81] == "2200380368847984" + assert own_account[102] == "" + + foreign_card = build_fixed_row_by_index( + file_name="f.xml", + record_id="R2", + operation_index=1, + operation_fields={"СведенияКартаИнБанк.НомерКарта": "5555444433332222"}, + participant_fields={}, + ) + assert foreign_card[102] == "5555444433332222" + assert foreign_card[81] == ""