docs(#116): Р-3 решено — словарь строк только в ядре, сервисы отдают распознанный текст

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Andrey Epifancev 2026-10-17 18:39:15 +04:00
parent 19e185984c
commit 18b7eb2371

View File

@ -1,7 +1,7 @@
# Единый алгоритм нормализации ББ/ОФР (scan-gateway и tabular-parser) — дизайн
Issue: arm-ka-docs#116. Статус: черновик; текущая цепочка описана, целевая картина по шагам 1–9 — предложение, ждёт
решений владельца Р-1…Р-3, Р-5…Р-7; Р-4 решено (brainstorming 17.10.2026).
решений владельца Р-1, Р-2, Р-5…Р-7; Р-3 и Р-4 решены (brainstorming 17.10.2026).
## Цель
@ -330,7 +330,9 @@ sheet:<A>,<B>`. `DISCLOSURE` и форма без колонки кодов —
статус строки, нарушения §7 по ячейкам, предупреждения с уровнем и привязкой. Уверенность, `is_recognized` и §7
сервис сводит в один признак ячейки `needs_review` (шаг 8) и из него, статусов строк и предупреждений выводит
статус документа; ядро при загрузке ничего не пересчитывает, после правок аналитика считает тем же общим кодом.
4. **Один словарь — одно место:** строки форм, проверки §7, периоды, заголовки форм, диапазоны кодов.
4. **Один словарь — одно место:** проверки §7, периоды, заголовки форм, диапазоны кодов — в общем коде сервисов;
соответствие «код → наименование» (словарь строк с редакциями) — только в ядре, сервисы его не знают и отдают
распознанный текст (решение владельца 17.10.2026, Р-3).
5. **Очистка OCR (§11.1) — не отдельный шаг, а первая стадия типовых разборов текста** в общем коде, там, где уже
известен смысл ячейки: ИНН и дата шапки (шаг 1), подписи колонок (шаг 2), код строки и разлепление склеенных
строк (шаг 3), сумма (шаг 4). Разбор вызывается для любой ячейки без `value`; у Excel он срабатывает только на
@ -465,16 +467,16 @@ line_name_confidence, values}`: `line_code` — разобранный код (4
`line_code_text` — сырой текст ячейки кода; `line_status` = `code_status` шага 3 (`ok` | `unreadable` | `missing`).
Несколько строк с одним кодом — обычные строки `ok`, порядок как в файле.
- **1. Источник наименования** — одно правило: наименование — из файла, с уверенностью источника; справочник наименование не подменяет. Справочное имя по коду и редакции добавляет ядро из единственного словаря строк (общий код, п. 3), экран показывает справочное, файловое — рядом (Р-3; AURORA-1406, 1522)
- **1. Источник наименования** — **решение владельца (17.10.2026):** сервисы отдают распознанный текст наименования как есть, с уверенностью источника; соответствие «код → наименование» — только в ядре и только когда нужно (показ справочного имени, достройка шаблонных строк). Экран показывает справочное имя, файловое — рядом (Р-3; AURORA-1406, 1522)
- scan-gateway: имя из `statement_lines.yaml` → имя из OCR
- tabular-parser: как сейчас
- **2. Редакция (66н / ФСБУ 4)** — в сервисах не определяется; редакция — свойство словаря строк (по дате отчёта), используется в шаге 7 (проверка «код не из редакции формы») и в ядре при достройке шаблонных строк
- **2. Редакция (66н / ФСБУ 4)** — в сервисах не определяется; редакция — свойство словаря строк ядра (по дате отчёта), ядро использует её при достройке шаблонных строк, показе справочного имени и проверке «код не из редакции формы»
- scan-gateway: `_choose_edition` уходит
- tabular-parser: без изменений
- **3. Справочник строк** — один словарь строк (в общем коде, Р-1); копия в шлюзе удаляется
- **3. Справочник строк** — только в ядре; в общий код сервисов не входит; копия в шлюзе удаляется
- scan-gateway: удаляет `api/rules/statement_lines.yaml`
- tabular-parser: без изменений
- **4. Уверенность кода** — от источника (ИС / 100), без срезания до 99 по справочнику; «не в справочнике» — предупреждение к строке в шаге 7
- **4. Уверенность кода** — от источника (ИС / 100), без срезания до 99 по справочнику; «код не в справочнике» — проверка ядра по его словарю, не сервисов
- scan-gateway: убирает `min(conf, 99)`
- tabular-parser: как сейчас
@ -501,8 +503,9 @@ line_name_confidence, values}`: `line_code` — разобранный код (4
**Вход:** `StatementDocument`.
**Единый выход:** `StatementChecks` у обоих: `relations_failed[]`, `soft_relations_failed[]` (каждое нарушение — с
кодами слагаемых и `column_index`, чтобы экран подсветил ячейки), `line_warnings[]` (код не из редакции формы по дате
отчёта, код не в словаре). `duplicate_line_codes` уходит: соотношения считаются по сумме значений одного кода в
кодами слагаемых и `column_index`, чтобы экран подсветил ячейки). Проверки по словарю строк (код не в словаре, код не
из редакции формы по дате отчёта) — в ядре, сервисы словаря строк не знают (Р-3). `duplicate_line_codes` уходит:
соотношения считаются по сумме значений одного кода в
колонке (повтор кода — законный случай, шаг 3 п. 3); нарушение подсвечивает все строки этого кода.
- **1. Проверки только у парсера; словарь §7 в двух копиях; ядро результат не читает** — проверки — общий код с одним словарём `statement_checks.yaml` у обоих сервисов; для OCR нарушение §7 — главный признак неверно прочитанной цифры; ядро читает `checks` из результата и пересчитывает тем же кодом только после правок аналитика (PATCH)
@ -554,7 +557,7 @@ column_index?}`, а не строка.
Одинаково, как сейчас; контракт `recognition-result.schema.json` → **v1.3**: `line_status`, `line_code` nullable,
`line_code_text`; `needs_review` у значения; `document.status`; `document.warnings[]` и `metrics.warnings[]`
структурные (уровень, привязка); `checks` обязателен для `BALANCE` / `INCOME` со строками у обоих конвейеров (у
документа без строк отсутствует), нарушения с кодами слагаемых, без `duplicate_line_codes`; `line_warnings`.
документа без строк отсутствует), нарушения с кодами слагаемых, без `duplicate_line_codes`.
### Что уходит из ядра
@ -567,8 +570,10 @@ column_index?}`, а не строка.
- `statement_status` (D-6): `RECOGNIZED` ⇔ `document.status = done` ∧ ИНН ≠ `MISMATCH` (единственное знание ядра);
остальные признаки D-6 не пересчитываются.
- §7 при загрузке: `checks` берутся из результата; пересчёт общим кодом — только после PATCH.
- Словарь строк и словарь §7: единственный экземпляр в общем коде (Р-1); копии ядра и шлюза удаляются.
- Достройка шаблонных строк: по тому же словарю; строки `missing` / `unreadable` показываются как пришли, с
- Словарь §7: единственный экземпляр в общем коде (Р-1), копия ядра удаляется. Словарь строк (код → наименование,
редакции) остаётся только в ядре, копия шлюза удаляется; проверки по нему (код не в словаре, код не из редакции по
дате отчёта) ядро делает само при загрузке и после PATCH, как предупреждения к строке.
- Достройка шаблонных строк: по словарю ядра; строки `missing` / `unreadable` показываются как пришли, с
подсветкой; код, у которого есть хотя бы одна строка из файла, шаблоном не достраивается.
- Экран: подсветка ячеек только по `needs_review` (уверенность, `is_recognized` и нарушения §7 уже сведены сервисом);
строк — по `line_status`; предупреждения документа — с привязкой к месту.
@ -576,12 +581,14 @@ column_index?}`, а не строка.
### Решения, которые нужны от владельца
- **Р-1** (шаг 1, п. 2) — форма общего кода: общий Python-пакет с dataclass-ами (сериализуемыми в json — golden-файлы
выхода шага 1 в fixtures), шагами 2–8 и словарями, который подключают оба сервиса и ядро (рекомендация); запасной
выхода шага 1 в fixtures), шагами 2–8 и словарями (§7, периоды, заголовки форм, диапазоны кодов; без словаря
строк), который подключают оба сервиса и ядро (рекомендация); запасной
вариант, если платформа не даст ставить пакет из git или зеркала, — копия по скрипту, как `sync-web.sh`.
- **Р-2** (шаг 4, п. 5) — отсутствующая OCR-ячейка под колонкой: чистый `null` (предложение; потерю ловит §7) или
подсветка «не распознано», как сейчас (больше ложных подсветок, AURORA-1524).
- **Р-3** (шаг 5, п. 1) — наименование: из файла в сервисах, справочное — в ядре (= решение № 2 по спринту 2,
AURORA-1406 / 1522; договорённость ДБД «из справочника» выполняется на экране).
- **Р-3** (шаг 5, п. 1) — **решено владельцем 17.10.2026:** сервисы отдают распознанный текст наименования;
соответствие «код → наименование» — только в ядре, при необходимости (= решение № 2 по спринту 2, AURORA-1406 /
1522; договорённость ДБД «из справочника» выполняется на экране).
- **Р-4** (шаг 3, п. 3) — **решено владельцем 17.10.2026:** повторы кодов законны; все строки сохраняются и
показываются, для проверок и всех операций после подтверждения или автоподтверждения — суммой по коду. Следствие:
снять уникальность `(meta_id, line_code)` в DBML.