gendesign/backend/tests/services
Light1YT 888c225029 fix(tradein): per-bucket velocity formula + realistic срок продажи (#574)
Root causes fixed:

1. Bug_Velocity_Mix_Static: bucket_v = market_vel_pm × share/100 made all
   bucket velocities proportional to market share, so Σ bucket_v ≡ market_vel_pm
   regardless of mix. Moving a slider changed share_pct but not the aggregate
   срок продажи (velocity numerator and denominator both scaled with share).

2. Bug_Velocity_Unrealistic: rosreestr fallback used city-wide total_deals
   (region 66, ~3815 deals/24 mo = 159 кв/мес) divided by district-only
   competitors_weighted (~5-10 ЖК), yielding 16-32 кв/мес per project
   and срок ~0.7 мес instead of realistic months.

Changes:
- Add _n_active_zhk_region(db, region_code): COUNT DISTINCT active ЖК
  in the full region — used as city-wide denominator for rosreestr fallback.
  Lazy-cached to avoid duplicate DB round-trips.
- Add _velocity_baseline_per_bucket(db, ...): query objective_corpus_room_month
  grouped by room_bucket (same mapping as _elasticity_per_bucket_coef) to get
  per-bucket median velocity. Returns None when < 3 observations.
- Replace static bucket_market_velocities computation in recommend_mix:
  - Objective path: use _velocity_baseline_per_bucket per-bucket medians.
    Each bucket is an independent constant (not share-derived).
  - Rosreestr fallback: bucket_deals / months / N_active_region.
    N_active_region (200-400+ for EKB) replaces competitors_district (5-10),
    giving realistic per-project velocities (~0.1-0.6 кв/мес per bucket).
- Add bucket["velocity_source"] = "objective_per_bucket" | "rosreestr_fallback"
  for transparency in API response and UI warnings.
- Add scope["n_active_region"] for debugging.
- Add 19 unit tests in test_recommend_mix_velocity.py covering both bugs.
2026-05-28 20:19:20 +05:00
..
cadastre fix(#265 review): CRS 3857→4326 + stable zone_id hash + rename 102 + tx comment 2026-05-17 10:45:52 +03:00
scrapers feat(22d): domrf_catalog_object scraper — fill ~25 NULL kn_objects cols from SSR __NEXT_DATA__ (#335) 2026-05-17 21:26:22 +00:00
site_finder fix(sf-09): capacity-aware redistribute (round 2) — bounded + correct invariant 2026-05-17 15:30:50 +03:00
__init__.py feat(cadastre): bulk_harvest worker + grid-walker + admin API (#168 PR3/5) (#171) 2026-05-15 13:31:32 +03:00
test_cadastre_bulk.py test(deploy): validate Forgejo Actions end-to-end flow (#189) 2026-05-15 21:55:04 +00:00
test_ekburg_permits.py fix(#242): ekburg_permits SSL — verify=False для CA Минцифры РФ 2026-05-17 08:57:42 +03:00
test_nspd_denorm.py feat(nspd): denorm nspd_parcels + nspd_buildings tables (#94 PR3 of 4) 2026-05-16 20:20:03 +03:00
test_objective_backfill.py feat(etl): objective_complex_mapping backfill via pg_trgm (#203) (#214) 2026-05-16 12:47:09 +00:00
test_quarter_dump_lookup.py Merge remote-tracking branch 'forgejo/main' into fix/234-nspd-harvest-eta-badge 2026-05-17 09:19:12 +03:00
test_recommend_mix_velocity.py fix(tradein): per-bucket velocity formula + realistic срок продажи (#574) 2026-05-28 20:19:20 +05:00