from rest_framework import serializers from django.db.utils import IntegrityError from django.template.loader import render_to_string from django.utils.http import urlsafe_base64_encode 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 shared.cryptography import encryption_util from tournaments.models import Club, LiveMatch, TeamScore, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamRegistration, PlayerRegistration, Purchase, FailedApiCall, DateInterval, Log, DeviceToken, UnregisteredTeam, UnregisteredPlayer, Image, DrawLog, Court from tournaments.models.enums import UserOrigin, RegistrationPaymentMode from biz.models import Activity, Prospect, Entity 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) def create(self, validated_data): # print(validated_data) umpire_code = None if 'umpire_code' in validated_data: umpire_code = validated_data['umpire_code'] phone = None if 'phone' in validated_data: phone = validated_data['phone'] licence_id = None if 'licence_id' in validated_data: licence_id = validated_data['licence_id'] country = None if 'country' in validated_data: country = validated_data['country'] username_lower = validated_data['username'].lower() if CustomUser.objects.filter(username__iexact=username_lower) | CustomUser.objects.filter(email__iexact=username_lower): raise serializers.ValidationError("Cet identifiant est déjà utilisé. Veuillez en choisir un autre :)") user = CustomUser.objects.create_user( username=validated_data['username'], last_update=validated_data.get('last_update'), email=validated_data['email'], password=validated_data['password'], first_name=validated_data['first_name'], last_name=validated_data['last_name'], is_active=False, umpire_code=umpire_code, phone=phone, licence_id=licence_id, country=country, summons_message_body=validated_data.get('summons_message_body'), summons_message_signature=validated_data.get('summons_message_signature'), summons_available_payment_methods=validated_data.get('summons_available_payment_methods'), summons_display_format=validated_data.get('summons_display_format'), summons_display_entry_fee=validated_data.get('summons_display_entry_fee'), summons_use_full_custom_message=validated_data.get('summons_use_full_custom_message'), match_formats_default_duration=validated_data.get('match_formats_default_duration'), 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'), origin=UserOrigin.APP, user_role=None, registration_payment_mode=validated_data.get('registration_payment_mode', RegistrationPaymentMode.DISABLED), umpire_custom_mail=validated_data.get('umpire_custom_mail'), umpire_custom_contact=validated_data.get('umpire_custom_contact'), umpire_custom_phone=validated_data.get('umpire_custom_phone'), hide_umpire_mail=validated_data.get('hide_umpire_mail', False), hide_umpire_phone=validated_data.get('hide_umpire_phone', True), disable_ranking_federal_ruling=validated_data.get('disable_ranking_federal_ruling', False) ) self.send_email(self.context['request'], user) # RegistrationProfile.objects.filter(user=user).send_activation_email() return user def send_email(self, request, user): current_site = get_current_site(request) mail_subject = 'Activez votre compte Padel Club !' message = render_to_string('tournaments/acc_active_email.html', { 'user': user, 'domain': current_site.domain, 'uid': urlsafe_base64_encode(force_bytes(user.pk)), 'token': account_activation_token.make_token(user), }) email = EmailMessage(mail_subject, message, to=[user.email]) email.content_subtype = "html" email.send() class Meta: club_id = serializers.PrimaryKeyRelatedField(queryset=Club.objects.all()) model = CustomUser fields = '__all__' # ['id', 'username', 'password', 'umpire_code', 'clubs', 'phone', 'first_name', 'last_name', 'licence_id'] class CustomUserSerializer(serializers.ModelSerializer): ### the one matching the CustomUser class and used for sync class Meta: model = CustomUser fields = CustomUser.fields_for_update() class ShortUserSerializer(serializers.ModelSerializer): class Meta: model = CustomUser fields = ['id', 'first_name', 'last_name'] class ClubSerializer(serializers.ModelSerializer): class Meta: model = Club fields = '__all__' def create(self, validated_data): user = self.context['request'].user validated_data['creator'] = user return super().create(validated_data) class TournamentSerializer(serializers.ModelSerializer): class Meta: model = Tournament fields = '__all__' class TournamentSummarySerializer(serializers.ModelSerializer): # English field names for all the information described in the comment tournament_name = serializers.SerializerMethodField() tournament_information = serializers.CharField(source='information', read_only=True) start_date = serializers.SerializerMethodField() end_date = serializers.SerializerMethodField() tournament_category = serializers.SerializerMethodField() # P25/P100/P250 as string tournament_type = serializers.SerializerMethodField() # homme/femme/mixte as string tournament_age_category = serializers.SerializerMethodField() # U10, U12, Senior, +45, etc. as string max_teams = serializers.IntegerField(source='team_count', read_only=True) registered_teams_count = serializers.SerializerMethodField() tournament_status = serializers.SerializerMethodField() # status as string registration_link = serializers.SerializerMethodField() umpire_name = serializers.SerializerMethodField() umpire_phone = serializers.SerializerMethodField() umpire_email = serializers.SerializerMethodField() class Meta: model = Tournament fields = [ 'id', 'tournament_name', 'tournament_information', 'start_date', 'end_date', 'tournament_category', 'tournament_type', 'tournament_age_category', 'max_teams', 'registered_teams_count', 'tournament_status', 'registration_link', 'umpire_name', 'umpire_phone', 'umpire_email' ] def get_start_date(self, obj): """Get formatted start date""" return obj.local_start_date() def get_end_date(self, obj): """Get formatted end date""" return obj.local_end_date() def get_tournament_name(self, obj): """Get the tournament name""" return obj.name or obj.name_and_event() def get_tournament_category(self, obj): """Get tournament category as string label (P25, P100, P250, etc.)""" return obj.level() def get_tournament_type(self, obj): """Get tournament type as string label (homme, femme, mixte)""" return obj.category() def get_tournament_age_category(self, obj): """Get tournament age category as string label (U10, U12, Senior, +45, etc.)""" return obj.age() def get_registered_teams_count(self, obj): """Get number of registered teams""" return len(obj.teams(False)) def get_tournament_status(self, obj): """Get tournament status as string""" return obj.get_tournament_status() def get_registration_link(self, obj): """Get appropriate link based on tournament status""" # This will need to be adapted based on your URL structure # For now, returning a placeholder that you can customize status = obj.get_online_registration_status() base_url = "https://padelclub.app/" if status.value in [1, 3, 5]: # OPEN, NOT_STARTED, WAITING_LIST_POSSIBLE return f"{base_url}tournament/{obj.id}/info/" elif status.value == 7: # IN_PROGRESS return f"{base_url}tournament/{obj.id}/live/" elif status.value == 8: # ENDED_WITH_RESULTS return f"{base_url}tournament/{obj.id}/rankings/" else: return f"{base_url}tournament/{obj.id}/info/" def get_umpire_name(self, obj): """Get umpire/referee name""" return obj.umpire_contact() def get_umpire_phone(self, obj): """Get umpire phone number""" return obj.umpire_phone() def get_umpire_email(self, obj): """Get umpire email address""" return obj.umpire_mail() class EventSerializer(serializers.ModelSerializer): class Meta: #club_id = serializers.PrimaryKeyRelatedField(queryset=Club.objects.all()) model = Event fields = '__all__' class RoundSerializer(serializers.ModelSerializer): class Meta: model = Round fields = '__all__' class GroupStageSerializer(serializers.ModelSerializer): class Meta: model = GroupStage fields = '__all__' class MatchSerializer(serializers.ModelSerializer): class Meta: model = Match fields = '__all__' class TeamScoreSerializer(serializers.ModelSerializer): class Meta: model = TeamScore fields = '__all__' class TeamRegistrationSerializer(serializers.ModelSerializer): class Meta: model = TeamRegistration fields = '__all__' class PlayerRegistrationSerializer(serializers.ModelSerializer): class Meta: model = PlayerRegistration fields = '__all__' class PurchaseSerializer(serializers.ModelSerializer): user = EncryptedUserField() class Meta: model = Purchase fields = '__all__' def create(self, validated_data): user = self.context['request'].user validated_data['user'] = user return super().create(validated_data) class LiveMatchSerializer(serializers.ModelSerializer): class Meta: model = LiveMatch fields = '__all__' # ['title', 'date'] # Serialize all fields of the model class CourtSerializer(serializers.ModelSerializer): class Meta: model = Court fields = '__all__' class DateIntervalSerializer(serializers.ModelSerializer): class Meta: model = DateInterval fields = '__all__' class FailedApiCallSerializer(serializers.ModelSerializer): class Meta: model = FailedApiCall fields = '__all__' class LogSerializer(serializers.ModelSerializer): class Meta: model = Log fields = '__all__' class DeviceTokenSerializer(serializers.ModelSerializer): class Meta: model = DeviceToken fields = '__all__' read_only_fields = ['user'] class DrawLogSerializer(serializers.ModelSerializer): class Meta: model = DrawLog fields = '__all__' class UnregisteredTeamSerializer(serializers.ModelSerializer): class Meta: # match_id = serializers.PrimaryKeyRelatedField(queryset=Match.objects.all()) # group_stage_id = serializers.PrimaryKeyRelatedField(queryset=GroupStage.objects.all()) model = UnregisteredTeam fields = '__all__' # ['id', 'group_stage_id', 'registration_date', 'call_date', 'bracket_position', # 'group_stage_position', 'logo'] class UnregisteredPlayerSerializer(serializers.ModelSerializer): class Meta: # team_registration_id = serializers.PrimaryKeyRelatedField(queryset=TeamRegistration.objects.all()) # team_state_id = serializers.PrimaryKeyRelatedField(queryset=TeamState.objects.all()) model = UnregisteredPlayer fields = '__all__' # ['id', 'team_registration_id', 'first_name', 'last_name', 'licence_id', 'rank', 'has_paid'] class ImageSerializer(serializers.ModelSerializer): image_url = serializers.SerializerMethodField() def get_image_url(self, obj): if obj.image: return self.context['request'].build_absolute_uri(obj.image.url) return None class Meta: model = Image fields = ['id', 'title', 'description', 'image', 'image_url', 'uploaded_at', 'event', 'image_type'] read_only_fields = ['id', 'uploaded_at', 'image_url'] ### CRM class ActivitySerializer(serializers.ModelSerializer): class Meta: model = Activity fields = '__all__' class ProspectSerializer(serializers.ModelSerializer): class Meta: model = Prospect fields = '__all__' class EntitySerializer(serializers.ModelSerializer): class Meta: model = Entity fields = '__all__'