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

Merged
lekss361 merged 1 commit from fix/velocity-cast-window-interval into main 2026-05-15 06:46:01 +00:00
lekss361 commented 2026-05-15 06:41:36 +00:00 (Migrated from github.com)

Bug

После merge PR #158 e2e velocity всё ещё null для cad 66:41:0204016:10. Backend logs:

psycopg.errors.SyntaxError: syntax error at or near ":"
LINE 18: WHERE crm.report_month >= (CURRENT_DATE - :window_in...
                                                    ^
velocity: objective sales query failed

Root cause

Идентичный bug как PR #152 (:weights::jsonb): SQLAlchemy text() parser confuses :window_interval (named param) + ::interval (cast operator). Psycopg видит literal :window_interval → syntax error → caught by velocity SAVEPOINT → silent return None.

Fix

:window_interval::intervalCAST(:window_interval AS interval) (velocity.py:189 + :302).

Verify

grep ':[a-z_]*::' backend/app/services/{site_finder/velocity,analytics_queries}.py
# expect: no output

Test after merge

curl POST /api/v1/parcels/66:41:0204016:10/analyze?profile_user_id=admin | jq .velocity
# expect: NOT null, competitors_count=3, months_observed=5-6
## Bug После merge PR #158 e2e velocity всё ещё **null** для cad 66:41:0204016:10. Backend logs: ``` psycopg.errors.SyntaxError: syntax error at or near ":" LINE 18: WHERE crm.report_month >= (CURRENT_DATE - :window_in... ^ velocity: objective sales query failed ``` ## Root cause **Идентичный bug как PR #152** (`:weights::jsonb`): SQLAlchemy text() parser confuses `:window_interval` (named param) + `::interval` (cast operator). Psycopg видит literal `:window_interval` → syntax error → caught by velocity SAVEPOINT → silent return None. ## Fix `:window_interval::interval` → `CAST(:window_interval AS interval)` (velocity.py:189 + :302). ## Verify ```bash grep ':[a-z_]*::' backend/app/services/{site_finder/velocity,analytics_queries}.py # expect: no output ``` ## Test after merge ```bash curl POST /api/v1/parcels/66:41:0204016:10/analyze?profile_user_id=admin | jq .velocity # expect: NOT null, competitors_count=3, months_observed=5-6 ```
lekss361 commented 2026-05-15 06:45:45 +00:00 (Migrated from github.com)

Final review (SHA a572cf3, CI )

Cross-checked агентом — clean recurrence-of-#152 fix.

Verified by agent

Оба :window_interval::interval заменены на CAST(:window_interval AS interval) (velocity.py:189 + :302) — identical pattern PR #152
Bind dicts (lines 196, 315) корректно передают "window_interval": f"{months_window} months"
Grep clean: :[a-zA-Z_]\w*:: в velocity.py + analytics_queries.py → no matches
Codebase-wide sweep: code search ::interval, ::jsonb, ::geometry в *.py — zero hits. Нет других latent recurrences.
SQL semantics: CAST(x AS interval) standard-form эквивалент x::interval — no behavioral change

Минор

PR body даже включает verification grep command — хороший pattern.

approve merge

## Final review (SHA `a572cf3`, CI ✅) Cross-checked агентом — clean recurrence-of-#152 fix. ### Verified by agent ✅ **Оба `:window_interval::interval`** заменены на `CAST(:window_interval AS interval)` (velocity.py:189 + :302) — identical pattern PR #152 ✅ **Bind dicts** (lines 196, 315) корректно передают `"window_interval": f"{months_window} months"` ✅ **Grep clean**: `:[a-zA-Z_]\w*::` в velocity.py + analytics_queries.py → no matches ✅ **Codebase-wide sweep**: code search `::interval`, `::jsonb`, `::geometry` в *.py — zero hits. Нет других latent recurrences. ✅ **SQL semantics**: `CAST(x AS interval)` standard-form эквивалент `x::interval` — no behavioral change ### Минор PR body даже включает verification grep command — хороший pattern. approve merge
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#160
No description provided.