Compare commits

...

3 commits

Author SHA1 Message Date
4c56c5189a Merge pull request 'fix(tradein/estimator): резолвить target-город коридора из payload.address (C2 hotfix)' (#2490) from fix/tradein-oblast-c2fix-corridor-city into main
Some checks failed
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 12s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / test (push) Has been cancelled
2026-07-12 17:50:19 +00:00
bot-backend
69f8b50934 docs(tradein): исправить GET-rehydrate comment — row.address=geo.full_address (city-stripped), corridor unscoped для не-ЕКБ (known limitation)
All checks were successful
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 8s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 51s
2026-07-12 20:48:25 +03:00
bot-backend
7801ac6cc1 fix(tradein/estimator): резолвить target-город коридора из payload.address (C2 hotfix)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 8s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 50s
C2 city-scope коридора был NO-OP для не-ЕКБ: estimate_quality резолвил город из geo.full_address, но геокодер РОНЯЕТ город для не-ЕКБ («Ленина, 1» вместо «Нижний Тагил, Ленина, 1») → target_city=None → коридор либо unscoped, либо None. Verified на проде: Н.Тагил corridor=None.

Фикс: резолвить город из payload.address (город есть) с fallback на canonical/geo; коридор матчить тоже по payload.address. GET: row.address приоритетнее canonical.

Verified прод-диагностикой: corridor(address=payload.address, city=resolve) → Н.Тагил=9, ЕКБ=15 (было: Н.Тагил=None). EKB regression-гейт байт-зелёный. geocoder full_address city-strip (display «Ленина,1») → cosmetic, E.
2026-07-12 20:36:08 +03:00
2 changed files with 14 additions and 6 deletions

View file

@ -284,10 +284,13 @@ def get_estimate(
else None else None
) )
# (oblast C2): city-scope корридора на GET-rehydrate тоже — тот же # (oblast C2): city-scope корридора на GET-rehydrate. NB: row.address здесь =
# resolver, что и на POST (estimate_quality), над персистированным адресом # geo.full_address (персистится на estimate-time), который РОНЯЕТ город для
# (canonical_address приоритетнее сырого row.address, если DaData отработал). # не-ЕКБ («Ленина, 1») → target_city=None → corridor unscoped/None для не-ЕКБ
target_city = _resolve_target_city(row.canonical_address or row.address) # (KNOWN LIMITATION: POST-path чинит через payload.address; GET получит паритет
# когда raw payload.address начнёт персиститься — follow-up). Для ЕКБ ок; reorder
# ниже безвреден (оба source city-stripped для не-ЕКБ, оба екб для ЕКБ).
target_city = _resolve_target_city(row.address) or _resolve_target_city(row.canonical_address)
dkp_raw = _fetch_dkp_corridor( dkp_raw = _fetch_dkp_corridor(
db, address=row.address, rooms=row.rooms, area=area_f, city=target_city db, address=row.address, rooms=row.rooms, area=area_f, city=target_city
) )

View file

@ -3207,13 +3207,18 @@ async def estimate_quality(
# (oblast C2): city-scope корридора — та же precedence, что и для # (oblast C2): city-scope корридора — та же precedence, что и для
# match_house_readonly выше (dadata.canonical_address приоритетнее сырого # match_house_readonly выше (dadata.canonical_address приоритетнее сырого
# geo.full_address, если DaData отработал). # geo.full_address, если DaData отработал).
target_city = _resolve_target_city( # payload.address (пользовательский ввод) — САМЫЙ надёжный источник города:
# geocoder.full_address/canonical часто роняют город для не-ЕКБ («Ленина, 1»
# вместо «Нижний Тагил, Ленина, 1») → без этого city-scope коридора (C2) был
# бы no-op для всей области (verified прод: tc=None → corridor=None). Fallback
# на canonical/geo для bare-адресов без города.
target_city = _resolve_target_city(payload.address) or _resolve_target_city(
(dadata.canonical_address if dadata else None) or geo.full_address (dadata.canonical_address if dadata else None) or geo.full_address
) )
dkp_raw = await asyncio.to_thread( dkp_raw = await asyncio.to_thread(
_fetch_dkp_corridor, _fetch_dkp_corridor,
db, db,
address=geo.full_address, address=payload.address,
rooms=payload.rooms, rooms=payload.rooms,
area=payload.area_m2, area=payload.area_m2,
city=target_city, city=target_city,