- toggleTreeCheck (utils/treeChecks): родитель отмечен, только если отмечены все потомки, на всех уровнях; скрытые поиском отметки берутся из состояния выпадашки — снятые подряд отметки больше не возвращаются; тесты. - Правило тегов из App.css → ConsolidationChessTableFilter.css (App.css пустой, как в main); класс с формы ЮЛ снят. - Спека: Known issues — остаток (одна сторона Дт/Кт) в техдолг AURORA-1799, решение (п), tasks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
98 lines
14 KiB
Markdown
98 lines
14 KiB
Markdown
## Context
|
||
|
||
Экран «Шахматка» [31-01] добавлен в `arm-core/web` PR #158 (ветка `feat/chessTable`, AURORA-1538) как вторая вкладка страницы
|
||
отчёта по версии. Страница `layouts/ConsolidatedOsvPage.tsx` разделена: общую шапку и вкладки держит
|
||
`layouts/ConsolidationReportPage.tsx`, содержимое вкладок — `widgets/ConsolidatedOsvContent` (прежняя сводная ОСВ без изменений
|
||
поведения) и `widgets/ConsolidatedChessContent` (матрица `ConsolidationChessTable` и результирующая таблица
|
||
`ConsolidationChessResTable`). Бэкенд — change `2026-10-16-intercompany-matrix` (матрица, результирующая таблица) и
|
||
`2026-10-22-intercompany-result-table-export` (выгрузка результирующей таблицы); расчёт — чистая функция версии, ничего не
|
||
хранится.
|
||
|
||
## Decisions
|
||
|
||
- **D-1. Маршрут `:tab`.** `OsvTabs` берёт активную вкладку из `useParams().tab` (по умолчанию `osv`) и по выбору заменяет
|
||
последний сегмент адреса. Неизвестный `tab` заменяется на `osv` (`navigate(…, {replace: true})`).
|
||
- **D-2. Ключ версии.** Страница отчёта разделена на обёртку с `key={version_id}` и содержимое: при смене версии карточка,
|
||
фильтры и данные создаются заново (как было в `ConsolidatedOsvPage`).
|
||
- **D-3. Режим расчёта из выбора счетов:** `manual` — при непустых Дт и Кт, `all` — при пустых обоих; при одной выбранной
|
||
стороне запроса нет (бэкенд ответил бы 422 на `manual`, а `all` показал бы не то, что выбрано). Тот же признак выбирает
|
||
маршрут экспорта.
|
||
- **D-4. Единицы, знаки и фильтр компаний — на клиенте.** Запрос повторяется только при смене выбора счетов или версии.
|
||
Единицы — сдвиг запятой в десятичной строке (`utils/chessTableCellFormatValue.ts`), `Intl.NumberFormat` получает строку и
|
||
форматирует её как точное десятичное (без float).
|
||
- **D-5. План счетов** — `GET /directories/accounts` целиком, деревья Дт и Кт строятся на клиенте по `parent_id`.
|
||
- **D-6. `apiFetchBlob(path, init)`** принимает `RequestInit`, чтобы выгружать POST-ом с телом; без `init` поведение прежнее.
|
||
- **D-7. Полноэкранный режим** — Fullscreen API на контейнере блока, состояние следует за `fullscreenchange`; выпадающие окна
|
||
antd рендерятся в `document.fullscreenElement` (`ConfigProvider getPopupContainer`).
|
||
- **D-8. Итоги — задача бэкенда.** Решение владельца 22.10.2026: агрегаты (строки «Итого») должен отдавать API. Перенос —
|
||
технический долг: AURORA-1756 (итоги и правило суммирования в API, ждёт аналитику AURORA-1373) и AURORA-1757 (вывод итогов из
|
||
API). До этого строки «Итого» остаются клиентскими (решение владельца: «особо не мешает»): точное сложение строк через
|
||
`sumAmounts`, под матрицей — `amount_a` по колонке, под результирующей таблицей — все статьи по колонке; колонка «Итого»
|
||
результирующей таблицы — `group_total` из ответа.
|
||
- **D-9. `useNotificationApi` мемоизирован** (`useMemo` по `notification` из `App.useApp()`, который antd сам мемоизирует):
|
||
объект уведомлений стабилен между рендерами, поэтому `loadData`/`loadResData` — `useCallback([notification])`, а эффекты
|
||
загрузки зависят от них без лишних перезапросов.
|
||
|
||
## Known issues
|
||
|
||
Открытая проблема на момент слияния (решение владельца 23.10.2026 — сливать, остаток в техдолг AURORA-1799):
|
||
|
||
1. Выбрана одна сторона Дт/Кт: «Экспорт» недоступен, но таблица показывает прежние данные, подсказка — всплывающее уведомление
|
||
и постоянный текст внутри выпадающего окна, текста у таблицы и у фильтров нет. Целевое поведение — решение (ж).
|
||
|
||
Пункты раунда 3 про поиск в дереве счетов и стили закрыты ревьюером (решение (п)).
|
||
|
||
## Decisions made without discussion
|
||
|
||
- **2026-10-21 (а). Спеку пишет ревьюер в ветке автора** — по решению владельца (разрешено явно); альтернатива — оставить
|
||
автору. Цена ошибки: автор может не согласиться с формулировками; правится одним коммитом в этом же change.
|
||
- **2026-10-21 (б). Спека описывает фактическое поведение, дефекты вынесены в «Known issues».** Отменено 22.10.2026 (е). Обоснование: спека — единственный
|
||
источник истины при рулингах, а закреплять баги требованиями нельзя; иначе их закрытие превратится в «нарушение спеки». Цена
|
||
ошибки: отдельные требования (например, режим `all` при выборе одной стороны, «Итого» из расхождений) описаны как есть
|
||
и после исправления потребуют MODIFIED.
|
||
- **2026-10-21 (в). При восстановлении затёртого фронта** (коммит 175343b) из `origin/main` взяты целиком все файлы без
|
||
шахматочных изменений, а в `App.tsx`, `layouts/index.ts`, `api/client.ts` (параметр `init`), `OsvTabs.tsx`,
|
||
`ConsolidatedOsvContent.tsx` оставлены изменения шахматки. Возвращён `key={version_id}` (разделением страницы на обёртку и
|
||
содержимое — поведение как в main). Обоснование: изменения PR в этих файлах относятся к шахматке; цена ошибки — незамеченная
|
||
откатившаяся правка main в этих пяти файлах (построчно сверено с `origin/main`, расхождений кроме шахматочных нет).
|
||
- **2026-10-21 (г). Механические правки biome без смены поведения** (коммит e19291c): тип `IntercompanyMatrixResponse` у `let res`,
|
||
`Number.isNaN`, `key` у `span` в `OsvTabs`, `?? null` вместо пустого фрагмента. Предупреждения eslint (8 новых в коде шахматки:
|
||
`any`, deps хуков, `console`) не исправлялись — они входят в Known issues. Цена ошибки: `key` на `span` внутри `Tooltip`
|
||
безвреден, но избыточен.
|
||
- **2026-10-21 (д). Дельта к `consolidated-osv-ui` не делается:** вкладки описаны в новой спеке, текст
|
||
`consolidated-osv-ui` не правился, чтобы не смешивать UI-половины. Цена ошибки: при архивации две спеки частично описывают
|
||
один компонент (`OsvTabs`).
|
||
- **2026-10-22 (е). Спека переписана на целевое поведение** (раунд 3 ревью): владелец решил, что спеки и тесты чужих PR ведём
|
||
мы, а автор правит продуктовый код; целевая спека даёт автору однозначный ориентир, расхождения кода — в «Known issues».
|
||
Цена ошибки: до исправлений спека и код ветки расходятся; PR не сливается, пока «Known issues» не закрыты.
|
||
- **2026-10-22 (ж). Выбрана одна сторона Дт/Кт — пустая таблица с текстом** «Для расчёта по счетам выберите счета и в Дт,
|
||
и в Кт» у таблицы и у фильтров, «Экспорт» матрицы недоступен. Альтернатива — оставить прежние данные с подсказкой; отвергнута:
|
||
на экране были бы данные, не соответствующие фильтру. Цена ошибки: правка текста и одного условия.
|
||
- **2026-10-22 (з). Правило отметок дерева по полному плану счетов** (родитель отмечен ⇔ отмечены все потомки), в том числе при
|
||
поиске. Обоснование: бэкенд разворачивает выбранный счёт в потомков, лишняя отметка родителя меняет расчёт. Цена ошибки: если
|
||
аналитик захочет «родитель + выбранные субсчета» как отдельный режим — MODIFIED требования.
|
||
- **2026-10-22 (и). Запасные имена файлов** `Шахматка_<ГК>_<год>_<квартал>.xlsx` и
|
||
`Результирующая_таблица_ВГО_<ГК>_<год>_<квартал>.xlsx`. Цена ошибки: низкая, имя из `Content-Disposition` приоритетнее.
|
||
- **2026-10-22 (к). Тесты форматтера** `utils/chessTableCellFormatValue.test.ts` написаны ревьюером: сдвиг единиц, точное
|
||
округление, большие суммы, «-0,00», пустые и нечисловые значения при любых единицах.
|
||
- **2026-10-22 (л). В ветку влит `main`** (PR #159), чтобы выгрузка результирующей таблицы работала на стенде из ветки.
|
||
- **2026-10-22 (м). Желательные пункты ревью закрыты ревьюером** (решение владельца): форматтер (проверка числа до сдвига
|
||
запятой, `Intl.StringNumericLiteral` через `ES2023.Intl` в `lib` tsconfig вместо `as any`, без мёртвого разбора скобок),
|
||
запасные имена (`utils/download.xlsxFilename`), отдельные флаги выгрузки, зависимости эффектов (D-9), «—» вместо выдуманного
|
||
нуля, ячейки по макету, «Год»/«Период» версии только для чтения, сервис `services/api/intercompanyMatrix.ts` с `withJsonBody`,
|
||
типы шахматки в `types/api.ts`, `Account.kind: 'A' | 'P' | 'AP' | null`. Цена ошибки: конфликты слияния у автора в
|
||
`ConsolidatedChessContent.tsx` и `ConsolidationChessTableFilter.tsx` — он правит те же файлы по «Known issues»; автору сказано
|
||
начать с `git pull`.
|
||
- **2026-10-22 (н). «-0,00» убирается проверкой готовой строки, а не опцией `signDisplay: 'negative'`.** Обоснование: на движке
|
||
без Intl.NumberFormat v3 неизвестное значение `signDisplay` бросает `RangeError` и ломает весь экран, а проверка строки
|
||
безопасна везде. Цена ошибки: нет.
|
||
- **2026-10-22 (о). Расхождение в скобках всегда**, в том числе нулевое — `(0,00)`: в API `variance_amount` — модуль разности
|
||
(неотрицательный), скобки в макете 31-01 — способ показа третьей строки, а не знак. Значок пропущенных строк ОСВ — оранжевый
|
||
`WarningOutlined` у первого числа. Подпись «Период» (не «Квартал») — как в макете. Цена ошибки: правка вида ячейки.
|
||
- **2026-10-23 (п). Остаток раунда 3 закрыт ревьюером, пункт про одну сторону Дт/Кт — в техдолг** (решение владельца: «доправим
|
||
сами, потом сольём»). Отметки дерева — чистая функция `utils/treeChecks.toggleTreeCheck` (правило (з) снизу вверх по полному
|
||
дереву на всех уровнях; скрытые поиском отметки берутся из состояния выпадашки, а не из применённого фильтра — иначе снятые
|
||
отметки возвращались), тесты `utils/treeChecks.test.ts`. Правило тегов из `App.css` перенесено в
|
||
`ConsolidationChessTableFilter.css`, класс с формы ЮЛ снят. Пустая таблица с подсказкой при одной стороне — AURORA-1799.
|
||
Цена ошибки: при одной стороне до AURORA-1799 на экране прежние данные, выгрузка недоступна.
|