Временный режим: период ОСВ из версии консолидации (#103) #104

Merged
aep merged 3 commits from feat/103-osv-period-from-version into main 2026-10-12 19:04:21 +03:00
Owner

Closes #103. Документация — RSHB/arm-ka-docs#96 (OQ-161, qa-guide §7.4, contour-transfer-guide).

Что и зачем

12.10.2026: ОСВ за 1 кв. 2025, загруженные в консолидацию 2026 Q1 и подтверждённые вручную, не попали в свод — fits требует document.period_year == consolidation.year, документ молча не привязывается. Для тестов на произвольных ОСВ — временный режим.

Настройка CONSOLIDATION_PERIOD_FROM_VERSION (по умолчанию false; в контуре — OPENBAO__APP__CONSOLIDATION_PERIOD_FROM_VERSION=true). В режиме ОСВ, файл которой загружен в консолидацию (stored_file.consolidation_id), а период шапки версии не подходит, считается нарастающей за год и квартал консолидации. ОСВ, подходящие по шапке, не трогаются (квартальные склеиваются как раньше).

  • api/src/domain/version_period.py — чистые функции: takes_version_period, with_version_period → замороженное представление VersionPeriodDocument. Документ в БД не меняется (первичка не мутируется), карточка показывает период из шапки.
  • consolidation_documents.for_consolidation — единая точка подмены. Её используют: fits и ключ замены R-1, bind_confirmed (подхват), on_document_confirmed, on_documents_mapped, свод (ConsolidatedOsvService._build → select_sources), чек-лист (кандидаты и привязанные), колонка «ОСВ» периметра (repo.osv_accounts).
  • Режим выключен — поведение прежнее, лишних запросов нет. ББ/ОФР и файлы с рабочего стола (без consolidation_id) режим не затрагивает.
  • README («Привязка документов», таблица настроек), .env.example, .env.test, CLAUDE.md.

Rulings I made

  • R-1 Подменённый период — «нарастающий за квартал консолидации» (а не «квартал версии с исходным признаком»). Следствие: у подменённых ОСВ склейки кварталов нет, на счёт ЮЛ один слот, побеждает подтверждённая последней. Ошибка стоит: при загрузке нескольких квартальных ОСВ «чужого» периода одного счёта в свод попадёт только последняя — описано в README и qa-guide §7.4.
  • R-7 Подмена — только если период шапки версии не подходит (fits_by_header), см. O-4.
  • R-2 Область подмены — только файлы, загруженные в эту консолидацию (stored_file.consolidation_id), а не все документы ЮЛ периметра. Иначе документы с рабочего стола и из других консолидаций неожиданно меняли бы период.
  • R-3 Режим не завязан на DEBUG — работает и в контуре (решение владельца в чате 12.10.2026).
  • R-4 Документы, подтверждённые до включения режима, автоматически не перепривязываются: подхват — через PUT …/members (убрать и вернуть ЮЛ) или новую консолидацию. Миграции данных нет. Описано в qa-guide §7.4 п. 3.
  • R-5 period_check остаётся UNKNOWN (OQ-120), предупреждение о несовпадении периода в этот PR не входит — вынесено в OQ-161 как открытый выбор постоянного решения.
  • R-6 Переход версии DOCUMENTS_PROCESSING → DATA_CORRECTION по маппингу (on_documents_mapped) тоже смотрит на подменённый период — иначе в режиме документ NEEDS_CHECK не переводил бы версию в корректировку.

Наблюдения

  • O-1 make e2e в составе check-full первый раз упал по таймауту: на машине запущено ядро стенда (:8000, NATS_ENABLED=true) в той же queue group arm-core, оно забрало ack/результат tabular-parser (парсер обработал задание a0e745a1… status=done). Повторный make e2e — PASSED. Не связано с изменением; при check-full ядро стенда стоит останавливать. — deferred (кандидат в заметку README «Сквозной прогон»).
  • O-2 Ключ новой настройки нужен и в api/.env.test (test_env_example_and_env_test_have_same_keys) — исправлено a1614b0. — fixed a1614b0
  • O-4 (найдено при подготовке проверки на стенде) Первая версия подменяла период у ВСЕХ ОСВ, загруженных в консолидацию: квартальные Q1–Q3 консолидации РБ 2024 Q3, привязанные до режима, становились «нарастающими за Q3», select_sources отдавал все три, и свод брал строки как есть — задвоение/затроение. Регрессионный тест test_mode_keeps_header_period_when_it_fits_version (падал: 3 строки вместо 1). — fixed a6418ca
Маркер Статус
R-1…R-6 приняты, описаны выше
O-1 deferred
O-2 fixed a1614b0
O-4 fixed a6418ca
R-7 принят

Проверки (make check-full, по частям)

  • make check (ruff, ruff format, mypy, unit): 1289 passed
  • dbml-check, check-infra: OK
  • make test-integration: 901 passed (в т. ч. новые tests/test_version_period.py — 5 сценариев)
  • make e2e: 1-й прогон — FAILED (O-1, ядро стенда в той же queue group), повтор — 1 passed
  • make docker-build: OK
  • make web-check (biome, tsc, build): OK — фронт не менялся

Новые тесты: tests/test_domain_version_period.py (9, без БД), tests/test_version_period.py (5, integration). Мутационная проверка: при принудительно выключенной подмене 3 позитивных интеграционных теста падают, 2 негативных проходят.

Проверка на локальном стенде (12.10.2026, ядро из этой ветки, флаг включён)

  • Регрессия: свод, суммы, чек-лист и osv_accounts консолидаций РБ 2024 Q3 (1385 строк — контрольная цифра qa-guide §7.2), РБ 2025 Q1 (1421) и Синтетика 2025 Q1 (460) совпадают с ядром main побайтно.
  • Сценарий: РБ 2026 Q1, ОСВ за 1 кв. 2025 у ВМГ и «Городского рынка» (16 документов). Подтверждены 9 оставшихся, 7 ранее подтверждённых перепривязаны через периметр (временное третье ЮЛ — периметр не меньше двух). Итог: 16 привязок (по одной на счёт ЮЛ, период документов в БД — 2025 Q1), версия DATA_CORRECTION, свод 1421 строка, суммы до копейки равны своду РБ 2025 Q1 из тех же файлов; чек-лист — CONFIRMED по всем загруженным счетам, MISSING только ББ, ОФР, ОСВ 90.
  • После исправления O-4: make check 1290 passed, make test-integration 902 passed.

Как включить на стенде / в контуре

Локально: CONSOLIDATION_PERIOD_FROM_VERSION=true в api/.env, перезапуск ядра. Контур: секрет OPENBAO__APP__CONSOLIDATION_PERIOD_FROM_VERSION=true. После тестов — убрать.

🤖 Generated with Claude Code

Closes #103. Документация — RSHB/arm-ka-docs#96 (OQ-161, qa-guide §7.4, contour-transfer-guide). ## Что и зачем 12.10.2026: ОСВ за 1 кв. 2025, загруженные в консолидацию 2026 Q1 и подтверждённые вручную, не попали в свод — `fits` требует `document.period_year == consolidation.year`, документ молча не привязывается. Для тестов на произвольных ОСВ — **временный** режим. Настройка `CONSOLIDATION_PERIOD_FROM_VERSION` (по умолчанию `false`; в контуре — `OPENBAO__APP__CONSOLIDATION_PERIOD_FROM_VERSION=true`). В режиме ОСВ, файл которой загружен в консолидацию (`stored_file.consolidation_id`), а период шапки версии **не подходит**, считается **нарастающей за год и квартал консолидации**. ОСВ, подходящие по шапке, не трогаются (квартальные склеиваются как раньше). - `api/src/domain/version_period.py` — чистые функции: `takes_version_period`, `with_version_period` → замороженное представление `VersionPeriodDocument`. Документ в БД не меняется (первичка не мутируется), карточка показывает период из шапки. - `consolidation_documents.for_consolidation` — единая точка подмены. Её используют: `fits` и ключ замены R-1, `bind_confirmed` (подхват), `on_document_confirmed`, `on_documents_mapped`, свод (`ConsolidatedOsvService._build` → `select_sources`), чек-лист (кандидаты и привязанные), колонка «ОСВ» периметра (`repo.osv_accounts`). - Режим выключен — поведение прежнее, лишних запросов нет. ББ/ОФР и файлы с рабочего стола (без `consolidation_id`) режим не затрагивает. - README («Привязка документов», таблица настроек), `.env.example`, `.env.test`, `CLAUDE.md`. ## Rulings I made - **R-1** Подменённый период — «нарастающий за квартал консолидации» (а не «квартал версии с исходным признаком»). Следствие: у подменённых ОСВ склейки кварталов нет, на счёт ЮЛ один слот, побеждает подтверждённая последней. Ошибка стоит: при загрузке нескольких квартальных ОСВ «чужого» периода одного счёта в свод попадёт только последняя — описано в README и qa-guide §7.4. - **R-7** Подмена — только если период шапки версии не подходит (`fits_by_header`), см. O-4. - **R-2** Область подмены — только файлы, загруженные в эту консолидацию (`stored_file.consolidation_id`), а не все документы ЮЛ периметра. Иначе документы с рабочего стола и из других консолидаций неожиданно меняли бы период. - **R-3** Режим не завязан на `DEBUG` — работает и в контуре (решение владельца в чате 12.10.2026). - **R-4** Документы, подтверждённые до включения режима, автоматически не перепривязываются: подхват — через `PUT …/members` (убрать и вернуть ЮЛ) или новую консолидацию. Миграции данных нет. Описано в qa-guide §7.4 п. 3. - **R-5** `period_check` остаётся `UNKNOWN` (OQ-120), предупреждение о несовпадении периода в этот PR не входит — вынесено в OQ-161 как открытый выбор постоянного решения. - **R-6** Переход версии `DOCUMENTS_PROCESSING → DATA_CORRECTION` по маппингу (`on_documents_mapped`) тоже смотрит на подменённый период — иначе в режиме документ `NEEDS_CHECK` не переводил бы версию в корректировку. ## Наблюдения - **O-1** `make e2e` в составе `check-full` первый раз упал по таймауту: на машине запущено ядро стенда (:8000, `NATS_ENABLED=true`) в той же queue group `arm-core`, оно забрало ack/результат tabular-parser (парсер обработал задание `a0e745a1… status=done`). Повторный `make e2e` — PASSED. Не связано с изменением; при `check-full` ядро стенда стоит останавливать. — `deferred` (кандидат в заметку README «Сквозной прогон»). - **O-2** Ключ новой настройки нужен и в `api/.env.test` (`test_env_example_and_env_test_have_same_keys`) — исправлено a1614b0. — `fixed a1614b0` - **O-4** (найдено при подготовке проверки на стенде) Первая версия подменяла период у ВСЕХ ОСВ, загруженных в консолидацию: квартальные Q1–Q3 консолидации РБ 2024 Q3, привязанные до режима, становились «нарастающими за Q3», `select_sources` отдавал все три, и свод брал строки как есть — задвоение/затроение. Регрессионный тест `test_mode_keeps_header_period_when_it_fits_version` (падал: 3 строки вместо 1). — `fixed a6418ca` | Маркер | Статус | |---|---| | R-1…R-6 | приняты, описаны выше | | O-1 | deferred | | O-2 | fixed a1614b0 | | O-4 | fixed a6418ca | | R-7 | принят | ## Проверки (`make check-full`, по частям) - `make check` (ruff, ruff format, mypy, unit): **1289 passed** - `dbml-check`, `check-infra`: OK - `make test-integration`: **901 passed** (в т. ч. новые `tests/test_version_period.py` — 5 сценариев) - `make e2e`: 1-й прогон — FAILED (O-1, ядро стенда в той же queue group), повтор — **1 passed** - `make docker-build`: OK - `make web-check` (biome, tsc, build): OK — фронт не менялся Новые тесты: `tests/test_domain_version_period.py` (9, без БД), `tests/test_version_period.py` (5, integration). Мутационная проверка: при принудительно выключенной подмене 3 позитивных интеграционных теста падают, 2 негативных проходят. ## Проверка на локальном стенде (12.10.2026, ядро из этой ветки, флаг включён) - Регрессия: свод, суммы, чек-лист и `osv_accounts` консолидаций РБ 2024 Q3 (1385 строк — контрольная цифра qa-guide §7.2), РБ 2025 Q1 (1421) и Синтетика 2025 Q1 (460) совпадают с ядром `main` побайтно. - Сценарий: РБ 2026 Q1, ОСВ за 1 кв. 2025 у ВМГ и «Городского рынка» (16 документов). Подтверждены 9 оставшихся, 7 ранее подтверждённых перепривязаны через периметр (временное третье ЮЛ — периметр не меньше двух). Итог: 16 привязок (по одной на счёт ЮЛ, период документов в БД — 2025 Q1), версия `DATA_CORRECTION`, свод **1421 строка**, суммы до копейки равны своду РБ 2025 Q1 из тех же файлов; чек-лист — `CONFIRMED` по всем загруженным счетам, `MISSING` только ББ, ОФР, ОСВ 90. - После исправления O-4: `make check` 1290 passed, `make test-integration` 902 passed. ## Как включить на стенде / в контуре Локально: `CONSOLIDATION_PERIOD_FROM_VERSION=true` в `api/.env`, перезапуск ядра. Контур: секрет `OPENBAO__APP__CONSOLIDATION_PERIOD_FROM_VERSION=true`. После тестов — убрать. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 2 commits 2026-10-12 18:28:22 +03:00
Настройка CONSOLIDATION_PERIOD_FROM_VERSION (по умолчанию false; в контуре —
OPENBAO__APP__CONSOLIDATION_PERIOD_FROM_VERSION): ОСВ, загруженная в консолидацию
(stored_file.consolidation_id), считается нарастающей за год и квартал консолидации,
какой бы период ни стоял в шапке. Нужен для тестов на произвольных ОСВ: без него ОСВ
за 1 кв. 2025 в консолидации 2026 Q1 молча не привязывается и свод пуст.

- domain/version_period.py: представление документа с периодом версии (первичка не меняется)
- consolidation_documents.for_consolidation: единая точка подмены; её используют привязка
  (fits, ключ R-1, bind_confirmed, хуки подтверждения и маппинга), свод, чек-лист,
  колонка «ОСВ» периметра (osv_accounts)
- ББ/ОФР и файлы с рабочего стола режим не затрагивает; склейки кварталов в режиме нет
- тесты: unit на чистые функции, интеграционные — сценарий 2025 Q1 → 2026 Q1 с режимом
  и без, файл вне консолидации, чек-лист и карточка, подхват «один слот на счёт»

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aep added 1 commit 2026-10-12 18:51:33 +03:00
Квартальные ОСВ, загруженные в консолидацию своего периода и уже привязанные, в режиме
становились «нарастающими за квартал версии»: select_sources возвращал все такие документы,
и свод брал их строки как есть — консолидация РБ 2024 Q3 на стенде задвоилась бы.
Теперь подмена — только если период шапки версии не подходит (fits_by_header);
регрессионный тест test_mode_keeps_header_period_when_it_fits_version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aep merged commit 880eab6c4b into main 2026-10-12 19:04:21 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/arm-core#104
No description provided.