Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
6.5 KiB
Proposal: Срез 2a — парсер ОСВ из XLS/XLSX/XLSB (динамическое обнаружение структуры §1)
Срез: 2 «Загрузка файлов + табличный парсер» (../docs/context/09-delivery-plan.md), первый подсрез по решению
владельца 05.10.2026: только парсер ОСВ. ББ/ОФР из Excel (§12), загрузка файлов и маппинг результата в ядре, UI —
следующие подсрезы. Репозиторий: arm-tabular-parser. Issue: RSHB/arm-tabular-parser#5.
Связанные change'и: ../docs/openspec/changes/slice-2a-osv-parser (контракт v1.1, §1, OQ; RSHB/arm-ka-docs#9),
фикстуры RSHB/arm-ka-fixtures#4 (синтетика, золотые снимки).
Why
После Среза 0 сервис принимает задания и отвечает NOT_IMPLEMENTED. Без разбора ОСВ невозможны ни сводная ОСВ, ни
ВГО, ни КФО — это самый рискованный блок системы (§1.0: ОСВ приходят из разных конфигураций 1С и других систем, и
«ни одна буква колонки, ни один номер строки, ни одно имя листа не являются контрактом»). В fixtures есть 66 реальных
ОСВ двух организаций (xls и xlsx, 2 и 3 строки заголовка, плавающие колонки, иерархия до 4 уровней, мусор правее
таблицы, пустая ОСВ), на которых парсер обязан проходить без единого правила под файл.
What Changes
- Парсер ОСВ
api/src/parser/: единая модель листа (grid.py), читатели xlsx/xls/xlsb, детекторы структуры по содержимому (detect.py), шапка иgroup_schema(header.py), каскад стратегий иерархии (hierarchy.py), классификация строк (classify.py), нормализация чисел вDecimal(numbers.py), контрольные суммы §1.4 (checks.py), оркестратор (osv.py).get_parser()возвращает реальную реализацию; воркер, NATS и S3 без изменений. - Словари
api/rules/{osv_headers,osv_groups,periods,data_types}.yamlс pydantic-валидацией при старте и тестом «каждая запись срабатывает хотя бы раз». - Зависимости
api/requirements.txt:openpyxl==3.1.5,xlrd==2.0.2,pyxlsb==1.0.10. - Настройки
PARSE_MAX_BYTES(50 МиБ),PARSE_TIMEOUT_SECONDS(120) — проверка дедлайна между шагами, без убийства потока. - Контракт v1.1: парсер пишет
schema_version = "1.1"и заполняетrows[].extra(нераспознанные колонки, §1.2); копия схемы вapi/contracts/обновляется вместе с источником в../docs/contracts/. - Тесты: unit по модулям на синтетических сетках; property-тест инвариантов §1.4 на всех
../fixtures/osv/**; золотые снимки../fixtures/golden/expected_osv_parse/; синтетические файлы../fixtures/osv/synthetic/из детерминированного генератора; тест-линтер «нет координат вsrc/parser/»; хелперARM_KA_FIXTURES(OQ-81). - Документы: README (как запустить на файле, коды ошибок, словари), CLAUDE.md, спека
osv-parsing.
Capabilities
New Capabilities
osv-parsing: разбор ОСВ из Excel по §1 — обнаружение листов, заголовка и колонок по содержимому, шапка, иерархия, классификация, числа, контрольные суммы, статусы и диагностика, словари, лимиты.
Modified Capabilities
tabular-recognition-service: требования «Парсер — заменяемый интерфейс» и «Результат по контракту» — реализация по умолчанию разбирает ОСВ, листы ББ/ОФР пропускаются с предупреждением (§12, следующий подсрез),NOT_IMPLEMENTEDостаётся только у заглушкиNullParserв тестах воркера; результат пишется сschema_version 1.1.
Impact
- Код:
api/src/parser/**(новое),api/src/core/config.py(две настройки),api/src/contract/common.py(CONTRACT_VERSION = "1.1"),api/contracts/recognition-result.schema.json(копия v1.1),api/rules/*.yaml,api/requirements.txt, тесты. - Таблицы DBML: не затрагиваются (сервис без БД). Поля результата — только из контракта.
- Правила: §1.0–§1.5, §1.2 (
extra), §1.4 (инварианты), §1.5 (период). Допущения:ASSUMPTION(OQ-02)—is_cumulativeтолько по тексту;ASSUMPTION(OQ-45)—data_type = NUвыдаётся как есть;ASSUMPTION(OQ-01)— «Итого» выдаётся строкойTOTAL, решение о хранении — за ядром. - Соседи:
../docs(контракт v1.1, §1),../fixtures(синтетика, golden),arm-core— копия схемы v1.1 отдельным bounded-PR, логика ядра не меняется (NoopMapper).
Non-goals
- ББ/ОФР из Excel (§12) — подсрез 2b; листы с признаками форм в этом подсрезе пропускаются с предупреждением.
- Загрузка файлов,
stored_file/recognition_jobв ядре, маппинг результата вdocument/osv_entry, UI — подсрезы 2c/2d. - Проверка
is_cumulativeпо данным других ОСВ (OQ-02), резолв контрагентов и счетов — ядро. - Отмена разбора извне, JetStream, изменение дедупа
(job_id, attempt)(OQ-73). - Распознавание сканов и PDF.