diff --git a/api/urls.py b/api/urls.py index 1d7ec8c..acdb689 100644 --- a/api/urls.py +++ b/api/urls.py @@ -38,6 +38,8 @@ urlpatterns = [ path('api-token-auth/', obtain_auth_token, name='api_token_auth'), path("user-by-token/", views.user_by_token, name="user_by_token"), path('refund-tournament//', views.process_refund, name='process-refund'), + path('validate-stripe-account/', views.validate_stripe_account, name='validate_stripe_account'), + path('xls-to-csv/', views.xls_to_csv, name='xls-to-csv'), # authentication path("change-password/", ChangePasswordView.as_view(), name="change_password"), diff --git a/api/views.py b/api/views.py index 1534039..5513011 100644 --- a/api/views.py +++ b/api/views.py @@ -1,7 +1,7 @@ from .serializers import ClubSerializer, CourtSerializer, DateIntervalSerializer, DrawLogSerializer, TournamentSerializer, UserSerializer, EventSerializer, RoundSerializer, GroupStageSerializer, MatchSerializer, TeamScoreSerializer, TeamRegistrationSerializer, PlayerRegistrationSerializer, PurchaseSerializer, ShortUserSerializer, FailedApiCallSerializer, LogSerializer, DeviceTokenSerializer, CustomUserSerializer, UnregisteredTeamSerializer, UnregisteredPlayerSerializer from tournaments.models import Club, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamScore, TeamRegistration, PlayerRegistration, Court, DateInterval, Purchase, FailedApiCall, Log, DeviceToken, DrawLog, UnregisteredTeam, UnregisteredPlayer -from rest_framework import viewsets, permissions +from rest_framework import viewsets from rest_framework.response import Response from rest_framework.decorators import api_view from rest_framework import status @@ -19,7 +19,16 @@ from rest_framework.decorators import permission_classes from rest_framework.permissions import IsAuthenticated from django.shortcuts import get_object_or_404 -from ..tournaments.services.payment_service import PaymentService +from tournaments.services.payment_service import PaymentService +from django.conf import settings +import stripe +import json +import pandas as pd +from tournaments.utils.extensions import create_random_filename +from django.core.files.storage import default_storage +from django.core.files.base import ContentFile +import os +from django.http import HttpResponse @api_view(['GET']) def user_by_token(request): @@ -315,3 +324,86 @@ def process_refund(request, team_registration_id): 'success': False, 'message': str(e) }, status=400) + +@api_view(['POST']) +@permission_classes([IsAuthenticated]) +def validate_stripe_account(request): + stripe.api_key = settings.STRIPE_SECRET_KEY + # Parse the request body + data = json.loads(request.body) + account_id = data.get('account_id') + + if not account_id: + return Response({ + 'valid': False, + 'error': 'Account ID is required' + }, status=400) + + # Try to retrieve the account from Stripe + try: + # Basic account verification + account = stripe.Account.retrieve(account_id) + + # Only check if the account can receive payments + is_valid = account.id is not None + return Response({ + 'valid': is_valid, + 'account': { + 'id': account.id + } + }) + + except stripe.error.PermissionError: + return Response({ + 'valid': False, + 'error': 'No permission to access this account' + }, status=403) + + except stripe.error.InvalidRequestError: + return Response({ + 'valid': False, + 'error': 'Invalid account ID' + }, status=400) + +@api_view(['POST']) +@permission_classes([IsAuthenticated]) +def xls_to_csv(request): + # Check if the request has a file + if 'file' in request.FILES: + uploaded_file = request.FILES['file'] + + # Save the uploaded file + directory = 'tmp/csv/' + file_path = os.path.join(directory, uploaded_file.name) + file_name = default_storage.save(file_path, ContentFile(uploaded_file.read())) + + # Check available sheets and look for 'inscriptions' + xls = pd.ExcelFile(file_name) + sheet_names = xls.sheet_names + + # Determine which sheet to use + target_sheet = 0 # Default to first sheet + if 'inscriptions' in [name.lower() for name in sheet_names]: + for i, name in enumerate(sheet_names): + if name.lower() == 'inscriptions': + target_sheet = i # or use the name directly: target_sheet = name + break + + # Convert to csv and save + data_xls = pd.read_excel(file_name, sheet_name=target_sheet, index_col=None) + csv_file_name = create_random_filename('players', 'csv') + output_path = os.path.join(directory, csv_file_name) + data_xls.to_csv(output_path, sep=';', index=False, encoding='utf-8') + + # Send the processed file back + with default_storage.open(output_path, 'rb') as file: + response = HttpResponse(file.read(), content_type='application/octet-stream') + response['Content-Disposition'] = f'attachment; filename="players.csv"' + + # Clean up: delete both files + default_storage.delete(file_path) + default_storage.delete(output_path) + + return response + else: + return HttpResponse("No file was uploaded", status=400) diff --git a/tournaments/urls.py b/tournaments/urls.py index 9f26e7e..f712e37 100644 --- a/tournaments/urls.py +++ b/tournaments/urls.py @@ -52,8 +52,6 @@ urlpatterns = [ path('download/', views.download, name='download'), path('apns/', views.test_apns, name='test-apns'), path('terms-of-use/', views.terms_of_use, name='terms-of-use'), - path('utils/validate-stripe-account/', views.validate_stripe_account, name='validate_stripe_account'), - path('utils/xls-to-csv/', views.xls_to_csv, name='xls-to-csv'), path('mail-test/', views.simple_form_view, name='mail-test'), path('login/', CustomLoginView.as_view(), name='custom-login'), path('custom_password_change/', views.custom_password_change, name='custom_password_change'), diff --git a/tournaments/views.py b/tournaments/views.py index 4b73e91..e7fbead 100644 --- a/tournaments/views.py +++ b/tournaments/views.py @@ -1,14 +1,11 @@ # Standard library imports import os import csv -import pandas as pd -from .utils.extensions import create_random_filename from api.serializers import GroupStageSerializer, MatchSerializer, PlayerRegistrationSerializer, TeamRegistrationSerializer, TeamScoreSerializer from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth import logout from .utils.extensions import is_not_sqlite_backend import stripe -from django.views.decorators.http import require_http_methods from django.contrib.auth import update_session_auth_hash from django.contrib.auth.views import PasswordResetCompleteView @@ -21,10 +18,7 @@ from django.utils.encoding import force_str from django.utils.http import urlsafe_base64_decode from django.urls import reverse from django.conf import settings -from django.views.decorators.csrf import csrf_exempt from django.contrib.admin.views.decorators import staff_member_required -from django.core.files.storage import default_storage -from django.core.files.base import ContentFile from django.views.generic import View from django.db.models import Q from .models import Club, Tournament, CustomUser, Event, Round, Match, TeamScore, TeamRegistration, PlayerRegistration, UserOrigin @@ -560,52 +554,6 @@ def test_websocket(request): def terms_of_use(request): return render(request, 'terms_of_use.html') -@csrf_exempt -def xls_to_csv(request): - if request.method == 'POST': - # Check if the request has a file - if 'file' in request.FILES: - uploaded_file = request.FILES['file'] - - # Save the uploaded file - directory = 'tmp/csv/' - file_path = os.path.join(directory, uploaded_file.name) - file_name = default_storage.save(file_path, ContentFile(uploaded_file.read())) - - # Check available sheets and look for 'inscriptions' - xls = pd.ExcelFile(file_name) - sheet_names = xls.sheet_names - - # Determine which sheet to use - target_sheet = 0 # Default to first sheet - if 'inscriptions' in [name.lower() for name in sheet_names]: - for i, name in enumerate(sheet_names): - if name.lower() == 'inscriptions': - target_sheet = i # or use the name directly: target_sheet = name - break - - # Convert to csv and save - data_xls = pd.read_excel(file_name, sheet_name=target_sheet, index_col=None) - csv_file_name = create_random_filename('players', 'csv') - output_path = os.path.join(directory, csv_file_name) - data_xls.to_csv(output_path, sep=';', index=False, encoding='utf-8') - - # Send the processed file back - with default_storage.open(output_path, 'rb') as file: - response = HttpResponse(file.read(), content_type='application/octet-stream') - response['Content-Disposition'] = f'attachment; filename="players.csv"' - - # Clean up: delete both files - default_storage.delete(file_path) - default_storage.delete(output_path) - - return response - else: - return HttpResponse("No file was uploaded", status=400) - else: - return HttpResponse("Only POST requests are allowed", status=405) - - def simple_form_view(request): if request.method == 'POST': @@ -1514,47 +1462,6 @@ def cancel_registration(request, tournament_id): messages.info(request, "Processus d'inscription annulé.") return redirect('tournament-info', tournament_id=tournament_id) -@csrf_exempt -@require_http_methods(["POST"]) -def validate_stripe_account(request): - stripe.api_key = settings.STRIPE_SECRET_KEY - # Parse the request body - data = json.loads(request.body) - account_id = data.get('account_id') - - if not account_id: - return JsonResponse({ - 'valid': False, - 'error': 'Account ID is required' - }, status=400) - - # Try to retrieve the account from Stripe - try: - # Basic account verification - account = stripe.Account.retrieve(account_id) - - # Only check if the account can receive payments - is_valid = account.id is not None - return JsonResponse({ - 'valid': is_valid, - 'account': { - 'id': account.id - } - }) - - except stripe.error.PermissionError: - return JsonResponse({ - 'valid': False, - 'error': 'No permission to access this account' - }, status=403) - - except stripe.error.InvalidRequestError: - return JsonResponse({ - 'valid': False, - 'error': 'Invalid account ID' - }, status=400) - - class UserListExportView(LoginRequiredMixin, View): def get(self, request, *args, **kwargs): users = CustomUser.objects.order_by('date_joined')