merge main + improvements

sync
Laurent 11 months ago
commit 3326eae98b
  1. 2
      .gitignore
  2. 54
      api/serializers.py
  3. 1
      api/urls.py
  4. 32
      api/views.py
  5. 0
      crm/__init__.py
  6. 1
      crm/_instructions/base.md
  7. 96
      crm/admin.py
  8. 5
      crm/apps.py
  9. 18
      crm/filters.py
  10. 40
      crm/forms.py
  11. 94
      crm/migrations/0001_initial.py
  12. 60
      crm/migrations/0002_alter_event_options_alter_prospect_options_and_more.py
  13. 0
      crm/migrations/__init__.py
  14. 6
      crm/mixins.py
  15. 112
      crm/models.py
  16. 43
      crm/services.py
  17. 10
      crm/static/js/prospect_list.js
  18. 31
      crm/templates/crm/add_prospect.html
  19. 71
      crm/templates/crm/base.html
  20. 27
      crm/templates/crm/event_form.html
  21. 16
      crm/templates/crm/event_row.html
  22. 58
      crm/templates/crm/events.html
  23. 57
      crm/templates/crm/prospect_list.html
  24. 47
      crm/templates/crm/send_bulk_email.html
  25. 0
      crm/templatetags/__init__.py
  26. 7
      crm/templatetags/crm_tags.py
  27. 3
      crm/tests.py
  28. 15
      crm/urls.py
  29. 186
      crm/views.py
  30. 2
      padelclub_backend/settings.py
  31. 2
      padelclub_backend/settings_local.py.dist
  32. 1
      padelclub_backend/urls.py
  33. 7
      requirements.txt
  34. 51
      shared/cryptography.py
  35. 2
      sync/models/base.py
  36. 0
      tmp/csv/dir_required_for_xls_conversion.txt
  37. BIN
      tmp/csv/inscriptions-4.xls
  38. BIN
      tmp/csv/inscriptions-4_Ayeaz16.xls
  39. BIN
      tmp/csv/inscriptions-4_Iplv4wH.xls
  40. 1
      tmp/data.json
  41. 174872
      tmp/dump.json
  42. 36063
      tmp/p250.json
  43. 10
      tmp/token.json
  44. 618
      tmp/user.json
  45. 642
      tmp/user2.json
  46. 928
      tmp/users.json
  47. 48
      tournaments/admin.py
  48. 5
      tournaments/forms.py
  49. 18
      tournaments/migrations/0080_alter_club_acronym.py
  50. 24
      tournaments/migrations/0080_modellog.py
  51. 18
      tournaments/migrations/0081_alter_modellog_operation.py
  52. 18
      tournaments/migrations/0081_round_group_stage_loser_bracket.py
  53. 18
      tournaments/migrations/0082_alter_modellog_operation.py
  54. 23
      tournaments/migrations/0082_alter_purchase_identifier_and_more.py
  55. 20
      tournaments/migrations/0083_modellog_creator.py
  56. 18
      tournaments/migrations/0083_purchase_expiration_date.py
  57. 28
      tournaments/migrations/0084_customuser_loser_bracket_mode_and_more.py
  58. 22
      tournaments/migrations/0084_remove_purchase_id_alter_purchase_identifier.py
  59. 18
      tournaments/migrations/0084_rename_creator_modellog_user.py
  60. 18
      tournaments/migrations/0085_modellog_store_id.py
  61. 18
      tournaments/migrations/0085_rename_identifier_purchase_id.py
  62. 154
      tournaments/migrations/0086_club_creation_date_club_last_update_and_more.py
  63. 14
      tournaments/migrations/0086_merge_20240919_1142.py
  64. 18
      tournaments/migrations/0087_alter_playerregistration_phone_number.py
  65. 17
      tournaments/migrations/0087_remove_modellog_store_id.py
  66. 19
      tournaments/migrations/0088_customuser_last_update.py
  67. 18
      tournaments/migrations/0088_groupstage_step.py
  68. 18
      tournaments/migrations/0089_alter_playerregistration_licence_id.py
  69. 49
      tournaments/migrations/0089_groupstage_store_id_match_store_id_and_more.py
  70. 79
      tournaments/migrations/0090_dynamic_store_id.py
  71. 23
      tournaments/migrations/0090_tournament_initial_seed_count_and_more.py
  72. 26
      tournaments/migrations/0091_drawlog.py
  73. 18
      tournaments/migrations/0091_modellog_store_id.py
  74. 18
      tournaments/migrations/0092_club_timezone.py
  75. 27
      tournaments/migrations/0092_dataaccess.py
  76. 63
      tournaments/migrations/0093_drawlog_draw_type_and_more.py
  77. 23
      tournaments/migrations/0093_modellog_parent_model_id_modellog_parent_model_name.py
  78. 58
      tournaments/migrations/0094_alter_customuser_bracket_match_format_preference_and_more.py
  79. 23
      tournaments/migrations/0094_remove_dataaccess_shared_with_dataaccess_shared_with.py
  80. 396
      tournaments/migrations/0095_club_creation_date_club_last_update_and_more.py
  81. 25
      tournaments/migrations/0095_remove_dataaccess_shared_with_dataaccess_shared_with.py
  82. 28
      tournaments/migrations/0096_alter_modellog_operation_and_more.py
  83. 30
      tournaments/migrations/0096_special_store_id.py
  84. 190
      tournaments/migrations/0097_club_last_updated_by_court_last_updated_by_and_more.py
  85. 108
      tournaments/migrations/0098_remove_club_last_updated_by_and_more.py
  86. 19
      tournaments/migrations/0099_dataaccess_last_hierarchy_update.py
  87. 100
      tournaments/migrations/0100_club_last_updated_by_court_last_updated_by_and_more.py
  88. 23
      tournaments/migrations/0101_remove_modellog_user_modellog_users.py
  89. 17
      tournaments/migrations/0102_remove_dataaccess_last_hierarchy_update.py
  90. 23
      tournaments/migrations/0103_remove_modellog_users_delete_dataaccess_and_more.py
  91. 19
      tournaments/migrations/0104_customuser_referees.py
  92. 18
      tournaments/migrations/0105_rename_referees_customuser_agents.py
  93. 165
      tournaments/migrations/0106_club_related_user_court_related_user_and_more.py
  94. 29
      tournaments/migrations/0107_remove_devicetoken_creation_date_and_more.py
  95. 3
      tournaments/models/__init__.py
  96. 15
      tournaments/models/club.py
  97. 3
      tournaments/models/custom_user.py
  98. 22
      tournaments/models/draw_log.py
  99. 21
      tournaments/models/enums.py
  100. 2
      tournaments/models/event.py
  101. Some files were not shown because too many files have changed in this diff Show More

2
.gitignore vendored

@ -6,7 +6,7 @@ padelclub_backend/settings_local.py
myenv/
tournaments/config_local.py
shared/config_local.py
# Byte-compiled / optimized / DLL files
__pycache__/

@ -9,10 +9,25 @@ from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.encoding import force_bytes
from django.core.mail import EmailMessage
from django.contrib.sites.shortcuts import get_current_site
from api.tokens import account_activation_token
# from tournaments.models.data_access import DataAccess
from shared.cryptography import encryption_util
from tournaments.models.draw_log import DrawLog
class EncryptedUserField(serializers.Field):
def to_representation(self, value):
# Encrypt data when sending it out
return encryption_util.encrypt_aes_gcm(str(value.id))
def to_internal_value(self, data):
# Decrypt data when receiving it
decrypted_user_id = encryption_util.decrypt_aes_gcm(data)
user = CustomUser.objects.get(id=decrypted_user_id)
if decrypted_user_id is None:
raise serializers.ValidationError("Invalid encrypted data")
return user
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
@ -55,6 +70,7 @@ class UserSerializer(serializers.ModelSerializer):
bracket_match_format_preference=validated_data.get('bracket_match_format_preference'),
group_stage_match_format_preference=validated_data.get('group_stage_match_format_preference'),
loser_bracket_match_format_preference=validated_data.get('loser_bracket_match_format_preference'),
loser_bracket_mode=validated_data.get('loser_bracket_mode'),
)
self.send_email(self.context['request'], user)
@ -104,27 +120,17 @@ class TournamentSerializer(serializers.ModelSerializer):
class Meta:
model = Tournament
fields = '__all__'
# ['id', 'name', 'event', 'creator_id', 'start_date', 'end_date', 'creation_date',
# 'is_private', 'format', 'group_stage_format', 'round_format', 'loser_round_format', 'bracket_sort_mode',
# 'group_stage_count', 'rank_source_date', 'day_duration', 'team_count', 'team_sorting',
# 'federal_category', 'federal_level_category', 'federal_age_category', 'group_stage_court_count',
# 'seed_count', 'closed_registration_date', 'group_stage_additional_qualified', 'court_count', 'prioritize_club_members',
# 'qualified_per_group_stage', 'teams_per_group_stage']
class EventSerializer(serializers.ModelSerializer):
class Meta:
#club_id = serializers.PrimaryKeyRelatedField(queryset=Club.objects.all())
model = Event
fields = '__all__'
# ['id', 'club_id', 'date', 'name', 'federal_tournament_data', 'court_count', 'tenup_id',
# 'group_stage_format', 'round_format', 'loser_round_format']
class RoundSerializer(serializers.ModelSerializer):
class Meta:
# tournament_id = serializers.PrimaryKeyRelatedField(queryset=Tournament.objects.all())
# loser_id = serializers.PrimaryKeyRelatedField(queryset=Round.objects.all())
model = Round
fields = '__all__' #['id', 'index', 'tournament_id', 'loser', 'format']
fields = '__all__'
class GroupStageSerializer(serializers.ModelSerializer):
class Meta:
@ -133,38 +139,26 @@ class GroupStageSerializer(serializers.ModelSerializer):
class MatchSerializer(serializers.ModelSerializer):
class Meta:
# round_id = serializers.PrimaryKeyRelatedField(queryset=Round.objects.all())
# group_stage_id = serializers.PrimaryKeyRelatedField(queryset=GroupStage.objects.all())
model = Match
fields = '__all__'
# ['id', 'round_id', 'group_stage_id', 'index', 'format', 'court', 'start_date', 'end_date',
# 'serving_team_id', 'winning_team_id', 'losing_team_id']
class TeamScoreSerializer(serializers.ModelSerializer):
class Meta:
# match_id = serializers.PrimaryKeyRelatedField(queryset=Match.objects.all())
# player_registrations_ids = serializers.Man
model = TeamScore
fields = '__all__' # ['id', 'match_id', 'score', 'walk_out', 'lucky_loser', 'player_registrations']
class TeamRegistrationSerializer(serializers.ModelSerializer):
class Meta:
# match_id = serializers.PrimaryKeyRelatedField(queryset=Match.objects.all())
# group_stage_id = serializers.PrimaryKeyRelatedField(queryset=GroupStage.objects.all())
model = TeamRegistration
fields = '__all__'
# ['id', 'group_stage_id', 'registration_date', 'call_date', 'bracket_position',
# 'group_stage_position', 'logo']
class PlayerRegistrationSerializer(serializers.ModelSerializer):
class Meta:
# team_registration_id = serializers.PrimaryKeyRelatedField(queryset=TeamRegistration.objects.all())
# team_state_id = serializers.PrimaryKeyRelatedField(queryset=TeamState.objects.all())
model = PlayerRegistration
fields = '__all__'
# ['id', 'team_registration_id', 'first_name', 'last_name', 'licence_id', 'rank', 'has_paid']
class PurchaseSerializer(serializers.ModelSerializer):
user = EncryptedUserField()
class Meta:
model = Purchase
@ -232,8 +226,8 @@ class DeviceTokenSerializer(serializers.ModelSerializer):
fields = '__all__'
read_only_fields = ['user']
# class DataAccessSerializer(serializers.ModelSerializer):
# class Meta:
# model = DataAccess
# fields = '__all__'
# read_only_fields = ['user']
class DrawLogSerializer(serializers.ModelSerializer):
class Meta:
model = DrawLog
fields = '__all__'

@ -20,6 +20,7 @@ router.register(r'player-registrations', views.PlayerRegistrationViewSet)
router.register(r'purchases', views.PurchaseViewSet)
router.register(r'courts', views.CourtViewSet)
router.register(r'date-intervals', views.DateIntervalViewSet)
router.register(r'draw-logs', views.DrawLogViewSet)
router.register(r'failed-api-calls', views.FailedApiCallViewSet)
router.register(r'logs', views.LogViewSet)
router.register(r'device-token', views.DeviceTokenViewSet)

@ -1,5 +1,6 @@
from .serializers import ClubSerializer, CourtSerializer, DateIntervalSerializer, TournamentSerializer, UserSerializer, ChangePasswordSerializer, EventSerializer, RoundSerializer, GroupStageSerializer, MatchSerializer, TeamScoreSerializer, TeamRegistrationSerializer, PlayerRegistrationSerializer, LiveMatchSerializer, PurchaseSerializer, CustomUserSerializer, FailedApiCallSerializer, LogSerializer, DeviceTokenSerializer, ShortUserSerializer
from tournaments.models import Club, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamScore, TeamRegistration, PlayerRegistration, Court, DateInterval, Purchase, FailedApiCall, Log, DeviceToken
from pandas.io.feather_format import pd
from .serializers import ClubSerializer, CourtSerializer, DateIntervalSerializer, DrawLogSerializer, TournamentSerializer, UserSerializer, ChangePasswordSerializer, EventSerializer, RoundSerializer, GroupStageSerializer, MatchSerializer, TeamScoreSerializer, TeamRegistrationSerializer, PlayerRegistrationSerializer, LiveMatchSerializer, PurchaseSerializer, ShortUserSerializer, FailedApiCallSerializer, LogSerializer, DeviceTokenSerializer, CustomUserSerializer
from tournaments.models import Club, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamScore, TeamRegistration, PlayerRegistration, Court, DateInterval, Purchase, FailedApiCall, Log, DeviceToken, DrawLog
from rest_framework import viewsets, permissions
from rest_framework.authtoken.models import Token
@ -162,7 +163,7 @@ class RoundViewSet(viewsets.ModelViewSet):
serializer_class = RoundSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('store_id')
tournament_id = self.request.query_params.get('store_id') or self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(tournament=tournament_id)
if self.request.user:
@ -174,7 +175,7 @@ class GroupStageViewSet(viewsets.ModelViewSet):
serializer_class = GroupStageSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('store_id')
tournament_id = self.request.query_params.get('store_id') or self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(tournament=tournament_id)
if self.request.user:
@ -186,7 +187,7 @@ class MatchViewSet(viewsets.ModelViewSet):
serializer_class = MatchSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('store_id')
tournament_id = self.request.query_params.get('store_id') or self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(Q(group_stage__tournament=tournament_id) | Q(round__tournament=tournament_id))
if self.request.user:
@ -198,9 +199,10 @@ class TeamScoreViewSet(viewsets.ModelViewSet):
serializer_class = TeamScoreSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('store_id')
tournament_id = self.request.query_params.get('store_id') or self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(team_registration__tournament=tournament_id)
q = Q(team_registration__tournament=tournament_id) | Q(match__group_stage__tournament=tournament_id) | Q(match__round__tournament=tournament_id)
return self.queryset.filter(q)
if self.request.user:
return self.queryset.filter(team_registration__tournament__event__creator=self.request.user)
return []
@ -210,7 +212,7 @@ class TeamRegistrationViewSet(viewsets.ModelViewSet):
serializer_class = TeamRegistrationSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('store_id')
tournament_id = self.request.query_params.get('store_id') or self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(tournament=tournament_id)
if self.request.user:
@ -222,7 +224,7 @@ class PlayerRegistrationViewSet(viewsets.ModelViewSet):
serializer_class = PlayerRegistrationSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('store_id')
tournament_id = self.request.query_params.get('store_id') or self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(team_registration__tournament=tournament_id)
if self.request.user:
@ -295,3 +297,15 @@ class DeviceTokenViewSet(viewsets.ModelViewSet):
def perform_create(self, serializer):
serializer.save(user=self.request.user)
class DrawLogViewSet(viewsets.ModelViewSet):
queryset = DrawLog.objects.all()
serializer_class = DrawLogSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('tournament') or self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(tournament=tournament_id)
if self.request.user:
return self.queryset.filter(tournament__event__creator=self.request.user)
return []

@ -0,0 +1 @@
This is a django customer relationship managemement (CRM) app.

@ -0,0 +1,96 @@
from django.contrib import admin
from django.utils.html import format_html
from .models import (
Prospect,
Status,
ProspectStatus,
Event,
EmailCampaign,
EmailTracker
)
@admin.register(Prospect)
class ProspectAdmin(admin.ModelAdmin):
list_display = ('name', 'email', 'region', 'created_at')
list_filter = ('region', 'created_at')
search_fields = ('name', 'email', 'region')
filter_horizontal = ('users',)
date_hierarchy = 'created_at'
@admin.register(Status)
class StatusAdmin(admin.ModelAdmin):
list_display = ('name', 'created_at')
search_fields = ('name',)
@admin.register(ProspectStatus)
class ProspectStatusAdmin(admin.ModelAdmin):
list_display = ('prospect', 'status', 'created_at')
list_filter = ('status', 'created_at')
search_fields = ('prospect__name', 'prospect__email')
date_hierarchy = 'created_at'
@admin.register(Event)
class EventAdmin(admin.ModelAdmin):
list_display = ('get_event_display', 'type', 'date', 'status', 'created_at')
list_filter = ('type', 'status', 'date')
search_fields = ('description',)
filter_horizontal = ('prospects',)
date_hierarchy = 'date'
def get_event_display(self, obj):
return str(obj)
get_event_display.short_description = 'Event'
@admin.register(EmailCampaign)
class EmailCampaignAdmin(admin.ModelAdmin):
list_display = ('subject', 'event', 'sent_at')
list_filter = ('sent_at',)
search_fields = ('subject', 'content')
date_hierarchy = 'sent_at'
readonly_fields = ('sent_at',)
@admin.register(EmailTracker)
class EmailTrackerAdmin(admin.ModelAdmin):
list_display = (
'campaign',
'prospect',
'tracking_id',
'sent_status',
'opened_status',
'clicked_status'
)
list_filter = ('sent', 'opened', 'clicked')
search_fields = (
'prospect__name',
'prospect__email',
'campaign__subject'
)
readonly_fields = (
'tracking_id', 'sent', 'sent_at',
'opened', 'opened_at',
'clicked', 'clicked_at'
)
date_hierarchy = 'sent_at'
def sent_status(self, obj):
return self._get_status_html(obj.sent, obj.sent_at)
sent_status.short_description = 'Sent'
sent_status.allow_tags = True
def opened_status(self, obj):
return self._get_status_html(obj.opened, obj.opened_at)
opened_status.short_description = 'Opened'
opened_status.allow_tags = True
def clicked_status(self, obj):
return self._get_status_html(obj.clicked, obj.clicked_at)
clicked_status.short_description = 'Clicked'
clicked_status.allow_tags = True
def _get_status_html(self, status, date):
if status:
return format_html(
'<span style="color: green;">✓</span> {}',
date.strftime('%Y-%m-%d %H:%M') if date else ''
)
return format_html('<span style="color: red;">✗</span>')

@ -0,0 +1,5 @@
from django.apps import AppConfig
class CrmConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'crm'

@ -0,0 +1,18 @@
import django_filters
from .models import Event, Status, Prospect
class ProspectFilter(django_filters.FilterSet):
region = django_filters.CharFilter(lookup_expr='icontains')
events = django_filters.ModelMultipleChoiceFilter(
queryset=Event.objects.all(),
field_name='events',
)
statuses = django_filters.ModelMultipleChoiceFilter(
queryset=Status.objects.all(),
field_name='prospectstatus__status',
)
class Meta:
model = Prospect
fields = ['region', 'events', 'statuses']

@ -0,0 +1,40 @@
from django import forms
from .models import Prospect, Event
import datetime
class SmallTextArea(forms.Textarea):
def __init__(self, *args, **kwargs):
kwargs.setdefault('attrs', {})
kwargs['attrs'].update({
'rows': 2,
'cols': 100,
'style': 'height: 80px; width: 800px;'
})
super().__init__(*args, **kwargs)
class CSVImportForm(forms.Form):
csv_file = forms.FileField()
class BulkEmailForm(forms.Form):
prospects = forms.ModelMultipleChoiceField(
queryset=Prospect.objects.all(),
widget=forms.CheckboxSelectMultiple
)
subject = forms.CharField(max_length=200)
content = forms.CharField(widget=forms.Textarea)
class EventForm(forms.ModelForm):
prospects = forms.ModelMultipleChoiceField(
queryset=Prospect.objects.all(),
widget=forms.SelectMultiple(attrs={'class': 'select2'}),
required=False
)
description = forms.CharField(widget=SmallTextArea)
attachment_text = forms.CharField(widget=SmallTextArea)
class Meta:
model = Event
fields = ['date', 'type', 'description', 'attachment_text', 'prospects', 'status']
widgets = {
'date': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
}

@ -0,0 +1,94 @@
# Generated by Django 4.2.11 on 2024-12-08 15:10
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Prospect',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('email', models.EmailField(max_length=254, unique=True)),
('name', models.CharField(max_length=200)),
('region', models.CharField(max_length=100)),
('created_at', models.DateTimeField(auto_now_add=True)),
('users', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Status',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, unique=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
],
),
migrations.CreateModel(
name='ProspectStatus',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('prospect', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='crm.prospect')),
('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='crm.status')),
],
options={
'ordering': ['-created_at'],
},
),
migrations.CreateModel(
name='Event',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField()),
('type', models.CharField(choices=[('MAIL', 'Mailing List'), ('SMS', 'SMS Campaign'), ('PRESS', 'Press Release')], max_length=10)),
('description', models.TextField()),
('attachment_text', models.TextField(blank=True)),
('status', models.CharField(choices=[('PLANNED', 'Planned'), ('ACTIVE', 'Active'), ('COMPLETED', 'Completed')], max_length=20)),
('created_at', models.DateTimeField(auto_now_add=True)),
('prospects', models.ManyToManyField(related_name='events', to='crm.prospect')),
],
options={
'ordering': ['-created_at'],
},
),
migrations.CreateModel(
name='EmailCampaign',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('subject', models.CharField(max_length=200)),
('content', models.TextField()),
('sent_at', models.DateTimeField(blank=True, null=True)),
('event', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='crm.event')),
],
),
migrations.CreateModel(
name='EmailTracker',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('tracking_id', models.UUIDField(default=uuid.uuid4, editable=False)),
('sent', models.BooleanField(default=False)),
('sent_at', models.DateTimeField(blank=True, null=True)),
('opened', models.BooleanField(default=False)),
('opened_at', models.DateTimeField(blank=True, null=True)),
('clicked', models.BooleanField(default=False)),
('clicked_at', models.DateTimeField(blank=True, null=True)),
('error_message', models.TextField(blank=True)),
('campaign', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='crm.emailcampaign')),
('prospect', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='crm.prospect')),
],
options={
'unique_together': {('campaign', 'prospect')},
},
),
]

@ -0,0 +1,60 @@
# Generated by Django 4.2.11 on 2024-12-08 20:58
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('crm', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='event',
options={'ordering': ['-created_at'], 'permissions': [('manage_events', 'Can manage events'), ('view_events', 'Can view events')]},
),
migrations.AlterModelOptions(
name='prospect',
options={'permissions': [('manage_prospects', 'Can manage prospects'), ('view_prospects', 'Can view prospects')]},
),
migrations.AddField(
model_name='event',
name='created_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_events', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='event',
name='modified_at',
field=models.DateTimeField(auto_now=True),
),
migrations.AddField(
model_name='event',
name='modified_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='modified_events', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='prospect',
name='created_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_prospects', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='prospect',
name='modified_at',
field=models.DateTimeField(auto_now=True),
),
migrations.AddField(
model_name='prospect',
name='modified_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='modified_prospects', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='event',
name='date',
field=models.DateTimeField(default=django.utils.timezone.now),
),
]

@ -0,0 +1,6 @@
from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
from django.core.exceptions import PermissionDenied
class CRMAccessMixin(LoginRequiredMixin, UserPassesTestMixin):
def test_func(self):
return self.request.user.groups.filter(name='CRM Manager').exists()

@ -0,0 +1,112 @@
from django.db import models
from django.contrib.auth import get_user_model
from django.utils import timezone
import uuid
User = get_user_model()
class EventType(models.TextChoices):
MAILING = 'MAIL', 'Mailing List'
SMS = 'SMS', 'SMS Campaign'
PRESS = 'PRESS', 'Press Release'
class Prospect(models.Model):
email = models.EmailField(unique=True)
name = models.CharField(max_length=200)
region = models.CharField(max_length=100)
users = models.ManyToManyField(get_user_model(), blank=True)
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(
User,
on_delete=models.SET_NULL,
null=True,
related_name='created_prospects'
)
modified_by = models.ForeignKey(
User,
on_delete=models.SET_NULL,
null=True,
related_name='modified_prospects'
)
modified_at = models.DateTimeField(auto_now=True)
class Meta:
permissions = [
("manage_prospects", "Can manage prospects"),
("view_prospects", "Can view prospects"),
]
def __str__(self):
return f"{self.name} ({self.email})"
class Status(models.Model):
name = models.CharField(max_length=100, unique=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class ProspectStatus(models.Model):
prospect = models.ForeignKey(Prospect, on_delete=models.CASCADE)
status = models.ForeignKey(Status, on_delete=models.PROTECT)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created_at']
class Event(models.Model):
date = models.DateTimeField(default=timezone.now)
type = models.CharField(max_length=10, choices=EventType.choices)
description = models.TextField()
attachment_text = models.TextField(blank=True)
prospects = models.ManyToManyField(Prospect, related_name='events')
status = models.CharField(max_length=20, choices=[
('PLANNED', 'Planned'),
('ACTIVE', 'Active'),
('COMPLETED', 'Completed'),
])
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(
User,
on_delete=models.SET_NULL,
null=True,
related_name='created_events'
)
modified_by = models.ForeignKey(
User,
on_delete=models.SET_NULL,
null=True,
related_name='modified_events'
)
modified_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created_at']
permissions = [
("manage_events", "Can manage events"),
("view_events", "Can view events"),
]
def __str__(self):
return f"{self.get_type_display()} - {self.date.date()}"
class EmailCampaign(models.Model):
event = models.OneToOneField(Event, on_delete=models.CASCADE)
subject = models.CharField(max_length=200)
content = models.TextField()
sent_at = models.DateTimeField(null=True, blank=True)
class EmailTracker(models.Model):
campaign = models.ForeignKey(EmailCampaign, on_delete=models.CASCADE)
prospect = models.ForeignKey(Prospect, on_delete=models.CASCADE)
tracking_id = models.UUIDField(default=uuid.uuid4, editable=False)
sent = models.BooleanField(default=False)
sent_at = models.DateTimeField(null=True, blank=True)
opened = models.BooleanField(default=False)
opened_at = models.DateTimeField(null=True, blank=True)
clicked = models.BooleanField(default=False)
clicked_at = models.DateTimeField(null=True, blank=True)
error_message = models.TextField(blank=True)
class Meta:
unique_together = ['campaign', 'prospect']

@ -0,0 +1,43 @@
# services.py
from django.core.mail import send_mail, get_connection
from django.conf import settings
from django.template.loader import render_to_string
def send_bulk_email(subject, content, prospects):
"""
Send bulk emails to prospects
Returns tuple of (success_count, error_count)
"""
success_count = 0
error_count = 0
# Get email connection
connection = get_connection()
# You might want to wrap this in try/except if you want to handle connection errors
connection.open()
for prospect in prospects:
try:
# You could add basic personalization here
personalized_content = content.replace('{name}', prospect.name)
send_mail(
subject=subject,
message=personalized_content, # Plain text version
html_message=personalized_content, # HTML version
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=[prospect.email],
connection=connection,
fail_silently=False,
)
success_count += 1
except Exception as e:
error_count += 1
# You might want to log the error here
print(f"Failed to send email to {prospect.email}: {str(e)}")
connection.close()
return success_count, error_count

@ -0,0 +1,10 @@
document.addEventListener("DOMContentLoaded", function () {
const selectAll = document.getElementById("select-all");
const prospectCheckboxes = document.getElementsByName("selected_prospects");
selectAll.addEventListener("change", function () {
prospectCheckboxes.forEach((checkbox) => {
checkbox.checked = selectAll.checked;
});
});
});

@ -0,0 +1,31 @@
{% extends "crm/base.html" %} {% block content %}
<div class="container padding-bottom">
<div class="grid-x padding-bottom">
<div class="cell medium-6 large-6 my-block bubble">
<h1 class="title">Add New Prospect</h1>
<form method="post">
{% csrf_token %}
<div class="form-group">
<label for="name">Name:</label>
<input type="text" name="name" id="name" required />
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" name="email" id="email" required />
</div>
<div class="form-group">
<label for="region">Region:</label>
<input type="text" name="region" id="region" required />
</div>
<button type="submit" class="small-button margin-v20">
Save Prospect
</button>
</form>
</div>
</div>
</div>
{% endblock %}

@ -0,0 +1,71 @@
<!DOCTYPE html>
<html>
{% load static %}
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link
rel="stylesheet"
href="{% static 'tournaments/css/foundation.min.css' %}"
/>
<link rel="stylesheet" href="{% static 'tournaments/css/style.css' %}" />
<link rel="stylesheet" href="{% static 'tournaments/css/basics.css' %}" />
<link
rel="icon"
type="image/png"
href="{% static 'tournaments/images/favicon.png' %}"
/>
<title>{% block head_title %}Page Title{% endblock %} - Padel Club</title>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(["setDocumentTitle", document.domain + "/" + document.title]);
_paq.push(["setDoNotTrack", true]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//matomo.padelclub.app/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '1']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body class="wrapper">
<header>
<div class="grid-x">
<div class="medium-6 large-9 cell topblock my-block ">
<a href="{% url 'index' %}">
<img
src="{% static 'tournaments/images/PadelClub_logo_512.png' %}"
class="logo inline"
/>
<div class="inline padding-left">
<h1 class="club">{% block first_title %}Page Title{% endblock %}</h1>
<h1 class="event">{% block second_title %}Page Title{% endblock %}</h1>
</div>
</a>
</div>
{% block right_header %}{% endblock %}
</div>
</header>
<main>
<!-- Content -->
{% block content %}
<!-- The content of child templates will be inserted here -->
{% endblock %}
</main>
<footer/>
</body>
</html>

@ -0,0 +1,27 @@
{% extends "crm/base.html" %} {% block content %}
<div class="container">
<div class="grid-x padding-bottom">
<div class="cell medium-6 large-6 my-block bubble">
<h1 class="title">
{% if form.instance.pk %}Edit{% else %}Add{% endif %} Event
</h1>
<form method="post">
{% csrf_token %} {{ form }}
<div class="mt-3">
<button type="submit" class="btn small-button">
Save Event
</button>
<a
href="{% url 'crm:planned_events' %}"
class="btn btn-secondary"
>Cancel</a
>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

@ -0,0 +1,16 @@
<div class="bottom-border">
<div class="table-row-3-colums">
<div class="left-column">
<div class="semibold">{{ event.get_type_display }}</div>
<div class="minor-info">{{ event.description|truncatechars:100 }}</div>
</div>
<div class="right-column">
<span>{{ event.date|date:"d/m/Y H:i" }}</span>
<a href="{% url 'crm:edit_event' event.id %}" class="small-button">Edit</a>
<!-- {% if event.status == 'PLANNED' %}
<a href="{% url 'crm:start_event' event.id %}" class="small-button">Start</a>
{% endif %} -->
</div>
</div>
</div>

@ -0,0 +1,58 @@
{% extends "crm/base.html" %}
{% load crm_tags %}
{% block content %}
{% if request.user|is_crm_manager %}
<div class="d-flex">
<a href="{% url 'crm:add_event' %}" class="small-button margin-v20">
Add Event
</a>
<a href="{% url 'crm:add_prospect' %}" class="small-button margin-v20 left-margin">
Add Prospect
</a>
</div>
<div class="container grid-x padding-bottom">
<div class="cell medium-6 large-6 my-block bubble">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1 class="title">Completed Events</h1>
</div>
<div class="list-group">
{% for event in completed_events %}
{% include "crm/event_row.html" with event=event %}
{% empty %}
<div class="list-group-item">No completed events.</div>
{% endfor %}
</div>
</div>
<div class="cell medium-6 large-6 my-block bubble">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1 class="title">Planned Events</h1>
</div>
<div class="list-group">
{% for event in planned_events %}
{% include "crm/event_row.html" with event=event %}
{% empty %}
<div class="list-group-item">No planned events.</div>
{% endfor %}
</div>
</div>
</div>
{% else %}
Not authorized
{% endif %}
{% endblock %}

@ -0,0 +1,57 @@
{% extends "crm/base.html" %}
{% block content %}
<div class="container bubble">
<h2>Prospects</h2>
<div class="card mb-4">
<div class="card-body">
<form method="get" class="row g-3">
{{ filter.form }}
<div class="col-12">
<button type="submit" class="btn btn-primary">Filter</button>
<a href="{% url 'crm:prospect-list' %}" class="btn btn-secondary">Clear</a>
</div>
</form>
</div>
</div>
<div class="mb-3">
<a href="{% url 'crm:prospect-import' %}" class="btn btn-success">Import CSV</a>
<a href="{% url 'crm:send-bulk-email' %}" class="btn btn-primary">Send Email</a>
</div>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th><input type="checkbox" id="select-all"></th>
<th>Name</th>
<th>Email</th>
<th>Region</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for prospect in prospects %}
<tr>
<td><input type="checkbox" name="selected_prospects" value="{{ prospect.id }}"></td>
<td>{{ prospect.name }}</td>
<td>{{ prospect.email }}</td>
<td>{{ prospect.region }}</td>
<td>
{% for status in prospect.prospectstatus_set.all %}
<span class="badge bg-primary">{{ status.status.name }}</span>
{% endfor %}
</td>
<td>
<button class="btn btn-sm btn-secondary">Edit</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}

@ -0,0 +1,47 @@
{% extends "crm/base.html" %}
{% block content %}
<div class="container mt-4">
<h2>Send Bulk Email</h2>
<form method="post">
{% csrf_token %}
<div class="mb-3">
<label class="form-label">{{ form.prospects.label }}</label>
{{ form.prospects }}
{% if form.prospects.errors %}
<div class="alert alert-danger">
{{ form.prospects.errors }}
</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label">{{ form.subject.label }}</label>
{{ form.subject }}
{% if form.subject.errors %}
<div class="alert alert-danger">
{{ form.subject.errors }}
</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label">{{ form.content.label }}</label>
{{ form.content }}
{% if form.content.errors %}
<div class="alert alert-danger">
{{ form.content.errors }}
</div>
{% endif %}
<div class="form-text">
You can use {name} to insert the prospect's name.
</div>
</div>
<button type="submit" class="btn btn-primary">Send Email</button>
<a href="{% url 'crm:prospect-list' %}" class="btn btn-secondary">Cancel</a>
</form>
</div>
{% endblock %}

@ -0,0 +1,7 @@
from django import template
register = template.Library()
@register.filter(name='is_crm_manager')
def is_crm_manager(user):
return user.groups.filter(name='CRM Manager').exists()

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

@ -0,0 +1,15 @@
from django.urls import path
from . import views
app_name = 'crm'
urlpatterns = [
path('', views.EventListView.as_view(), name='planned_events'),path('', views.EventListView.as_view(), name='planned-events'),
path('events/add/', views.EventCreateView.as_view(), name='add_event'),
path('events/<int:pk>/edit/', views.EditEventView.as_view(), name='edit_event'),
path('events/<int:pk>/start/', views.StartEventView.as_view(), name='start_event'),
path('prospects/', views.ProspectListView.as_view(), name='prospect-list'),
path('add-prospect/', views.add_prospect, name='add_prospect'),
path('prospects/import/', views.CSVImportView.as_view(), name='prospect-import'),
path('email/send/', views.SendBulkEmailView.as_view(), name='send-bulk-email'),
]

@ -0,0 +1,186 @@
# views.py
from django.views.generic import FormView, ListView, DetailView, CreateView, UpdateView
from django.views.generic.edit import FormView, BaseUpdateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import permission_required
from django.contrib import messages
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy
from django.http import HttpResponse, HttpResponseRedirect
from django.views import View
from django.utils import timezone
from django.contrib.sites.shortcuts import get_current_site
from django.template.loader import render_to_string
from django.core.mail import send_mail
from django.conf import settings
from .models import Event, Prospect, EmailTracker, EmailCampaign, EventType
from .filters import ProspectFilter
from .forms import CSVImportForm, BulkEmailForm, EventForm
from .mixins import CRMAccessMixin
import csv
from io import TextIOWrapper
from datetime import datetime
@permission_required('crm.view_crm', raise_exception=True)
def add_prospect(request):
if request.method == 'POST':
name = request.POST.get('name')
email = request.POST.get('email')
region = request.POST.get('region')
try:
prospect = Prospect.objects.create(
name=name,
email=email,
region=region,
created_by=request.user,
modified_by=request.user
)
messages.success(request, f'Prospect {name} has been added successfully!')
return redirect('crm:events') # or wherever you want to redirect after success
except Exception as e:
messages.error(request, f'Error adding prospect: {str(e)}')
return render(request, 'crm/add_prospect.html')
class EventCreateView(CRMAccessMixin, CreateView):
model = Event
form_class = EventForm
template_name = 'crm/event_form.html'
success_url = reverse_lazy('crm:planned_events')
def form_valid(self, form):
form.instance.created_by = self.request.user
form.instance.modified_by = self.request.user
return super().form_valid(form)
class EditEventView(CRMAccessMixin, UpdateView):
model = Event
form_class = EventForm
template_name = 'crm/event_form.html'
success_url = reverse_lazy('crm:planned_events')
def form_valid(self, form):
form.instance.modified_by = self.request.user
response = super().form_valid(form)
messages.success(self.request, 'Event updated successfully!')
return response
class StartEventView(CRMAccessMixin, BaseUpdateView):
model = Event
http_method_names = ['post', 'get']
def get(self, request, *args, **kwargs):
return self.post(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
event = get_object_or_404(Event, pk=kwargs['pk'], status='PLANNED')
event.status = 'ACTIVE'
event.save()
if event.type == 'MAIL':
return HttpResponseRedirect(
reverse_lazy('crm:setup_email_campaign', kwargs={'event_id': event.id})
)
elif event.type == 'SMS':
return HttpResponseRedirect(
reverse_lazy('crm:setup_sms_campaign', kwargs={'event_id': event.id})
)
elif event.type == 'PRESS':
return HttpResponseRedirect(
reverse_lazy('crm:setup_press_release', kwargs={'event_id': event.id})
)
messages.success(request, 'Event started successfully!')
return HttpResponseRedirect(reverse_lazy('crm:planned_events'))
class EventListView(CRMAccessMixin, ListView):
model = Event
template_name = 'crm/events.html'
context_object_name = 'events' # We won't use this since we're providing custom context
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['planned_events'] = Event.objects.filter(
status='PLANNED'
).order_by('date')
context['completed_events'] = Event.objects.filter(
status='COMPLETED'
).order_by('-date')
return context
class ProspectListView(CRMAccessMixin, ListView):
model = Prospect
template_name = 'crm/prospect_list.html'
context_object_name = 'prospects'
filterset_class = ProspectFilter
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = self.filterset_class(
self.request.GET,
queryset=self.get_queryset()
)
return context
class CSVImportView(CRMAccessMixin, FormView):
template_name = 'crm/csv_import.html'
form_class = CSVImportForm
success_url = reverse_lazy('prospect-list')
def form_valid(self, form):
csv_file = TextIOWrapper(
form.cleaned_data['csv_file'].file,
encoding='utf-8'
)
reader = csv.DictReader(csv_file)
for row in reader:
Prospect.objects.create(
email=row['email'],
name=row.get('name', ''),
region=row.get('region', ''),
created_by=self.request.user,
modified_by=self.request.user
)
return super().form_valid(form)
class SendBulkEmailView(CRMAccessMixin, FormView):
template_name = 'crm/send_bulk_email.html'
form_class = BulkEmailForm
success_url = reverse_lazy('crm:prospect-list')
def form_valid(self, form):
prospects = form.cleaned_data['prospects']
subject = form.cleaned_data['subject']
content = form.cleaned_data['content']
# Create Event for this email campaign
event = Event.objects.create(
date=datetime.now(),
type=EventType.MAILING,
description=f"Bulk email: {subject}",
status='COMPLETED',
created_by=self.request.user,
modified_by=self.request.user
)
event.prospects.set(prospects)
# Send emails
success_count, error_count = send_bulk_email(
subject=subject,
content=content,
prospects=prospects
)
# Show result message
messages.success(
self.request,
f"Sent {success_count} emails successfully. {error_count} failed."
)
return super().form_valid(form)

@ -35,6 +35,7 @@ INSTALLED_APPS = [
'daphne',
'sync',
'tournaments',
'crm',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
@ -46,6 +47,7 @@ INSTALLED_APPS = [
'dj_rest_auth',
'qr_code',
'channels_redis',
'django_filters',
]
AUTH_USER_MODEL = "tournaments.CustomUser"

@ -9,6 +9,8 @@ DEBUG = True
ALLOWED_HOSTS = []
SITE_NAME = 'local'
#ADMINS = [('Laurent', 'laurent@padelclub.app'), ('Razmig', 'razmig@padelclub.app')]
DATABASES = {

@ -19,6 +19,7 @@ from django.urls import include, path
urlpatterns = [
path("", include("tournaments.urls")),
path("crm/", include("crm.urls")),
path('roads/', include("api.urls")),
path('kingdom/', admin.site.urls),
path('api-auth/', include('rest_framework.urls')),

@ -7,6 +7,13 @@ pycryptodome==3.20.0
requests==2.31.0
PyJWT==2.8.0
httpx[http2]==0.27.0
<<<<<<< HEAD
channels[daphne]==4.1.0
twisted[http2,tls]==24.11.0
channels-redis==4.2.1
=======
pandas==2.2.2
xlrd==2.0.1
openpyxl==3.1.5
django-filter==24.3
>>>>>>> main

@ -0,0 +1,51 @@
from Crypto.Cipher import AES
import base64
import os
from .config_local import CRYPTO_KEY
class EncryptionUtil:
def __init__(self, key):
# In a real application, store this key securely (e.g., environment variables)
self.crypto_key = key
def encrypt_aes_gcm(self, plaintext):
# Decode the base64 encoded key
key = base64.b64decode(self.crypto_key)
# Generate a random 12-byte nonce
nonce = os.urandom(12)
# Create the cipher object
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
# Encrypt the plaintext
ciphertext, tag = cipher.encrypt_and_digest(plaintext.encode('utf-8'))
# Combine nonce, ciphertext, and tag
encrypted_data = nonce + ciphertext + tag
# Encode the result in base64
encrypted_base64 = base64.b64encode(encrypted_data).decode('utf-8')
return encrypted_base64
def decrypt_aes_gcm(self, encrypted_base64):
# Decode the base64 encoded data and key
encrypted_data = base64.b64decode(encrypted_base64)
key = base64.b64decode(self.crypto_key)
# Extract the nonce, tag, and ciphertext from the combined encrypted data
nonce = encrypted_data[:12] # AES GCM nonce is 12 bytes
tag = encrypted_data[-16:] # AES GCM tag is 16 bytes
ciphertext = encrypted_data[12:-16] # Ciphertext is everything in between
# Create the cipher object and decrypt the data
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
decrypted_data = cipher.decrypt_and_verify(ciphertext, tag)
# Convert decrypted bytes to string (assuming UTF-8 encoding)
decrypted_text = decrypted_data.decode('utf-8')
return decrypted_text
encryption_util = EncryptionUtil(CRYPTO_KEY)

@ -127,7 +127,7 @@ class BaseModel(models.Model):
return instances
class SideStoreModel(BaseModel):
store_id = models.CharField(max_length=100)
store_id = models.CharField(max_length=100, default="") # a value matching LeStorage directory sub-stores. Matches the name of the directory.
class Meta:
abstract = True

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

@ -1,10 +0,0 @@
[
{
"model": "authtoken.token",
"pk": "1269d3a4e73e69bdab65a10a30accdf3c99487ef",
"fields": {
"user": "cbd61da8-a892-4d75-97b8-1406aaa5baf9",
"created": "2024-08-24T07:07:07.479Z"
}
}
]

@ -1,618 +0,0 @@
[
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$Be254DGrWWVIYUw60BV0w4$nuaijlEr1+9BBoLS22qvZ7FioM7DmJeEiWnJfplo2n4=",
"last_login": null,
"is_superuser": false,
"username": "apple-test",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-19T19:48:06.656Z",
"email": "razmig.sarkissian@gmail.com",
"umpire_code": null,
"phone": "",
"first_name": "Apple",
"last_name": "Apple",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$YYbNLTsSwxFTVDEwLjIBO7$4c7lhu5K1JXe8Fw466TRWBNk+qllWBs+cGADIKo1rAc=",
"last_login": null,
"is_superuser": false,
"username": "Xav",
"is_staff": false,
"is_active": true,
"date_joined": "2024-05-17T12:59:19.525Z",
"email": "roussetx@orange.fr",
"umpire_code": null,
"phone": "0632027200",
"first_name": "Xavier",
"last_name": "Rousset",
"licence_id": "4348094",
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$otoCcdpm3uBRAUHOV3WAAf$8D9RElwRxhkqrc9ZiyJ1ylxmIcRHu7aT+Vd+Qzd/96o=",
"last_login": null,
"is_superuser": false,
"username": "montest",
"is_staff": false,
"is_active": false,
"date_joined": "2024-06-25T13:19:07.102Z",
"email": "montestdeouf@hotmail.com",
"umpire_code": null,
"phone": "06 11 39 15 64",
"first_name": "Lolo",
"last_name": "Lolo",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$oFtBCAV0HqLROYna0WP5T1$Njqw1kAA7UDPdKrSGw5P+g0K/IeM3z0fDoVu5/t4T3g=",
"last_login": null,
"is_superuser": false,
"username": "lisek6",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-11T17:14:45.707Z",
"email": "lisek6@hotmail.fr",
"umpire_code": null,
"phone": "0669354417",
"first_name": "Lise",
"last_name": "Franc",
"licence_id": null,
"country": "France",
"summons_message_body": "Sportivement,",
"summons_message_signature": "Lise, juge arbitre du Sporting club de Cassis",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$BhKcoN29NTkIfLXDgVb87c$nrtoVHougWIIb86ho8T654GRZA9MINYGdlgryvbJTAI=",
"last_login": null,
"is_superuser": false,
"username": "matthias13190",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-11T14:03:22.441Z",
"email": "matthias13190@gmail.com",
"umpire_code": null,
"phone": "0645656009",
"first_name": "Matthias",
"last_name": "Hanoun",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$jdiBHCyNwF6H8AkD4PtmyN$uKW7KoMCVAYVNXXz3QWsQahXzdNjhwWuhgUCCPyAnfA=",
"last_login": null,
"is_superuser": false,
"username": "lise",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-24T16:23:50.713Z",
"email": "imagesincassis@hotmail.fr",
"umpire_code": null,
"phone": "06 69 35 44 17",
"first_name": "Lise",
"last_name": "Franc",
"licence_id": null,
"country": "France",
"summons_message_body": "",
"summons_message_signature": "",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$MIMYmP5TuDtrWfzMfM57yA$qRKWNH7Cvj3+Mn+SytT7O/G6Ykv2g8+BkGEwK34g1a0=",
"last_login": null,
"is_superuser": false,
"username": "bbott07",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-22T14:52:27.383Z",
"email": "bastienbott@icloud.com",
"umpire_code": null,
"phone": "06 28 60 02 53",
"first_name": "Bastien",
"last_name": "Bott",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": [8, 40],
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$3LWQ2yqP5qIXLSw2L9g26O$h3aMWqyXKVwU6ebEH8X8/iTGtIubVJP1H9c4Y0rZPJg=",
"last_login": null,
"is_superuser": false,
"username": "juliencompigne",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-10T09:21:53.628Z",
"email": "julien@padelbusinessleague.com",
"umpire_code": null,
"phone": "0671028451",
"first_name": "Julien",
"last_name": "Compigne",
"licence_id": null,
"country": "France",
"summons_message_body": "",
"summons_message_signature": "",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$wKBIKw5fOEGxQpaAFRw5c2$T5rYXKJ6pLB5i0ELG9EEReF7OhxqT6n5NMzHYrsqKdE=",
"last_login": "2024-06-25T08:36:26.117Z",
"is_superuser": true,
"username": "laurent",
"is_staff": true,
"is_active": true,
"date_joined": "2024-03-09T11:23:34.532Z",
"email": "laurent@staxriver.com",
"umpire_code": null,
"phone": null,
"first_name": "Laurent",
"last_name": "Morvillier",
"licence_id": null,
"country": null,
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": 6,
"group_stage_match_format_preference": 0,
"loser_bracket_match_format_preference": 1,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$HePZx2xIlUuoo9iDNI3s8n$4dnTp0ofPX0gr4aA6bCISe279JQd2DPaKKE/iw/aoFQ=",
"last_login": null,
"is_superuser": false,
"username": "alexisledu",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-04T17:20:48.642Z",
"email": "tenpro64@yahoo.fr",
"umpire_code": null,
"phone": null,
"first_name": "Alexis",
"last_name": "Le du",
"licence_id": null,
"country": "France",
"summons_message_body": "",
"summons_message_signature": "",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$htg58iTu4m0j7SPnC7Xhb8$D62EKDhS5LjtTT7KbGMnPVGPBtpS77usb7wfVDW70x0=",
"last_login": null,
"is_superuser": false,
"username": "raz-stax",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-21T10:39:14.700Z",
"email": "razmig@staxriver.com",
"umpire_code": null,
"phone": "06 81 59 81 93",
"first_name": "Raz Stax",
"last_name": "Raz",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$93Gq2izTTYWFWY9liTr0Gj$bl7nez2g0PxQy84TfQGo4tpQ7fWaeKlbkRfbzSEuSgs=",
"last_login": null,
"is_superuser": false,
"username": "jawllm",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-05T13:24:01.287Z",
"email": "jeanalexandrewillem@gmail.com",
"umpire_code": null,
"phone": "0686689103",
"first_name": "Jean Alexandre",
"last_name": "Willem",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$GW2aqxXBDMXmuxlrgE3lgk$OE4kDAmoFBk2FoU8tq4YoxFSHmhYkUDc6CJLfNti1SA=",
"last_login": null,
"is_superuser": false,
"username": "JPH",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-27T15:47:21.565Z",
"email": "jp_houdaille@yahoo.fr",
"umpire_code": null,
"phone": "06 09 56 81 29",
"first_name": "Jean Paul",
"last_name": "Houdaille",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$Xz7ay2tEPAieZwFBaHG1Pv$nNGhqHHTy16N1XVaq4Wv8x9UEPldyYDsCCi3Z6AvauU=",
"last_login": "2024-06-22T15:08:17.091Z",
"is_superuser": true,
"username": "razmig",
"is_staff": true,
"is_active": true,
"date_joined": "2024-03-09T11:32:46.820Z",
"email": "razmig@padelclub.app",
"umpire_code": null,
"phone": null,
"first_name": "Razmig",
"last_name": "Sarkissian",
"licence_id": "3515696",
"country": null,
"summons_message_body": "Il est conseillé de vous présenter 10 minutes avant de jouer.\nMerci de me confirmer votre présence avec votre nom et de prévenir votre partenaire.\n\nLe Club House sera ouvert toute la journée pour vous restaurer.\n\nLe club se situe Avenue des gorguettes, 13260 Cassis.\nLe parking du club est accessible juste après les tennis.",
"summons_message_signature": "Sportivement,\nLise Franc et Razmig Sarkissian, vos JAPs.",
"summons_available_payment_methods": "Règlement possible par chèque ou espèces.",
"summons_display_format": false,
"summons_display_entry_fee": true,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": 3,
"group_stage_match_format_preference": 3,
"loser_bracket_match_format_preference": 3,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$lHPAVgdC4anhmMGP28VYde$xptgy0yBKUfvaOrxk1giZhwd5Pg40QvTFo0/4otUa/o=",
"last_login": null,
"is_superuser": false,
"username": "jadu59",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-06T11:59:03.095Z",
"email": "willemjeanalexandre@gmail.com",
"umpire_code": null,
"phone": "0686689103",
"first_name": "Jean",
"last_name": "Willem",
"licence_id": null,
"country": "France",
"summons_message_body": "Il est conseillé de vous présenter 10 minutes avant de jouer.",
"summons_message_signature": "Sportivement,\nJean Alexandre Willem, votre JAP.",
"summons_available_payment_methods": "Règlement possible par chèque ou espèces.",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": [9, 35, 8, 40],
"bracket_match_format_preference": 9,
"group_stage_match_format_preference": 8,
"loser_bracket_match_format_preference": 8,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"fields": {
"password": "pbkdf2_sha256$600000$hPdS3eX976rRow0la6PDhK$SxGJyNch/xkxSLtcp3Y2o3oCzfWeI5fRdKddQkWIEnw=",
"last_login": null,
"is_superuser": false,
"username": "kiskino",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-30T12:34:35.718Z",
"email": "nicolas.kischkewitz@hotmail.fr",
"umpire_code": null,
"phone": "0619413862",
"first_name": "Nicolas",
"last_name": "Kischkewitz",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "authtoken.token",
"pk": "0410863f2a6695ec5e83548dabbb64ab8d458689",
"fields": {
"user": ["alexisledu"],
"created": "2024-06-05T11:28:05.329Z"
}
},
{
"model": "authtoken.token",
"pk": "143dbeb9130d64d23bf0b002062c6da32cdff17f",
"fields": {
"user": ["lisek6"],
"created": "2024-06-26T10:29:16.999Z"
}
},
{
"model": "authtoken.token",
"pk": "1878e126635415ff655e14967555d2c0a80ef0c0",
"fields": {
"user": ["bbott07"],
"created": "2024-06-22T15:23:14.515Z"
}
},
{
"model": "authtoken.token",
"pk": "5cf41d657d5b4eb076d73622be622a272ca28cac",
"fields": {
"user": ["juliencompigne"],
"created": "2024-06-10T14:41:52.716Z"
}
},
{
"model": "authtoken.token",
"pk": "5d724d22810b903d5f6b2cdc4c3a6394a18cfa93",
"fields": {
"user": ["laurent"],
"created": "2024-06-25T08:31:52.365Z"
}
},
{
"model": "authtoken.token",
"pk": "6934604fa54aaece3071f293d991094cb066f692",
"fields": {
"user": ["apple-test"],
"created": "2024-06-19T19:49:35.723Z"
}
},
{
"model": "authtoken.token",
"pk": "72d333841398c2887bfffe5d060e0fd8782a72bc",
"fields": {
"user": ["Xav"],
"created": "2024-05-17T13:01:28.268Z"
}
},
{
"model": "authtoken.token",
"pk": "a28c9c74668193c34f17d1312be80192d4276f73",
"fields": {
"user": ["razmig"],
"created": "2024-03-10T13:51:33.373Z"
}
},
{
"model": "authtoken.token",
"pk": "b4c9149fd70c0a4d2d24ce273be1ce53f2cc97e9",
"fields": {
"user": ["kiskino"],
"created": "2024-06-30T12:35:08.609Z"
}
},
{
"model": "authtoken.token",
"pk": "cbf77bdc3607447ba3f61f03cd814a3721be78f4",
"fields": {
"user": ["jadu59"],
"created": "2024-06-06T11:59:30.290Z"
}
},
{
"model": "authtoken.token",
"pk": "e20c56d828a1e2263efe87908579b6775b0abb4c",
"fields": {
"user": ["JPH"],
"created": "2024-06-27T19:09:37.149Z"
}
},
{
"model": "authtoken.token",
"pk": "f8bc995073e57d8e9b05c0bcc60836a54d8560f6",
"fields": {
"user": ["matthias13190"],
"created": "2024-06-11T14:22:26.345Z"
}
},
{
"model": "authtoken.token",
"pk": "fea091d7af39f5cac5bfbea9e9a2960f5eef49d9",
"fields": {
"user": ["raz-stax"],
"created": "2024-06-21T10:39:30.933Z"
}
}
]

@ -1,642 +0,0 @@
[
{
"model": "tournaments.customuser",
"pk": "0718b707-6108-4c29-9c6e-468a8873fcd7",
"fields": {
"password": "pbkdf2_sha256$600000$Be254DGrWWVIYUw60BV0w4$nuaijlEr1+9BBoLS22qvZ7FioM7DmJeEiWnJfplo2n4=",
"last_login": null,
"is_superuser": false,
"username": "apple-test",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-19T19:48:06.656Z",
"email": "razmig.sarkissian@gmail.com",
"umpire_code": null,
"phone": "",
"first_name": "Apple",
"last_name": "Apple",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "0c9cbcb4-c0d4-469b-a227-ad7b3f14a614",
"fields": {
"password": "pbkdf2_sha256$600000$YYbNLTsSwxFTVDEwLjIBO7$4c7lhu5K1JXe8Fw466TRWBNk+qllWBs+cGADIKo1rAc=",
"last_login": null,
"is_superuser": false,
"username": "Xav",
"is_staff": false,
"is_active": true,
"date_joined": "2024-05-17T12:59:19.525Z",
"email": "roussetx@orange.fr",
"umpire_code": null,
"phone": "0632027200",
"first_name": "Xavier",
"last_name": "Rousset",
"licence_id": "4348094",
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "29c18f0b-a3c9-4ec3-9565-60cc8061ef37",
"fields": {
"password": "pbkdf2_sha256$600000$otoCcdpm3uBRAUHOV3WAAf$8D9RElwRxhkqrc9ZiyJ1ylxmIcRHu7aT+Vd+Qzd/96o=",
"last_login": null,
"is_superuser": false,
"username": "montest",
"is_staff": false,
"is_active": false,
"date_joined": "2024-06-25T13:19:07.102Z",
"email": "montestdeouf@hotmail.com",
"umpire_code": null,
"phone": "06 11 39 15 64",
"first_name": "Lolo",
"last_name": "Lolo",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "365de47c-26fa-4f20-81c8-d010d0581f04",
"fields": {
"password": "pbkdf2_sha256$600000$oFtBCAV0HqLROYna0WP5T1$Njqw1kAA7UDPdKrSGw5P+g0K/IeM3z0fDoVu5/t4T3g=",
"last_login": null,
"is_superuser": false,
"username": "lisek6",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-11T17:14:45.707Z",
"email": "lisek6@hotmail.fr",
"umpire_code": null,
"phone": "0669354417",
"first_name": "Lise",
"last_name": "Franc",
"licence_id": "3084859",
"country": "France",
"summons_message_body": "Sportivement,",
"summons_message_signature": "Lise, juge arbitre du Sporting club de Cassis",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "4353d6de-8b85-401a-ac79-8e675830670c",
"fields": {
"password": "pbkdf2_sha256$600000$BhKcoN29NTkIfLXDgVb87c$nrtoVHougWIIb86ho8T654GRZA9MINYGdlgryvbJTAI=",
"last_login": null,
"is_superuser": false,
"username": "matthias13190",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-11T14:03:22.441Z",
"email": "matthias13190@gmail.com",
"umpire_code": null,
"phone": "0645656009",
"first_name": "Matthias",
"last_name": "Hanoun",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "50d2f818-ad64-4c69-909e-76081597ffb0",
"fields": {
"password": "pbkdf2_sha256$600000$jdiBHCyNwF6H8AkD4PtmyN$uKW7KoMCVAYVNXXz3QWsQahXzdNjhwWuhgUCCPyAnfA=",
"last_login": null,
"is_superuser": false,
"username": "lise",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-24T16:23:50.713Z",
"email": "imagesincassis@hotmail.fr",
"umpire_code": null,
"phone": "06 69 35 44 17",
"first_name": "Lise",
"last_name": "Franc",
"licence_id": null,
"country": "France",
"summons_message_body": "",
"summons_message_signature": "",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "5f683e93-0bde-46a8-a285-29fcaf5091b0",
"fields": {
"password": "pbkdf2_sha256$600000$MIMYmP5TuDtrWfzMfM57yA$qRKWNH7Cvj3+Mn+SytT7O/G6Ykv2g8+BkGEwK34g1a0=",
"last_login": null,
"is_superuser": false,
"username": "bbott07",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-22T14:52:27.383Z",
"email": "bastienbott@icloud.com",
"umpire_code": null,
"phone": "06 28 60 02 53",
"first_name": "Bastien",
"last_name": "Bott",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": [
8,
40
],
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "69c7dc4a-d9ef-4334-8ea4-bb142f16dbce",
"fields": {
"password": "pbkdf2_sha256$600000$3LWQ2yqP5qIXLSw2L9g26O$h3aMWqyXKVwU6ebEH8X8/iTGtIubVJP1H9c4Y0rZPJg=",
"last_login": null,
"is_superuser": false,
"username": "juliencompigne",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-10T09:21:53.628Z",
"email": "julien@padelbusinessleague.com",
"umpire_code": null,
"phone": "0671028451",
"first_name": "Julien",
"last_name": "Compigne",
"licence_id": null,
"country": "France",
"summons_message_body": "",
"summons_message_signature": "",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "7e919851-2bf3-4a3a-bc71-6582563d6e75",
"fields": {
"password": "pbkdf2_sha256$600000$wKBIKw5fOEGxQpaAFRw5c2$T5rYXKJ6pLB5i0ELG9EEReF7OhxqT6n5NMzHYrsqKdE=",
"last_login": "2024-06-25T08:36:26.117Z",
"is_superuser": true,
"username": "laurent",
"is_staff": true,
"is_active": true,
"date_joined": "2024-03-09T11:23:34.532Z",
"email": "laurent@staxriver.com",
"umpire_code": null,
"phone": null,
"first_name": "Laurent",
"last_name": "Morvillier",
"licence_id": null,
"country": null,
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": 6,
"group_stage_match_format_preference": 0,
"loser_bracket_match_format_preference": 1,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "94f45ed2-8938-4c32-a4b6-e4525073dd33",
"fields": {
"password": "pbkdf2_sha256$600000$HePZx2xIlUuoo9iDNI3s8n$4dnTp0ofPX0gr4aA6bCISe279JQd2DPaKKE/iw/aoFQ=",
"last_login": null,
"is_superuser": false,
"username": "alexisledu",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-04T17:20:48.642Z",
"email": "tenpro64@yahoo.fr",
"umpire_code": null,
"phone": null,
"first_name": "Alexis",
"last_name": "Le du",
"licence_id": null,
"country": "France",
"summons_message_body": "",
"summons_message_signature": "",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "a0ea9ad7-3ea0-4c02-8d49-7e61ac07f8de",
"fields": {
"password": "pbkdf2_sha256$600000$htg58iTu4m0j7SPnC7Xhb8$D62EKDhS5LjtTT7KbGMnPVGPBtpS77usb7wfVDW70x0=",
"last_login": null,
"is_superuser": false,
"username": "raz-stax",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-21T10:39:14.700Z",
"email": "razmig@staxriver.com",
"umpire_code": null,
"phone": "06 81 59 81 93",
"first_name": "Raz Stax",
"last_name": "Raz",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "afef77ba-903d-4dca-ae90-6e4aad63b49d",
"fields": {
"password": "pbkdf2_sha256$600000$93Gq2izTTYWFWY9liTr0Gj$bl7nez2g0PxQy84TfQGo4tpQ7fWaeKlbkRfbzSEuSgs=",
"last_login": null,
"is_superuser": false,
"username": "jawllm",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-05T13:24:01.287Z",
"email": "jeanalexandrewillem@gmail.com",
"umpire_code": null,
"phone": "0686689103",
"first_name": "Jean Alexandre",
"last_name": "Willem",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "b8e48bf9-c7b4-4dde-b04f-333d0d1d4907",
"fields": {
"password": "pbkdf2_sha256$600000$GW2aqxXBDMXmuxlrgE3lgk$OE4kDAmoFBk2FoU8tq4YoxFSHmhYkUDc6CJLfNti1SA=",
"last_login": null,
"is_superuser": false,
"username": "JPH",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-27T15:47:21.565Z",
"email": "jp_houdaille@yahoo.fr",
"umpire_code": null,
"phone": "06 09 56 81 29",
"first_name": "Jean Paul",
"last_name": "Houdaille",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "cbd61da8-a892-4d75-97b8-1406aaa5baf9",
"fields": {
"password": "pbkdf2_sha256$600000$Xz7ay2tEPAieZwFBaHG1Pv$nNGhqHHTy16N1XVaq4Wv8x9UEPldyYDsCCi3Z6AvauU=",
"last_login": "2024-06-22T15:08:17.091Z",
"is_superuser": true,
"username": "razmig",
"is_staff": true,
"is_active": true,
"date_joined": "2024-03-09T11:32:46.820Z",
"email": "razmig@padelclub.app",
"umpire_code": null,
"phone": null,
"first_name": "Razmig",
"last_name": "Sarkissian",
"licence_id": "3515696",
"country": null,
"summons_message_body": "Il est conseillé de vous présenter 10 minutes avant de jouer.\nMerci de me confirmer votre présence avec votre nom et de prévenir votre partenaire.\n\nLe Club House sera ouvert toute la journée pour vous restaurer.\n\nLe club se situe Avenue des gorguettes, 13260 Cassis.\nLe parking du club est accessible juste après les tennis.",
"summons_message_signature": "Sportivement,\nLise Franc et Razmig Sarkissian, vos JAPs.",
"summons_available_payment_methods": "Règlement possible par chèque ou espèces.",
"summons_display_format": false,
"summons_display_entry_fee": true,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": 3,
"group_stage_match_format_preference": 3,
"loser_bracket_match_format_preference": 3,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "df12cea6-d196-4c34-8165-a74d0e103adf",
"fields": {
"password": "pbkdf2_sha256$600000$lHPAVgdC4anhmMGP28VYde$xptgy0yBKUfvaOrxk1giZhwd5Pg40QvTFo0/4otUa/o=",
"last_login": null,
"is_superuser": false,
"username": "jadu59",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-06T11:59:03.095Z",
"email": "willemjeanalexandre@gmail.com",
"umpire_code": null,
"phone": "0686689103",
"first_name": "Jean",
"last_name": "Willem",
"licence_id": null,
"country": "France",
"summons_message_body": "Il est conseillé de vous présenter 10 minutes avant de jouer.",
"summons_message_signature": "Sportivement,\nJean Alexandre Willem, votre JAP.",
"summons_available_payment_methods": "Règlement possible par chèque ou espèces.",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": [
9,
35,
8,
40
],
"bracket_match_format_preference": 9,
"group_stage_match_format_preference": 8,
"loser_bracket_match_format_preference": 8,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "fd201ebb-c95d-4bff-b27b-cc4a142857a9",
"fields": {
"password": "pbkdf2_sha256$600000$hPdS3eX976rRow0la6PDhK$SxGJyNch/xkxSLtcp3Y2o3oCzfWeI5fRdKddQkWIEnw=",
"last_login": null,
"is_superuser": false,
"username": "kiskino",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-30T12:34:35.718Z",
"email": "nicolas.kischkewitz@hotmail.fr",
"umpire_code": null,
"phone": "0619413862",
"first_name": "Nicolas",
"last_name": "Kischkewitz",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "authtoken.token",
"pk": "0410863f2a6695ec5e83548dabbb64ab8d458689",
"fields": {
"user": "94f45ed2-8938-4c32-a4b6-e4525073dd33",
"created": "2024-06-05T11:28:05.329Z"
}
},
{
"model": "authtoken.token",
"pk": "143dbeb9130d64d23bf0b002062c6da32cdff17f",
"fields": {
"user": "365de47c-26fa-4f20-81c8-d010d0581f04",
"created": "2024-06-26T10:29:16.999Z"
}
},
{
"model": "authtoken.token",
"pk": "1878e126635415ff655e14967555d2c0a80ef0c0",
"fields": {
"user": "5f683e93-0bde-46a8-a285-29fcaf5091b0",
"created": "2024-06-22T15:23:14.515Z"
}
},
{
"model": "authtoken.token",
"pk": "5cf41d657d5b4eb076d73622be622a272ca28cac",
"fields": {
"user": "69c7dc4a-d9ef-4334-8ea4-bb142f16dbce",
"created": "2024-06-10T14:41:52.716Z"
}
},
{
"model": "authtoken.token",
"pk": "5d724d22810b903d5f6b2cdc4c3a6394a18cfa93",
"fields": {
"user": "7e919851-2bf3-4a3a-bc71-6582563d6e75",
"created": "2024-06-25T08:31:52.365Z"
}
},
{
"model": "authtoken.token",
"pk": "6934604fa54aaece3071f293d991094cb066f692",
"fields": {
"user": "0718b707-6108-4c29-9c6e-468a8873fcd7",
"created": "2024-06-19T19:49:35.723Z"
}
},
{
"model": "authtoken.token",
"pk": "72d333841398c2887bfffe5d060e0fd8782a72bc",
"fields": {
"user": "0c9cbcb4-c0d4-469b-a227-ad7b3f14a614",
"created": "2024-05-17T13:01:28.268Z"
}
},
{
"model": "authtoken.token",
"pk": "a28c9c74668193c34f17d1312be80192d4276f73",
"fields": {
"user": "cbd61da8-a892-4d75-97b8-1406aaa5baf9",
"created": "2024-03-10T13:51:33.373Z"
}
},
{
"model": "authtoken.token",
"pk": "b4c9149fd70c0a4d2d24ce273be1ce53f2cc97e9",
"fields": {
"user": "fd201ebb-c95d-4bff-b27b-cc4a142857a9",
"created": "2024-06-30T12:35:08.609Z"
}
},
{
"model": "authtoken.token",
"pk": "cbf77bdc3607447ba3f61f03cd814a3721be78f4",
"fields": {
"user": "df12cea6-d196-4c34-8165-a74d0e103adf",
"created": "2024-06-06T11:59:30.290Z"
}
},
{
"model": "authtoken.token",
"pk": "e20c56d828a1e2263efe87908579b6775b0abb4c",
"fields": {
"user": "b8e48bf9-c7b4-4dde-b04f-333d0d1d4907",
"created": "2024-06-27T19:09:37.149Z"
}
},
{
"model": "authtoken.token",
"pk": "f8bc995073e57d8e9b05c0bcc60836a54d8560f6",
"fields": {
"user": "4353d6de-8b85-401a-ac79-8e675830670c",
"created": "2024-06-11T14:22:26.345Z"
}
},
{
"model": "authtoken.token",
"pk": "fea091d7af39f5cac5bfbea9e9a2960f5eef49d9",
"fields": {
"user": "a0ea9ad7-3ea0-4c02-8d49-7e61ac07f8de",
"created": "2024-06-21T10:39:30.933Z"
}
}
]

@ -1,928 +0,0 @@
[
{
"model": "tournaments.customuser",
"pk": "0c9cbcb4-c0d4-469b-a227-ad7b3f14a614",
"fields": {
"password": "pbkdf2_sha256$600000$YYbNLTsSwxFTVDEwLjIBO7$4c7lhu5K1JXe8Fw466TRWBNk+qllWBs+cGADIKo1rAc=",
"last_login": null,
"is_superuser": false,
"username": "Xav",
"is_staff": false,
"is_active": true,
"date_joined": "2024-05-17T12:59:19.525Z",
"email": "roussetx@orange.fr",
"umpire_code": null,
"phone": "0632027200",
"first_name": "Xavier",
"last_name": "Rousset",
"licence_id": "4348094",
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": "9B921A32-CD09-4CBD-82AB-D8A3C98BCC3C",
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "29c18f0b-a3c9-4ec3-9565-60cc8061ef37",
"fields": {
"password": "pbkdf2_sha256$600000$otoCcdpm3uBRAUHOV3WAAf$8D9RElwRxhkqrc9ZiyJ1ylxmIcRHu7aT+Vd+Qzd/96o=",
"last_login": null,
"is_superuser": false,
"username": "montest",
"is_staff": false,
"is_active": false,
"date_joined": "2024-06-25T13:19:07.102Z",
"email": "montestdeouf@hotmail.com",
"umpire_code": null,
"phone": "06 11 39 15 64",
"first_name": "Lolo",
"last_name": "Lolo",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "365de47c-26fa-4f20-81c8-d010d0581f04",
"fields": {
"password": "pbkdf2_sha256$600000$oFtBCAV0HqLROYna0WP5T1$Njqw1kAA7UDPdKrSGw5P+g0K/IeM3z0fDoVu5/t4T3g=",
"last_login": null,
"is_superuser": false,
"username": "lisek6",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-11T17:14:45.707Z",
"email": "lisek6@hotmail.fr",
"umpire_code": null,
"phone": "0669354417",
"first_name": "Lise",
"last_name": "Franc",
"licence_id": "3084859",
"country": "France",
"summons_message_body": "Sportivement,",
"summons_message_signature": "Lise, juge arbitre du Sporting club de Cassis",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "3af8f03e-81aa-4dd2-859d-b0122e5edeae",
"fields": {
"password": "pbkdf2_sha256$600000$herJ9eWGyaUK3v5lmX5ARA$Rhz0GgpnoJLaV59ijeSNbl10f0/TOQeLpcSePvFiVk4=",
"last_login": null,
"is_superuser": false,
"username": "tcbandol",
"is_staff": false,
"is_active": true,
"date_joined": "2024-07-20T12:32:39.990Z",
"email": "alex.rusovan@gmail.com",
"umpire_code": null,
"phone": "0606508651",
"first_name": "Alex",
"last_name": "Rusovan",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": "87888E6A-12CC-4BC8-81C8-39A924B0A33E",
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "4353d6de-8b85-401a-ac79-8e675830670c",
"fields": {
"password": "pbkdf2_sha256$600000$BhKcoN29NTkIfLXDgVb87c$nrtoVHougWIIb86ho8T654GRZA9MINYGdlgryvbJTAI=",
"last_login": null,
"is_superuser": false,
"username": "matthias13190",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-11T14:03:22.441Z",
"email": "matthias13190@gmail.com",
"umpire_code": null,
"phone": "0645656009",
"first_name": "Matthias",
"last_name": "Hanoun",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "445b65de-f601-479d-a27c-badb2f624815",
"fields": {
"password": "pbkdf2_sha256$600000$8SZLYcI6j9M6NzdtsWmqsj$V2l1Ttc17yVEpVquVklXkgUU7FhYvLTt+L8iDjl6n5Q=",
"last_login": null,
"is_superuser": false,
"username": "Morgane",
"is_staff": false,
"is_active": true,
"date_joined": "2024-07-10T12:12:34.702Z",
"email": "morgane.pincin@gmail.com",
"umpire_code": null,
"phone": "0644788919",
"first_name": "Morgane",
"last_name": "Pincin",
"licence_id": null,
"country": "France",
"summons_message_body": "",
"summons_message_signature": "Sportivement,\nMorgane Pincin, votre JAP.",
"summons_available_payment_methods": "Règlement possible par chèque ou espèces.",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": true,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": "E4EA0C5E-DC9B-407B-AC4B-86D001C65DF1",
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "44a20810-f29d-48a7-afa3-2bf49624ebd6",
"fields": {
"password": "pbkdf2_sha256$600000$eK4mrO5dfrXyR5o3uNTJ5M$b1YYoN7Wg9S/q6m9+1ZItgbjoWKAFmxxdBvCAnE+uf4=",
"last_login": null,
"is_superuser": false,
"username": "Gabriel",
"is_staff": false,
"is_active": true,
"date_joined": "2024-07-10T12:08:44.134Z",
"email": "gabriel@padel-horizon.com",
"umpire_code": null,
"phone": "0608662461",
"first_name": "Gabriel",
"last_name": "Oliveira",
"licence_id": "3501687",
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": 8,
"group_stage_match_format_preference": 8,
"loser_bracket_match_format_preference": 8,
"device_id": "199674B8-FC34-539E-B996-32AC139A9E76",
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "50d2f818-ad64-4c69-909e-76081597ffb0",
"fields": {
"password": "pbkdf2_sha256$600000$jdiBHCyNwF6H8AkD4PtmyN$uKW7KoMCVAYVNXXz3QWsQahXzdNjhwWuhgUCCPyAnfA=",
"last_login": null,
"is_superuser": false,
"username": "lise",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-24T16:23:50.713Z",
"email": "imagesincassis@hotmail.fr",
"umpire_code": null,
"phone": "06 69 35 44 17",
"first_name": "Lise",
"last_name": "Franc",
"licence_id": null,
"country": "France",
"summons_message_body": "",
"summons_message_signature": "",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "5f683e93-0bde-46a8-a285-29fcaf5091b0",
"fields": {
"password": "pbkdf2_sha256$600000$MIMYmP5TuDtrWfzMfM57yA$qRKWNH7Cvj3+Mn+SytT7O/G6Ykv2g8+BkGEwK34g1a0=",
"last_login": null,
"is_superuser": false,
"username": "bbott07",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-22T14:52:27.383Z",
"email": "bastienbott@icloud.com",
"umpire_code": null,
"phone": "06 28 60 02 53",
"first_name": "Bastien",
"last_name": "Bott",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": [8, 40],
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "69c7dc4a-d9ef-4334-8ea4-bb142f16dbce",
"fields": {
"password": "pbkdf2_sha256$600000$3LWQ2yqP5qIXLSw2L9g26O$h3aMWqyXKVwU6ebEH8X8/iTGtIubVJP1H9c4Y0rZPJg=",
"last_login": null,
"is_superuser": false,
"username": "juliencompigne",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-10T09:21:53.628Z",
"email": "julien@padelbusinessleague.com",
"umpire_code": null,
"phone": "0671028451",
"first_name": "Julien",
"last_name": "Compigne",
"licence_id": null,
"country": "France",
"summons_message_body": "",
"summons_message_signature": "",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "74218fdc-833a-48b5-81d4-2584927e8b97",
"fields": {
"password": "pbkdf2_sha256$600000$bBNjEiMnHJxg7gPt8XpyEG$6srbz1rU/cBJjNLLCLQL2Y12ez8RyWkNMrPOgwZu5YE=",
"last_login": null,
"is_superuser": false,
"username": "JPLuce",
"is_staff": false,
"is_active": true,
"date_joined": "2024-07-21T13:09:36.435Z",
"email": "jean-philippe.luce@orange.fr",
"umpire_code": null,
"phone": "06 88 33 15 18",
"first_name": "Jean-Philippe",
"last_name": "LUCE",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": "3B0B7EC1-03CB-4A8F-9526-CF105C6F7BFB",
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "7e919851-2bf3-4a3a-bc71-6582563d6e75",
"fields": {
"password": "pbkdf2_sha256$600000$wKBIKw5fOEGxQpaAFRw5c2$T5rYXKJ6pLB5i0ELG9EEReF7OhxqT6n5NMzHYrsqKdE=",
"last_login": "2024-08-19T07:56:00.533Z",
"is_superuser": true,
"username": "laurent",
"is_staff": true,
"is_active": true,
"date_joined": "2024-03-09T11:23:34.532Z",
"email": "laurent@staxriver.com",
"umpire_code": null,
"phone": null,
"first_name": "Laurent",
"last_name": "Morvillier",
"licence_id": null,
"country": null,
"summons_message_body": "",
"summons_message_signature": "",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": 6,
"group_stage_match_format_preference": 0,
"loser_bracket_match_format_preference": 1,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "89753db0-ca76-4691-8819-774d2cac7803",
"fields": {
"password": "pbkdf2_sha256$600000$Eynm19rQDmtB1gjKG7RiWY$LM+qjdwd4eh+PdxuTvSrbMJ8CxGJQUMUWzko74K/dWU=",
"last_login": null,
"is_superuser": false,
"username": "MutGuillaume",
"is_staff": false,
"is_active": false,
"date_joined": "2024-08-16T07:38:15.960Z",
"email": "mutguillaume@gmail.com",
"umpire_code": null,
"phone": "0651941389",
"first_name": "Guillaume",
"last_name": "Mut",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "94f45ed2-8938-4c32-a4b6-e4525073dd33",
"fields": {
"password": "pbkdf2_sha256$600000$HePZx2xIlUuoo9iDNI3s8n$4dnTp0ofPX0gr4aA6bCISe279JQd2DPaKKE/iw/aoFQ=",
"last_login": null,
"is_superuser": false,
"username": "alexisledu",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-04T17:20:48.642Z",
"email": "tenpro64@yahoo.fr",
"umpire_code": null,
"phone": null,
"first_name": "Alexis",
"last_name": "Le du",
"licence_id": null,
"country": "France",
"summons_message_body": "",
"summons_message_signature": "",
"summons_available_payment_methods": "",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "9b1a85b9-1f03-4465-8b1c-d804bedd3d3f",
"fields": {
"password": "pbkdf2_sha256$600000$6E9oaBca2FomyU3kLaVE6g$hgcs7qMykEnDilNdmjYDMeKgd2C36io0qKDiBdC6cuE=",
"last_login": null,
"is_superuser": false,
"username": "arthurvoisin",
"is_staff": false,
"is_active": true,
"date_joined": "2024-07-27T11:07:33.103Z",
"email": "arthur.voisin2002@gmail.com",
"umpire_code": null,
"phone": "0622257747",
"first_name": "Arthur",
"last_name": "Voisin",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": [4, 40],
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": "BDBB7ECB-1701-4A64-BB60-59E8CAB118A7",
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "afef77ba-903d-4dca-ae90-6e4aad63b49d",
"fields": {
"password": "pbkdf2_sha256$600000$93Gq2izTTYWFWY9liTr0Gj$bl7nez2g0PxQy84TfQGo4tpQ7fWaeKlbkRfbzSEuSgs=",
"last_login": null,
"is_superuser": false,
"username": "jawllm",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-05T13:24:01.287Z",
"email": "jeanalexandrewillem@gmail.com",
"umpire_code": null,
"phone": "0686689103",
"first_name": "Jean Alexandre",
"last_name": "Willem",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "b3c28f36-1b88-4b7c-afda-1a0db7904486",
"fields": {
"password": "pbkdf2_sha256$600000$G2xI897yIeiDkfIDkZGvI0$2AF06vE5H5Etm2TJlDvjmXigJh1edppdti9H9b961RY=",
"last_login": null,
"is_superuser": false,
"username": "GuiGui",
"is_staff": false,
"is_active": true,
"date_joined": "2024-07-10T12:15:40.604Z",
"email": "guillaume@padel-horizon.com",
"umpire_code": null,
"phone": "0651840064",
"first_name": "Guillaume",
"last_name": "Oliveira",
"licence_id": null,
"country": "France",
"summons_message_body": "Il est conseillé de vous présenter 10 minutes avant de jouer.\nMerci de me confirmer votre présence avec votre nom et de prévenir votre partenaire.",
"summons_message_signature": "Sportivement,\nGuillaume Oliveira, votre JAP.",
"summons_available_payment_methods": "Règlement possible par chèque ou espèces.",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": [8, 55],
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": "8093D328-902A-4068-B24F-80F1AC2FBE30",
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "b8e48bf9-c7b4-4dde-b04f-333d0d1d4907",
"fields": {
"password": "pbkdf2_sha256$600000$GW2aqxXBDMXmuxlrgE3lgk$OE4kDAmoFBk2FoU8tq4YoxFSHmhYkUDc6CJLfNti1SA=",
"last_login": null,
"is_superuser": false,
"username": "JPH",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-27T15:47:21.565Z",
"email": "jp_houdaille@yahoo.fr",
"umpire_code": null,
"phone": "06 09 56 81 29",
"first_name": "Jean Paul",
"last_name": "Houdaille",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "b921c496-603f-4be0-bbea-8281f210a87e",
"fields": {
"password": "pbkdf2_sha256$600000$kVU6PAgWAGiO0bZSltGm8v$d1TDNZkkkoEZ4nVAm65Av01iQksG0zlMZsAQAg2MhSA=",
"last_login": null,
"is_superuser": false,
"username": "apple-test",
"is_staff": false,
"is_active": true,
"date_joined": "2024-07-16T13:44:17.072Z",
"email": "razmig.sarkissian@gmail.com",
"umpire_code": null,
"phone": null,
"first_name": "Apple",
"last_name": "Apple",
"licence_id": null,
"country": null,
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": 3,
"group_stage_match_format_preference": 3,
"loser_bracket_match_format_preference": 3,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "cbd61da8-a892-4d75-97b8-1406aaa5baf9",
"fields": {
"password": "pbkdf2_sha256$600000$Xz7ay2tEPAieZwFBaHG1Pv$nNGhqHHTy16N1XVaq4Wv8x9UEPldyYDsCCi3Z6AvauU=",
"last_login": "2024-07-27T06:42:56.283Z",
"is_superuser": true,
"username": "razmig",
"is_staff": true,
"is_active": true,
"date_joined": "2024-03-09T11:32:46.820Z",
"email": "razmig@padelclub.app",
"umpire_code": null,
"phone": null,
"first_name": "Razmig",
"last_name": "Sarkissian",
"licence_id": "3515696",
"country": null,
"summons_message_body": "Il est conseillé de vous présenter 10 minutes avant de jouer.\r\nMerci de me confirmer votre présence avec votre nom et de prévenir votre partenaire.\r\n\r\nLe Club House sera ouvert toute la journée pour vous restaurer.\r\n\r\nLe club se situe Avenue des gorguettes, 13260 Cassis.\r\nLe parking du club est accessible juste après les tennis.",
"summons_message_signature": "Sportivement,\r\nLise Franc et Razmig Sarkissian, vos JAPs.",
"summons_available_payment_methods": "Règlement possible par chèque ou espèces.",
"summons_display_format": false,
"summons_display_entry_fee": true,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": 3,
"group_stage_match_format_preference": 3,
"loser_bracket_match_format_preference": 3,
"device_id": "4C4F4B5B-3A04-4A67-A581-BBC1A67B95BE",
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "df12cea6-d196-4c34-8165-a74d0e103adf",
"fields": {
"password": "pbkdf2_sha256$600000$lHPAVgdC4anhmMGP28VYde$xptgy0yBKUfvaOrxk1giZhwd5Pg40QvTFo0/4otUa/o=",
"last_login": null,
"is_superuser": false,
"username": "jadu59",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-06T11:59:03.095Z",
"email": "willemjeanalexandre@gmail.com",
"umpire_code": null,
"phone": "0686689103",
"first_name": "Jean",
"last_name": "Willem",
"licence_id": "1590652",
"country": "France",
"summons_message_body": "Il est conseillé de vous présenter 10 minutes avant de jouer.",
"summons_message_signature": "Sportivement,\nJean Alexandre Willem, votre JAP.",
"summons_available_payment_methods": "Règlement possible par chèque ou espèces.",
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": [8, 40, 9, 35],
"bracket_match_format_preference": 9,
"group_stage_match_format_preference": 8,
"loser_bracket_match_format_preference": 8,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "e1f672c9-5b82-4f8b-b865-144b2cef75aa",
"fields": {
"password": "pbkdf2_sha256$600000$eZ7JwsPukAi4FQBaIPoUjh$GeV0hIpLQsK/Bg/oKYoqmM1ODGpKR/kUmeYF+LTWVLA=",
"last_login": null,
"is_superuser": false,
"username": "Didi",
"is_staff": false,
"is_active": true,
"date_joined": "2024-07-10T12:15:05.980Z",
"email": "edwin@padel-horizon.com",
"umpire_code": null,
"phone": "0620525441",
"first_name": "Edwin",
"last_name": "Menager",
"licence_id": null,
"country": "France",
"summons_message_body": "Il est conseillé de vous présenter 10 minutes avant de jouer.\nMerci de me confirmer votre présence avec votre nom et de prévenir votre partenaire.",
"summons_message_signature": "Sportivement,\nEdwin Menager, votre JAP.",
"summons_available_payment_methods": "Règlement possible par chèque ou espèces.",
"summons_display_format": false,
"summons_display_entry_fee": true,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": "2CFC1CF7-DE9B-4618-802C-77A2D8B60E03",
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "tournaments.customuser",
"pk": "fd201ebb-c95d-4bff-b27b-cc4a142857a9",
"fields": {
"password": "pbkdf2_sha256$600000$hPdS3eX976rRow0la6PDhK$SxGJyNch/xkxSLtcp3Y2o3oCzfWeI5fRdKddQkWIEnw=",
"last_login": null,
"is_superuser": false,
"username": "kiskino",
"is_staff": false,
"is_active": true,
"date_joined": "2024-06-30T12:34:35.718Z",
"email": "nicolas.kischkewitz@hotmail.fr",
"umpire_code": null,
"phone": "0619413862",
"first_name": "Nicolas",
"last_name": "Kischkewitz",
"licence_id": null,
"country": "France",
"summons_message_body": null,
"summons_message_signature": null,
"summons_available_payment_methods": null,
"summons_display_format": false,
"summons_display_entry_fee": false,
"summons_use_full_custom_message": false,
"match_formats_default_duration": null,
"bracket_match_format_preference": null,
"group_stage_match_format_preference": null,
"loser_bracket_match_format_preference": null,
"device_id": null,
"groups": [],
"user_permissions": [],
"clubs": []
}
},
{
"model": "authtoken.token",
"pk": "0410863f2a6695ec5e83548dabbb64ab8d458689",
"fields": {
"user": "94f45ed2-8938-4c32-a4b6-e4525073dd33",
"created": "2024-06-05T11:28:05.329Z"
}
},
{
"model": "authtoken.token",
"pk": "0d1891e2b5e478cf2f644567993d6869ed42f1db",
"fields": {
"user": "cbd61da8-a892-4d75-97b8-1406aaa5baf9",
"created": "2024-08-16T08:46:24.238Z"
}
},
{
"model": "authtoken.token",
"pk": "143dbeb9130d64d23bf0b002062c6da32cdff17f",
"fields": {
"user": "365de47c-26fa-4f20-81c8-d010d0581f04",
"created": "2024-06-26T10:29:16.999Z"
}
},
{
"model": "authtoken.token",
"pk": "1878e126635415ff655e14967555d2c0a80ef0c0",
"fields": {
"user": "5f683e93-0bde-46a8-a285-29fcaf5091b0",
"created": "2024-06-22T15:23:14.515Z"
}
},
{
"model": "authtoken.token",
"pk": "1f3468375992283037f3a368d09ddeda96e0f8c9",
"fields": {
"user": "b3c28f36-1b88-4b7c-afda-1a0db7904486",
"created": "2024-07-10T12:16:24.616Z"
}
},
{
"model": "authtoken.token",
"pk": "37a7526f512986c3329a1466287e6900dfcb4d79",
"fields": {
"user": "44a20810-f29d-48a7-afa3-2bf49624ebd6",
"created": "2024-07-10T12:09:11.777Z"
}
},
{
"model": "authtoken.token",
"pk": "42b5e8a673729549fdd9bf9ac0836e16af16e94f",
"fields": {
"user": "74218fdc-833a-48b5-81d4-2584927e8b97",
"created": "2024-07-22T07:59:47.782Z"
}
},
{
"model": "authtoken.token",
"pk": "5cf41d657d5b4eb076d73622be622a272ca28cac",
"fields": {
"user": "69c7dc4a-d9ef-4334-8ea4-bb142f16dbce",
"created": "2024-06-10T14:41:52.716Z"
}
},
{
"model": "authtoken.token",
"pk": "72d333841398c2887bfffe5d060e0fd8782a72bc",
"fields": {
"user": "0c9cbcb4-c0d4-469b-a227-ad7b3f14a614",
"created": "2024-05-17T13:01:28.268Z"
}
},
{
"model": "authtoken.token",
"pk": "9384965e223ed47a7317a3f89edc18ae23020a8f",
"fields": {
"user": "9b1a85b9-1f03-4465-8b1c-d804bedd3d3f",
"created": "2024-07-27T11:08:02.737Z"
}
},
{
"model": "authtoken.token",
"pk": "a0aa8ed59f1af6298dd258dadad014066921e32d",
"fields": {
"user": "e1f672c9-5b82-4f8b-b865-144b2cef75aa",
"created": "2024-07-10T12:16:15.761Z"
}
},
{
"model": "authtoken.token",
"pk": "b196a188b208ea909633ba6c0656e0d5910e8267",
"fields": {
"user": "445b65de-f601-479d-a27c-badb2f624815",
"created": "2024-07-10T12:13:09.079Z"
}
},
{
"model": "authtoken.token",
"pk": "b4c9149fd70c0a4d2d24ce273be1ce53f2cc97e9",
"fields": {
"user": "fd201ebb-c95d-4bff-b27b-cc4a142857a9",
"created": "2024-06-30T12:35:08.609Z"
}
},
{
"model": "authtoken.token",
"pk": "cbf77bdc3607447ba3f61f03cd814a3721be78f4",
"fields": {
"user": "df12cea6-d196-4c34-8165-a74d0e103adf",
"created": "2024-06-06T11:59:30.290Z"
}
},
{
"model": "authtoken.token",
"pk": "d98bfac4d43548b15c102ffdd9218693d9dcc334",
"fields": {
"user": "3af8f03e-81aa-4dd2-859d-b0122e5edeae",
"created": "2024-07-20T12:33:14.328Z"
}
},
{
"model": "authtoken.token",
"pk": "e20c56d828a1e2263efe87908579b6775b0abb4c",
"fields": {
"user": "b8e48bf9-c7b4-4dde-b04f-333d0d1d4907",
"created": "2024-06-27T19:09:37.149Z"
}
},
{
"model": "authtoken.token",
"pk": "f8896724ce97a725cdfe590c0325a9ea39ecb975",
"fields": {
"user": "7e919851-2bf3-4a3a-bc71-6582563d6e75",
"created": "2024-07-19T14:11:42.603Z"
}
},
{
"model": "authtoken.token",
"pk": "f8bc995073e57d8e9b05c0bcc60836a54d8560f6",
"fields": {
"user": "4353d6de-8b85-401a-ac79-8e675830670c",
"created": "2024-06-11T14:22:26.345Z"
}
}
]

@ -1,6 +1,7 @@
from django.contrib import admin
from tournaments.models.device_token import DeviceToken
from tournaments.models.draw_log import DrawLog
from .models import Club, TeamScore, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamRegistration, PlayerRegistration, Purchase, Court, DateInterval, FailedApiCall, Log
from django.contrib.auth.admin import UserAdmin
@ -16,13 +17,14 @@ class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
model = CustomUser
list_display = ['email', 'username', 'is_active', 'is_staff', 'first_name', 'last_name', 'date_joined', 'event_count']
ordering = ['-date_joined']
fieldsets = [
(None, {'fields': ['id', 'username', 'email', 'password', 'first_name', 'last_name', 'is_active',
'clubs', 'country', 'phone', 'licence_id', 'umpire_code',
'summons_message_body', 'summons_message_signature', 'summons_available_payment_methods',
'summons_display_format', 'summons_display_entry_fee', 'summons_use_full_custom_message',
'match_formats_default_duration', 'bracket_match_format_preference', 'group_stage_match_format_preference',
'loser_bracket_match_format_preference', 'device_id', 'agents'
'loser_bracket_match_format_preference', 'device_id', 'loser_bracket_mode', 'groups', 'agents'
]}),
]
add_fieldsets = [
@ -30,19 +32,20 @@ class CustomUserAdmin(UserAdmin):
None,
{
"classes": ["wide"],
"fields": ['username', 'email', 'password1', 'password2', 'first_name', 'last_name', 'clubs', 'country', 'phone', 'licence_id', 'umpire_code', ],
"fields": ['username', 'email', 'password1', 'password2', 'first_name', 'last_name', 'clubs', 'country', 'phone', 'licence_id', 'umpire_code', 'groups'],
},
),
]
class EventAdmin(AutoUpdateAdmin):
list_display = ['creation_date', 'name', 'club', 'creator']
list_filter = ['creator']
class EventAdmin(admin.ModelAdmin):
list_display = ['creation_date', 'name', 'club', 'creator', 'tenup_id']
list_filter = ['creator', 'tenup_id']
ordering = ['-creation_date']
class TournamentAdmin(AutoUpdateAdmin):
list_display = ['display_name', 'event', 'is_private', 'start_date', 'payment', 'is_canceled']
list_filter = ['is_deleted']
class TournamentAdmin(admin.ModelAdmin):
list_display = ['display_name', 'event', 'is_private', 'start_date', 'payment', 'creator']
list_filter = ['is_deleted', 'event__creator']
ordering = ['-start_date']
class TeamRegistrationAdmin(AutoUpdateAdmin):
list_display = ['player_names', 'group_stage_position', 'name', 'tournament']
@ -56,28 +59,37 @@ class RoundAdmin(AutoUpdateAdmin):
list_display = ['tournament', 'name', 'index', 'parent']
list_filter = [SimpleTournamentListFilter, SimpleIndexListFilter]
search_fields = ['id']
ordering = ['parent']
class PlayerRegistrationAdmin(AutoUpdateAdmin):
list_display = ['first_name', 'last_name', 'licence_id', 'rank']
search_fields = ('first_name', 'last_name')
list_filter = [TeamScoreTournamentListFilter]
ordering = ['last_name', 'first_name']
class MatchAdmin(AutoUpdateAdmin):
list_display = ['__str__', 'round', 'group_stage', 'start_date', 'index']
class MatchAdmin(admin.ModelAdmin):
list_display = ['__str__', 'round', 'group_stage', 'start_date', 'end_date', 'index']
list_filter = [MatchTypeListFilter, MatchTournamentListFilter, SimpleIndexListFilter]
ordering = ['-group_stage', 'round']
class GroupStageAdmin(AutoUpdateAdmin):
list_display = ['tournament', 'index', 'start_date']
class GroupStageAdmin(admin.ModelAdmin):
list_display = ['tournament', 'start_date', 'index']
list_filter = [SimpleTournamentListFilter]
ordering = ['-start_date', 'index']
class ClubAdmin(AutoUpdateAdmin):
list_display = ['name', 'acronym', 'city', 'creator', 'events_count', 'broadcast_code']
search_fields = ('name', 'acronym')
search_fields = ('name', 'acronym', 'city')
ordering = ['creator']
class PurchaseAdmin(AutoUpdateAdmin):
list_display = ['user', 'identifier', 'product_id', 'quantity', 'purchase_date', 'revocation_date']
class PurchaseAdmin(admin.ModelAdmin):
list_display = ['id', 'user', 'product_id', 'quantity', 'purchase_date', 'revocation_date', 'expiration_date']
list_filter = ['user']
ordering = ['-purchase_date']
class CourtAdmin(AutoUpdateAdmin):
list_display = ['index', 'name', 'club']
ordering = ['club']
class DateIntervalAdmin(AutoUpdateAdmin):
list_display = ['court_index', 'event']
@ -93,6 +105,11 @@ class LogAdmin(AutoUpdateAdmin):
class DeviceTokenAdmin(AutoUpdateAdmin):
list_display = ['user', 'value']
class DrawLogAdmin(admin.ModelAdmin):
list_display = ['tournament', 'draw_date', 'draw_seed', 'draw_match_index', 'draw_team_position']
list_filter = [SimpleTournamentListFilter]
ordering = ['draw_date']
admin.site.register(CustomUser, CustomUserAdmin)
admin.site.register(Club, ClubAdmin)
admin.site.register(Event, EventAdmin)
@ -109,3 +126,4 @@ admin.site.register(DateInterval, DateIntervalAdmin)
admin.site.register(FailedApiCall, FailedApiCallAdmin)
admin.site.register(Log, LogAdmin)
admin.site.register(DeviceToken, DeviceTokenAdmin)
admin.site.register(DrawLog, DrawLogAdmin)

@ -1,4 +1,5 @@
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django import forms
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
@ -12,3 +13,7 @@ class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = UserCreationForm.Meta.fields + ('umpire_code', 'clubs', 'phone', 'first_name', 'last_name', 'licence_id', 'country')
class SimpleForm(forms.Form):
# A single field for user input (e.g., a text field)
name = forms.CharField(label='Enter your name!', max_length=100)

@ -0,0 +1,18 @@
# Generated by Django 5.1 on 2024-08-31 17:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0079_alter_event_creator'),
]
operations = [
migrations.AlterField(
model_name='club',
name='acronym',
field=models.CharField(max_length=50),
),
]

@ -1,24 +0,0 @@
# Generated by Django 5.1 on 2024-09-12 13:49
import uuid
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0079_alter_event_creator'),
]
operations = [
migrations.CreateModel(
name='ModelLog',
fields=[
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('model_id', models.UUIDField()),
('operation', models.IntegerField(choices=[(0, 'POST'), (1, 'PUT'), (2, 'DELETE')])),
('date', models.DateTimeField()),
('model_name', models.CharField(max_length=50)),
],
),
]

@ -1,18 +0,0 @@
# Generated by Django 5.1 on 2024-09-12 15:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0080_modellog'),
]
operations = [
migrations.AlterField(
model_name='modellog',
name='operation',
field=models.IntegerField(choices=[('POST', 'POST'), ('PUT', 'PUT'), ('DELETE', 'DELETE')]),
),
]

@ -0,0 +1,18 @@
# Generated by Django 4.2.11 on 2024-09-09 11:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0080_alter_club_acronym'),
]
operations = [
migrations.AddField(
model_name='round',
name='group_stage_loser_bracket',
field=models.BooleanField(default=False),
),
]

@ -1,18 +0,0 @@
# Generated by Django 5.1 on 2024-09-12 15:30
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0081_alter_modellog_operation'),
]
operations = [
migrations.AlterField(
model_name='modellog',
name='operation',
field=models.CharField(choices=[('POST', 'POST'), ('PUT', 'PUT'), ('DELETE', 'DELETE')], max_length=50),
),
]

@ -0,0 +1,23 @@
# Generated by Django 5.1 on 2024-09-16 08:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0081_round_group_stage_loser_bracket'),
]
operations = [
migrations.AlterField(
model_name='purchase',
name='identifier',
field=models.BigIntegerField(unique=True),
),
migrations.AlterField(
model_name='tournament',
name='federal_age_category',
field=models.IntegerField(choices=[(0, ''), (120, 'U12'), (140, 'U14'), (160, 'U16'), (180, 'U18'), (200, 'Senior'), (450, '+45 ans'), (550, '+55 ans')], default=200),
),
]

@ -1,20 +0,0 @@
# Generated by Django 5.1 on 2024-10-09 08:10
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0082_alter_modellog_operation'),
]
operations = [
migrations.AddField(
model_name='modellog',
name='creator',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
]

@ -0,0 +1,18 @@
# Generated by Django 5.1 on 2024-09-16 13:11
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0082_alter_purchase_identifier_and_more'),
]
operations = [
migrations.AddField(
model_name='purchase',
name='expiration_date',
field=models.DateTimeField(blank=True, null=True),
),
]

@ -0,0 +1,28 @@
# Generated by Django 4.2.11 on 2024-09-18 08:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0083_purchase_expiration_date'),
]
operations = [
migrations.AddField(
model_name='customuser',
name='loser_bracket_mode',
field=models.IntegerField(default=0),
),
migrations.AddField(
model_name='round',
name='loser_bracket_mode',
field=models.IntegerField(default=0),
),
migrations.AddField(
model_name='tournament',
name='loser_bracket_mode',
field=models.IntegerField(default=0),
),
]

@ -0,0 +1,22 @@
# Generated by Django 5.1 on 2024-09-18 08:33
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0083_purchase_expiration_date'),
]
operations = [
migrations.RemoveField(
model_name='purchase',
name='id',
),
migrations.AlterField(
model_name='purchase',
name='identifier',
field=models.BigIntegerField(primary_key=True, serialize=False, unique=True),
),
]

@ -1,18 +0,0 @@
# Generated by Django 5.1 on 2024-10-09 08:18
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0083_modellog_creator'),
]
operations = [
migrations.RenameField(
model_name='modellog',
old_name='creator',
new_name='user',
),
]

@ -1,18 +0,0 @@
# Generated by Django 5.1 on 2024-10-09 11:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0084_rename_creator_modellog_user'),
]
operations = [
migrations.AddField(
model_name='modellog',
name='store_id',
field=models.CharField(blank=True, max_length=200, null=True),
),
]

@ -0,0 +1,18 @@
# Generated by Django 5.1 on 2024-09-18 08:34
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0084_remove_purchase_id_alter_purchase_identifier'),
]
operations = [
migrations.RenameField(
model_name='purchase',
old_name='identifier',
new_name='id',
),
]

@ -1,154 +0,0 @@
# Generated by Django 5.1 on 2024-10-15 14:42
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0085_modellog_store_id'),
]
operations = [
migrations.AddField(
model_name='club',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='club',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='court',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='court',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='dateinterval',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='dateinterval',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='devicetoken',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='devicetoken',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='event',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='failedapicall',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='failedapicall',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='groupstage',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='groupstage',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='log',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='log',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='match',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='match',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='playerregistration',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='playerregistration',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='purchase',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='purchase',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='round',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='round',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='teamregistration',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='teamregistration',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='teamscore',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='teamscore',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='tournament',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
]

@ -0,0 +1,14 @@
# Generated by Django 5.1 on 2024-09-19 09:42
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0084_customuser_loser_bracket_mode_and_more'),
('tournaments', '0085_rename_identifier_purchase_id'),
]
operations = [
]

@ -0,0 +1,18 @@
# Generated by Django 4.2.11 on 2024-09-24 12:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0086_merge_20240919_1142'),
]
operations = [
migrations.AlterField(
model_name='playerregistration',
name='phone_number',
field=models.CharField(blank=True, max_length=50, null=True),
),
]

@ -1,17 +0,0 @@
# Generated by Django 5.1 on 2024-10-16 12:42
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0086_club_creation_date_club_last_update_and_more'),
]
operations = [
migrations.RemoveField(
model_name='modellog',
name='store_id',
),
]

@ -1,19 +0,0 @@
# Generated by Django 5.1 on 2024-10-17 10:36
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0087_remove_modellog_store_id'),
]
operations = [
migrations.AddField(
model_name='customuser',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
]

@ -0,0 +1,18 @@
# Generated by Django 4.2.11 on 2024-09-28 15:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0087_alter_playerregistration_phone_number'),
]
operations = [
migrations.AddField(
model_name='groupstage',
name='step',
field=models.IntegerField(default=0),
),
]

@ -0,0 +1,18 @@
# Generated by Django 4.2.11 on 2024-10-12 14:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0088_groupstage_step'),
]
operations = [
migrations.AlterField(
model_name='playerregistration',
name='licence_id',
field=models.CharField(blank=True, max_length=50, null=True),
),
]

@ -1,49 +0,0 @@
# Generated by Django 5.1 on 2024-10-17 13:02
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0088_customuser_last_update'),
]
operations = [
migrations.AddField(
model_name='groupstage',
name='store_id',
field=models.CharField(default='', max_length=100),
preserve_default=False,
),
migrations.AddField(
model_name='match',
name='store_id',
field=models.CharField(default='', max_length=100),
preserve_default=False,
),
migrations.AddField(
model_name='playerregistration',
name='store_id',
field=models.CharField(default='', max_length=100),
preserve_default=False,
),
migrations.AddField(
model_name='round',
name='store_id',
field=models.CharField(default='', max_length=100),
preserve_default=False,
),
migrations.AddField(
model_name='teamregistration',
name='store_id',
field=models.CharField(default='', max_length=100),
preserve_default=False,
),
migrations.AddField(
model_name='teamscore',
name='store_id',
field=models.CharField(default='', max_length=100),
preserve_default=False,
),
]

@ -1,79 +0,0 @@
# Generated by Django 5.1 on 2024-10-17 13:02
from ast import Match
from django.db import migrations
from tournaments.models.player_registration import PlayerRegistration
def update_group_stage_store_id(apps):
GroupStage = apps.get_model('tournaments', 'GroupStage')
for group_stage in GroupStage.objects.all():
group_stage.store_id = str(group_stage.tournament.id)
group_stage.save()
def update_round_store_id(apps):
Round = apps.get_model('tournaments', 'Round')
for round in Round.objects.all():
round.store_id = str(round.tournament.id)
round.save()
def update_team_registration_store_id(apps):
TeamRegistration = apps.get_model('tournaments', 'TeamRegistration')
for tr in TeamRegistration.objects.all():
tr.store_id = str(tr.tournament.id)
tr.save()
def update_player_registration_store_id(apps):
PlayerRegistration = apps.get_model('tournaments', 'PlayerRegistration')
for pr in PlayerRegistration.objects.all():
pr.store_id = str(pr.team_registration.tournament.id)
pr.save()
def update_match_store_id(apps):
Match = apps.get_model('tournaments', 'Match')
for match in Match.objects.all():
if match.round:
tournament = match.round.tournament
else:
tournament = match.group_stage.tournament
match.store_id = str(tournament.id)
match.save()
def update_team_score_store_id(apps):
TeamScore = apps.get_model('tournaments', 'TeamScore')
for team_score in TeamScore.objects.all():
tournament = None
if team_score.team_registration:
tournament = team_score.team_registration.tournament
elif team_score.match:
if team_score.match.round:
tournament = team_score.match.round.tournament
else:
tournament = team_score.team_registration.tournament
team_score.store_id = str(tournament.id)
team_score.save()
def update_models(apps, schema_editor):
update_group_stage_store_id(apps)
update_round_store_id(apps)
update_team_registration_store_id(apps)
update_player_registration_store_id(apps)
update_match_store_id(apps)
update_team_score_store_id(apps)
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0089_groupstage_store_id_match_store_id_and_more'),
]
operations = [
migrations.RunPython(update_models),
]

@ -0,0 +1,23 @@
# Generated by Django 4.2.11 on 2024-10-17 08:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0089_alter_playerregistration_licence_id'),
]
operations = [
migrations.AddField(
model_name='tournament',
name='initial_seed_count',
field=models.IntegerField(default=0),
),
migrations.AddField(
model_name='tournament',
name='initial_seed_round',
field=models.IntegerField(default=0),
),
]

@ -0,0 +1,26 @@
# Generated by Django 4.2.11 on 2024-10-24 06:55
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0090_tournament_initial_seed_count_and_more'),
]
operations = [
migrations.CreateModel(
name='DrawLog',
fields=[
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('draw_date', models.DateTimeField()),
('draw_seed', models.IntegerField()),
('draw_match_index', models.IntegerField()),
('draw_team_position', models.IntegerField()),
('tournament', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tournaments.tournament')),
],
),
]

@ -1,18 +0,0 @@
# Generated by Django 5.1 on 2024-10-30 08:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0090_dynamic_store_id'),
]
operations = [
migrations.AddField(
model_name='modellog',
name='store_id',
field=models.CharField(blank=True, max_length=200, null=True),
),
]

File diff suppressed because one or more lines are too long

@ -1,27 +0,0 @@
# Generated by Django 5.1 on 2024-11-01 08:02
import django.db.models.deletion
import uuid
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0091_modellog_store_id'),
]
operations = [
migrations.CreateModel(
name='DataAccess',
fields=[
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('model_name', models.CharField(max_length=50)),
('model_id', models.UUIDField()),
('granted_at', models.DateTimeField(auto_now_add=True)),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owned_data', to=settings.AUTH_USER_MODEL)),
('shared_with', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shared_data', to=settings.AUTH_USER_MODEL)),
],
),
]

@ -0,0 +1,63 @@
# Generated by Django 4.2.11 on 2024-11-05 08:23
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0092_club_timezone'),
]
operations = [
migrations.AddField(
model_name='drawlog',
name='draw_type',
field=models.IntegerField(default=0),
),
migrations.AlterField(
model_name='customuser',
name='bracket_match_format_preference',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='customuser',
name='group_stage_match_format_preference',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='customuser',
name='loser_bracket_match_format_preference',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='groupstage',
name='format',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='match',
name='format',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='round',
name='format',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='tournament',
name='group_stage_format',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='tournament',
name='loser_round_format',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='tournament',
name='round_format',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point')], default=3, null=True),
),
]

@ -1,23 +0,0 @@
# Generated by Django 5.1 on 2024-11-08 15:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0092_dataaccess'),
]
operations = [
migrations.AddField(
model_name='modellog',
name='parent_model_id',
field=models.UUIDField(null=True),
),
migrations.AddField(
model_name='modellog',
name='parent_model_name',
field=models.CharField(max_length=50, null=True),
),
]

@ -0,0 +1,58 @@
# Generated by Django 4.2.11 on 2024-11-18 08:02
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0093_drawlog_draw_type_and_more'),
]
operations = [
migrations.AlterField(
model_name='customuser',
name='bracket_match_format_preference',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point'), (13, 'Single set of four games'), (14, 'Single set of four games with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='customuser',
name='group_stage_match_format_preference',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point'), (13, 'Single set of four games'), (14, 'Single set of four games with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='customuser',
name='loser_bracket_match_format_preference',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point'), (13, 'Single set of four games'), (14, 'Single set of four games with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='groupstage',
name='format',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point'), (13, 'Single set of four games'), (14, 'Single set of four games with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='match',
name='format',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point'), (13, 'Single set of four games'), (14, 'Single set of four games with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='round',
name='format',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point'), (13, 'Single set of four games'), (14, 'Single set of four games with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='tournament',
name='group_stage_format',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point'), (13, 'Single set of four games'), (14, 'Single set of four games with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='tournament',
name='loser_round_format',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point'), (13, 'Single set of four games'), (14, 'Single set of four games with decisive point')], default=3, null=True),
),
migrations.AlterField(
model_name='tournament',
name='round_format',
field=models.IntegerField(blank=True, choices=[(0, 'Two sets'), (1, 'Two sets super tie'), (2, 'Two sets of four games'), (3, 'Nine games'), (4, 'Super Tie-Break'), (5, 'Mega Tie-Break'), (6, 'Two Sets with decisive point'), (7, 'Two Sets with decisive point and super tie-break'), (8, 'Two sets of four games with decisive point'), (9, 'Nine games with decisive point'), (10, 'Two sets of Super Tie-Break decisive point'), (11, 'Single set'), (12, 'Single set with decisive point'), (13, 'Single set of four games'), (14, 'Single set of four games with decisive point')], default=3, null=True),
),
]

@ -1,23 +0,0 @@
# Generated by Django 5.1 on 2024-11-08 16:16
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0093_modellog_parent_model_id_modellog_parent_model_name'),
]
operations = [
migrations.RemoveField(
model_name='dataaccess',
name='shared_with',
),
migrations.AddField(
model_name='dataaccess',
name='shared_with',
field=models.ManyToManyField(related_name='shared_data', to=settings.AUTH_USER_MODEL),
),
]

@ -0,0 +1,396 @@
# Generated by Django 5.1 on 2024-12-13 13:13
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0094_alter_customuser_bracket_match_format_preference_and_more'),
]
operations = [
migrations.AddField(
model_name='club',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='club',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='club',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='club',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='court',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='court',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='court',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='court',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='customuser',
name='agents',
field=models.ManyToManyField(blank=True, related_name='owners', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='customuser',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='dateinterval',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='dateinterval',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='dateinterval',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='dateinterval',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='event',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='event',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='event',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='failedapicall',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='failedapicall',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='failedapicall',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='failedapicall',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='groupstage',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='groupstage',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='groupstage',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='groupstage',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='groupstage',
name='store_id',
field=models.CharField(default='', max_length=100),
),
migrations.AddField(
model_name='log',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='log',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='log',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='log',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='match',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='match',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='match',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='match',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='match',
name='store_id',
field=models.CharField(default='', max_length=100),
),
migrations.AddField(
model_name='playerregistration',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='playerregistration',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='playerregistration',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='playerregistration',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='playerregistration',
name='store_id',
field=models.CharField(default='', max_length=100),
),
migrations.AddField(
model_name='round',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='round',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='round',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='round',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='round',
name='store_id',
field=models.CharField(default='', max_length=100),
),
migrations.AddField(
model_name='teamregistration',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='teamregistration',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='teamregistration',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='teamregistration',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='teamregistration',
name='store_id',
field=models.CharField(default='', max_length=100),
),
migrations.AddField(
model_name='teamscore',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='teamscore',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='teamscore',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='teamscore',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='teamscore',
name='store_id',
field=models.CharField(default='', max_length=100),
),
migrations.AddField(
model_name='tournament',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.AddField(
model_name='tournament',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='tournament',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='club',
name='creator',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='creator_clubs', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='court',
name='club',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='courts', to='tournaments.club'),
),
migrations.AlterField(
model_name='customuser',
name='clubs',
field=models.ManyToManyField(blank=True, related_name='creators', to='tournaments.club'),
),
migrations.AlterField(
model_name='dateinterval',
name='event',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='date_intervals', to='tournaments.event'),
),
migrations.AlterField(
model_name='devicetoken',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='device_tokens', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='event',
name='club',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='events', to='tournaments.club'),
),
migrations.AlterField(
model_name='event',
name='creator',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='events', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='failedapicall',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='failed_api_calls', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='groupstage',
name='tournament',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='group_stages', to='tournaments.tournament'),
),
migrations.AlterField(
model_name='log',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='logs', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='match',
name='group_stage',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='matches', to='tournaments.groupstage'),
),
migrations.AlterField(
model_name='match',
name='round',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='matches', to='tournaments.round'),
),
migrations.AlterField(
model_name='playerregistration',
name='team_registration',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='player_registrations', to='tournaments.teamregistration'),
),
migrations.AlterField(
model_name='round',
name='tournament',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rounds', to='tournaments.tournament'),
),
migrations.AlterField(
model_name='teamregistration',
name='group_stage',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='team_registrations', to='tournaments.groupstage'),
),
migrations.AlterField(
model_name='teamregistration',
name='tournament',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='team_registrations', to='tournaments.tournament'),
),
migrations.AlterField(
model_name='teamscore',
name='team_registration',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='team_scores', to='tournaments.teamregistration'),
),
migrations.AlterField(
model_name='tournament',
name='event',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tournaments', to='tournaments.event'),
),
]

@ -1,25 +0,0 @@
# Generated by Django 5.1 on 2024-11-08 16:45
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0094_remove_dataaccess_shared_with_dataaccess_shared_with'),
]
operations = [
migrations.RemoveField(
model_name='dataaccess',
name='shared_with',
),
migrations.AddField(
model_name='dataaccess',
name='shared_with',
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='shared_data', to=settings.AUTH_USER_MODEL),
preserve_default=False,
),
]

@ -1,28 +0,0 @@
# Generated by Django 5.1 on 2024-11-08 16:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0095_remove_dataaccess_shared_with_dataaccess_shared_with'),
]
operations = [
migrations.AlterField(
model_name='modellog',
name='operation',
field=models.CharField(choices=[('POST', 'POST'), ('PUT', 'PUT'), ('DELETE', 'DELETE'), ('GRANT_ACCESS', 'GRANT_ACCESS'), ('REVOKE_ACCESS', 'REVOKE_ACCESS')], max_length=50),
),
migrations.AlterField(
model_name='modellog',
name='parent_model_id',
field=models.UUIDField(blank=True, null=True),
),
migrations.AlterField(
model_name='modellog',
name='parent_model_name',
field=models.CharField(blank=True, max_length=50, null=True),
),
]

@ -0,0 +1,30 @@
# Generated by Django 5.1 on 2024-12-13 13:04
from django.db import migrations
def init_store_id(apps, schema_editor):
models = ["GroupStage", "Round", "TeamRegistration", "PlayerRegistration", "Match", "TeamScore", "DrawLog"]
for model in models:
Model = apps.get_model("tournaments", model)
for instance in Model.objects.all():
instance.store_id = str(instance.tournament_id())
instance.save()
def init_related_names(apps, schema_editor):
models = ["Club", "Event"]
for model in models:
Model = apps.get_model("tournaments", model)
for instance in Model.objects.all():
instance.related_user = instance.creator
instance.save()
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0095_club_creation_date_club_last_update_and_more'),
]
operations = [
migrations.RunPython(init_store_id),
migrations.RunPython(init_related_names),
]

@ -1,190 +0,0 @@
# Generated by Django 5.1 on 2024-11-12 16:41
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0096_alter_modellog_operation_and_more'),
]
operations = [
migrations.AddField(
model_name='club',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='court',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='dateinterval',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='devicetoken',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='event',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='failedapicall',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='groupstage',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='log',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='match',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='playerregistration',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='purchase',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='round',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='teamregistration',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='teamscore',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='tournament',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='club',
name='creator',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='creator_clubs', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='court',
name='club',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='courts', to='tournaments.club'),
),
migrations.AlterField(
model_name='customuser',
name='clubs',
field=models.ManyToManyField(blank=True, related_name='creators', to='tournaments.club'),
),
migrations.AlterField(
model_name='dateinterval',
name='event',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='date_intervals', to='tournaments.event'),
),
migrations.AlterField(
model_name='devicetoken',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='device_tokens', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='event',
name='club',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='events', to='tournaments.club'),
),
migrations.AlterField(
model_name='event',
name='creator',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='events', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='failedapicall',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='failed_api_calls', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='groupstage',
name='tournament',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='group_stages', to='tournaments.tournament'),
),
migrations.AlterField(
model_name='log',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='logs', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='match',
name='group_stage',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='matches', to='tournaments.groupstage'),
),
migrations.AlterField(
model_name='match',
name='round',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='matches', to='tournaments.round'),
),
migrations.AlterField(
model_name='modellog',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='model_logs', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='playerregistration',
name='team_registration',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='player_registrations', to='tournaments.teamregistration'),
),
migrations.AlterField(
model_name='purchase',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='purchases', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='round',
name='tournament',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rounds', to='tournaments.tournament'),
),
migrations.AlterField(
model_name='teamregistration',
name='group_stage',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='team_registrations', to='tournaments.groupstage'),
),
migrations.AlterField(
model_name='teamregistration',
name='tournament',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='team_registrations', to='tournaments.tournament'),
),
migrations.AlterField(
model_name='teamscore',
name='team_registration',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='team_scores', to='tournaments.teamregistration'),
),
migrations.AlterField(
model_name='tournament',
name='event',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tournaments', to='tournaments.event'),
),
]

@ -1,108 +0,0 @@
# Generated by Django 5.1 on 2024-11-15 14:45
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0097_club_last_updated_by_court_last_updated_by_and_more'),
]
operations = [
migrations.RemoveField(
model_name='club',
name='last_updated_by',
),
migrations.RemoveField(
model_name='court',
name='last_updated_by',
),
migrations.RemoveField(
model_name='dateinterval',
name='last_updated_by',
),
migrations.RemoveField(
model_name='devicetoken',
name='last_updated_by',
),
migrations.RemoveField(
model_name='event',
name='last_updated_by',
),
migrations.RemoveField(
model_name='failedapicall',
name='last_updated_by',
),
migrations.RemoveField(
model_name='groupstage',
name='last_updated_by',
),
migrations.RemoveField(
model_name='log',
name='last_updated_by',
),
migrations.RemoveField(
model_name='match',
name='last_updated_by',
),
migrations.RemoveField(
model_name='modellog',
name='parent_model_id',
),
migrations.RemoveField(
model_name='modellog',
name='parent_model_name',
),
migrations.RemoveField(
model_name='playerregistration',
name='last_updated_by',
),
migrations.RemoveField(
model_name='purchase',
name='last_updated_by',
),
migrations.RemoveField(
model_name='round',
name='last_updated_by',
),
migrations.RemoveField(
model_name='teamregistration',
name='last_updated_by',
),
migrations.RemoveField(
model_name='teamscore',
name='last_updated_by',
),
migrations.RemoveField(
model_name='tournament',
name='last_updated_by',
),
migrations.AddField(
model_name='dataaccess',
name='creation_date',
field=models.DateTimeField(default=django.utils.timezone.now, editable=False),
),
migrations.AddField(
model_name='dataaccess',
name='last_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
migrations.RemoveField(
model_name='dataaccess',
name='shared_with',
),
migrations.AlterField(
model_name='tournament',
name='event',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='tournaments.event'),
),
migrations.AddField(
model_name='dataaccess',
name='shared_with',
field=models.ManyToManyField(related_name='shared_data', to=settings.AUTH_USER_MODEL),
),
]

@ -1,19 +0,0 @@
# Generated by Django 5.1 on 2024-11-18 12:54
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0098_remove_club_last_updated_by_and_more'),
]
operations = [
migrations.AddField(
model_name='dataaccess',
name='last_hierarchy_update',
field=models.DateTimeField(default=django.utils.timezone.now),
),
]

@ -1,100 +0,0 @@
# Generated by Django 5.1 on 2024-11-20 14:15
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0099_dataaccess_last_hierarchy_update'),
]
operations = [
migrations.AddField(
model_name='club',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='court',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='dataaccess',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='dateinterval',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='devicetoken',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='event',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='failedapicall',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='groupstage',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='log',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='match',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='playerregistration',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='purchase',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='round',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='teamregistration',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='teamscore',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='tournament',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='tournament',
name='event',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tournaments', to='tournaments.event'),
),
]

@ -1,23 +0,0 @@
# Generated by Django 5.1 on 2024-11-26 09:48
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0100_club_last_updated_by_court_last_updated_by_and_more'),
]
operations = [
migrations.RemoveField(
model_name='modellog',
name='user',
),
migrations.AddField(
model_name='modellog',
name='users',
field=models.ManyToManyField(blank=True, related_name='model_logs', to=settings.AUTH_USER_MODEL),
),
]

@ -1,17 +0,0 @@
# Generated by Django 5.1 on 2024-11-26 10:33
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0101_remove_modellog_user_modellog_users'),
]
operations = [
migrations.RemoveField(
model_name='dataaccess',
name='last_hierarchy_update',
),
]

@ -1,23 +0,0 @@
# Generated by Django 5.1 on 2024-12-02 15:39
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0102_remove_dataaccess_last_hierarchy_update'),
]
operations = [
migrations.RemoveField(
model_name='modellog',
name='users',
),
migrations.DeleteModel(
name='DataAccess',
),
migrations.DeleteModel(
name='ModelLog',
),
]

@ -1,19 +0,0 @@
# Generated by Django 5.1 on 2024-12-04 15:40
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0103_remove_modellog_users_delete_dataaccess_and_more'),
]
operations = [
migrations.AddField(
model_name='customuser',
name='referees',
field=models.ManyToManyField(blank=True, related_name='owners', to=settings.AUTH_USER_MODEL),
),
]

@ -1,18 +0,0 @@
# Generated by Django 5.1 on 2024-12-05 11:14
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0104_customuser_referees'),
]
operations = [
migrations.RenameField(
model_name='customuser',
old_name='referees',
new_name='agents',
),
]

@ -1,165 +0,0 @@
# Generated by Django 5.1 on 2024-12-10 15:12
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0105_rename_referees_customuser_agents'),
]
operations = [
migrations.AddField(
model_name='club',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='court',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='dateinterval',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='devicetoken',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='event',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='failedapicall',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='groupstage',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='log',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='match',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='playerregistration',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='purchase',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='round',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='teamregistration',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='teamscore',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='tournament',
name='related_user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='club',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='court',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='dateinterval',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='devicetoken',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='event',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='failedapicall',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='groupstage',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='log',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='match',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='playerregistration',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='purchase',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='round',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='teamregistration',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='teamscore',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='tournament',
name='last_updated_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
]

@ -1,29 +0,0 @@
# Generated by Django 5.1 on 2024-12-11 16:39
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0106_club_related_user_court_related_user_and_more'),
]
operations = [
migrations.RemoveField(
model_name='devicetoken',
name='creation_date',
),
migrations.RemoveField(
model_name='devicetoken',
name='last_update',
),
migrations.RemoveField(
model_name='devicetoken',
name='last_updated_by',
),
migrations.RemoveField(
model_name='devicetoken',
name='related_user',
),
]

@ -7,7 +7,7 @@ from .date_interval import DateInterval
from .enums import TournamentPayment, FederalCategory, FederalLevelCategory, FederalAgeCategory, FederalMatchCategory, ModelOperation
from .player_enums import PlayerSexType, PlayerDataSource, PlayerPaymentType
from .event import Event
from .tournament import Tournament, TeamSummon, TeamSortingType, TeamList
from .tournament import Tournament, TeamSummon, TeamSortingType, TeamItem
from .group_stage import GroupStage
from .round import Round
from .match import Match, LiveMatch
@ -18,3 +18,4 @@ from .purchase import Purchase
from .failed_api_call import FailedApiCall
from .log import Log
from .device_token import DeviceToken
from .draw_log import DrawLog

@ -1,4 +1,5 @@
from django.db import models
from zoneinfo import available_timezones
import uuid
from . import BaseModel
@ -6,7 +7,7 @@ class Club(BaseModel):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True)
creator = models.ForeignKey('CustomUser', blank=True, null=True, on_delete=models.SET_NULL, related_name='creator_clubs')
name = models.CharField(max_length=50)
acronym = models.CharField(max_length=10)
acronym = models.CharField(max_length=50)
phone = models.CharField(max_length=15, null=True, blank=True)
code = models.CharField(max_length=10, null=True, blank=True)
federal_club_data = models.JSONField(null=True, blank=True)
@ -16,7 +17,11 @@ class Club(BaseModel):
zip_code = models.CharField(max_length=10, null=True, blank=True)
latitude = models.FloatField(null=True, blank=True)
longitude = models.FloatField(null=True, blank=True)
timezone = models.CharField(
max_length=50, null=True, blank=True,
choices=[(tz, tz) for tz in sorted(available_timezones())],
default='CET'
)
court_count = models.IntegerField(default=2)
broadcast_code = models.CharField(max_length=10, null=True, blank=True, unique=True)
@ -44,3 +49,9 @@ class Club(BaseModel):
return f"{self.zip_code} {self.city}"
else:
return ""
def computedShortTitle(self):
if len(self.name) > 15:
return self.acronym
else:
return self.name

@ -34,6 +34,7 @@ class CustomUser(AbstractUser):
device_id = models.CharField(max_length=50, null=True, blank=True)
agents = models.ManyToManyField('CustomUser', blank=True, related_name='owners')
loser_bracket_mode = models.IntegerField(default=0)
### ### ### ### ### ### ### ### ### ### ### WARNING ### ### ### ### ### ### ### ### ### ###
### WARNING : Any added field MUST be inserted in the method below: fields_for_update() ###
@ -46,7 +47,7 @@ class CustomUser(AbstractUser):
'summons_message_body', 'summons_message_signature', 'summons_available_payment_methods',
'summons_display_format', 'summons_display_entry_fee',
'summons_use_full_custom_message', 'match_formats_default_duration', 'bracket_match_format_preference',
'group_stage_match_format_preference', 'loser_bracket_match_format_preference', 'device_id']
'group_stage_match_format_preference', 'loser_bracket_match_format_preference', 'device_id', 'loser_bracket_mode']
def __str__(self):

@ -0,0 +1,22 @@
from django.db import models
from . import SideStoreModel
import uuid
class DrawLog(SideStoreModel):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True)
tournament = models.ForeignKey('Tournament', on_delete=models.CASCADE)
draw_date = models.DateTimeField()
draw_seed = models.IntegerField()
draw_match_index = models.IntegerField()
draw_team_position = models.IntegerField()
draw_type = models.IntegerField(default=0)
def __str__(self):
return f'{self.draw_date}'
def save(self, *args, **kwargs):
self.store_id = str(self.tournament_id())
super().save(*args, **kwargs)
def tournament_id(self):
return self.tournament.id

@ -25,13 +25,13 @@ class FederalLevelCategory(models.IntegerChoices):
class FederalAgeCategory(models.IntegerChoices):
UNLISTED = 0, ''
A11_12 = 120, 'A11_12'
A13_14 = 140, 'A13_14'
A15_16 = 160, 'A15_16'
A17_18 = 180, 'A17_18'
SENIOR = 200, 'SENIOR'
A45 = 450, 'A45'
A55 = 550, 'A55'
A11_12 = 120, 'U12'
A13_14 = 140, 'U14'
A15_16 = 160, 'U16'
A17_18 = 180, 'U18'
SENIOR = 200, 'Senior'
A45 = 450, '+45 ans'
A55 = 550, '+55 ans'
class FederalMatchCategory(models.IntegerChoices):
TWO_SETS = 0, 'Two sets'
@ -44,6 +44,11 @@ class FederalMatchCategory(models.IntegerChoices):
TWO_SETS_DECISIVE_POINT_SUPER_TIE = 7, 'Two Sets with decisive point and super tie-break'
TWO_SETS_FOUR_GAME_DECISIVE_POINT = 8, 'Two sets of four games with decisive point'
NINE_GAMES_DECISIVE_POINT = 9, 'Nine games with decisive point'
TWO_SETS_OF_SUPER_TIE = 10, 'Two sets of Super Tie-Break decisive point'
SINGLE_SET = 11, 'Single set'
SINGLE_SET_DECISIVE_POINT = 12, 'Single set with decisive point'
SINGLE_SET_OF_FOUR_GAMES = 13, 'Single set of four games'
SINGLE_SET_OF_FOUR_GAMES_DECISIVE_POINT = 14, 'Single set of four games with decisive point'
def last_set_is_tie_break(value):
if value == FederalMatchCategory.TWO_SETS_FOUR_GAME or value == FederalMatchCategory.TWO_SETS_FOUR_GAME_DECISIVE_POINT or value == FederalMatchCategory.TWO_SETS_SUPER_TIE or value == FederalMatchCategory.SUPER_TIE or value == FederalMatchCategory.MEGA_TIE or value == FederalMatchCategory.TWO_SETS_DECISIVE_POINT_SUPER_TIE:
@ -52,7 +57,7 @@ class FederalMatchCategory(models.IntegerChoices):
return False
def max_number_of_sets(value):
if value == FederalMatchCategory.SUPER_TIE or value == FederalMatchCategory.MEGA_TIE or value == FederalMatchCategory.NINE_GAMES or value == FederalMatchCategory.NINE_GAMES_DECISIVE_POINT:
if value == FederalMatchCategory.SUPER_TIE or value == FederalMatchCategory.MEGA_TIE or value == FederalMatchCategory.NINE_GAMES or value == FederalMatchCategory.NINE_GAMES_DECISIVE_POINT or value == FederalMatchCategory.SINGLE_SET or value == FederalMatchCategory.SINGLE_SET_DECISIVE_POINT or value == FederalMatchCategory.SINGLE_SET_OF_FOUR_GAMES or value == FederalMatchCategory.SINGLE_SET_OF_FOUR_GAMES_DECISIVE_POINT:
return 1
else:
return 3

@ -22,7 +22,7 @@ class Event(BaseModel):
def display_name(self):
if self.club and self.club.name and self.name:
return self.club.acronym + " " + self.name
return self.club.computedShortTitle() + " " + self.name
if self.name:
return self.name
elif self.club and self.club.name:

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save