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

9.4 KiB
Raw Blame History

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).