feat(osv): ИНН из названия контрагента, ИНН строкой выше, ИНН/КПП в ячейке (#9) #15

Merged
aep merged 1 commits from feat/9-inn-in-text into feat/11-dkb-formats 2026-10-06 13:00:40 +03:00
Owner

Closes #9. Stacked on #13 (ветка feat/11-dkb-formats: общие classify.py, header.py, rules.py); после слияния #13 — перенацелить на main. Парный PR с golden/синтетикой: RSHB/arm-ka-fixtures#8.

Что сделано

  1. ИНН в тексте названия (OQ-100): counterparty_inn — цифры (10 или 12) в конце названия после запятой, скобки, «/», пробела или метки «ИНН»; counterparty_name — без ИНН и разделителя; row_value не меняется. Приоритет: колонка ИНН → строка выше → хвост названия. Только для COUNTERPARTY (договоры не трогаются).
  2. ИНН строкой выше (OQ-130): строка без сумм с одним ИНН над строкой с суммами того же уровня (outline и отступ) склеивается со следующей и убирается из rows (не OTHER); предупреждение «ИНН … над строкой … отнесён к ней». Другой уровень / нет сумм у следующей — строка остаётся как есть.
  3. «ИНН/КПП» в одной ячейке колонки ИНН → только ИНН.
  4. Правила — osv_headers.yaml (counterparty_inn_suffix, inn_only_row, inn_kpp_cell), не код; загрузчик проверяет обязательные группы tail/inn.
  5. Синтетика s17_inn_in_name, s18_inn_row_above, s19_inn_kpp_cell (генератор + сценарные тесты).

Как проверить

make check            # 1962 passed (+ новые юнит и синтетические тесты)
make test-fixtures    # 886 passed (нужен fixtures на ветке feat/9-golden либо после слияния fixtures#8)

Golden: 9 снимков изменились, 3 новых. Diff: меняются только counterparty_name и counterparty_inn (30 строк null → ИНН): rb/*/сч 60 ×5 («ДОРСЕРВИС ООО ИНН 3523022660» → имя «ДОРСЕРВИС ООО», ИНН 3523022660), schastl/*/сч 76 ×4 («Полиграф, 3528315710» → «Полиграф»/3528315710, «Костыгова Наталья Валериевна, 352800390201», «Межрегиональное операционное УФК (ФТС России), 7730176610», «УФК по Вологодской области (ОСП …), 3525144985», «Русский бисквит, 3528052718»).
На пакете ДКБ ИНН в названии теперь извлекаются и у НМ/Агрокомплекс (не golden).

Находки

маркер суть статус
A9-1 Несколько названий «УФК …» из golden schastl 76 содержат непарную скобку до отрезанного ИНН («…л/с05301А54000, 3525144985»): имя после отрезки тоже с обрывом — это исходный текст файла rejected: данные файла
A9-2 Если ИНН колонки и ИНН в названии различаются, берётся колонка, предупреждения о расхождении нет deferred (нужно ли предупреждение — решение владельца)
A9-3 Строка-ИНН над НЕ-контрагентом (счёт, договор) приклеивается к следующей строке и ИНН теряется молча (в inn_above лежит, но используется только в COUNTERPARTY); предупреждение о склейке при этом печатается deferred
A9-4 В НМ ОСВ 63 строка «ПЗК ООО 6155090625» — OTHER (нет метки группировки «Контрагенты»), ИНН из неё не извлекается deferred (см. A11-3)
A9-5 docs: OQ-100/OQ-130 → «реализовано», 05-domain-rules.md §1.3 дописать (repo docs не трогал) deferred

Decisions made without discussion

  • 2026-10-06: ИНН в названии распознаётся только в конце текста и только при наличии разделителя/метки перед цифрами («ООО Альфа7701234567» и ИНН в середине — не ИНН). Цена ошибки: пропуск экзотической записи (ИНН остаётся в имени), ложных срабатываний нет.
  • 2026-10-06: «над названием» = тот же outline и тот же отступ (в синтетике иерархия по outline); если реальный формат ставит ИНН на другом уровне — не склеится (останется OTHER, как раньше).
  • 2026-10-06: ИНН из строки выше приоритетнее ИНН из названия, но ниже колонки ИНН.
  • 2026-10-06: строка-ИНН удаляется из rows (ее row_number из результата исчезает), а не помечается — иначе она нарушила бы дерево и типизацию.

Что проверить человеку

  • Что rows без строки-ИНН устраивает ядро (нумерация строк с пропуском).
  • Имена контрагентов в golden schastl 76 после отрезки ИНН (выше).
  • Порядок слияния: #13 → fixtures#8 → этот PR (или fixtures#8 одновременно).

🤖 Generated with Claude Code

Closes #9. **Stacked on #13** (ветка `feat/11-dkb-formats`: общие `classify.py`, `header.py`, `rules.py`); после слияния #13 — перенацелить на main. Парный PR с golden/синтетикой: RSHB/arm-ka-fixtures#8. ## Что сделано 1. **ИНН в тексте названия** (OQ-100): `counterparty_inn` — цифры (10 или 12) в конце названия после запятой, скобки, «/», пробела или метки «ИНН»; `counterparty_name` — без ИНН и разделителя; `row_value` не меняется. Приоритет: колонка ИНН → строка выше → хвост названия. Только для `COUNTERPARTY` (договоры не трогаются). 2. **ИНН строкой выше** (OQ-130): строка без сумм с одним ИНН над строкой с суммами того же уровня (outline и отступ) склеивается со следующей и убирается из `rows` (не OTHER); предупреждение «ИНН … над строкой … отнесён к ней». Другой уровень / нет сумм у следующей — строка остаётся как есть. 3. **«ИНН/КПП» в одной ячейке** колонки ИНН → только ИНН. 4. Правила — `osv_headers.yaml` (`counterparty_inn_suffix`, `inn_only_row`, `inn_kpp_cell`), не код; загрузчик проверяет обязательные группы `tail`/`inn`. 5. Синтетика `s17_inn_in_name`, `s18_inn_row_above`, `s19_inn_kpp_cell` (генератор + сценарные тесты). ## Как проверить ``` make check # 1962 passed (+ новые юнит и синтетические тесты) make test-fixtures # 886 passed (нужен fixtures на ветке feat/9-golden либо после слияния fixtures#8) ``` Golden: 9 снимков изменились, 3 новых. Diff: меняются только `counterparty_name` и `counterparty_inn` (30 строк `null` → ИНН): `rb/*/сч 60` ×5 («ДОРСЕРВИС ООО ИНН 3523022660» → имя «ДОРСЕРВИС ООО», ИНН 3523022660), `schastl/*/сч 76` ×4 («Полиграф, 3528315710» → «Полиграф»/3528315710, «Костыгова Наталья Валериевна, 352800390201», «Межрегиональное операционное УФК (ФТС России), 7730176610», «УФК по Вологодской области (ОСП …), 3525144985», «Русский бисквит, 3528052718»). На пакете ДКБ ИНН в названии теперь извлекаются и у НМ/Агрокомплекс (не golden). ## Находки | маркер | суть | статус | |---|---|---| | A9-1 | Несколько названий «УФК …» из golden schastl 76 содержат непарную скобку до отрезанного ИНН («…л/с05301А54000, 3525144985»): имя после отрезки тоже с обрывом — это исходный текст файла | rejected: данные файла | | A9-2 | Если ИНН колонки и ИНН в названии различаются, берётся колонка, предупреждения о расхождении нет | deferred (нужно ли предупреждение — решение владельца) | | A9-3 | Строка-ИНН над НЕ-контрагентом (счёт, договор) приклеивается к следующей строке и ИНН теряется молча (в `inn_above` лежит, но используется только в COUNTERPARTY); предупреждение о склейке при этом печатается | deferred | | A9-4 | В НМ ОСВ 63 строка «ПЗК ООО 6155090625» — OTHER (нет метки группировки «Контрагенты»), ИНН из неё не извлекается | deferred (см. A11-3) | | A9-5 | docs: OQ-100/OQ-130 → «реализовано», `05-domain-rules.md` §1.3 дописать (repo docs не трогал) | deferred | ## Decisions made without discussion - 2026-10-06: ИНН в названии распознаётся только в **конце** текста и только при наличии разделителя/метки перед цифрами («ООО Альфа7701234567» и ИНН в середине — не ИНН). Цена ошибки: пропуск экзотической записи (ИНН остаётся в имени), ложных срабатываний нет. - 2026-10-06: «над названием» = тот же outline и тот же отступ (в синтетике иерархия по outline); если реальный формат ставит ИНН на другом уровне — не склеится (останется OTHER, как раньше). - 2026-10-06: ИНН из строки выше приоритетнее ИНН из названия, но ниже колонки ИНН. - 2026-10-06: строка-ИНН удаляется из `rows` (ее `row_number` из результата исчезает), а не помечается — иначе она нарушила бы дерево и типизацию. ## Что проверить человеку - Что `rows` без строки-ИНН устраивает ядро (нумерация строк с пропуском). - Имена контрагентов в golden schastl 76 после отрезки ИНН (выше). - Порядок слияния: #13 → fixtures#8 → этот PR (или fixtures#8 одновременно). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 1 commit 2026-10-06 12:14:18 +03:00
- OQ-100: ИНН в конце названия («Полиграф, 3528315710», «(ИНН …)», пробел) уходит в counterparty_inn, имя — без ИНН
  и разделителя; колонка ИНН приоритетнее; только для COUNTERPARTY.
- OQ-130: строка без сумм с одним ИНН над строкой с суммами того же уровня склеивается со следующей и не уходит в OTHER.
- «ИНН/КПП» в ячейке колонки ИНН даёт ИНН.
- Правила — osv_headers.yaml (counterparty_inn_suffix, inn_only_row, inn_kpp_cell), не код.
- Синтетика s17–s19 (генератор, тесты); golden — в репозитории fixtures (feat/9-golden).

Stacked on #13 (feat/11-dkb-formats).
Closes #9

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
aep merged commit ae1e872e3e into feat/11-dkb-formats 2026-10-06 13:00:40 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/arm-tabular-parser#15
No description provided.