gendesign/tradein-mvp/backend
bot-backend 18b22c9df8
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
fix(tradein/v2): canonical sources_used — kill «ИСТОЧНИКОВ X/7» POST↔GET desync
Единый helper estimator._canonical_sources(analogs, valuation_flags) — источник
правды для sources_used, зовётся идентично на POST (estimate_quality) и
GET-rehydrate (get_estimate) из ТЕХ ЖЕ persisted analogs + оценочных флагов.

Root cause: три расходящиеся деривации — POST брал sources_used из top-N
analogs_lots, GET возвращал persisted-колонку (радиусный набор + quarter_index),
source_counts на GET считался из persisted analogs. Источник (напр. cian) мог
попасть в source_counts, но не в sources_used → счётчик «X/7» прыгал 4→5 между
POST-ответом и reload(GET).

- sources_used = {листинговые из persisted analogs} ∪ {avito_imv/yandex_valuation/
  cian_valuation}. Детерминированно отсортирован.
- source_counts на POST теперь тоже из analogs_lots (не полной metadata-выборки)
  → инвариант source_counts.keys() ⊆ sources_used на POST и GET.
- POST персистит канонический sources_used в колонку (history/PDF консистентны для
  новых строк); GET рехайдрейтит его же helper'ом — чинит и СТАРЫЕ строки
  (листинговая часть пересобирается из analogs, quarter_index/радиусный шум
  отбрасывается фильтром оценочных флагов).

Оценочные флаги персистятся в колонке sources_used и читаются оттуда на GET —
реконструкция не требуется.

Repro 451de30b: до — sources_used=[avito,avito_imv,domklik,yandex], source_counts
имеет cian (не в sources_used); после — sources_used=[avito,avito_imv,cian,
domklik,yandex] (5/7), counts.keys() ⊆ sources_used.

Part of #2087 (M1).
2026-07-02 17:22:20 +03:00
..
app fix(tradein/v2): canonical sources_used — kill «ИСТОЧНИКОВ X/7» POST↔GET desync 2026-07-02 17:22:20 +03:00
data/sql feat(market): contract views market.v_* over producer tables (#2130) 2026-07-02 14:02:59 +00:00
scripts feat(tradein/domclick): local-runner + ingest tooling → main (split from parked Layer-B) 2026-06-28 10:26:52 +03:00
tests fix(tradein/v2): canonical sources_used — kill «ИСТОЧНИКОВ X/7» POST↔GET desync 2026-07-02 17:22:20 +03:00
.dockerignore feat: add tradein-mvp subproject (Trade-In Estimator под /trade-in) 2026-05-21 00:25:39 +03:00
Dockerfile fix(tradein): гарантировать lxml в backend-образе — bust кэша uv sync + assert import (#2061) 2026-06-28 15:16:04 +00:00
pyproject.toml chore(scraper-kit): scaffold internal package + uv workspace, build-safe (#2128) 2026-07-02 14:06:07 +00:00