Code-review #1927 found 2 MAJOR bugs in the initial fix: 1. JOIN fan-out: objective_complex_mapping UNIQUE is (objective_complex_name, objective_group), NOT domrf_obj_id (68_schema:321) — one obj_id can map to multiple rows (same name, different group), so COUNT(*) over cm JOIN ol double-counts lots (GROUP BY collapses output rows but not dups inside the aggregate). Fixed with COUNT(DISTINCT ol.objective_lot_id). 2. Missing premise_kind: MarketMetrics._STOCK_SQL filters premise_kind='квартира'; the new SQL did not, so sold parking/storage/non-residential lots counted as sold flats (over-count). Added AND ol.premise_kind = :premise_kind. 3. Aligned the sold predicate to MarketMetrics exactly: is_sold IS TRUE OR contract_date IS NOT NULL OR LOWER(status)='продан' (Objective populates these inconsistently — OR mirrors _STOCK_SQL:285-289), not contract_date alone. Tests: added static SQL-structure guards (fan-out-safe COUNT(DISTINCT), premise_kind filter, full predicate) since mock-based API tests bypass real SQL and cannot detect fan-out; the live-DB fan-out/EXPLAIN check lives in test_phantom_columns (skipped without TEST_DATABASE_URL). Updated phantom EXPLAIN to the new SQL. Full suite: 3530 passed, 51 skipped, 0 failed. Ruff clean. |
||
|---|---|---|
| .. | ||
| api | ||
| core | ||
| models | ||
| observability | ||
| schemas | ||
| scrapers | ||
| services | ||
| templates | ||
| workers | ||
| __init__.py | ||
| main.py | ||