fix payment errors

timetoconfirm
Raz 7 months ago
parent 840d760ba4
commit 01a2c8880b
  1. 3
      api/views.py
  2. 77
      tournaments/services/email_service.py
  3. 2
      tournaments/services/payment_service.py
  4. 14
      tournaments/services/tournament_registration.py
  5. 13
      tournaments/views.py

@ -313,11 +313,12 @@ def process_refund(request, team_registration_id):
}, status=403) }, status=403)
payment_service = PaymentService(request) payment_service = PaymentService(request)
players_serializer = PlayerRegistrationSerializer(team_registration.players_sorted_by_rank, many=True)
success, message, refund = payment_service.process_refund(team_registration_id) success, message, refund = payment_service.process_refund(team_registration_id)
return Response({ return Response({
'success': success, 'success': success,
'message': message, 'message': message,
'players': team_registration.players_sorted_by_rank 'players': players_serializer.data
}) })
except Exception as e: except Exception as e:
return Response({ return Response({

@ -2,6 +2,7 @@ from django.core.mail import EmailMessage
from enum import Enum from enum import Enum
from ..models.enums import RegistrationStatus from ..models.enums import RegistrationStatus
from ..models.tournament import TeamSortingType from ..models.tournament import TeamSortingType
from django.utils import timezone
class TeamEmailType(Enum): class TeamEmailType(Enum):
REGISTERED = "registered" REGISTERED = "registered"
@ -515,13 +516,85 @@ class TournamentEmailService:
# For unpaid teams, add payment instructions # For unpaid teams, add payment instructions
payment_info = [ payment_info = [
"\n\n Paiement des frais d'inscription requis", "\n\n Paiement des frais d'inscription requis",
f"Les frais d'inscription de {tournament.entry_fee}€ par joueur doivent être payés pour confirmer votre participation.", f"Les frais d'inscription de {tournament.entry_fee:.2f}€ par joueur doivent être payés pour confirmer votre participation.",
"Vous pouvez effectuer le paiement en vous connectant à votre compte Padel Club.", "Vous pouvez effectuer le paiement en vous connectant à votre compte Padel Club.",
f"Lien pour payer: https://padelclub.app/tournament/{tournament.id}/info" f"Lien pour payer: https://padelclub.app/tournament/{tournament.id}/info"
] ]
return "\n".join(payment_info) return "\n".join(payment_info)
@staticmethod
def send_payment_confirmation(team_registration, payment):
"""
Send a payment confirmation email to team members
Args:
team_registration: The team registration
payment: The payment details from Stripe
"""
tournament = team_registration.tournament
player_registrations = team_registration.players_sorted_by_rank
# Calculate payment amount
payment_amount = None
if payment and 'amount' in payment:
# Convert cents to euros
payment_amount = payment['amount'] / 100
if payment_amount is None:
payment_amount = tournament.team_fee()
for player in player_registrations:
if not player.email or not player.registered_online:
continue
tournament_details_str = tournament.build_tournament_details_str()
other_player = team_registration.get_other_player(player) if len(player_registrations) > 1 else None
body_parts = [
"Bonjour,\n\n",
f"Votre paiement pour le tournoi {tournament_details_str}, prévu le {tournament.formatted_start_date()} au club {tournament.event.club.name} a été reçu avec succès."
]
# Add information about the other player if available
if other_player:
body_parts.append(
f"\n\nVous êtes inscrit avec {other_player.name()}, n'oubliez pas de prévenir votre partenaire de la confirmation du paiement."
)
# Add payment details
body_parts.append(
f"\n\nMontant payé : {payment_amount:.2f}"
)
payment_date = timezone.now().strftime("%d/%m/%Y")
body_parts.append(
f"\nDate du paiement : {payment_date}"
)
absolute_url = f"https://padelclub.app/tournament/{tournament.id}/info"
link_text = "informations sur le tournoi"
absolute_url = f'<a href="{absolute_url}">{link_text}</a>'
body_parts.append(f"\n\nVoir les {absolute_url}")
if tournament.team_sorting == TeamSortingType.RANK:
cloture_date = tournament.local_registration_federal_limit().strftime("%d/%m/%Y à %H:%M")
loc = ""
if cloture_date is not None:
loc = f", prévu le {cloture_date}"
body_parts.append(f"\n\nAttention, la sélection définitive se fera par poids d'équipe à la clôture des inscriptions{loc}.")
body_parts.extend([
f"\n\n{TournamentEmailService._format_umpire_contact(tournament)}",
"\n\nCeci est un e-mail automatique, veuillez ne pas y répondre."
])
email_body = "".join(body_parts)
email_subject = TournamentEmailService.email_subject(tournament, "Confirmation de paiement")
TournamentEmailService._send_email(player.email, email_subject, email_body)
@staticmethod @staticmethod
def send_refund_confirmation(tournament, team_registration, refund_details): def send_refund_confirmation(tournament, team_registration, refund_details):
""" """
@ -562,7 +635,7 @@ class TournamentEmailService:
# Add refund details # Add refund details
body_parts.append( body_parts.append(
f"\n\nMontant remboursé : {refund_amount}€ par joueur" f"\n\nMontant remboursé : {refund_amount:.2f}"
) )
refund_date = timezone.now().strftime("%d/%m/%Y") refund_date = timezone.now().strftime("%d/%m/%Y")

@ -233,6 +233,8 @@ class PaymentService:
if 'team_registration_id' in self.request.session: if 'team_registration_id' in self.request.session:
del self.request.session['team_registration_id'] del self.request.session['team_registration_id']
if success:
TournamentEmailService.send_payment_confirmation(team_registration, checkout_session.payment_intent)
return success return success
except TeamRegistration.DoesNotExist: except TeamRegistration.DoesNotExist:
print(f"Team registration not found with ID: {team_registration_id}") print(f"Team registration not found with ID: {team_registration_id}")

@ -6,6 +6,7 @@ from ..utils.licence_validator import LicenseValidator
from ..utils.player_search import get_player_name_from_csv from ..utils.player_search import get_player_name_from_csv
from ..models.enums import FederalCategory, RegistrationStatus from ..models.enums import FederalCategory, RegistrationStatus
from ..models.player_enums import PlayerSexType, PlayerDataSource from ..models.player_enums import PlayerSexType, PlayerDataSource
from django.contrib.auth import get_user_model
class RegistrationCartManager: class RegistrationCartManager:
""" """
@ -351,6 +352,15 @@ class RegistrationCartManager:
if player_data.get('found_in_french_federation', False) == True: if player_data.get('found_in_french_federation', False) == True:
data_source = PlayerDataSource.FRENCH_FEDERATION # Now using the enum value data_source = PlayerDataSource.FRENCH_FEDERATION # Now using the enum value
User = get_user_model()
matching_user = None
if player_licence_id:
try:
# Using icontains for case-insensitive match
matching_user = User.objects.get(licence_id__icontains=player_licence_id)
except User.DoesNotExist:
pass
# Create player registration with all the original fields # Create player registration with all the original fields
PlayerRegistration.objects.create( PlayerRegistration.objects.create(
team_registration=team_registration, team_registration=team_registration,
@ -369,8 +379,8 @@ class RegistrationCartManager:
rank=rank, rank=rank,
computed_rank=computed_rank, computed_rank=computed_rank,
licence_id=player_data.get('licence_id'), licence_id=player_data.get('licence_id'),
email=player_data.get('email'), email=matching_user.email if matching_user else player_data.get('email'),
phone_number=player_data.get('mobile_number', mobile_number), phone_number=matching_user.phone if matching_user else player_data.get('mobile_number'),
registration_status=RegistrationStatus.CONFIRMED if self.session.get('waiting_list_position', 0) < 0 else RegistrationStatus.WAITING registration_status=RegistrationStatus.CONFIRMED if self.session.get('waiting_list_position', 0) < 0 else RegistrationStatus.WAITING
) )

@ -1306,6 +1306,14 @@ def handle_add_player_request(request, tournament, cart_manager, context):
"""Handle the 'add_player' POST action""" """Handle the 'add_player' POST action"""
add_player_form = AddPlayerForm(request.POST) add_player_form = AddPlayerForm(request.POST)
if add_player_form.is_valid(): if add_player_form.is_valid():
# Get the current form data for phone number
team_form = TournamentRegistrationForm(request.POST)
if team_form.is_valid():
# Update cart with mobile number before adding player
cart_manager.update_contact_info(
mobile_number=team_form.cleaned_data.get('mobile_number')
)
success, message = cart_manager.add_player(add_player_form.cleaned_data) success, message = cart_manager.add_player(add_player_form.cleaned_data)
if success: if success:
messages.success(request, message) messages.success(request, message)
@ -1313,6 +1321,11 @@ def handle_add_player_request(request, tournament, cart_manager, context):
cart_data = cart_manager.get_cart_data() cart_data = cart_manager.get_cart_data()
context['current_players'] = cart_data['players'] context['current_players'] = cart_data['players']
context['team_form'] = TournamentRegistrationForm(initial={
'email': request.user.email if request.user.is_authenticated else '',
'mobile_number': cart_data.get('mobile_number', '')
})
# Prepare a fresh form for the next player if needed # Prepare a fresh form for the next player if needed
if len(cart_data['players']) < tournament.minimum_player_per_team: if len(cart_data['players']) < tournament.minimum_player_per_team:
context['add_player_form'] = AddPlayerForm() context['add_player_form'] = AddPlayerForm()

Loading…
Cancel
Save