From bcb348da402844fd9c96b7c092bfbc4410670b1a Mon Sep 17 00:00:00 2001 From: bot-backend Date: Wed, 17 Jun 2026 21:22:53 +0300 Subject: [PATCH] fix(leads): replace ::interval cast with make_interval (psycopg v3 trap) (#1383 follow-up) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (:bind || ' months')::interval is a psycopg v3 SyntaxError — the driver sees '::' immediately after the bind placeholder token and chokes. Replace all 6 occurrences (admin_leads.py + analytics_queries.py) with make_interval(months => :bind) which is unambiguous to the parser and semantically identical. --- backend/app/api/v1/admin_leads.py | 2 +- backend/app/services/analytics_queries.py | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/backend/app/api/v1/admin_leads.py b/backend/app/api/v1/admin_leads.py index c5a7a89d..f23b839c 100644 --- a/backend/app/api/v1/admin_leads.py +++ b/backend/app/api/v1/admin_leads.py @@ -138,7 +138,7 @@ def leads_stats( WITH window_leads AS ( SELECT * FROM prinzip_leads - WHERE created_at >= NOW() - (:m || ' months')::interval + WHERE created_at >= NOW() - make_interval(months => :m) ) SELECT (SELECT COUNT(*) FROM prinzip_leads) AS leads_total, diff --git a/backend/app/services/analytics_queries.py b/backend/app/services/analytics_queries.py index b542ae66..cd368a89 100644 --- a/backend/app/services/analytics_queries.py +++ b/backend/app/services/analytics_queries.py @@ -184,8 +184,7 @@ def quartirography(db: Session, source: str, region_id: int = 66) -> list[dict[s -- ('2025-07-01' расширял «recent»-окно каждую неделю по мере -- доливки ETL новых report_months → перекос в сторону всё -- более длинной истории). Тот же фикс, что #1203 и _BUCKET_SQL. - AND period_start_date >= NOW() - - (:months_window || ' months')::INTERVAL + AND period_start_date >= NOW() - make_interval(months => :months_window) ), bucketed AS ( SELECT CASE @@ -1169,7 +1168,7 @@ def prinzip_funnel_monthly(db: Session, months: int = 24) -> list[dict[str, Any] """ SELECT month, source, leads, engaged, converted, conv_pct FROM prinzip_funnel_monthly - WHERE month >= (CURRENT_DATE - (:months || ' months')::interval)::date + WHERE month >= (CURRENT_DATE - make_interval(months => :months))::date ORDER BY month DESC, leads DESC """ ), @@ -1203,7 +1202,7 @@ def prinzip_funnel_by_source(db: Session, months: int = 12) -> list[dict[str, An SUM(converted) AS converted, ROUND(100.0 * SUM(converted) / NULLIF(SUM(leads), 0), 2) AS conv_pct FROM prinzip_funnel_monthly - WHERE month >= (CURRENT_DATE - (:months || ' months')::interval)::date + WHERE month >= (CURRENT_DATE - make_interval(months => :months))::date GROUP BY source ORDER BY leads DESC """ @@ -1364,8 +1363,7 @@ _BUCKET_SQL = text( AND deal_count > 0 AND (area / deal_count) BETWEEN 15 AND 200 AND price_per_sqm BETWEEN 30000 AND 1000000 - AND period_start_date >= NOW() - - (:months_window || ' months')::INTERVAL + AND period_start_date >= NOW() - make_interval(months => :months_window) ), bucketed AS ( SELECT CASE @@ -1995,7 +1993,7 @@ def _elasticity_coef( {where_district} {where_class} AND crm.deals_total_avg_price_thousand_rub_per_m2 > 0 - AND crm.report_month >= NOW() - (:ew || ' months')::interval + AND crm.report_month >= NOW() - make_interval(months => :ew) ) SELECT regr_slope(y, x) AS slope, @@ -2086,7 +2084,7 @@ def _elasticity_per_bucket_coef( {where_class} AND crm.deals_total_count > 0 AND crm.deals_total_avg_price_thousand_rub_per_m2 > 0 - AND crm.report_month >= NOW() - (:ew || ' months')::interval + AND crm.report_month >= NOW() - make_interval(months => :ew) ) SELECT bucket, regr_slope(y, x) AS slope,