38 KiB
Дизайн: экран «Таблица корректировки» (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, вкладка открывается на стенде на
реальной версии и проходит сценарии спеки; расхождения ответа с контрактом правятся в той ветке, где ошибка (фейк или
бэкенд). Сверяем фейк с реальным ответом мы (владелец / этот агент) при подключении.
Источники и их вес
- Аналитика Лысенко — DOC-272613, ответы 1–7 (AURORA-1395, 27.10), DOC-274230. Приоритетна над нашими правилами и черновиками (решение владельца 28.10).
- Дизайн от 23.10.2026 —
ДКБ_таблица_корректировок_23_10_26_1.html(вложение к DOC-272613; в корне workspace). Как лежат строки в дизайне — визуализация; логика — по аналитике. - ТЗ 6.8 / Прил. 9 — ниже аналитики, иногда игнорируется.
- Контракт 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, применимость правила). Флаг по умолчанию выключен; фейк включается только переменной окружения, но код фейка остаётся в бандле (R-21, R-26).
Таблица
Колонки как в дизайне: «Учитывать в КФО»; Дебет — ЮЛ, Строка баланса, Счёт, Сумма; Кредит — то же; Контроль — Отклонение %, Отклонение сумма; Корректировка — Строка баланса, Сумма (Дт), Строка баланса, Сумма (Кт), Комментарий; колонка действий.
- Строка агрегата. Суммы сторон, счета (
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: «Итого» показывается только при наличии видимых агрегатов (при «Нераспределенные записи» его нет) | сценарий спеки | показать «Итого» с пустыми значениями |
| 28.10.2026 | R-10: ROW_ACTIONS_READY/actionsEnabled удалены; контролы строк неактивны при !editable (с подсказкой readOnlyHint) и на время запроса (busy, без подсказки) |
включение R-7 в Task 5; блокировка на время запроса не даёт отправить два решения подряд | аналитик не видит, почему контрол замер, пока идёт запрос (виден спиннер таблицы) |
| 28.10.2026 | R-11: любая ошибка 409 при решении/отмене — уведомление с текстом сервера и reload() (needsReload) |
409 = версия закрылась, блокировку забрали, корректировку уже изменили/отозвали: локальная таблица устарела | лишний запрос при 409 без смысла для таблицы; комментарий окна отмены теряется при 409 и перезагрузке — допустимо, корректировка уже изменена; перечитывание и при 404 (needsReload) |
| 28.10.2026 | R-12: после allocate таблица заменяется ответом целиком (replace), после revoke подменяется один агрегат (replaceAggregate); окно отмены при не-409 ошибке остаётся открытым, при 409 закрывается |
allocate меняет и нераспределённые, revoke отдаёт агрегат; при сетевой ошибке комментарий не должен пропасть |
после revoke нераспределённые не обновляются (по контракту revoke их не трогает) |
| 28.10.2026 | R-13: меню строки вынесено в чистую allocationMenu (ключ MOVE — «выбрать правило», уходит как ASSIGN); правило-кандидат, которого нет в rules, пункт «в правило» не включает |
тестируемость без React; фронт не выдумывает правил | при рассинхроне справочника правил пункт неактивен |
| 28.10.2026 | R-14: окно получило пропс onReload сверх сигнатуры плана и рендерится только пока открыто (key = ключ агрегата) | при CORRECTION_VERSION_CONFLICT/409/404 окну нужно перечитать таблицу; черновик читается один раз при открытии | окно без onReload не обновит таблицу при конфликте |
| 28.10.2026 | R-15: черновик пишется только при editable и если состояние отличается от исходного (суммы — копейками); вернули к исходному — черновик удаляется; при конфликте редакций правки остаются в окне, черновик сохраняется с прежним baseVersionNo, плашка «Корректировку изменили после ваших правок» | в режиме чтения черновик бессмыслен; совпавший с исходным — мусор в localStorage | при ручном возврате к исходному плашка восстановления пропадает |
| 28.10.2026 | R-16: ключ строки статьи в окне — устойчивый числовой id из счётчика компонента (в EditorState ids нет); наружу (черновик, PUT) уходит EditorState без id | ключ-индекс при удалении строки переносил бы введённый текст на соседнюю | id не попадают в черновик, после перезагрузки выдаются заново |
| 28.10.2026 | R-17: после UNASSIGN/ASSIGN в окне суммы статей без своих правок (не dirty) пересобираются из нового агрегата (initialEditorState), при правках — остаются как есть | у агрегата без корректировки статья предлагается с суммой стороны, она изменилась; затирать ввод аналитика нельзя | при правках статьи не подстраиваются под новые суммы сторон — их видно по строке контроля |
| 28.10.2026 | R-18: суммы в окне показываются в рублях (1 000 000,00) независимо от единиц панели, а в полях ввода — как есть (1000000.00, пробелы запрещены R-4); у строки контроля без процента (percent = null, одна сторона 0) процент не пишется, у равенства — «= 0,00» | единицы панели — про таблицу; дизайн показывает «(100%)» там, где процент к меньшей стороне не определён, фронт его не выдумывает | расхождение с дизайном в тексте контроля |
| 28.10.2026 | R-19: агрегат исчез из ответа — окно открыто, стороны «—», «Сохранить» неактивна, пояснение в плашке; ключ PUT берётся из ответа, поэтому без агрегата сохранить нельзя | Review Focus плана | — |
| 28.10.2026 | R-20: в окне нет названий статей рядом с кодом («дт 1230 Дебиторская задолженность» в дизайне) | в ответе API названий статей нет, а фронт их не выдумывает | добавить поле article_name в контракт и показать |
| 28.10.2026 | R-21: код фейка (correctionsFake, mockData, mockCalc, ~20 КБ исходников) остаётся в прод-бандле при сборке без флага; сам не вырезал | Config.CORRECTIONS_MOCK — обычное чтение process.env.REACT_APP_CORRECTIONS_MOCK, импорты статические: npm run build без флага даёт строку «Требуется сверка» в index_script; вырезание требует динамического импорта фейка или define-константы в rsbuild — не мелкая правка; Task 8 фейк всё равно удаляет | лишние ~8 КБ gzip в бандле до Task 8; вопрос владельцу: делать ли вырезание сейчас |
| 28.10.2026 | R-22: Prettier и ESLint применены к файлам задачи (npm run lint падал на форматировании 17 файлов, на вложенных тернарниках окна и BOM-литерале в фейке); BOM — \uFEFF, поведение то же | npm run lint — шаг проверки Task 7 | — |
| 28.10.2026 | R-23: «Вернуть к автоматике» на нераспределённой строке в фейке только снимает «исключена» и не возвращает строку в правило | фейк не знает, какое правило было автоматическим; настоящее поведение — на бэкенде (1540) | аналитик на демо на фейке не увидит возврата; проверить при подключении API |
| 28.10.2026 | R-24: у агрегата флажок «Учитывать в КФО» — серый неактивный индикатор «Да / Частично / Нет», а в дизайне зелёный | решение 28.10 (флажок ставится на строках, у агрегата производное) | ответ по п. 4 «на агрегат» |
| 28.10.2026 | R-25: отдельное ревью Task 7 (стиль, два мелких фикса, документация) не делалось, оно покрыто финальным ревью ветки | дифф механический, финальное ревью читает всю ветку | мелкая ошибка в Task 7 всплывёт на финальном ревью |
| 28.10.2026 | R-26: фейк (R-21) остаётся в бандле до Task 8, который его удаляет | вырезание требует динамического импорта или define в rsbuild, и всё равно временное | ~20 КБ в бандле до подключения API |
| 28.10.2026 | R-27: mockData и mockCalc остаются как тестовые фикстуры (их импортируют тесты tableModel, editorModel, readOnly, draftStorage); Task 8 удаляет только correctionsFake.ts (+ его тест) и ветку флага в corrections.ts. Уточняет R-5, R-21, R-26: «вырезается» относится только к фейку контракта correctionsFake | иначе при подключении API пришлось бы переписывать тесты моделей | если фикстуры устареют относительно контракта — тесты моделей перестанут ловить расхождения; сверять при Task 8 |
| 28.10.2026 | R-28: окно выбора нераспределённой строки (picker) не показывает исключённые (excluded) — исключённую сначала возвращают в учёт флажком в таблице | исключённая строка сознательно убрана из КФО; разнесение её в правило молча вернуло бы её в расчёт | аналитику нужен лишний шаг; если захотят выбирать исключённые — снять условие !u.excluded в pickerCandidates |