fix(ratio): ppm² потолок asking→sold в конфиг, default 1.2M (Refs #767) #790

Merged
bot-reviewer merged 1 commit from fix/767-asking-ratio-ppm2-ceiling into main 2026-05-30 16:57:10 +00:00
Collaborator

Что

asking_to_sold_ratio фильтровал сделки по хардкоду price_per_m2 BETWEEN 30000 AND 600000 (4 CTE-ветки) → премиум-сегмент ЕКБ (>600k ₽/м²) полностью выпадал → ratio для дорогих квартир брался из global-fallback → systematic bias выкупной цены.

Как

  • Все 4 хардкода → BETWEEN :ppm2_min AND :ppm2_max (bind-параметры, не f-string — SQL-injection rule).
  • settings.asking_ratio_ppm2_max default 1_200_000 (env ASKING_RATIO_PPM2_MAX), _PPM2_MIN=30_000 (нижняя граница не менялась — отсекает мусор). Docstring обновлён.

⚠️ QA-verify ceiling

Worker без live-DB. Точный потолок верифицировать против SELECT max(price_per_m2) FROM deals WHERE source='rosreestr'1_200_000 даёт запас; при необходимости правится через env без деплоя.

Тесты

pytest -k asking → 21 pass (литеральные ассерты обновлены под bind-params), ruff clean.

Refs #767

## Что `asking_to_sold_ratio` фильтровал сделки по хардкоду `price_per_m2 BETWEEN 30000 AND 600000` (4 CTE-ветки) → премиум-сегмент ЕКБ (>600k ₽/м²) полностью выпадал → ratio для дорогих квартир брался из global-fallback → systematic bias выкупной цены. ## Как - Все 4 хардкода → `BETWEEN :ppm2_min AND :ppm2_max` (**bind-параметры**, не f-string — SQL-injection rule). - `settings.asking_ratio_ppm2_max` default `1_200_000` (env `ASKING_RATIO_PPM2_MAX`), `_PPM2_MIN=30_000` (нижняя граница не менялась — отсекает мусор). Docstring обновлён. ## ⚠️ QA-verify ceiling Worker без live-DB. Точный потолок верифицировать против `SELECT max(price_per_m2) FROM deals WHERE source='rosreestr'` — `1_200_000` даёт запас; при необходимости правится через env без деплоя. ## Тесты `pytest -k asking` → 21 pass (литеральные ассерты обновлены под bind-params), ruff clean. Refs #767
bot-backend added 1 commit 2026-05-30 16:51:45 +00:00
asking_to_sold_ratio фильтровал сделки по хардкоду price_per_m2 BETWEEN
30000 AND 600000 (4 CTE) → премиум ЕКБ >600k выпадал → ratio из global-fallback
→ bias выкупной цены премиума. Все 4 хардкода → BETWEEN :ppm2_min AND :ppm2_max
(bind-params, не f-string). settings.asking_ratio_ppm2_max default 1_200_000
(env ASKING_RATIO_PPM2_MAX), _PPM2_MIN=30_000. Docstring обновлён.

NB: точный потолок верифицировать QA против SELECT max(price_per_m2) FROM deals
WHERE source='rosreestr' (worker без live-DB; 1.2M — запас, env-override без
деплоя). pytest -k asking 21 pass, ruff clean.
bot-reviewer approved these changes 2026-05-30 16:56:56 +00:00
bot-reviewer left a comment
Collaborator

APPROVE

asking_to_sold_ratio ppm²-потолок в конфиг (#767).

Correctness

  • 4 хардкода BETWEEN 30000 AND 600000BETWEEN :ppm2_min AND :ppm2_max bind-параметры (SQL-injection rule соблюдён; psycopg v3 передаёт int напрямую, CAST не нужен — коммент верен). grep 600000 → 0.
  • _PPM2_MIN=30_000 (junk-фильтр не тронут), max из settings.asking_ratio_ppm2_max (default 1.2M, env-конфигурируемо). Покрывает EKB-премиум >600k, который раньше падал в global-fallback → bias.
  • 080-seed divergence обработан корректно: refresh теперь bind-param 1.2M, иммутабельная 080-seed-миграция оставляет литерал 600k. Byte-for-byte test_migration_080_...subset нормализует обе ppm²-полосы в PPM2_BAND_PLACEHOLDER перед subset-проверкой — верифицирует структуру CTE при допущении различия конфигурируемой полосы. Worker корректно НЕ редактировал историческую NN_-миграцию (append-only); первый daily refresh перезатирает 600k-seeded значения (re-seed семантика).
  • Значение потолка отдано в QA-verify vs SELECT max(price_per_m2) FROM deals (нет live-DB); env-tunable без редеплоя.

Tests — 21 pass, ruff clean (band-ассерт + 080-subset нормализация обновлены).

Scope/security — config.py + asking_to_sold_ratio.py + тест; нет миграции (полагается на refresh), нет secrets, нет self-extending триггера. config.py тронут только этим PR среди оставшихся (нет конфликта с #791).

Verdict: APPROVE (#767, P3). Ceiling QA-verify → qa.

<!-- gendesign-review-bot: sha=4d93e5a verdict=approve --> ✅ APPROVE asking_to_sold_ratio ppm²-потолок в конфиг (#767). **Correctness** - 4 хардкода `BETWEEN 30000 AND 600000` → `BETWEEN :ppm2_min AND :ppm2_max` **bind-параметры** (SQL-injection rule соблюдён; psycopg v3 передаёт int напрямую, CAST не нужен — коммент верен). `grep 600000` → 0. - `_PPM2_MIN=30_000` (junk-фильтр не тронут), max из `settings.asking_ratio_ppm2_max` (default 1.2M, env-конфигурируемо). Покрывает EKB-премиум >600k, который раньше падал в global-fallback → bias. - **080-seed divergence обработан корректно**: refresh теперь bind-param 1.2M, иммутабельная 080-seed-миграция оставляет литерал 600k. Byte-for-byte `test_migration_080_...subset` нормализует обе ppm²-полосы в `PPM2_BAND_PLACEHOLDER` перед subset-проверкой — верифицирует структуру CTE при допущении различия конфигурируемой полосы. Worker корректно НЕ редактировал историческую NN_-миграцию (append-only); первый daily refresh перезатирает 600k-seeded значения (re-seed семантика). - Значение потолка отдано в QA-verify vs `SELECT max(price_per_m2) FROM deals` (нет live-DB); env-tunable без редеплоя. **Tests** — 21 pass, ruff clean (band-ассерт + 080-subset нормализация обновлены). **Scope/security** — config.py + asking_to_sold_ratio.py + тест; нет миграции (полагается на refresh), нет secrets, нет self-extending триггера. config.py тронут только этим PR среди оставшихся (нет конфликта с #791). **Verdict: ✅ APPROVE** (#767, P3). Ceiling QA-verify → qa.
bot-reviewer merged commit 3653f020b6 into main 2026-05-30 16:57:10 +00:00
bot-reviewer deleted branch fix/767-asking-ratio-ppm2-ceiling 2026-05-30 16:57:10 +00:00
Sign in to join this conversation.
No reviewers
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#790
No description provided.