mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-07-06 15:24:01 +02:00
Models
This commit is contained in:
165
apps/family/models.py
Normal file
165
apps/family/models.py
Normal file
@ -0,0 +1,165 @@
|
||||
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()
|
Reference in New Issue
Block a user