Andrey Epifancev 1908288613 feat(consolidation): переходы DOCUMENTS_PROCESSING и DATA_CORRECTION по загрузке и маппингу
Загрузка с consolidation_version_id: проверки до приёма (404/409/422), после приёма
INITIATED -> DOCUMENTS_PROCESSING в отдельной транзакции без блокировки версии.
Маппинг: on_documents_mapped переводит версии DOCUMENTS_PROCESSING в DATA_CORRECTION
при подходящем документе NEEDS_CHECK (changed_by = uploaded_by), привязки не создаёт.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-06 05:30:45 +04:00

65 lines
7.2 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.

# Tasks: Срез 4 — arm-core
Каждая задача ≤ половины дня, начинается с тестов, заканчивается зелёным `make check` и интеграционными тестами своей
области. Допущения в коде — `# ASSUMPTION(OQ-nn)`. DBML v5.16 — `../docs/model/data-model-v5.16.dbml` (ветка
`feat/19-slice-4-consolidation` в `.wt/slice-4/docs`). Детальный план с кодом — `docs/superpowers/plans/` (writing-plans).
## 1. Модель
- [x] 1.1 **DBML v5.16, миграция 0004, `match_kind` в маппинге.** `CounterpartyMatchKind` enum, колонка
`OsvEntry.counterparty_match_kind`; миграция `0004_dbml_v5_16` (enum, колонка, backfill SQL, downgrade); `DBML_VERSION`,
`Makefile`, `dbml_parity`, `test_migrations` (HEAD), `test_enums`, `test_check_dbml_script` (фиктивная 5.17);
`CounterpartyIndex.resolve` → `Resolution(entity_id, kind) | None`; `result_mapping._with_counterparty` пишет kind;
`EntryOut.match_kind`. Тесты: backfill на трёх строках, golden-маппинг с kind, `test_counterparty_resolve`.
- [x] 1.2 **Фабрики и репозиторий.** `tests/factories.py`: `make_consolidation(session, *, group, year, quarter, members, status)`,
`make_lock`, `make_confirmed_osv(entity, account, year, quarter, cumulative, rows)`; `repositories/consolidations.py`:
`get_version(scope)`, `list_periods(group)`, `lock_version`, `lock_versions_for_entity(entity_id, statuses)`, `active_lock`,
`members`, `bound_documents`, `load_osv_rows`, `history`; `CommittedJobs.cleanup()` знает таблицы консолидации.
## 2. Версии, периметр, блокировка, статусы
- [x] 2.1 **Создание, список, карточка.** `schemas/consolidations.py` (D-16), `services/consolidations.py:create/list_periods/card`,
`domain/consolidation_periods.py:reporting_date`, эндпоинты `POST /consolidations`, `GET /company-groups/{id}/consolidations`,
`GET /consolidations/versions/{id}`, роутер. Тесты: сценарии `consolidations-api` «Создание», «Список и карточка», policy 404.
- [x] 2.2 **Статусы и политика.** `domain/policy.py:IN_WORK_STATUSES, ensure_version_editable`; `services/consolidation_status.py:
transition(version, to, by, comment, *, manual)` с таблицей Среза 4; `POST …/status`. Тесты: `CANCELLED` с/без комментария,
возврат в `INITIATED`, `TRANSITION_NOT_ALLOWED`, `VERSION_NOT_EDITABLE`, `LOCK_REQUIRED`.
- [x] 2.3 **Блокировка.** `services/consolidation_locks.py:take/release`, `POST/DELETE …/lock`, `IntegrityError` → `LOCKED_BY_OTHER`.
Тесты: сценарии «Взять в работу», гонка двух `POST` (`test_api_constraint_races`), `CANCELLED` снимает блокировку.
- [x] 2.4 **Периметр.** `PUT …/members` с подхватом/отвязкой (вызывает 3.1), `MEMBERSHIP_CHANGE`. Тесты: сценарии «Периметр версии».
## 3. Привязка документов и чек-лист
- [x] 3.1 **Привязка.** `services/consolidation_documents.py:fits(document, version)`, `bind_confirmed(version, entity_ids)`,
`unbind_entity`, `on_document_confirmed(document, user)`, `on_file_superseded(file, documents)`; правки
`DocumentService.confirm` (версии `FOR UPDATE` после документа), `supersede_previous` (`unbound_version_ids` в аудите).
Тесты: сценарии `documents-api` (привязка, период, `CANCELLED`, подхват, две версии документа), `primary-files`
«Заменённый документ был в версии», порядок блокировок (подтверждение ∥ правка периметра).
- [x] 3.2 **Статусы по событиям файлов.** `upload.py`: `consolidation_version_id` (проверки, переход после приёма);
`result_mapping`: хук `on_documents_mapped` (NEEDS_CHECK → `DATA_CORRECTION`, `uploaded_by`, пропуск при NULL).
Тесты: сценарии `primary-files` «Загрузка в контексте версии», `osv-result-mapping` «Предупреждение маппинга».
- [ ] 3.3 **Чек-лист.** `domain/checklist.py:build(rules, members, documents, files)` (чистая), `GET …/checklist`, ячейки в карточке.
Тесты: пробел Q2, субсчёт, `PROCESSING`, `ERROR`, ББ/ОФР за квартал версии.
## 4. Сводная ОСВ
- [ ] 4.1 **Домен.** `domain/consolidation_periods.py:select_sources` (нарастающий/квартальные/пробел), `domain/consolidated_osv.py:
build(...)` (склейка по ключу, нули, дубли, `entry_ids`, `warnings`, дорезолв, признак, фильтры, порядок). Тесты без БД:
все сценарии «Выбор источников», «Строки свода», фильтры, версия за Q1, дубль ключа, расхождение `counterparty_id`.
- [ ] 4.2 **API свода.** `services/consolidated_osv.py:page/summary`, `GET …/osv`, `GET …/osv/summary`. Тесты: страница на
PostgreSQL с тремя кварталами, `unmapped`, `match_kind`, `q`, чтение `CANCELLED`, `curator_go` читает.
- [ ] 4.3 **Кандидаты и сопоставление.** `GET …/counterparty-candidates`, `POST …/osv/entries/{id}/counterparty`
(`services/counterparty_mapping.py`: алиас, `ALIAS_TAKEN`, перенос, `MANUAL`/`PROPAGATED`, ИНН-противоречие, аудит).
Тесты: все сценарии «Кандидаты», «Ручное сопоставление», блокировка/статус.
- [ ] 4.4 **Экспорт.** `services/osv_export.py` (openpyxl, два листа, `BytesIO`), `GET …/osv/export`, `Content-Disposition`,
аудит `EXPORT`. Тест: файл читается `openpyxl`, суммы равны API, лист «Пробелы».
## 5. Сквозной тест и документы
- [ ] 5.1 **Фикстуры РБ.** `tests/test_consolidation_fixtures.py` (маркер `fixtures`): маппинг golden-снимков ОСВ РБ и
Счастливочной за Q1–Q3 2024 → подтверждение → консолидация 2024 Q3 → свод: счета 60/62 у обеих и 76 у Счастливочной,
остальные в `gaps`; одно сопоставление «Пекарня Счастливочная ООО» → `GSK` у всех строк РБ с этим именем;
экспорт открывается.
- [ ] 5.2 **Документы.** README (консолидации, статусы Среза 4, свод, сопоставление, экспорт, коды ошибок), CLAUDE.md
(новые модули, порядок блокировок), `openspec` спеки; синхронизация с docs-change (OQ, §2/§3/§9).