Commit graph

436 commits

Author SHA1 Message Date
92725c6122 fix(tradein): Mera-audit fix-4 — верифицировать DEAL_MAX_PPM2 vs prod данных
All checks were successful
CI / changes (pull_request) Successful in 7s
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
Данные на 2026-06-21 (prod deals table, 49 791 записей):
  p90=172 419 ₽/м², p95=199 583 ₽/м², p99=278 681 ₽/м², p99.9=500 000 ₽/м²
  deals >800k = 13 штук (0.026%) — нерыночные outlier'ы, не легитимный премиум ЕКБ.
  listings p99 (is_active, <800k фильтр) = 392 795 ₽/м².

Вывод: DEAL_MAX_PPM2=800_000 НЕ срезает легитимный ЕКБ-премиум (p99.9 сделок=500k).
Значение NOT изменено — задокументировано в комментарии рядом с константой
для обоснования порога и последующей ревалидации при росте рынка.
2026-06-21 09:06:36 +03:00
af1d882745 fix(tradein): Mera-audit fix-3 — cross-source dedup в _fetch_price_trend
Один объект на avito_imv + yandex_valuation с разными ext_item_id создаёт
дубликаты в house_placement_history и double-count'ится в помесячной медиане.
Решение: CTE с DISTINCT ON (round(area_m2), floor, price, price_date) с
приоритетом avito_imv через CASE sort. Легитимные разные квартиры (разные
площадь/этаж/цена) не затрагиваются.

За флагом estimate_price_trend_dedup_enabled (дефолт True в settings).
False → точно старое поведение (backward-compat). Graceful: без изменений
в логике min_points и возврата None при недостатке данных.

Тесты: 6 новых тест-кейсов в test_estimator_price_trend_dedup.py (SQL содержит
DISTINCT ON, flag OFF не содержит, Source1 preferred, данные возвращаются корректно).
2026-06-21 09:05:57 +03:00
81ee864d80 fix(tradein): Mera-audit fix-2 — _is_plausible_deal floor edge + area/price guards
Ужесточает валидацию ДКП-сделок в _is_plausible_deal:
- floor < 1 или floor=0 → drop (floor=-5/0/999 из битого парсера)
- area_m2 задана и <= 0 → drop (нулевая/отрицательная площадь из битого парсера)
- price_rub задана и <= 0 → drop (нерыночная/техническая сделка)
- floor=None → допустимо (graceful, нечем судить)

Все новые параметры area_m2/price_rub keyword-only с дефолтом None →
backward-compatible для существующих вызовов. Caller _fetch_deals обновлён
для передачи area_m2/price_rub из данных сделки.

Тесты: 16 новых тест-кейсов в test_deals_sanitize.py (floor=-5, floor=999,
floor=None ok, area_m2=0 drop, price_rub=-1 drop и пр.).
2026-06-21 09:04:54 +03:00
50a72f030a fix(tradein): Mera-audit fix-1 — Cian valuation price sanity bounds
Добавляет _is_price_sane() в cian_valuation.py: если sale_price_rub вне
[cian_valuation_min_rub, cian_valuation_max_rub] (дефолты 500k/500M),
или low_price > high_price, или любой bound отрицательный — результат
не кэшируется и возвращается None (graceful). Защита от garbage-ответов
API (999_999 < min, 9_999_999_999 > max).

Новые settings: cian_valuation_min_rub=500_000, cian_valuation_max_rub=500_000_000.
Тесты: 11 новых тест-кейсов в test_cian_valuation.py. Пофиксен pre-existing
KeyError в test_cache_hit_returns_cached (missing low_price/high_price в mock).
2026-06-21 09:02:32 +03:00
b2cd2925fd fix(estimator): clamp expected_sold <= asking (ratio cap 1.0) -- smoke 3к exp_sold>asking
All checks were successful
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI / changes (pull_request) Successful in 8s
CI / backend-tests (pull_request) Has been skipped
2026-06-21 00:35:23 +03:00
f2cfe66b02 fix(scrapers): yandex history skip area<=0 items
_save_yandex_history_items теперь пропускает items с area_m2 is None или
area_m2 <= 0 (битый парс «0,5 м²» и пр.) перед сохранением в
house_placement_history. Грязь копилась в БД и искажала price_trend.

Estimator защищён NULLIF на уровне SQL, но фильтрация на входе надёжнее.
Лог кол-ва отброшенных (info). Батч не падает из-за одного битого item.
2026-06-21 00:25:43 +03:00
b6ea986134 fix(estimator): radius-path нижний floor от DKP-коридора (анти-undershoot)
Anchor-путь имеет hard floor от comp_min_ppm2×(1-tol). Radius-путь аналогичной
защиты снизу не имел — quarter-index-вниз или corridor-clamp могли занизить
median неоправданно (asymmetry).

Добавлен floor: если итоговый median_ppm2 < dkp_low_ppm2 × factor → поднять
до floor + лог. Только radius-путь (anchor_tier is None); без dkp_raw → no-op.
За флагами estimate_radius_floor_enabled (default True) и
estimate_radius_floor_factor (default 0.8).
2026-06-21 00:25:05 +03:00
352dfc8053 fix(estimator): asking_to_sold ratio tier по финальному headline
_get_asking_sold_ratio теперь вызывается ПОСЛЕ anchor/IMV-blend/quarter-index/
corridor-clamp, получая ФИНАЛЬНЫЙ median_ppm2 для tier-placement (#928 audit).

До фикса: tier резолвился по pre-anchor radius-медиане (~105k), но ratio
применялся к post-anchor headline (~300k) — несовпадение tier'а в premium-
сегменте. После: ratio берётся из того же tier, что и финальный headline.

Graceful: нет ratio → expected_sold_* = None, headline не меняется.
2026-06-21 00:24:02 +03:00
7f036a96af fix(scrapers): avito ban-triggered IP rotation (#1790) — changeip on block, bounded
All checks were successful
CI / changes (pull_request) Successful in 6s
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
- Добавлен `_rotate_proxy_ip()` в scrape_pipeline.py: вызывает changeip-URL
  (settings.avito_proxy_rotate_url) + settle-sleep
  (settings.avito_proxy_rotate_settle_s, default 9s), логирует old→new IP.
- В `run_avito_pipeline` (Steps 4/5/5b) и `run_avito_city_sweep` (Phase 4/5/5b):
  при достижении consecutive-block порога — сначала ротация IP, сброс счётчика,
  продолжение; только при исчерпании бюджета (enrich_rotations_done >=
  avito_proxy_max_rotations) — abort (bounded). #1820 graceful сохранён: один
  блок ниже порога ротацию не вызывает.
- Добавлено `avito_proxy_rotate_settle_s: float = 9.0` в config.py
  (ENV: AVITO_PROXY_ROTATE_SETTLE_S). avito_proxy_max_rotations был 4 (с #1731).
- Тесты: rotation_called / bounded_abort / single_block_no_rotation.
2026-06-20 21:24:12 +03:00
37f12f6303 fix(tradein/yandex): инкрементальный per-combo save + bounded gate-timeout (анти-зомби city_sweep)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
2026-06-20 20:57:41 +03:00
06fa5b4910 Merge pull request 'feat(tradein): бэкфилл координат листингов из ekb_geoportal_buildings (street+house match)' (#1841) from feat/tradein-backfill-coords-geoportal into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 7s
Deploy Trade-In / build-browser (push) Successful in 28s
Deploy Trade-In / build-frontend (push) Successful in 28s
Deploy Trade-In / test (push) Successful in 1m23s
Deploy Trade-In / build-backend (push) Successful in 50s
Deploy Trade-In / deploy (push) Successful in 47s
Reviewed-on: #1841
2026-06-20 14:14:12 +00:00
d35e61be16 feat(tradein): бэкфилл координат листингов из ekb_geoportal_buildings (street+house match)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
2026-06-20 17:08:46 +03:00
f026423715 feat(tradein/avito): per-card ЕКБ гео-фильтр (отсечь padding по России) + сплит комнат 4/5+
All checks were successful
CI / changes (pull_request) Successful in 5s
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
FIX 1: в _parse_html добавлен гео-фильтр per-card source_url. При
avito_serp_ekb_only=True (ENV AVITO_SERP_EKB_ONLY, дефолт True) карточки без
/ekaterinburg/ в source_url отбрасываются — Авито добивает выдачу
«по всей России» при малом числе ЕКБ-результатов (rooms=4 давал 96% не-ЕКБ).
Карточки без распознанного city-slug пропускаются консервативно.
Лог: «avito SERP: dropped N non-EKB cards (padding)».

FIX 2 (анализ): ROOM_SLUGS уже содержит отдельные бакеты «4-комн.» и «5+комн.»
(разбиты ранее). rooms-значение берётся из текста заголовка карточки
(_extract_rooms_from_title: regex «(\d)-к. квартира»), а не из бакета —
4/5/6 различаются по факту парсинга. Сплит slug'ов был сделан ранее, регрессий нет.

Тесты: 4 новых unit-теста в test_avito_ekb_geo_filter.py покрывают:
EKB+non-EKB → только EKB; ekb_only=False → все проходят;
без city-slug → консервативно оставляем; все EKB → ничего не дропается.
2026-06-20 16:59:12 +03:00
cc3ff7c3d2 feat(tradein/scrapers): detail_backfill через curl_cffi+backconnect вместо браузера/auv (развязка прокси)
All checks were successful
CI / changes (pull_request) Successful in 7s
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
SERP (full_load/city_sweep) и detail_backfill делили один прокси-аккаунт auv (~5 коннектов).
Browser-фетч в backfill открывал десятки CONNECT-туннелей → cap превышался → HTTP 500/краши.

- config.py: avito_detail_backfill_use_curl=True (ENV AVITO_DETAIL_BACKFILL_USE_CURL)
- avito_detail_backfill.py: browser_mode гейтится флагом; use_curl=True → session=None,
  browser_fetcher=None → fetch_detail строит _build_detail_session() через scraper_proxy_url
  (backconnect mproxy, авто-ротация, 1 коннект/запрос)
- tests: 2 новых теста (use_curl=True → BrowserFetcher не создаётся; False → создаётся)
2026-06-20 15:55:24 +03:00
93783602c5 Merge pull request 'feat(scrapers): live pacing-регулятор + data-quality coverage API' (#1829) from feat/scrapers-config-apis into main
Some checks failed
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 7s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been cancelled
Deploy Trade-In / test (push) Has been cancelled
Reviewed-on: #1829
2026-06-20 12:31:47 +00:00
daa2edfac3 test(estimator): unit tests для audit fixes #audit-1..5 + empty-series guard
All checks were successful
CI / changes (pull_request) Successful in 6s
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
18 тестов покрывают все 5 фиксов: low-conf gate, analog_tier enum,
price_trend freshness, sigma=0 guard, sber staleness, thin-market flag.
Попутный fix: _load_sber_index_series — guard 'if not series: continue'
предотвращает max() на пустом dict при MagicMock rows (truthy=True).
2026-06-20 15:06:59 +03:00
a6ef2c73e1 fix(estimator): data-age guards — sber staleness + IMV thin-market (#audit-5)
5a: _load_sber_index_series логирует warning если latest месяц серии
старее sber_index_max_age_days (дефолт 35) — расчёт не блокируется.
5b: AvitoImvSummary.thin_market (bool, дефолт False) — True когда
market_count < avito_imv_thin_market_threshold (дефолт 10). Все три
точки конструирования AvitoImvSummary обновлены. Warning при thin.
2026-06-20 15:03:19 +03:00
5b2a39cd5e fix(estimator): MAD-clip после similarity-weighting + sigma=0 guard (#audit-4)
sigma=0 guard: safe_area_sigma2/safe_floor_sigma2 предотвращает div/0 при
нулевом sigma из конфига. Post-weight MAD-clip (estimate_sb_clip_after_weight,
дефолт True) выполняется ПОСЛЕ Gaussian weighting — видовые/топ-юниты
с высоким ppm² больше не выкидываются до учёта similarity. За флагом.
2026-06-20 15:01:36 +03:00
17edac532b fix(estimator): Yandex history freshness filter в price_trend (#audit-3)
_fetch_price_trend(freshness_months) — новый параметр, дефолт из
settings.estimate_price_trend_max_age_months (6 мес).
WHERE scraped_at > now() - N months исключает устаревшие items
(yandex_valuation 2024 и т.д.) из house_placement_history fallback.
houses_price_dynamics (Source 1) не затронут. psycopg v3 CAST syntax.
2026-06-20 15:00:55 +03:00
6b99f7d238 fix(estimator): структурный analog_tier + address_precision в API (#audit-2)
Добавляет AggregatedEstimate.analog_tier — стабильный enum для фронта:
same_building (Tier A), micro_radius (Tier C), district (S/H/0), city (W),
null (нет данных). Фронт не парсит tier из explanation.
address_precision уже был в схеме (подтверждено: line 208). Explanation не
удаляется — фронт fallback'ает на него.
2026-06-20 15:00:12 +03:00
55c7bc2c72 fix(estimator): anchor low-confidence gate (#audit-1)
Якорь с confidence=low ИЛИ (n<gate_min_n И FSD>gate_max_fsd) не заменяет
headline — fallback на radius-median. Дефолты (min_n=3, max_fsd=0.20) не
режут здоровые якоря (n≥4, FSD<0.15 проходят). За флагом
estimate_sb_low_conf_gate_enabled (дефолт True). Логируется с причиной.
2026-06-20 14:59:05 +03:00
b6634ea40c feat(scrapers): live pacing-регулятор (GET/PUT /scraper/pacing) + data-quality coverage endpoint
All checks were successful
CI / changes (pull_request) Successful in 7s
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
- browser/server.py: GET /pacing и PUT /pacing — read/write _MIN_PAGE_INTERVAL_BY_PROVIDER
  in-memory; валидация source in PROVIDERS, interval_s >= 0; логирует изменения; сбрасывается
  к env-дефолту на рестарте by design
- backend/admin.py: GET /scraper/pacing — прокси к browser /pacing, PacingResponse pydantic;
  PUT /scraper/pacing/{source} — прокси PUT с валидацией ge=0 le=120; 502/503 при недоступности
- backend/admin.py: GET /scraper/data-quality — single-pass FILTER-агрегаты по listings WHERE
  is_active GROUP BY source (description/photo_urls/address/lat/lon/kitchen_area_m2/living_area_m2/
  ceiling_height/ceiling_height_m/metro_stations); houses (total/avito_validated_at%/rating_score%/
  house_type%); house_reviews count
- browser/test_server_pacing.py: 10 новых тестов GET+PUT /pacing (16 total, все зелёные)
- backend/tests/test_scraper_admin_apis.py: тесты pacing-прокси + data-quality shape/pct-range
  (21 total, все зелёные)
2026-06-20 12:47:03 +03:00
533299ea47 feat(tradein/scrapers): full_load пропускает листинги обновлённые сегодня при повторном прогоне (skip_seen_today)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
2026-06-20 12:13:32 +03:00
89cbddf318 fix(tradein/db): widen offer_price_history.diff_percent numeric(5,2)→(8,2) + clamp в триггере (краш full_load)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
2026-06-20 11:43:23 +03:00
8361961a44 fix(scrapers/backend): socks5 health-probe (httpx[socks]) + status Literal whitelist + #1820 ext_id=0 dedup-гард
All checks were successful
CI / changes (pull_request) Successful in 7s
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
- pyproject.toml: httpx[socks]>=0.27.0 — тянет socksio, socks5:// прокси в _probe_current_ip работает прозрачно
- admin.py list_scrape_runs_unified: status Literal["done","running","banned","zombie","failed","cancelled"] вместо str|None — невалидные значения → 422
- avito_houses.py save_house_catalog_enrichment: гард ext_id=0 + нет адреса → skip without DB touch; два id-less novostroyka URL не схлопываются в bogus avito:0 в house_sources
- тесты: test_unified_runs_invalid_status_422 + test_unified_runs_valid_statuses_200; test_save_house_catalog_enrichment_skips_zero_ext_id_no_address + *_with_address_persists
2026-06-20 10:17:37 +03:00
cd91d5e279 fix(scrapers): avito pipeline — новостройки house graceful (без housePage), AvitoBlockedError per-item не крашит прогон (#1820)
All checks were successful
CI / changes (pull_request) Successful in 7s
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
2026-06-20 09:53:46 +03:00
2f88a71915 feat(admin): unified scrape/runs + scraper/health + rotate-ip API для единой scrapers-страницы
All checks were successful
CI / changes (pull_request) Successful in 5s
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
2026-06-20 09:25:57 +03:00
3cb11355e6 fix(tradein/estimator): расширить corridor-clamp slack 0.25→0.40 для премиума без own-листингов
All checks were successful
CI / changes (pull_request) Successful in 5s
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
2026-06-20 09:16:00 +03:00
37fc50ad08 fix(scrapers): avito_detail_backfill — снапшот ЕКБ+active, detail browser-only без curl-fallback на бан (#1814)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
2026-06-19 21:58:35 +03:00
ebdd70a38d Merge pull request 'feat(scrapers): avito SERP дефолт на BrowserFetcher (camoufox), curl_cffi fallback (#1805)' (#1809) from feat/avito-serp-browser-default into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m15s
Deploy Trade-In / build-backend (push) Successful in 58s
Deploy Trade-In / deploy (push) Successful in 45s
Reviewed-on: #1809
2026-06-19 17:53:12 +00:00
65cec74cca Merge pull request 'feat(scrapers): cian SERP на BrowserFetcher (camoufox), снят code-side rotate (#1806)' (#1810) from feat/cian-serp-browser into main
Some checks failed
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Has been cancelled
Reviewed-on: #1810
2026-06-19 17:51:59 +00:00
93f7c9ae3f feat(scrapers): avito SERP дефолт на BrowserFetcher (camoufox), curl_cffi fallback (#1805)
All checks were successful
CI / changes (pull_request) Successful in 6s
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
2026-06-19 20:42:04 +03:00
b1fb0c5711 feat(scrapers): cian SERP на BrowserFetcher (camoufox), снят code-side rotate (#1806)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
2026-06-19 20:41:44 +03:00
494f2e00e0 fix(tradein/estimator): clamp premium headline к коридору сделок + робастный anchor (#1795)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
2026-06-19 20:34:48 +03:00
8467cc647f test(browser): remove obsolete pool-routing tests (FEATURE_BROWSER_POOL_ENABLED/_build_proxy_map removed in #1793 per-provider rewrite; routing covered by browser/test_server.py)
All checks were successful
CI / changes (pull_request) Successful in 5s
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
2026-06-19 20:12:51 +03:00
2e3291abc9 Merge pull request 'fix(scrapers): cian_detail — ceiling из offer.building.ceilingHeight, repair из decoration (#1791)' (#1800) from feat/cian-detail-field-mapping into main
Some checks failed
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Failing after 1m20s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Has been skipped
Reviewed-on: #1800
2026-06-19 17:07:14 +00:00
2d3ca78b0b fix(scrapers): cian_detail — ceiling/repair актуальные пути state (#1791)
All checks were successful
CI / changes (pull_request) Successful in 5s
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
ceiling_height на detail-странице лежит в offer.building.ceilingHeight,
а не offer.ceilingHeight (всегда null) → было 0% покрытия. repairType
часто пустой, структурное значение приходит как offer.decoration
('preFine'/...) — читаем оба + добавлен preFine->needs_repair и
case-insensitive lookup в нормализаторе. kitchen/description пути уже
верны (offer.kitchenArea/offer.description) — низкое покрытие = мёртвый
CIAN_PROXY_URL, не маппинг. Регресс-тест на реальной карточке 330982715.
2026-06-19 19:57:18 +03:00
0084efc12a fix(scrapers): yandex_detail — area/ceiling из структурного блока, покрытие area 63%->~95% (#1792)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
2026-06-19 19:37:51 +03:00
464e9faf7b fix(scrapers): avito_houses читает MFE props-вложенность виджетов — отзывы/история/тип ЖК теперь долетают (#1789)
All checks were successful
CI / changes (pull_request) Successful in 5s
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
2026-06-19 19:21:49 +03:00
112e5cc2f1 fix(tradein): verify=False for EKB geoportal WFS (Russian-CA cert)
All checks were successful
CI / changes (pull_request) Successful in 5s
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
The geoportal serves a Russian national-CA (Минцифры) TLS cert absent from
httpx's default trust store → CERTIFICATE_VERIFY_FAILED, loader fetched 0.
Public read-only data → verify=False (same as the curl -k used in recon).
2026-06-19 18:19:03 +03:00
91b04a1851 test(tradein): patch _geoportal_house_match in cadastral-before-yandex test
All checks were successful
CI / changes (pull_request) Successful in 6s
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
#1786 merged before the test fix landed → main red on
test_geocode_uses_cadastral_before_yandex. The new geoportal house-match
tier runs first in geocode(); this legacy cadastral test must mock it to
None so it exercises the cadastral forward path (else the MagicMock db row
leaks through the new tier as lat=1.0).
2026-06-19 18:06:28 +03:00
7bf39e24df Merge pull request 'fix(db): #1781 backfill listings.house_id_fk from house_sources (cian novostroyki)' (#1784) from fix/1781-cian-novostroyki-fk-backfill into main
Some checks failed
Deploy Trade-In / changes (push) Successful in 6s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Failing after 1m19s
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / deploy (push) Has been skipped
Reviewed-on: #1784
2026-06-19 14:56:09 +00:00
64d113d649 feat(tradein): EKB geoportal building ingest + geocoder tier (complete city buildings)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
2026-06-19 17:51:07 +03:00
8adbbef88c fix(db): #1781 backfill listings.house_id_fk from house_sources
All checks were successful
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 / changes (pull_request) Successful in 6s
The realtime FK mirror (base.py:607-616) only landed 2026-06-17 (e63b21e).
Listings matched into house_sources before that — notably 9205 cian novostroyki
frozen at 2026-05-31 — never had house_id_fk mirrored back, breaking the
canonical "same-building via house_id_fk" estimator path (93% of active cian
novostroyki had NULL fk citywide).

Add data/sql/130_backfill_listings_house_id_fk.sql: deterministic source-id
backfill via house_sources (ext_source, ext_id → house_id), idempotent
(WHERE house_id_fk IS NULL), no fuzzy/address fallback. Prod (read-only):
9235/9235 target rows resolve deterministically, zero unresolvable. One-time
backlog drain; future rows linked in realtime by the e63b21e mirror.
2026-06-19 16:20:32 +05:00
99e2a5d75c feat(tradein): estimate accepts client-provided coords, skips geocode (Variant A)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
2026-06-19 14:15:02 +03:00
c2a1dc8aeb fix(tradein): parse street+house for cadastral geocode match (resolve ~60% of failing addresses from local DB)
All checks were successful
CI / changes (pull_request) Successful in 6s
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
2026-06-19 14:04:12 +03:00
ea453c3ff2 fix(tradein): remove «Практика» white-label brand (DB row + account mapping + assets)
All checks were successful
CI / openapi-codegen-check (pull_request) Has been skipped
CI / changes (pull_request) Successful in 6s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
2026-06-19 12:53:37 +03:00
80380dc32a fix(tradein): budget Cian valuation call to stop 25s estimate stalls
All checks were successful
CI / openapi-codegen-check (pull_request) Has been skipped
CI / changes (pull_request) Successful in 5s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
The Cian Valuation enrichment was the only ungated external call in
estimate_quality() — its internal curl timeout (~25s) blocks the whole
/estimate request on every cache-miss, intermittently pushing latency
past the gateway/patience window (perceived as 'сервис не считает').

Wrap it in _with_budget() (mirrors the existing Yandex-valuation guard):
on timeout it degrades to None — the same graceful path as a network
error — instead of stalling. New setting estimate_cian_valuation_timeout_s
(default 8.0s, env ESTIMATE_CIAN_VALUATION_TIMEOUT_S).
2026-06-19 12:43:28 +03:00
ee2703419b Merge pull request 'fix(estimator): #1774 Tier A admits same-building novostroyki resales (secondary-dominant gate)' (#1776) from fix/1774-tier-a-same-building-primary into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 7s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m21s
Deploy Trade-In / build-backend (push) Successful in 51s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 1m4s
Reviewed-on: #1776
2026-06-19 09:28:16 +00:00
19f740f2e9 Merge pull request 'fix(avito): de-glue house number from district in _clean_address (#1773 part)' (#1775) from fix/1773-avito-address-deglue into main
Some checks failed
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 7s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m19s
Deploy Trade-In / build-backend (push) Has been cancelled
Reviewed-on: #1775
2026-06-19 09:26:26 +00:00