vanitha commited on
Commit
b707bc9
·
1 Parent(s): d4c0c14

dashboard layout and widget

Browse files
app/dashboard/constants.py CHANGED
@@ -30,7 +30,7 @@ class DashboardStatus(str, Enum):
30
 
31
  # MongoDB Collections
32
  DASHBOARD_USER_LAYOUTS_COLLECTION = "dashboard_user_layouts"
33
- WIDGET_CATALOG_COLLECTION = "bloom_dashboard_widgets"
34
 
35
  # Chart Widget IDs and Handlers
36
  CHART_WIDGET_IDS = {
 
30
 
31
  # MongoDB Collections
32
  DASHBOARD_USER_LAYOUTS_COLLECTION = "dashboard_user_layouts"
33
+ WIDGET_CATALOG_COLLECTION = "dashboard_widgets"
34
 
35
  # Chart Widget IDs and Handlers
36
  CHART_WIDGET_IDS = {
app/dashboard/controllers/dashboard_router.py CHANGED
@@ -26,14 +26,14 @@ async def get_dashboard_layout(
26
  _: TokenUser = Depends(require_scm_permission("dashboard", "view"))
27
  ):
28
  """
29
- Get dashboard layout for merchant+role+associate combination.
30
  Returns layout or empty with status true if no layout exists.
31
  """
32
  try:
33
  layout_doc = await DashboardService.get_layout(
34
  merchant_id=current_user.merchant_id,
35
  role_id=current_user.role,
36
- associate_id=getattr(current_user, 'associate_id', None)
37
  )
38
 
39
  if layout_doc:
@@ -80,7 +80,7 @@ async def update_dashboard_layout(
80
  merchant_id=current_user.merchant_id,
81
  role_id=current_user.role,
82
  layout_data=layout_data,
83
- associate_id=getattr(current_user, 'associate_id', None),
84
  updated_by=current_user.user_id
85
  )
86
 
@@ -121,7 +121,7 @@ async def update_widget_positions(
121
  merchant_id=current_user.merchant_id,
122
  role_id=current_user.role,
123
  position_updates=positions_data.items,
124
- associate_id=getattr(current_user, 'associate_id', None),
125
  updated_by=current_user.user_id
126
  )
127
 
@@ -168,7 +168,7 @@ async def create_dashboard_widget(
168
  merchant_id=current_user.merchant_id,
169
  role_id=current_user.role,
170
  widget_request=widget_data,
171
- associate_id=getattr(current_user, 'associate_id', None),
172
  updated_by=current_user.user_id
173
  )
174
 
@@ -213,7 +213,7 @@ async def delete_dashboard_widget(
213
  merchant_id=current_user.merchant_id,
214
  role_id=current_user.role,
215
  widget_id=widget_id,
216
- associate_id=getattr(current_user, 'associate_id', None),
217
  updated_by=current_user.user_id
218
  )
219
 
@@ -257,7 +257,7 @@ async def reset_dashboard_layout(
257
  deleted = await DashboardService.reset_layout(
258
  merchant_id=current_user.merchant_id,
259
  role_id=current_user.role,
260
- associate_id=getattr(current_user, 'associate_id', None)
261
  )
262
 
263
  logger.info(f"Dashboard layout reset", extra={
@@ -333,4 +333,6 @@ async def list_dashboard_layouts(
333
  raise HTTPException(
334
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
335
  detail="Error retrieving dashboard layouts"
336
- )
 
 
 
26
  _: TokenUser = Depends(require_scm_permission("dashboard", "view"))
27
  ):
28
  """
29
+ Get dashboard layout for merchant+role combination.
30
  Returns layout or empty with status true if no layout exists.
31
  """
32
  try:
33
  layout_doc = await DashboardService.get_layout(
34
  merchant_id=current_user.merchant_id,
35
  role_id=current_user.role,
36
+ user_id=getattr(current_user, 'user_id', None)
37
  )
38
 
39
  if layout_doc:
 
80
  merchant_id=current_user.merchant_id,
81
  role_id=current_user.role,
82
  layout_data=layout_data,
83
+ user_id=getattr(current_user, 'user_id', None),
84
  updated_by=current_user.user_id
85
  )
86
 
 
121
  merchant_id=current_user.merchant_id,
122
  role_id=current_user.role,
123
  position_updates=positions_data.items,
124
+ user_id=getattr(current_user, 'user_id', None),
125
  updated_by=current_user.user_id
126
  )
127
 
 
168
  merchant_id=current_user.merchant_id,
169
  role_id=current_user.role,
170
  widget_request=widget_data,
171
+ user_id=getattr(current_user, 'user_id', None),
172
  updated_by=current_user.user_id
173
  )
174
 
 
213
  merchant_id=current_user.merchant_id,
214
  role_id=current_user.role,
215
  widget_id=widget_id,
216
+ user_id=getattr(current_user, 'user_id', None),
217
  updated_by=current_user.user_id
218
  )
219
 
 
257
  deleted = await DashboardService.reset_layout(
258
  merchant_id=current_user.merchant_id,
259
  role_id=current_user.role,
260
+ user_id=getattr(current_user, 'user_id', None)
261
  )
262
 
263
  logger.info(f"Dashboard layout reset", extra={
 
333
  raise HTTPException(
334
  status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
335
  detail="Error retrieving dashboard layouts"
336
+ )
337
+
338
+
app/dashboard/controllers/widget_router.py CHANGED
@@ -9,14 +9,14 @@ from app.core.schemas import StatusResponse
9
  from app.dashboard.schemas.widget_schemas import (
10
  ChartWidgetRequest, ChartWidgetResponse, ChartListRequest,
11
  TableWidgetRequest, TableWidgetResponse, TableListRequest,
12
- KPIStatsRequest, KPIStatsResponse, IndividualKPIRequest,
13
  IndividualKPIResponse, KPIListRequest
14
  )
15
  from app.dependencies.auth import get_current_user, TokenUser
16
  from app.dependencies.scm_permissions import require_scm_permission
17
  from app.dashboard.services.widget_data_service import WidgetDataService
18
  from app.dashboard.constants import (
19
- CHART_WIDGET_IDS, TABLE_WIDGET_IDS, KPI_WIDGET_IDS,
20
  is_valid_widget_id, WIDGET_CATALOG_COLLECTION
21
  )
22
  from app.nosql import get_database
@@ -30,11 +30,9 @@ async def require_widget_access(widget_id: str, current_user: TokenUser) -> Toke
30
  """Check if user has access to specific widget via access_roles.widget_access."""
31
  try:
32
  db = get_database()
33
- access_roles_collection = db["access_roles"]
34
-
35
  # Find user's role permissions
36
  role_doc = await access_roles_collection.find_one({
37
- "merchant_id": current_user.merchant_id,
38
  "role_id": current_user.role
39
  })
40
 
@@ -302,7 +300,6 @@ async def list_chart_widgets(
302
  # Build query filters
303
  query = {
304
  "type": "chart",
305
- "status": "active"
306
  }
307
 
308
  # Add request filters
@@ -310,8 +307,8 @@ async def list_chart_widgets(
310
  query.update(request.filters)
311
 
312
  if request.widget_types:
313
- query["widget_type"] = {"$in": request.widget_types}
314
-
315
  if request.categories:
316
  query["category"] = {"$in": request.categories}
317
 
@@ -374,8 +371,7 @@ async def list_table_widgets(
374
 
375
  # Build query filters
376
  query = {
377
- "type": "table",
378
- "status": "active"
379
  }
380
 
381
  # Add request filters
@@ -383,8 +379,8 @@ async def list_table_widgets(
383
  query.update(request.filters)
384
 
385
  if request.widget_types:
386
- query["widget_type"] = {"$in": request.widget_types}
387
-
388
  if request.categories:
389
  query["category"] = {"$in": request.categories}
390
 
@@ -447,8 +443,7 @@ async def list_kpi_widgets(
447
 
448
  # Build query filters
449
  query = {
450
- "type": "kpi",
451
- "status": "active"
452
  }
453
 
454
  # Add request filters
 
9
  from app.dashboard.schemas.widget_schemas import (
10
  ChartWidgetRequest, ChartWidgetResponse, ChartListRequest,
11
  TableWidgetRequest, TableWidgetResponse, TableListRequest,
12
+ KPIStatsRequest, KPIStatsResponse, IndividualKPIRequest,
13
  IndividualKPIResponse, KPIListRequest
14
  )
15
  from app.dependencies.auth import get_current_user, TokenUser
16
  from app.dependencies.scm_permissions import require_scm_permission
17
  from app.dashboard.services.widget_data_service import WidgetDataService
18
  from app.dashboard.constants import (
19
+ CHART_WIDGET_IDS, TABLE_WIDGET_IDS, KPI_WIDGET_IDS,
20
  is_valid_widget_id, WIDGET_CATALOG_COLLECTION
21
  )
22
  from app.nosql import get_database
 
30
  """Check if user has access to specific widget via access_roles.widget_access."""
31
  try:
32
  db = get_database()
33
+ access_roles_collection = db["scm_access_roles"]
 
34
  # Find user's role permissions
35
  role_doc = await access_roles_collection.find_one({
 
36
  "role_id": current_user.role
37
  })
38
 
 
300
  # Build query filters
301
  query = {
302
  "type": "chart",
 
303
  }
304
 
305
  # Add request filters
 
307
  query.update(request.filters)
308
 
309
  if request.widget_types:
310
+ query["type"] = {"$in": request.widget_types}
311
+
312
  if request.categories:
313
  query["category"] = {"$in": request.categories}
314
 
 
371
 
372
  # Build query filters
373
  query = {
374
+ "type": "table"
 
375
  }
376
 
377
  # Add request filters
 
379
  query.update(request.filters)
380
 
381
  if request.widget_types:
382
+ query["type"] = {"$in": request.widget_types}
383
+
384
  if request.categories:
385
  query["category"] = {"$in": request.categories}
386
 
 
443
 
444
  # Build query filters
445
  query = {
446
+ "type": "kpi"
 
447
  }
448
 
449
  # Add request filters
app/dashboard/services/dashboard_service.py CHANGED
@@ -27,7 +27,7 @@ class DashboardService:
27
  async def get_layout(
28
  merchant_id: str,
29
  role_id: str,
30
- associate_id: Optional[str] = None
31
  ) -> Optional[Dict[str, Any]]:
32
  """
33
  Get dashboard layout for merchant+role+associate combination.
@@ -43,11 +43,11 @@ class DashboardService:
43
  "role_id": role_id
44
  }
45
 
46
- # Add associate_id if provided (for personal layouts)
47
- if associate_id:
48
- query["associate_id"] = associate_id
49
  else:
50
- query["associate_id"] = {"$exists": False}
51
 
52
  layout_doc = await collection.find_one(query)
53
 
@@ -55,14 +55,14 @@ class DashboardService:
55
  logger.info(f"Layout found", extra={
56
  "merchant_id": merchant_id,
57
  "role_id": role_id,
58
- "associate_id": associate_id,
59
  "widget_count": len(layout_doc.get("widgets", []))
60
  })
61
  else:
62
  logger.info(f"No layout found", extra={
63
  "merchant_id": merchant_id,
64
  "role_id": role_id,
65
- "associate_id": associate_id
66
  })
67
 
68
  return layout_doc
@@ -76,7 +76,7 @@ class DashboardService:
76
  merchant_id: str,
77
  role_id: str,
78
  layout_data: DashboardLayoutCreate,
79
- associate_id: Optional[str] = None,
80
  updated_by: Optional[str] = None
81
  ) -> Dict[str, Any]:
82
  """
@@ -93,8 +93,8 @@ class DashboardService:
93
  "role_id": role_id
94
  }
95
 
96
- if associate_id:
97
- query["associate_id"] = associate_id
98
 
99
  # Hydrate widget data_config from catalog
100
  widgets_with_config = []
@@ -141,7 +141,7 @@ class DashboardService:
141
  logger.info(f"Layout {'created' if result.upserted_id else 'updated'}", extra={
142
  "merchant_id": merchant_id,
143
  "role_id": role_id,
144
- "associate_id": associate_id,
145
  "widget_count": len(widgets_with_config),
146
  "upserted": bool(result.upserted_id)
147
  })
@@ -157,7 +157,7 @@ class DashboardService:
157
  merchant_id: str,
158
  role_id: str,
159
  position_updates: List[WidgetPositionUpdate],
160
- associate_id: Optional[str] = None,
161
  updated_by: Optional[str] = None
162
  ) -> Dict[str, Any]:
163
  """
@@ -174,8 +174,8 @@ class DashboardService:
174
  "role_id": role_id
175
  }
176
 
177
- if associate_id:
178
- query["associate_id"] = associate_id
179
 
180
  # Get current layout
181
  current_layout = await collection.find_one(query)
@@ -214,7 +214,7 @@ class DashboardService:
214
  logger.info(f"Widget positions updated", extra={
215
  "merchant_id": merchant_id,
216
  "role_id": role_id,
217
- "associate_id": associate_id,
218
  "updates_count": len(position_updates)
219
  })
220
 
@@ -229,7 +229,7 @@ class DashboardService:
229
  merchant_id: str,
230
  role_id: str,
231
  widget_request: CreateWidgetRequest,
232
- associate_id: Optional[str] = None,
233
  updated_by: Optional[str] = None
234
  ) -> Dict[str, Any]:
235
  """
@@ -246,8 +246,8 @@ class DashboardService:
246
  "role_id": role_id
247
  }
248
 
249
- if associate_id:
250
- query["associate_id"] = associate_id
251
 
252
  # Get current layout or create new one
253
  current_layout = await collection.find_one(query)
@@ -258,7 +258,7 @@ class DashboardService:
258
  grid_settings=None # Will use defaults
259
  )
260
  return await DashboardService.create_or_update_layout(
261
- merchant_id, role_id, layout_data, associate_id, updated_by
262
  )
263
 
264
  # Add widget to existing layout
@@ -293,7 +293,7 @@ class DashboardService:
293
  logger.info(f"Widget added to layout", extra={
294
  "merchant_id": merchant_id,
295
  "role_id": role_id,
296
- "associate_id": associate_id,
297
  "widget_id": widget_request.widget_id,
298
  "widget_type": widget_request.type
299
  })
@@ -309,7 +309,7 @@ class DashboardService:
309
  merchant_id: str,
310
  role_id: str,
311
  widget_id: str,
312
- associate_id: Optional[str] = None,
313
  updated_by: Optional[str] = None
314
  ) -> Dict[str, Any]:
315
  """
@@ -326,8 +326,8 @@ class DashboardService:
326
  "role_id": role_id
327
  }
328
 
329
- if associate_id:
330
- query["associate_id"] = associate_id
331
 
332
  # Get current layout
333
  current_layout = await collection.find_one(query)
@@ -355,7 +355,7 @@ class DashboardService:
355
  logger.info(f"Widget removed from layout", extra={
356
  "merchant_id": merchant_id,
357
  "role_id": role_id,
358
- "associate_id": associate_id,
359
  "widget_id": widget_id
360
  })
361
 
@@ -369,7 +369,7 @@ class DashboardService:
369
  async def reset_layout(
370
  merchant_id: str,
371
  role_id: str,
372
- associate_id: Optional[str] = None
373
  ) -> bool:
374
  """
375
  Delete layout for merchant+role+associate combination.
@@ -385,17 +385,17 @@ class DashboardService:
385
  "role_id": role_id
386
  }
387
 
388
- if associate_id:
389
- query["associate_id"] = associate_id
390
  else:
391
- query["associate_id"] = {"$exists": False}
392
 
393
  result = await collection.delete_one(query)
394
 
395
  logger.info(f"Layout reset", extra={
396
  "merchant_id": merchant_id,
397
  "role_id": role_id,
398
- "associate_id": associate_id,
399
  "deleted": result.deleted_count > 0
400
  })
401
 
 
27
  async def get_layout(
28
  merchant_id: str,
29
  role_id: str,
30
+ user_id: Optional[str] = None
31
  ) -> Optional[Dict[str, Any]]:
32
  """
33
  Get dashboard layout for merchant+role+associate combination.
 
43
  "role_id": role_id
44
  }
45
 
46
+ # Add user_id if provided (for personal layouts)
47
+ if user_id:
48
+ query["user_id"] = user_id
49
  else:
50
+ query["user_id"] = {"$exists": False}
51
 
52
  layout_doc = await collection.find_one(query)
53
 
 
55
  logger.info(f"Layout found", extra={
56
  "merchant_id": merchant_id,
57
  "role_id": role_id,
58
+ "user_id": user_id,
59
  "widget_count": len(layout_doc.get("widgets", []))
60
  })
61
  else:
62
  logger.info(f"No layout found", extra={
63
  "merchant_id": merchant_id,
64
  "role_id": role_id,
65
+ "user_id": user_id
66
  })
67
 
68
  return layout_doc
 
76
  merchant_id: str,
77
  role_id: str,
78
  layout_data: DashboardLayoutCreate,
79
+ user_id: Optional[str] = None,
80
  updated_by: Optional[str] = None
81
  ) -> Dict[str, Any]:
82
  """
 
93
  "role_id": role_id
94
  }
95
 
96
+ if user_id:
97
+ query["user_id"] = user_id
98
 
99
  # Hydrate widget data_config from catalog
100
  widgets_with_config = []
 
141
  logger.info(f"Layout {'created' if result.upserted_id else 'updated'}", extra={
142
  "merchant_id": merchant_id,
143
  "role_id": role_id,
144
+ "user_id": user_id,
145
  "widget_count": len(widgets_with_config),
146
  "upserted": bool(result.upserted_id)
147
  })
 
157
  merchant_id: str,
158
  role_id: str,
159
  position_updates: List[WidgetPositionUpdate],
160
+ user_id: Optional[str] = None,
161
  updated_by: Optional[str] = None
162
  ) -> Dict[str, Any]:
163
  """
 
174
  "role_id": role_id
175
  }
176
 
177
+ if user_id:
178
+ query["user_id"] = user_id
179
 
180
  # Get current layout
181
  current_layout = await collection.find_one(query)
 
214
  logger.info(f"Widget positions updated", extra={
215
  "merchant_id": merchant_id,
216
  "role_id": role_id,
217
+ "user_id": user_id,
218
  "updates_count": len(position_updates)
219
  })
220
 
 
229
  merchant_id: str,
230
  role_id: str,
231
  widget_request: CreateWidgetRequest,
232
+ user_id: Optional[str] = None,
233
  updated_by: Optional[str] = None
234
  ) -> Dict[str, Any]:
235
  """
 
246
  "role_id": role_id
247
  }
248
 
249
+ if user_id:
250
+ query["user_id"] = user_id
251
 
252
  # Get current layout or create new one
253
  current_layout = await collection.find_one(query)
 
258
  grid_settings=None # Will use defaults
259
  )
260
  return await DashboardService.create_or_update_layout(
261
+ merchant_id, role_id, layout_data, user_id, updated_by
262
  )
263
 
264
  # Add widget to existing layout
 
293
  logger.info(f"Widget added to layout", extra={
294
  "merchant_id": merchant_id,
295
  "role_id": role_id,
296
+ "user_id": user_id,
297
  "widget_id": widget_request.widget_id,
298
  "widget_type": widget_request.type
299
  })
 
309
  merchant_id: str,
310
  role_id: str,
311
  widget_id: str,
312
+ user_id: Optional[str] = None,
313
  updated_by: Optional[str] = None
314
  ) -> Dict[str, Any]:
315
  """
 
326
  "role_id": role_id
327
  }
328
 
329
+ if user_id:
330
+ query["user_id"] = user_id
331
 
332
  # Get current layout
333
  current_layout = await collection.find_one(query)
 
355
  logger.info(f"Widget removed from layout", extra={
356
  "merchant_id": merchant_id,
357
  "role_id": role_id,
358
+ "user_id": user_id,
359
  "widget_id": widget_id
360
  })
361
 
 
369
  async def reset_layout(
370
  merchant_id: str,
371
  role_id: str,
372
+ user_id: Optional[str] = None
373
  ) -> bool:
374
  """
375
  Delete layout for merchant+role+associate combination.
 
385
  "role_id": role_id
386
  }
387
 
388
+ if user_id:
389
+ query["user_id"] = user_id
390
  else:
391
+ query["user_id"] = {"$exists": False}
392
 
393
  result = await collection.delete_one(query)
394
 
395
  logger.info(f"Layout reset", extra={
396
  "merchant_id": merchant_id,
397
  "role_id": role_id,
398
+ "user_id": user_id,
399
  "deleted": result.deleted_count > 0
400
  })
401
 
app/dashboard/services/widget_data_service.py CHANGED
@@ -4,6 +4,7 @@ Handles data aggregation and retrieval for dashboard widgets.
4
  """
5
  from datetime import datetime, timedelta
6
  from typing import Optional, List, Dict, Any
 
7
  from sqlalchemy import text
8
  from app.core.logging import get_logger
9
  from app.sql import async_session
@@ -41,9 +42,10 @@ class WidgetDataService:
41
  if use_cache:
42
  cached_data = await cache_service.get(cache_key)
43
  if cached_data:
44
- cached_data["cached"] = True
45
- return cached_data
46
-
 
47
  # Get widget configuration
48
  widget_config = get_widget_config(widget_id)
49
  if not widget_config:
@@ -64,8 +66,8 @@ class WidgetDataService:
64
  # Cache the result
65
  if use_cache:
66
  ttl = get_cache_ttl_for_widget(widget_id)
67
- await cache_service.set(cache_key, data, ttl)
68
-
69
  return data
70
 
71
  except Exception as e:
@@ -94,9 +96,10 @@ class WidgetDataService:
94
  if use_cache:
95
  cached_data = await cache_service.get(cache_key)
96
  if cached_data:
97
- cached_data["cached"] = True
98
- return cached_data
99
-
 
100
  # Get widget configuration
101
  widget_config = get_widget_config(widget_id)
102
  if not widget_config:
@@ -117,8 +120,8 @@ class WidgetDataService:
117
  # Cache the result
118
  if use_cache:
119
  ttl = get_cache_ttl_for_widget(widget_id)
120
- await cache_service.set(cache_key, data, ttl)
121
-
122
  return data
123
 
124
  except Exception as e:
@@ -143,8 +146,8 @@ class WidgetDataService:
143
  if use_cache:
144
  cached_data = await cache_service.get(cache_key)
145
  if cached_data:
146
- return cached_data
147
-
148
  # Get KPI data (mock for now)
149
  kpis = {}
150
  charts = {} if include_charts else None
@@ -199,8 +202,8 @@ class WidgetDataService:
199
  # Cache the result
200
  if use_cache:
201
  ttl = get_cache_ttl_for_widget("kpi_stats")
202
- await cache_service.set(cache_key, data, ttl)
203
-
204
  return data
205
 
206
  except Exception as e:
 
4
  """
5
  from datetime import datetime, timedelta
6
  from typing import Optional, List, Dict, Any
7
+ import json
8
  from sqlalchemy import text
9
  from app.core.logging import get_logger
10
  from app.sql import async_session
 
42
  if use_cache:
43
  cached_data = await cache_service.get(cache_key)
44
  if cached_data:
45
+ data = json.loads(cached_data)
46
+ data["cached"] = True
47
+ return data
48
+
49
  # Get widget configuration
50
  widget_config = get_widget_config(widget_id)
51
  if not widget_config:
 
66
  # Cache the result
67
  if use_cache:
68
  ttl = get_cache_ttl_for_widget(widget_id)
69
+ await cache_service.set(cache_key, json.dumps(data), ttl)
70
+
71
  return data
72
 
73
  except Exception as e:
 
96
  if use_cache:
97
  cached_data = await cache_service.get(cache_key)
98
  if cached_data:
99
+ data = json.loads(cached_data)
100
+ data["cached"] = True
101
+ return data
102
+
103
  # Get widget configuration
104
  widget_config = get_widget_config(widget_id)
105
  if not widget_config:
 
120
  # Cache the result
121
  if use_cache:
122
  ttl = get_cache_ttl_for_widget(widget_id)
123
+ await cache_service.set(cache_key, json.dumps(data), ttl)
124
+
125
  return data
126
 
127
  except Exception as e:
 
146
  if use_cache:
147
  cached_data = await cache_service.get(cache_key)
148
  if cached_data:
149
+ return json.loads(cached_data)
150
+
151
  # Get KPI data (mock for now)
152
  kpis = {}
153
  charts = {} if include_charts else None
 
202
  # Cache the result
203
  if use_cache:
204
  ttl = get_cache_ttl_for_widget("kpi_stats")
205
+ await cache_service.set(cache_key, json.dumps(data), ttl)
206
+
207
  return data
208
 
209
  except Exception as e:
app/main.py CHANGED
@@ -8,6 +8,7 @@ from fastapi.responses import JSONResponse
8
  from fastapi.exceptions import RequestValidationError
9
  from jose import JWTError
10
  from pymongo.errors import PyMongoError, ConnectionFailure, OperationFailure
 
11
  from app.core.logging import get_logger, setup_logging
12
  from app.core.config import settings
13
 
@@ -86,7 +87,7 @@ async def startup_event():
86
  logger.info("Starting SCM Microservice")
87
  await connect_to_mongo()
88
  await connect_to_database()
89
-
90
  # Start sync workers
91
  try:
92
  from app.superadmin.sync_service import get_sync_management_service
@@ -115,6 +116,7 @@ async def shutdown_event():
115
 
116
  await close_mongo_connection()
117
  await disconnect_from_database()
 
118
  logger.info("SCM Microservice shut down successfully")
119
 
120
 
 
8
  from fastapi.exceptions import RequestValidationError
9
  from jose import JWTError
10
  from pymongo.errors import PyMongoError, ConnectionFailure, OperationFailure
11
+ from app.cache import close_redis_connection, connect_to_redis
12
  from app.core.logging import get_logger, setup_logging
13
  from app.core.config import settings
14
 
 
87
  logger.info("Starting SCM Microservice")
88
  await connect_to_mongo()
89
  await connect_to_database()
90
+ await connect_to_redis()
91
  # Start sync workers
92
  try:
93
  from app.superadmin.sync_service import get_sync_management_service
 
116
 
117
  await close_mongo_connection()
118
  await disconnect_from_database()
119
+ await close_redis_connection()
120
  logger.info("SCM Microservice shut down successfully")
121
 
122