fix(velocity): :window_interval::interval cast syntax — same bug as PR #152 (#160)

SQLAlchemy text() parser confuses ':window_interval' (named param) followed
by '::interval' (cast operator) — exactly как было в PR #152 с :weights::jsonb.

Result: psycopg видит literal ':window_interval' в SQL → syntax error →
exception caught by velocity catch → return None → UI shows null.

## Fix

':window_interval::interval' → 'CAST(:window_interval AS interval)' (2 мест:
sales_rows query + _get_ekb_median percentile).

Pre-push code-reviewer должен был catch — добавим в feedback что для каждого
text() SQL grep ':[a-z]*::' before push.

Refs: PR #158 deploy verify, e2e velocity = null root cause

Co-authored-by: lekss361 <claudestars@proton.me>
This commit is contained in:
lekss361 2026-05-15 09:46:01 +03:00 committed by GitHub
parent 8fa1d005fd
commit 46584d7c75
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -186,7 +186,7 @@ def compute_velocity(
FROM objective_corpus_room_month crm
JOIN mapped m
ON m.objective_complex_name = crm.project_name
WHERE crm.report_month >= (CURRENT_DATE - :window_interval::interval)
WHERE crm.report_month >= (CURRENT_DATE - CAST(:window_interval AS interval))
AND crm.deals_total_count > 0
GROUP BY m.obj_id
"""
@ -299,7 +299,7 @@ def _get_ekb_median(db: Session, months_window: int = 6) -> float | None:
deals_total_count * 45.0)) AS total_sqm,
COUNT(DISTINCT report_month) AS months_data
FROM objective_corpus_room_month
WHERE report_month >= (CURRENT_DATE - :window_interval::interval)
WHERE report_month >= (CURRENT_DATE - CAST(:window_interval AS interval))
AND deals_total_count > 0
GROUP BY project_name
HAVING COUNT(DISTINCT report_month) >= 3