8.1 KiB
Raw Blame History

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.