Andrey Epifancev 6e5ab834ec spec(slice-4): OpenSpec change консолидации — версии, периметр, блокировка, привязка документов, сводная ОСВ, экспорт
Proposal, design (D-1…D-16, решения без обсуждения), tasks и дельты спек: новые capability consolidations-api и
consolidated-osv; изменения data-model (DBML v5.16, counterparty_match_kind), documents-api (привязка при
подтверждении), primary-files (consolidation_version_id, отвязка при автозамене), osv-result-mapping (match_kind,
NEEDS_CHECK → DATA_CORRECTION), directory-policy (редактируемость версии), audit-trail (события консолидации).
Решения владельца 06.10.2026: OQ-03 пробел, OQ-19 блокировка, статусы по событиям, явная привязка, экспорт одним листом.

Refs RSHB/arm-core#18

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-06 02:52:23 +04:00

88 lines
9.4 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: Срез 4 — консолидация: версии, периметр, блокировка, привязка документов, сводная ОСВ, экспорт xlsx
**Срез:** 4 (`../docs/context/09-delivery-plan.md`). **Репозиторий:** arm-core. **Issue:** RSHB/arm-core#18.
**Родительский change:** `../docs/openspec/changes/slice-4-consolidation` (DBML v5.16, правила §2/§3/§9 по факту, OQ;
RSHB/arm-ka-docs#19). Объём по решению владельца 06.10.2026: **бэкенд, API, экспорт xlsx**; UI (список, карточка,
состав, вкладка ОСВ) делает другой разработчик по этим спекам.
## Why
После Среза 2c строки ОСВ лежат в `osv_entry` по документам, но объекта «консолидация» в ядре нет: модели шести таблиц
есть, сервисов, репозиториев и эндпоинтов нет; права `CONSOLIDATION_*` ни на одном маршруте не используются;
`period_check = UNKNOWN`. Без Среза 4 нет периметра версии, нет сводной ОСВ, на которой стоят шахматка и ВГО (Срез 5),
нет чек-листа комплекта и некуда показывать результат ручного сопоставления контрагентов.
## What Changes
- **DBML v5.16**: enum `counterparty_match_kind` (`INN`, `NAME`, `ALIAS`, `MANUAL`, `PROPAGATED`) и колонка
`osv_entry.counterparty_match_kind` — как появился `counterparty_id` (решение владельца 06.10.2026: строки,
сопоставленные автоматически по имени или алиасу, должны выделяться в API). Миграция `0004_dbml_v5_16` с backfill
по уже смапленным строкам. Таблиц 43, enum'ов 28.
- **Маппинг (2c)** пишет `counterparty_match_kind` по шагу резолва (`CounterpartyIndex.resolve` возвращает шаг).
- **Консолидации** (`consolidations-api`): `POST /consolidations` (ГК + ГСК + год + квартал → `consolidation`,
`consolidation_version` №1 `INITIATED`, `consolidation_member` из текущего состава ГСК, минимум 2 ЮЛ);
список по ГК с деревом версий; карточка версии с периметром, ответственным и ячейками чек-листа; `PUT …/members`;
блокировка `POST/DELETE …/lock` с перехватом по причине; `POST …/status` (в Срезе 4 — только `CANCELLED` и возврат
в `INITIATED`); чек-лист `GET …/checklist` (перенесён из Среза 3: без него негде показать пробелы кварталов).
- **Привязка документов** (`documents-api`, `primary-files`): подтверждение документа привязывает его
(`consolidation_document`) ко всем версиям в работе, которым он подходит по периметру и периоду, и двигает статус
`INITIATED`/`DOCUMENTS_PROCESSING → DATA_CORRECTION`; создание версии и добавление ЮЛ подхватывают уже подтверждённые
документы; автозамена файла и удаление ЮЛ из периметра снимают привязку. Загрузка файла принимает необязательный
`consolidation_version_id` (`INITIATED → DOCUMENTS_PROCESSING`); маппинг документа `NEEDS_CHECK` для ЮЛ периметра —
`DOCUMENTS_PROCESSING → DATA_CORRECTION`.
- **Сводная ОСВ** (`consolidated-osv`): чистая функция `domain/consolidated_osv.py` от версии, периметра и привязанных
ОСВ: приведение квартальных ОСВ к нарастающим (§2: ключ (счёт, контрагент), пропуск квартала → пробел, строки не
строятся), признак контрагента ГСК/ГК/Внешний, дорезолв незаполненного `counterparty_id` на чтение (не сохраняется),
`match_kind`/`match_stored`. `GET …/osv` (страница, фильтры), `GET …/osv/summary` (счётчики, пробелы),
`GET …/counterparty-candidates`, `POST …/osv/entries/{id}/counterparty` (алиас, перенос алиаса, автоприменение,
`OSV_COUNTERPARTY_MAP`), `GET …/osv/export` (xlsx, openpyxl, два листа, аудит `EXPORT`).
- **Политика** (`directory-policy`): видимость консолидации = видимость её ГК; правки версии — только в статусе «в
работе» и при своей активной блокировке.
- **Аудит** (`audit-trail`): `CONSOLIDATION_CREATE`, `MEMBERSHIP_CHANGE`, `CONSOLIDATION_LOCK`,
`CONSOLIDATION_LOCK_TAKEOVER`, `CONSOLIDATION_STATUS_CHANGE`, `OSV_COUNTERPARTY_MAP`, `EXPORT` — все с
`consolidation_version_id`.
- **Тесты**: домен без БД (приведение периодов, пробелы, признак), API на PostgreSQL, гонки блокировок, сквозной
`fixtures`-тест: консолидация группы «Русский бисквит» за Q3 2024, одно ручное сопоставление → ГСК у всех строк
«Пекарня Счастливочная».
- **Документы**: README среза, CLAUDE.md, спеки.
## Capabilities
### New Capabilities
- `consolidations-api`: создание, список, карточка, периметр, блокировка, статусы, чек-лист.
- `consolidated-osv`: расчёт сводной ОСВ, кандидаты и ручное сопоставление контрагента, экспорт xlsx.
### Modified Capabilities
- `data-model`: схема равна DBML **v5.16**, миграции 0001 → 0004.
- `documents-api`: подтверждение документа привязывает его к версиям и меняет их статус.
- `primary-files`: загрузка с `consolidation_version_id`; автозамена снимает привязку заменённых документов.
- `osv-result-mapping`: `counterparty_match_kind` при резолве; переход версии в `DATA_CORRECTION` по `NEEDS_CHECK`.
- `directory-policy`: видимость консолидаций и правило редактируемости версии.
- `audit-trail`: события консолидации.
## Impact
- **Таблицы DBML v5.16:** `consolidation`, `consolidation_version`, `consolidation_status_history`, `consolidation_lock`,
`consolidation_member`, `consolidation_document`, `osv_entry` (новая колонка), `legal_entity_alias`,
`required_document_rule`, `audit_event`.
- **Правила:** §2 (приведение периодов), §3 (сводная ОСВ, ручное сопоставление), §9.1 (статусы Среза 4), §9.3
(`period_check` остаётся `UNKNOWN`, см. design D-12), §9.5 (отвязка при автозамене), §10 (права), `04-data-model-guide`
(«что не хранится»).
- **Код:** новые `api/endpoints/consolidations/`, `services/consolidations.py`, `services/consolidation_locks.py`,
`services/consolidation_documents.py`, `services/consolidated_osv.py`, `services/osv_export.py`,
`repositories/consolidations.py`, `domain/consolidated_osv.py`, `domain/consolidation_periods.py`,
`schemas/consolidations.py`; правки `services/documents.py`, `services/result_mapping.py`, `services/primary_files.py`,
`repositories/counterparties.py`, `domain/policy.py`, `api/endpoints/files/upload.py`, миграция `0004`.
- **Потребители:** фронт (2d/4-UI) — по этим спекам; tabular-parser и контракт v1.1 не меняются.
## Non-goals
- Маршрут согласования после `DATA_CORRECTION` (`CONSOLIDATION_RF` и далее), УОБ, `ex_snapshot`, «Добавить версию»,
сценарий `CONFIRM`, подход `EXTENDED` — Срезы 6–7. Переходы в эти статусы отвечают 409 `TRANSITION_NOT_ALLOWED`.
- Запрет загрузки/подтверждения документов в статусах после `DATA_CORRECTION` (ТЗ 03_9 A1) — Срез 7, OQ-118.
- `period_check` документа по версии (OQ-120): остаётся `UNKNOWN`; подходящесть документа версии считается на лету.
- Шахматка, пары ВГО, корректировки (Срез 5), ББ/ОФР из Excel (2b), PDF (Срез 3), UI (другой разработчик).
- CSV чек-листа (макет `37`) — фронт строит из JSON.
- Отвязка контрагента от строки (обратное действие): перевязка покрывает исправление ошибки.
- Зоны ответственности в политике (OQ-86), истечение блокировки по времени (OQ-119).