Improve Payment Service: Add Transaction Safety and Error Handling

main
Razmig Sarkissian 3 weeks ago
parent 8de8a9ac49
commit 11d6913807
  1. 94
      tournaments/services/payment_service.py

@ -4,8 +4,10 @@ from django.urls import reverse
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.db import transaction
import stripe
from datetime import datetime, timedelta
import traceback
from ..models import TeamRegistration, PlayerRegistration, Tournament
from ..models.player_registration import PlayerPaymentType
@ -544,47 +546,67 @@ class PaymentService:
team_registration_id = metadata.get('team_registration_id')
registration_type = metadata.get('registration_type')
if tournament_id and registration_type == 'cart':
try:
tournament = Tournament.objects.get(id=tournament_id)
tournament.reserved_spots = max(0, tournament.reserved_spots - 1)
tournament.save()
print(f"Decreased reserved spots for tournament {tournament_id} after payment failure")
except Tournament.DoesNotExist:
print(f"Tournament not found with ID: {tournament_id}")
except Exception as e:
print(f"Error saving tournament for team registration: {str(e)}")
if not team_registration_id:
print("No team registration ID found in session")
return False
# Wrap all database operations in an atomic transaction
# This ensures either all changes are saved or none are
try:
print(f"Looking for team registration with ID: {team_registration_id}")
team_registration = TeamRegistration.objects.get(id=team_registration_id)
if tournament_id and registration_type == 'cart' and team_registration.tournament is None:
try:
tournament = Tournament.objects.get(id=tournament_id)
team_registration.tournament = tournament
team_registration.save()
print(f"Saved tournament for team registration {team_registration.id}")
except Tournament.DoesNotExist:
print(f"Tournament not found with ID: {tournament_id}")
except Exception as e:
print(f"Error saving tournament for team registration: {str(e)}")
if team_registration.is_paid():
return True
team_registration.confirm_registration(checkout_session.payment_intent)
with transaction.atomic():
if tournament_id and registration_type == 'cart':
try:
tournament = Tournament.objects.get(id=tournament_id)
tournament.reserved_spots = max(0, tournament.reserved_spots - 1)
tournament.save()
print(f"Decreased reserved spots for tournament {tournament_id}")
except Tournament.DoesNotExist:
print(f"Tournament not found with ID: {tournament_id}")
except Exception as e:
print(f"Error saving tournament for team registration: {str(e)}")
if not team_registration_id:
print("No team registration ID found in session")
return False
print(f"Looking for team registration with ID: {team_registration_id}")
team_registration = TeamRegistration.objects.get(id=team_registration_id)
if tournament_id and registration_type == 'cart' and team_registration.tournament is None:
try:
tournament = Tournament.objects.get(id=tournament_id)
team_registration.tournament = tournament
team_registration.save()
print(f"Saved tournament for team registration {team_registration.id}")
except Tournament.DoesNotExist:
print(f"Tournament not found with ID: {tournament_id}")
except Exception as e:
print(f"Error saving tournament for team registration: {str(e)}")
if team_registration.is_paid():
print(f"Team registration {team_registration.id} is already paid")
return True
# Update player registration with payment info
team_registration.confirm_registration(checkout_session.payment_intent)
print(f"✅ Registration confirmed and committed to database")
TournamentEmailService.send_payment_confirmation(team_registration, checkout_session.payment_intent)
return True
except TeamRegistration.DoesNotExist:
print(f"Team registration not found with ID: {team_registration_id}")
return False
except Exception as e:
print(f"Error in _process_direct_payment: {str(e)}")
return False
print(f"❌ Error in process_direct_payment database operations: {str(e)}")
traceback.print_exc()
return False
# After successful database commit, send confirmation email
# Email failures won't affect the payment confirmation
try:
print(f"Sending payment confirmation email...")
TournamentEmailService.send_payment_confirmation(team_registration, checkout_session.payment_intent)
print(f"✅ Email sent successfully")
except Exception as email_error:
print(f" Warning: Email sending failed but payment was confirmed: {str(email_error)}")
traceback.print_exc()
# Don't return False - payment is still confirmed
return True
@staticmethod
@csrf_exempt

Loading…
Cancel
Save