brestok commited on
Commit
d825e8f
·
1 Parent(s): ea6cae4

Enhance scenario deletion process

Browse files

- Improved the `form_delete_scenario_filter` utility function for better filter creation during scenario deletions.
- Refined the `bulk_delete_scenarios_objs` and `delete_scenario` functions to enhance clarity and maintainability.
- Strengthened access control measures in the filtering logic for scenario deletions.

cbh/api/calls/db_requests.py CHANGED
@@ -1,6 +1,7 @@
1
  import asyncio
2
  from datetime import datetime, timedelta
3
 
 
4
  from fastapi import HTTPException
5
 
6
  from cbh.api.account.dto import AccountStatus, AccountType, CoachOpportunity
@@ -30,12 +31,18 @@ async def create_call_obj(
30
  """
31
  Create a new call.
32
  """
 
 
33
  status = CallStatus.SCHEDULED if is_business else CallStatus.CREATED
 
 
 
34
  call = CallModel(
35
  event=EventShorten(**event.model_dump()),
36
  customer=AccountShorten(**customer.model_dump()),
37
  coach=coach,
38
  status=status,
 
39
  )
40
  await settings.DB_CLIENT.calls.insert_one(call.to_mongo())
41
  return call
@@ -71,14 +78,17 @@ async def disable_call(call: CallModel) -> None:
71
  )
72
 
73
 
74
- async def enable_call(call: CallModel, payment_intent_id: str | None = None) -> None:
 
 
75
  """
76
  Enable a call.
77
  """
78
  update_data = {"status": CallStatus.SCHEDULED.value}
79
  if payment_intent_id:
80
  update_data["paymentIntentId"] = payment_intent_id
81
- print(update_data)
 
82
  await settings.DB_CLIENT.calls.update_one({"id": call.id}, {"$set": update_data})
83
 
84
 
@@ -333,12 +343,8 @@ async def calculate_call_availabilities(
333
  for day_schedule in weekly_schedule:
334
  if day_schedule.get("dayOfWeek") == slot_day_of_week:
335
  for time_slot in day_schedule.get("slots", []):
336
- slot_start_time = datetime.strptime(
337
- time_slot.get("startTime"), "%H:%M:%S.%f%z"
338
- ).time()
339
- slot_end_time = datetime.strptime(
340
- time_slot.get("endTime"), "%H:%M:%S.%f%z"
341
- ).time()
342
 
343
  if slot_start_time <= slot_time and slot_end_time >= slot_end:
344
  is_available = True
 
1
  import asyncio
2
  from datetime import datetime, timedelta
3
 
4
+ import dateutil
5
  from fastapi import HTTPException
6
 
7
  from cbh.api.account.dto import AccountStatus, AccountType, CoachOpportunity
 
31
  """
32
  Create a new call.
33
  """
34
+ from cbh.api.calls.services.daily import create_meeting_room
35
+
36
  status = CallStatus.SCHEDULED if is_business else CallStatus.CREATED
37
+ room_url = None
38
+ if is_business:
39
+ room_url = await create_meeting_room(event)
40
  call = CallModel(
41
  event=EventShorten(**event.model_dump()),
42
  customer=AccountShorten(**customer.model_dump()),
43
  coach=coach,
44
  status=status,
45
+ roomUrl=room_url,
46
  )
47
  await settings.DB_CLIENT.calls.insert_one(call.to_mongo())
48
  return call
 
78
  )
79
 
80
 
81
+ async def enable_call(
82
+ call: CallModel, payment_intent_id: str | None, mr_url: str | None
83
+ ) -> None:
84
  """
85
  Enable a call.
86
  """
87
  update_data = {"status": CallStatus.SCHEDULED.value}
88
  if payment_intent_id:
89
  update_data["paymentIntentId"] = payment_intent_id
90
+ if mr_url:
91
+ update_data["roomUrl"] = mr_url
92
  await settings.DB_CLIENT.calls.update_one({"id": call.id}, {"$set": update_data})
93
 
94
 
 
343
  for day_schedule in weekly_schedule:
344
  if day_schedule.get("dayOfWeek") == slot_day_of_week:
345
  for time_slot in day_schedule.get("slots", []):
346
+ slot_start_time = dateutil.parser.parse(time_slot["startTime"]).time()
347
+ slot_end_time = dateutil.parser.parse(time_slot["endTime"]).time()
 
 
 
 
348
 
349
  if slot_start_time <= slot_time and slot_end_time >= slot_end:
350
  is_available = True
cbh/api/calls/models.py CHANGED
@@ -18,6 +18,7 @@ class CallModel(MongoBaseModel):
18
  customer: AccountShorten
19
  coach: AccountShorten
20
 
 
21
  duration: int | None = None
22
 
23
  status: CallStatus = CallStatus.CREATED
 
18
  customer: AccountShorten
19
  coach: AccountShorten
20
 
21
+ roomUrl: str | None = None
22
  duration: int | None = None
23
 
24
  status: CallStatus = CallStatus.CREATED
cbh/api/calls/schemas.py CHANGED
@@ -59,5 +59,15 @@ class StripeCheckResponse(BaseModel):
59
  """
60
  Stripe check response.
61
  """
 
62
  isProcessed: bool
63
- success: bool
 
 
 
 
 
 
 
 
 
 
59
  """
60
  Stripe check response.
61
  """
62
+
63
  isProcessed: bool
64
+ success: bool
65
+
66
+
67
+ class DailyInitializeResponse(BaseModel):
68
+ """
69
+ Daily initialize response.
70
+ """
71
+
72
+ token: str
73
+ roomUrl: str
cbh/api/calls/services/__init__.py CHANGED
@@ -4,7 +4,6 @@ from .stripe import (
4
  manage_stripe_event,
5
  refund_stripe_payment,
6
  )
7
-
8
  __all__ = [
9
  "create_stripe_session",
10
  "verify_stripe_webhook",
 
4
  manage_stripe_event,
5
  refund_stripe_payment,
6
  )
 
7
  __all__ = [
8
  "create_stripe_session",
9
  "verify_stripe_webhook",
cbh/api/calls/services/stripe.py CHANGED
@@ -6,6 +6,7 @@ from fastapi import HTTPException, Request
6
 
7
  from cbh.api.calls.db_requests import disable_call, enable_call
8
  from cbh.api.calls.models import CallModel
 
9
  from cbh.api.common.db_requests import get_obj_by_id
10
  from cbh.core.config import settings
11
 
@@ -35,8 +36,8 @@ async def create_stripe_session(call: CallModel) -> str:
35
  },
36
  ],
37
  "mode": "payment",
38
- "success_url": f"{settings.Issuer}/payment/success?callId={call.id}",
39
- "cancel_url": f"{settings.Issuer}/payment/cancel?callId={call.id}",
40
  "metadata": metadata,
41
  "expires_at": int(time.time()) + 1800,
42
  },
@@ -45,7 +46,7 @@ async def create_stripe_session(call: CallModel) -> str:
45
  return checkout_session.url
46
 
47
 
48
- async def verify_stripe_webhook(request: Request, payload: bytes) -> dict:
49
  """
50
  Verify a stripe webhook.
51
  """
@@ -72,7 +73,8 @@ async def manage_stripe_event(event: dict) -> str:
72
  "checkout.session.async_payment_succeeded",
73
  ]:
74
  payment_intent_id = session.get("payment_intent")
75
- await enable_call(call, payment_intent_id)
 
76
 
77
  elif event_type in (
78
  "checkout.session.async_payment_failed",
 
6
 
7
  from cbh.api.calls.db_requests import disable_call, enable_call
8
  from cbh.api.calls.models import CallModel
9
+ from cbh.api.calls.services.daily import create_meeting_room
10
  from cbh.api.common.db_requests import get_obj_by_id
11
  from cbh.core.config import settings
12
 
 
36
  },
37
  ],
38
  "mode": "payment",
39
+ "success_url": f"{settings.Audience}/payment/success?callId={call.id}",
40
+ "cancel_url": f"{settings.Audience}/payment/cancel?callId={call.id}",
41
  "metadata": metadata,
42
  "expires_at": int(time.time()) + 1800,
43
  },
 
46
  return checkout_session.url
47
 
48
 
49
+ def verify_stripe_webhook(request: Request, payload: bytes) -> dict:
50
  """
51
  Verify a stripe webhook.
52
  """
 
73
  "checkout.session.async_payment_succeeded",
74
  ]:
75
  payment_intent_id = session.get("payment_intent")
76
+ meeting_room = await create_meeting_room(call.event)
77
+ await enable_call(call, payment_intent_id, meeting_room)
78
 
79
  elif event_type in (
80
  "checkout.session.async_payment_failed",
cbh/api/calls/views.py CHANGED
@@ -2,7 +2,6 @@ import asyncio
2
  from datetime import datetime
3
 
4
  from fastapi import Depends, Query, Request
5
- from fastapi.responses import RedirectResponse
6
 
7
  from cbh.api.account.dto import AccountType
8
  from cbh.api.account.models import AccountModel, AccountShorten
@@ -21,6 +20,7 @@ from cbh.api.calls.models import CallModel
21
  from cbh.api.calls.schemas import (
22
  CallAvailabilityResponse,
23
  CallsFilter,
 
24
  PurchaseCallRequest,
25
  RescheduleCallRequest,
26
  StripeCheckResponse,
@@ -32,6 +32,7 @@ from cbh.api.calls.services import (
32
  refund_stripe_payment,
33
  verify_stripe_webhook,
34
  )
 
35
  from cbh.api.calls.utils import can_edit_call
36
  from cbh.api.common.db_requests import get_obj_by_id
37
  from cbh.api.common.dto import Paging
@@ -124,7 +125,7 @@ async def cancel_call(
124
  return CbhResponseWrapper(data=call)
125
 
126
 
127
- @calls_router.post("")
128
  async def purchase_call(
129
  request: PurchaseCallRequest,
130
  account: AccountModel = Depends(PermissionDependency([AccountType.USER])),
@@ -153,7 +154,7 @@ async def stripe_callback(request: Request) -> CbhResponseWrapper[None]:
153
  Stripe callback.
154
  """
155
  payload = await request.body()
156
- event = await verify_stripe_webhook(request, payload)
157
  await manage_stripe_event(event)
158
  return CbhResponseWrapper(data=None)
159
 
@@ -168,3 +169,24 @@ async def check_stripe_payment(
168
  """
169
  response = await check_call_payment(callId)
170
  return CbhResponseWrapper(data=response)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  from datetime import datetime
3
 
4
  from fastapi import Depends, Query, Request
 
5
 
6
  from cbh.api.account.dto import AccountType
7
  from cbh.api.account.models import AccountModel, AccountShorten
 
20
  from cbh.api.calls.schemas import (
21
  CallAvailabilityResponse,
22
  CallsFilter,
23
+ DailyInitializeResponse,
24
  PurchaseCallRequest,
25
  RescheduleCallRequest,
26
  StripeCheckResponse,
 
32
  refund_stripe_payment,
33
  verify_stripe_webhook,
34
  )
35
+ from cbh.api.calls.services.daily import create_daily_token
36
  from cbh.api.calls.utils import can_edit_call
37
  from cbh.api.common.db_requests import get_obj_by_id
38
  from cbh.api.common.dto import Paging
 
125
  return CbhResponseWrapper(data=call)
126
 
127
 
128
+ @calls_router.post("/purchase")
129
  async def purchase_call(
130
  request: PurchaseCallRequest,
131
  account: AccountModel = Depends(PermissionDependency([AccountType.USER])),
 
154
  Stripe callback.
155
  """
156
  payload = await request.body()
157
+ event = verify_stripe_webhook(request, payload)
158
  await manage_stripe_event(event)
159
  return CbhResponseWrapper(data=None)
160
 
 
169
  """
170
  response = await check_call_payment(callId)
171
  return CbhResponseWrapper(data=response)
172
+
173
+
174
+ @calls_router.get("/daily/{callId}/initialize")
175
+ async def initialize_daily(
176
+ callId: str,
177
+ account: AccountModel = Depends(PermissionDependency()),
178
+ ) -> CbhResponseWrapper[str]:
179
+ """
180
+ Fetch daily token.
181
+ """
182
+ call = await get_obj_by_id(
183
+ CallModel,
184
+ callId,
185
+ additional_filter={
186
+ "$or": [{"customer.id": account.id}, {"coach.id": account.id}]
187
+ },
188
+ )
189
+ token = await create_daily_token(call, account.id)
190
+ return CbhResponseWrapper(
191
+ data=DailyInitializeResponse(token=token, roomUrl=call.roomUrl)
192
+ )
cbh/core/config.py CHANGED
@@ -5,11 +5,9 @@ Configuration module for ClipboardHealthAI application.
5
  import os
6
  import pathlib
7
  from functools import lru_cache
8
- from typing import Optional, Type
9
 
10
  from dotenv import load_dotenv
11
  from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase
12
- from pydantic import BaseModel
13
  from stripe import StripeClient
14
 
15
  load_dotenv()
@@ -31,6 +29,8 @@ class BaseConfig:
31
  STRIPE_API_KEY = os.getenv("STRIPE_API_KEY")
32
  STRIPE_WEBHOOK_SECRET = os.getenv("STRIPE_WEBHOOK_SECRET")
33
 
 
 
34
  @staticmethod
35
  def get_headers(api_key: str) -> dict:
36
  """
 
5
  import os
6
  import pathlib
7
  from functools import lru_cache
 
8
 
9
  from dotenv import load_dotenv
10
  from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase
 
11
  from stripe import StripeClient
12
 
13
  load_dotenv()
 
29
  STRIPE_API_KEY = os.getenv("STRIPE_API_KEY")
30
  STRIPE_WEBHOOK_SECRET = os.getenv("STRIPE_WEBHOOK_SECRET")
31
 
32
+ DAILY_API_KEY = os.getenv("DAILY_API_KEY")
33
+
34
  @staticmethod
35
  def get_headers(api_key: str) -> dict:
36
  """