fix(tradein): coarse-geo downgrade works without DaData on prod (#693) #718
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#718
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/693-coarse-geo-prod"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
QA smoke FAIL on #693 (geo-quality gate from PR #707 never fired on prod).
Root cause (confirmed via QA probes): PR #707's downgrade was gated on
dadata.qc_geo >= 2, but on prod DaData is off (DADATA_*token unset) →dadata_clean_address()returnsNone→dadata is not Noneis always False → the coarse-geo downgrade never executed, even for region/city centroids. Unit tests passed because they mockeddadata_result=_make_dadata(qc_geo=3)— a signal absent in production.Fix
Add a DaData-independent coarse signal
_geocode_is_coarse(geo), OR'd into the existing gate:full_address("Россия, Свердловская область, Екатеринбург") does not.(?<!\d)\d{1,3}[а-яёa-z]?(?!\d)matches a house number while excluding postcode (6 digits) and year (4 digits).geo.confidence == "locality"(future-proof; current providers don't emit it yet).Guards unchanged: only downgrades when
anchor_tier is None(same-building #691 path untouched) andmedian_price > 0.Properties:
geo.full_addressregardless of provider/cache, so already-cached coarse entries downgrade immediately.Test plan
pytest tests/test_same_building_anchor.py→ 48 passed (+4: prod coarse-geo without DaData → low+flag; region centroid; coarse+anchor not downgraded;_geocode_is_coarseunit incl. postcode/locality cases).test_estimate_no_dadata_no_false_downgradestill green (precise geo + no DaData → no downgrade).ruff check+ruff-formatclean.Post-merge QA repro (
POST /trade-in/api/v1/trade-in/estimate):{"address":"фывапролд 999","rooms":2,"area_m2":50}→ expectconfidence="low"+ «оценка ориентировочная» flag (was confidentmedium).Refs #693
✅ APPROVE — correct root-cause fix for the #693 QA-fail (prod DaData off → old
qc_geo>=2gate never fired).Verified against the real files:
GeocodeResult(geocoder.py:34-39) is a frozen dataclass withfull_address: strandconfidence: Literal["exact","approximate","locality"] = "approximate"→ both_make_fake_geo_coarse()(omits confidence) andgeo.confidence == "locality"are valid; plain str, no enum mismatch.geois guaranteed non-None at the gate (earlyif geo is None: return _empty_estimate(...)before line ~1969) → no NPE on_geocode_is_coarse(geo).(?<!\d)\d{1,3}[а-яёa-z]?(?!\d): excludes 6-digit postcode + 4-digit year, matches real house numbers incl. cyrillic корпус-литера ("16а"). Numeric-street ("8 Марта") stays precise — documented conservative choice (zero false-downgrade).anchor_tier is Noneguard preserved verbatim → no #691 same-building regression; #707 DaData path unchanged (OR-extended, not replaced)._geocode_is_coarseunit (city/region/postcode/locality + precise) + 3 integration paths (coarse-no-dadata→low, region-centroid→low, coarse+anchor→NOT downgraded).Minor (non-blocking, not queued):
"locality"confidence isn't emitted by current providers (forward-compat stub; branch 2 covers prod). Merging.