Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
8.4 KiB
8.4 KiB
Proposal: Срез 2c — загрузка файлов ОСВ, очередь распознавания, маппинг результата в document/osv_entry
Срез: 2, подсрез 2c (../docs/context/09-delivery-plan.md; порядок по решению владельца 05.10.2026: 2a → 2c → 2b → 2d).
Репозиторий: arm-core. Issue: RSHB/arm-core#14. Родительский change: ../docs/openspec/changes/slice-2c-osv-ingest
(DBML v5.15, правила по факту, OQ; RSHB/arm-ka-docs#16). Фикстуры не меняются (golden-снимки парсера из Среза 2a).
Why
После Среза 2a парсер разбирает ОСВ, но результат некуда положить: в ядре нет загрузки файлов (stored_file нигде не
создаётся), inbox фиксирует конверт, а маппер — NoopMapper. Без 2c нет сквозного пути «файл → строки ОСВ в БД», на
котором стоят чек-лист (Срез 3), сводная ОСВ и ВГО (Срезы 4–5), и тестировщику нечего проверять на реальных данных.
What Changes
- DBML v5.15:
osv_data_type+NU(OQ-45);app_user.emailхранится в нижнем регистре (OQ-59, нормализация при записи, UNIQUE прежний); миграция0003_dbml_v5_15(enum +UPDATE app_user SET email = lower(email));DBML_VERSION,Makefile,dbml_parity, тесты миграций — на v5.15. Таблиц 43, enum'ов 27. - Загрузка файлов
POST /api/v1/legal-entities/{id}/files(multipart, несколько файлов,DOCUMENT_EDIT, policy видимости ЮЛ):s3_object(uploads/{file_id}/{job_id}/{имя}, sha256) +stored_file(UPLOADED)+recognition_job(queued)+current_recognition_job_idодной транзакцией; тип по расширению и сигнатуре (xls/xlsx/xlsb →tabular, pdf/png/jpg →image); дедуп по sha256 в пределах ЮЛ (409); лимитUPLOAD_MAX_BYTES50 МиБ; частичный успех по файлам; аудитFILE_UPLOAD. - Статусы файла в обмене: ack →
PROCESSING;error/timeout/dlq→ERRORс причиной (OQ-67, inbox). - Цикл маппинга (
services/result_mapping.py, фоновая задача lifespan, периодMAPPING_POLL_SECONDS): заданиеdone|needs_checkс файломPROCESSINGиcurrent_recognition_job_id = job→FOR UPDATE SKIP LOCKED→ проверка ключа (OQ-70) → чтение результата из S3 вне транзакции → валидация v1.1 → одна транзакция:document+osv_entry+group_schema+ статус файлаPROCESSED; ошибка чтения/валидации →ERROR; исключение → повтор до 3 раз (metrics.mapping_attempts), затемERROR(OQ-69 — маппинг отделён от inbox). - Маппинг по §1.3/§3/§9.3: все строки кроме
TOTAL(OQ-01) сparent_entry_id; нормализация кода счёта,account_root,account_idпо плану счетов; резолв контрагента ИНН → имя → алиас, несколько кандидатов → NULL;counterparty_checkпо шапке;period_check = UNKNOWNдо Среза 4;is_cumulativeпо данным Q1 (OQ-02); статус документаRECOGNIZED|NEEDS_CHECK(OQ-05); второй лист с тем же счётом — предупреждение иNEEDS_CHECK. - Автозамена (решение владельца 05.10.2026): после маппинга прежние файлы того же ЮЛ с документом того же типа, счёта
и периода →
SUPERSEDED(superseded_by_file_id,version_no), аудитFILE_REPLACE(с предупреждением, если заменёнCONFIRMED). УдалениеDELETE /files/{id}— пока нетCONFIRMEDдокументов; аудитFILE_DELETE. - API чтения (
DOCUMENT_VIEW): список файлов ЮЛ с заданием и документами, карточка файла, документ с проверками и схемой, строки документа деревом (до 2000 на страницу); подтверждениеPOST /documents/{id}/confirm(DOCUMENT_EDIT,DOCUMENT_CONFIRM). - S3:
S3Storage.get_bytes(key);FakeStorage.get_bytesв тестах. - Тесты: unit (нормализация кода, резолв, проверки шапки), integration (загрузка/дедуп/статусы/цикл/автозамена/
удаление/API),
fixtures— маппинг всех 82 golden-снимков парсера без NATS и сквозной прогон через compose с реальнымtabular-parserнаrb/2024-FY/ОСВ_66 за 2024.xls. - Документы: README (загрузка, статусы, маппинг, API), CLAUDE.md, спеки.
Capabilities
New Capabilities
primary-files: загрузка файлов отчётности, дедуп, статусы файла, автозамена, удаление.osv-result-mapping: цикл маппинга результата распознавания вdocument/osv_entry, резолвы, проверки, статусы документа.documents-api: чтение файлов, документов и строк ОСВ, подтверждение документа.
Modified Capabilities
recognition-job-exchange: ack и финальные статусы задания меняютstored_file.status; результатdone|needs_checkне маппится в inbox, а передаётся циклу маппинга (NoopMapperи протоколResultMapperудаляются).data-model: схема равна DBML v5.15, цепочка миграций 0001 → 0003.audit-trail: события файлов и документов (FILE_UPLOAD,FILE_REPLACE,FILE_DELETE,DOCUMENT_CONFIRM).
Impact
- Таблицы DBML v5.15:
s3_object,stored_file,recognition_job(group_schema,metrics),document,osv_entry,chart_of_account(чтение),legal_entity,legal_entity_alias(чтение),app_user(email в нижнем регистре),audit_event. Полей вне DBML нет. - Правила: §1.3 (маппинг строк, нормализация,
account_root/account_id), §1.5 (is_cumulativeпо данным,period_check), §3 п. 4 (резолв контрагента), §9.2–9.4 (статусы). Допущения:ASSUMPTION(OQ-02)(по данным — только сравнение с Q1 того же года),ASSUMPTION(OQ-55)(события обмена не аудируются),ASSUMPTION(OQ-100)(ИНН из текста строки не извлекается),ASSUMPTION(OQ-103)(буквенный первый сегмент →account_id = NULL). - Соседи:
../docs(DBML v5.15, §, OQ),tabular-parser— без изменений; compose — без изменений. - Seed:
users.yamldev-email уже в нижнем регистре;permissions/матрица не меняются (DOCUMENT_VIEW/DOCUMENT_EDITесть).
Non-goals
- UI (панель «Первичные документы», окно загрузки, экран проверки ОСВ) — подсрез 2d.
- Маппинг
statementDocument(ББ/ОФР), логические проверки §7, правка распознанных значений (RECOGNIZED_DATA_EDIT), чек-лист — Срез 3 / подсрез 2b. - Ручное сопоставление контрагентов (
OSV_COUNTERPARTY_MAP),period_checkпо версии консолидации — Срез 4. - Replay заданий (
dlq → queued, OQ-73), аудит смены статусов задания (OQ-55), JetStream. - Ограничение удаления по консолидациям (ANL-020) — Срез 4.