Synchronization fix and improvement

sync_v2
Laurent 7 months ago
parent d25893698d
commit 98a8bf3d12
  1. 2
      sync/admin.py
  2. 26
      sync/models/base.py
  3. 5
      sync/views.py
  4. 1
      tournaments/models/__init__.py
  5. 7
      tournaments/models/draw_log.py
  6. 23
      tournaments/models/group_stage.py
  7. 35
      tournaments/models/match.py
  8. 24
      tournaments/models/player_registration.py
  9. 15
      tournaments/models/round.py
  10. 15
      tournaments/models/team_registration.py
  11. 36
      tournaments/models/team_score.py
  12. 12
      tournaments/models/tournament_sub_model.py
  13. 3
      tournaments/views.py

@ -8,6 +8,8 @@ class SyncedObjectAdmin(admin.ModelAdmin):
if isinstance(obj, BaseModel): if isinstance(obj, BaseModel):
obj.last_updated_by = request.user obj.last_updated_by = request.user
obj.last_update = timezone.now() obj.last_update = timezone.now()
if obj.related_user is None:
obj.related_user = request.user
super().save_model(request, obj, form, change) super().save_model(request, obj, form, change)
def delete_model(self, request, obj): def delete_model(self, request, obj):

@ -12,6 +12,11 @@ class BaseModel(models.Model):
class Meta: class Meta:
abstract = True 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): def get_store_id(self):
if isinstance(self, SideStoreModel): if isinstance(self, SideStoreModel):
return self.store_id return self.store_id
@ -126,6 +131,27 @@ class BaseModel(models.Model):
return instances 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): class SideStoreModel(BaseModel):
store_id = models.CharField(max_length=100, default="") # a value matching LeStorage directory sub-stores. Matches the name of the directory. store_id = models.CharField(max_length=100, default="") # a value matching LeStorage directory sub-stores. Matches the name of the directory.

@ -120,7 +120,12 @@ class SynchronizationApi(HierarchyApiView):
model = sync_registry.get_model(model_name) model = sync_registry.get_model(model_name)
if model_operation == 'POST': 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}) serializer = serializer_class(data=data, context={'request': request})
if serializer.is_valid(): if serializer.is_valid():
instance = serializer.save() instance = serializer.save()
result = serializer.data result = serializer.data

@ -1,5 +1,6 @@
from sync.models import BaseModel, SideStoreModel from sync.models import BaseModel, SideStoreModel
from .tournament_sub_model import TournamentSubModel
from .custom_user import CustomUser from .custom_user import CustomUser
from .club import Club from .club import Club
from .court import Court from .court import Court

@ -1,8 +1,8 @@
from django.db import models from django.db import models
from . import SideStoreModel from . import TournamentSubModel
import uuid import uuid
class DrawLog(SideStoreModel): class DrawLog(TournamentSubModel):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) 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) tournament = models.ForeignKey('Tournament', on_delete=models.SET_NULL, related_name='draw_logs', null=True)
draw_date = models.DateTimeField() draw_date = models.DateTimeField()
@ -18,7 +18,8 @@ class DrawLog(SideStoreModel):
return f'{self.draw_date}' return f'{self.draw_date}'
def save(self, *args, **kwargs): 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) super().save(*args, **kwargs)
def get_tournament_id(self): def get_tournament_id(self):

@ -1,14 +1,14 @@
# from asyncio.streams import StreamReaderProtocol # from asyncio.streams import StreamReaderProtocol
from django.db import models from django.db import models
from . import SideStoreModel, Tournament, FederalMatchCategory from . import TournamentSubModel, Tournament, FederalMatchCategory
import uuid import uuid
from ..utils.extensions import format_seconds from ..utils.extensions import format_seconds
from datetime import timedelta from datetime import timedelta
from django.utils import timezone from django.utils import timezone
from django.db.models import Count, Q from django.db.models import Count, Q
class GroupStage(SideStoreModel): class GroupStage(TournamentSubModel):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) 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) tournament = models.ForeignKey(Tournament, on_delete=models.SET_NULL, related_name='group_stages', null=True, blank=True)
index = models.IntegerField(default=0) index = models.IntegerField(default=0)
@ -29,15 +29,18 @@ class GroupStage(SideStoreModel):
def __str__(self): def __str__(self):
return self.display_name() return self.display_name()
def save(self, *args, **kwargs): def get_tournament(self): # mandatory method for TournamentSubModel
self.store_id = str(self.get_tournament_id()) return self.tournament
super().save(*args, **kwargs)
def get_tournament_id(self): # def save(self, *args, **kwargs):
if self.tournament: # self.store_id = str(self.get_tournament_id())
return self.tournament.id # super().save(*args, **kwargs)
else:
return None # def get_tournament_id(self):
# if self.tournament:
# return self.tournament.id
# else:
# return None
def display_name(self): def display_name(self):
if self.name: if self.name:

@ -1,6 +1,6 @@
from django.db import models from django.db import models
# from tournaments.models import group_stage # 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 django.utils import timezone, formats
from datetime import datetime, timedelta from datetime import datetime, timedelta
@ -8,7 +8,7 @@ import uuid
from ..utils.extensions import format_seconds from ..utils.extensions import format_seconds
class Match(SideStoreModel): class Match(TournamentSubModel):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) 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') 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') 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: else:
return f"{self.stage_name()}" return f"{self.stage_name()}"
def save(self, *args, **kwargs): # def save(self, *args, **kwargs):
self.store_id = str(self.get_tournament_id()) # self.store_id = str(self.get_tournament_id())
super().save(*args, **kwargs) # super().save(*args, **kwargs)
def tournament(self): def get_tournament(self): # mandatory method for TournamentSubModel
if self.round: if self.round:
return self.round.tournament return self.round.tournament
elif self.group_stage: elif self.group_stage:
return self.group_stage.tournament return self.group_stage.tournament
return None return None
def get_tournament_id(self): # def get_tournament_id(self):
tournament = self.tournament() # tournament = self.get_tournament()
if tournament: # if tournament:
return tournament.id # return tournament.id
else: # else:
return None # return None
def court_name(self, index): def court_name(self, index):
club = None club = None
tournament = self.tournament() tournament = self.get_tournament()
if tournament and tournament.event: if tournament and tournament.event:
club = self.tournament().event.club club = self.get_tournament().event.club
if club: if club:
return club.court_name(index) return club.court_name(index)
@ -167,7 +167,6 @@ class Match(SideStoreModel):
return self.index return self.index
def player_names(self): def player_names(self):
return map(lambda ts: ts.player_names(), self.team_scores.all()) return map(lambda ts: ts.player_names(), self.team_scores.all())
@ -303,7 +302,7 @@ class Match(SideStoreModel):
return teams return teams
def local_start_date(self): def local_start_date(self):
timezone = self.tournament().timezone() timezone = self.get_tournament().timezone()
return self.start_date.astimezone(timezone) return self.start_date.astimezone(timezone)
def formatted_start_date(self): def formatted_start_date(self):
@ -327,10 +326,10 @@ class Match(SideStoreModel):
return 'À suivre' return 'À suivre'
else: else:
# timezoned_datetime = timezone.localtime(self.start_date) # timezoned_datetime = timezone.localtime(self.start_date)
timezone = self.tournament().timezone() timezone = self.get_tournament().timezone()
local_start = self.start_date.astimezone(timezone) local_start = self.start_date.astimezone(timezone)
time_format ='l H:i' 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' time_format = 'l d M à H:i'
if self.confirmed: if self.confirmed:
return formats.date_format(local_start, format=time_format) return formats.date_format(local_start, format=time_format)

@ -1,9 +1,9 @@
from django.db import models from django.db import models
from . import SideStoreModel, TeamRegistration, PlayerSexType, PlayerDataSource, PlayerPaymentType, OnlineRegistrationStatus from . import TournamentSubModel, TeamRegistration, PlayerSexType, PlayerDataSource, PlayerPaymentType, OnlineRegistrationStatus
import uuid import uuid
from django.utils import timezone from django.utils import timezone
class PlayerRegistration(SideStoreModel): class PlayerRegistration(TournamentSubModel):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) 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) 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) first_name = models.CharField(max_length=50, blank=True)
@ -44,16 +44,22 @@ class PlayerRegistration(SideStoreModel):
def __str__(self): def __str__(self):
return self.name() return self.name()
def save(self, *args, **kwargs): def get_tournament(self): # mandatory method for TournamentSubModel
self.store_id = str(self.get_tournament_id()) if self.team_registration:
super().save(*args, **kwargs) return self.team_registration.tournament
def get_tournament_id(self):
if self.team_registration and self.team_registration.tournament:
return self.team_registration.tournament.id
else: else:
return None 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): def name(self):
return f"{self.first_name} {self.last_name}" return f"{self.first_name} {self.last_name}"

@ -1,8 +1,8 @@
from django.db import models from django.db import models
from . import SideStoreModel, Tournament, FederalMatchCategory from . import TournamentSubModel, Tournament, FederalMatchCategory
import uuid import uuid
class Round(SideStoreModel): class Round(TournamentSubModel):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) 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) tournament = models.ForeignKey(Tournament, on_delete=models.SET_NULL, related_name='rounds', null=True)
index = models.IntegerField(default=0) index = models.IntegerField(default=0)
@ -26,15 +26,8 @@ class Round(SideStoreModel):
else: else:
return self.name() return self.name()
def save(self, *args, **kwargs): def get_tournament(self): # mandatory method for TournamentSubModel
self.store_id = str(self.get_tournament_id()) return self.tournament
super().save(*args, **kwargs)
def get_tournament_id(self):
if self.tournament:
return self.tournament.id
else:
return None
def name(self): def name(self):
if self.parent and self.parent.parent is None: if self.parent and self.parent.parent is None:

@ -1,9 +1,9 @@
from django.db import models from django.db import models
from . import SideStoreModel, Tournament, GroupStage, Match from . import TournamentSubModel, Tournament, GroupStage, Match
import uuid import uuid
from django.utils import timezone from django.utils import timezone
class TeamRegistration(SideStoreModel): class TeamRegistration(TournamentSubModel):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True) 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) 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') 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 f"{self.name}: {self.player_names()}"
return self.player_names() return self.player_names()
def save(self, *args, **kwargs): def get_tournament(self): # mandatory method for TournamentSubModel
self.store_id = str(self.get_tournament_id()) return self.tournament
super().save(*args, **kwargs)
def get_tournament_id(self):
if self.tournament:
return self.tournament.id
else:
return None
def player_names_as_list(self): def player_names_as_list(self):
players = list(self.player_registrations.all()) players = list(self.player_registrations.all())

@ -1,9 +1,9 @@
from django.db import models from django.db import models
from . import SideStoreModel, Match, TeamRegistration, FederalMatchCategory from . import TournamentSubModel, Match, TeamRegistration, FederalMatchCategory
import uuid import uuid
from .match import Team # Import Team only when needed 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) 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) 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") 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: else:
return "Empty" return "Empty"
def save(self, *args, **kwargs): def get_tournament(self): # mandatory method for TournamentSubModel
self.store_id = str(self.get_tournament_id())
super().save(*args, **kwargs)
def tournament(self):
if self.team_registration: if self.team_registration:
return self.team_registration.tournament return self.team_registration.tournament
elif self.match: elif self.match:
return self.match.tournament() return self.match.get_tournament()
else: else:
return None return None
def get_tournament_id(self): # def save(self, *args, **kwargs):
tournament = self.tournament() # self.store_id = str(self.get_tournament_id())
if tournament: # super().save(*args, **kwargs)
return tournament.id
else: # def tournament(self):
return None # 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): def player_names(self):
if self.team_registration: if self.team_registration:

@ -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

@ -682,8 +682,7 @@ def signup(request):
user.origin = UserOrigin.SITE user.origin = UserOrigin.SITE
user.save() 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', { return render(request, 'registration/signup_success.html', {
'next_url': next_url, 'next_url': next_url,

Loading…
Cancel
Save