Andrey Epifancev da15355dd7 Архив OpenSpec consolidations-ui (PR #166)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 11:00:20 +04:00

260 lines
26 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.

# consolidations-ui Specification
## Purpose
Аналитик работает со списком консолидаций ГК [34] (флажок «Только в работе», «Версия», меню «⋯»), берёт версию в работу или перехватывает её [35], создаёт консолидацию [42] и меняет статус версии из шапки страницы отчёта [30], [33-01]; при уходе со «Сводной ОСВ» с несопоставленными строками — предупреждение [31-00].
## 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`):
- блокировки нет — текст «Консолидация <год> К<n> · <ГК> будет закреплена за вами для редактирования.», кнопки
«Отмена» / «Взять в работу»; «Взять в работу» отправляет `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
закрывать модалку с сообщением «Нельзя взять в работу отменённую версию.». Прочие ошибки (403 без права
`CONSOLIDATION_EDIT`, иные 409/422) SHALL показываться текстом сервера (`ApiError.message`), модалка остаётся открытой. ФИО
в тексте модалки не получает вторую точку («Соколов А. В. Укажите причину замены.»). У версии со статусом `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** «Взять в работу» в её строке неактивна
#### Scenario: Нет права
- **WHEN** пользователь без `CONSOLIDATION_EDIT` подтверждает перехват, сервер отвечает 403
- **THEN** показан текст ответа сервера («недостаточно прав: требуется CONSOLIDATION_EDIT»), модалка открыта
#### 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** вкладка открывается без модалки
### Requirement: Предупреждение о несохранённых правках в модалках консолидаций
Пока открыта модалка с начатым вводом, браузер SHALL спрашивать подтверждение при закрытии или перезагрузке вкладки
(стандартный диалог `beforeunload`, текст задаёт браузер): «Взять консолидацию в работу?» — введена причина перехвата
(непустая после обрезки пробелов); «Изменить статус» — выбран новый этап или введён комментарий; «Новая консолидация» —
выбрано хотя бы одно из полей ГК, ГСК, год, квартал. После закрытия модалки (отправка или «Отмена») предупреждения нет.
Переход по меню приложения при открытой модалке закрыт её маской.
#### Scenario: Причина перехвата введена
- **WHEN** в модалке перехвата введена причина «Отпуск» и аналитик перезагружает вкладку
- **THEN** браузер показывает диалог подтверждения ухода
#### Scenario: Ничего не введено
- **WHEN** модалка «Изменить статус» открыта, этап не выбран, комментарий пуст, аналитик закрывает вкладку
- **THEN** вкладка закрывается без диалога