From 9863b4614006a745def708f38fd3c731682aa6b0 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Sun, 18 Oct 2026 11:50:44 +0400 Subject: [PATCH 1/2] =?UTF-8?q?=C2=A71=20=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=9E=D0=A1=D0=92:=20cp1251=20=D0=B4=D0=BB=D1=8F=20xl?= =?UTF-8?q?s=20=D0=B1=D0=B5=D0=B7=20CODEPAGE,=20=C2=AB=D0=9A=D0=BE=D0=BB-?= =?UTF-8?q?=D0=B2=D0=BE=C2=BB/=C2=AB=D0=92=D0=B0=D0=BB=C2=BB,=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=BD=D0=B5=D1=86=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86?= =?UTF-8?q?=D1=8B=20=D0=BD=D0=B0=20=D0=BF=D0=B5=D1=80=D0=B2=D0=BE=D0=B9=20?= =?UTF-8?q?=C2=AB=D0=98=D1=82=D0=BE=D0=B3=D0=BE=C2=BB=20(tabular-parser=20?= =?UTF-8?q?#47,=20AURORA-1662,=201663,=201664)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5.5 --- context/05-domain-rules.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/context/05-domain-rules.md b/context/05-domain-rules.md index bd9286a..1a5e1ec 100644 --- a/context/05-domain-rules.md +++ b/context/05-domain-rules.md @@ -155,9 +155,13 @@ r11 Договоры ← Из текста ИНН отрезается всегда: `counterparty_name` без ИНН и разделителя, `row_value` — исходный текст; только для строк `COUNTERPARTY`, договоры и прочее не трогаются; правила — `osv_headers.yaml` (`counterparty_inn_suffix`, `inn_only_row`, `inn_kpp_cell`); **реализовано**, OQ-100, OQ-163 (строки ИНН; ранее OQ-130, tabular-parser #9, PR #15; синтетика `s17`–`s19`), -`data_type` (строки «USD», «Вал.», «Кол.» под контрагентом → CURRENCY/QUANTITY; по умолчанию — из шапки). +`data_type` (строки «USD», «Вал.», «Кол.», «Кол-во» под контрагентом → CURRENCY/QUANTITY; по умолчанию — из шапки). -Строки «Вал.», «Кол.» и трёхбуквенный код валюты («USD») — не уровень группировки, а вид сумм родителя: +«Вал» **без точки** — не метка валюты: так называется материал (счёт 10); валютная строка — «Вал.» с точкой или код +валюты из словаря (**реализовано**, tabular-parser #47, AURORA-1663). «Кол-во» — строка количества, как «Кол.» и +«Количество» (там же). + +Строки «Вал.», «Кол.», «Кол-во» и трёхбуквенный код валюты («USD») — не уровень группировки, а вид сумм родителя: `group_type = OTHER`, `data_type = CURRENCY | QUANTITY`, позицию в `group_schema` не занимают, **не наследуют** `counterparty_name`/`counterparty_inn` (контрагента потребитель находит по родителю), `account_code_raw` наследуют от ветки; их суммы остаются в шести полях, но в проверки родителя не входят (§1.4). @@ -227,6 +231,10 @@ r11 Договоры ← (показатели без суммы и сама «Итого» не входят; сальдо — по колонкам либо по нетто, если «Итого» свёрнуто, как у родителя выше, R-21); при одном корне сверка прежняя. Вторая итоговая строка сразу за «Итого» («Итого развернутое») — тоже `TOTAL`, в сверку не входит; строка сумм без подписи в конце таблицы принимается за «Итого» с предупреждением. + **Таблица кончается на первой «Итого»** (на корневом уровне оформления; плюс «Итого развернутое» сразу за ней): всё + ниже (подпись «Ответственный:», блоки, дописанные аналитиком, в том числе строки, начинающиеся с «Итого») — вне + документа, в `rows` не попадает; числа в хвосте — предупреждение «ниже таблицы … есть числа» без смены статуса (статус + решают контрольные суммы). **Реализовано**, tabular-parser #47, AURORA-1664 (закрывает tabular-parser #7, M-2). Если корня нет (**пустая ОСВ**: заголовок и сразу «Итого» — в фикстурах две, schastl 58 и 66 за 2 кв. 2025) — «Итого» должна быть пустой или нулевой; такая ОСВ штатна: `done`, `hierarchy=trivial`, `metrics.rows = 0`, предупреждение «нет строк данных». Если строка «Итого» не @@ -296,7 +304,10 @@ result-osv-needs-check.json`. предупреждением (`sheet=<имя> skipped: нет признаков ОСВ или формы`; листы форм теперь разбираются, §12). Другие предупреждения: `sheet=<имя> hierarchy=<стратегия>` (всегда), свёрнутое сальдо, нераспознанное число (с номером строки), не найденное поле шапки, «нет строк данных». xlsb не содержит outline level — каскад начинается с отступа (предупреждение -«xlsb: outline level недоступен»). +«xlsb: outline level недоступен»). xls (BIFF5/7) без записи CODEPAGE читается как cp1251 (кодовая страница 1С и Excel в +русской локали; по содержимому кодировка не угадывается) с предупреждением «xls без кодовой страницы — строки прочитаны +как cp1251»; без этого xlrd декодирует строки как latin-1 и лист ОСВ не находится. BIFF8 хранит строки в Unicode и от +CODEPAGE не зависит. **Реализовано**, tabular-parser #47, AURORA-1662. Лимиты: `PARSE_MAX_BYTES` (по умолчанию 50 МиБ) и `PARSE_TIMEOUT_SECONDS` (120 с; кооперативный — проверка между листами, в циклах по листу и между стратегиями; чтение книги библиотекой он не прерывает). Поэтому до библиотеки чтения действуют @@ -307,7 +318,7 @@ openpyxl, после чтения — только диапазоны, кото Словари: `osv_headers.yaml` (признаки листов, группы сумм, «Дебет»/«Кредит», колонка ИНН, «Итого», метки шапки), `osv_groups.yaml` (группировка → `group_type`), `periods.yaml` (период → квартал и нарастающий итог), `data_types.yaml` -(БУ/НУ/сумма, строки «Вал.»/«Кол.», коды и написания валют). Каждая запись словаря обязана срабатывать хотя бы на одной +(БУ/НУ/сумма, строки «Вал.»/«Кол.»/«Кол-во», коды и написания валют). Каждая запись словаря обязана срабатывать хотя бы на одной фикстуре или синтетике (тест покрытия). --- From e47f1ab69c7a93fed39f2bc32f290a52ec3dd28e Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Sun, 18 Oct 2026 12:04:48 +0400 Subject: [PATCH 2/2] =?UTF-8?q?=C2=A71.4:=20=D1=82=D0=BE=D1=87=D0=BD=D0=BE?= =?UTF-8?q?=D0=B5=20=C2=AB=D0=98=D1=82=D0=BE=D0=B3=D0=BE=C2=BB=20=D0=B8?= =?UTF-8?q?=D1=89=D0=B5=D1=82=D1=81=D1=8F=20=D1=80=D0=B0=D0=BD=D1=8C=D1=88?= =?UTF-8?q?=D0=B5=20=C2=AB=D0=98=D1=82=D0=BE=D0=B3=D0=BE=20=E2=80=A6=C2=BB?= =?UTF-8?q?,=20=D1=85=D0=B2=D0=BE=D1=81=D1=82=20=E2=80=94=20=D1=87=D0=B8?= =?UTF-8?q?=D1=81=D0=BB=D0=B0=20=D0=B2=20=D0=BA=D0=BE=D0=BB=D0=BE=D0=BD?= =?UTF-8?q?=D0=BA=D0=B0=D1=85=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D1=8B?= =?UTF-8?q?=20(tabular-parser=20#47,=20AURORA-1664)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5.5 --- context/05-domain-rules.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/context/05-domain-rules.md b/context/05-domain-rules.md index 1a5e1ec..5dc4098 100644 --- a/context/05-domain-rules.md +++ b/context/05-domain-rules.md @@ -233,8 +233,12 @@ r11 Договоры ← в сверку не входит; строка сумм без подписи в конце таблицы принимается за «Итого» с предупреждением. **Таблица кончается на первой «Итого»** (на корневом уровне оформления; плюс «Итого развернутое» сразу за ней): всё ниже (подпись «Ответственный:», блоки, дописанные аналитиком, в том числе строки, начинающиеся с «Итого») — вне - документа, в `rows` не попадает; числа в хвосте — предупреждение «ниже таблицы … есть числа» без смены статуса (статус - решают контрольные суммы). **Реализовано**, tabular-parser #47, AURORA-1664 (закрывает tabular-parser #7, M-2). + документа, в `rows` не попадает. Сначала ищется первая строка корневого уровня с текстом ровно «Итого» + (`total_row_exact`), и только если такой нет — первая, начинающаяся с «Итого» (`total_row`): так контрагент + «Итого-Сервис» на плоском листе без outline и отступов не обрезает таблицу. Остаточный риск — только когда точного + «Итого» нет вовсе (ловит проверка «TOTAL = корень»). Числа в хвосте **в колонках таблицы** (от колонки текста до + правого края сумм) — предупреждение «ниже таблицы … есть числа» без смены статуса (статус решают контрольные суммы); + числа правее таблицы (контрольные суммы) хвостом не считаются. **Реализовано**, tabular-parser #47, AURORA-1664 (закрывает tabular-parser #7, M-2). Если корня нет (**пустая ОСВ**: заголовок и сразу «Итого» — в фикстурах две, schastl 58 и 66 за 2 кв. 2025) — «Итого» должна быть пустой или нулевой; такая ОСВ штатна: `done`, `hierarchy=trivial`, `metrics.rows = 0`, предупреждение «нет строк данных». Если строка «Итого» не