Andrey Epifancev f5b73d2146 spec: ОСВ других учётных систем — признаки листа, группы, «ВСЕГО» (#81)
AURORA-1717, AURORA-1719, AURORA-1732.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 19:52:43 +04:00

130 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Context
Классификация листа (`detect.classify_sheet`): ОСВ, если в первых `SHEET_MARKER_ROWS` (30) строках есть ячейка,
совпадающая с `sheet_markers`; иначе вид листа определяет пакет `arm_statements` (форма / продолжение / прочее).
`sheet_markers` сейчас один: `оборотно\s*сальдовая\s+ведомость`. Заголовок таблицы (`_find_group_row`) — первая строка,
где есть группы «обороты» и «сальдо на конец». Сторона ищется в начале текста ячейки (`^(дебет|дт|д т)\b`) — в
отдельной ячейке под группой либо в остатке ячейки группы после совпадения (`_group_cells`: «Сальдо на начало Дт»).
Файлы — банк первичных документов `awp-ca/doc-bank/` (индекс `index/index.csv`, колонки `parse_status`, `parse_error`,
`parse_bug`, `sha256`; в git не кладутся). Списки затронутых файлов с ГК, ЮЛ и sha256 — вложения `список_файлов.csv`
к AURORA-1717 и AURORA-1719. Образцы во вложениях задач:
| Задача | Файл | Что показывает |
|---|---|---|
| 1717, 1719 | «ОСВ по внб счету 009 за 9 мес 2025.xlsx» (Промлит) | «Оборотная ведомость», «Остаток на начало/конец» |
| 1717, 1719 | «ОСВ 66 67 01-06 2025.xlsx» (Виола) | «Отчет по Главной книге», SAP «Сальдо вх Дт / Сальдо исх Кт» |
| 1717 | «67 9 мес. 25.xlsx» (Айсберри) | Navision «Фин. Обороты Листок», «НачалоДт / КонецКт» |
| 1719 | «ОСВсч62_3кв2025.xls» (НМЖК) | SAP «Сальдо НачальноеДТВВ / КонечноеКТВВ» |
| 1732 | «ОСВ по внб сч 009 за 3 кв 2025.xlsx» (КТЗ) | итог «ВСЕГО» |
Эксперимент автора задач на копии словарей (20.10.2026, синонимы 1717 + 1719 без «ДТВВ» и без запасного признака): из
129 файлов 1717 — 43 «Готово», 43 «Требует проверки», 43 упираются в группы и иерархию; из 159 файлов 1719 — 53
«Готово», 58 «Требует проверки», 48 — другое (AURORA-1720, 1721, 1723). Остальные ОСВ банка статусы не ухудшили.
## Goals / Non-Goals
**Goals:**
- Листы с перечисленными названиями и листы без названия с полным заголовком таблицы ОСВ распознаются как ОСВ.
- Перечисленные написания групп и сторон находятся; заголовок таблицы этих файлов не падает с `INVALID_FORMAT`
«нет групп сумм».
- «ВСЕГО» — итоговая строка листа.
- Ни один документ банка первички и ни одна фикстура не ухудшает результат (см. «Регрессия»).
**Non-Goals:**
- Довести все затронутые файлы до «Готово»: дальше их держат иерархия (AURORA-1721, 1730), одинаковые подписи начала и
конца (AURORA-1720), обороты без подзаголовков в варианте НОВО-МАР и SAP со стороной перед группой (AURORA-1722),
ведомости ОС/ТМЦ (AURORA-1723, 1731). Эти файлы могут остаться `needs_check` или `INVALID_FORMAT` по другой причине.
- Отчёт 1С «Обороты счета» (1 файл, ГК Сейма): внутри «Оборот Дт/Кт» колонки корреспондирующих счетов, это отдельная
форма. Синоним `обороты\s+счета` не добавляется.
- Правило «расшифровка без кодов ББ не может быть Готово» (вторая половина AURORA-1718) — пакет `arm_statements`,
ждёт AURORA-1677.
**Anti-goals (провал, даже если тесты зелёные):**
- Лист формы ББ/ОФР, её продолжения или расшифровки становится ОСВ по запасному признаку или по новому названию
ведомости, хотя ведомостью не является. Ведомость, которую сегодня ложно забирает конвейер форм (10 файлов «Оборотный
баланс», AURORA-1718), становится ОСВ по названию — это цель, а не ухудшение (признак по названию проверяется раньше
форм, как сейчас).
- `if` под файл, организацию, систему-источник или имя листа вместо синонима в YAML.
## Decisions
### D1. Запасной признак листа — последним шагом (решение владельца 28.10.2026)
Порядок классификации: признак ОСВ по названию (`sheet_markers`) → форма / продолжение / прочее (пакет). Только если
пакет вернул «прочее», лист проверяется запасным признаком: в первых `SHEET_MARKER_ROWS` строках есть строка групп, где
найдены **все три** группы (начало, обороты, конец), и у каждой группы найдены **обе** стороны — Дебет и Кредит
(в ячейках под группой или в самой ячейке группы). Свёрнутое сальдо (одна колонка в группе) запасной признак не даёт.
Нашёлся — лист `OSV`, дальше обычный конвейер ОСВ; нет — `SHEET_OTHER`, как сейчас.
Почему так: расшифровки ББ с колонками «Остаток на начало / … / Остаток на конец» забирает классификатор форм раньше,
до запасного признака они не доходят; поиск заголовка выполняется только на листах «прочее», а не на каждом листе книги
с формами. Требование трёх групп и обеих сторон строже обычного заголовка ОСВ («начало» там необязательно), поэтому
ложное срабатывание требует почти полной таблицы ОСВ.
### D2. Новые записи словарей
Ориентир — рекомендации из AURORA-1717/1719/1732; окончательные паттерны подбирает исполнитель по образцам, каждая
запись — с синтетикой, где она срабатывает (R-22). Паттерны пишутся по нормализованному тексту (нижний регистр, «ё» →
«е», дефисы и переносы → пробел).
| Ключ | Написания |
|---|---|
| `sheet_markers` | «Оборотная ведомость …», «ОСВ по сч. …» (с начала ячейки), «Оборотный баланс», «Фин. Обороты Листок», «Отчет по Главной книге» |
| `groups.opening` | «Остаток на начало (периода)», «Начальное сальдо» (уже есть `\bнач(альн\w*)?\.?\s*сальдо`), «Сальдо начальное…», «Сальдо вх …», «НачалоДт / НачалоКт» |
| `groups.closing` | симметрично: «Остаток на конец», «Конечное сальдо», «Сальдо конечное…», «Сальдо исх …», «КонецДт / КонецКт» |
| `debit` / `credit` | «по дебету» / «по кредиту» (в остатке ячейки группы «Оборот по дебету»); сторона, приклеенная к названию без границы слова («…ДТВВ», «…КТВВ», «НачалоДт») |
| `total_row_exact` | «ВСЕГО» |
Если сторону без границы слова нельзя выразить записью словаря при текущем `_side` (поиск с начала остатка ячейки),
допустима правка поиска стороны в `detect.py`, общая для всех написаний, без упоминания конкретной системы.
### D3. Регрессия по банку первички
До изменений и после — прогон парсера (CLI, `ENV_FILE=.env.test`) по всем файлам банка с `route = парсер` (xls, xlsx,
xlsb) на main `a8c9605` и на ветке. Сравнение по каждому документу: вид (ОСВ / форма / прочее), статус, код ошибки.
Ухудшение — `done` → `needs_check`/ошибка, `needs_check` → ошибка, любой переход форма/расшифровка → ОСВ через запасной
признак, переход форма/расшифровка → ОСВ по названию ведомости или «прочее» → ОСВ, если лист не ведомость (каждый такой
переход по названию просматривается вручную: ожидаемы «Оборотный баланс» и другие ведомости из списков 1717/1719).
Каждое ухудшение разбирается до PR: либо исправляется, либо выносится владельцу с образцом.
Банк — `awp-ca/doc-bank/` (в worktree — симлинк `.wt/osv-dict/doc-bank`), только чтение. Базовый прогон на main
`a8c9605` снимается до первой правки кода. Скрипт прогона и сравнения и его результаты — `awp-ca/admin/osv-other-systems-regress/`
(не репозиторий; в PR — только итоговая таблица).
Приёмка: сценарии спеки на синтетике, зелёный `make check-full`, нет ухудшений D3. Число файлов банка, перешедших в
«Готово» / «Требует проверки», — отчёт, а не порог. Реальные безымянные листы, которые конвейер форм относит к форме или
продолжению (до запасного признака они не доходят), остаются как есть и перечисляются в PR как остаток. Итоговая
таблица переходов статусов (было → стало, число файлов) — в описание PR и комментарий к AURORA-1717/1719. Плюс обычные
`make check-full` (golden, property, покрытие словарей) и `tests/fixtures/test_osv_dkb.py`.
### D4. Правило в 05-domain-rules.md
§1.1: признак листа — название ведомости по словарю `sheet_markers` (примеры написаний) или, если лист не опознан как
форма ББ/ОФР или её продолжение, полный заголовок таблицы ОСВ в первых 30 строках (D1). §1.2: варианты написания групп
и сторон дополняются написаниями из D2. PR в arm-ka-docs из ветки `feat/81-osv-other-systems` worktree
`.wt/osv-dict/docs`, ссылка на tabular-parser#81.
## Risks / Trade-offs
- [`^осв\b` и «оборотн… ведомост» в тексте формы] → проверка ОСВ идёт первой; регрессия D3 ловит листы форм, ставшие
ОСВ; паттерн «ОСВ» — только с начала ячейки.
- [Расшифровка, не узнанная пакетом, проходит запасной признак] → D1 требует три группы и обе стороны; регрессия D3.
- [Новые синонимы групп матчат преамбулу шапки («Остаток на начало: …») как строку групп] → в такой строке нет
«оборотов», `_find_group_row` её пропускает (R-12); синтетика с преамбулой.
- [Сторона без границы слова («дт» внутри слова)] → искать её только в остатке ячейки группы после совпадения группы, не
в произвольных ячейках.
## Decisions made without discussion
| Дата | Решение | Обоснование | Цена ошибки |
|---|---|---|---|
| 2026-10-28 | R-1. Отчёт 1С «Обороты счета» вне объёма, синоним не добавляется | автор AURORA-1717 проверил: с синонимом файл даёт «Требует проверки» с договорами в контрагентах — нужна отдельная форма | 1 файл остаётся `INVALID_DOCUMENT`; отдельная задача |
| 2026-10-28 | R-2. Запасной признак ищет строку групп только в первых `SHEET_MARKER_ROWS` (30) строках | у безымянных листов таблица начинается сразу; ограничение снижает время и ложные срабатывания на длинных листах «прочее» | безымянный лист с преамбулой длиннее 30 строк не распознаётся; поднимется регрессией D3 |
| 2026-10-28 | R-3. Запасной признак не принимает свёрнутое сальдо (одна колонка в группе) | строгость против ложных ОСВ (D1) | ОСВ без названия со свёрнутым сальдо не распознаётся |
| 2026-10-28 | R-5. Новые `sheet_markers` якорятся к началу ячейки (`^…`); якорь снимается для конкретного названия, только если по спискам 1717 файлы с ним иначе не находятся | «Оборотная ведомость», «Оборотный баланс» могут встретиться в примечаниях к ББ; признак по названию проверяется раньше форм | часть ведомостей с текстом перед названием не распознаётся; видно в регрессии D3 |
| 2026-10-28 | R-6. Запасной признак переиспользует поиск строки групп и колонок обычного заголовка (`_find_group_row`, `_columns_of_group`) в строгом режиме, а не отдельную функцию | запасной признак и конвейер не должны расходиться в том, что считать заголовком | — |
| 2026-10-28 | R-7. Порядок PR: `fixtures` (golden синтетики, отдельный коммит `make golden-update`) → tabular-parser → docs | golden-тесты tabular-parser читают `../fixtures` | — |
| 2026-10-28 | R-8. Приёмка — синтетика + `make check-full` + нет ухудшений D3; число исправленных файлов банка — отчёт, не порог | эксперимент автора задач — ориентир, а не обязательство; остаток держат 1720–1723 | — |
| 2026-10-28 | R-4. AURORA-1722 (SAP со стороной перед группой, НОВО-МАР) не входит | в задачах указан порядок: после 1717/1719; причина варианта НОВО-МАР не разобрана | эти файлы остаются с ошибкой до 1722 |