REOPENED. L3 future-supply rows are computed per (district_name, dev_group_name) but dev_group_name was never a key column — only embedded in method text. With complex_id/obj_class NULL for L3, every dev_group of a district collapsed to one upsert key → ~95.6% loss. Ground-truth (Академический, prod): should be 13,808 units / 15 dev_groups / 54 objects; only 1 row / 607 units survived. Migration 128: ADD COLUMN supply_layers.dev_group_name TEXT + rebuild uq_supply_layers_logical to (layer, district_name, complex_id, obj_class, dev_group_name, source, snapshot_date) NULLS NOT DISTINCT (L1/L2 dev_group_name NULL stays transparent → their dedup unchanged; L3 distinct groups no longer collapse). Dry-run-verified vs prod catalog (applies clean, ROLLBACK clean). Worker: SupplyLayerRow gains dev_group_name (L1/L2=None, L3=group); _UPSERT_SQL adds it to INSERT/VALUES (CAST(:dev_group_name AS text)) + ON CONFLICT (key col, not in DO UPDATE SET). Service+worker regression tests assert same-district/ different-dev_group → distinct keys (no collapse). 234 supply tests pass. Deploy applies migration before container restart; collapsed data self-heals on next supply_layers_refresh. Verification = prod re-measure post-deploy. Refs #970 |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| best_layouts.py | ||
| cadastre_fetch.py | ||
| competitors.py | ||
| custom_pois.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 | ||