Skip to content

Commit 03de4bd

Browse files
authored
Merge pull request #2603 from gtech-mulearn/dev
[FEATURE] IG Levels
2 parents 34674f6 + 4d9bef3 commit 03de4bd

File tree

5 files changed

+98
-50
lines changed

5 files changed

+98
-50
lines changed

.env.sample

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,6 @@ DISCORD_GUILD_ID=xxx
4646
DISCORD_BOT_TOKEN=xxx
4747

4848
QSEVERSE_BASE_URL=
49-
QSEVERSE_API_KEY=
49+
QSEVERSE_API_KEY=
50+
51+
BACKEND_API_KEY=

api/dashboard/profile/profile_serializer.py

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from django.db.models import F, Sum, Q
66
from rest_framework import serializers
77
from rest_framework.serializers import ModelSerializer
8-
8+
from db.task import UserIgLvlLink
99
from db.organization import UserOrganizationLink, District
1010
from db.task import (
1111
InterestGroup,
@@ -15,6 +15,7 @@
1515
Wallet,
1616
UserIgLink,
1717
UserLvlLink,
18+
UserIgLvlLink,
1819
)
1920
from db.user import User, UserSettings, Socials
2021
from utils.exception import CustomException
@@ -25,6 +26,7 @@
2526
MainRoles,
2627
WebHookActions,
2728
WebHookCategory,
29+
UnitType,
2830
)
2931
from utils.utils import DateTimeUtils, DiscordWebhooks
3032

@@ -178,25 +180,37 @@ def get_karma_distribution(self, obj):
178180
)
179181

180182
def get_interest_groups(self, obj):
183+
184+
# Get all IGs where user has a level entry (has interacted with this IG)
185+
user_ig_levels = UserIgLvlLink.objects.filter(user=obj).select_related('ig', 'level')
186+
187+
# Get user's currently selected IGs
188+
selected_ig_ids = set(
189+
UserIgLink.objects.filter(user=obj).values_list('ig_id', flat=True)
190+
)
191+
181192
interest_groups = []
182-
for ig_link in UserIgLink.objects.filter(user=obj):
193+
for ig_level_link in user_ig_levels:
194+
# Calculate IG-specific karma
183195
total_ig_karma = (
184-
0
185-
if KarmaActivityLog.objects.filter(
186-
task__ig=ig_link.ig, user=obj, appraiser_approved=True
196+
KarmaActivityLog.objects.filter(
197+
task__ig=ig_level_link.ig, user=obj, appraiser_approved=True
187198
)
188199
.aggregate(Sum("karma"))
189-
.get("karma__sum")
190-
is None
191-
else KarmaActivityLog.objects.filter(
192-
task__ig=ig_link.ig, user=obj, appraiser_approved=True
193-
)
194-
.aggregate(Sum("karma"))
195-
.get("karma__sum")
196-
)
197-
interest_groups.append(
198-
{"id": ig_link.ig.id, "name": ig_link.ig.name, "karma": total_ig_karma}
200+
.get("karma__sum") or 0
199201
)
202+
203+
interest_groups.append({
204+
"id": ig_level_link.ig.id,
205+
"name": ig_level_link.ig.name,
206+
"karma": total_ig_karma,
207+
"selected": ig_level_link.ig.id in selected_ig_ids,
208+
"level": {
209+
"count": ig_level_link.level.level_order,
210+
"unit": UnitType.LEVEL.value
211+
}
212+
})
213+
200214
return interest_groups
201215

202216

@@ -414,6 +428,31 @@ def update(self, instance, validated_data):
414428
if len(user_ig_links) > 3:
415429
raise CustomException("Cannot add more than 3 interest groups")
416430
UserIgLink.objects.bulk_create(user_ig_links)
431+
432+
# Initialize IG levels for newly added IGs
433+
from django.db import connection
434+
for ig_id in ig_details:
435+
# Get level 1 ID
436+
with connection.cursor() as cursor:
437+
cursor.execute("SELECT id FROM level WHERE level_order = 1 LIMIT 1")
438+
level_1_id = cursor.fetchone()
439+
if level_1_id:
440+
# UPSERT: Insert level 1 if doesn't exist, do nothing if exists
441+
cursor.execute("""
442+
INSERT INTO user_ig_lvl_link (id, user_id, ig_id, level_id, created_by, created_at, updated_by, updated_at)
443+
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
444+
ON DUPLICATE KEY UPDATE updated_at = updated_at
445+
""", [
446+
str(uuid.uuid4()),
447+
str(instance.id),
448+
str(ig_id),
449+
level_1_id[0],
450+
str(instance.id),
451+
DateTimeUtils.get_current_utc_time(),
452+
str(instance.id),
453+
DateTimeUtils.get_current_utc_time()
454+
])
455+
417456
return super().update(instance, validated_data)
418457

419458
class Meta:

api/dashboard/profile/profile_view.py

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,6 @@ def patch(self, request):
105105
user_id = JWTUtils.fetch_user_id(request)
106106
user = User.objects.get(id=user_id)
107107

108-
old_ig_links = list(user.user_ig_link_user.all())
109-
old_ig_ids = set(link.ig_id for link in old_ig_links)
110-
old_role_links = list(user.user_role_link_user.all())
111-
old_role_ids = set(link.role_id for link in old_role_links)
112-
113108
serializer = profile_serializer.UserIgEditSerializer(
114109
user, data=request.data, partial=True
115110
)
@@ -118,35 +113,7 @@ def patch(self, request):
118113
return CustomResponse(response=serializer.errors).get_failure_response()
119114

120115
serializer.save()
121-
new_ig_links = list(user.user_ig_link_user.all())
122-
new_ig_ids = set(link.ig_id for link in new_ig_links)
123-
124-
old_ig_roles = set()
125-
for ig_id in old_ig_ids:
126-
ig = InterestGroup.objects.filter(id=ig_id).first()
127-
if ig:
128-
role = Role.objects.filter(title=ig.name).first()
129-
if role:
130-
old_ig_roles.add(role.id)
131-
UserRoleLink.objects.filter(user=user, role_id__in=old_ig_roles).delete()
132-
133-
134-
new_ig_roles = set()
135-
for ig_id in new_ig_ids:
136-
ig = InterestGroup.objects.filter(id=ig_id).first()
137-
if ig:
138-
role = Role.objects.filter(title=ig.name).first()
139-
if role:
140-
new_ig_roles.add(role.id)
141-
142-
for role_id in new_ig_roles:
143-
if not UserRoleLink.objects.filter(user=user, role_id=role_id).exists():
144-
UserRoleLink.objects.create(
145-
user=user,
146-
role_id=role_id,
147-
created_by=user,
148-
verified=True,
149-
)
116+
150117

151118
DiscordWebhooks.general_updates(
152119
WebHookCategory.USER.value,

db/task.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,36 @@ class Meta:
230230
db_table = "user_ig_link"
231231

232232

233+
class UserIgLvlLink(models.Model):
234+
id = models.CharField(primary_key=True, max_length=36, default=uuid.uuid4)
235+
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="user_ig_lvl_link_user")
236+
ig = models.ForeignKey(InterestGroup, on_delete=models.CASCADE, related_name="user_ig_lvl_link_ig")
237+
level = models.ForeignKey(Level, on_delete=models.CASCADE, related_name="user_ig_lvl_link_level")
238+
updated_by = models.ForeignKey(User, on_delete=models.SET(settings.SYSTEM_ADMIN_ID), db_column="updated_by",
239+
related_name="user_ig_lvl_link_updated_by")
240+
updated_at = models.DateTimeField(auto_now=True)
241+
created_by = models.ForeignKey(User, on_delete=models.SET(settings.SYSTEM_ADMIN_ID), db_column="created_by",
242+
related_name="user_ig_lvl_link_created_by")
243+
created_at = models.DateTimeField(auto_now_add=True)
244+
245+
class Meta:
246+
managed = False
247+
db_table = "user_ig_lvl_link"
248+
unique_together = [("user", "ig")]
249+
250+
251+
class UserIgLvlLog(models.Model):
252+
id = models.CharField(primary_key=True, max_length=36, default=uuid.uuid4)
253+
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="user_ig_lvl_log_user")
254+
ig = models.ForeignKey(InterestGroup, on_delete=models.CASCADE, related_name="user_ig_lvl_log_ig")
255+
level = models.ForeignKey(Level, on_delete=models.CASCADE, related_name="user_ig_lvl_log_level")
256+
created_at = models.DateTimeField(auto_now_add=True)
257+
258+
class Meta:
259+
managed = False
260+
db_table = "user_ig_lvl_log"
261+
262+
233263
class VoucherLog(models.Model):
234264
id = models.CharField(primary_key=True, max_length=36)
235265
code = models.CharField(unique=True, max_length=255)

utils/types.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,16 @@ def get_all_values(cls):
192192
return [member.value for member in cls]
193193

194194

195+
class UnitType(Enum):
196+
LEVEL = "level"
197+
KARMA = "karma"
198+
TASK = "task"
199+
200+
@classmethod
201+
def get_all_values(cls):
202+
return [member.value for member in cls]
203+
204+
195205
DEFAULT_HACKATHON_FORM_FIELDS = {
196206
"name": "system",
197207
"gender": "system",

0 commit comments

Comments
 (0)