113 lines
3.4 KiB
Python
113 lines
3.4 KiB
Python
from django.db import models
|
|
from django.core.exceptions import ValidationError
|
|
|
|
# products/models.py
|
|
from django.db import models
|
|
|
|
|
|
class ReusableAutoField(models.PositiveIntegerField):
|
|
"""A django auto field that can reuse deleted primary keys"""
|
|
|
|
def get_next_available_id(self, model_cls, using=None):
|
|
"""
|
|
Returns the next available id for the given model class.
|
|
"""
|
|
all_ids = set(range(1, model_cls._default_manager.count()+1))
|
|
used_ids = set(model_cls._default_manager.all().values_list('pk', flat=True))
|
|
available_ids = all_ids - used_ids
|
|
|
|
if available_ids:
|
|
return min(available_ids)
|
|
|
|
if used_ids:
|
|
return max(used_ids) + 1
|
|
|
|
return 1
|
|
|
|
def get_default(self):
|
|
"""Returns the default value for this field"""
|
|
|
|
return self.get_next_available_id(self.model)
|
|
|
|
|
|
class Peg(models.Model):
|
|
"""Represents a person's peg"""
|
|
|
|
peg_number = ReusableAutoField(primary_key=True, default=ReusableAutoField.get_default, editable=False)
|
|
|
|
def __str__(self):
|
|
return f"Peg {self.peg_number}"
|
|
|
|
|
|
def validate_team_size(value):
|
|
if Member.objects.filter(team=value).count() >= 3:
|
|
raise ValidationError('Team already has maximal amount of members (3)')
|
|
|
|
|
|
class Member(models.Model):
|
|
"""Represents a member of a team"""
|
|
|
|
first_name = models.CharField(max_length=255)
|
|
last_name = models.CharField(max_length=255)
|
|
team = models.ForeignKey("Team", on_delete=models.SET_NULL, null=True, blank=True, validators=(validate_team_size,), related_name='members')
|
|
# peg = models.OneToOneField("Peg", on_delete=models.SET_NULL, null=True, blank=True)
|
|
|
|
def __str__(self):
|
|
return f"{self.first_name} {self.last_name} (team {self.team.team_number}))"
|
|
|
|
@property
|
|
def fullname(self) -> str:
|
|
return f"{self.first_name} {self.last_name}"
|
|
|
|
|
|
class Team(models.Model):
|
|
"""Represents a team"""
|
|
|
|
team_number = ReusableAutoField(primary_key=True, default=ReusableAutoField.get_default, editable=False)
|
|
section = models.OneToOneField("Section", on_delete=models.SET_NULL, null=True, blank=True)
|
|
|
|
def __str__(self):
|
|
return f"Team {self.team_number}"
|
|
|
|
@property
|
|
def members(self) -> list[Member]:
|
|
Member.objects.filter(team=self)
|
|
|
|
|
|
def validate_section_character(value):
|
|
"""Validates the section character"""
|
|
|
|
value = value.upper()
|
|
banned_characters = ["I"]
|
|
|
|
if value in banned_characters:
|
|
raise ValidationError(f"The character <{value}> is a prohibited character.")
|
|
|
|
|
|
class Section(models.Model):
|
|
"""Represents a section of the scoreboard"""
|
|
|
|
# character field stores a single character but doesnt allow for 'I' or 'i'
|
|
character = models.CharField(primary_key=True, max_length=1, validators=(validate_section_character, ))
|
|
|
|
def clean(self):
|
|
self.character = self.character.upper()
|
|
|
|
def __str__(self):
|
|
return f"Section {self.character}"
|
|
|
|
|
|
#class Scoreboard(models.Model):
|
|
# class Status(models.IntegerChoices):
|
|
# ACTIVE = 1, "Active"
|
|
# INACTIVE = 2, "Inactive"
|
|
# ARCHIVED = 3, "Archived"
|
|
#
|
|
# name = models.CharField(max_length=255)
|
|
# category = models.CharField(max_length=255)
|
|
# price = models.DecimalField(max_digits=10, decimal_places=2)
|
|
# cost = models.DecimalField(max_digits=10, decimal_places=2)
|
|
# status = models.PositiveSmallIntegerField(choices=Status.choices)
|
|
#
|
|
# def __str__(self):
|
|
# return self.name |