fix(ptica): нет сделок за окно — цена не 0 ₽/м², а «нет данных» (#2464-B) #2868
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2868
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2464-layouts-zero-price"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Что
deals_per_bucketв_INLINE_VELOCITY_SQLоборачивал деление вCOALESCE(..., 0):Сделок за окно нет → делитель NULL → подставляется 0. Пользователю это читается как
«средняя цена продаж в этой комнатности — 0 ₽/м²».
Обещание в контракте без реализации
Схема уже объявляла честный ответ:
и Python-потребитель уже умеет None — пропускает такую строку во взвешенном роллапе
(
if row["avg_price_per_m2_rub"] is not None). То есть честная ветка была написана,а
COALESCEделал её недостижимой. Правка не добавляет поведение, а включаетуже заявленное.
Замер (прод, 13.08, окно 6 месяцев)
Сначала посчитал не то: агрегат по всему городу даёт 5 комнатностей, все непустые,
и разницы нет вообще. Но
deals_per_bucketгруппирует поroom_bucketпосле джойнас проектами в радиусе — значит попадёт ноль или нет, зависит от того, сколько замапленных
проектов рядом с участком. Правильные цифры — по слоям:
Чем беднее окрестность участка, тем чаще выдумывался ноль. Для участка, у которого
в радиусе один проект из тех 80, обнулялись все комнатности.
Отдельно проверил гипотезу из аудита («все слагаемые площади/цены NULL»): строк с
deals_total_count > 0и NULL-ценой — 0. Механизм другой — пустое окно продаж.Что НЕ трогаю
avg_area_m2остаётся сCOALESCE(...,0):TopLayoutRow.avg_area_m2: float— не Optional,честный NULL требует правки схемы, перегенерации типов фронта и решения, что писать
в
area_bin(сейчас при нулевой площади молча подставляется"<25", то есть выдумываетсяещё и типоразмер). Вынес в #2867 с теми же замерами, чтобы не тащить контрактную
правку прицепом к однострочнику.
Проверка
(172470 / 153540 / 146960 / 159240 / 180750 — до и после совпадают), меняются только
пустые:
0→NULLpytest -k layout— 128 passed, 7 skippedruff check— cleanЧестно про тесты: DB-прогона по данным в наборе нет (интеграционный харнесс ПТИЦЫ —
только EXPLAIN), поэтому численная проверка — прод-A/B выше, а не юнит-тест.
Refs #2464
openapi-codegen-checkпокраснел на первом прогоне — не из-за этой правки.Проверил прямо: дампнул
app.openapi()с этой ветки и с main-эквивалента —байт-в-байт одинаково (348 531 байт обоих). SQL-правка схему API не трогает, так что
«типы фронта устарели» тут физически невозможно.
Настоящая причина — диск VPS был заполнен на 94%, job упал на установке зависимостей.
Тем же дефицитом объясняются красный
backend-testsна #2865 и обе сборки деплоя main.Вычистил кэш старых buildx-билдеров: свободно 13G → 28G. Разбор — #2869.
Прогон перезапущен на разгруженном хосте.