kamau1 commited on
Commit
c54345d
·
1 Parent(s): 5ef066f

fix(sqlalchemy): replace deprecated subquery() usages with select().scalar_subquery() across services to eliminate warnings

Browse files
docs/devlogs/server/runtimeerror.txt CHANGED
@@ -1,113 +1,55 @@
1
- ===== Application Startup at 2025-12-08 12:51:08 =====
2
 
3
- Traceback (most recent call last):
4
- File "/usr/local/bin/uvicorn", line 8, in <module>
5
- sys.exit(main())
6
- ^^^^^^
7
- File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1485, in __call__
8
- return self.main(*args, **kwargs)
9
- ^^^^^^^^^^^^^^^^^^^^^^^^^^
10
- File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1406, in main
11
- rv = self.invoke(ctx)
12
- ^^^^^^^^^^^^^^^^
13
- File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1269, in invoke
14
- return ctx.invoke(self.callback, **ctx.params)
15
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16
- File "/usr/local/lib/python3.11/site-packages/click/core.py", line 824, in invoke
17
- return callback(*args, **kwargs)
18
- ^^^^^^^^^^^^^^^^^^^^^^^^^
19
- File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 416, in main
20
- run(
21
- File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 587, in run
22
- server.run()
23
- File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 61, in run
24
- return asyncio.run(self.serve(sockets=sockets))
25
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26
- File "/usr/local/lib/python3.11/asyncio/runners.py", line 190, in run
27
- return runner.run(main)
28
- ^^^^^^^^^^^^^^^^
29
- File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run
30
- return self._loop.run_until_complete(task)
31
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32
- File "uvloop/loop.pyx", line 1518, in uvloop.loop.Loop.run_until_complete
33
- File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 68, in serve
34
- config.load()
35
- File "/usr/local/lib/python3.11/site-packages/uvicorn/config.py", line 467, in load
36
- self.loaded_app = import_from_string(self.app)
37
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
38
- File "/usr/local/lib/python3.11/site-packages/uvicorn/importer.py", line 21, in import_from_string
39
- module = importlib.import_module(module_str)
40
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
41
- File "/usr/local/lib/python3.11/importlib/__init__.py", line 126, in import_module
42
- return _bootstrap._gcd_import(name[level:], package, level)
43
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44
- File "<frozen importlib._bootstrap>", line 1204, in _gcd_import
45
- File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
46
- File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
47
- File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
48
- File "<frozen importlib._bootstrap_external>", line 940, in exec_module
49
- File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
50
- File "/app/src/app/main.py", line 142, in <module>
51
- from app.api.v1.router import api_router
52
- File "/app/src/app/api/v1/router.py", line 5, in <module>
53
- from app.api.v1 import (
54
- File "/app/src/app/api/v1/projects.py", line 111, in <module>
55
- planned_start_from: Optional[date] = Query(None),
56
- ^^^^
57
- NameError: name 'date' is not defined
58
- Traceback (most recent call last):
59
- File "/usr/local/bin/uvicorn", line 8, in <module>
60
- sys.exit(main())
61
- ^^^^^^
62
- File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1485, in __call__
63
- return self.main(*args, **kwargs)
64
- ^^^^^^^^^^^^^^^^^^^^^^^^^^
65
- File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1406, in main
66
- rv = self.invoke(ctx)
67
- ^^^^^^^^^^^^^^^^
68
- File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1269, in invoke
69
- return ctx.invoke(self.callback, **ctx.params)
70
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
71
- File "/usr/local/lib/python3.11/site-packages/click/core.py", line 824, in invoke
72
- return callback(*args, **kwargs)
73
- ^^^^^^^^^^^^^^^^^^^^^^^^^
74
- File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 416, in main
75
- run(
76
- File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 587, in run
77
- server.run()
78
- File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 61, in run
79
- return asyncio.run(self.serve(sockets=sockets))
80
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
81
- File "/usr/local/lib/python3.11/asyncio/runners.py", line 190, in run
82
- return runner.run(main)
83
- ^^^^^^^^^^^^^^^^
84
- File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run
85
- return self._loop.run_until_complete(task)
86
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
87
- File "uvloop/loop.pyx", line 1518, in uvloop.loop.Loop.run_until_complete
88
- File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 68, in serve
89
- config.load()
90
- File "/usr/local/lib/python3.11/site-packages/uvicorn/config.py", line 467, in load
91
- self.loaded_app = import_from_string(self.app)
92
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
93
- File "/usr/local/lib/python3.11/site-packages/uvicorn/importer.py", line 21, in import_from_string
94
- module = importlib.import_module(module_str)
95
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
96
- File "/usr/local/lib/python3.11/importlib/__init__.py", line 126, in import_module
97
- return _bootstrap._gcd_import(name[level:], package, level)
98
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
99
- File "<frozen importlib._bootstrap>", line 1204, in _gcd_import
100
- File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
101
- File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
102
- File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
103
- File "<frozen importlib._bootstrap_external>", line 940, in exec_module
104
- File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
105
- File "/app/src/app/main.py", line 142, in <module>
106
- from app.api.v1.router import api_router
107
- File "/app/src/app/api/v1/router.py", line 5, in <module>
108
- from app.api.v1 import (
109
- File "/app/src/app/api/v1/projects.py", line 111, in <module>
110
- planned_start_from: Optional[date] = Query(None),
111
- ^^^^
112
- NameError: name 'date' is not defined
113
-
 
1
+ ===== Application Startup at 2025-12-08 13:11:53 =====
2
 
3
+ INFO: 2025-12-08T13:12:13 - app.main: ============================================================
4
+ INFO: Started server process [7]
5
+ INFO: 2025-12-08T13:12:13 - app.main: 🚀 SwiftOps API v1.0.0 | PRODUCTION
6
+ INFO: Waiting for application startup.
7
+ INFO: 2025-12-08T13:12:13 - app.main: 📊 Dashboard: Enabled
8
+ INFO: 2025-12-08T13:12:13 - app.main: ============================================================
9
+ INFO: 2025-12-08T13:12:13 - app.main: 📦 Database:
10
+ INFO: 2025-12-08T13:12:13 - app.main: ✓ Connected | 45 tables | 6 users
11
+ INFO: 2025-12-08T13:12:13 - app.main: 💾 Cache & Sessions:
12
+ INFO: 2025-12-08T13:12:14 - app.services.otp_service: ✅ OTP Service initialized with Redis storage
13
+ INFO: 2025-12-08T13:12:14 - app.main: ✓ Redis: Connected
14
+ INFO: 2025-12-08T13:12:14 - app.main: 🔌 External Services:
15
+ INFO: 2025-12-08T13:12:15 - app.main: ✓ Cloudinary: Connected
16
+ INFO: 2025-12-08T13:12:15 - app.main: ✓ Resend: Configured
17
+ INFO: 2025-12-08T13:12:15 - app.main: WASender: Disconnected
18
+ INFO: 2025-12-08T13:12:15 - app.main: ✓ Supabase: Connected | 6 buckets
19
+ INFO: 2025-12-08T13:12:15 - app.main: ============================================================
20
+ INFO: 2025-12-08T13:12:15 - app.main: ✅ Startup complete | Ready to serve requests
21
+ INFO: 2025-12-08T13:12:15 - app.main: ============================================================
22
+ INFO: Application startup complete.
23
+ INFO: Uvicorn running on http://0.0.0.0:7860 (Press CTRL+C to quit)
24
+ INFO: 10.16.37.13:39871 - "GET /health HTTP/1.1" 200 OK
25
+ INFO: 10.16.13.79:21557 - "GET /health HTTP/1.1" 200 OK
26
+ INFO: 10.16.37.13:15177 - "GET /health HTTP/1.1" 200 OK
27
+ INFO: 2025-12-08T13:12:39 - app.api.deps: Checking active user: 43b778b0-2062-4724-abbb-916a4835a9b0, is_active: True, type: <class 'bool'>
28
+ INFO: 2025-12-08T13:12:39 - app.api.deps: User 43b778b0-2062-4724-abbb-916a4835a9b0 is active - proceeding
29
+ INFO: 10.16.37.13:15177 - "GET /api/v1/auth/me HTTP/1.1" 200 OK
30
+ INFO: 2025-12-08T13:12:39 - app.api.deps: Checking active user: 43b778b0-2062-4724-abbb-916a4835a9b0, is_active: True, type: <class 'bool'>
31
+ INFO: 2025-12-08T13:12:39 - app.api.deps: User 43b778b0-2062-4724-abbb-916a4835a9b0 is active - proceeding
32
+ INFO: 10.16.37.13:15177 - "GET /api/v1/auth/me/preferences/available-apps HTTP/1.1" 200 OK
33
+ INFO: 2025-12-08T13:12:39 - app.api.deps: Checking active user: 43b778b0-2062-4724-abbb-916a4835a9b0, is_active: True, type: <class 'bool'>
34
+ INFO: 2025-12-08T13:12:39 - app.api.deps: User 43b778b0-2062-4724-abbb-916a4835a9b0 is active - proceeding
35
+ INFO: 10.16.13.79:49016 - "GET /api/v1/auth/me/preferences HTTP/1.1" 200 OK
36
+ INFO: 2025-12-08T13:12:40 - app.api.deps: Checking active user: 43b778b0-2062-4724-abbb-916a4835a9b0, is_active: True, type: <class 'bool'>
37
+ INFO: 2025-12-08T13:12:40 - app.api.deps: User 43b778b0-2062-4724-abbb-916a4835a9b0 is active - proceeding
38
+ INFO: 10.16.13.79:49016 - "GET /api/v1/analytics/user/overview?limit=50 HTTP/1.1" 200 OK
39
+ INFO: 2025-12-08T13:12:41 - app.api.deps: Checking active user: 43b778b0-2062-4724-abbb-916a4835a9b0, is_active: True, type: <class 'bool'>
40
+ INFO: 2025-12-08T13:12:41 - app.api.deps: User 43b778b0-2062-4724-abbb-916a4835a9b0 is active - proceeding
41
+ INFO: 2025-12-08T13:12:41 - app.services.project_service: Listed 1 projects (total: 1) for user 43b778b0-2062-4724-abbb-916a4835a9b0
42
+ INFO: 10.16.13.79:49016 - "GET /api/v1/projects?page=1&per_page=100&status=active HTTP/1.1" 200 OK
43
+ INFO: 2025-12-08T13:12:45 - app.api.deps: Checking active user: 43b778b0-2062-4724-abbb-916a4835a9b0, is_active: True, type: <class 'bool'>
44
+ INFO: 2025-12-08T13:12:45 - app.api.deps: User 43b778b0-2062-4724-abbb-916a4835a9b0 is active - proceeding
45
+ INFO: 2025-12-08T13:12:45 - app.services.dashboard_service: Dashboard cache MISS for project 0ade6bd1-e492-4e25-b681-59f42058d29a, user 43b778b0-2062-4724-abbb-916a4835a9b0 - building fresh data
46
+ INFO: 2025-12-08T13:12:45 - app.services.dashboard_service: Built and cached dashboard for project 0ade6bd1-e492-4e25-b681-59f42058d29a
47
+ INFO: 10.16.13.79:1190 - "GET /api/v1/projects/0ade6bd1-e492-4e25-b681-59f42058d29a/dashboard HTTP/1.1" 200 OK
48
+ INFO: 2025-12-08T13:12:47 - app.api.deps: Checking active user: 43b778b0-2062-4724-abbb-916a4835a9b0, is_active: True, type: <class 'bool'>
49
+ INFO: 2025-12-08T13:12:47 - app.api.deps: User 43b778b0-2062-4724-abbb-916a4835a9b0 is active - proceeding
50
+ INFO: 10.16.13.79:1190 - "GET /api/v1/projects/0ade6bd1-e492-4e25-b681-59f42058d29a/regions HTTP/1.1" 200 OK
51
+ INFO: 10.16.37.13:61170 - "GET /api/v1/tickets/stats?project_id=0ade6bd1-e492-4e25-b681-59f42058d29a&status=open HTTP/1.1" 200 OK
52
+ /app/src/app/services/ticket_service.py:792: SAWarning: Coercing Subquery object into a select() for use in IN(); please pass a select() construct explicitly
53
+ query = query.filter(Ticket.project_id.in_(team_projects))
54
+ INFO: 2025-12-08T13:12:48 - app.services.ticket_service: Listed 6 tickets (total: 6) for user 43b778b0-2062-4724-abbb-916a4835a9b0
55
+ INFO: 10.16.37.13:1625 - "GET /api/v1/tickets?project_id=0ade6bd1-e492-4e25-b681-59f42058d29a&page=1&page_size=50&status=open HTTP/1.1" 200 OK
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/app/api/v1/map.py CHANGED
@@ -9,6 +9,7 @@ from typing import List, Optional
9
  from uuid import UUID
10
  from fastapi import APIRouter, Depends, HTTPException, Query, status
11
  from sqlalchemy.orm import Session
 
12
 
13
  from app.api.deps import get_db, get_current_user
14
  from app.models.user import User
@@ -241,10 +242,10 @@ async def get_agent_journey_history(
241
  can_view = True
242
  else:
243
  # Check if current user is a manager in any project where target user is a team member
244
- target_projects = db.query(ProjectTeam.project_id).filter(
245
  ProjectTeam.user_id == user_id,
246
  ProjectTeam.deleted_at.is_(None)
247
- ).subquery()
248
 
249
  manager_membership = db.query(ProjectTeam).filter(
250
  ProjectTeam.user_id == current_user.id,
 
9
  from uuid import UUID
10
  from fastapi import APIRouter, Depends, HTTPException, Query, status
11
  from sqlalchemy.orm import Session
12
+ from sqlalchemy import select
13
 
14
  from app.api.deps import get_db, get_current_user
15
  from app.models.user import User
 
242
  can_view = True
243
  else:
244
  # Check if current user is a manager in any project where target user is a team member
245
+ target_projects = select(ProjectTeam.project_id).filter(
246
  ProjectTeam.user_id == user_id,
247
  ProjectTeam.deleted_at.is_(None)
248
+ ).scalar_subquery()
249
 
250
  manager_membership = db.query(ProjectTeam).filter(
251
  ProjectTeam.user_id == current_user.id,
src/app/services/ticket_service.py CHANGED
@@ -20,7 +20,7 @@ Authorization:
20
  - client_admin: View their organization's tickets
21
  """
22
  from sqlalchemy.orm import Session, joinedload
23
- from sqlalchemy import and_, or_, func, desc, case
24
  from fastapi import HTTPException, status
25
  from typing import List, Tuple, Optional
26
  from uuid import UUID
@@ -687,11 +687,11 @@ class TicketService(BaseFilterService):
687
  from app.models.project_team import ProjectTeam
688
 
689
  # Get projects the field agent is assigned to
690
- team_projects = db.query(ProjectTeam.project_id).filter(
691
  ProjectTeam.user_id == current_user.id,
692
  ProjectTeam.deleted_at.is_(None),
693
  ProjectTeam.removed_at.is_(None)
694
- ).subquery()
695
 
696
  query = query.filter(Ticket.project_id.in_(team_projects))
697
  else:
@@ -784,11 +784,11 @@ class TicketService(BaseFilterService):
784
  query = query.filter(Project.client_id == current_user.client_id)
785
  elif current_user.role in [AppRole.FIELD_AGENT.value, AppRole.SALES_AGENT.value]:
786
  from app.models.project_team import ProjectTeam
787
- team_projects = db.query(ProjectTeam.project_id).filter(
788
  ProjectTeam.user_id == current_user.id,
789
  ProjectTeam.deleted_at.is_(None),
790
  ProjectTeam.removed_at.is_(None)
791
- ).subquery()
792
  query = query.filter(Ticket.project_id.in_(team_projects))
793
  else:
794
  raise HTTPException(
 
20
  - client_admin: View their organization's tickets
21
  """
22
  from sqlalchemy.orm import Session, joinedload
23
+ from sqlalchemy import and_, or_, func, desc, case, select
24
  from fastapi import HTTPException, status
25
  from typing import List, Tuple, Optional
26
  from uuid import UUID
 
687
  from app.models.project_team import ProjectTeam
688
 
689
  # Get projects the field agent is assigned to
690
+ team_projects = select(ProjectTeam.project_id).filter(
691
  ProjectTeam.user_id == current_user.id,
692
  ProjectTeam.deleted_at.is_(None),
693
  ProjectTeam.removed_at.is_(None)
694
+ ).scalar_subquery()
695
 
696
  query = query.filter(Ticket.project_id.in_(team_projects))
697
  else:
 
784
  query = query.filter(Project.client_id == current_user.client_id)
785
  elif current_user.role in [AppRole.FIELD_AGENT.value, AppRole.SALES_AGENT.value]:
786
  from app.models.project_team import ProjectTeam
787
+ team_projects = select(ProjectTeam.project_id).filter(
788
  ProjectTeam.user_id == current_user.id,
789
  ProjectTeam.deleted_at.is_(None),
790
  ProjectTeam.removed_at.is_(None)
791
+ ).scalar_subquery()
792
  query = query.filter(Ticket.project_id.in_(team_projects))
793
  else:
794
  raise HTTPException(