1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-07-23 01:06:47 +02:00

Models fixed

This commit is contained in:
Ehouarn
2025-07-06 18:11:09 +02:00
parent f6ad6197de
commit c7bd733911
2 changed files with 59 additions and 76 deletions

View File

@ -11,16 +11,17 @@ class Family(models.Model):
name = models.CharField(
max_length=255,
verbose_name=_('name'),
unique=True
unique=True,
)
description = models.CharField(
max_length=255,
verbose_name=_('description')
verbose_name=_('description'),
)
score = models.PositiveIntegerField(
verbose_name=_('score')
verbose_name=_('score'),
default=0,
)
rank = models.PositiveIntegerField(
@ -34,6 +35,36 @@ class Family(models.Model):
def __str__(self):
return self.name
def update_score(self, *args, **kwargs):
challenge_set = Challenge.objects.select_for_update().filter(achievement__family=self)
points_sum = challenge_set.aggregate(models.Sum("points"))
self.score = points_sum["points__sum"]
self.save()
self.update_ranking()
@staticmethod
def update_ranking(*args, **kwargs):
"""
Update ranking when adding or removing points
"""
family_set = Family.objects.select_for_update().all().order_by("-score")
for i in range(family_set.count()):
if i == 0 or family_set[i].score != family_set[i - 1].score:
new_rank = i + 1
family = family_set[i]
family.rank = new_rank
family._force_save = True
family.save()
def save(self, *args, **kwargs):
if self.rank is None:
last_family = Family.objects.order_by("rank").last()
if last_family is None or last_family.score > self.score:
self.rank = Family.objects.count() + 1
else:
self.rank = last_family.rank
super().save(*args, **kwargs)
class FamilyMembership(models.Model):
user = models.OneToOneField(
@ -64,21 +95,6 @@ class FamilyMembership(models.Model):
return _('Family membership of {user} to {family}').format(user=self.user.username, family=self.family.name, )
class ChallengeCategory(models.Model):
name = models.CharField(
max_length=255,
verbose_name=_('name'),
unique=True,
)
class Meta:
verbose_name = _('challenge category')
verbose_name_plural = _('challenge categories')
def __str__(self):
return self.name
class Challenge(models.Model):
name = models.CharField(
max_length=255,
@ -94,15 +110,18 @@ class Challenge(models.Model):
verbose_name=_('points'),
)
category = models.ForeignKey(
ChallengeCategory,
verbose_name=_('category'),
on_delete=models.PROTECT
obtained = models.PositiveIntegerField(
verbose_name=_('obtained'),
default=0,
)
obtained = models.PositiveIntegerField(
verbose_name=_('obtained')
)
@transaction.atomic
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
# Update families who already obtained this challenge
achievements = Achievement.objects.filter(challenge=self)
for achievement in achievements:
achievement.save()
class Meta:
verbose_name = _('challenge')
@ -136,20 +155,6 @@ class Achievement(models.Model):
def __str__(self):
return _('Challenge {challenge} carried out by Family {family}').format(challenge=self.challenge.name, family=self.family.name, )
@classmethod
def update_ranking(cls, *args, **kwargs):
"""
Update ranking when adding or removing points
"""
family_set = cls.objects.select_for_update().all().order_by("-score")
for i in range(family_set.count()):
if i == 0 or family_set[i].score != family_set[i - 1].score:
new_rank = i + 1
family = family_set[i]
family.rank = new_rank
family._force_save = True
family.save()
@transaction.atomic
def save(self, *args, **kwargs):
"""
@ -157,25 +162,20 @@ class Achievement(models.Model):
"""
self.family = Family.objects.select_for_update().get(pk=self.family_id)
self.challenge = Challenge.objects.select_for_update().get(pk=self.challenge_id)
challenge_points = self.challenge.points
is_new = self.pk is None
super.save(*args, **kwargs)
super().save(*args, **kwargs)
# Only grant points when getting a new achievement
self.family.refresh_from_db()
self.family.update_score()
# Count only when getting a new achievement
if is_new:
self.family.refresh_from_db()
self.family.score += challenge_points
self.family._force_save = True
self.family.save()
self.challenge.refresh_from_db()
self.challenge.obtained += 1
self.challenge._force_save = True
self.challenge.save()
self.__class__.update_ranking()
@transaction.atomic
def delete(self, *args, **kwargs):
"""
@ -183,20 +183,15 @@ class Achievement(models.Model):
"""
# Get the family and challenge before deletion
self.family = Family.objects.select_for_update().get(pk=self.family_id)
challenge_points = self.challenge.points
# Delete the achievement
super().delete(*args, **kwargs)
# Remove points from the family
self.family.refresh_from_db()
self.family.score -= challenge_points
self.family._force_save = True
self.family.save()
self.family.update_score()
self.challenge.refresh_from_db()
self.challenge.obtained -= 1
self.challenge._force_save = True
self.challenge.save()
self.__class__.update_ranking()