(medium) page.tsx / KpiCard «Нежилые» и «Машино-места»: hint гейтит на perc, но печатает realised → возможна строка «null продано» #1408

Closed
opened 2026-06-15 05:53:38 +00:00 by bot-backend · 1 comment
Collaborator

Severity: medium · Категория: frontend · Файл: frontend/src/app/analytics/objects/[id]/page.tsx:165-182

page.tsx:165-182. Карточка «Нежилые» (168-172): hint показывается при nonliv?.perc != null, но в тело подставляется ${nonliv.realised}: ${nonliv.realised} продано (${nonliv.perc}%). Аналогично «Машино-места» (177-181) гейтит на parking?.perc != null, печатает ${parking.realised}. Эталонная карточка «Квартир» (141-146) для того же hint гейтит правильно — на apartments?.realised != null. По типу ObjectSalesAggRow (analytics.ts:179-181) total/realised/perc независимо nullable (number|null), поэтому возможна строка с perc != null и realised == null. В этом случае JSX-интерполяция ${null} даёт литерал 'null', и пользователь видит «null продано (37%)» — порча клиентского текста для финдиректора. Как чинить: гейтить hint на realised != null (как в карточке «Квартир»), а не на perc.

Почему баг: Поля total/realised/perc приходят независимо из DOM.РФ (domrf_kn.py:upsert_sales_agg кладёт d.get('total'/'realised'/'perc') без взаимной валидации; в БД все nullable — types/analytics.ts ObjectSalesAggRow.realised: number|null). Поэтому возможна строка с perc != null и realised == null. Тогда JSX-интерполяция ${null} даёт литеральную строку 'null': пользователь видит «null продано (37%)». Это порча клиентского текста (report-lies, нечитаемо для финдиректора).

Как чинить: Гейтить hint на realised != null (как у apartments) или использовать перц-only текст: ${nonliv.realised ?? '—'} продано (${nonliv.perc}%). То же для parking.


deep-audit «армия ботов 2» · verify+harden, confidence 0.82 · unit U74

**Severity:** medium · **Категория:** frontend · **Файл:** `frontend/src/app/analytics/objects/[id]/page.tsx:165-182` page.tsx:165-182. Карточка «Нежилые» (168-172): hint показывается при nonliv?.perc != null, но в тело подставляется ${nonliv.realised}: `${nonliv.realised} продано (${nonliv.perc}%)`. Аналогично «Машино-места» (177-181) гейтит на parking?.perc != null, печатает ${parking.realised}. Эталонная карточка «Квартир» (141-146) для того же hint гейтит правильно — на apartments?.realised != null. По типу ObjectSalesAggRow (analytics.ts:179-181) total/realised/perc независимо nullable (number|null), поэтому возможна строка с perc != null и realised == null. В этом случае JSX-интерполяция ${null} даёт литерал 'null', и пользователь видит «null продано (37%)» — порча клиентского текста для финдиректора. Как чинить: гейтить hint на realised != null (как в карточке «Квартир»), а не на perc. **Почему баг:** Поля total/realised/perc приходят независимо из DOM.РФ (domrf_kn.py:upsert_sales_agg кладёт d.get('total'/'realised'/'perc') без взаимной валидации; в БД все nullable — types/analytics.ts ObjectSalesAggRow.realised: number|null). Поэтому возможна строка с perc != null и realised == null. Тогда JSX-интерполяция ${null} даёт литеральную строку 'null': пользователь видит «null продано (37%)». Это порча клиентского текста (report-lies, нечитаемо для финдиректора). **Как чинить:** Гейтить hint на realised != null (как у apartments) или использовать перц-only текст: `${nonliv.realised ?? '—'} продано (${nonliv.perc}%)`. То же для parking. --- <sub>deep-audit «армия ботов 2» · verify+harden, confidence 0.82 · unit U74</sub>
bot-backend added the
week ревью 1
label 2026-06-15 05:53:38 +00:00
bot-backend added the
scope/frontend
label 2026-06-15 11:02:00 +00:00
Owner

🔍 week ревью 1 — верификация (ПОДТВЕРЖДЕНО)

Текущее состояние кода: frontend/src/app/analytics/objects/[id]/page.tsx:157-174 (карточки «Нежилые» и «Машино-места»); эталон — :133-138 (карточка «Квартир»).

Корень: Карточка «Квартир» гейтит hint правильно на apartments?.realised != null (:134), затем печатает ${apartments.realised} продано (${apartments.perc}%). А «Нежилые» (:161) и «Машино-места» (:170) гейтят на perc != null, но в тело подставляют ${nonliv.realised} / ${parking.realised}. По типу ObjectSalesAggRow (analytics.ts:179-181) total/realised/perc независимо nullable. При perc != null && realised == null JSX-интерполяция ${null} даёт литерал «null» → пользователь видит «null продано (37%)» — порча клиентского текста.

Что править:

  • Гейтить hint на realised != null (как у «Квартир»): nonliv?.realised != null ? ... : undefined и аналогично для parking.
  • Либо null-safe текст: ${nonliv.realised ?? '—'} продано (${nonliv.perc}%).

Что посмотреть:

  • Код: page.tsx:157-174; сверить с эталоном :133-138.
  • Vault: релевантных заметок не найдено.
**🔍 week ревью 1 — верификация (ПОДТВЕРЖДЕНО)** **Текущее состояние кода:** `frontend/src/app/analytics/objects/[id]/page.tsx:157-174` (карточки «Нежилые» и «Машино-места»); эталон — `:133-138` (карточка «Квартир»). **Корень:** Карточка «Квартир» гейтит hint правильно на `apartments?.realised != null` (:134), затем печатает `${apartments.realised} продано (${apartments.perc}%)`. А «Нежилые» (:161) и «Машино-места» (:170) гейтят на `perc != null`, но в тело подставляют `${nonliv.realised}` / `${parking.realised}`. По типу `ObjectSalesAggRow` (analytics.ts:179-181) `total/realised/perc` независимо nullable. При `perc != null && realised == null` JSX-интерполяция `${null}` даёт литерал «null» → пользователь видит «null продано (37%)» — порча клиентского текста. **Что править:** - Гейтить hint на `realised != null` (как у «Квартир»): `nonliv?.realised != null ? ... : undefined` и аналогично для `parking`. - Либо null-safe текст: `${nonliv.realised ?? '—'} продано (${nonliv.perc}%)`. **Что посмотреть:** - Код: `page.tsx:157-174`; сверить с эталоном `:133-138`. - Vault: релевантных заметок не найдено.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1408
No description provided.