From 1dc1d75cf1d77fb48a98b9a61f57646944b694f2 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Sat, 12 Sep 2026 15:44:57 +0300 Subject: [PATCH] =?UTF-8?q?feat(sber-index):=20=D0=B3=D1=80=D1=83=D0=B7?= =?UTF-8?q?=D0=B8=D0=BC=20=D1=80=D1=8F=D0=B4=20=D0=9C=D0=BE=D1=81=D0=BA?= =?UTF-8?q?=D0=BE=D0=B2=D1=81=D0=BA=D0=BE=D0=B9=20=D0=BE=D0=B1=D0=BB=D0=B0?= =?UTF-8?q?=D1=81=D1=82=D0=B8=20=D0=B7=D0=B0=D1=80=D0=B0=D0=BD=D0=B5=D0=B5?= =?UTF-8?q?,=20=D0=B4=D0=BE=20=D0=BF=D0=BE=D1=8F=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D1=80=D0=B5=D0=B3=D0=B8=D0=BE=D0=BD=D0=B0=2050?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Под задачу «регион 50 в продукт» нужна поправка на время по области. Разведка предлагала завести имя ряда в карте эстиматора — но SQL показал, что ряда в БД нет вовсе: в sber_price_index лежат ровно три города, Москва, Свердловская область и Россия. Строка в карте без загруженного ряда молча увела бы оценку на общероссийский ряд, то есть ровно в ту ошибку, от которой карта и защищает. Проверил источник живьём 12.09.2026 через прод: REF_AREA=50 отдаёт данные под именем «Московская область» на всех трёх дашбордах, глубина и свежесть те же, что у Москвы — real_estate_deals 116 месячных точек 2017-01..2026-08. Поэтому загрузку включаем СЕЙЧАС, отдельно и заранее. Ряд наполняется месяцами и задним числом не восстанавливается: начнём грузить вместе с включением региона — первые недели область будет считаться по стране. На оценку это ничего не меняет. Эстиматор берёт ряды через _SBER_REGION_SERIES, кода 50 там нет, и до его появления область в расчёт не попадает. Монитор свежести тоже молчит: SBER_REQUIRED_REGIONS и SBER_MONITORED_REGIONS считаются от карты ЭСТИМАТОРА, а не от карты загрузчика — это и закреплено тестом, чтобы связь не разъехалась при следующей правке. Тесты: 86 passed по четырём сберовским файлам, ruff чистый. Claude-Session: https://claude.ai/code/session_01NQb6WeJtagZwZnUsSjDizs --- tradein-mvp/backend/app/services/sber_index.py | 13 +++++++++++++ tradein-mvp/backend/tests/test_sber_index.py | 15 +++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/tradein-mvp/backend/app/services/sber_index.py b/tradein-mvp/backend/app/services/sber_index.py index 8331b2d2..04ce4928 100644 --- a/tradein-mvp/backend/app/services/sber_index.py +++ b/tradein-mvp/backend/app/services/sber_index.py @@ -40,6 +40,18 @@ REF_AREA codes (sberindex internal region IDs, not ОКАТО/ISO): 77 = Москва — verified 2026-05-31 brute-force against /api/sowa (region name from ref_area field of response); real_estate_deals: 2017-01 148 471 → 2026-04 309 510 руб/м². + 50 = Московская область — verified live 2026-09-12 (все три дашборда, ref_area + в ответе = «Московская область»); real_estate_deals 116 месячных точек + 2017-01..2026-08, residential_real_estate_prices 47 (2022-10..2026-08), + dinamika-tsen-obyavlenii 56 (2021-12..2026-07) — та же глубина и свежесть, + что у Москвы. + +Область заведена ЗАРАНЕЕ, до появления региона 50 в реестре regions.REGIONS. Ряд +источника наполняется месяцами и задним числом не восстанавливается, поэтому +загружать его надо начинать раньше, чем он понадобится оценщику. На саму оценку +это не влияет: estimator берёт ряды через _SBER_REGION_SERIES, кода 50 там нет, и +до его появления область в расчёт не попадает. Мониторинг свежести тоже не +затронут — SBER_REQUIRED_REGIONS считается от карты ЭСТИМАТОРА, а не отсюда. """ from __future__ import annotations @@ -71,6 +83,7 @@ SBER_REF_AREAS: dict[str, str] = { "643": "Россия", "66": "Свердловская область", "77": "Москва", + "50": "Московская область", } diff --git a/tradein-mvp/backend/tests/test_sber_index.py b/tradein-mvp/backend/tests/test_sber_index.py index ae70ad4f..6c566f37 100644 --- a/tradein-mvp/backend/tests/test_sber_index.py +++ b/tradein-mvp/backend/tests/test_sber_index.py @@ -537,3 +537,18 @@ async def test_pull_sber_indices_asking_benchmark_logged(caplog: pytest.LogCaptu assert any("115000" in record.message for record in caplog.records), ( "Benchmark log should include the latest asking index value" ) + + +def test_moscow_oblast_ref_area_is_loaded_but_not_yet_used_by_estimator() -> None: + """Область грузится заранее: ряд наполняется месяцами, задним числом не берётся. + + Одновременно проверяем, что заведение ряда НЕ включает область в оценку и НЕ + поднимает тревогу монитора свежести: обе величины считаются от карты + эстиматора (_SBER_REGION_SERIES), а не от карты загрузчика. + """ + from app.services.estimator import SBER_MONITORED_REGIONS, SBER_REQUIRED_REGIONS + from app.services.sber_index import SBER_REF_AREAS + + assert SBER_REF_AREAS["50"] == "Московская область" + assert "Московская область" not in SBER_REQUIRED_REGIONS + assert "Московская область" not in SBER_MONITORED_REGIONS -- 2.45.3