diff --git a/sync/admin.py b/sync/admin.py index 4b00649..16d3c77 100644 --- a/sync/admin.py +++ b/sync/admin.py @@ -8,6 +8,8 @@ class SyncedObjectAdmin(admin.ModelAdmin): if isinstance(obj, BaseModel): obj.last_updated_by = request.user obj.last_update = timezone.now() + if obj.related_user is None: + obj.related_user = request.user super().save_model(request, obj, form, change) def delete_model(self, request, obj): diff --git a/sync/models/base.py b/sync/models/base.py index 275e9f8..95ee41c 100644 --- a/sync/models/base.py +++ b/sync/models/base.py @@ -12,6 +12,11 @@ class BaseModel(models.Model): class Meta: abstract = True + def save(self, *args, **kwargs): + if self.related_user is None: + self.related_user = self.find_related_user() + super().save(*args, **kwargs) + def get_store_id(self): if isinstance(self, SideStoreModel): return self.store_id @@ -126,6 +131,27 @@ class BaseModel(models.Model): return instances + def find_related_user(self, processed_objects: Set = None): + if processed_objects is None: + processed_objects = set() + + # Skip if we've already processed this object to avoid infinite recursion + if self.pk in processed_objects: + return None + + processed_objects.add(self.pk) + + # Get immediate parents + parents_by_model = self.get_parents_by_model() + for parent in parents_by_model.values(): + if isinstance(parent, BaseModel): + if parent.related_user: + return parent.related_user + else: + return parent.find_related_user(processed_objects) + + return None + class SideStoreModel(BaseModel): store_id = models.CharField(max_length=100, default="") # a value matching LeStorage directory sub-stores. Matches the name of the directory. diff --git a/sync/views.py b/sync/views.py index 5ff0480..3d80895 100644 --- a/sync/views.py +++ b/sync/views.py @@ -120,7 +120,12 @@ class SynchronizationApi(HierarchyApiView): model = sync_registry.get_model(model_name) if model_operation == 'POST': + + if data['related_user'] is None: # affect related_user is necessary + data['related_user'] = request.user.id + serializer = serializer_class(data=data, context={'request': request}) + if serializer.is_valid(): instance = serializer.save() result = serializer.data diff --git a/tournaments/models/__init__.py b/tournaments/models/__init__.py index 6e3d720..545a5b1 100644 --- a/tournaments/models/__init__.py +++ b/tournaments/models/__init__.py @@ -1,5 +1,6 @@ from sync.models import BaseModel, SideStoreModel +from .tournament_sub_model import TournamentSubModel from .custom_user import CustomUser from .club import Club from .court import Court diff --git a/tournaments/models/draw_log.py b/tournaments/models/draw_log.py index 114a228..1424535 100644 --- a/tournaments/models/draw_log.py +++ b/tournaments/models/draw_log.py @@ -1,8 +1,8 @@ from django.db import models -from . import SideStoreModel +from . import TournamentSubModel import uuid -class DrawLog(SideStoreModel): +class DrawLog(TournamentSubModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) tournament = models.ForeignKey('Tournament', on_delete=models.SET_NULL, related_name='draw_logs', null=True) draw_date = models.DateTimeField() @@ -18,7 +18,8 @@ class DrawLog(SideStoreModel): return f'{self.draw_date}' def save(self, *args, **kwargs): - self.store_id = str(self.get_tournament_id()) + if self.tournament: + self.store_id = str(self.tournament.id) super().save(*args, **kwargs) def get_tournament_id(self): diff --git a/tournaments/models/group_stage.py b/tournaments/models/group_stage.py index 5c43b3c..f53bfdf 100644 --- a/tournaments/models/group_stage.py +++ b/tournaments/models/group_stage.py @@ -1,14 +1,14 @@ # from asyncio.streams import StreamReaderProtocol from django.db import models -from . import SideStoreModel, Tournament, FederalMatchCategory +from . import TournamentSubModel, Tournament, FederalMatchCategory import uuid from ..utils.extensions import format_seconds from datetime import timedelta from django.utils import timezone from django.db.models import Count, Q -class GroupStage(SideStoreModel): +class GroupStage(TournamentSubModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) tournament = models.ForeignKey(Tournament, on_delete=models.SET_NULL, related_name='group_stages', null=True, blank=True) index = models.IntegerField(default=0) @@ -29,15 +29,18 @@ class GroupStage(SideStoreModel): def __str__(self): return self.display_name() - def save(self, *args, **kwargs): - self.store_id = str(self.get_tournament_id()) - super().save(*args, **kwargs) + def get_tournament(self): # mandatory method for TournamentSubModel + return self.tournament - def get_tournament_id(self): - if self.tournament: - return self.tournament.id - else: - return None + # def save(self, *args, **kwargs): + # self.store_id = str(self.get_tournament_id()) + # super().save(*args, **kwargs) + + # def get_tournament_id(self): + # if self.tournament: + # return self.tournament.id + # else: + # return None def display_name(self): if self.name: diff --git a/tournaments/models/match.py b/tournaments/models/match.py index 302bf17..f846598 100644 --- a/tournaments/models/match.py +++ b/tournaments/models/match.py @@ -1,6 +1,6 @@ from django.db import models # from tournaments.models import group_stage -from . import SideStoreModel, Round, GroupStage, FederalMatchCategory +from . import TournamentSubModel, Round, GroupStage, FederalMatchCategory from django.utils import timezone, formats from datetime import datetime, timedelta @@ -8,7 +8,7 @@ import uuid from ..utils.extensions import format_seconds -class Match(SideStoreModel): +class Match(TournamentSubModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) round = models.ForeignKey(Round, null=True, blank=True, on_delete=models.SET_NULL, related_name='matches') group_stage = models.ForeignKey(GroupStage, null=True, blank=True, on_delete=models.SET_NULL, related_name='matches') @@ -39,29 +39,29 @@ class Match(SideStoreModel): else: return f"{self.stage_name()}" - def save(self, *args, **kwargs): - self.store_id = str(self.get_tournament_id()) - super().save(*args, **kwargs) + # def save(self, *args, **kwargs): + # self.store_id = str(self.get_tournament_id()) + # super().save(*args, **kwargs) - def tournament(self): + def get_tournament(self): # mandatory method for TournamentSubModel if self.round: return self.round.tournament elif self.group_stage: return self.group_stage.tournament return None - def get_tournament_id(self): - tournament = self.tournament() - if tournament: - return tournament.id - else: - return None + # def get_tournament_id(self): + # tournament = self.get_tournament() + # if tournament: + # return tournament.id + # else: + # return None def court_name(self, index): club = None - tournament = self.tournament() + tournament = self.get_tournament() if tournament and tournament.event: - club = self.tournament().event.club + club = self.get_tournament().event.club if club: return club.court_name(index) @@ -167,7 +167,6 @@ class Match(SideStoreModel): return self.index - def player_names(self): return map(lambda ts: ts.player_names(), self.team_scores.all()) @@ -303,7 +302,7 @@ class Match(SideStoreModel): return teams def local_start_date(self): - timezone = self.tournament().timezone() + timezone = self.get_tournament().timezone() return self.start_date.astimezone(timezone) def formatted_start_date(self): @@ -327,10 +326,10 @@ class Match(SideStoreModel): return 'À suivre' else: # timezoned_datetime = timezone.localtime(self.start_date) - timezone = self.tournament().timezone() + timezone = self.get_tournament().timezone() local_start = self.start_date.astimezone(timezone) time_format ='l H:i' - if self.tournament().day_duration >= 7: + if self.get_tournament().day_duration >= 7: time_format = 'l d M à H:i' if self.confirmed: return formats.date_format(local_start, format=time_format) diff --git a/tournaments/models/player_registration.py b/tournaments/models/player_registration.py index b79cace..6b1568d 100644 --- a/tournaments/models/player_registration.py +++ b/tournaments/models/player_registration.py @@ -1,9 +1,9 @@ from django.db import models -from . import SideStoreModel, TeamRegistration, PlayerSexType, PlayerDataSource, PlayerPaymentType, OnlineRegistrationStatus +from . import TournamentSubModel, TeamRegistration, PlayerSexType, PlayerDataSource, PlayerPaymentType, OnlineRegistrationStatus import uuid from django.utils import timezone -class PlayerRegistration(SideStoreModel): +class PlayerRegistration(TournamentSubModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) team_registration = models.ForeignKey(TeamRegistration, on_delete=models.SET_NULL, related_name='player_registrations', null=True) first_name = models.CharField(max_length=50, blank=True) @@ -44,16 +44,22 @@ class PlayerRegistration(SideStoreModel): def __str__(self): return self.name() - def save(self, *args, **kwargs): - self.store_id = str(self.get_tournament_id()) - super().save(*args, **kwargs) - - def get_tournament_id(self): - if self.team_registration and self.team_registration.tournament: - return self.team_registration.tournament.id + def get_tournament(self): # mandatory method for TournamentSubModel + if self.team_registration: + return self.team_registration.tournament else: return None + # def save(self, *args, **kwargs): + # self.store_id = str(self.get_tournament_id()) + # super().save(*args, **kwargs) + + # def get_tournament_id(self): + # if self.team_registration and self.team_registration.tournament: + # return self.team_registration.tournament.id + # else: + # return None + def name(self): return f"{self.first_name} {self.last_name}" diff --git a/tournaments/models/round.py b/tournaments/models/round.py index 6d89a8c..2bb7204 100644 --- a/tournaments/models/round.py +++ b/tournaments/models/round.py @@ -1,8 +1,8 @@ from django.db import models -from . import SideStoreModel, Tournament, FederalMatchCategory +from . import TournamentSubModel, Tournament, FederalMatchCategory import uuid -class Round(SideStoreModel): +class Round(TournamentSubModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) tournament = models.ForeignKey(Tournament, on_delete=models.SET_NULL, related_name='rounds', null=True) index = models.IntegerField(default=0) @@ -26,15 +26,8 @@ class Round(SideStoreModel): else: return self.name() - def save(self, *args, **kwargs): - self.store_id = str(self.get_tournament_id()) - super().save(*args, **kwargs) - - def get_tournament_id(self): - if self.tournament: - return self.tournament.id - else: - return None + def get_tournament(self): # mandatory method for TournamentSubModel + return self.tournament def name(self): if self.parent and self.parent.parent is None: diff --git a/tournaments/models/team_registration.py b/tournaments/models/team_registration.py index d2360fe..6ff5168 100644 --- a/tournaments/models/team_registration.py +++ b/tournaments/models/team_registration.py @@ -1,9 +1,9 @@ from django.db import models -from . import SideStoreModel, Tournament, GroupStage, Match +from . import TournamentSubModel, Tournament, GroupStage, Match import uuid from django.utils import timezone -class TeamRegistration(SideStoreModel): +class TeamRegistration(TournamentSubModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) tournament = models.ForeignKey(Tournament, on_delete=models.SET_NULL, related_name='team_registrations', null=True) group_stage = models.ForeignKey(GroupStage, null=True, blank=True, on_delete=models.SET_NULL, related_name='team_registrations') @@ -43,15 +43,8 @@ class TeamRegistration(SideStoreModel): # return f"{self.name}: {self.player_names()}" return self.player_names() - def save(self, *args, **kwargs): - self.store_id = str(self.get_tournament_id()) - super().save(*args, **kwargs) - - def get_tournament_id(self): - if self.tournament: - return self.tournament.id - else: - return None + def get_tournament(self): # mandatory method for TournamentSubModel + return self.tournament def player_names_as_list(self): players = list(self.player_registrations.all()) diff --git a/tournaments/models/team_score.py b/tournaments/models/team_score.py index cbf9eee..0ca950f 100644 --- a/tournaments/models/team_score.py +++ b/tournaments/models/team_score.py @@ -1,9 +1,9 @@ from django.db import models -from . import SideStoreModel, Match, TeamRegistration, FederalMatchCategory +from . import TournamentSubModel, Match, TeamRegistration, FederalMatchCategory import uuid from .match import Team # Import Team only when needed -class TeamScore(SideStoreModel): +class TeamScore(TournamentSubModel): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) match = models.ForeignKey(Match, on_delete=models.SET_NULL, related_name="team_scores", null=True) team_registration = models.ForeignKey(TeamRegistration, on_delete=models.SET_NULL, null=True, blank=True, related_name="team_scores") @@ -20,24 +20,32 @@ class TeamScore(SideStoreModel): else: return "Empty" - def save(self, *args, **kwargs): - self.store_id = str(self.get_tournament_id()) - super().save(*args, **kwargs) - - def tournament(self): + def get_tournament(self): # mandatory method for TournamentSubModel if self.team_registration: return self.team_registration.tournament elif self.match: - return self.match.tournament() + return self.match.get_tournament() else: return None - def get_tournament_id(self): - tournament = self.tournament() - if tournament: - return tournament.id - else: - return None + # def save(self, *args, **kwargs): + # self.store_id = str(self.get_tournament_id()) + # super().save(*args, **kwargs) + + # def tournament(self): + # if self.team_registration: + # return self.team_registration.tournament + # elif self.match: + # return self.match.tournament() + # else: + # return None + + # def get_tournament_id(self): + # tournament = self.tournament() + # if tournament: + # return tournament.id + # else: + # return None def player_names(self): if self.team_registration: diff --git a/tournaments/models/tournament_sub_model.py b/tournaments/models/tournament_sub_model.py new file mode 100644 index 0000000..2d7f354 --- /dev/null +++ b/tournaments/models/tournament_sub_model.py @@ -0,0 +1,12 @@ +from . import SideStoreModel + +class TournamentSubModel(SideStoreModel): + + def save(self, *args, **kwargs): + tournament = self.get_tournament() + if tournament: + self.store_id = str(tournament.id) + super().save(*args, **kwargs) + + class Meta: + abstract = True diff --git a/tournaments/views.py b/tournaments/views.py index 61ca4a8..cf7ff98 100644 --- a/tournaments/views.py +++ b/tournaments/views.py @@ -682,8 +682,7 @@ def signup(request): user.origin = UserOrigin.SITE user.save() - if not settings.DEBUG: - send_verification_email(request, user, next_url) + send_verification_email(request, user, next_url) return render(request, 'registration/signup_success.html', { 'next_url': next_url,