fix(site-finder): competitors avg-price по per-object снапшоту, не глобальному (#2445-A5) #2447

Merged
bot-backend merged 1 commit from fix/competitors-per-object-snapshot into main 2026-07-05 18:54:37 +00:00
Collaborator

Summary

Аудит-находка A5 (epic #2445). _AVG_PRICE_SQL фильтровал domrf_kn_flats по одной глобальной MAX(snapshot_date), но таблица — per-object time series (UNIQUE(obj_id, snapshot_date)). На глобальной дате обычно лишь 1 объект → у остальных конкурентов 0 строк → avg_price_per_m2=NULL_price_similarity падает на нейтральные 0.5, молча деградируя relevance-ранжирование.

Тот же баг чинили в best_layouts.py (#1956), но фикс не портировали сюда.

Fix

Портирован flats_latest DISTINCT ON (obj_id) ... ORDER BY snapshot_date DESC, id DESC CTE из best_layouts.py — каждый конкурент берёт свой последний снапшот. Индекс 174_domrf_kn_flats_obj_snapshot_idx уже обслуживает CTE (новая миграция не нужна). Objective-fallback композиция не тронута.

Test plan

  • 564 теста site_finder/competitors зелёные (+ новый SQL-invariant файл + multi-object API-тест)
  • ruff чисто, psycopg CAST конвенция соблюдена
  • code-reviewer: APPROVE (0 блокеров)

Post-deploy verify

Проверить, что миграция 174 применена на проде (deploy success ≠ применилось), и что конкуренты в multi-object радиусе теперь дают per-object domrf-цены (price_source="domrf", меньше уходит в "objective").

Refs #2445

## Summary Аудит-находка A5 (epic #2445). `_AVG_PRICE_SQL` фильтровал `domrf_kn_flats` по одной глобальной `MAX(snapshot_date)`, но таблица — per-object time series (`UNIQUE(obj_id, snapshot_date)`). На глобальной дате обычно лишь 1 объект → у остальных конкурентов 0 строк → `avg_price_per_m2=NULL` → `_price_similarity` падает на нейтральные 0.5, молча деградируя relevance-ранжирование. Тот же баг чинили в `best_layouts.py` (#1956), но фикс не портировали сюда. ## Fix Портирован `flats_latest DISTINCT ON (obj_id) ... ORDER BY snapshot_date DESC, id DESC` CTE из `best_layouts.py` — каждый конкурент берёт свой последний снапшот. Индекс `174_domrf_kn_flats_obj_snapshot_idx` уже обслуживает CTE (новая миграция не нужна). Objective-fallback композиция не тронута. ## Test plan - [x] 564 теста site_finder/competitors зелёные (+ новый SQL-invariant файл + multi-object API-тест) - [x] ruff чисто, psycopg `CAST` конвенция соблюдена - [x] code-reviewer: ✅ APPROVE (0 блокеров) ## Post-deploy verify Проверить, что миграция 174 применена на проде (deploy success ≠ применилось), и что конкуренты в multi-object радиусе теперь дают per-object domrf-цены (`price_source="domrf"`, меньше уходит в "objective"). Refs #2445
bot-backend added 1 commit 2026-07-05 18:31:42 +00:00
fix(site-finder): per-object latest snapshot в competitors avg-price SQL (#2445-A5)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 11s
CI / changes (pull_request) Successful in 11s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m53s
CI / backend-tests (pull_request) Successful in 14m49s
6471900592
_AVG_PRICE_SQL фильтровал domrf_kn_flats по одной глобальной MAX(snapshot_date),
но таблица — per-object time series (UNIQUE(obj_id, snapshot_date)). На глобальной
дате обычно присутствует лишь 1 объект → у всех остальных конкурентов 0 строк →
avg_price_per_m2=NULL → _price_similarity падает на нейтральные 0.5, молча
деградируя relevance-ранжирование.

Портируем flats_latest DISTINCT ON (obj_id) ... ORDER BY snapshot_date DESC, id DESC
CTE из best_layouts.py (#1956) — каждый конкурент берёт СВОЙ последний снапшот.
Индекс 174_domrf_kn_flats_obj_snapshot_idx уже обслуживает CTE (новая миграция
не нужна). Objective-fallback композиция не тронута: missing_price_ids считается
после domrf-запроса → естественно сжимается.

Refs #2445
bot-backend merged commit c8c96a87ee into main 2026-07-05 18:54:37 +00:00
bot-backend deleted branch fix/competitors-per-object-snapshot 2026-07-05 18:54:37 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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#2447
No description provided.