Compare commits

..

No commits in common. "c6321c767d2ec9ba6f1e90dc7c76d17ad866d71c" and "541c4ff28ddcbeb159416fc945dcaa3c727af9ea" have entirely different histories.

2 changed files with 1 additions and 42 deletions

View file

@ -50,7 +50,6 @@ from app.schemas.trade_in import (
TradeInEstimateInput,
)
from app.services import account_quota
from app.services import regions as regions_mod
from app.services.exporters.trade_in_pdf import generate_trade_in_pdf
from app.services.image_sanitizer import ImageSanitizationError, sanitize_image
from app.services.user_events import schedule_event
@ -764,22 +763,8 @@ def load_estimate(
# когда raw payload.address начнёт персиститься — follow-up). Для ЕКБ ок; reorder
# ниже безвреден (оба source city-stripped для не-ЕКБ, оба екб для ЕКБ).
target_city = _resolve_target_city(row.address) or _resolve_target_city(row.canonical_address)
# #3051 PR-A: тот же region_code-скоуп, что и POST /estimate — гарантирует
# «регион не резолвится → DEFAULT_REGION_CODE (66)», не NULL (NULL в SQL
# обнулил бы фильтр). row.lat/row.lon персистятся с estimate-time.
target_region = (
regions_mod.region_for_point(row.lat, row.lon)
if row.lat is not None and row.lon is not None
else None
)
target_region_code = target_region.code if target_region else regions_mod.DEFAULT_REGION_CODE
dkp_raw = _fetch_dkp_corridor(
db,
address=row.address,
rooms=row.rooms,
area=area_f,
city=target_city,
region_code=target_region_code,
db, address=row.address, rooms=row.rooms, area=area_f, city=target_city
)
dkp_corridor = DkpCorridor(**dkp_raw) if dkp_raw else None

View file

@ -66,7 +66,6 @@ from app.schemas.trade_in import (
PriceTrendPoint,
TradeInEstimateInput,
)
from app.services import regions as regions_mod
from app.services.dadata import DadataAddressResult
# enrich_address = /clean с graceful fallback на /suggest (#dadata-403: на проде услуга
@ -1833,7 +1832,6 @@ def _fetch_dkp_corridor(
rooms: int | None,
area: float | None,
city: str | None = None,
region_code: int = regions_mod.DEFAULT_REGION_CODE,
period_months: int = DEALS_PERIOD_MONTHS,
area_tolerance: float = AREA_TOLERANCE,
) -> dict[str, Any] | None:
@ -1853,16 +1851,6 @@ def _fetch_dkp_corridor(
Тагиле/Лесном/Краснотурьинске/Серове/ЕКБ/Первоуральске) коридор превращался
в кросс-областной мусор для не-ЕКБ таргетов. None (город не определился)
фильтр не применяется, прежнее (pre-oblast) поведение сохраняется как есть.
region_code: (#3051 «Москва», PR-A) — регион целевого запроса, ОБЯЗАТЕЛЬНЫЙ
фильтр (не advisory, в отличие от city) в обоих ДКП-запросах. `city`
распознаётся только для Свердловской области (_resolve_target_city матчит
исключительно SVERDLOVSK_OBLAST_CITIES) для Москвы/любого нового региона
city=None и street-ILIKE фильтр остаётся ЕДИНСТВЕННЫМ скоупом сделки; без
region_code одноимённая улица чужого региона (или сделка без узнанного
города вовсе) утекает в коридор через тот же street ILIKE. Дефолт
regions_mod.DEFAULT_REGION_CODE (66) байт-в-байт прежнее поведение для
всех сегодняшних вызовов (все сделки в БД сейчас region_code=66).
"""
if not address or rooms is None or not area:
return None
@ -1887,7 +1875,6 @@ def _fetch_dkp_corridor(
FROM deals d
LEFT JOIN deal_city_price_bands b ON b.city = d.city
WHERE d.source = 'rosreestr'
AND d.region_code = CAST(:region_code AS int)
AND d.address ILIKE :street_pattern
AND d.address ~* :street_regex
AND d.rooms = CAST(:rooms AS integer)
@ -1915,7 +1902,6 @@ def _fetch_dkp_corridor(
"ppm_min": DEAL_MIN_PPM2,
"ppm_max": DEAL_MAX_PPM2,
"target_city": city.lower() if city else None,
"region_code": region_code,
},
)
.mappings()
@ -1970,7 +1956,6 @@ def _fetch_dkp_corridor(
FROM deals d
LEFT JOIN deal_city_price_bands b ON b.city = d.city
WHERE d.source = 'rosreestr'
AND d.region_code = CAST(:region_code AS int)
AND d.city IS NOT NULL
AND LOWER(d.city) = CAST(:target_city AS text)
AND d.rooms = CAST(:rooms AS integer)
@ -1990,7 +1975,6 @@ def _fetch_dkp_corridor(
"period_months": period_months,
"ppm_min": DEAL_MIN_PPM2,
"ppm_max": DEAL_MAX_PPM2,
"region_code": region_code,
},
)
.mappings()
@ -4571,15 +4555,6 @@ async def estimate_quality(
target_city = _resolve_target_city(payload.address) or _resolve_target_city(
(dadata.canonical_address if dadata else None) or geo.full_address
)
# #3051 PR-A: региональный скоуп ДКП-коридора — target_city выше распознаёт
# ТОЛЬКО города Свердловской области (_resolve_target_city матчит
# SVERDLOVSK_OBLAST_CITIES), т.е. для Москвы/любого нового региона city=None
# и без region_code street ILIKE ловил бы одноимённую улицу ЧУЖОГО региона.
# region_for_point(None) (точка вне охвата ни одного региона) → дефолт 66,
# НЕ None — NULL в SQL-параметре обнулил бы фильтр (`= NULL` не матчит
# ничего), т.е. держим гарантию «не резолвится → 66», не пусто.
target_region = regions_mod.region_for_point(geo.lat, geo.lon)
target_region_code = target_region.code if target_region else regions_mod.DEFAULT_REGION_CODE
dkp_raw = await asyncio.to_thread(
_fetch_dkp_corridor,
db,
@ -4587,7 +4562,6 @@ async def estimate_quality(
rooms=payload.rooms,
area=payload.area_m2,
city=target_city,
region_code=target_region_code,
)
# ── Stage 3: Avito IMV evaluation as 5-th source (on-demand cached) ──