From c1257b26710b2fcdd17b19ceee9be7310ab3e171 Mon Sep 17 00:00:00 2001 From: Light1YT Date: Sat, 13 Jun 2026 11:06:59 +0500 Subject: [PATCH] =?UTF-8?q?fix(competitors):=20=5FAVG=5FPRICE=5FSQL=20?= =?UTF-8?q?=E2=80=94=20=D1=84=D0=B8=D0=BB=D1=8C=D1=82=D1=80=20latest=20sna?= =?UTF-8?q?pshot=20(#1210)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit domrf_kn_flats версионируется (UNIQUE(id, snapshot_date), м.50), scraper UPSERT per snapshot — то же что для domrf_kn_objects (которое в L3 supply после #1212 берём только latest). _AVG_PRICE_SQL фильтра snapshot_date НЕ имел → AVG усреднял ИСТОРИЮ цен (stale на растущем рынке) → UI-поле Competitor.avg_price_per_m2 + вход _price_similarity получали устаревшую цену. COUNT '%прод%' множил sold ×N снапшотов → raw_sold/flat_count кратно завышен → попадал в гард-нейтраль 0.5 или искажал stage_at_horizon как ×N-завышенный sold_pct. Patch: WHERE f.snapshot_date = (SELECT MAX(snapshot_date) FROM domrf_kn_flats). Зеркало паттерна best_layouts._SUPPLY_BATCH_SQL и _COMPETITORS_SQL DISTINCT ON (уже было latest). 51/51 competitors-тестов зелёные. Closes #1210 --- backend/app/services/site_finder/competitors.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/backend/app/services/site_finder/competitors.py b/backend/app/services/site_finder/competitors.py index e9413a1b..3173d75d 100644 --- a/backend/app/services/site_finder/competitors.py +++ b/backend/app/services/site_finder/competitors.py @@ -437,6 +437,12 @@ _COMPETITORS_SQL = text(""" # заполнен слабо (~0.2%), поэтому flats_sold чаще будет 0/мало → stage_at_horizon # падает в нейтраль 0.5 (graceful, см. helper). Колонка добавлена в ТОТ ЖЕ запрос # (без 4-го db.execute), чтобы не ломать существующие callers/тесты. +# #1210: domrf_kn_flats версионируется (UNIQUE(id, snapshot_date) — м.50, +# scraper UPSERT per snapshot). Без фильтра snapshot_date AVG усреднял +# ИСТОРИЮ цен (stale на растущем рынке), а COUNT '%прод%' множил sold ×N +# снапшотов (raw_sold/flat_count кратно завышен → попадал в гард-нейтраль +# 0.5 или искажал stage_at_horizon). Берём ТОЛЬКО latest snapshot — зеркало +# паттерна best_layouts._SUPPLY_BATCH_SQL и _COMPETITORS_SQL DISTINCT ON. _AVG_PRICE_SQL = text(""" SELECT f.obj_id, @@ -448,6 +454,9 @@ _AVG_PRICE_SQL = text(""" ) AS flats_sold FROM domrf_kn_flats f WHERE f.obj_id = ANY(:obj_ids) + AND f.snapshot_date = ( + SELECT MAX(snapshot_date) FROM domrf_kn_flats + ) GROUP BY f.obj_id """)