From 0f57ceb5f19375653ca79d9e97a57e0225c6aa8f Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Sat, 17 Oct 2026 18:27:25 +0400 Subject: [PATCH] =?UTF-8?q?docs(#116):=20=D0=A0-4=20=D1=80=D0=B5=D1=88?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=20=E2=80=94=20=D0=BF=D0=BE=D0=B2=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D1=8B=20=D0=BA=D0=BE=D0=B4=D0=BE=D0=B2=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D0=BD=D1=8B,=20=D0=B2=D1=81=D0=B5=20=D1=81?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=BA=D0=B8=20=D1=85=D1=80=D0=B0=D0=BD=D1=8F?= =?UTF-8?q?=D1=82=D1=81=D1=8F,=20=D0=B4=D0=B0=D0=BB=D1=8C=D1=88=D0=B5=20?= =?UTF-8?q?=D1=81=D1=83=D0=BC=D0=BC=D0=BE=D0=B9=20=D0=BF=D0=BE=20=D0=BA?= =?UTF-8?q?=D0=BE=D0=B4=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5.1 --- .../unified-statement-normalization/design.md | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/openspec/changes/unified-statement-normalization/design.md b/openspec/changes/unified-statement-normalization/design.md index 03d8c40..a02c59f 100644 --- a/openspec/changes/unified-statement-normalization/design.md +++ b/openspec/changes/unified-statement-normalization/design.md @@ -415,8 +415,9 @@ sheet:,`. `DISCLOSURE` и форма без колонки кодов — **Единый выход:** `RawLine[]` — по строке на каждую строку сетки с ролью `data`, у которой есть код или хотя бы одно число: `ref`, ячейка кода, `code_status` (`ok` | `unreadable` — код есть, но не разобран | `missing` — кода нет, суммы -есть | `duplicate` — код уже встречался), ячейка наименования, ячейки значений по колонкам раскладки. Строка без кода -и без чисел (заголовок раздела «АКТИВ», «в том числе:») — не строка. Счётчиков отброшенных нет — есть статусы. +есть), ячейка наименования, ячейки значений по колонкам раскладки. Строка без кода и без чисел (заголовок раздела +«АКТИВ», «в том числе:») — не строка. Счётчиков отброшенных нет — есть статусы. Повтор кода — не статус: по правилам +отчётности один код может стоять у нескольких строк с разными наименованиями, все они `ok`. - **1. Код-мусор** — статус `unreadable`, строка сохраняется с сырым текстом кода (AURORA-1462: «ИЧ,250» видна, аналитик назначает 1250) - scan-gateway: счётчик → статус @@ -424,10 +425,10 @@ sheet:,`. `DISCLOSURE` и форма без колонки кодов — - **2. Склейка двух строк в одну** — одно правило: ячейка кода содержит N кодов через перевод строки и ячейки значений — N частей → N строк (OQ-156); у Excel не срабатывает - scan-gateway: как сейчас, через общее правило - tabular-parser: правило общее, no-op -- **3. Повтор кода** — статус `duplicate` у второй и последующих строк; строки сохраняются; текстовое предупреждение и `checks.duplicate_line_codes` уходят; что показывать и как считать — ядро (Р-4) - - scan-gateway: «оставлена первая» → обе строки - - tabular-parser: `duplicates` → статус -- **4. Отброшенная строка** — строки не отбрасываются: `unreadable` / `missing` / `duplicate` идут дальше со статусом (AURORA-1634, 1462, 1406); ядро не достраивает вместо них пустую шаблонную строку молча +- **3. Повтор кода** — **решение владельца (17.10.2026):** повтор кода — законный случай (один код, разные наименования), не ошибка и не предупреждение. Все строки сохраняются как есть со статусом `ok`; текстовое предупреждение и `checks.duplicate_line_codes` уходят. Для проверок §7, подтверждения и всего, что идёт после, значения одного кода идут суммой (см. «Что уходит из ядра»; договорённость ДБД в AURORA-1431). Неверно прочитанный код, случайно совпавший с существующим, ловит §7 через сумму + - scan-gateway: «оставлена первая» → все строки + - tabular-parser: `duplicates` уходит +- **4. Отброшенная строка** — строки не отбрасываются: `unreadable` / `missing` идут дальше со статусом (AURORA-1634, 1462, 1406); ядро не достраивает вместо них пустую шаблонную строку молча - scan-gateway: счётчики → статусы - tabular-parser: счётчики → статусы @@ -460,7 +461,8 @@ sheet:,`. `DISCLOSURE` и форма без колонки кодов — **Единый выход:** `StatementLine {line_status, line_code, line_code_text, line_code_confidence, line_name, line_name_confidence, values}`: `line_code` — разобранный код (4–5 цифр) или `null` при `unreadable` / `missing`; -`line_code_text` — сырой текст ячейки кода; `line_status` = `code_status` шага 3. +`line_code_text` — сырой текст ячейки кода; `line_status` = `code_status` шага 3 (`ok` | `unreadable` | `missing`). +Несколько строк с одним кодом — обычные строки `ok`, порядок как в файле. - **1. Источник наименования** — одно правило: наименование — из файла, с уверенностью источника; справочник наименование не подменяет. Справочное имя по коду и редакции добавляет ядро из своего (единственного) словаря, экран показывает справочное, файловое — рядом (Р-3; AURORA-1406, 1522) - scan-gateway: имя из `statement_lines.yaml` → имя из OCR @@ -499,7 +501,8 @@ line_name_confidence, values}`: `line_code` — разобранный код (4 **Единый выход:** `StatementChecks` у обоих: `relations_failed[]`, `soft_relations_failed[]` (каждое нарушение — с кодами слагаемых и `column_index`, чтобы экран подсветил ячейки), `line_warnings[]` (код не из редакции формы по дате -отчёта, код не в словаре). `duplicate_line_codes` уходит в `line_status`. +отчёта, код не в словаре). `duplicate_line_codes` уходит: соотношения считаются по сумме значений одного кода в +колонке (повтор кода — законный случай, шаг 3 п. 3); нарушение подсвечивает все строки этого кода. - **1. Проверки только у парсера; словарь §7 в двух копиях; ядро результат не читает** — проверки — общий код с одним словарём `statement_checks.yaml` у обоих сервисов; для OCR нарушение §7 — главный признак неверно прочитанной цифры; ядро читает `checks` из результата и пересчитывает тем же кодом только после правок аналитика (PATCH) - scan-gateway: добавляет шаг @@ -553,13 +556,17 @@ column_index?}`, а не строка. ### Что уходит из ядра - `build_statement`: повторная дедупликация колонок, кодов и значений (контракт гарантирует уникальность колонок; - повторы строк приходят со статусом `duplicate`). + повторы кодов — законные строки, хранятся все как пришли). +- Повторы кодов (решение владельца 17.10.2026): в `financial_statement_line` хранятся все строки; уникальный индекс + `(meta_id, line_code)` из DBML v5.18 снимается (DBML v5.19, миграция). Для проверок §7, подтверждения и всего, что + идёт после (КФО, выгрузки, сверки), документ читается через агрегат по коду — сумма значений, справочное имя — + чистой функцией, без хранения (DECISION-5). Экран показывает строки как в файле. - `statement_status` (D-6): `RECOGNIZED` ⇔ `document.status = done` ∧ ИНН ≠ `MISMATCH` (единственное знание ядра); остальные признаки D-6 не пересчитываются. - §7 при загрузке: `checks` берутся из результата; пересчёт общим кодом — только после PATCH. - Словарь строк и словарь §7: единственный экземпляр в общем коде (Р-1); копии ядра и шлюза удаляются. -- Достройка шаблонных строк: по тому же словарю; строки `missing` / `unreadable` / `duplicate` показываются как - пришли, с подсветкой. +- Достройка шаблонных строк: по тому же словарю; строки `missing` / `unreadable` показываются как пришли, с + подсветкой; код, у которого есть хотя бы одна строка из файла, шаблоном не достраивается. - Экран: подсветка ячеек только по `needs_review` (уверенность, `is_recognized` и нарушения §7 уже сведены сервисом); строк — по `line_status`; предупреждения документа — с привязкой к месту. @@ -572,8 +579,9 @@ column_index?}`, а не строка. подсветка «не распознано», как сейчас (больше ложных подсветок, AURORA-1524). - **Р-3** (шаг 5, п. 1) — наименование: из файла в сервисах, справочное — в ядре (= решение № 2 по спринту 2, AURORA-1406 / 1522; договорённость ДБД «из справочника» выполняется на экране). -- **Р-4** (шаг 3, п. 3) — повторы кодов: сервисы отдают обе строки со статусом; показ обеих и сумма по договорённости - ДБД (AURORA-1431) — в ядре и на экране. +- **Р-4** (шаг 3, п. 3) — **решено владельцем 17.10.2026:** повторы кодов законны; все строки сохраняются и + показываются, для проверок и всех операций после подтверждения или автоподтверждения — суммой по коду. Следствие: + снять уникальность `(meta_id, line_code)` в DBML. - **Р-5** (шаг 8, п. 1) — порог уверенности для `done` (= решение № 7 по спринту 2, AURORA-1519 / 1524); предложение — 100, как сейчас. - **Р-6** (шаг 2, п. 6) — неизвестная числовая колонка без периода: оставлять без даты с предупреждением (`needs_check`)