From 9235e6ad796a4bbc216e443c664fbbaebf97b3d1 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Tue, 6 Oct 2026 21:25:40 +0400 Subject: [PATCH] =?UTF-8?q?docs:=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BD=D1=83?= =?UTF-8?q?=D0=BC=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D1=8F=20OQ-137=E2=80=A6142?= =?UTF-8?q?=20->=20OQ-138=E2=80=A6143=20(R-15)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Номер OQ-137 в main занят вопросом о раскладке горячих папок ИС Сканирование. Refs #26 Co-Authored-By: Claude Sonnet 5.5 Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b --- context/05-domain-rules.md | 16 +++++++-------- context/06-test-data.md | 10 +++++----- context/07-open-questions.md | 12 +++++------ context/09-delivery-plan.md | 8 ++++---- dev/qa-guide.md | 4 ++-- ...-10-06-slice-2b-statement-parser-ledger.md | 2 +- .../2026-10-06-slice-2b-statement-parser.md | 20 +++++++++---------- 7 files changed, 36 insertions(+), 36 deletions(-) diff --git a/context/05-domain-rules.md b/context/05-domain-rules.md index 4ec5bf7..f825e68 100644 --- a/context/05-domain-rules.md +++ b/context/05-domain-rules.md @@ -849,7 +849,7 @@ OQ-92 (пустые «Организация»/«Группа компаний» 2. **Колонка кодов**: в блоке ≥ 60 % непустых значений — коды (ББ 1100–1799, ОФР 2100–2999, расшифровки 5xxx, пятизначные — по первым четырём цифрам), кодов не меньше `min_codes` = 3; заголовок «Код/Коды» необязателен, числа вида `1110.0` читаются как текст «1110». Колонки нет — документ без строк, `needs_check`, предупреждение «колонка кодов не - найдена»; сопоставление по наименованиям строк **не делается** (решение владельца, OQ-138). + найдена»; сопоставление по наименованиям строк **не делается** (решение владельца, OQ-139). 3. **Колонка наименований** — ближайшая левее кодов с преобладанием текста; «Пояснения» (пустые или ≤ 3 символов) не наименование. 4. **Колонки-периоды**: ячейки заголовка правее кодов с распознанным периодом («На 31 декабря 2024 г.», «31.12.2024», @@ -859,9 +859,9 @@ OQ-92 (пустые «Организация»/«Группа компаний» («Изменение», «%») **не читаются** (одно предупреждение на документ): у `statementDocument` поля `extra` нет. 5. **Значения**: `Decimal`, скобки → минус, «–»/пусто → `null`, нечисловой текст → `string_value`, `is_recognized = false`. **Единицы не нормализуются**: `amount` как в ячейке, `header.units` — текст шапки; при «тыс.» и - ≥ 10 % значений с дробной частью — предупреждение «значений с дробной частью при единице тыс. руб.: N из M» (OQ-137, + ≥ 10 % значений с дробной частью — предупреждение «значений с дробной частью при единице тыс. руб.: N из M» (OQ-138, решение владельца). Строки без кода (разделы, «в том числе:», «Реализация иного имущества…» у НПЗ) не отдаются - (`ASSUMPTION(OQ-36)`, OQ-140); повтор кода — остаётся первая строка, код в `checks.duplicate_line_codes`, `needs_check`. + (`ASSUMPTION(OQ-36)`, OQ-141); повтор кода — остаётся первая строка, код в `checks.duplicate_line_codes`, `needs_check`. Пятизначные подстроки (11101, 12301…) отдаются как обычные строки. 6. **Шапка**: организация (после метки «Организация», иначе текст с признаком ОПФ строкой выше метки — НПЗ), ИНН 10/12 цифр у метки «ИНН» (**ИНН аудитора не берётся**: строки после метки «аудитор» исключены), ОКПО, ОКОПФ/ОКФС, ОКЕИ, адрес, @@ -877,7 +877,7 @@ OQ-92 (пустые «Организация»/«Группа компаний» `documents[].checks` (`relations_failed`, `soft_relations_failed`, `duplicate_line_codes`) и предупреждения. **Фактически сходятся полные формы только у Межениновской**: книга НПЗ (`npz/2025-Q3`) — ББ `needs_check`: `1600 = 1700` расходится на 1.94 / 9.02 / 2.48 руб., потому что значения в рублях с копейками при шапке «тыс. руб.»; допуск ±1 остаётся - (решение владельца 06.10.2026, вариант А, OQ-137). ОФР НПЗ и ОФР Унагранде (стр. 1) тоже `needs_check` по 2100/2200/2300 + (решение владельца 06.10.2026, вариант А, OQ-138). ОФР НПЗ и ОФР Унагранде (стр. 1) тоже `needs_check` по 2100/2200/2300 по той же причине; ББ Унагранде (стр. 1) — только актив, `1600 = 1700` не сходится. Это сигнал о данных файла, а не о неверно угаданной структуре; допуск под файл не подгоняется. 8. **Расшифровки** (0710003/0710004, пояснения, лист «Примечания» шаблона) — `DISCLOSURE` с `locator` и шапкой, если @@ -885,15 +885,15 @@ OQ-92 (пустые «Организация»/«Группа компаний» 9. **Склейка**: листы-продолжения внутри книги присоединяются к последнему открытому документу формы, если число колонок сумм совпадает; строки добавляются в конец, `locator` перечисляет листы через запятую. **Страницы в разных файлах не склеиваются** (1С печатает форму постранично, один файл = одна страница): страница 2 без первой — документ с пустой шапкой - и `needs_check`, предупреждение «страница-продолжение без шапки: загрузите форму одним файлом» (решение владельца, OQ-139). + и `needs_check`, предупреждение «страница-продолжение без шапки: загрузите форму одним файлом» (решение владельца, OQ-140). Продолжение без колонки кодов при непустом результате не теряется молча — `needs_check`. 10. **Статус**: документ `ok` ⇔ жёсткие соотношения сошлись по всем колонкам ∧ нет дубликатов кодов ∧ найдена колонка кодов ∧ есть колонка-период ∧ в шапке есть организация или ИНН ∧ документ не одинокое продолжение. Книга — `done`, если `ok` у всех документов, иначе `needs_check`; книга без листов ОСВ и форм — `INVALID_DOCUMENT`. Порядок документов: сначала ОСВ в порядке листов, затем формы. Шаблоны (коды есть, сумм нет, шапки нет) — `needs_check`. -11. **Отложено**: запасной путь по именам строк (OQ-138), нормализация единиц (OQ-137), признак продолжения в контракте и - склейка страниц из разных файлов в ядре (OQ-139, Срез 3), строки без кода (OQ-140), образцы ФСБУ (OQ-141), лист - продолжения с единственной кодовой строкой (OQ-142: лист ОФР НПЗ с одной строкой 2400 не распознаётся как форма и +11. **Отложено**: запасной путь по именам строк (OQ-139), нормализация единиц (OQ-138), признак продолжения в контракте и + склейка страниц из разных файлов в ядре (OQ-140, Срез 3), строки без кода (OQ-141), образцы ФСБУ (OQ-142), лист + продолжения с единственной кодовой строкой (OQ-143: лист ОФР НПЗ с одной строкой 2400 не распознаётся как форма и теряется, `min_codes` = 3). Что это даёт ядру: один маппинг `statementDocument → document + financial_statement_*` для PDF и Excel (маппинг форм — diff --git a/context/06-test-data.md b/context/06-test-data.md index f8967b3..2226cf2 100644 --- a/context/06-test-data.md +++ b/context/06-test-data.md @@ -156,14 +156,14 @@ arm-tabular-parser#11, OQ-131…OQ-135. ИНН организаций в шап | Раскладка | Где | Особенности | |---|---|---| | 1С-xls постранично | `unagrande-co/2024-FY/`, `unagrande-group/{2024-FY,2025-Q3}/` | один файл = одна страница формы; на странице 1 титул (организация, ИНН, ОКПО, единица «в тыс. рублей», ОКЕИ, аудитор со **своим** ИНН), на странице 2 только «Форма 0710001 с.2»; пятизначные подстроки (11101…), значения в рублях с копейками при «тыс. руб.»; страниц 1 ББ в пакете нет (только актив) и ОФР Групп 2024 — только стр. 2 | -| Многолистовая xlsx ФСБУ 4/2023 | `npz/2025-Q3/` | ББ на 5 листах, ОФР на 3; заголовок формы после титула; листы 2–5 без заголовка и маркера; строка 1105 «Гудвил», подстроки 12301…, строка без кода с суммами; лист ОФР с одной строкой 2400 (OQ-142) | +| Многолистовая xlsx ФСБУ 4/2023 | `npz/2025-Q3/` | ББ на 5 листах, ОФР на 3; заголовок формы после титула; листы 2–5 без заголовка и маркера; строка 1105 «Гудвил», подстроки 12301…, строка без кода с суммами; лист ОФР с одной строкой 2400 (OQ-143) | | `TDSheet` 66н | `mezheninovskaya/2025-Q3/` | вся форма на одном листе, дата тройкой «30 \| 9 \| 2025» числами, двухстрочные заголовки, строка нумерации колонок, значения — тысячи с дробной частью | -| Шаблоны | `templates/` | 66н и ФСБУ 4/2023: коды есть, сумм и шапки нет; заголовок на две строки; в шаблоне ФСБУ «АКТИВ» и код 1110 в одной строке (OQ-141) | +| Шаблоны | `templates/` | 66н и ФСБУ 4/2023: коды есть, сумм и шапки нет; заголовок на две строки; в шаблоне ФСБУ «АКТИВ» и код 1110 в одной строке (OQ-142) | **Манифест** `tabular-parser/api/tests/statements_manifest.yaml`: для каждого из 18 файлов — организация, ИНН, документы по порядку (`type`, `status`, `complete`, причина `needs_check`, `failed_relations`). Статусы сверены прогоном: `done` только у Межениновской (ББ и ОФР); остальные — `needs_check` по данным файла (рубли с копейками при шапке «тыс. руб.», только -актив, страница 2 без шапки, шаблон без сумм), НПЗ — `1600 = 1700` расходится на 1.94 / 9.02 / 2.48 руб. (OQ-137). +актив, страница 2 без шапки, шаблон без сумм), НПЗ — `1600 = 1700` расходится на 1.94 / 9.02 / 2.48 руб. (OQ-138). Таблица «файл → статус» — README `tabular-parser`, «Парсер форм». **Golden** `fixtures/golden/expected_statement_parse/<тот же путь без расширения>.json` — 24 снимка (18 реальных файлов + @@ -178,9 +178,9 @@ arm-tabular-parser#11, OQ-131…OQ-135. ИНН организаций в шап |---|---| | `st01_both_forms_one_sheet` | ББ и ОФР на одном листе, два документа с одним `locator` (§12 п. 1) | | `st02_csv_like` | csv-подобный лист: двухстрочный заголовок, коды без подписи «Код», отрицательное значение, единиц нет | -| `st03_no_codes` | форма без колонки кодов → `needs_check`, «колонка кодов не найдена» (OQ-138) | +| `st03_no_codes` | форма без колонки кодов → `needs_check`, «колонка кодов не найдена» (OQ-139) | | `st04_mixed_book` | книга: лист ОСВ + лист баланса, порядок документов ОСВ → форма | -| `st05_continuation_only` | одинокая страница 2 → `needs_check`, предупреждение о продолжении (OQ-139) | +| `st05_continuation_only` | одинокая страница 2 → `needs_check`, предупреждение о продолжении (OQ-140) | | `st06_header_variants` | варианты, которых нет в реальных файлах: старое название ОФР, расшифровки/ОДДС/ОИК, форма только с ОКУД 0710xxx, организация в «», «Адрес», «Пояснения», числовая дата (покрытие словарей `statement_*.yaml`) | ## 5. Прочее diff --git a/context/07-open-questions.md b/context/07-open-questions.md index 32515cd..c8aec64 100644 --- a/context/07-open-questions.md +++ b/context/07-open-questions.md @@ -143,12 +143,12 @@ | OQ-135 | Отчёт 1С «Анализ счета» с отбором по контрагентам группы (`fixtures/analysis-reports/`, в именах файлов «ОСВ_…ПоКомпаниямГруппы»): не ОСВ, но содержит ВГО по корреспонденции счетов. Нужен ли отдельный тип документа для Среза 5, или ВГО считаются только из ОСВ | пакет ДКБ 06.10.2026 | `document_type`, Срез 5 | открыт: допущение — не разбирать; парсер отвечает `INVALID_DOCUMENT` | | OQ-136 | ИНН организаций пакета ДКБ (Цимлянский, НКЗ, Новоросметалл, Приманыческий, Агрокомплекс) в шапках ОСВ отсутствуют; для теста консолидации по этим группам нужны ИНН и состав ГК/ГСК (выгрузка ЕЦП или список от ДКБ) | пакет ДКБ 06.10.2026 | seed/фикстуры справочников, тесты Среза 4–5 на новых группах | открыт | | OQ-137 | Раскладка горячих папок ИС Сканирование: scan-gateway кладёт `Input/_` через временный `Tmp/.<имя>.part`, ничего не удаляет; PDFWorker старого АРМ (`RSHB/armka_file_worker`, проверен в контуре) кладёт `Input/.` через временный `<назначение>..tmp` рядом (ИС игнорирует `*.tmp`), читает батч `Output//*.json` и удаляет `Output//` и входящий файл после чтения. Какая раскладка актуальна? | сравнение `armka_file_worker` (README «Файлы», `clients.py`) и `scan-gateway/gateway/hotfolder.py`, `smb.py`; OQ-78, OQ-79 | scan-gateway (спека `image-recognition-gateway`, эмулятор, тесты) | **закрыт владельцем 06.10.2026: «правильно как в FileWorker»** — имя `.`, временный `*.tmp` рядом с назначением (каталог `Tmp` из OQ-79 не нужен), очистка `Output//` и входящего файла после чтения; `Output//*.json` батчем и стабилизация набора (OQ-78) остаются. Реализация — arm-scan-gateway #6 | -| OQ-137 | Единицы «тыс. руб.» в шапке против значений в рублях с копейками в выгрузках 1С (Унагранде Компани/Групп, НПЗ) и тысяч с дробями (Межениновская): кто и где приводит единицы. Примеры: книга НПЗ (`npz/2025-Q3`) — ББ `needs_check`, `1600 = 1700` расходится на 1.94 / 9.02 / 2.48 руб.; ОФР НПЗ и ОФР Унагранде (стр. 1) — `needs_check` по 2100/2200/2300 по той же причине; полные формы по факту сходятся только у Межениновской | `fixtures/statements-xlsx/README.md`, tabular-parser design 2b D-6, D-7, решения №22–24 (R-11, R-13, R-14) | Срез 3 (маппинг форм), §8 (КФО в тыс. руб.) | допущение принято (решение владельца 06.10.2026, вариант А): парсер отдаёт значения и `units` как в файле, при «тыс.» и ≥ 10 % значений с дробной частью — предупреждение; допуск ±1 не меняется, не нормализуем; приведение единиц — ядро/аналитик (Срез 3) | -| OQ-138 | Форма без колонки кодов: сопоставление по именам строк из шаблонов 66н/ФСБУ (словарь `statement_lines.yaml`, `line_code_confidence < 100`)? Сейчас документ без строк и `needs_check` («колонка кодов не найдена») | решение владельца 06.10.2026 (вопрос 6), tabular-parser design 2b D-4 | §12 п. 2, Срез 3 | открыт: нужен реальный файл без колонки кодов; допущение — не сопоставлять по именам | -| OQ-139 | Страница-продолжение в отдельном файле (1С печатает ББ/ОФР постранично, один файл = страница): склейка в ядре по ЮЛ + период + тип формы; признак `is_continuation` / `form_page` в контракте (MINOR, две необязательных поля) | решение владельца 06.10.2026 (вопрос 2), design 2b D-8 | §12 п. 9, Срез 3, контракт v1.x | допущение принято: страницы разных файлов не склеиваются; страница 2 без шапки — документ с пустой шапкой и `needs_check`, «загрузите форму одним файлом» | -| OQ-140 | Строка без кода, но с суммами в ОФР ФСБУ 4/2023 (НПЗ «Реализация иного имущества…»): хранить ли (OQ-36 расширяется с расшифровочных строк на строки с суммами) | `fixtures/statements-xlsx/npz`, design 2b D-6 | Срез 3, DBML `financial_statement_line` (хранит только строки с кодом) | допущение принято: строки без кода не отдаются, при наличии сумм — предупреждение «строк без кода с суммами пропущено: N» | -| OQ-141 | Образец ФСБУ 4/2023 (`templates/ББ после 01.01.2025.xlsx`): «АКТИВ» и код 1110 в одной строке из-за объединённых ячеек; шаблоны (коды есть, сумм и шапки нет) не данные. Нужен ли их разбор вообще | `fixtures/statements-xlsx/templates`, design 2b D-8 | §12 п. 10, тесты | допущение принято: шаблоны дают `needs_check` (шапка пустая, значения `null`); разбор шаблонов как источника данных не планируется, пока владелец не скажет иначе | -| OQ-142 | Лист продолжения с **единственной** кодовой строкой (книга НПЗ: лист ОФР с одной строкой 2400): `min_codes` = 3 → лист не распознаётся как форма и пропускается, строка 2400 теряется при `needs_check` документа. Понизить порог / принимать лист по близости к открытому документу ОФР / маркеру продолжения | tabular-parser design 2b: решение №25, O-9 | §12 п. 2, п. 9; полнота ОФР НПЗ | открыт: отложено на финальное ревью 2b; допущение — строка 2400 листа продолжения НПЗ в результате отсутствует | +| OQ-138 | Единицы «тыс. руб.» в шапке против значений в рублях с копейками в выгрузках 1С (Унагранде Компани/Групп, НПЗ) и тысяч с дробями (Межениновская): кто и где приводит единицы. Примеры: книга НПЗ (`npz/2025-Q3`) — ББ `needs_check`, `1600 = 1700` расходится на 1.94 / 9.02 / 2.48 руб.; ОФР НПЗ и ОФР Унагранде (стр. 1) — `needs_check` по 2100/2200/2300 по той же причине; полные формы по факту сходятся только у Межениновской | `fixtures/statements-xlsx/README.md`, tabular-parser design 2b D-6, D-7, решения №22–24 (R-11, R-13, R-14) | Срез 3 (маппинг форм), §8 (КФО в тыс. руб.) | допущение принято (решение владельца 06.10.2026, вариант А): парсер отдаёт значения и `units` как в файле, при «тыс.» и ≥ 10 % значений с дробной частью — предупреждение; допуск ±1 не меняется, не нормализуем; приведение единиц — ядро/аналитик (Срез 3) | +| OQ-139 | Форма без колонки кодов: сопоставление по именам строк из шаблонов 66н/ФСБУ (словарь `statement_lines.yaml`, `line_code_confidence < 100`)? Сейчас документ без строк и `needs_check` («колонка кодов не найдена») | решение владельца 06.10.2026 (вопрос 6), tabular-parser design 2b D-4 | §12 п. 2, Срез 3 | открыт: нужен реальный файл без колонки кодов; допущение — не сопоставлять по именам | +| OQ-140 | Страница-продолжение в отдельном файле (1С печатает ББ/ОФР постранично, один файл = страница): склейка в ядре по ЮЛ + период + тип формы; признак `is_continuation` / `form_page` в контракте (MINOR, две необязательных поля) | решение владельца 06.10.2026 (вопрос 2), design 2b D-8 | §12 п. 9, Срез 3, контракт v1.x | допущение принято: страницы разных файлов не склеиваются; страница 2 без шапки — документ с пустой шапкой и `needs_check`, «загрузите форму одним файлом» | +| OQ-141 | Строка без кода, но с суммами в ОФР ФСБУ 4/2023 (НПЗ «Реализация иного имущества…»): хранить ли (OQ-36 расширяется с расшифровочных строк на строки с суммами) | `fixtures/statements-xlsx/npz`, design 2b D-6 | Срез 3, DBML `financial_statement_line` (хранит только строки с кодом) | допущение принято: строки без кода не отдаются, при наличии сумм — предупреждение «строк без кода с суммами пропущено: N» | +| OQ-142 | Образец ФСБУ 4/2023 (`templates/ББ после 01.01.2025.xlsx`): «АКТИВ» и код 1110 в одной строке из-за объединённых ячеек; шаблоны (коды есть, сумм и шапки нет) не данные. Нужен ли их разбор вообще | `fixtures/statements-xlsx/templates`, design 2b D-8 | §12 п. 10, тесты | допущение принято: шаблоны дают `needs_check` (шапка пустая, значения `null`); разбор шаблонов как источника данных не планируется, пока владелец не скажет иначе | +| OQ-143 | Лист продолжения с **единственной** кодовой строкой (книга НПЗ: лист ОФР с одной строкой 2400): `min_codes` = 3 → лист не распознаётся как форма и пропускается, строка 2400 теряется при `needs_check` документа. Понизить порог / принимать лист по близости к открытому документу ОФР / маркеру продолжения | tabular-parser design 2b: решение №25, O-9 | §12 п. 2, п. 9; полнота ОФР НПЗ | открыт: отложено на финальное ревью 2b; допущение — строка 2400 листа продолжения НПЗ в результате отсутствует | Служебные идентификаторы в DBML/аналитике: `ANL-nnn` — замечания аналитика к макету; `ARCH-nnn` — архитектурные решения; `DECISION-n` — решения по модели; `FIX-nn` — исправления дефектов v4. diff --git a/context/09-delivery-plan.md b/context/09-delivery-plan.md index e266480..45d42a2 100644 --- a/context/09-delivery-plan.md +++ b/context/09-delivery-plan.md @@ -120,10 +120,10 @@ Change'и: `tabular-parser/openspec/changes/slice-2a-osv-parser` (issue arm-tabu golden `expected_statement_parse/` (18 + 6 снимков), интеграционный тест воркера на книге НПЗ. - **Объём:** парсер + контракт v1.2; **маппинг форм в ядре (`statementDocument → document + financial_statement_*`) — Срез 3**. По факту `done` только у форм Межениновской; остальные `needs_check` по данным файлов (рубли с копейками при - «тыс. руб.», страницы без шапки, шаблоны) — OQ-137, OQ-139. -- **Не сделано / риски:** единицы не нормализуются (OQ-137); форма без колонки кодов не разбирается (OQ-138); страницы - в разных файлах не склеиваются (OQ-139); строки без кода не хранятся (OQ-140); лист ОФР НПЗ с единственной строкой 2400 - теряется (OQ-142); после контракта v1.2 `docs/contracts/**` заморожены (копии схемы в arm-core и scan-gateway должны совпадать с ними; в tabular-parser версия закреплена тестом `api/tests/unit/test_contract_v12.py`, побайтное сравнение копий — вручную через `diff` при раскатке); косметика T1.1/T2.x уходит в следующий MINOR. + «тыс. руб.», страницы без шапки, шаблоны) — OQ-138, OQ-140. +- **Не сделано / риски:** единицы не нормализуются (OQ-138); форма без колонки кодов не разбирается (OQ-139); страницы + в разных файлах не склеиваются (OQ-140); строки без кода не хранятся (OQ-141); лист ОФР НПЗ с единственной строкой 2400 + теряется (OQ-143); после контракта v1.2 `docs/contracts/**` заморожены (копии схемы в arm-core и scan-gateway должны совпадать с ними; в tabular-parser версия закреплена тестом `api/tests/unit/test_contract_v12.py`, побайтное сравнение копий — вручную через `diff` при раскатке); косметика T1.1/T2.x уходит в следующий MINOR. ### Срез 2c — Загрузка файлов и маппинг результата в ядре (`arm-core`) — реализован, ожидает ревью и merge diff --git a/dev/qa-guide.md b/dev/qa-guide.md index d508065..8e3fdaa 100644 --- a/dev/qa-guide.md +++ b/dev/qa-guide.md @@ -386,11 +386,11 @@ ENV_FILE=.env.test .venv/bin/python -m src.parser.cli "/путь/к/файлу.x Что смотреть: `document_type` соответствует форме на листе; `columns[].period_date` — даты колонок слева направо (для ОФР — конец периода); `checks.relations_failed` (жёсткие соотношения §7 с `expected`/`actual` по колонкам — причина `needs_check`), `checks.soft_relations_failed` и `duplicate_line_codes`; в `metrics.warnings` — предупреждение об единицах («значений с -дробной частью при единице тыс. руб.: N из M»: значения как в файле, не нормализованы, OQ-137), «колонка кодов не найдена», +дробной частью при единице тыс. руб.: N из M»: значения как в файле, не нормализованы, OQ-138), «колонка кодов не найдена», «страница-продолжение без шапки». Ожидания по реальным файлам — `../tabular-parser/api/tests/statements_manifest.yaml` и таблица «файл → статус» в README `tabular-parser`; файлы — `../fixtures/statements-xlsx/` (синтетика `st01…st06`). Постраничные xls из 1С (страница 2 отдельным файлом, ББ только актив) и формы в рублях при шапке «тыс. руб.» дают -`needs_check` — это штатно (OQ-137, OQ-139), не баг; `done` ожидается только у форм, где §7 сходится (Межениновская). +`needs_check` — это штатно (OQ-138, OQ-140), не баг; `done` ожидается только у форм, где §7 сходится (Межениновская). **Как делать свои файлы.** Возьмите любую реальную ОСВ и меняйте по одному признаку, после каждого — прогон и чек-лист: diff --git a/docs/superpowers/plans/2026-10-06-slice-2b-statement-parser-ledger.md b/docs/superpowers/plans/2026-10-06-slice-2b-statement-parser-ledger.md index 342c73d..ee552ae 100644 --- a/docs/superpowers/plans/2026-10-06-slice-2b-statement-parser-ledger.md +++ b/docs/superpowers/plans/2026-10-06-slice-2b-statement-parser-ledger.md @@ -116,7 +116,7 @@ Task 12: implementer sonnet DONE_WITH_CONCERNS 10b5bda; make check: 2 failed (go Task 12: review dispatched (sonnet) Task 12: review sonnet: spec ✅, Approved (Critical/Important нет). Review Focus 4, 5 покрыты тестами (мутации M1–M5 падают). Ruling: R-10 — отклонения Task 12 принимаются (флаг dropped: продолжение без колонки кодов → needs_check книги; OTHER-продолжение по правилам ББ; form_name не передаётся) и вносятся в design (#21) — цена ошибки: лишний needs_check на редком листе. -Ruling: R-11 — НПЗ даёт needs_check (1600=1700 расходится на 1.94/9.02/2.48 ₽ в источнике; значения в рублях с копейками при «тыс. руб.»), допуск ±1 по спеке НЕ меняется; ожидание манифеста НПЗ в задаче 14 — needs_check с причиной; выносится владельцу (OQ-137) — цена ошибки: если владелец хочет done — допуск/нормировка в словаре (design #22). +Ruling: R-11 — НПЗ даёт needs_check (1600=1700 расходится на 1.94/9.02/2.48 ₽ в источнике; значения в рублях с копейками при «тыс. руб.»), допуск ±1 по спеке НЕ меняется; ожидание манифеста НПЗ в задаче 14 — needs_check с причиной; выносится владельцу (OQ-138) — цена ошибки: если владелец хочет done — допуск/нормировка в словаре (design #22). Task 12: golden s12/s14 (синтетика, документы форм вместо заглушки) пересозданы контроллером (make golden-update, diff просмотрен: только s12/s14, статусы done→needs_check и документы форм без колонки кодов), коммит fixtures-wt "test(golden): s12/s14". Task 12: minor T12.1 (deferred): мёртвые счётчики fractional_values/numeric_values в Draft; предупреждение о дробной части считается по листу, не по документу (спека — «по документу»? уточнить в финале). T12.2 (deferred): ветка lonely_continuation в _is_ok избыточна — комментарий/тест. T12.3 (deferred): can_join игнорирует тип формы при маркере продолжения другого типа. T12.4 (deferred): join O(n·m). T12.5 (deferred): побочный эффект _document дописывает draft.warnings. T12.6 (deferred): test_template_without_sums_is_needs_check вакуумен при пустых lines. T12.7 (deferred): docstring после assert в synthetic documents(). T12.8 (deferred): повторяющийся приём form_name в header.py. T12.9 (deferred): нет теста дубликата внутри продолжения. O-7: D-8 «лист ОСВ между страницами → одиночка» не реализуем интерфейсом (формы получают только листы форм). Task 12: complete (commits b9e6e31..10b5bda + fixtures golden s12/s14, review clean) diff --git a/docs/superpowers/plans/2026-10-06-slice-2b-statement-parser.md b/docs/superpowers/plans/2026-10-06-slice-2b-statement-parser.md index 2878e1b..dc538ff 100644 --- a/docs/superpowers/plans/2026-10-06-slice-2b-statement-parser.md +++ b/docs/superpowers/plans/2026-10-06-slice-2b-statement-parser.md @@ -3521,20 +3521,20 @@ Refs #14" ### Task 16: Документы docs — §12, §7, 06-test-data, 03-architecture, 09-delivery-plan, OQ, qa-guide **Files (DOCS):** -- Modify: `docs/context/05-domain-rules.md` (§12 целиком, пометки в §7), `docs/context/06-test-data.md` (новый подраздел «4б. Формы ББ/ОФР в Excel: манифест, golden, синтетика» после 4а и строка в §7 про `expected_statement_parse`), `docs/context/03-architecture.md` (контракт 1.2, `BookParser`), `docs/context/09-delivery-plan.md` (Срез 2b — статус и объём), `docs/context/07-open-questions.md` (OQ-137…OQ-141, статус OQ-131), `docs/dev/qa-guide.md` §6.7 (абзац про формы) +- Modify: `docs/context/05-domain-rules.md` (§12 целиком, пометки в §7), `docs/context/06-test-data.md` (новый подраздел «4б. Формы ББ/ОФР в Excel: манифест, golden, синтетика» после 4а и строка в §7 про `expected_statement_parse`), `docs/context/03-architecture.md` (контракт 1.2, `BookParser`), `docs/context/09-delivery-plan.md` (Срез 2b — статус и объём), `docs/context/07-open-questions.md` (OQ-138…OQ-142, статус OQ-131), `docs/dev/qa-guide.md` §6.7 (абзац про формы) - [ ] **Step 1: §12 — заменить текст пунктов 1–8 и добавить 9–11** Структура нового §12 (каждый пункт — решение из design D-2…D-8 и brainstorming 06.10.2026): 1. Классификация листов: ОСВ → форма (заголовок/ОКУД в любой строке до таблицы; титул «Бухгалтерская отчетность» не тип) → продолжение (маркер «с.2», подпись «Код» с периодами, колонка кодов) → прочее. Типы: 0710001 → BALANCE, 0710002 → INCOME, прочие 0710xxx и пояснения → DISCLOSURE. Две формы на листе — по второму заголовку. -2. Колонка кодов: ≥ 60 % непустых значений — коды (ББ 1100–1799, ОФР 2100–2999, расшифровки 5xxx, пятизначные по первым четырём цифрам), ≥ 3 кодов. Нет колонки — `needs_check`, «колонка кодов не найдена»; сопоставление по именам отложено (OQ-138). +2. Колонка кодов: ≥ 60 % непустых значений — коды (ББ 1100–1799, ОФР 2100–2999, расшифровки 5xxx, пятизначные по первым четырём цифрам), ≥ 3 кодов. Нет колонки — `needs_check`, «колонка кодов не найдена»; сопоставление по именам отложено (OQ-139). 3. Колонка наименований и «Пояснения» — как было. 4. Колонки-периоды: подпись «Код» и ячейки-периоды правее; двухстрочный заголовок склеивается; строка нумерации пропускается; `period_date` — дата или конец периода; колонки без периода не читаются (предупреждение; `extra` у форм нет). -5. Значения: Decimal, скобки → минус, прочерк → null; **единицы как в файле, не нормализуются**; при «тыс.» и ≥ 10 % значений с дробной частью — предупреждение (решение владельца 06.10.2026, OQ-137). +5. Значения: Decimal, скобки → минус, прочерк → null; **единицы как в файле, не нормализуются**; при «тыс.» и ≥ 10 % значений с дробной частью — предупреждение (решение владельца 06.10.2026, OQ-138). 6. Шапка: метки, ИНН не аудитора, организация над меткой, дата из подзаголовка или тройки. 7. Самопроверка: соотношения §7 — данные `statement_checks.yaml`, жёсткие/мягкие, допуск ±1, двойной расчёт знаков (`abs_terms`), подстроки «в том числе» как мягкая проверка; результат — `statementDocument.checks` (v1.2) и предупреждения. 8. Расшифровки — DISCLOSURE без строк (OQ-23). -9. Склейка: листы-продолжения внутри книги присоединяются к последнему открытому документу при равном числе колонок; `locator` перечисляет листы; **страницы в разных файлах не склеиваются**: страница без шапки — документ с пустой шапкой и `needs_check` (решение владельца, OQ-139). +9. Склейка: листы-продолжения внутри книги присоединяются к последнему открытому документу при равном числе колонок; `locator` перечисляет листы; **страницы в разных файлах не склеиваются**: страница без шапки — документ с пустой шапкой и `needs_check` (решение владельца, OQ-140). 10. Статус: критерий `ok` (D-8); книга `done`/`needs_check`; `INVALID_DOCUMENT` без ОСВ и форм; порядок документов — ОСВ, затем формы. 11. Отложено: запасной путь по именам, нормализация единиц, признак продолжения в контракте, склейка в ядре (Срез 3). @@ -3543,11 +3543,11 @@ Refs #14" - [ ] **Step 2: OQ** Добавить строки (формат таблицы как у OQ-136): -- OQ-137 — единицы «тыс. руб.» в шапке против значений в рублях с копейками в 1С-выгрузках (Унагранде, НПЗ) и тысяч с дробями (Межениновская): кто и где приводит; парсер отдаёт как есть + предупреждение; ядро/аналитик — Срез 3. Откуда: `statements-xlsx/README.md`, design 2b D-6. Влияет: Срез 3, §8 (КФО в тыс. руб.). Допущение: не нормализовать. -- OQ-138 — форма без колонки кодов: словарь имён строк из шаблонов 66н/ФСБУ (`statement_lines.yaml`), `line_code_confidence < 100`; сейчас `needs_check`. Нужен реальный файл. -- OQ-139 — страница-продолжение в отдельном файле (1С печатает ББ/ОФР постранично): склейка в ядре по ЮЛ+период+тип, признак `is_continuation`/`form_page` в контракте (MINOR). Сейчас `needs_check`. -- OQ-140 — строка без кода с суммами в ОФР ФСБУ 4/2023 (НПЗ «Реализация иного имущества…»): хранить ли (OQ-36 расширяется на суммы). -- OQ-141 — образец ФСБУ 4/2023 (шаблон): «АКТИВ» и код 1110 в одной строке из-за объединений; шаблоны не являются данными, парсер даёт `needs_check`; нужен ли их разбор вообще. +- OQ-138 — единицы «тыс. руб.» в шапке против значений в рублях с копейками в 1С-выгрузках (Унагранде, НПЗ) и тысяч с дробями (Межениновская): кто и где приводит; парсер отдаёт как есть + предупреждение; ядро/аналитик — Срез 3. Откуда: `statements-xlsx/README.md`, design 2b D-6. Влияет: Срез 3, §8 (КФО в тыс. руб.). Допущение: не нормализовать. +- OQ-139 — форма без колонки кодов: словарь имён строк из шаблонов 66н/ФСБУ (`statement_lines.yaml`), `line_code_confidence < 100`; сейчас `needs_check`. Нужен реальный файл. +- OQ-140 — страница-продолжение в отдельном файле (1С печатает ББ/ОФР постранично): склейка в ядре по ЮЛ+период+тип, признак `is_continuation`/`form_page` в контракте (MINOR). Сейчас `needs_check`. +- OQ-141 — строка без кода с суммами в ОФР ФСБУ 4/2023 (НПЗ «Реализация иного имущества…»): хранить ли (OQ-36 расширяется на суммы). +- OQ-142 — образец ФСБУ 4/2023 (шаблон): «АКТИВ» и код 1110 в одной строке из-за объединений; шаблоны не являются данными, парсер даёт `needs_check`; нужен ли их разбор вообще. - OQ-131 — статус: «границы периода `period_start/period_end/is_from_year_start` в контракте v1.2 (docs change 2b); парсер заполняет (PR #13 + 2b); ядро — привязка скользящего документа к версии остаётся открытой». - [ ] **Step 3: 03-architecture, 09-delivery-plan, 06-test-data, qa-guide** @@ -3558,7 +3558,7 @@ Refs #14" ```bash git -C DOCS add docs/context docs/dev -git -C DOCS commit -m "docs(2b): §12 по решениям владельца, §7 жёсткие/мягкие, 06-test-data формы, 03-architecture v1.2, OQ-137…141 +git -C DOCS commit -m "docs(2b): §12 по решениям владельца, §7 жёсткие/мягкие, 06-test-data формы, 03-architecture v1.2, OQ-138…143 Refs #26" ```