mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-07-04 06:42:13 +02:00
166 lines
4.1 KiB
Python
166 lines
4.1 KiB
Python
from django.db import models, transaction
|
|
from django.utils import timezone
|
|
from django.contrib.auth.models import User
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
|
class Family(models.Model):
|
|
name = models.CharField(
|
|
max_length=255,
|
|
verbose_name=_('name'),
|
|
unique=True
|
|
)
|
|
|
|
description = models.CharField(
|
|
max_length=255,
|
|
verbose_name=_('description')
|
|
)
|
|
|
|
score = models.PositiveIntegerField(
|
|
verbose_name=_('score')
|
|
)
|
|
|
|
rank = models.PositiveIntegerField(
|
|
verbose_name=_('rank'),
|
|
)
|
|
|
|
class Meta:
|
|
verbose_name = _('Family')
|
|
verbose_name_plural = _('Families')
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
|
|
class FamilyMembership(models.Model):
|
|
user = models.OneToOneField(
|
|
User,
|
|
on_delete=models.PROTECT,
|
|
related_name=_('family_memberships'),
|
|
verbose_name=_('user'),
|
|
)
|
|
|
|
family = models.ForeignKey(
|
|
Family,
|
|
on_delete=models.PROTECT,
|
|
related_name=_('members'),
|
|
verbose_name=_('family'),
|
|
)
|
|
|
|
year = models.PositiveIntegerField(
|
|
verbose_name=_('year'),
|
|
default=timezone.now().year,
|
|
)
|
|
|
|
class Meta:
|
|
verbose_name = _('family membership')
|
|
verbose_name_plural = _('family memberships')
|
|
|
|
def __str__(self):
|
|
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,
|
|
verbose_name=_('name'),
|
|
)
|
|
|
|
description = models.CharField(
|
|
max_length=255,
|
|
verbose_name=_('description'),
|
|
)
|
|
|
|
points = models.PositiveIntegerField(
|
|
verbose_name=_('points'),
|
|
)
|
|
|
|
category = models.ForeignKey(
|
|
ChallengeCategory,
|
|
verbose_name=_('category'),
|
|
on_delete=models.PROTECT
|
|
)
|
|
|
|
class Meta:
|
|
verbose_name = _('challenge')
|
|
verbose_name_plural = _('challenges')
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
|
|
class Achievement(models.Model):
|
|
challenge = models.ForeignKey(
|
|
Challenge,
|
|
on_delete=models.PROTECT,
|
|
|
|
)
|
|
family = models.ForeignKey(
|
|
Family,
|
|
on_delete=models.PROTECT,
|
|
verbose_name=_('family'),
|
|
)
|
|
|
|
obtained_at = models.DateTimeField(
|
|
verbose_name=_('obtained at'),
|
|
default=timezone.now,
|
|
)
|
|
|
|
class Meta:
|
|
verbose_name = _('achievement')
|
|
verbose_name_plural = _('achievements')
|
|
|
|
def __str__(self):
|
|
return _('Challenge {challenge} carried out by Family {family}').format(challenge=self.challenge.name, family=self.family.name, )
|
|
|
|
@transaction.atomic
|
|
def save(self, *args, **kwargs):
|
|
"""
|
|
When saving, also grants points to the family
|
|
"""
|
|
self.family = Family.objects.select_for_update().get(pk=self.family_id)
|
|
challenge_points = self.challenge.points
|
|
is_new = self.pk is None
|
|
|
|
super.save(*args, **kwargs)
|
|
|
|
# Only grant points 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()
|
|
|
|
@transaction.atomic
|
|
def delete(self, *args, **kwargs):
|
|
"""
|
|
When deleting, also removes points from the family
|
|
"""
|
|
# 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()
|