From 4f32d74ba089180e1c4e84bd82ad203bc64af3b6 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Fri, 23 Oct 2026 00:50:58 +0400 Subject: [PATCH] =?UTF-8?q?docs(openspec):=20change=20consolidations-ui=20?= =?UTF-8?q?=E2=80=94=20=D1=86=D0=B5=D0=BB=D0=B5=D0=B2=D0=BE=D0=B5=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=8D=D0=BA?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=BA=D0=BE=D0=BD=D1=81=D0=BE?= =?UTF-8?q?=D0=BB=D0=B8=D0=B4=D0=B0=D1=86=D0=B8=D0=B9=20(PR=20#166,=20AURO?= =?UTF-8?q?RA-1589)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Спека consolidations-ui: список консолидаций [34] (колонки, «Версия», «Только в работе»), «Взять в работу» и перехват [35], меню «⋯», панель «Организации», подписи статусов, вид модалки [42], «Изменить статус» [33-01] с зеркалом MANUAL_TRANSITIONS, пояснение статуса под заголовком, модалка [31-00]. design.md: решения, Known issues ветки 71ef633, решения без обсуждения; tasks.md: ревьюер / автор / тесты. Co-Authored-By: Claude Opus 5.5 --- .../changes/consolidations-ui/.openspec.yaml | 2 + openspec/changes/consolidations-ui/design.md | 117 +++++++++ .../changes/consolidations-ui/proposal.md | 62 +++++ .../specs/consolidations-ui/spec.md | 226 ++++++++++++++++++ openspec/changes/consolidations-ui/tasks.md | 35 +++ 5 files changed, 442 insertions(+) create mode 100644 openspec/changes/consolidations-ui/.openspec.yaml create mode 100644 openspec/changes/consolidations-ui/design.md create mode 100644 openspec/changes/consolidations-ui/proposal.md create mode 100644 openspec/changes/consolidations-ui/specs/consolidations-ui/spec.md create mode 100644 openspec/changes/consolidations-ui/tasks.md diff --git a/openspec/changes/consolidations-ui/.openspec.yaml b/openspec/changes/consolidations-ui/.openspec.yaml new file mode 100644 index 0000000..f56fe13 --- /dev/null +++ b/openspec/changes/consolidations-ui/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-10-23 diff --git a/openspec/changes/consolidations-ui/design.md b/openspec/changes/consolidations-ui/design.md new file mode 100644 index 0000000..e3f3f0f --- /dev/null +++ b/openspec/changes/consolidations-ui/design.md @@ -0,0 +1,117 @@ +## Context + +PR RSHB/arm-core#166 (ветка `AURORA-1589`, автор — Степанов, задача AURORA-1589) доводит до макета экраны консолидаций: +список консолидаций ГК [34] (`widgets/ConsoleTable/`), модалку «Взять в работу» и перехват [35] +(`widgets/ConsoleTable/LockModal.tsx`), панель «Организации» (`widgets/ConsoleLegalEntities/`), модалку «Новая +консолидация» [42] (`widgets/NewConsoleModal/`, строка ЮЛ — `CompanyOptionRow.tsx`), кнопку «Изменить статус» в шапке +карточки версии [30] (`layouts/ConsolidatedOsvPage.tsx`) и модалку [33-01] (`widgets/StatusChangeModal/ChangeStatusModal.tsx`). +Бэкенд — спека `consolidations-api` (список с `in_work_only`, «Взять в работу, перехват, снятие», «Статусы Среза 4»); API не +меняется. В ветку добавлена вторая библиотека иконок `lucide-react` (иконки макета: меню «⋯», «Взять в работу», «К +отчётности», боковое меню). + +Спеку, документацию и тесты ведёт ревьюер коммитами в ветку автора (правило владельца для чужих PR); продуктовый код +правит автор. Спека описывает **целевое** поведение; расхождения кода ветки (коммит 71ef633) — раздел «Known issues». +Источники: макет [34], [35], [42], [30], [33-01], [33], [31-00] (`docs/mockup/INDEX.md`), описание AURORA-1589, ТЗ +«Статусная модель» (`docs/source/tz/…08_4. Статусная модель.md`), гайд фронта по API §5.7. + +## Decisions + +- **D-1. Ручные переходы — зеркало `MANUAL_TRANSITIONS` во фронте.** API не отдаёт допустимые переходы (в `VersionCard` + нет `allowed_transitions`, заметка AURORA-1589 от 12.10.2026). Фронт держит одну константу «статус → допустимые ручные + переходы», совпадающую с `api/src/services/consolidation_status.py`: `INITIATED → {CANCELLED}`, + `DOCUMENTS_PROCESSING → {CANCELLED, INITIATED}`, `DATA_CORRECTION → {CANCELLED, INITIATED}`. С маршрутом согласования + (Срез 7) константа заменяется ответом API без переделки модалки. Расхождение константы с бэком сервер ловит 409 + `TRANSITION_NOT_ALLOWED`; заметка о зеркале — в гайде фронта §5.7 (PR в RSHB/arm-ka-docs). +- **D-2. Комментарий обязателен для обоих ручных переходов** (AURORA-1589): для `CANCELLED` его требует и сервер (422 + `COMMENT_REQUIRED`), для возврата в `INITIATED` — только фронт. +- **D-3. «Изменить статус» доступна по `lock` карточки и `/me`**: активна, если `lock.locked_by` = текущий пользователь и в + D-1 есть переходы из текущего статуса. Подсказка «Возьмите консолидацию в работу» (текст задачи AURORA-1589). +- **D-4. После смены статуса экран берёт карточку из ответа** `POST …/status` (`VersionCard`), без повторного + `GET`: бейдж, пояснение и кнопка обновляются сразу; после `CANCELLED` сервер снимает блокировку, кнопка становится + неактивной. +- **D-5. По умолчанию в «Новом этапе» ничего не выбрано** (ревью раунда 1): в макете [33-01] предложен следующий этап, но + сейчас один из двух вариантов — необратимая «Отменена», и случайная отправка по умолчанию недопустима. +- **D-6. «Только в работе» — серверный фильтр `in_work_only`**, по умолчанию выключен (макет [34], значение API по + умолчанию `false`). Фронт не фильтрует по статусу сам: множество «в работе» для списка определяет сервер. +- **D-7. Модалка [35] читает свежую карточку версии** перед показом: данные `lock` строки списка могут устареть. Перехват — + в той же модалке: при известной чужой блокировке сразу поле причины, при 409 `LOCKED_BY_OTHER` (гонка) — предупреждение + и поле причины. +- **D-8. ГСК в API нет (решение владельца П-3)**: колонка «ГСК» — «—», в тексте модалки [35] вместо ГСК макета — ГК + (`company_group.name` карточки). +- **D-9. Подпись `CANCELLED` — «Отменена»** (AURORA-1589, ревью): в ТЗ «Статусная модель» — «Отменен», в словаре UI + `10-user-journey.md` — «Отмена КФО»; выбран вариант задачи (согласование с «консолидацией»). «Корректировка данных» — + как в ТЗ (было «Коррекция данных»). +- **D-10. Кнопку «Взять в работу» блокирует код статуса `CANCELLED`, а не подпись** — подпись меняется (D-9), условие по + подписи ломается молча. + +## Known issues + +Расхождения кода ветки `AURORA-1589` (71ef633) с целевой спекой — по пунктам ревью раунда 1; исправляет автор PR. + +1. **404 при смене статуса.** `services/api/consolidations.ts` `updateStatus` шлёт `POST /consolidation/versions/{id}/status` + (нет «s»); нужен `/consolidations/versions/{id}/status`. +2. **Переходы — заглушка `mockStatusMappingFetch()` внутри модалки** (`ChangeStatusModal.tsx`). Нужна одна константа (D-1) + рядом с подписями статусов. Для статусов без переходов сейчас `nextStatusOptions = undefined`: форма скрыта, кнопка + «Изменить статус» в шапке при этом активна. +3. **«Новый этап» предвыбран** (`initialValues.to_status = nextStatusOptions[0]`, на стенде — «Отменён»); нужно пусто (D-5). +4. **Кнопка «Изменить статус»**: подсказка «Сначала возьмите версию в работу» вместо «Возьмите консолидацию в работу»; + отсутствие ручных переходов не учитывается (при своей блокировке `VERIFIED` кнопка активна, модалка пустая). +5. **Колонка «Версия» инвертирована** (`ConsoleTable/config.tsx`): показывает «1» и скрывает 2+; нужно наоборот. +6. **«Только в работе» включён по умолчанию** (`ConsoleTable.tsx`: `searchParams.get('in_work_only') || true`, флажок + отмечен, пока параметр не `'false'`); нужно выключен (D-6). +7. **Пункты «⋯» не `disabled`**: у них только класс `ant-dropdown-menu-item-disabled`, клик обрабатывается + («История изменений» ведёт в пустой «Журнал действий», остальные — `message.info('Будет позже')`); в `ITEMS` лишний + пустой элемент `{}`. +8. **Подпись `CANCELLED` — «Отменён»** (нужно «Отменена», D-9); «Взять в работу» блокируется сравнением + `row.status === 'Отменён'` — после переименования условие перестанет срабатывать (D-10). +9. **Перехват [35]**: плейсхолдер поля причины «Type message»; проверка длины `< 1000` вместо `≤ 1000`; квартал в тексте — + `Q3` вместо «К3»; опечатки «обнаржуена», «нформацию». +10. **Пояснение под заголовком**: для `INITIATED`, `DOCUMENTS_PROCESSING`, `DATA_CORRECTION` повторяется название статуса; + тексты `VERIFIED` и `CONSOLIDATION_RF` в `consStatusDescriptionMapping` расходятся с макетом [30], [33-01]. +11. **Модалка [31-00] «Остались неуказанные ИНН»** не реализована. Другие вкладки отчёта в ветке пока неактивны + (`OsvTabs`), поэтому сценарий проверяется после появления вкладки «Шахматка» (PR #158) или в нём же. +12. **«+ Создать» активна при одном отмеченном ЮЛ** (`NewConsoleModal.tsx`, `!legEntIds?.length`); нужно не меньше двух + (сервер отвечает 422 `PERIMETER_TOO_SMALL`). +13. **Модалка «Изменить статус», замечено при написании спеки** (в комментарий ревью раунда 1 не вошло): ошибка + `getVersionCard` не обрабатывается — модалка остаётся в загрузке; `comment.trim()` вызывается на значении + `Form.useWatch`, которое до монтирования формы `undefined`. +14. **Тестов нет.** Чистые правила (подпись версии, переходы, активность кнопок, параметр `in_work_only`) зашиты в + компоненты; тесты vitest — после их выноса в чистые функции (`tasks.md`). +15. **`lucide-react@0.263.1` в зеркале npm банка не проверен.** Пакет в `dependencies`, снимок контура его оставляет + (`docs/dev/contour-transfer-guide.md` §3.2); если версии нет в Nexus, сборка в контуре упадёт. +16. **Предупреждение браузера о несохранённых правках** (пункт AURORA-1589) не реализовано; в спеку не входит (решение (е)). + +## Decisions made without discussion + +- **2026-10-23 (а). Новая capability `consolidations-ui`; `consolidation-setup` и `consolidated-osv-ui` не правятся.** Вид + модалки [42], шапка карточки версии и модалка [31-00] описаны в новой спеке; состав модалки [42], создание и «К + отчётности» остаются в `consolidation-setup`, сводная ОСВ — в `consolidated-osv-ui`. Обоснование: не смешивать дельты + трёх спек в одном PR фронта. Цена ошибки: при архивации модалку [42] и страницу отчёта описывают по две спеки; сведение — + MODIFIED-дельтой позже. +- **2026-10-23 (б). Временные пояснения статусов первой очереди и `CANCELLED` — дословные фрагменты ТЗ «Статусная + модель»** (колонка «Описание»), пока аналитик не дал тексты (AURORA-1589: «тексты для статусов первой очереди — у + аналитика»); для `VERIFIED` и `CONSOLIDATION_RF` — тексты макета вместо текстов автора. Обоснование: подзаголовок не + должен повторять название статуса, а придумывать формулировки нельзя. Цена ошибки: замена строк в одном месте. +- **2026-10-23 (в). Порядок версий в дереве — как в ответе API** (сверху последняя версия периода, под ней предыдущие), как + в `main`. В макете [34] версия 1 стоит сверху, версия 2 — под ней. Цена ошибки: правка `flatten.ts` / `groupAdjacent.ts` + и MODIFIED требования «Список консолидаций ГК». +- **2026-10-23 (г). Минимум два ЮЛ для «+ Создать»** — из описания [42] в `docs/mockup/INDEX.md` («минимум 2») и 422 + `PERIMETER_TOO_SMALL`; фронт блокирует раньше сервера. Цена ошибки: одно условие. +- **2026-10-23 (д). Модалка [31-00] — только при переходе на другую вкладку отчёта**, не при «Назад» и переходах по меню. + Открытые вопросы владельцу: (1) нужно ли предупреждать и при уходе со страницы отчёта; (2) AURORA-1589: «на реальных + данных в счётчик попадают строки, которые не являются организациями… до нуля он не доводится» — поведение согласовать с + задачей «Блокировка шага до сопоставления контрагентов без ИНН»; до решения модалка не блокирует переход. Цена ошибки: + расширение триггера — MODIFIED требования. +- **2026-10-23 (е). Предупреждение браузера о несохранённых правках не включено в спеку**: пункт задачи касается всех форм + и модалок приложения, а не экранов консолидаций; остаётся задачей автора в `tasks.md`. Цена ошибки: требование появится + отдельной спекой (или дельтой) позже. +- **2026-10-23 (ж). Подпись `DOCUMENTS_PROCESSING` оставлена «Обработка документов»** (как в `main`); в ТЗ — «Загрузка, + распознавание и корректировка документов», в словаре UI — «Загрузка и распознавание документов». Вопрос аналитику. + Цена ошибки: замена одной подписи. +- **2026-10-23 (з). Тексты сообщений об ошибках 409/422 в модалке «Изменить статус» не фиксируются дословно**: спека + требует сообщение и открытую модалку. Цена ошибки: низкая. +- **2026-10-23 (и). В ветку влит `origin/main`** (шахматка «пара без встречной стороны» PR #165 и архивы OpenSpec + PR #160, #167, #168) — без конфликтов; файлы `web/` ветки слиянием не затронуты. Цена ошибки: низкая, PR и так + сливается в этот `main`. +- **2026-10-23 (к). «Единицы» и «Знаков после запятой» сводной ОСВ (коммит 71ef633, AURORA-1539) в спеку не включены** — + автору предложено вынести их в отдельный PR. Цена ошибки: если коммит останется в PR, его поведение будет без спеки. diff --git a/openspec/changes/consolidations-ui/proposal.md b/openspec/changes/consolidations-ui/proposal.md new file mode 100644 index 0000000..e79e868 --- /dev/null +++ b/openspec/changes/consolidations-ui/proposal.md @@ -0,0 +1,62 @@ +## Why + +В ветке `AURORA-1589` (PR RSHB/arm-core#166, автор — Степанов, задача AURORA-1589) фронт доводит экраны консолидаций до +макета: список консолидаций ГК [34] с «Взять в работу» и перехватом [35], модалку «Новая консолидация» [42] и кнопку +«Изменить статус» в карточке версии [30] с модалкой [33-01]. Бэкенд этих действий уже в main (`consolidations-api`: +список с `in_work_only`, блокировка и перехват, ручная смена статуса). У экранов нет UI-спеки. Спеку, документацию и тесты +ведёт ревьюер коммитами в ветку автора (правило владельца): спека задаёт целевое поведение, расхождения кода ветки с ней — +`design.md`, «Known issues»; продуктовый код правит автор. + +## What Changes + +Репозиторий — только arm-core (`web/`). Эндпоинты arm-core (без изменений): `GET /company-groups/{id}/consolidations` +(`in_work_only`), `GET /consolidations/versions/{id}`, `POST /consolidations/versions/{id}/lock` (`takeover_reason`), +`POST /consolidations/versions/{id}/status`, `POST /consolidations`. + +- Список консолидаций [34]: колонки, дерево версий с номером только у версий 2+, фильтр «Только в работе» (выключен по + умолчанию), «Взять в работу» с подтверждением [35] и перехватом с причиной, неактивные пункты меню «⋯». +- Панель «Организации» без выбранной консолидации и серый статус «Отсутствует». +- Подписи статусов версии («Корректировка данных», «Отменена») и пояснение статуса под заголовком карточки. +- Модалка «Новая консолидация» [42]: ИНН отдельной колонкой, «+ Создать», без звёздочек обязательности. +- «Изменить статус» [33-01]: допустимые переходы — зеркало `MANUAL_TRANSITIONS` бэка, по умолчанию ничего не выбрано, + кнопка доступна только владельцу блокировки и при наличии ручных переходов. +- Модалка [31-00] «Остались неуказанные ИНН» при уходе со «Сводной ОСВ» на другую вкладку отчёта. +- Новая спека `consolidations-ui` (ADDED Requirements). +- Документация фронта: `web/CLAUDE.md` (вторая библиотека иконок `lucide-react`), `web/ARCHITECTURE.md` (новые виджеты). + +## Non-goals + +- Исправление продуктового кода по «Known issues» (`design.md`) — за автором PR. +- «Единицы» и «Знаков после запятой» в сводной ОСВ (коммит 71ef633, AURORA-1539) — автору предложено вынести в отдельный + PR; в эту спеку не входят. +- Полный маршрут согласования (переходы Среза 7), «Добавить версию», «Отключить подтверждение КФО», «История изменений», + «Редактировать состав», «Импорт», «Дата верификации», «Утверждён в РФ» / «Верифицирован в ГО» — зонтичная задача + AURORA-1416. +- ГСК консолидации в API списка и карточки (колонка «ГСК») — отдельная задача ядра; до неё колонка пустая. +- Список допустимых переходов из API (`allowed_transitions`) — с маршрутом согласования; до него фронт держит зеркало. +- Предупреждение браузера о несохранённых правках (пункт задачи AURORA-1589) — касается всех форм приложения, в эту спеку + не входит (`design.md`, решение без обсуждения (е)). +- Изменения бэкенда и DBML. + +## Capabilities + +### New Capabilities +- `consolidations-ui`: список консолидаций ГК, взятие в работу и перехват, модалка новой консолидации (вид), смена статуса + версии и шапка карточки версии. + +### Modified Capabilities + +Нет: `consolidation-setup` (состав модалки [42], создание, «К отчётности») и `consolidated-osv-ui` (сводная ОСВ) не +правятся — добавленное поведение описано в новой спеке (`design.md`, решение без обсуждения (а)). + +## Impact + +- `web/src/widgets/ConsoleTable/` (`ConsoleTable.tsx`, `LockModal.tsx`, `config.tsx`, `consts.ts`), + `web/src/widgets/StatusChangeModal/ChangeStatusModal.tsx`, `web/src/widgets/NewConsoleModal/` + (`NewConsoleModal.tsx`, `CompanyOptionRow.tsx`), `web/src/widgets/ConsoleLegalEntities/`, + `web/src/layouts/ConsolidatedOsvPage.tsx`, `web/src/layouts/ConsolidationsList.tsx`, + `web/src/services/api/consolidations.ts`, `web/src/store/slices/consolidations/thunks.ts`, `web/src/types/`, + `web/src/widgets/Sidebar/` (иконки), `web/package.json` (`lucide-react`). +- Права: действия требуют `CONSOLIDATION_EDIT` на сервере; меню по правам не скрывается. +- Гайд фронта по API (`docs/dev/frontend-api-guide.md` §5.7): заметка о зеркале ручных переходов — PR в RSHB/arm-ka-docs, + сливать вместе с этим PR. diff --git a/openspec/changes/consolidations-ui/specs/consolidations-ui/spec.md b/openspec/changes/consolidations-ui/specs/consolidations-ui/spec.md new file mode 100644 index 0000000..4d9ce36 --- /dev/null +++ b/openspec/changes/consolidations-ui/specs/consolidations-ui/spec.md @@ -0,0 +1,226 @@ +## ADDED Requirements + +### Requirement: Список консолидаций ГК +Экран консолидаций ГК [34] SHALL показывать версии из `GET /company-groups/{id}/consolidations` таблицей с колонками +Год, Квартал (К1–К4), Версия, Статус (бейдж, подписи — «Подписи статусов версии»), ГСК, Дата создания, Дата верификации, +Организаций (`members_count`) и колонкой действий: «Взять в работу» (или «В работе»), «К отчётности», меню «⋯». Версии +одного периода SHALL показываться деревом: верхняя строка — первая версия периода из ответа API (по убыванию +`version_no`), остальные — раскрываемыми строками под ней. Колонка «ГСК» SHALL иметь фильтр в заголовке, «Дата создания» — +без фильтра. Пока API не отдаёт ГСК консолидации и дату верификации, колонки «ГСК» и «Дата верификации» SHALL показывать +«—». Рядом с заголовком «Консолидации» — число строк («N шт.»). Клик по строке SHALL выбирать версию для панели +«Организации» и подсвечивать строку. + +#### Scenario: Колонки списка +- **WHEN** открыт список консолидаций ГК «Русский бисквит» +- **THEN** у таблицы колонки Год, Квартал, Версия, Статус, ГСК, Дата создания, Дата верификации, Организаций и колонка + действий; у «ГСК» есть фильтр, у «Дата создания» — нет; в «ГСК» и «Дата верификации» — «—» + +#### Scenario: Выбор версии +- **WHEN** аналитик кликает по строке версии 2024 К3 +- **THEN** строка подсвечена, панель «Организации» показывает состав этой версии + +### Requirement: Колонка «Версия» +Колонка «Версия» SHALL быть пустой у версии с `version_no = 1` и показывать номер у версий с `version_no ≥ 2`. + +#### Scenario: Единственная версия периода +- **WHEN** у консолидации 2025 К1 одна версия (`version_no = 1`) +- **THEN** ячейка «Версия» пустая + +#### Scenario: Вторая версия периода +- **WHEN** у консолидации 2024 К1 версии 2 и 1 +- **THEN** у строки версии 2 в колонке «Версия» — «2», у строки версии 1 — пусто + +### Requirement: Фильтр «Только в работе» +Над таблицей SHALL быть флажок «Только в работе», по умолчанию **выключенный**. Включённый флажок SHALL перечитывать список +запросом `GET /company-groups/{id}/consolidations?in_work_only=true` (отбор делает сервер: остаются версии со статусом не +из `VERIFIED`, `CANCELLED`, `ARCHIVED`, `REJECTED`); выключенный — запросом с `in_work_only=false` (или без параметра). +Фронт MUST NOT фильтровать версии по статусу сам. + +#### Scenario: Открытие экрана +- **WHEN** аналитик впервые открывает список консолидаций ГК +- **THEN** флажок «Только в работе» снят, запрос — с `in_work_only=false`, в таблице есть верифицированные и отменённые + версии + +#### Scenario: Включение фильтра +- **WHEN** аналитик отмечает «Только в работе» +- **THEN** список перечитан с `in_work_only=true`, отменённой версии в таблице нет + +### Requirement: Взять в работу +Кнопка «Взять в работу» в строке SHALL открывать модалку «Взять консолидацию в работу?» [35]. Состояние блокировки +модалка SHALL брать из свежей карточки `GET /consolidations/versions/{id}` (`lock`): +- блокировки нет — текст «Консолидация <год> К · <ГК> будет закреплена за вами для редактирования.», кнопки + «Отмена» / «Взять в работу»; «Взять в работу» отправляет `POST /consolidations/versions/{id}/lock` без + `takeover_reason`; +- версию держит другой пользователь — текст «Консолидация взята в работу <ФИО>. Укажите причину замены.» и поле причины + (обязательно, ≤ 1000 символов, строка из пробелов считается пустой); «Взять в работу» неактивна, пока причина пуста, и + отправляет `POST …/lock {takeover_reason}` (перехват). + +После 200/201 модалка SHALL закрыться с сообщением «Консолидация взята в работу.» и перечитать список. Ответ 409 +`LOCKED_BY_OTHER` на запрос без причины (версию успели взять) SHALL переводить модалку в режим перехвата с предупреждением +«<ФИО> только что взял(-а) консолидацию в работу.» и пустым полем причины. Ответ 409 `VERSION_NOT_EDITABLE` SHALL +закрывать модалку с сообщением «Нельзя взять в работу отменённую версию.». У версии со статусом `CANCELLED` кнопка +«Взять в работу» SHALL быть неактивной (условие — по коду статуса, а не по подписи); у версии, которую держит текущий +пользователь, вместо неё SHALL показываться неактивная кнопка «В работе». + +#### Scenario: Свободная версия +- **WHEN** аналитик нажимает «Взять в работу» у версии без блокировки и подтверждает +- **THEN** отправлен `POST …/lock` без тела причины, модалка закрыта, в строке — неактивная «В работе» + +#### Scenario: Перехват с причиной +- **WHEN** версию держит «Соколов А. В.», аналитик нажимает «Взять в работу» +- **THEN** модалка показывает «Консолидация взята в работу Соколов А. В. Укажите причину замены.» и поле причины; + «Взять в работу» неактивна, пока причина пуста; после ввода «Отпуск» отправлен `POST …/lock {takeover_reason: "Отпуск"}` + +#### Scenario: Версию взяли, пока модалка открыта +- **WHEN** в модалке свободной версии аналитик нажимает «Взять в работу», а сервер отвечает 409 `LOCKED_BY_OTHER` +- **THEN** модалка остаётся открытой в режиме перехвата с предупреждением «<ФИО> только что взял(-а) консолидацию в + работу.» и пустым полем причины + +#### Scenario: Отменённая версия +- **WHEN** версия в статусе «Отменена» +- **THEN** «Взять в работу» в её строке неактивна + +### Requirement: Меню «⋯» строки консолидации +Меню «⋯» строки SHALL содержать пункты «Добавить версию», «Отключить подтверждение КФО», «История изменений» с иконками +[43]. Пока функции нет, пункты SHALL быть неактивными (`disabled`) с подсказкой «Будет позже»; нажатие на неактивный пункт +MUST NOT выполнять действий (ни перехода, ни всплывающего сообщения). + +#### Scenario: Неактивный пункт +- **WHEN** аналитик открывает «⋯» и нажимает «История изменений» +- **THEN** пункт неактивен, видна подсказка «Будет позже», переход в «Журнал действий» не происходит + +### Requirement: Панель «Организации» +Пока в списке не выбрана версия, панель «Организации» SHALL показывать заголовок «Организации» с подписью «Выберите +консолидацию» и текст «Выберите консолидацию выше» вместо таблицы. В колонках «ОФР» и «Бух. баланс» статус «Отсутствует» +SHALL быть нейтральным серым бейджем (как в легенде чек-листа [37]); красный — только у «Ошибка». + +#### Scenario: Версия не выбрана +- **WHEN** открыт список консолидаций, строка не выбрана +- **THEN** панель «Организации» без таблицы и без «0 шт.», в ней текст «Выберите консолидацию выше» + +#### Scenario: Документ отсутствует +- **WHEN** у ЮЛ выбранной версии нет ББ +- **THEN** в колонке «Бух. баланс» — серый бейдж «Отсутствует» + +### Requirement: Подписи статусов версии +Фронт SHALL показывать статусы версии одними подписями в списке, фильтре колонки «Статус», шапке карточки и модалке +«Изменить статус»: `INITIATED` — «Инициация», `DOCUMENTS_PROCESSING` — «Обработка документов», `DATA_CORRECTION` — +«Корректировка данных», `CONSOLIDATION_RF` — «Консолидация РФ», `VERIFICATION_RF` — «Верификация РФ», `CONSOLIDATION_GO` — +«Консолидация ГО», `VERIFICATION_GO` — «Верификация ГО», `VERIFIED` — «Верифицирован», `CANCELLED` — «Отменена», +`ADJUSTMENT` — «Корректировка», `ARCHIVED` — «В архиве», `REJECTED` — «Отклонён». + +#### Scenario: Корректировка данных +- **WHEN** версия в статусе `DATA_CORRECTION` +- **THEN** в списке и в карточке — бейдж «Корректировка данных» + +#### Scenario: Отменённая версия +- **WHEN** версия в статусе `CANCELLED` +- **THEN** в списке и в карточке — бейдж «Отменена» + +### Requirement: Вид модалки «Новая консолидация» +Модалка [42] (состав и создание — спека `consolidation-setup`) SHALL показывать поля без звёздочек обязательности и кнопку +«+ Создать» (иконка «плюс»), неактивную, пока не выбраны ГК, ГСК, год, квартал и не отмечено не меньше двух ЮЛ. В блоке +«ЮЛ консолидации» строка ЮЛ SHALL содержать флажок, наименование (длинное — с многоточием) и ИНН отдельной колонкой, +выровненной по правому краю независимо от длины наименования; над списком — поиск по наименованию, под списком — +«Выбрано: N / M». + +#### Scenario: Выравнивание ИНН +- **WHEN** в блоке «ЮЛ консолидации» есть ЮЛ «ВМГ, ООО» и «ПЕКАРНЯ СЧАСТЛИВОЧНАЯ, ООО» +- **THEN** их ИНН стоят в одной колонке на одной вертикали + +#### Scenario: Одно ЮЛ +- **WHEN** выбраны ГК, ГСК, год, квартал и отмечено одно ЮЛ +- **THEN** «+ Создать» неактивна + +### Requirement: Кнопка «Изменить статус» в карточке версии +Шапка карточки версии [30] SHALL показывать справа «Статус отчёта» (бейдж) и кнопку «Изменить статус». Кнопка SHALL быть +активной, только если версия взята в работу текущим пользователем (`lock.locked_by` карточки = `id` из `/me`) и для +текущего статуса есть хотя бы один ручной переход (требование «Модалка «Изменить статус»»). Без своей блокировки кнопка +SHALL быть неактивной с подсказкой «Возьмите консолидацию в работу»; при своей блокировке и отсутствии ручных переходов — +неактивной. + +#### Scenario: Версия не взята в работу +- **WHEN** аналитик открыл карточку версии `DATA_CORRECTION`, блокировки нет +- **THEN** «Изменить статус» неактивна, подсказка «Возьмите консолидацию в работу» + +#### Scenario: Версия у текущего пользователя +- **WHEN** аналитик взял версию `DATA_CORRECTION` в работу и открыл карточку +- **THEN** «Изменить статус» активна + +#### Scenario: Нет ручных переходов +- **WHEN** аналитик держит блокировку версии `VERIFIED` +- **THEN** «Изменить статус» неактивна + +### Requirement: Модалка «Изменить статус» +Модалка [33-01] SHALL показывать «Текущий этап» (бейдж статуса), «Новый этап» (выпадающий список) и «Комментарий» +(≤ 1000 символов), кнопки «Отмена» / «Изменить статус». Варианты «Нового этапа» SHALL совпадать с ручными переходами бэка +(`MANUAL_TRANSITIONS` в `api/src/services/consolidation_status.py`; API их не отдаёт, фронт держит зеркало в одном месте): +- `INITIATED` → `CANCELLED`; +- `DOCUMENTS_PROCESSING` → `CANCELLED`, `INITIATED`; +- `DATA_CORRECTION` → `CANCELLED`, `INITIATED`; +- из остальных статусов ручных переходов нет. + +По умолчанию в «Новом этапе» ничего не выбрано. «Изменить статус» SHALL быть активной, только когда выбран новый этап и +комментарий непуст после обрезки пробелов (комментарий обязателен для обоих переходов). Нажатие SHALL отправлять +`POST /consolidations/versions/{id}/status {to_status, comment}` (комментарий обрезан); при 200 модалка закрывается, а +карточка версии на экране заменяется карточкой из ответа: бейдж, пояснение под заголовком и состояние кнопки «Изменить +статус» берутся из неё (после «Отменена» блокировка снята — кнопка неактивна). Ответы 409 (`VERSION_NOT_EDITABLE`, +`LOCK_REQUIRED`, `LOCKED_BY_OTHER`, `TRANSITION_NOT_ALLOWED`) и 422 (`COMMENT_REQUIRED`) SHALL показываться сообщением об +ошибке, модалка остаётся открытой, статус на экране не меняется. + +#### Scenario: Варианты из «Корректировки данных» +- **WHEN** аналитик держит блокировку версии `DATA_CORRECTION` и открывает «Изменить статус» +- **THEN** «Текущий этап» — «Корректировка данных», в «Новом этапе» ничего не выбрано, варианты — «Отменена» и + «Инициация»; «Изменить статус» неактивна + +#### Scenario: Отмена версии +- **WHEN** аналитик выбирает «Отменена», пишет комментарий «Дубль» и нажимает «Изменить статус» +- **THEN** отправлен `POST /consolidations/versions/{id}/status {to_status: "CANCELLED", comment: "Дубль"}`; модалка + закрыта; бейдж — «Отменена», «Изменить статус» неактивна; в списке консолидаций у версии статус «Отменена» + +#### Scenario: Возврат в «Инициацию» +- **WHEN** аналитик держит блокировку версии `DOCUMENTS_PROCESSING`, выбирает «Инициация» и пишет комментарий +- **THEN** после ответа 200 бейдж — «Инициация», кнопка «Изменить статус» остаётся активной (переход в «Отменена» доступен) + +#### Scenario: Комментарий из пробелов +- **WHEN** выбран новый этап, комментарий состоит из пробелов +- **THEN** «Изменить статус» неактивна + +#### Scenario: Переход отклонён сервером +- **WHEN** пока модалка открыта, статус версии изменился, и сервер отвечает 409 `TRANSITION_NOT_ALLOWED` +- **THEN** показано сообщение об ошибке, модалка открыта, бейдж на экране прежний + +### Requirement: Пояснение статуса под заголовком карточки +Под заголовком карточки версии «<ГК> — <год> <квартал>» SHALL показываться пояснение текущего статуса, а не его +название: `CONSOLIDATION_RF` — «Автоматическая консолидация, ручные проверки и сравнение КФО клиента и банка», `VERIFIED` — +«Отчет верифицирован ГО, КА ГО внес в систему номер и дату решения УОБ» (макет [30], [33-01]); `INITIATED`, +`DOCUMENTS_PROCESSING`, `DATA_CORRECTION`, `CANCELLED` — тексты аналитика, до их получения — временные из ТЗ «Статусная +модель» (`design.md`, решение без обсуждения (б)): `INITIATED` — «Система зафиксировала состав ГСК на отчетную дату и +инициатора (КА РФ или КА ГО)», `DOCUMENTS_PROCESSING` — «КА загружает документы; система отправляет pdf файлы в ИС +Сканирование, производит парсинг ОСВ, бухгалтерского баланса и ОФР», `DATA_CORRECTION` — «Выявлены некорректные данные в +ИС Сканирование, проводится ручная корректировка. Пользователь валидирует распарсенные данные и вносит правки», +`CANCELLED` — «Заявка на формирование/подтверждение КФО аннулирована по инициативе пользователя». Тексты держатся в одном +месте рядом с подписями статусов. + +#### Scenario: Пояснение «Корректировки данных» +- **WHEN** открыта карточка версии `DATA_CORRECTION` +- **THEN** под заголовком — пояснение статуса, а не слова «Корректировка данных» + +#### Scenario: Пояснение после смены статуса +- **WHEN** версия переведена в «Отменена» из модалки «Изменить статус» +- **THEN** пояснение под заголовком сменилось на пояснение статуса `CANCELLED` без перезагрузки страницы + +### Requirement: Предупреждение «Остались неуказанные ИНН» +При уходе со вкладки «ОСВ» на другую вкладку отчёта версии, если в сводке `unmapped_total > 0`, фронт SHALL показывать +модалку [31-00] «Остались неуказанные ИНН»: «В ОСВ остались неуказанные ИНН», «Не заполнено ИНН: N. Точно хотите перейти +в другой раздел?», кнопки «Остаться» / «Перейти». «Остаться» SHALL закрывать модалку без перехода, «Перейти» — выполнять +переход. При `unmapped_total = 0` переход SHALL выполняться без модалки. + +#### Scenario: Есть несопоставленные строки +- **WHEN** в сводке `unmapped_total = 2` и аналитик выбирает другую вкладку отчёта +- **THEN** показана модалка «Не заполнено ИНН: 2. Точно хотите перейти в другой раздел?»; «Остаться» оставляет вкладку + «ОСВ», «Перейти» открывает выбранную вкладку + +#### Scenario: Все строки сопоставлены +- **WHEN** `unmapped_total = 0` и аналитик выбирает другую вкладку отчёта +- **THEN** вкладка открывается без модалки diff --git a/openspec/changes/consolidations-ui/tasks.md b/openspec/changes/consolidations-ui/tasks.md new file mode 100644 index 0000000..1d45493 --- /dev/null +++ b/openspec/changes/consolidations-ui/tasks.md @@ -0,0 +1,35 @@ +## 1. Ревьюер (RSHB/arm-core#166, AURORA-1589) + +- [x] 1.1 Влить `origin/main` в ветку `AURORA-1589` (без конфликтов). +- [x] 1.2 Change `consolidations-ui`: proposal, design (Decisions, Known issues, Decisions made without discussion), спека + `consolidations-ui` — целевое поведение. +- [x] 1.3 `web/CLAUDE.md` — `lucide-react` в «Стек»; `web/ARCHITECTURE.md` — новые виджеты экранов консолидаций. +- [x] 1.4 Гайд фронта по API §5.7 — заметка о зеркале ручных переходов (PR в RSHB/arm-ka-docs, сливать вместе с #166). + +## 2. Автор PR + +- [ ] 2.1 Исправить «Known issues» 1–13 из `design.md`. +- [ ] 2.2 Вынести коммит 71ef633 («Единицы» сводной ОСВ, AURORA-1539) в отдельный PR. +- [ ] 2.3 Вынести чистые правила из компонентов в функции без React: подпись колонки «Версия», константа ручных переходов + (D-1), активность кнопки «Изменить статус» (D-3), активность «Изменить статус» в модалке, параметр `in_work_only`, + подписи и пояснения статусов. +- [ ] 2.4 Предупреждение браузера о несохранённых правках (пункт AURORA-1589; вне спеки, решение (е) в `design.md`). +- [ ] 2.5 Проверить наличие `lucide-react@0.263.1` в зеркале npm банка (Known issues 15) или заменить иконки на + `@ant-design/icons`. +- [ ] 2.6 Перед слиянием: `make web-check`, `npm test`, `npm run lint` — зелёные, вывод в описание PR. +- [ ] 2.7 Сверка экранов с макетом [34], [35], [42], [30], [33-01], [31-00] на стенде; сценарий AURORA-1589: взять версию + в работу → «Изменить статус» → «Отменена» с комментарием → новый статус в списке и запись в истории; то же для + возврата в «Инициация». + +## 3. Тесты (ревьюер, после 2.3) + +- [ ] 3.1 vitest на вынесенные функции: «Версия» (1 → пусто, 2 → «2»); переходы — совпадение с `MANUAL_TRANSITIONS` + и пустой список для `VERIFIED`, `CANCELLED`, статусов Среза 7; кнопка «Изменить статус» (своя / чужая / нет + блокировки × есть / нет переходов); модалка — нет выбора, комментарий из пробелов; `in_work_only` по умолчанию `false`; + подписи «Корректировка данных», «Отменена»; пояснение не равно подписи для статусов из спеки. + +## 4. После слияния + +- [ ] 4.1 Тексты пояснений статусов первой очереди от аналитика вместо временных (решение (б)). +- [ ] 4.2 С маршрутом согласования (Срез 7): допустимые переходы из API вместо зеркала (D-1), MODIFIED-дельта спеки. +- [ ] 4.3 ГСК консолидации в API — колонка «ГСК» и текст модалки [35] (D-8).