from django.utils import timezone import uuid import datetime from ..models import PlayerRegistration, TeamRegistration, Tournament from ..utils.licence_validator import LicenseValidator from ..utils.player_search import get_player_name_from_csv def get_or_create_registration_cart_id(request): """Get or create a registration cart ID in the session""" if 'registration_cart_id' not in request.session: request.session['registration_cart_id'] = str(uuid.uuid4()) return request.session['registration_cart_id'] def get_cart_expiry(request): """Get the cart expiry time from the session""" if 'registration_cart_expiry' not in request.session: # Set default expiry to 30 minutes from now expiry = timezone.now() + datetime.timedelta(minutes=30) request.session['registration_cart_expiry'] = expiry.isoformat() return request.session['registration_cart_expiry'] def is_cart_expired(request): """Check if the registration cart is expired""" if 'registration_cart_expiry' not in request.session: return False expiry_str = request.session['registration_cart_expiry'] try: expiry = datetime.datetime.fromisoformat(expiry_str) return timezone.now() > expiry except (ValueError, TypeError): return True def reset_cart_expiry(request): """Reset the cart expiry time""" expiry = timezone.now() + datetime.timedelta(minutes=30) request.session['registration_cart_expiry'] = expiry.isoformat() request.session.modified = True def get_tournament_from_cart(request): """Get the tournament ID associated with the current cart""" return request.session.get('registration_tournament_id') def initialize_registration_cart(request, tournament_id): """Initialize a new registration cart for a tournament""" # Clear any existing cart clear_registration_cart(request) # Set up the new cart request.session['registration_cart_id'] = str(uuid.uuid4()) request.session['registration_tournament_id'] = tournament_id request.session['registration_cart_players'] = [] reset_cart_expiry(request) request.session.modified = True def get_registration_cart_data(request): """Get the data for the current registration cart""" # Ensure cart players array exists if 'registration_cart_players' not in request.session: request.session['registration_cart_players'] = [] request.session.modified = True # Ensure tournament ID exists if 'registration_tournament_id' not in request.session: # If no tournament ID but we have players, this is an inconsistency if request.session.get('registration_cart_players'): print("WARNING: Found players but no tournament ID - clearing players") request.session['registration_cart_players'] = [] request.session.modified = True cart_data = { 'cart_id': get_or_create_registration_cart_id(request), 'tournament_id': request.session.get('registration_tournament_id'), 'players': request.session.get('registration_cart_players', []), 'expiry': get_cart_expiry(request), 'mobile_number': request.session.get('registration_mobile_number', request.user.phone if hasattr(request.user, 'phone') else '') } # Debug: print the cart content print(f"Cart data - Tournament ID: {cart_data['tournament_id']}") print(f"Cart data - Players count: {len(cart_data['players'])}") return cart_data def add_player_to_cart(request, player_data): """Add a player to the registration cart""" if is_cart_expired(request): return False, "Votre session d'inscription a expiré, veuillez réessayer." # Get cart data tournament_id = request.session.get('registration_tournament_id') if not tournament_id: return False, "Pas d'inscription active." # Get tournament try: tournament = Tournament.objects.get(id=tournament_id) except Tournament.DoesNotExist: return False, "Tournoi introuvable." # Get existing players directly from session players = request.session.get('registration_cart_players', []) # Debug: Initial players count print(f"Before adding - Players in session: {len(players)}") # Check if we've reached the team limit (usually 2 for padel) if len(players) >= 2: # Assuming teams of 2 for padel return False, "Nombre maximum de joueurs déjà ajouté." # Process player data licence_id = player_data.get('licence_id', '').upper() if player_data.get('licence_id') else None first_name = player_data.get('first_name', '') last_name = player_data.get('last_name', '').upper() # Handle case where user is authenticated, has no license, and license is required if tournament.license_is_required: # If license is required but not provided if not licence_id: # First player (authentication check) or partner user_message = "Le numéro de licence est obligatoire." if len(players) == 0 else "Le numéro de licence de votre partenaire est obligatoire." return False, user_message # Validate the license format validator = LicenseValidator(licence_id) if not validator.validate_license(): return False, "Le numéro de licence est invalide, la lettre ne correspond pas." # Check if player is already registered in tournament stripped_license = validator.stripped_license if _is_player_already_registered(stripped_license, tournament): return False, "Un joueur avec ce numéro de licence est déjà inscrit dans une équipe." # Check if this is the authenticated user trying to register as first player if request.user.is_authenticated and len(players) == 0 and request.user.licence_id is None: # Try to update the user's license ID in the database try: request.user.licence_id = validator.computed_licence_id request.user.save() request.user.refresh_from_db() except: return False, "Erreur lors de la mise à jour de votre licence: cette licence est déjà utilisée par un autre joueur." # Check for duplicate licenses in cart existing_licenses = [p.get('licence_id') for p in players if p.get('licence_id')] if licence_id and licence_id in existing_licenses: return False, "Ce joueur est déjà dans l'équipe." # Process based on whether license ID was provided and tournament rules if licence_id: # Get federation data fed_data, found = get_player_name_from_csv(tournament.federal_category, licence_id) if found and fed_data: # Use federation data (including check for eligibility) player_register_check = tournament.player_register_check(licence_id) if player_register_check: return False, ", ".join(player_register_check) # Update player data from federation data player_data.update({ 'first_name': fed_data['first_name'], 'last_name': fed_data['last_name'], 'rank': fed_data['rank'], 'is_woman': fed_data['is_woman'], 'points': fed_data.get('points'), 'assimilation': fed_data.get('assimilation'), 'tournament_count': fed_data.get('tournament_count'), 'ligue_name': fed_data.get('ligue_name'), 'club_name': fed_data.get('club_name'), 'birth_year': fed_data.get('birth_year'), 'found_in_french_federation': True, }) elif tournament.license_is_required: # License required but not found in federation data return False, "La licence fournit n'a pas été trouvée dans la base FFT. Contactez le juge arbitre si cette licence est valide." elif not first_name or not last_name: # License not required or not found, but name is needed return False, "Le prénom et le nom sont obligatoires pour les joueurs sans licence." elif not tournament.license_is_required: # License not required, check if name is provided if not first_name or not last_name: return False, "Le prénom et le nom sont obligatoires pour les joueurs sans licence." # Set default rank for players without a license if player_data.get('rank') is None: default_data, _ = get_player_name_from_csv(tournament.federal_category, None) if default_data: player_data['rank'] = default_data.get('rank') player_data['is_woman'] = default_data.get('is_woman', False) else: # License is required but not provided return False, "Le numéro de licence est obligatoire." # Add player to cart players.append(player_data) request.session['registration_cart_players'] = players reset_cart_expiry(request) request.session.modified = True return True, "Joueur ajouté avec succès." def remove_player_from_cart(request): """Remove the last player from the cart""" if is_cart_expired(request): return False, "Votre session d'inscription a expiré, veuillez réessayer." players = request.session.get('registration_cart_players', []) if not players: return False, "Pas de joueur à supprimer." # Remove last player players.pop() request.session['registration_cart_players'] = players reset_cart_expiry(request) request.session.modified = True # If cart is now empty and user is authenticated with license, re-add them automatically if not players: add_authenticated_user_to_cart(request) return True, "Joueur retiré." def update_cart_contact_info(request, mobile_number=None): """Update contact info for the cart""" if is_cart_expired(request): return False, "Votre session d'inscription a expiré, veuillez réessayer." if mobile_number is not None: request.session['registration_mobile_number'] = mobile_number reset_cart_expiry(request) request.session.modified = True return True, "Informations de contact mises à jour." def checkout_registration_cart(request): """Convert cart to an actual tournament registration""" if is_cart_expired(request): return False, "Votre session d'inscription a expiré, veuillez réessayer." # Get cart data cart_data = get_registration_cart_data(request) tournament_id = cart_data.get('tournament_id') players = cart_data.get('players') mobile_number = cart_data.get('mobile_number') # Validate cart data if not tournament_id: return False, "Aucun tournoi sélectionné." if not players: return False, "Aucun joueur dans l'inscription." # Get tournament try: tournament = Tournament.objects.get(id=tournament_id) except Tournament.DoesNotExist: return False, "Tournoi introuvable." # Check minimum players if len(players) < tournament.minimum_player_per_team: return False, f"Vous avez besoin d'au moins {tournament.minimum_player_per_team} joueurs pour vous inscrire." # Create team registration team_registration = TeamRegistration.objects.create( tournament=tournament, registration_date=timezone.now(), walk_out=False ) # Create player registrations for idx, player_data in enumerate(players): PlayerRegistration.objects.create( team_registration=team_registration, first_name=player_data.get('first_name', ''), last_name=player_data.get('last_name', '').upper(), licence_id=player_data.get('licence_id'), rank=player_data.get('rank'), points=player_data.get('points'), club_name=player_data.get('club_name'), ligue_name=player_data.get('ligue_name'), email=player_data.get('email'), phone_number=player_data.get('phone'), assimilation=player_data.get('assimilation'), tournament_played=player_data.get('tournament_count'), birthdate=str(player_data.get('birth_year', '')), captain=(idx == 0), # First player is captain registered_online=True, registration_status='CONFIRMED' if tournament.get_waiting_list_position() < 0 else 'WAITING' ) # Update user phone if provided if request.user.is_authenticated and mobile_number: request.user.phone = mobile_number request.user.save(update_fields=['phone']) # Clear the cart clear_registration_cart(request) return True, team_registration def clear_registration_cart(request): """Clear the registration cart""" keys_to_clear = [ 'registration_cart_id', 'registration_tournament_id', 'registration_cart_players', 'registration_cart_expiry', 'registration_mobile_number' ] for key in keys_to_clear: if key in request.session: del request.session[key] request.session.modified = True def _is_player_already_registered(stripped_license, tournament): """Check if a player is already registered in the tournament""" return PlayerRegistration.objects.filter( team_registration__tournament=tournament, licence_id__icontains=stripped_license, team_registration__walk_out=False ).exists() def add_authenticated_user_to_cart(request): """ Adds the authenticated user to the cart if they have a valid license. Returns True if added, False otherwise. """ if not request.user.is_authenticated or not request.user.licence_id: return False # Create player data for the authenticated user player_data = { 'first_name': request.user.first_name, 'last_name': request.user.last_name, 'licence_id': request.user.licence_id, 'email': request.user.email, 'phone': request.user.phone } # Add the user to the cart success, _ = add_player_to_cart(request, player_data) return success