Andrey Epifancev 76b2b36f21 openspec: спека Среза 2b — парсер ББ и ОФР из Excel (statement-parsing), контракт v1.2
Proposal, design (D-1…D-11, решения без обсуждения №1–№11), новая capability statement-parsing,
дельта tabular-recognition-service (BookParser, schema_version 1.2), tasks. Решения владельца 06.10.2026:
только парсер и контракт; страницы-продолжения без склейки между файлами; единицы как есть; пятизначные
подстроки как строки; контракт MINOR 1.2; без запасного пути по именам.

Refs #14

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
2026-10-06 13:21:27 +04:00

75 lines
8.1 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.

# Proposal: Срез 2b — парсер ББ и ОФР из Excel (§12), контракт v1.2
**Срез:** 2 «Загрузка файлов + табличный парсер», подсрез 2b (`../docs/context/09-delivery-plan.md`). **Репозиторий:**
arm-tabular-parser. **Issue:** RSHB/arm-tabular-parser#14. **Сквозной change:** `../docs/openspec/changes/slice-2b-statement-parser`
(контракт v1.2, §12, OQ; RSHB/arm-ka-docs#26). Golden и синтетика — отдельный PR в arm-ka-fixtures. Копии схемы v1.2 —
bounded-PR в arm-core и arm-scan-gateway (без изменения поведения) до мержа этого change.
Решение владельца 06.10.2026 (brainstorming): объём среза — **только парсер и контракт**; маппинг `statementDocument` в
ядро остаётся в Срезе 3.
## Why
После Среза 2a сервис разбирает только ОСВ, а листы с признаками ББ/ОФР пропускает с предупреждением
`skipped: statement (slice 2b)`. Без форм из Excel нет пути «отчётность компании → консолидация»: ББ и ОФР дают строки
КФО (§8), гудвилл (1310) и логические проверки (§7). В fixtures есть 15 реальных файлов пакета ДКБ в трёх раскладках
(постраничные xls 1С, многолистовая книга ФСБУ 4/2023, выгрузка `TDSheet`) и четыре пустых шаблона 66н / ФСБУ 4/2023 —
на них парсер обязан проходить без единого правила под файл, организацию или имя листа (§1.0, §12).
## What Changes
- **Оркестратор книги** `api/src/parser/book.py` (`BookParser`): лимит размера, чтение книги, дедлайн, классификация
листов (`detect.classify_sheet`), раздача листов конвейерам ОСВ и форм, сбор документов, предупреждений, метрик и
статуса. `OsvParser` сужается до конвейера листа ОСВ (`parse_sheet`); `get_parser()` возвращает `BookParser`.
- **Конвейер форм** `api/src/parser/statements/` (`StatementParser`): заголовок формы и ОКУД, колонка кодов,
шапка документа, колонки-периоды, строки и значения, соотношения §7, склейка листов-продолжений внутри книги,
расшифровки как `DISCLOSURE`.
- **Словари** `api/rules/statement_headers.yaml`, `statement_periods.yaml`, `statement_checks.yaml` (соотношения §7 —
данные, не код) с pydantic-валидацией при старте и тестом покрытия.
- **Контракт v1.2** (копия `api/contracts/`, `CONTRACT_VERSION = "1.2"`): `statementDocument.document_type` +
`DISCLOSURE`; `statementDocument.checks`; `osvDocument.header.period_start/period_end/is_from_year_start`.
- **Тесты**: unit по модулям на синтетических сетках; property-тест на всех `../fixtures/statements-xlsx/**` по манифесту;
golden `../fixtures/golden/expected_statement_parse/`; синтетика `../fixtures/statements-xlsx/synthetic/`; линтер «нет
координат» на `statements/**` и `book.py`; покрытие словарей; интеграционный тест воркера с книгой НПЗ.
- **Документы**: README (раздел «Парсер форм»), CLAUDE.md сервиса, `rules/README.md`, спеки `statement-parsing` (новая)
и `tabular-recognition-service` (дельта).
## Capabilities
### New Capabilities
- `statement-parsing`: разбор ББ/ОФР из Excel по §12 — классификация листов и продолжений, тип формы, шапка, колонки-
периоды, колонка кодов, строки и значения, соотношения §7, склейка листов, статусы и диагностика, словари.
### Modified Capabilities
- `tabular-recognition-service`: «Парсер — заменяемый интерфейс» — реализация по умолчанию разбирает и ОСВ, и формы
(`BookParser`), результат пишется с `schema_version = "1.2"`; каталог `api/rules/` содержит словари форм.
## Impact
- Код: `api/src/parser/book.py` (новое), `api/src/parser/statements/**` (новое), `api/src/parser/osv.py` (удаление
`parse`/`_parse_book`), `api/src/parser/detect.py` (`classify_sheet`: продолжения форм, поиск признаков по области до
таблицы), `api/src/parser/__init__.py` (`get_parser`), `api/src/contract/{common,result}.py` (v1.2), `api/contracts/`
(копия), `api/rules/statement_*.yaml`, тесты, README, CLAUDE.md.
- Таблицы DBML: не затрагиваются (сервис без БД). Поля результата — только из контракта v1.2.
- Правила: §12 п. 1–8 (с решениями владельца 06.10.2026, внесёнными в §12 сквозным change'ем), §7 (формулы), §1.2 (числа).
Допущения: `ASSUMPTION(OQ-12)` — знаки 2410/2420/2430 проверяются мягко; `ASSUMPTION(OQ-36)` — строки без кода не
отдаются; `ASSUMPTION(OQ-23)` — расшифровки только классифицируются; `ASSUMPTION(OQ-37)` — код 1105 как пришёл.
- Соседи: `../docs` (контракт v1.2, §12, OQ), `../fixtures` (golden, синтетика), `arm-core` и `scan-gateway` — копия
схемы и pydantic-модели v1.2 отдельными bounded-PR, логика не меняется (ядро по-прежнему маппит только ОСВ).
- Пересечение с параллельной работой по ОСВ (issues #9, #10, #11): модули `header.py`, `classify.py`, `checks.py`,
`hierarchy.py`, `periods.yaml`, `osv_headers.yaml`, golden ОСВ в этом change не правятся; точка пересечения —
`osv.py` и `test_osv_parser.py`, разрешается при rebase на main перед PR.
## Non-goals
- Маппинг `statementDocument` в `document` / `financial_statement_*` ядра, логические проверки §7 в ядре, подтверждение
документа, чек-лист ББ/ОФР — Срез 3.
- Склейка страниц одной формы из **разных файлов** (постраничные xls 1С): страница-продолжение без шапки отдаётся как
документ с пустой шапкой и `needs_check`; признак продолжения в контракте — позже, при появлении потребителя в ядре.
- Сопоставление строк по наименованиям при отсутствии колонки кодов (§12 п. 2, словарь `statement_lines.yaml`) —
отложено до реального файла; форма без колонки кодов даёт `needs_check`.
- Нормализация единиц измерения (деление на 1000, пересчёт рублей в тысячи) — ядро и аналитик; парсер отдаёт как есть.
- Разбор содержимого расшифровок (`DISCLOSURE`), лист `К балансу`, рекомендуемые формы банка (OQ-23).
- Изменения в парсере ОСВ, кроме переноса оркестрации книги в `BookParser`; заполнение новых полей шапки ОСВ
`period_start/period_end/is_from_year_start` — в ветке issue #11 либо follow-up, см. design D-9.