From 8d08b18d08cebc758fc86b0814e6048cc7b07730 Mon Sep 17 00:00:00 2001 From: Emmy D'Anello Date: Tue, 20 Feb 2024 22:54:12 +0100 Subject: [PATCH] Configure Hello Asso return endpoint Signed-off-by: Emmy D'Anello --- locale/fr/LC_MESSAGES/django.po | 267 +++++++++++++++++++------------- registration/models.py | 27 +++- registration/urls.py | 4 +- registration/views.py | 77 ++++++++- tfjm/helloasso.py | 4 +- 5 files changed, 259 insertions(+), 120 deletions(-) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index df731b2..39ac97b 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: TFJM\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-18 22:25+0100\n" +"POT-Creation-Date: 2024-02-20 22:48+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Emmy D'Anello \n" "Language-Team: LANGUAGE \n" @@ -326,7 +326,7 @@ msgstr "Continuer le tirage" #: draw/templates/draw/tournament_content.html:216 participation/admin.py:100 #: participation/models.py:249 participation/models.py:434 -#: registration/models.py:146 +#: registration/models.py:156 msgid "team" msgstr "équipe" @@ -377,7 +377,7 @@ msgstr "Vous n'êtes pas dans une équipe." msgid "Logs" msgstr "Logs" -#: logs/models.py:22 registration/models.py:31 +#: logs/models.py:22 registration/models.py:33 msgid "user" msgstr "utilisateur" @@ -711,7 +711,7 @@ msgstr "" "L'équipe {trigram} n'a pas encore été validée par les organisateurices. " "Merci de patienter." -#: participation/models.py:193 registration/models.py:482 +#: participation/models.py:193 registration/models.py:492 msgid "Pending validation" msgstr "Validation en attente" @@ -1791,7 +1791,7 @@ msgstr "rôle" msgid "participant" msgstr "participant⋅e" -#: registration/forms.py:25 registration/models.py:416 +#: registration/forms.py:25 registration/models.py:426 msgid "coach" msgstr "encadrant⋅e" @@ -1803,20 +1803,20 @@ msgstr "En attente" msgid "You must upload your receipt." msgstr "Vous devez envoyer votre justificatif." -#: registration/models.py:36 +#: registration/models.py:38 msgid "Grant Animath to contact me in the future about other actions" msgstr "" "Autoriser Animath à me recontacter à l'avenir à propos d'autres actions" -#: registration/models.py:41 +#: registration/models.py:43 msgid "email confirmed" msgstr "email confirmé" -#: registration/models.py:49 +#: registration/models.py:51 msgid "Activate your TFJM² account" msgstr "Activez votre compte du TFJM²" -#: registration/models.py:98 +#: registration/models.py:108 #, python-brace-format msgid "" "Your email address is not validated. Please click on the link you received " @@ -1827,52 +1827,52 @@ msgstr "" "avez reçu par mail. Vous pouvez renvoyer un mail en cliquant sur ce lien." -#: registration/models.py:118 +#: registration/models.py:128 msgid "registration" msgstr "inscription" -#: registration/models.py:119 registration/models.py:503 +#: registration/models.py:129 registration/models.py:513 msgid "registrations" msgstr "inscriptions" -#: registration/models.py:151 +#: registration/models.py:161 msgid "gender" msgstr "genre" -#: registration/models.py:153 +#: registration/models.py:163 msgid "Female" msgstr "Femme" -#: registration/models.py:154 +#: registration/models.py:164 msgid "Male" msgstr "Homme" -#: registration/models.py:155 +#: registration/models.py:165 #: registration/templates/registration/payment_form.html:73 msgid "Other" msgstr "Autre" -#: registration/models.py:162 +#: registration/models.py:172 msgid "address" msgstr "adresse" -#: registration/models.py:166 +#: registration/models.py:176 msgid "zip code" msgstr "code postal" -#: registration/models.py:172 +#: registration/models.py:182 msgid "city" msgstr "ville" -#: registration/models.py:176 +#: registration/models.py:186 msgid "phone number" msgstr "numéro de téléphone" -#: registration/models.py:181 +#: registration/models.py:191 msgid "health issues" msgstr "problèmes de santé" -#: registration/models.py:183 +#: registration/models.py:193 msgid "" "You can indicate here your allergies or anything that is important to know " "for organizers." @@ -1880,11 +1880,11 @@ msgstr "" "Vous pouvez indiquer ici vos allergies ou n'importe quoi qui peut être bon à " "savoir pour les organisateur⋅rices." -#: registration/models.py:187 +#: registration/models.py:197 msgid "housing constraints" msgstr "contraintes de logement" -#: registration/models.py:189 +#: registration/models.py:199 msgid "" "You can fill in something here if you have any housing constraints, e.g. " "medical problems, scheduling issues, gender issues, or anything else you " @@ -1897,11 +1897,11 @@ msgstr "" "organisateur⋅rices. Laissez vide si vous n'avez rien de spécifique à " "déclarer." -#: registration/models.py:196 +#: registration/models.py:206 msgid "photo authorization" msgstr "autorisation de droit à l'image" -#: registration/models.py:225 +#: registration/models.py:235 #, python-brace-format msgid "" "You are not in a team. You can create one or ou rejoindre une équipe existante pour " "participer." -#: registration/models.py:231 +#: registration/models.py:241 msgid "No team" msgstr "Pas d'équipe" -#: registration/models.py:239 +#: registration/models.py:249 #, python-brace-format msgid "" "You have not uploaded your photo authorization. You can do it by clicking on " @@ -1924,71 +1924,71 @@ msgstr "" "Vous n'avez pas envoyé votre autorisation de droit à l'image. Vous pouvez le " "faire en cliquant sur ce lien." -#: registration/models.py:244 +#: registration/models.py:254 msgid "Photo authorization" msgstr "Autorisation de droit à l'image" -#: registration/models.py:255 +#: registration/models.py:265 msgid "participant registration" msgstr "inscription de participant⋅e" -#: registration/models.py:256 +#: registration/models.py:266 msgid "participant registrations" msgstr "inscriptions de participant⋅es" -#: registration/models.py:265 +#: registration/models.py:275 msgid "birth date" msgstr "date de naissance" -#: registration/models.py:271 +#: registration/models.py:281 msgid "12th grade" msgstr "Terminale" -#: registration/models.py:272 +#: registration/models.py:282 msgid "11th grade" msgstr "Première" -#: registration/models.py:273 +#: registration/models.py:283 msgid "10th grade or lower" msgstr "Seconde ou inférieur" -#: registration/models.py:275 +#: registration/models.py:285 msgid "student class" msgstr "classe" -#: registration/models.py:280 +#: registration/models.py:290 msgid "school" msgstr "école" -#: registration/models.py:285 +#: registration/models.py:295 msgid "responsible name" msgstr "nom d'un⋅e responsable légal⋅e" -#: registration/models.py:290 +#: registration/models.py:300 msgid "responsible phone number" msgstr "numéro de téléphone d'un⋅e responsable légal⋅e" -#: registration/models.py:295 +#: registration/models.py:305 msgid "responsible email address" msgstr "adresse e-mail d'un⋅e responsable légal⋅e" -#: registration/models.py:300 +#: registration/models.py:310 msgid "parental authorization" msgstr "autorisation parentale" -#: registration/models.py:307 +#: registration/models.py:317 msgid "health sheet" msgstr "fiche sanitaire" -#: registration/models.py:314 +#: registration/models.py:324 msgid "vaccine sheet" msgstr "carnet de vaccination" -#: registration/models.py:322 +#: registration/models.py:332 msgid "student" msgstr "élève" -#: registration/models.py:333 +#: registration/models.py:343 #, python-brace-format msgid "" "You have not uploaded your parental authorization. You can do it by clicking " @@ -1997,11 +1997,11 @@ msgstr "" "Vous n'avez pas envoyé votre autorisation parentale. Vous pouvez le faire en " "cliquant sur ce lien." -#: registration/models.py:338 +#: registration/models.py:348 msgid "Parental authorization" msgstr "Autorisation parentale" -#: registration/models.py:344 +#: registration/models.py:354 #, python-brace-format msgid "" "You have not uploaded your health sheet. You can do it by clicking on ce lien." -#: registration/models.py:349 +#: registration/models.py:359 msgid "Health sheet" msgstr "Fiche sanitaire" -#: registration/models.py:355 +#: registration/models.py:365 #, python-brace-format msgid "" "You have not uploaded your vaccine sheet. You can do it by clicking on ce lien." -#: registration/models.py:360 +#: registration/models.py:370 msgid "Vaccine sheet" msgstr "Carnet de vaccination" -#: registration/models.py:369 +#: registration/models.py:379 #, python-brace-format msgid "" "You have to pay {amount} € for your registration, or send a scholarship " @@ -2038,27 +2038,27 @@ msgstr "" "notification de bourse ou un justificatif de paiement. Vous pouvez le faire " "sur la page de paiement." -#: registration/models.py:375 registration/models.py:384 +#: registration/models.py:385 registration/models.py:394 msgid "Payment" msgstr "Paiement" -#: registration/models.py:381 +#: registration/models.py:391 msgid "Your payment is under approval." msgstr "Votre paiement est en cours de validation." -#: registration/models.py:393 +#: registration/models.py:403 msgid "student registration" msgstr "inscription d'élève" -#: registration/models.py:394 +#: registration/models.py:404 msgid "student registrations" msgstr "inscriptions d'élève" -#: registration/models.py:405 +#: registration/models.py:415 msgid "most recent degree in mathematics, computer science or physics" msgstr "Dernier diplôme obtenu en mathématiques, informatique ou physique" -#: registration/models.py:406 +#: registration/models.py:416 msgid "" "Your most recent degree in maths, computer science or physics, or your last " "entrance exam (CAPES, Agrégation,…)" @@ -2066,23 +2066,23 @@ msgstr "" "Votre dernier diplôme en mathématiques, informatique ou physique, ou votre " "dernier concours obtenu (CAPES, Agrégation, …)" -#: registration/models.py:411 registration/models.py:433 +#: registration/models.py:421 registration/models.py:443 msgid "professional activity" msgstr "activité professionnelle" -#: registration/models.py:424 +#: registration/models.py:434 msgid "coach registration" msgstr "inscription d'encadrant⋅e" -#: registration/models.py:425 +#: registration/models.py:435 msgid "coach registrations" msgstr "inscriptions d'encadrant⋅es" -#: registration/models.py:437 +#: registration/models.py:447 msgid "administrator" msgstr "administrateur⋅rice" -#: registration/models.py:438 +#: registration/models.py:448 msgid "" "An administrator has all rights. Please don't give this right to all juries " "and volunteers." @@ -2090,15 +2090,15 @@ msgstr "" "Un⋅e administrateur⋅rice a tous les droits. Merci de ne pas donner ce droit " "à toustes les juré⋅es et bénévoles." -#: registration/models.py:448 +#: registration/models.py:458 msgid "admin" msgstr "admin" -#: registration/models.py:448 +#: registration/models.py:458 msgid "volunteer" msgstr "bénévole" -#: registration/models.py:461 +#: registration/models.py:471 msgid "" "Registrations for tournament {tournament} are closing on {date:%Y-%m-%d %H:" "%M}. There are for now {validated_teams} validated teams (+ {pending_teams} " @@ -2108,11 +2108,11 @@ msgstr "" "%M}. Il y a pour l'instant {validated_teams} équipes validées (+ " "{pending_teams} en attente) sur {max_teams} attendues." -#: registration/models.py:469 +#: registration/models.py:479 msgid "Registrations" msgstr "Inscriptions" -#: registration/models.py:476 +#: registration/models.py:486 #, python-brace-format msgid "" "The team {trigram} requested to be validated for the tournament of " @@ -2123,19 +2123,19 @@ msgstr "" "Vous pouvez vérifier le statut de l'équipe sur la page de " "l'équipe." -#: registration/models.py:491 +#: registration/models.py:501 msgid "volunteer registration" msgstr "inscription de bénévole" -#: registration/models.py:492 +#: registration/models.py:502 msgid "volunteer registrations" msgstr "inscriptions de bénévoles" -#: registration/models.py:507 +#: registration/models.py:517 msgid "grouped" msgstr "groupé" -#: registration/models.py:509 +#: registration/models.py:519 msgid "" "If set to true, then one payment is made for the full team, for example if " "the school pays for all." @@ -2143,84 +2143,84 @@ msgstr "" "Si vrai, alors un seul paiement est fait pour toute l'équipe, par exemple si " "le lycée paie pour tout le monde." -#: registration/models.py:514 +#: registration/models.py:524 msgid "total amount" msgstr "montant total" -#: registration/models.py:515 +#: registration/models.py:525 msgid "Corresponds to the total required amount to pay, in euros." msgstr "Correspond au montant total à payer, en euros." -#: registration/models.py:520 +#: registration/models.py:530 msgid "for final tournament" msgstr "pour la finale" -#: registration/models.py:525 +#: registration/models.py:535 msgid "type" msgstr "type" -#: registration/models.py:528 +#: registration/models.py:538 msgid "No payment" msgstr "Pas de paiement" -#: registration/models.py:529 +#: registration/models.py:539 #: registration/templates/registration/payment_form.html:56 msgid "Credit card" msgstr "Carte bancaire" -#: registration/models.py:530 +#: registration/models.py:540 msgid "Scholarship" msgstr "Notification de bourse" -#: registration/models.py:531 +#: registration/models.py:541 #: registration/templates/registration/payment_form.html:61 msgid "Bank transfer" msgstr "Virement bancaire" -#: registration/models.py:532 +#: registration/models.py:542 msgid "Other (please indicate)" msgstr "Autre (veuillez spécifier)" -#: registration/models.py:533 +#: registration/models.py:543 msgid "The tournament is free" msgstr "Le tournoi est gratuit" -#: registration/models.py:540 +#: registration/models.py:550 msgid "Hello Asso checkout intent ID" msgstr "ID de l'intention de paiement Hello Asso" -#: registration/models.py:547 +#: registration/models.py:557 msgid "receipt" msgstr "justificatif" -#: registration/models.py:548 +#: registration/models.py:558 msgid "only if you have a scholarship or if you chose a bank transfer." msgstr "" "Nécessaire seulement si vous déclarez être boursièr⋅e ou si vous payez par " "virement bancaire." -#: registration/models.py:555 +#: registration/models.py:565 msgid "additional information" msgstr "informations additionnelles" -#: registration/models.py:556 +#: registration/models.py:566 msgid "To help us to find your payment." msgstr "Pour nous aider à retrouver votre paiement, si nécessaire." -#: registration/models.py:562 +#: registration/models.py:572 msgid "payment valid" msgstr "paiement valide" -#: registration/models.py:571 +#: registration/models.py:630 #, python-brace-format msgid "Payment of {registrations}" msgstr "Paiements de {registrations}" -#: registration/models.py:574 +#: registration/models.py:633 msgid "payment" msgstr "paiement" -#: registration/models.py:575 +#: registration/models.py:634 msgid "payments" msgstr "paiements" @@ -2228,7 +2228,7 @@ msgstr "paiements" #: registration/templates/registration/add_organizer.html:12 #: registration/templates/registration/add_organizer.html:21 #: registration/templates/registration/user_list.html:9 -#: registration/views.py:88 +#: registration/views.py:90 msgid "Add organizer" msgstr "Ajouter un⋅e organisateur⋅rice" @@ -2388,7 +2388,7 @@ msgstr "Réinitialiser mon mot de passe" #: registration/templates/registration/payment_form.html:9 #, python-format msgid "You must pay %(amount)s € for your registration." -msgstr "Vous devez payez %(amount)s € pour votre inscription." +msgstr "Vous devez payer %(amount)s € pour votre inscription." #: registration/templates/registration/payment_form.html:13 msgid "This price includes the registrations of all members of your team." @@ -2435,7 +2435,7 @@ msgstr "J'ai une bourse" #: registration/templates/registration/signup.html:5 #: registration/templates/registration/signup.html:12 -#: registration/templates/registration/signup.html:19 registration/views.py:44 +#: registration/templates/registration/signup.html:19 registration/views.py:46 msgid "Sign up" msgstr "Inscription" @@ -2581,7 +2581,7 @@ msgid "valid:" msgstr "valide :" #: registration/templates/registration/user_detail.html:163 -#: registration/views.py:458 +#: registration/views.py:461 msgid "Update payment" msgstr "Modifier le paiement" @@ -2598,90 +2598,135 @@ msgid "Impersonate" msgstr "Impersonifier" #: registration/templates/registration/user_detail.html:195 -#: registration/views.py:313 +#: registration/views.py:316 msgid "Upload photo authorization" msgstr "Téléverser l'autorisation de droit à l'image" #: registration/templates/registration/user_detail.html:200 -#: registration/views.py:334 +#: registration/views.py:337 msgid "Upload health sheet" msgstr "Téléverser la fiche sanitaire" #: registration/templates/registration/user_detail.html:205 -#: registration/views.py:355 +#: registration/views.py:358 msgid "Upload vaccine sheet" msgstr "Téléverser le carnet de vaccination" #: registration/templates/registration/user_detail.html:210 #: registration/templates/registration/user_detail.html:215 -#: registration/views.py:376 +#: registration/views.py:379 msgid "Upload parental authorization" msgstr "Téléverser l'autorisation parentale" -#: registration/views.py:120 +#: registration/views.py:122 msgid "New TFJM² organizer account" msgstr "Nouveau compte organisateur⋅rice pour le TFJM²" -#: registration/views.py:146 +#: registration/views.py:148 msgid "Email validation" msgstr "Validation de l'adresse mail" -#: registration/views.py:148 +#: registration/views.py:150 msgid "Validate email" msgstr "Valider l'adresse mail" -#: registration/views.py:187 +#: registration/views.py:189 msgid "Email validation unsuccessful" msgstr "Échec de la validation de l'adresse mail" -#: registration/views.py:198 +#: registration/views.py:200 msgid "Email validation email sent" msgstr "Mail de confirmation de l'adresse mail envoyé" -#: registration/views.py:206 +#: registration/views.py:208 msgid "Resend email validation link" msgstr "Renvoyé le lien de validation de l'adresse mail" -#: registration/views.py:248 +#: registration/views.py:251 #, python-brace-format msgid "Detail of user {user}" msgstr "Détails de l'utilisateur⋅rice {user}" -#: registration/views.py:273 +#: registration/views.py:276 #, python-brace-format msgid "Update user {user}" msgstr "Mise à jour de l'utilisateur⋅rice {user}" #: registration/views.py:503 +msgid "This payment is already valid or pending validation." +msgstr "Le paiement est déjà validé ou en attente de validation." + +#: registration/views.py:563 +msgid "The payment is not found or is already validated." +msgstr "Le paiement n'est pas trouvé ou déjà validé." + +#: registration/views.py:582 +#, python-brace-format +msgid "An error occurred during the payment: {error}" +msgstr "Une erreur est survenue lors du paiement : {error}" + +#: registration/views.py:588 +msgid "The payment has been refused." +msgstr "Le paiement a été refusé." + +#: registration/views.py:591 +#, python-brace-format +msgid "The return code is unknown: {code}" +msgstr "Le code de retour est inconnu : {code}" + +#: registration/views.py:594 +#, python-brace-format +msgid "The return type is unknown: {type}" +msgstr "Le type de retour est inconnu : {type}" + +#: registration/views.py:601 +msgid "" +"The payment has been successfully validated! Your registration is now " +"complete." +msgstr "" +"Le paiement a été validé avec succès ! Votre inscription est désormais " +"complète." + +#: registration/views.py:606 +msgid "" +"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." +msgstr "" +"Votre paiement est effectué ! La validation de votre paiement peut prendre " +"quelques minutes, et sera faite automatiquement. Si ce n'est pas le cas, " +"merci de nous contacter." + +#: registration/views.py:641 #, python-brace-format msgid "Photo authorization of {student}.{ext}" msgstr "Autorisation de droit à l'image de {student}.{ext}" -#: registration/views.py:526 +#: registration/views.py:665 #, python-brace-format msgid "Health sheet of {student}.{ext}" msgstr "Fiche sanitaire de {student}.{ext}" -#: registration/views.py:549 +#: registration/views.py:689 #, python-brace-format msgid "Vaccine sheet of {student}.{ext}" msgstr "Carnet de vaccination de {student}.{ext}" -#: registration/views.py:572 +#: registration/views.py:713 #, python-brace-format msgid "Parental authorization of {student}.{ext}" msgstr "Autorisation parentale de {student}.{ext}" -#: registration/views.py:594 +#: registration/views.py:736 #, python-brace-format msgid "Payment receipt of {user}.{ext}" msgstr "Justificatif de paiement de {user}.{ext}" -#: tfjm/settings.py:164 +#: tfjm/settings.py:167 msgid "English" msgstr "Anglais" -#: tfjm/settings.py:165 +#: tfjm/settings.py:168 msgid "French" msgstr "Français" diff --git a/registration/models.py b/registration/models.py index cc0ef80..b13870a 100644 --- a/registration/models.py +++ b/registration/models.py @@ -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=[ diff --git a/registration/urls.py b/registration/urls.py index 463d2c5..5de4de3 100644 --- a/registration/urls.py +++ b/registration/urls.py @@ -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//toggle-group-mode/", PaymentUpdateGroupView.as_view(), name="update_payment_group_mode"), path("update-payment//hello-asso/", PaymenRedirectHelloAssoView.as_view(), name="payment_hello_asso"), + path("update-payment//hello-asso/return/", PaymentHelloAssoReturnView.as_view(), + name="payment_hello_asso_return"), path("user//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"), diff --git a/registration/views.py b/registration/views.py index 304de01..57eefd8 100644 --- a/registration/views.py +++ b/registration/views.py @@ -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}" diff --git a/tfjm/helloasso.py b/tfjm/helloasso.py index bbd0b66..48968e4 100644 --- a/tfjm/helloasso.py +++ b/tfjm/helloasso.py @@ -57,7 +57,7 @@ def get_hello_asso_access_token(): return _access_token -def get_checkout_intent(checkout_id): +def get_checkout_intent(checkout_id, none_if_link_disabled=False): base_url = _get_hello_asso_api_base_url() token = get_hello_asso_access_token() @@ -72,7 +72,7 @@ def get_checkout_intent(checkout_id): response.raise_for_status() checkout_intent = response.json() - if requests.head(checkout_intent["redirectUrl"]).status_code == 404: + if none_if_link_disabled and requests.head(checkout_intent["redirectUrl"]).status_code == 404: return None return checkout_intent