Andrey Epifancev 1cce1575b8 openspec: архив counter-pairs, Purpose consolidations-ui (#195, AURORA-1746, M-7)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 23:10:42 +04:00

30 KiB
Raw Blame History

consolidations-ui Specification

Purpose

Аналитик работает со списком консолидаций ГК [34] (флажок «Только в работе», «Версия», меню «⋯»), берёт версию в работу или перехватывает её [35], создаёт консолидацию [42] и меняет статус версии из шапки страницы отчёта [30], [33-01]; при уходе со «Сводной ОСВ», если есть пары участников без встречных записей, — предупреждение «Проверьте встречные записи участников» (AURORA-1746, вместо [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):

  • блокировки нет — текст «Консолидация <год> К · <ГК> будет закреплена за вами для редактирования.», кнопки «Отмена» / «Взять в работу»; «Взять в работу» отправляет 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: Предупреждение о несохранённых правках в модалках консолидаций

Пока открыта модалка с начатым вводом, браузер SHALL спрашивать подтверждение при закрытии или перезагрузке вкладки (стандартный диалог beforeunload, текст задаёт браузер): «Взять консолидацию в работу?» — введена причина перехвата (непустая после обрезки пробелов); «Изменить статус» — выбран новый этап или введён комментарий; «Новая консолидация» — выбрано хотя бы одно из полей ГК, ГСК, год, квартал. После закрытия модалки (отправка или «Отмена») предупреждения нет. Переход по меню приложения при открытой модалке закрыт её маской.

Scenario: Причина перехвата введена

  • WHEN в модалке перехвата введена причина «Отпуск» и аналитик перезагружает вкладку
  • THEN браузер показывает диалог подтверждения ухода

Scenario: Ничего не введено

  • WHEN модалка «Изменить статус» открыта, этап не выбран, комментарий пуст, аналитик закрывает вкладку
  • THEN вкладка закрывается без диалога

Requirement: Текущий пользователь и его роли в боковом меню

Клик по логотипу «АРМ КА» в раскрытом боковом меню SHALL раскрывать блок с данными из GET /me: ФИО, логин (email), роли (названия из role_details[].name через запятую; если названия нет — код роли; без ролей — «не назначена») и филиал. Повторный клик или клик вне блока SHALL закрывать его. Названия — только для показа, логика фронта по ним не решается.

Scenario: Пользователь с несколькими ролями

  • WHEN пользователь с ролями KA_RF и RKA кликает по логотипу «АРМ КА»
  • THEN раскрывается блок с его ФИО, email, подписью «Роли» и названиями обеих ролей (не кодами) и филиалом

Scenario: Название роли недоступно

  • WHEN в role_details нет названия для роли пользователя
  • THEN в блоке показан код этой роли

Requirement: Предупреждение «Нет встречных записей»

При уходе со вкладки «ОСВ» на другую вкладку отчёта версии фронт SHALL показывать модалку «Проверьте встречные записи участников», если в сводке есть пары counter_pairs и этот список пар ещё не показывался в модалке для этой версии в текущей сессии браузера. Текст: «Нет встречных записей: N пар у M участников.» (N — число пар, M — число разных missing_id; слова согласуются с числом: «1 пара у 1 участника», «2 пары у 2 участников», «5 пар у 3 участников») и «Возможно, контрагент среди строк без ИНН, его ИНН не найден в справочнике или это пропуск в учёте. Ещё K строк без ИНН учтены как внешние.» (K — unmapped_total; при K = 0 вторая фраза без последнего предложения). Кнопки:

  • «Показать пары» — закрыть модалку без перехода и открыть на вкладке «ОСВ» режим «Встречные записи» с первой парой;
  • «Остаться» — закрыть модалку без перехода;
  • «Перейти» — выполнить переход.

Показ запоминается в sessionStorage браузера по версии вместе со списком пар (упорядоченные пары holder_id → missing_id); повторный уход с «ОСВ» в той же сессии модалку не показывает, пока список пар не изменился (например, сопоставление закрыло одну из пар — модалка покажет оставшиеся). Недоступное хранилище — модалка показывается при каждом уходе, ошибкой это не считается. Без пар (counter_pairs пуст) переход SHALL выполняться без модалки при любом unmapped_total. В БД ничего не пишется (решение владельца 27.10.2026). Для версии в завершённом статусе (VERIFIED, CANCELLED, ARCHIVED, REJECTED) модалка не показывается. Пока шагов после ОСВ нет, их вкладки неактивны и модалка не вызывается.

Scenario: Пара без встречных записей

  • WHEN в сводке одна пара (Русский бисквит ← Пекарня Счастливочная), unmapped_total = 1260, и аналитик выбирает вкладку «Шахматка»
  • THEN показана модалка «Нет встречных записей: 1 пара у 1 участника…»; «Перейти» открывает шахматку

Scenario: Повтор в той же сессии

  • WHEN аналитик вернулся на «ОСВ» и снова выбирает «Шахматку», список пар не изменился
  • THEN шахматка открывается без модалки

Scenario: Список пар изменился

  • WHEN после показа модалки аналитик сопоставил контрагента, закрыв одну из двух пар, и выбирает «Шахматку»
  • THEN модалка показана снова с «Нет встречных записей: 1 пара у 1 участника…»

Scenario: Только строки без ИНН

  • WHEN counter_pairs пуст, unmapped_total = 214, и аналитик выбирает «Шахматку»
  • THEN шахматка открывается без модалки

Scenario: Показать пары

  • WHEN в модалке нажато «Показать пары»
  • THEN вкладка «ОСВ» остаётся, открыт режим «Встречные записи» с первой парой