From de2d67c7f900e87da135f02b4bec9abc0a41eba6 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Sat, 12 Sep 2026 13:55:40 +0500 Subject: [PATCH] =?UTF-8?q?docs(mera/sales-vs-listings):=20=D1=8F=D0=BA?= =?UTF-8?q?=D0=BE=D1=80=D1=8C=20=D0=B8=20=D0=B4=D0=BE=D0=BA=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BF=D0=BE=20=D0=B7=D0=B0=D0=BC?= =?UTF-8?q?=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC=20=D1=80=D0=B5=D0=B2?= =?UTF-8?q?=D1=8C=D1=8E=20PR=20#3461?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ревью справедливо поймало два места, где текст после снятия предиката стал неточным: 1. Якорь в deploy/import-rosreestr.sh обещал «потребителей, фильтрующих по d.rooms, больше нет» — это верно только про предикаты РАВЕНСТВА. app/tasks/asking_to_sold_ratio.py:148,152 по-прежнему КЛЮЧУЕТСЯ этим бакетом (GROUP BY LEAST(GREATEST(rooms,0),4)) и намеренно зеркалит ту же синтетику на листинговой стороне (#2620). Прежняя формулировка сказала бы будущему редактору, что проверять некого, — а в сценарии «поменяли CASE на реальную комнатность» вернулся бы именно #2620. 2. Докстринг GET /sales-vs-listings обещал listing «с такими же rooms». После снятия предиката это верно для пары запрос↔объявление, но не для пары сделка↔объявление: deal_rooms может не совпадать с запрошенным rooms. Кода правка не касается. Полный сьют: 5946 passed, 35 skipped; ruff чист. Co-Authored-By: Claude Opus 5 --- tradein-mvp/backend/app/api/v1/trade_in.py | 8 ++++++-- tradein-mvp/deploy/import-rosreestr.sh | 7 ++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/tradein-mvp/backend/app/api/v1/trade_in.py b/tradein-mvp/backend/app/api/v1/trade_in.py index 35406e73..211ca88b 100644 --- a/tradein-mvp/backend/app/api/v1/trade_in.py +++ b/tradein-mvp/backend/app/api/v1/trade_in.py @@ -2488,8 +2488,12 @@ def get_sales_vs_listings( """Pairs (ДКП-сделка, listing) для улицы целевого адреса (PR K / #564). Для каждой ДКП-сделки Росреестра в окне `period_months` пытаемся найти - matching listing на той же улице с такими же rooms / близкой area_m2 / - listing_date в окне [deal_date - window_days, deal_date + 30d grace]. + matching listing на той же улице с близкой area_m2 / listing_date в окне + [deal_date - window_days, deal_date + 30d grace]. Комнатность в ключе стоит + ТОЛЬКО на стороне объявлений (`l.rooms = p_rooms`, комнатность клиента): у + сделок Росреестра `rooms` — синтетика из площади, предикат по ней снят + миграцией 300 (#3451/#3256). Поэтому `deal_rooms` в паре может не совпадать + с запрошенным `rooms`. Возвращаем LEFT JOIN: сделки без listing match сохраняются (listing_* = None), чтобы вычислить linkage_rate. diff --git a/tradein-mvp/deploy/import-rosreestr.sh b/tradein-mvp/deploy/import-rosreestr.sh index 1e2430d1..f53acefc 100755 --- a/tradein-mvp/deploy/import-rosreestr.sh +++ b/tradein-mvp/deploy/import-rosreestr.sh @@ -76,10 +76,15 @@ docker exec "$SRC_PG" psql -U "$SRC_USER" -d "$SRC_DB" -v ON_ERROR_STOP=on -c " -- НЕ фильтруют по deals.rooms ИМЕННО потому, что здесь синтетика; с -- настоящей комнатностью предикат нужно вернуть, иначе все сайты молча -- продолжат ключеваться площадью. - -- Потребителей, фильтрующих по d.rooms, БОЛЬШЕ НЕТ: последний — + -- Потребителей, фильтрующих РАВЕНСТВОМ по d.rooms, больше нет: последний — -- TVF street_sales_vs_listings — расчищен миграцией 300 (#3451). Ключ там -- асимметричный: d.rooms снят, l.rooms ОСТАВЛЕН (у объявлений комнатность -- настоящая). Появится новый потребитель — сверься с этим якорем. + -- НО: app/tasks/asking_to_sold_ratio.py:148,152 по-прежнему КЛЮЧУЕТСЯ этим + -- бакетом (GROUP BY LEAST(GREATEST(rooms,0),4)) и намеренно зеркалит ту же + -- синтетику на листинговой стороне (#2620). Поменяешь CASE на реальную + -- комнатность — вернётся именно #2620 (миграция 23-55% объявлений между + -- бакетами, ratio>1 в «4+»), а не только вопрос предикатов. CASE WHEN area < 30 THEN 0 WHEN area < 44 THEN 1 WHEN area < 62 THEN 2 WHEN area < 85 THEN 3