1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2025-06-22 22:38:24 +02:00

Configure Hello Asso return endpoint

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello
2024-02-20 22:54:12 +01:00
parent 8c7e9648dd
commit 8d08b18d08
5 changed files with 259 additions and 120 deletions

View File

@ -80,6 +80,14 @@ class Registration(PolymorphicModel):
def participates(self):
return isinstance(self, ParticipantRegistration)
@property
def is_student(self):
return isinstance(self, StudentRegistration)
@property
def is_coach(self):
return isinstance(self, CoachRegistration)
@property
def is_admin(self):
return isinstance(self, VolunteerRegistration) and self.admin or self.user.is_superuser
@ -566,6 +574,17 @@ class Payment(models.Model):
default=False,
)
@property
def team(self):
return self.registrations.first().team
@property
def tournament(self):
if self.final:
from participation.models import Tournament
return Tournament.final_tournament()
return self.registrations.first().team.participation.tournament
def get_checkout_intent(self):
if self.checkout_intent_id is None:
return None
@ -576,17 +595,15 @@ class Payment(models.Model):
if checkout_intent is not None:
return checkout_intent
from participation.models import Tournament
tournament = self.registrations.first().team.participation.tournament \
if not self.final else Tournament.final_tournament()
tournament = self.tournament
year = datetime.now().year
base_site = "https://" + Site.objects.first().domain
checkout_intent = helloasso.create_checkout_intent(
amount=100 * self.amount,
name=f"Participation au TFJM² {year} - {tournament.name}",
back_url=base_site + reverse('registration:update_payment', args=(self.id,)),
error_url=base_site + reverse('registration:update_payment', args=(self.id,)),
return_url=base_site + reverse('registration:update_payment', args=(self.id,)),
error_url=f"{base_site}{reverse('registration:payment_hello_asso_return', args=(self.id,))}?type=error",
return_url=f"{base_site}{reverse('registration:payment_hello_asso_return', args=(self.id,))}?type=return",
contains_donation=False,
metadata=dict(
users=[

View File

@ -5,7 +5,7 @@ from django.urls import path
from .views import AddOrganizerView, AdultPhotoAuthorizationTemplateView, ChildPhotoAuthorizationTemplateView, \
InstructionsTemplateView, MyAccountDetailView, ParentalAuthorizationTemplateView, \
PaymentUpdateGroupView, PaymentUpdateView, PaymenRedirectHelloAssoView, \
PaymentHelloAssoReturnView, PaymentUpdateGroupView, PaymentUpdateView, PaymenRedirectHelloAssoView, \
ResetAdminView, SignupView, UserDetailView, UserImpersonateView, UserListView, UserResendValidationEmailView, \
UserUpdateView, UserUploadHealthSheetView, UserUploadParentalAuthorizationView, UserUploadPhotoAuthorizationView, \
UserUploadVaccineSheetView, UserValidateView, UserValidationEmailSentView
@ -41,6 +41,8 @@ urlpatterns = [
path("update-payment/<int:pk>/toggle-group-mode/", PaymentUpdateGroupView.as_view(),
name="update_payment_group_mode"),
path("update-payment/<int:pk>/hello-asso/", PaymenRedirectHelloAssoView.as_view(), name="payment_hello_asso"),
path("update-payment/<int:pk>/hello-asso/return/", PaymentHelloAssoReturnView.as_view(),
name="payment_hello_asso_return"),
path("user/<int:pk>/impersonate/", UserImpersonateView.as_view(), name="user_impersonate"),
path("user/list/", UserListView.as_view(), name="user_list"),
path("reset-admin/", ResetAdminView.as_view(), name="reset_admin"),

View File

@ -6,6 +6,7 @@ import subprocess
from tempfile import mkdtemp
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
@ -19,6 +20,7 @@ from django.urls import reverse_lazy
from django.utils import timezone, translation
from django.utils.crypto import get_random_string
from django.utils.http import urlsafe_base64_decode
from django.utils.text import format_lazy
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, DetailView, RedirectView, TemplateView, UpdateView, View
from django_tables2 import SingleTableView
@ -215,6 +217,7 @@ class MyAccountDetailView(LoginRequiredMixin, RedirectView):
"""
Redirect to our own profile detail page.
"""
def get_redirect_url(self, *args, **kwargs):
return reverse_lazy("registration:user_detail", args=(self.request.user.pk,))
@ -550,10 +553,76 @@ class PaymenRedirectHelloAssoView(LoginRequiredMixin, DetailView):
return redirect(checkout_intent["redirectUrl"])
class PaymentHelloAssoReturnView(DetailView):
model = Payment
def get(self, request, *args, **kwargs):
checkout_id = request.GET.get("checkoutIntentId")
payment = Payment.objects.get(checkout_intent_id=checkout_id).exclude(valid=True)
if payment != self.get_object():
messages.error(request, _("The payment is not found or is already validated."))
return redirect("index")
team = payment.team
tournament = payment.tournament
right_to_see = not request.user.is_anonymous \
and (request.user.registration.is_admin
or request.user.registration in payment.registrations.all()
or (request.user.registration.is_volunteer
and tournament in request.user.registration.organized_tournaments.all())
or (request.user.registration.is_coach and request.user.registration.team == team))
if right_to_see:
error_response = redirect("registration:update_payment", args=(payment.pk,))
else:
error_response = redirect("index")
return_type = request.GET.get("type")
if return_type == "error":
messages.error(request, format_lazy(_("An error occurred during the payment: {error}"),
error=request.GET.get("error")))
return error_response
elif return_type == "return":
code = request.GET.get("code")
if code == "refused":
messages.error(request, _("The payment has been refused."))
return error_response
elif code != "success":
messages.error(request, format_lazy(_("The return code is unknown: {code}"), code=code))
return error_response
else:
messages.error(request, format_lazy(_("The return type is unknown: {type}"), type=return_type))
return error_response
checkout_intent = payment.get_checkout_intent()
if 'order' in checkout_intent:
payment.valid = True
payment.save()
messages.success(request, _("The payment has been successfully validated! "
"Your registration is now complete."))
else:
payment.valid = None
payment.save()
messages.success(request, _("Your payment is done! "
"The validation of your payment may takes a few minutes, "
"and will be automatically done. "
"If it is not the case, please contact us."))
if request.user.registration in payment.registrations.all():
success_response = redirect("registration:user_detail", args=(request.user.pk,))
elif right_to_see:
success_response = redirect("participation:team_detail", args=(team.pk,))
else:
success_response = redirect("index")
return success_response
class PhotoAuthorizationView(LoginRequiredMixin, View):
"""
Display the sent photo authorization.
"""
def get(self, request, *args, **kwargs):
filename = kwargs["filename"]
path = f"media/authorization/photo/{filename}"
@ -577,6 +646,7 @@ class HealthSheetView(LoginRequiredMixin, View):
"""
Display the sent health sheet.
"""
def get(self, request, *args, **kwargs):
filename = kwargs["filename"]
path = f"media/authorization/health/{filename}"
@ -600,6 +670,7 @@ class VaccineSheetView(LoginRequiredMixin, View):
"""
Display the sent health sheet.
"""
def get(self, request, *args, **kwargs):
filename = kwargs["filename"]
path = f"media/authorization/vaccine/{filename}"
@ -623,6 +694,7 @@ class ParentalAuthorizationView(LoginRequiredMixin, View):
"""
Display the sent parental authorization.
"""
def get(self, request, *args, **kwargs):
filename = kwargs["filename"]
path = f"media/authorization/parental/{filename}"
@ -646,6 +718,7 @@ class ReceiptView(LoginRequiredMixin, View):
"""
Display the sent payment receipt or scholarship notification.
"""
def get(self, request, *args, **kwargs):
filename = kwargs["filename"]
path = f"media/authorization/receipt/{filename}"
@ -668,6 +741,7 @@ class SolutionView(LoginRequiredMixin, View):
"""
Display the sent solution.
"""
def get(self, request, *args, **kwargs):
filename = kwargs["filename"]
path = f"media/solutions/{filename}"
@ -686,7 +760,7 @@ class SolutionView(LoginRequiredMixin, View):
if not (user.registration.is_admin
or user.registration.is_volunteer and user.registration
in (solution.participation.tournament
if not solution.final_solution else Tournament.final_tournament()).organizers.all()
if not solution.final_solution else Tournament.final_tournament()).organizers.all()
or user.registration.is_volunteer
and Passage.objects.filter(Q(pool__juries=user.registration)
| Q(pool__tournament__in=user.registration.organized_tournaments.all()),
@ -711,6 +785,7 @@ class SynthesisView(LoginRequiredMixin, View):
"""
Display the sent synthesis.
"""
def get(self, request, *args, **kwargs):
filename = kwargs["filename"]
path = f"media/syntheses/{filename}"