diff --git a/backend/app/services/site_finder/competitors.py b/backend/app/services/site_finder/competitors.py index 1de7bd55..e9413a1b 100644 --- a/backend/app/services/site_finder/competitors.py +++ b/backend/app/services/site_finder/competitors.py @@ -57,8 +57,14 @@ _TIME_WINDOW_MONTHS: dict[str, float] = { "last_year": 12.0, } -# site_status значения, считающиеся «активными» -_ACTIVE_STATUSES = frozenset({"sales", "construction"}) +# site_status значения, считающиеся «активными» (#1213). domrf_kn_objects.site_status +# хранит русские значения ровно как scraper берёт из siteStatus дом.рф (см. domrf_kn.py:316 +# — без перевода). Прод-аудит: 105_add_sales_started_flag.sql фильтрует по 'Строящиеся' +# (~1322 строки), partial index в 66_indexes_recommend.sql использует те же, фронтовые +# проверки MarketTab/CompetitorTable — тоже русские. Английские 'sales'/'construction' +# не совпадали никогда → у всех Competitor is_active=false и active_count=0 при любых +# данных. is_sold_out_filter сохранён как раньше — на стороне фронта. +_ACTIVE_STATUSES = frozenset({"Строящиеся"}) # #968 (949-A): радиус спатиального матча domrf↔complexes для velocity gap-fill. # 200м + tolerant-name + nearest-per-domrf → подтверждаем «тот же ЖК» И гео, И diff --git a/backend/tests/api/v1/test_parcel_competitors.py b/backend/tests/api/v1/test_parcel_competitors.py index 63ca61e4..908bdfc5 100644 --- a/backend/tests/api/v1/test_parcel_competitors.py +++ b/backend/tests/api/v1/test_parcel_competitors.py @@ -26,7 +26,7 @@ def _coord_row(lat: float = 56.838, lon: float = 60.605) -> MagicMock: def _obj_row( obj_id: int = 1, distance_m: float = 400.0, - site_status: str = "sales", + site_status: str = "Строящиеся", obj_class: str | None = "comfort", velocity: float = 5.0, flat_count: int | None = 200, @@ -148,11 +148,15 @@ def test_competitors_basic() -> None: def test_competitors_summary_calc() -> None: - """summary: total_competitors, active_count, weighted_avg_velocity корректны.""" + """summary: total_competitors, active_count, weighted_avg_velocity корректны. + + site_status — реальные русские значения как у домрф (#1213 fix). + «Строящиеся» считаются активными, «Сданные» — нет. + """ rows = [ - _obj_row(obj_id=1, site_status="sales", velocity=10.0), - _obj_row(obj_id=2, site_status="construction", velocity=6.0), - _obj_row(obj_id=3, site_status="completed", velocity=2.0), + _obj_row(obj_id=1, site_status="Строящиеся", velocity=10.0), + _obj_row(obj_id=2, site_status="Строящиеся", velocity=6.0), + _obj_row(obj_id=3, site_status="Сданные", velocity=2.0), ] db = _make_db(coord=_coord_row(), obj_rows=rows) @@ -391,11 +395,12 @@ def test_competitors_avg_price_populated() -> None: def test_competitors_is_active_flag() -> None: - """is_active=True для sales/construction, False для completed/null.""" + """is_active=True для русского 'Строящиеся' (реальная prod-форма #1213), + False для 'Сданные'/null/прочих.""" rows = [ - _obj_row(obj_id=1, site_status="sales"), - _obj_row(obj_id=2, site_status="construction"), - _obj_row(obj_id=3, site_status="completed"), + _obj_row(obj_id=1, site_status="Строящиеся"), + _obj_row(obj_id=2, site_status="Строящиеся"), + _obj_row(obj_id=3, site_status="Сданные"), ] db = _make_db(coord=_coord_row(), obj_rows=rows)