AURORA-1894: красная рамка у ошибки ячейки, тост без Server error:undefined #277

Open
aep wants to merge 1 commits from feat/275-aurora-1894-error-border-toast into test
Owner

Closes #275.

Проблема

Ошибки найдены при разборе замечания заказчика «7. Контроль ошибок»:

  • А (рамка): у вводимой ячейки с ошибкой валидации (например, transfer-less-total:
    data.q1.transfer_econ > data.q1.total) рамка оставалась светло-серой
    (EDITABLE_STYLES), потому что в Cell.jsx порядок спреда стилей был
    INVALID_STYLES, затем EDITABLE_STYLES — редактируемый вариант перетирал
    красную рамку ошибки. У нередактируемых (расчётных) ячеек рамка оставалась
    красной, потому что NOT_EDITABLE_STYLES рамку не задаёт.
  • Б (тост): RealtimeContext.js строил текст тоста как
    `Server error:${data.error.message}` || ''. Backend шлёт error то
    строкой (например «Ячейка уже редактируется другим пользователем»), то
    объектом {code, field, message} (ошибки SQL, например
    computed_field: q1.corrected_plan). Для строки data.error.message —
    undefined, и || '' никогда не срабатывает (левая часть — непустая
    строка), так что тост показывал «Server error:undefined». А при ошибках БД
    пользователь видел технический префикс (computed_field: ...) вместо
    понятного текста.

Что сделано

  1. web/src/components/RealtimeTable/Cell/Cell/Cell.jsx — порядок спреда стилей
    в cellStyles изменён на base → editable/not-editable → locked → invalid
    (INVALID_STYLES теперь всегда последний), остальной файл не трогал.
  2. Новый модуль web/src/components/RealtimeTable/utils/wsErrorUtils.js с
    чистой функцией getWsErrorMessage(error):
    • строка → возвращается как есть (после проверки на известный префикс);
    • объект → message || detail;
    • известные технические префиксы заменяются человеческим текстом:
      computed_field: → «Это расчётная ячейка, её нельзя изменить»,
      role_not_allowed: → «Нет прав на изменение этой колонки»,
      window_closed: → «Окно ввода для этой колонки закрыто»,
      org_not_assigned → «Вы не назначены на эту форму»;
    • прочий текст — без префикса Server error:;
    • никогда не возвращает undefined/null (дефолт — «Неизвестная ошибка
      сервера»).
  3. web/src/components/RealtimeTable/contexts/RealtimeContext.js —
    toast.error(getWsErrorMessage(data.error)) вместо шаблонной строки с
    || ''; console.log(data.error) вместо console.log(data.error.message)
    (чтобы и в консоли не терять данные для строковых ошибок).

Тесты

cd web && node --test src/components/RealtimeTable/utils/wsErrorUtils.test.js:
10 passed, 0 failed — строка, объект с message, объект без message
(берёт detail), объект без обоих полей (дефолтный текст, не undefined),
каждый из 4 известных префиксов (в т.ч. в составе message объекта),
неизвестный текст без Server error:, пустая/отсутствующая ошибка.

Запускал также весь набор node --test src/components/RealtimeTable/utils/*.test.js:
34 passed, 1 failed — падение в columnLayoutUtils.test.js
(Cannot find package '@tanstack/table-core') не связано с этой правкой:
в web/node_modules нет @tanstack/table-core вообще (не установлен в этом
воркзпейсе); подтвердил, что падение воспроизводится и на коммите до моих
правок (временно стэшировал diff и прогнал тест ещё раз). Лёгкий фикс/логика
Cell.jsx и RealtimeContext.js не задействует этот пакет.

npx biome check на изменённых и новом файлах — чисто.

Сценарий А и Б проверены по коду (живой стенд не поднимал, backend не трогал):

  • А: с новым порядком спреда INVALID_STYLES (красная рамка 2px) теперь
    накладывается после EDITABLE_STYLES/NOT_EDITABLE_STYLES и LOCKED_STYLES,
    так что у ячейки с ошибкой рамка красная независимо от isEditable.
  • Б: data.error как строка («Ячейка уже редактируется другим пользователем»,
    websocket.py:1051/1095) теперь попадает в тост как есть; data.error как
    объект с message вида computed_field: q1.corrected_plan
    (websocket.py:1217-1220, map_sqlalchemy_error) теперь даёт понятный текст
    «Это расчётная ячейка, её нельзя изменить» вместо «Server error:undefined».

Rulings

R-1: console.log(data.error.message) заменён на console.log(data.error) —
не было явно в тикете, но то же || undefined-поведение било и по консоли
для ошибок-строк; счёл логичным исправить в рамках той же правки, т.к. это
однострочное изменение в том же месте кода.
R-2: для org_not_assigned сопоставление по префиксу через startsWith, как
и для остальных (хотя в спеке префикс без :) — покрывает и голый
org_not_assigned, и варианты вида org_not_assigned: form_id=123, если
backend когда-нибудь добавит подробности.

⚠️ Известное пересечение: соседняя ветка feat/276-aurora-1892-negative-amounts
(#276) также правит Cell.jsx (выносит formatNumber в numberFormat.js,
меняет раскраску отрицательных чисел). Эта правка — только реордер спреда
стилей в cellStyles, остальной файл не тронут, чтобы минимизировать
поверхность конфликта. Обе ветки от одного origin/test tip (9229ee5),
слияние — на человеке.

🤖 Generated with Claude Code

Closes #275. ## Проблема Ошибки найдены при разборе замечания заказчика «7. Контроль ошибок»: - **А (рамка)**: у вводимой ячейки с ошибкой валидации (например, transfer-less-total: `data.q1.transfer_econ` > `data.q1.total`) рамка оставалась светло-серой (EDITABLE_STYLES), потому что в `Cell.jsx` порядок спреда стилей был `INVALID_STYLES`, затем `EDITABLE_STYLES` — редактируемый вариант перетирал красную рамку ошибки. У нередактируемых (расчётных) ячеек рамка оставалась красной, потому что `NOT_EDITABLE_STYLES` рамку не задаёт. - **Б (тост)**: `RealtimeContext.js` строил текст тоста как `` `Server error:${data.error.message}` || '' ``. Backend шлёт `error` то строкой (например «Ячейка уже редактируется другим пользователем»), то объектом `{code, field, message}` (ошибки SQL, например `computed_field: q1.corrected_plan`). Для строки `data.error.message` — `undefined`, и `|| ''` никогда не срабатывает (левая часть — непустая строка), так что тост показывал «Server error:undefined». А при ошибках БД пользователь видел технический префикс (`computed_field: ...`) вместо понятного текста. ## Что сделано 1. `web/src/components/RealtimeTable/Cell/Cell/Cell.jsx` — порядок спреда стилей в `cellStyles` изменён на base → editable/not-editable → locked → invalid (`INVALID_STYLES` теперь всегда последний), остальной файл не трогал. 2. Новый модуль `web/src/components/RealtimeTable/utils/wsErrorUtils.js` с чистой функцией `getWsErrorMessage(error)`: - строка → возвращается как есть (после проверки на известный префикс); - объект → `message || detail`; - известные технические префиксы заменяются человеческим текстом: `computed_field:` → «Это расчётная ячейка, её нельзя изменить», `role_not_allowed:` → «Нет прав на изменение этой колонки», `window_closed:` → «Окно ввода для этой колонки закрыто», `org_not_assigned` → «Вы не назначены на эту форму»; - прочий текст — без префикса `Server error:`; - никогда не возвращает `undefined`/`null` (дефолт — «Неизвестная ошибка сервера»). 3. `web/src/components/RealtimeTable/contexts/RealtimeContext.js` — `toast.error(getWsErrorMessage(data.error))` вместо шаблонной строки с `|| ''`; `console.log(data.error)` вместо `console.log(data.error.message)` (чтобы и в консоли не терять данные для строковых ошибок). ## Тесты `cd web && node --test src/components/RealtimeTable/utils/wsErrorUtils.test.js`: **10 passed, 0 failed** — строка, объект с `message`, объект без `message` (берёт `detail`), объект без обоих полей (дефолтный текст, не `undefined`), каждый из 4 известных префиксов (в т.ч. в составе `message` объекта), неизвестный текст без `Server error:`, пустая/отсутствующая ошибка. Запускал также весь набор `node --test src/components/RealtimeTable/utils/*.test.js`: 34 passed, 1 failed — падение в `columnLayoutUtils.test.js` (`Cannot find package '@tanstack/table-core'`) не связано с этой правкой: в `web/node_modules` нет `@tanstack/table-core` вообще (не установлен в этом воркзпейсе); подтвердил, что падение воспроизводится и на коммите до моих правок (временно стэшировал diff и прогнал тест ещё раз). Лёгкий фикс/логика Cell.jsx и RealtimeContext.js не задействует этот пакет. `npx biome check` на изменённых и новом файлах — чисто. Сценарий А и Б проверены по коду (живой стенд не поднимал, backend не трогал): - А: с новым порядком спреда `INVALID_STYLES` (красная рамка 2px) теперь накладывается после `EDITABLE_STYLES`/`NOT_EDITABLE_STYLES` и `LOCKED_STYLES`, так что у ячейки с ошибкой рамка красная независимо от `isEditable`. - Б: `data.error` как строка («Ячейка уже редактируется другим пользователем», websocket.py:1051/1095) теперь попадает в тост как есть; `data.error` как объект с `message` вида `computed_field: q1.corrected_plan` (websocket.py:1217-1220, map_sqlalchemy_error) теперь даёт понятный текст «Это расчётная ячейка, её нельзя изменить» вместо «Server error:undefined». ## Rulings R-1: `console.log(data.error.message)` заменён на `console.log(data.error)` — не было явно в тикете, но то же `|| undefined`-поведение било и по консоли для ошибок-строк; счёл логичным исправить в рамках той же правки, т.к. это однострочное изменение в том же месте кода. R-2: для `org_not_assigned` сопоставление по префиксу через `startsWith`, как и для остальных (хотя в спеке префикс без `:`) — покрывает и голый `org_not_assigned`, и варианты вида `org_not_assigned: form_id=123`, если backend когда-нибудь добавит подробности. ⚠️ Известное пересечение: соседняя ветка `feat/276-aurora-1892-negative-amounts` (#276) также правит `Cell.jsx` (выносит `formatNumber` в `numberFormat.js`, меняет раскраску отрицательных чисел). Эта правка — только реордер спреда стилей в `cellStyles`, остальной файл не тронут, чтобы минимизировать поверхность конфликта. Обе ветки от одного `origin/test` tip (`9229ee5`), слияние — на человеке. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 1 commit 2026-11-01 11:11:08 +03:00
Cell.jsx: порядок спреда стилей — base → editable/not-editable → locked →
invalid (INVALID_STYLES последним), чтобы красная рамка 2px не перетиралась
EDITABLE_STYLES у вводимых ячеек с ошибкой.

utils/wsErrorUtils.js: getWsErrorMessage(error) — строка возвращается как
есть, объект берёт message || detail, известные технические префиксы
(computed_field:, role_not_allowed:, window_closed:, org_not_assigned)
заменяются понятным текстом, прочее отдаётся без "Server error:".

RealtimeContext.js: toast.error(getWsErrorMessage(data.error)) вместо
`Server error:${data.error.message}` || '', которое всегда давало undefined
для ошибок-строк (|| не срабатывает на непустой строке).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/275-aurora-1894-error-border-toast:feat/275-aurora-1894-error-border-toast
git checkout feat/275-aurora-1894-error-border-toast
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: RSHB/DFiP_Budget_planing#277
No description provided.