2026-10-28 21:22:56 +04:00

28 KiB
Raw Blame History

Дизайн: экран «Таблица корректировки» (AURORA-1541, arm-core #206)

Зачем

Кредитный аналитик на шаге консолидации видит, где внутригрупповые обороты двух компаний не сошлись, разбирается, из каких строк ОСВ сложилась каждая сторона, переносит строки между правилами и вносит корректировку — сколько и из каких статей ББ исключить. Без экрана корректировки ВГО делаются только вне системы, и тестирование корректировок (AURORA-1542, с 03.11) начать нельзя.

Что считается готовым (слова владельца, 28.10.2026)

  • К сроку 02.11 — рабочий экран на настоящем API, не демо на моках. Если бэкенд (AURORA-1540) или аналитика не успевают — мы сами помогаем ребятам доделать.
  • Моки нужны, чтобы фронт не стоял, пока нет API, а не как результат.

Объём плана — только web/. Бэкенд (DBML, vgo_assignment, разнесение, эндпоинты, аудит) — AURORA-1540 Цыганкова; помогаем ему на ревью его PR, а не задачами этого плана. Последняя задача плана — подключение к настоящему API, когда 1540 слит: флаг REACT_APP_CORRECTIONS_MOCK выключается, если эндпоинты есть в main, вкладка открывается на стенде на реальной версии и проходит сценарии спеки; расхождения ответа с контрактом правятся в той ветке, где ошибка (фейк или бэкенд). Сверяем фейк с реальным ответом мы (владелец / этот агент) при подключении.

Источники и их вес

  1. Аналитика Лысенко — DOC-272613, ответы 1–7 (AURORA-1395, 27.10), DOC-274230. Приоритетна над нашими правилами и черновиками (решение владельца 28.10).
  2. Дизайн от 23.10.2026 — ДКБ_таблица_корректировок_23_10_26_1.html (вложение к DOC-272613; в корне workspace). Как лежат строки в дизайне — визуализация; логика — по аналитике.
  3. ТЗ 6.8 / Прил. 9 — ниже аналитики, иногда игнорируется.
  4. Контракт API — ../docs/dev/api-contract-corrections.md и .openapi.yaml (docs #183, вложение в AURORA-1540).

Открытые вопросы аналитику (комментарий [design-23-10-check] в AURORA-1395, п. 1–12 + 3 по ТЗ; в AURORA-1396 — ОФР) не блокируют работу: зависящие места сделаны так, чтобы ответ менял поведение точечно.

Цели

  • Вкладка «Таблица корректировки» страницы отчёта версии, по виду — как дизайн 23.10.
  • Таблица агрегатов с раскрытием до строк ОСВ, нераспределённые строки, итоги, фильтры, пресеты по правилам, единицы, настройка колонок, экспорт, полный экран.
  • Окно «Корректировка операции» агрегата: строки сторон, распределение по статьям, контроль, комментарий, сохранение.
  • Решения по строкам: флажок «Учитывать в КФО», отнести / перенести / убрать / вернуть к автоматике.
  • Отмена корректировки агрегата.
  • Только чтение, когда сервер так говорит (editable = false).

Не цели

  • Бэкенд и DBML (AURORA-1540), правила §8 в 05-domain-rules.md.
  • ОФР (нет в дизайне; AURORA-1396), импорт xlsx (ТЗ 6.8, ждёт ответа).
  • Корректировка строки ОСВ и нераспределённой строки (аналитика: только агрегат; ждёт п. 2).
  • Переход из шахматки с фокусом на паре (AURORA-1653), учёт корректировок в шахматке (AURORA-1643).

Анти-цели (провал, даже если «работает»)

  • Фронт сам считает разнесение строк, отклонения, порог 5 % или статусы агрегата — это делает сервер; фронт только показывает, форматирует и суммирует видимые строки для «Итого».
  • Деньги через number/float с потерей копеек. Суммы — строки контракта, сложение — точное десятичное.
  • Экран, в котором можно что-то нажать и молча потерять изменения окна корректировки.
  • Кнопки правки у версии, которую сервер считает нередактируемой.

Ограничения

  • web/ arm-core: React 18 + TS strict, antd 6, react-router 7, biome (140, одинарные кавычки), vitest.
  • Деньги в API — рубли строками с двумя знаками; показ в руб. / тыс. руб. и 0–2 знака — как в шахматке.
  • Состояние экрана — локальные хуки (стор Redux пуст по соглашению шаблона).
  • Пользователь слаб во фронте — решения в PR объясняются простыми словами.
  • Каждый экран сверяется с дизайном в Playwright и проходится руками до сдачи.

Как устроено

Данные

  • GET …/corrections?statement_type=balance — одна загрузка всей таблицы; фильтры, сортировка, «Итого» — на клиенте.
  • Правки: PUT …/aggregates/{rule}/{c1}/{c2} (сохранить), POST …/revoke, POST …/allocations (решение по строке, ответ — вся таблица), GET …/export.
  • Клиент — web/src/services/api/corrections.ts поверх api/client.ts. При REACT_APP_CORRECTIONS_MOCK=true те же функции отвечают из фейка контракта в памяти (данные — из дизайна 23.10, с проверками контракта: обязательный комментарий, expected_version_no, применимость правила). Флаг по умолчанию выключен; в production-сборке фейк не используется.

Таблица

Колонки как в дизайне: «Учитывать в КФО»; Дебет — ЮЛ, Строка баланса, Счёт, Сумма; Кредит — то же; Контроль — Отклонение %, Отклонение сумма; Корректировка — Строка баланса, Сумма (Дт), Строка баланса, Сумма (Кт), Комментарий; колонка действий.

  • Строка агрегата. Суммы сторон, счета (accounts), отклонение. Процент и сумма отклонения красные при exceeds_threshold. Корректировка — статьи и суммы correction.debit / credit (несколько статей стороны — по строке на статью в ячейке), комментарий. Действия: «Корректировать» (окно), меню «…» — «Отменить корректировку» (если есть). composition_changed — подсветка строки и значок с подсказкой «Состав изменился после корректировки». correction.status = DRAFT — пометка «черновик» у корректировки.
  • Раскрытие. Под агрегатом — его строки ОСВ (side_1.entries, затем side_2.entries): строка стороны 1 заполняет блок «Дебет», стороны 2 — «Кредит», остальные ячейки пустые (DOC-272613 п. 3.4; пары строк из дизайна не строим). У строки — флажок «Учитывать в КФО» и меню: «Перенести в правило…» (правила — candidate_rule_ids строки; фронт сам не сверяет счета с правилами), «Убрать из правила», «Вернуть к автоматике» (если decision = ASSIGN).
  • Флажок агрегата «Учитывать в КФО» — только показ: «Да» — все строки учитываются, «Частично» — часть исключена, «Нет» — все исключены. Сам признак ставится на строке (DOC-272613; ждёт п. 4).
  • Нераспределённые строки — после агрегатов, фон приглушён. Владелец — на своей стороне (дебетовая строка — в «Дебет», кредитовая — в «Кредит»), на другой стороне — только ЮЛ контрагента. Строка баланса не показывается (DOC-272613 п. 4.3). Флажок «Учитывать в КФО», меню «Отнести к правилу…» (список — candidate_rule_ids), «Вернуть к автоматике» для reason = UNASSIGNED. Кнопки «Корректировать» нет (ждёт п. 2).
  • «Итого» — суммы сторон, отклонения и корректировок по видимым агрегатам, точным сложением строк; процент «Итого» не показываем (смысл не задан).
  • Подписи «Отнести/Перенести в правило…» показывают правила как пресеты: «Правило N: <статья 1> — <статья 2>».

Панель

  • «Отображение»: «Общий» / «По пресету»; при «По пресету» — выбор правила (подпись с номером — снимает одинаковые подписи правил 5 и 8 из дизайна, п. 12); в таблице только агрегаты этого правила и те нераспределённые строки, у которых это правило есть в candidate_rule_ids (их можно отнести к нему).
  • «Тип записи»: «Все» / «Пары счетов» (агрегаты) / «Нераспределенные записи».
  • Фильтры «ЮЛ» и «Счёт» действуют и на нераспределённые строки; «Строка баланса» и «Отклонение» — только на агрегаты, при заданном одном из них нераспределённые строки скрываются (у них нет статьи и отклонения).
  • Составная статья правила ("1450/1550", "1310/1350", правила 1 и 2) показывается как «1450 / 1550»; в фильтре «Строка баланса» это два кода; в окне корректировки подставляется первый код, аналитик может выбрать второй.
  • Единицы и знаки — тот же компонент, что в шахматке.
  • Фильтры в заголовках: ЮЛ (подстрока, обе стороны), Строка баланса (список), Счёт (начало кода), Отклонение % («Все» / «≥ 5 %» / «< 5 %», по exceeds_threshold); «Сбросить фильтры» — когда что-то задано.
  • «Настройка таблицы» — GenericTable/ColumnSettings (видимость групп и колонок); «Экспорт» — файл сервера; «На весь экран» — как в шахматке.

Окно «Корректировка операции»

По дизайну: шапка сторон (компания, статья правила), блоки «Исходные данные ОСВ» и «Распределение корректировки» для каждой стороны, итоги, комментарий, «Отменить» / «Сохранить корректировки».

  • Исходные данные ОСВ — строки стороны агрегата. «×» у строки — «Убрать из правила» (UNASSIGN), «Добавить строку ОСВ» — выбор из нераспределённых строк, которые подходят под эту сторону: та же пара компаний (владелец и контрагент), сторона строки = сторона правила, правило агрегата есть в candidate_rule_ids (ответ 3(а)). Обе операции идут на сервер сразу (POST …/allocations), окно перечитывает агрегат.
  • Распределение — статьи стороны: строка баланса (код статьи) и сумма; «Добавить строку» — дочерняя статья. Без корректировки окно предлагает по стороне одну статью правила с суммой стороны (как в дизайне).
  • Контроль — суммы исходных строк сторон и суммы распределения сторон, разница и процент к меньшему (как в таблице; 79,77 % из дизайна — ошибка дизайна, п. 7). Расхождение не запрещает сохранение (ждёт п. 8).
  • Сохранить — PUT с status = APPLIED, expected_version_no из ответа; ошибки сервера показываются в окне по коду (COMMENT_REQUIRED — у поля комментария, INVALID_LINE_CODE — у статьи, CORRECTION_VERSION_CONFLICT — «Корректировку уже изменили, таблица обновлена», окно перечитывает данные).
  • Черновик окна в localStorage (решение владельца 28.10.2026 вместо блокировки переходов): статьи распределения и комментарий сохраняются при каждой правке; ключ — пользователь + версия + агрегат (rule_id, компании), в записи — время и version_no корректировки, от которой начаты правки. Переход «Назад», закрытие вкладки, переход по ссылке правки не теряют. При открытии окна этого агрегата черновик подставляется с плашкой «Восстановлены несохранённые правки от ЧЧ:ММ» и кнопкой «Сбросить»; если version_no на сервере уже другой — плашка «Корректировку изменили после ваших правок» (аналитик решает: оставить или сбросить). Черновик удаляется после успешного сохранения и после «Отменить» с подтверждением «Есть несохранённые изменения. Закрыть без сохранения?». Действия со строками в черновик не входят (они уже на сервере). Доступ к хранилищу — в try/catch: недоступно (приватный режим) — работаем без черновика.

Только чтение

editable = false — «Корректировать», флажки и меню решений неактивны; подсказка по read_only_reason: VERSION_NOT_EDITABLE — «Версия закрыта для изменений», LOCK_REQUIRED — «Возьмите консолидацию в работу», LOCKED_BY_OTHER — «Консолидацию редактирует другой пользователь». Окно корректировки открывается на просмотр.

Состояния

Загрузка — индикатор на месте таблицы; ошибка — уведомление с текстом сервера и «Повторить»; пусто — «Внутригрупповых остатков между компаниями периметра нет»; фильтры ничего не нашли — «Нет записей для выбранных фильтров» (текст дизайна).

Что оставлено исполнителю

Разбиение на компоненты и хуки, имена файлов внутри widgets/CorrectionTable/, способ раскрытия (antd expandable или собственные строки), вид меню действий, точная раскладка окна в пределах дизайна, состав данных фейка.

Decisions made without discussion

Дата Решение Почему Цена ошибки
28.10.2026 Контракт API пишем сами (docs #183), markdown + OpenAPI; корректировка в контракте — только на агрегат API ещё нет; аналитика приоритетна при ответе «можно на строку» (п. 2) — новый эндпоинт и кнопки на строках
28.10.2026 Раскрытие агрегата — строки ОСВ под своей стороной, не пары из дизайна DOC-272613 п. 3.4; пары нигде не хранятся ответ по п. 3 «пары нужны» — доработка раскрытия и контракта
28.10.2026 «Учитывать в КФО» ставится на строке; у агрегата — производное «Да / Частично / Нет» DOC-272613 (EXCLUDE на osv_entry) ответ по п. 4 «на агрегат» — поменять флажок агрегата на действие
28.10.2026 Действия со строками в окне корректировки идут на сервер сразу, статьи и комментарий — по «Сохранить» разнесение и корректировка — разные записи (vgo_assignment / correction); аналитик видит новые суммы до ввода корректировки отмена окна не откатывает перенос строк — аналитику нужно вернуть строку вручную
28.10.2026 Сохранение сразу применяет (APPLIED), черновик не показываем в дизайне одна кнопка ответ по п. 9 «нужен черновик» — вторая кнопка
28.10.2026 «Отменить корректировку» — в меню агрегата, с комментарием REVOKED в аналитике есть, в дизайне нет места ответ по п. 9 — перенести кнопку
28.10.2026 Процент в окне — к меньшему, как в таблице аналитика; в дизайне две формулы —
28.10.2026 Без корректировки окно предлагает суммы сторон целиком так в дизайне; в аналитике подсказка не описана ответ по п. 8 — поменять подсказку на min
28.10.2026 Фильтр «Отклонение» — по exceeds_threshold (≥ 5 % / < 5 %), а не диапазон чисел порог — главный вопрос аналитика; диапазон в дизайне не описан доработка фильтра
28.10.2026 «Итого» без процента смысл процента по итогам не задан добавить колонку
28.10.2026 Фейк контракта под флагом REACT_APP_CORRECTIONS_MOCK, данные из дизайна фронт не ждёт бэкенд; тот же код ходит в настоящий API фейк расходится с бэкендом — ловится при подключении API и ревью AURORA-1540
28.10.2026 Только statement_type = balance, переключателя ББ/ОФР нет в дизайне его нет; ОФР ждёт AURORA-1396 добавить переключатель
28.10.2026 Ключ черновика — пользователь + версия + агрегат; черновик без срока жизни, удаляется сохранением или «Отменить» на общем компьютере у разных пользователей разные черновики старые черновики копятся в localStorage — объём мал
28.10.2026 План — только web/, бэкенду помогаем на ревью 1540; последняя задача — подключение к API и снятие флага слова владельца «поможем ребятам на ревью» если 1540 не успеет к 02.11, экран сдаётся на фейке
28.10.2026 В контракт добавлен candidate_rule_ids у строки агрегата иначе фронту пришлось бы сверять счета с правилами — это разнесение, анти-цель правка контракта до начала 1540 — дёшево
28.10.2026 expected_version_no = null, когда действующей корректировки нет (и после отзыва) иначе после отзыва фронту неоткуда взять номер —
28.10.2026 Составная статья правил 1 и 2 — в окне первый код, можно выбрать второй line_code — один код; особый расчёт правил 1 и 2 (DOC-274230) — на сервере при ответе «нужно распределение по обеим» — аналитик добавляет вторую статью руками
28.10.2026 «По пресету» показывает и подходящие нераспределённые строки; «Строка баланса» и «Отклонение» скрывают нераспределённые пресет — рабочее место по правилу, строки для отнесения нужны рядом поменять функцию фильтров
28.10.2026 R-1: список правил в плане — ориентир; при расхождении с api/seed/core/elimination_rules_v1.yaml (в плане статья 1230/1510 встречается дважды) номера и статьи берутся из yaml, тесты плана про правила 1, 3, 6, 7 остаются верными seed — источник истины поправка mockData и тестов
28.10.2026 R-2: в фейк добавлен widgets/CorrectionTable/mockCalc.ts (пересчёт агрегата и итогов через BigInt-копейки) — общий для mockData и correctionsFake, иначе циклический импорт план не называл файл; без него циклический импорт перенос функций, без поведения
28.10.2026 R-3: в mockData сверх дизайна добавлены агрегат правила 6 «ООО "БСК"» — «ПМП ООО» (310000.00 / 300000.00) и агрегат правила 4 «Агро-Холдинг» без второй стороны (ONE_SIDED); status в фейке — ONE_SIDED / DISCREPANCY / AUTO, MANUAL не выдаётся тест фильтра ооо "бск" из плана требует агрегат с таким ЮЛ; ONE_SIDED нужен для проверки отображения поправка данных фейка, на прод не влияет
28.10.2026 R-4: в окне корректировки сумма с пробелами («1 000 000,5») отклоняется с ошибкой «Сумма без пробелов», хотя parseAmountInput пробелы принимает Review Focus плана прямо требует ошибку для этого ввода если заказчик хочет пробелы — снять одну проверку в validateLines
28.10.2026 R-5: percentOfSmaller, toCents, fromCents и порог 5 % (THRESHOLD_PERCENT_HUNDREDTHS) вынесены в utils/money.ts; editorModel и mockCalc импортируют оттуда, зависимости editorModel → mockCalc нет фейк mockCalc вырезается при подключении API, экран не должен от него зависеть (ревью Task 3, T3.1) поведение то же; тесты перенесены в utils/money.test.ts
28.10.2026 R-6: тексты ошибок валидации окна и ключ ошибки lines для «Добавьте статью» выбраны исполнителем бриф их не задаёт; тексты в spec не указаны правка строк
28.10.2026 R-7: флажки «Учитывать в КФО» и меню строк неактивны всегда (actionsEnabled=false) до Task 5–6, подсказка «только чтение» подключена бриф Task 4: решения по строкам — в Task 5 забыть включить флаг в Task 5
28.10.2026 R-8: ошибка загрузки показывается уведомлением с «Повторить» (по спеке) и кнопкой на месте таблицы после закрытия уведомления аналитик не остаётся без выхода две кнопки повтора
28.10.2026 R-9: «Итого» показывается только при наличии видимых агрегатов (при «Нераспределенные записи» его нет) сценарий спеки показать «Итого» с пустыми значениями