Mbonea commited on
Commit
f9fbe3f
·
1 Parent(s): 95ff486

user powers not tested

Browse files
App/Payments/Model.py CHANGED
@@ -60,19 +60,23 @@ class Payment(Model):
60
  async def create_subscription_if_cash(self):
61
  if self.payment_method == PaymentMethod.CASH and self.user and self.plan:
62
  if self.amount >= self.plan.amount:
63
- expiration_time = datetime.datetime.now() + datetime.timedelta(
64
- hours=self.plan.duration
65
- )
66
- # Create the subscription
67
- await Subscription.create(
68
- user=self.user,
69
- duration=self.plan.duration,
70
- download_mb=self.plan.download_speed * 1024,
71
- upload_mb=self.plan.upload_speed * 1024,
72
- created_time=datetime.datetime.now(),
73
- expiration_time=expiration_time,
74
- active=True,
75
- )
 
 
 
 
76
  self.status = "subscription-created"
77
  await self.save()
78
  # Send payment success message with subscription details
@@ -90,27 +94,31 @@ class Payment(Model):
90
  async def create_subscription_or_balance(self):
91
  if self.user and self.plan:
92
  if self.amount >= self.plan.amount:
93
- expiration_time = datetime.datetime.now() + datetime.timedelta(
94
- hours=self.plan.duration
95
- )
 
 
 
 
 
 
 
 
 
 
 
96
  user = await self.user
97
 
98
- # Create the subscription
99
- await Subscription.create(
100
- user=user,
101
- duration=self.plan.duration,
102
- download_mb=self.plan.download_speed * 1024,
103
- upload_mb=self.plan.upload_speed * 1024,
104
- created_time=datetime.datetime.now(),
105
- expiration_time=expiration_time,
106
- active=True,
107
- )
108
  self.status = "subscription-created"
109
  await self.save()
110
  # Send payment success message with subscription details
111
- await user.send_payment_success_message(
112
  amount=self.amount, plan_name=self.plan.name
113
  )
 
114
  else:
115
  self.status = "insufficient-funds"
116
  await self.save()
 
60
  async def create_subscription_if_cash(self):
61
  if self.payment_method == PaymentMethod.CASH and self.user and self.plan:
62
  if self.amount >= self.plan.amount:
63
+ await self.fetch_related("user", "plan")
64
+ # expiration_time = datetime.datetime.now() + datetime.timedelta(
65
+ # hours=self.plan.duration
66
+ # )
67
+ # # Create the subscription
68
+ # await Subscription.create(
69
+ # user=self.user,
70
+ # duration=self.plan.duration,
71
+ # download_mb=self.plan.download_speed * 1024,
72
+ # upload_mb=self.plan.upload_speed * 1024,
73
+ # created_time=datetime.datetime.now(),
74
+ # expiration_time=expiration_time,
75
+ # active=True,
76
+ # )
77
+
78
+ self.user: User
79
+ await self.user.create_subscription(self.plan)
80
  self.status = "subscription-created"
81
  await self.save()
82
  # Send payment success message with subscription details
 
94
  async def create_subscription_or_balance(self):
95
  if self.user and self.plan:
96
  if self.amount >= self.plan.amount:
97
+ await self.fetch_related("user", "plan")
98
+ # expiration_time = datetime.datetime.now() + datetime.timedelta(
99
+ # hours=self.plan.duration
100
+ # )
101
+ # # Create the subscription
102
+ # await Subscription.create(
103
+ # user=self.user,
104
+ # duration=self.plan.duration,
105
+ # download_mb=self.plan.download_speed * 1024,
106
+ # upload_mb=self.plan.upload_speed * 1024,
107
+ # created_time=datetime.datetime.now(),
108
+ # expiration_time=expiration_time,
109
+ # active=True,
110
+ # )
111
  user = await self.user
112
 
113
+ self.user: User
114
+ await self.user.create_subscription(self.plan)
 
 
 
 
 
 
 
 
115
  self.status = "subscription-created"
116
  await self.save()
117
  # Send payment success message with subscription details
118
+ await self.user.send_payment_success_message(
119
  amount=self.amount, plan_name=self.plan.name
120
  )
121
+
122
  else:
123
  self.status = "insufficient-funds"
124
  await self.save()
App/Plans/Model.py CHANGED
@@ -1,5 +1,6 @@
1
  from tortoise import fields
2
  from tortoise.models import Model
 
3
 
4
 
5
  class Plan(Model):
@@ -13,6 +14,36 @@ class Plan(Model):
13
  duration = fields.IntField(description="Duration of the subscription in hours")
14
  download_speed = fields.FloatField(description="Download speed in Mbps")
15
  upload_speed = fields.FloatField(description="Upload speed in Mbps")
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  class Meta:
18
  table = "plans"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from tortoise import fields
2
  from tortoise.models import Model
3
+ from datetime import datetime, timedelta
4
 
5
 
6
  class Plan(Model):
 
14
  duration = fields.IntField(description="Duration of the subscription in hours")
15
  download_speed = fields.FloatField(description="Download speed in Mbps")
16
  upload_speed = fields.FloatField(description="Upload speed in Mbps")
17
+ expire_date = fields.DatetimeField(
18
+ default=None, null=True, description="Expiration date of the plan"
19
+ )
20
+ is_promo = fields.BooleanField(
21
+ default=False, description="Indicates if the plan is a promotional plan"
22
+ )
23
+ promo_duration_days = fields.IntField(
24
+ default=None, null=True, description="Number of days the promotion is valid"
25
+ )
26
+ is_valid = fields.BooleanField(
27
+ default=True, description="Indicates if the plan is valid"
28
+ )
29
 
30
  class Meta:
31
  table = "plans"
32
+
33
+ async def set_expiration(self):
34
+ """Set the expiration date based on the promo duration if applicable."""
35
+ if self.is_promo and self.promo_duration_days:
36
+ self.expire_date = datetime.now() + timedelta(days=self.promo_duration_days)
37
+ elif self.duration:
38
+ self.expire_date = datetime.now() + timedelta(
39
+ days=self.duration // 24
40
+ ) # Convert hours to days
41
+ await self.save()
42
+
43
+ async def is_promo_valid(self) -> bool:
44
+ """Check if the promotional plan is still valid."""
45
+ if self.is_promo and self.expire_date:
46
+ return datetime.now() < self.expire_date
47
+ self.is_valid = False
48
+ await self.save()
49
+ return False
App/Plans/PlanRoutes.py CHANGED
@@ -22,7 +22,25 @@ async def create_plan(request: CreatePlanRequest):
22
  detail="A plan with this name already exists",
23
  )
24
 
25
- # Create a new plan
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  plan = await Plan.create(
27
  name=request.name,
28
  amount=request.amount,
 
22
  detail="A plan with this name already exists",
23
  )
24
 
25
+ if request.is_promo:
26
+ plan = await Plan.create(
27
+ name=request.name,
28
+ amount=request.amount,
29
+ duration=request.duration,
30
+ download_speed=request.download_speed,
31
+ upload_speed=request.upload_speed,
32
+ is_promo=request.is_promo,
33
+ )
34
+ await plan.set_expiration()
35
+ await plan.save()
36
+
37
+ return BaseResponse(
38
+ code=200,
39
+ message="Plan created successfully",
40
+ payload={"plan_id": str(plan.id)},
41
+ )
42
+
43
+ # Create a new plan not promo
44
  plan = await Plan.create(
45
  name=request.name,
46
  amount=request.amount,
App/Plans/Schema.py CHANGED
@@ -15,6 +15,8 @@ class CreatePlanRequest(BaseModel):
15
  duration: int = Field(..., description="Duration of the subscription in hours")
16
  download_speed: float = Field(..., description="Download speed in Mbps")
17
  upload_speed: float = Field(..., description="Upload speed in Mbps")
 
 
18
 
19
 
20
  class UpdatePlanRequest(BaseModel):
 
15
  duration: int = Field(..., description="Duration of the subscription in hours")
16
  download_speed: float = Field(..., description="Download speed in Mbps")
17
  upload_speed: float = Field(..., description="Upload speed in Mbps")
18
+ is_promo: Optional[bool] = Field(..., description="is it a promo", default=False)
19
+ promo_days: Optional[int] = Field(..., description="promotion days", default=None)
20
 
21
 
22
  class UpdatePlanRequest(BaseModel):
App/Users/Model.py CHANGED
@@ -5,6 +5,8 @@ from passlib.context import CryptContext
5
  from App.Android.Android import AndroidClient
6
  from App.Android.Schema import RegisterUserRequest as AndroidRegister
7
  from App.Templates.Templates import MessageTemplate
 
 
8
  import datetime
9
  import uuid
10
  import random
@@ -56,6 +58,15 @@ class User(models.Model):
56
  """Hashes a plain password."""
57
  return pwd_context.hash(plain_password)
58
 
 
 
 
 
 
 
 
 
 
59
  async def verify_password(self, plain_password: str) -> bool:
60
  """
61
  Verifies a plain password against the hashed password.
@@ -144,10 +155,19 @@ class User(models.Model):
144
  )
145
  logger.error(f"Error creating user: {e}")
146
  raise e
147
-
148
- # Create the user in the database
149
  new_user = await cls.create(**user_data)
150
  logger.info(f"User {new_user.phoneNumber} created successfully.")
 
 
 
 
 
 
 
 
 
 
 
151
  # Decide whether to rollback user creation or proceed
152
  # For simplicity, we'll proceed
153
 
@@ -159,16 +179,32 @@ class User(models.Model):
159
  logger.error(f"Error creating user: {e}")
160
  raise e
161
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  async def send_welcome_message(self):
163
  """Sends a welcome message to the user."""
164
  message = self.message_templates.registration_message(user_name=self.name)
165
- try:
166
- await self.android_client.send_message(
167
- phone_numbers=self.phoneNumber, message=message
168
- )
169
- logger.info(f"Welcome message sent to {self.phoneNumber}.")
170
- except Exception as e:
171
- logger.error(f"Failed to send welcome message to {self.phoneNumber}: {e}")
172
 
173
  async def send_reset_token_message(self):
174
  """Sends the reset token to the user's phone number."""
@@ -261,5 +297,20 @@ class User(models.Model):
261
  f"Failed to send insufficient funds message to {self.phoneNumber}: {e}"
262
  )
263
 
264
- async def delete_user(self):
265
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  from App.Android.Android import AndroidClient
6
  from App.Android.Schema import RegisterUserRequest as AndroidRegister
7
  from App.Templates.Templates import MessageTemplate
8
+ from App.Subscriptions.Model import Subscription
9
+ from App.Plans.Model import Plan
10
  import datetime
11
  import uuid
12
  import random
 
58
  """Hashes a plain password."""
59
  return pwd_context.hash(plain_password)
60
 
61
+ async def send_message(self, message: str):
62
+ try:
63
+ await self.android_client.send_message(
64
+ phone_numbers=self.phoneNumber, message=message
65
+ )
66
+ logger.info(f"Welcome message sent to {self.phoneNumber}.")
67
+ except Exception as e:
68
+ logger.error(f"Failed to send welcome message to {self.phoneNumber}: {e}")
69
+
70
  async def verify_password(self, plain_password: str) -> bool:
71
  """
72
  Verifies a plain password against the hashed password.
 
155
  )
156
  logger.error(f"Error creating user: {e}")
157
  raise e
 
 
158
  new_user = await cls.create(**user_data)
159
  logger.info(f"User {new_user.phoneNumber} created successfully.")
160
+ # if there is a promotion and activate the user
161
+ promo_plans = await Plan.filter(is_promo=True).all()
162
+ for promo_plan in promo_plans:
163
+ plan_valid = await promo_plan.is_promo_valid()
164
+ if plan_valid:
165
+ Subscription.create()
166
+ await new_user.activate_user()
167
+ await new_user.send_plan_subscription_message(promo_plan)
168
+
169
+ # Create the user in the database
170
+
171
  # Decide whether to rollback user creation or proceed
172
  # For simplicity, we'll proceed
173
 
 
179
  logger.error(f"Error creating user: {e}")
180
  raise e
181
 
182
+ async def send_plan_subscription_message(self, plan: Plan):
183
+ message = self.message_templates.subscription_created_message(
184
+ user_name=self.name, plan_name=plan.name
185
+ )
186
+ await self.send_message(message=message)
187
+
188
+ async def create_subscription(self, plan: Plan):
189
+ expiration_time = datetime.datetime.now() + datetime.timedelta(
190
+ hours=plan.duration
191
+ )
192
+ # Create the subscription
193
+ await Subscription.create(
194
+ user=self,
195
+ duration=plan.duration,
196
+ download_mb=plan.download_speed * 1024,
197
+ upload_mb=plan.upload_speed * 1024,
198
+ created_time=datetime.datetime.now(),
199
+ expiration_time=expiration_time,
200
+ active=True,
201
+ )
202
+ await self.activate_user()
203
+
204
  async def send_welcome_message(self):
205
  """Sends a welcome message to the user."""
206
  message = self.message_templates.registration_message(user_name=self.name)
207
+ await self.send_message(message=message)
 
 
 
 
 
 
208
 
209
  async def send_reset_token_message(self):
210
  """Sends the reset token to the user's phone number."""
 
297
  f"Failed to send insufficient funds message to {self.phoneNumber}: {e}"
298
  )
299
 
300
+ async def activate_user(self):
301
+ """Activate the user using the Android client."""
302
+ try:
303
+ response = await self.android_client.activate_user(self.phoneNumber)
304
+ if response.get("status") == "success":
305
+ logger.info(f"User {self.phoneNumber} activated successfully.")
306
+ self.account_locked = False # Assuming activation unlocks the account
307
+ await self.save()
308
+ return True
309
+ else:
310
+ logger.error(
311
+ f"Failed to activate user {self.phoneNumber}: {response.get('message')}"
312
+ )
313
+ return False
314
+ except Exception as e:
315
+ logger.error(f"Error activating user {self.phoneNumber}: {str(e)}")
316
+ return False