From ce776f6ab73711a680807645f1928696b9e3076c Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Tue, 13 Oct 2026 15:50:10 +0400 Subject: [PATCH] =?UTF-8?q?=D0=A2=D0=B5=D1=81=D1=82=D1=8B=20=D1=81=D0=B8?= =?UTF-8?q?=D0=BD=D1=82=D0=B5=D1=82=D0=B8=D0=BA=D0=B8:=20s28=20=E2=80=94?= =?UTF-8?q?=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B0=2013=20=D0=B2=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B5=D0=B4=D1=83=D0=BF=D1=80=D0=B5=D0=B6=D0=B4=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B8=20=D0=B8=20=D0=BE=D1=81=D1=82=D0=B0=D1=91?= =?UTF-8?q?=D1=82=D1=81=D1=8F=20COUNTERPARTY=20=D0=B1=D0=B5=D0=B7=20=D0=98?= =?UTF-8?q?=D0=9D=D0=9D;=20=D0=BF=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D1=88=D0=B0=D0=BF=D0=BA=D0=B0=20generate.?= =?UTF-8?q?py=20(H.3,=20T5.2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- api/tests/synthetic/generate.py | 9 ++++----- api/tests/synthetic/test_synthetic_files.py | 8 ++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/api/tests/synthetic/generate.py b/api/tests/synthetic/generate.py index b8cfa99..74d1d02 100644 --- a/api/tests/synthetic/generate.py +++ b/api/tests/synthetic/generate.py @@ -2,10 +2,9 @@ Файлы s01…s13 — по одному сценарию спеки `osv-parsing` на файл, s14…s16 — записи словарей, которых нет в реальных ОСВ (R-22), s17…s19 — ИНН в тексте названия, ИНН строкой выше и «ИНН/КПП» в одной ячейке (issue #9), s20…s27 — восемь -раскладок строки ИНН, s28 — ИНН с неверной контрольной суммой (#35); описание — -`osv/synthetic/README.md` в репозитории fixtures. Генератор самодостаточен (openpyxl + -`xlsb_writer`) и детерминирован: повторный запуск даёт те же байты — метки времени книги и zip постоянны, порядок -записи фиксирован. +раскладок строки ИНН, s28 — ИНН с неверной контрольной суммой (#35); описание — `osv/synthetic/README.md` в репозитории +fixtures. Генератор самодостаточен (openpyxl + `xlsb_writer`) и детерминирован: повторный запуск даёт те же байты — +метки времени книги и zip постоянны, порядок записи фиксирован. Суммы арифметически согласованы по построению: у листа дерева сальдо на конец вычисляется из начала и оборотов, у родителя — сумма детей по колонкам; поэтому все файлы, кроме `s10_broken_sum`, сходятся по §1.4. Позиции колонок и @@ -660,7 +659,7 @@ def inn_rows_tree(node: Node, layout: InnLayout, *, sums: bool) -> Node: Колонки ИНН нет, в названии ИНН не пишется.""" kids: list[Node] = [] for kid in node.kids: - kid = inn_rows_tree(kid, layout, sums=sums) # noqa: PLW2901 - узел заменяется своей копией с строками ИНН + kid = inn_rows_tree(kid, layout, sums=sums) # noqa: PLW2901 - узел заменяется своей копией со строками ИНН if kid.inn is None or kid.indicator: kids.append(kid) continue diff --git a/api/tests/synthetic/test_synthetic_files.py b/api/tests/synthetic/test_synthetic_files.py index ab5695f..e76c92e 100644 --- a/api/tests/synthetic/test_synthetic_files.py +++ b/api/tests/synthetic/test_synthetic_files.py @@ -37,6 +37,7 @@ INN_LAYOUT_FILES = ( "s27_inn_below_sibling_blank.xlsx", ) INN_BAD_CHECKSUM_FILE = "s28_inn_bad_checksum.xlsx" +TYPO_ROW = 13 # строка «7701234567» с неверной контрольной суммой в s28 EXPECTED_NAMES = [ "s01_variant2_header.xlsx", "s02_no_outline_indent.xlsx", @@ -590,6 +591,13 @@ def test_s28_bad_checksum_inn_row_stays_a_row_and_needs_check(fixtures_dir: Path "похожа на ИНН 7701234567" in warning and "контрольная сумма не сходится" in warning for warning in warnings_of(outcome) ) + # решение 20: предупреждение названо для строки 13, строка остаётся COUNTERPARTY без ИНН, в OTHER не уходит + assert any(f"строка {TYPO_ROW}: похожа на ИНН 7701234567" in warning for warning in warnings_of(outcome)) + typo_rows = [row for row in doc.rows if row.row_number == TYPO_ROW] + assert [(row.row_value, row.group_type, row.counterparty_inn) for row in typo_rows] == [ + ("7701234567", "COUNTERPARTY", None) + ] + assert not [row for row in doc.rows if row.group_type == "OTHER"] def test_s19_inn_kpp_cell_gives_inn_only(fixtures_dir: Path) -> None: