leadguru-jobs 0.646.0__tar.gz → 0.648.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/PKG-INFO +1 -1
  2. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/leadguru_jobs.egg-info/PKG-INFO +1 -1
  3. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/jobs/workspace_connect.py +27 -19
  4. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/enums.py +1 -0
  5. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/notifications/notification.py +46 -1
  6. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/mongo_repository.py +29 -10
  7. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/MANIFEST.in +0 -0
  8. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/README.md +0 -0
  9. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/leadguru_jobs.egg-info/SOURCES.txt +0 -0
  10. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/leadguru_jobs.egg-info/dependency_links.txt +0 -0
  11. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/leadguru_jobs.egg-info/not-zip-safe +0 -0
  12. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/leadguru_jobs.egg-info/requires.txt +0 -0
  13. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/leadguru_jobs.egg-info/top_level.txt +0 -0
  14. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/__init__.py +0 -0
  15. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/assets/images/arrow.png +0 -0
  16. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/assets/images/firework.png +0 -0
  17. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/assets/images/lock.png +0 -0
  18. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/assets/images/logo.png +0 -0
  19. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/assets/images/mail.png +0 -0
  20. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/basejobs.py +0 -0
  21. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/env.py +0 -0
  22. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/jobs/__init__.py +0 -0
  23. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/jobs/analytics.py +0 -0
  24. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/jobs/bot_stats_update.py +0 -0
  25. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/jobs/chat_history.py +0 -0
  26. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/jobs/connect_sources.py +0 -0
  27. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/jobs/inbox_leads.py +0 -0
  28. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/jobs/load_slack_people.py +0 -0
  29. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/jobs/mass_message.py +0 -0
  30. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/jobs/send_code.py +0 -0
  31. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/jobs/send_slack_message.py +0 -0
  32. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/jobs/update_slack_profile.py +0 -0
  33. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/__init__.py +0 -0
  34. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/discord_client/__init__.py +0 -0
  35. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/discord_client/discord_client.py +0 -0
  36. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/discord_client/methods.py +0 -0
  37. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/enums/__init__.py +0 -0
  38. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/enums/slack_errors.py +0 -0
  39. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/helpers.py +0 -0
  40. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/pubsub/__init__.py +0 -0
  41. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/pubsub/messages.py +0 -0
  42. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/pubsub/pubsubfactory.py +0 -0
  43. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/slack_client/__init__.py +0 -0
  44. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/slack_client/methods.py +0 -0
  45. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/slack_client/slack_client.py +0 -0
  46. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_common/slack_client/web_client.py +0 -0
  47. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/__init__.py +0 -0
  48. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/analytics.py +0 -0
  49. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/engine.py +0 -0
  50. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/helpers.py +0 -0
  51. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/model.py +0 -0
  52. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/__init__.py +0 -0
  53. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/base.py +0 -0
  54. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/boards/__init__.py +0 -0
  55. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/boards/board.py +0 -0
  56. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/boards/status.py +0 -0
  57. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/bots/__init__.py +0 -0
  58. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/bots/base_bot.py +0 -0
  59. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/bots/bot_info.py +0 -0
  60. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/bots/dedicated_bot.py +0 -0
  61. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/chat/__init__.py +0 -0
  62. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/chat/file.py +0 -0
  63. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/chat/grouped_messages.py +0 -0
  64. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/chat/message.py +0 -0
  65. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/chat/request.py +0 -0
  66. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/chat/scheduled_message.py +0 -0
  67. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/contacts/__init__.py +0 -0
  68. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/contacts/contact.py +0 -0
  69. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/external/__init__.py +0 -0
  70. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/external/cloud/__init__.py +0 -0
  71. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/external/cloud/file.py +0 -0
  72. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/external/discord/__init__.py +0 -0
  73. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/external/discord/user.py +0 -0
  74. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/external/slack/__init__.py +0 -0
  75. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/external/slack/timezone.py +0 -0
  76. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/external/slack/user.py +0 -0
  77. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/external/user_workspace.py +0 -0
  78. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/leads/__init__.py +0 -0
  79. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/leads/config.py +0 -0
  80. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/leads/extended_lead.py +0 -0
  81. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/leads/lead.py +0 -0
  82. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/leads/message.py +0 -0
  83. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/notifications/__init__.py +0 -0
  84. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/notifications/notification_settings.py +0 -0
  85. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/people/__init__.py +0 -0
  86. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/people/people.py +0 -0
  87. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/people/profile.py +0 -0
  88. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/post/__init__.py +0 -0
  89. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/post/message.py +0 -0
  90. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/post/post.py +0 -0
  91. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/templates/__init__.py +0 -0
  92. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/templates/template.py +0 -0
  93. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/user/__init__.py +0 -0
  94. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/user/feature.py +0 -0
  95. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/user/general_settings.py +0 -0
  96. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/user/reset_password.py +0 -0
  97. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/user/subscription.py +0 -0
  98. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/user/user.py +0 -0
  99. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/user/user_follow_ups.py +0 -0
  100. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/user/user_page.py +0 -0
  101. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/user/verification.py +0 -0
  102. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/user_leads/__init__.py +0 -0
  103. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/user_leads/extended_user_lead.py +0 -0
  104. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/models/user_leads/user_lead.py +0 -0
  105. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/repositories/__init__.py +0 -0
  106. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/repositories/post/__init__.py +0 -0
  107. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/lgt_data/repositories/post/posts.py +0 -0
  108. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/main.py +0 -0
  109. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/runner.py +0 -0
  110. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/services/__init__.py +0 -0
  111. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/services/web_client.py +0 -0
  112. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/simple_job.py +0 -0
  113. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/smtp.py +0 -0
  114. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/lgt_jobs/templates/new_message.html +0 -0
  115. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/setup.cfg +0 -0
  116. {leadguru_jobs-0.646.0 → leadguru_jobs-0.648.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: leadguru_jobs
3
- Version: 0.646.0
3
+ Version: 0.648.0
4
4
  Summary: LGT jobs builds
5
5
  Author-email: developer@leadguru.co
6
6
  Classifier: Development Status :: 5 - Production/Stable
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: leadguru_jobs
3
- Version: 0.646.0
3
+ Version: 0.648.0
4
4
  Summary: LGT jobs builds
5
5
  Author-email: developer@leadguru.co
6
6
  Classifier: Development Status :: 5 - Production/Stable
@@ -1,3 +1,5 @@
1
+ import random
2
+ import time
1
3
  from abc import ABC
2
4
  from typing import Dict
3
5
  import requests
@@ -45,35 +47,41 @@ class ConnectSlackAccountJob(BaseBackgroundJob, ABC):
45
47
  if code_confirmed_response.status_code != 200:
46
48
  log.warning(f'Unable to confirm code due to error: {code_confirmed_response.content}')
47
49
  slack_user.status = StatusConnection.FAILED
48
- UserMongoRepository().set(current_user.id,
49
- slack_users=[user.to_dic() for user in current_user.slack_users])
50
+ UserMongoRepository().set(current_user.id, slack_users=[user.to_dic() for user in current_user.slack_users])
50
51
  return
51
52
 
52
53
  code_confirmed = code_confirmed_response.json().get('ok', False)
53
54
  if not code_confirmed:
54
55
  slack_user.status = StatusConnection.FAILED
55
- UserMongoRepository().set(current_user.id,
56
- slack_users=[user.to_dic() for user in current_user.slack_users])
56
+ UserMongoRepository().set(current_user.id, slack_users=[user.to_dic() for user in current_user.slack_users])
57
57
  log.warning(f'Invalid code')
58
58
  return
59
59
 
60
60
  slack_user.cookies = client.client.cookies = code_confirmed_response.cookies.get_dict()
61
61
 
62
- workspaces_response = client.find_workspaces(data.user_agent)
63
- if workspaces_response.status_code != 200:
64
- slack_user.status = StatusConnection.FAILED
65
- UserMongoRepository().set(current_user.id,
66
- slack_users=[user.to_dic() for user in current_user.slack_users])
67
- log.warning(f'Unable to get workspaces due to error: {workspaces_response.content}')
68
- return
69
- if not workspaces_response.json().get('ok', False):
70
- slack_user.status = StatusConnection.FAILED
71
- log.warning(f'Unable to get workspaces due to error: {workspaces_response.content}')
62
+ workspaces_response = None
63
+ attempt = 1
64
+ while attempt <= 5:
65
+ workspaces_response = client.find_workspaces(data.user_agent)
66
+ if workspaces_response.status_code != 200:
67
+ slack_user.status = StatusConnection.FAILED
68
+ log.warning(f'Attempt: {attempt}. Unable to get workspaces due to error: {workspaces_response.content}')
69
+ attempt += 1
70
+ time.sleep(60)
71
+ if not workspaces_response.json().get('ok', False):
72
+ slack_user.status = StatusConnection.FAILED
73
+ log.warning(f'Attempt: {attempt}. Unable to get workspaces due to error: {workspaces_response.json()}')
74
+ attempt += 1
75
+ time.sleep(60)
76
+ else:
77
+ slack_user.status = StatusConnection.IN_PROGRESS
78
+ break
79
+
80
+ UserMongoRepository().set(current_user.id, slack_users=[user.to_dic() for user in current_user.slack_users])
81
+
82
+ if attempt > 5:
72
83
  return
73
84
 
74
- UserMongoRepository().set(current_user.id,
75
- slack_users=[user.to_dic() for user in current_user.slack_users])
76
-
77
85
  log.info(f'{slack_user.email}: got workspaces data {workspaces_response.json()}')
78
86
  user_workspaces = next((user for user in workspaces_response.json()['current_teams']
79
87
  if user['email'] == data.slack_email), {}).get('teams', [])
@@ -97,14 +105,14 @@ class ConnectSlackAccountJob(BaseBackgroundJob, ABC):
97
105
  workspace.magic_login_url = login_url
98
106
  workspace.token = token
99
107
  workspace.domain = workspace.domain
108
+ time.sleep(random.uniform(0.5, 2))
100
109
 
101
110
  slack_user.cookies = session.cookies.get_dict()
102
111
  slack_user.workspaces = user_workspaces
103
112
  slack_user.status = StatusConnection.COMPLETE
104
113
 
105
114
  slack_users_dict = [user.to_dic() for user in current_user.slack_users]
106
- UserMongoRepository().set(current_user.id,
107
- slack_users=slack_users_dict)
115
+ UserMongoRepository().set(current_user.id, slack_users=slack_users_dict)
108
116
 
109
117
  dedicated_bots_repository = DedicatedBotRepository()
110
118
  dedicated_bots = dedicated_bots_repository.get_all(user_id=current_user.id, user_name=data.slack_email,
@@ -97,3 +97,4 @@ class NotificationType(str, Enum):
97
97
  ONCE_A_WEEK = 'once_a_week'
98
98
  WEEK_BEFORE = 'week_before'
99
99
  UNREAD_FOR_FEW_MINUTES = 'unread_for_few_minutes'
100
+ FEW_MINUTES_BEFORE = 'few_minutes_before'
@@ -198,6 +198,35 @@ class BulkReactionsNotification(Notification):
198
198
 
199
199
  class FollowUpNotification(Notification):
200
200
 
201
+ @property
202
+ def need_to_notify_now(self) -> bool:
203
+ allowed_types = [NotificationType.ONCE_A_DAY, NotificationType.ONCE_A_DAY, NotificationType.FEW_MINUTES_BEFORE]
204
+ if not self.enabled or self.type not in allowed_types:
205
+ return False
206
+
207
+ now = datetime.now(UTC)
208
+ if self.last_notification:
209
+ self.last_notification = self.last_notification.replace(tzinfo=UTC)
210
+
211
+ if (self.type == NotificationType.ONCE_A_DAY and self.last_notification
212
+ and (self.last_notification.day == now.day or self.hour != now.hour)):
213
+ return False
214
+
215
+ if (self.type == NotificationType.ONCE_A_WEEK and self.last_notification
216
+ and (self.last_notification.day == now.day or (now.hour != self.hour or now.day != self.day))):
217
+ return False
218
+
219
+ return True
220
+
221
+ def has_not_notified_leads(self, actual: list[UserLeadModel]) -> bool:
222
+ if self.type == NotificationType.FEW_MINUTES_BEFORE and self.last_notification:
223
+ self.last_notification = self.last_notification.replace(tzinfo=UTC)
224
+ not_notified_leads = [lead for lead in actual if lead.followup_date.replace(tzinfo=UTC) >
225
+ (self.last_notification + timedelta(minutes=self.minute))]
226
+ return bool(not_notified_leads)
227
+
228
+ return True
229
+
201
230
  @staticmethod
202
231
  def get_button_name(actual: list[UserLeadModel]) -> str:
203
232
  if len(actual) > 1:
@@ -206,7 +235,7 @@ class FollowUpNotification(Notification):
206
235
 
207
236
  def get_button_url(self, actual: list[UserLeadModel]) -> str:
208
237
  if len(actual) > 1:
209
- if self.type == NotificationType.ONCE_A_DAY:
238
+ if self.type == NotificationType.ONCE_A_DAY or self.type == NotificationType.FEW_MINUTES_BEFORE:
210
239
  return f'{portal_url}/dashboard/calendar?view=day'
211
240
  return f'{portal_url}/dashboard/calendar?view=week'
212
241
  return f'{portal_url}/feed?senderId={actual[0].message.sender_id}&sourceId={actual[0].message.source.source_id}'
@@ -218,6 +247,10 @@ class FollowUpNotification(Notification):
218
247
  return f'{subject_text} for today'
219
248
  elif self.type == NotificationType.ONCE_A_WEEK:
220
249
  return f'{subject_text} for this week'
250
+ elif self.type == NotificationType.FEW_MINUTES_BEFORE:
251
+ return f'{subject_text} for today in {self.minute} minutes'
252
+
253
+ return subject_text
221
254
 
222
255
  def get_notification_text(self, actual: list[ExtendedUserLeadModel], overdue: list[ExtendedUserLeadModel]) -> str:
223
256
  notification_text = ''
@@ -240,6 +273,18 @@ class FollowUpNotification(Notification):
240
273
  case _:
241
274
  notification_text = (f'You have planned to send follow-up to {", ".join(names[:3])} '
242
275
  f'and {len(names) - 3} other leads this week.')
276
+ elif self.type == NotificationType.FEW_MINUTES_BEFORE:
277
+ match len(actual):
278
+ case 1:
279
+ notification_text = (f'You have planned to send follow-up today in '
280
+ f'{self.minute} minutes to {names[0]}.')
281
+ case 2 | 3:
282
+ notification_text = (f'You have planned to send follow-up today in '
283
+ f'{self.minute} minutes to {", ".join(names)}.')
284
+ case _:
285
+ notification_text = (f'You have planned to send follow-up today in '
286
+ f'{self.minute} minutes to {", ".join(names[:3])} '
287
+ f'and {len(names) - 3} other leads.')
243
288
 
244
289
  return f'{notification_text} Plus you have {len(overdue)} overdue follow-ups.' if overdue else notification_text
245
290
 
@@ -242,10 +242,29 @@ class UserLeadMongoRepository(BaseMongoRepository):
242
242
  'notification_settings': '$user.notification_settings',
243
243
  'subscription_id': "$user.subscription_id",
244
244
  'followup_to': {
245
- '$cond': {
246
- 'if': {'$eq': ['$user.notification_settings.follow_ups.type', 'once_a_day']},
247
- 'then': this_day,
248
- 'else': after_week
245
+ '$switch': {
246
+ 'branches': [
247
+ {
248
+ 'case': {'$eq': ['$user.notification_settings.follow_ups.type', 'once_a_day']},
249
+ 'then': this_day
250
+ },
251
+ {
252
+ 'case': {'$eq': ['$user.notification_settings.follow_ups.type', 'once_a_week']},
253
+ 'then': after_week
254
+ },
255
+ {
256
+ 'case': {'$eq': ['$user.notification_settings.follow_ups.type',
257
+ 'few_minutes_before']},
258
+ 'then': {
259
+ '$dateSubtract': {
260
+ 'startDate': now,
261
+ 'unit': 'minute',
262
+ 'amount': '$user.notification_settings.follow_ups.minute'
263
+ }
264
+ }
265
+ }
266
+ ],
267
+ 'default': this_day
249
268
  }
250
269
  },
251
270
  'followup_date': 1,
@@ -811,12 +830,12 @@ class BoardsMongoRepository(BaseMongoRepository):
811
830
  if not board:
812
831
  return None
813
832
 
814
- board.statuses.append(BoardedStatus().from_dic({'name': 'Lead', 'order': 0}))
815
- board.statuses.append(BoardedStatus().from_dic({'name': 'Prospect', 'order': 1}))
816
- board.statuses.append(BoardedStatus().from_dic({'name': 'Opportunity', 'order': 2}))
817
- board.statuses.append(BoardedStatus().from_dic({'name': 'Call', 'order': 3}))
818
- board.statuses.append(BoardedStatus().from_dic({'name': 'Contract', 'order': 4}))
819
- board.statuses.append(BoardedStatus().from_dic({'name': 'Refused', 'order': 5}))
833
+ board.statuses.append(BoardedStatus().from_dic({'id': 'Lead', 'name': 'Lead', 'order': 0}))
834
+ board.statuses.append(BoardedStatus().from_dic({'id': 'Prospect', 'name': 'Prospect', 'order': 1}))
835
+ board.statuses.append(BoardedStatus().from_dic({'id': 'Opportunity', 'name': 'Opportunity', 'order': 2}))
836
+ board.statuses.append(BoardedStatus().from_dic({'id': 'Call', 'name': 'Call', 'order': 3}))
837
+ board.statuses.append(BoardedStatus().from_dic({'id': 'Contract', 'name': 'Contract', 'order': 4}))
838
+ board.statuses.append(BoardedStatus().from_dic({'id': 'Refused', 'name': 'Refused', 'order': 5}))
820
839
 
821
840
  return self.update_board(user_id, board_id, statuses=board.statuses)
822
841