Audit #1871/#1926: competitor block computed flats_sold from domrf_kn_flats.status (LIKE '%прод%'/'sold'), populated in only ~0.2% of rows (99.8% NULL) -> massive undercount (~1600 units in reported case) and divergence from MarketMetrics, which counts sold via objective_lots.contract_date (100% populated for sold lots). Fix: new _SOLD_COUNT_SQL counts sold lots from objective_lots.contract_date IS NOT NULL, bridged domrf obj_id -> objective_complex_mapping.domrf_obj_id -> objective_complex_mapping.objective_complex_name == objective_lots.project_name (same 1:1 mapping pattern as _OBJECTIVE_PRICE_FALLBACK_SQL primary_price CTE). This is the exact source MarketMetrics._STOCK_SQL uses, so the two paths agree. Dropped the domrf_kn_flats.status count from _AVG_PRICE_SQL (price-only now). No schema/Pydantic field change (flats_sold/sold_pct already existed) -> codegen not needed. psycopg v3 CAST style preserved. Tests: updated mock DB ordering (+ sold-count execute), added test_competitors_flats_sold_from_contract_date (120/200 -> 60% sold) and phantom-column EXPLAIN check for _SOLD_COUNT_SQL. |
||
|---|---|---|
| .. | ||
| analysis_runs | ||
| analytics | ||
| cadastre | ||
| chat | ||
| etl | ||
| exporters | ||
| forecasting | ||
| generative | ||
| llm | ||
| photos | ||
| scrapers | ||
| site_finder | ||
| __init__.py | ||
| analytics_queries.py | ||
| analytics_refresh.py | ||
| forecast_request_cache.py | ||
| insights.py | ||
| job_settings.py | ||
| objective_etl.py | ||
| objective_sync_config.py | ||
| own_projects.py | ||
| weather_cache.py | ||