Add build_site_finder_report (orchestrator.py): computes the §9.x layers (market metrics, supply layers, future-supply pressure, demand/supply forecast, scenarios, score card, special indices, recommendation overlay) with their heterogeneous signatures and feeds the PURE assemble_report → §22 SiteFinderReport. Default segment = modal competitor class; each §9.x call _safe_call-wrapped (graceful). Standalone — no endpoint/Celery/persistence (that is 3b). Prod ground-truth of the orchestrator surfaced a false-BUY bug: future_supply (compute_future_supply_pressure) read the mixed-vocab persisted view v_supply_layers_latest by a SCALAR admin district_name, missing all Layer-1 micro-keyed rows → admin parcel (Кировский) got supply=0 → false +1.0 deficit → 'Строить: недонасыщен' headline despite ~45k competing units. Fix: resolve admin→micros, filter district_name = ANY(CAST(:names AS text[])) where names = micros (L1) + admin (L2/L3), with :has_district EKB-wide guard (extends PR #1054's resolver to the persisted-view path it missed). future_supply is the only v_supply_layers_latest consumer on the forecast path (verified). Prod after: Кировский supply 0→~42953, deficit +1.0→−1.0 (honest oversupply), MOI 0→116.6, false-BUY headline gone, overall 0.734→0.42. 80 module tests pass (signature-trap + resolver-regression guards genuine); ruff clean. Refs #961 #969. |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| best_layouts.py | ||
| cadastre_fetch.py | ||
| competitors.py | ||
| custom_pois.py | ||
| district_resolver.py | ||
| filters.py | ||
| future_supply.py | ||
| gate_verdict.py | ||
| layout_signature.py | ||
| layout_velocity_refresh.py | ||
| macro.py | ||
| market_metrics.py | ||
| noise_loader.py | ||
| parser.py | ||
| poi_loader.py | ||
| poi_score.py | ||
| pzz_loader.py | ||
| quarter_dump_lookup.py | ||
| quarter_price_index_refresh.py | ||
| quarter_price_refresh.py | ||
| scorer.py | ||
| supply_layers.py | ||
| velocity.py | ||
| weight_profiles.py | ||