From 4d157b2bd70d0a50ab8e9d9a4d5d7d12c4994bce Mon Sep 17 00:00:00 2001
From: Emmy D'Anello
Les participant⋅es " "qui n'ont pas encore payé sont : {participants}.
" -#: participation/models.py:477 +#: participation/models.py:478 msgid "Missing payments" msgstr "Paiements manquants" -#: participation/models.py:484 +#: participation/models.py:485 msgid "" "The solutions for the tournament of {tournament} are due on the {date:%Y-" "%m-%d %H:%M}.
You have currently sent {nb_solutions} " @@ -837,36 +838,36 @@ msgstr "" "pouvez envoyer vos solutions sur votre page de " "participation.
" -#: participation/models.py:493 +#: participation/models.py:494 msgid "Solutions due" msgstr "Rendu des solutions" -#: participation/models.py:503 participation/models.py:536 +#: participation/models.py:504 participation/models.py:537 msgid "participations" msgstr "participations" -#: participation/models.py:518 participation/models.py:519 +#: participation/models.py:519 participation/models.py:520 #, python-brace-format msgid "Round {round}" msgstr "Tour {round}" -#: participation/models.py:542 +#: participation/models.py:543 msgid "juries" msgstr "jurys" -#: participation/models.py:549 +#: participation/models.py:550 msgid "BigBlueButton URL" msgstr "Lien BigBlueButton" -#: participation/models.py:550 +#: participation/models.py:551 msgid "The link of the BBB visio for this pool." msgstr "Le lien du salon BBB pour cette poule." -#: participation/models.py:555 +#: participation/models.py:556 msgid "results available" msgstr "résultats disponibles" -#: participation/models.py:556 +#: participation/models.py:557 msgid "" "Check this case when results become accessible to teams. They stay " "accessible to you. Only averages are given." @@ -875,28 +876,28 @@ msgstr "" "Ils restent toujours accessibles pour vous. Seules les moyennes sont " "communiquées." -#: participation/models.py:576 +#: participation/models.py:577 #, python-brace-format msgid "Pool of day {round} for tournament {tournament} with teams {teams}" msgstr "Poule du jour {round} du tournoi {tournament} avec les équipes {teams}" -#: participation/models.py:596 +#: participation/models.py:597 msgid "position" msgstr "position" -#: participation/models.py:603 +#: participation/models.py:604 msgid "defended solution" msgstr "solution défendue" -#: participation/models.py:636 +#: participation/models.py:637 msgid "observer" msgstr "observateur⋅rice" -#: participation/models.py:641 +#: participation/models.py:642 msgid "penalties" msgstr "pénalités" -#: participation/models.py:643 +#: participation/models.py:644 msgid "" "Number of penalties for the defender. The defender will loose a 0.5 " "coefficient per penalty." @@ -904,124 +905,124 @@ msgstr "" "Nombre de pénalités pour l'équipe défenseuse. Elle perd un coefficient 0.5 " "sur sa présentation orale par pénalité." -#: participation/models.py:719 participation/models.py:722 -#: participation/models.py:725 participation/models.py:728 +#: participation/models.py:720 participation/models.py:723 +#: participation/models.py:726 participation/models.py:729 #, python-brace-format msgid "Team {trigram} is not registered in the pool." msgstr "L'équipe {trigram} n'est pas inscrite dans la poule." -#: participation/models.py:733 +#: participation/models.py:734 #, python-brace-format msgid "Passage of {defender} for problem {problem}" msgstr "Passage de {defender} pour le problème {problem}" -#: participation/models.py:737 participation/models.py:746 -#: participation/models.py:827 participation/models.py:869 +#: participation/models.py:738 participation/models.py:747 +#: participation/models.py:828 participation/models.py:870 msgid "passage" msgstr "passage" -#: participation/models.py:738 +#: participation/models.py:739 msgid "passages" msgstr "passages" -#: participation/models.py:757 +#: participation/models.py:758 msgid "difference" msgstr "différence" -#: participation/models.py:758 +#: participation/models.py:759 msgid "Score to add/remove on the final score" msgstr "Score à ajouter/retrancher au score final" -#: participation/models.py:765 +#: participation/models.py:766 msgid "tweak" msgstr "harmonisation" -#: participation/models.py:766 +#: participation/models.py:767 msgid "tweaks" msgstr "harmonisations" -#: participation/models.py:794 +#: participation/models.py:795 msgid "solution for the final tournament" msgstr "solution pour la finale" -#: participation/models.py:799 participation/models.py:838 +#: participation/models.py:800 participation/models.py:839 msgid "file" msgstr "fichier" -#: participation/models.py:805 +#: participation/models.py:806 #, python-brace-format msgid "Solution of team {team} for problem {problem}" msgstr "Solution de l'équipe {team} pour le problème {problem}" -#: participation/models.py:807 +#: participation/models.py:808 msgid "for final" msgstr "pour la finale" -#: participation/models.py:810 +#: participation/models.py:811 msgid "solution" msgstr "solution" -#: participation/models.py:811 +#: participation/models.py:812 msgid "solutions" msgstr "solutions" -#: participation/models.py:844 +#: participation/models.py:845 #, python-brace-format msgid "Synthesis of {team} as {type} for problem {problem} of {defender}" msgstr "" "Note de synthèse de l'équipe {team} en tant que {type} pour le problème " "{problem} de {defender}" -#: participation/models.py:852 +#: participation/models.py:853 msgid "synthesis" msgstr "note de synthèse" -#: participation/models.py:853 +#: participation/models.py:854 msgid "syntheses" msgstr "notes de synthèse" -#: participation/models.py:862 +#: participation/models.py:863 msgid "jury" msgstr "jury" -#: participation/models.py:874 +#: participation/models.py:875 msgid "defender writing note" msgstr "note d'écrit de la défense" -#: participation/models.py:880 +#: participation/models.py:881 msgid "defender oral note" msgstr "note d'oral de la défense" -#: participation/models.py:886 +#: participation/models.py:887 msgid "opponent writing note" msgstr "note d'écrit de l'opposition" -#: participation/models.py:892 +#: participation/models.py:893 msgid "opponent oral note" msgstr "note d'oral de l'opposition" -#: participation/models.py:898 +#: participation/models.py:899 msgid "reporter writing note" msgstr "note d'écrit du rapportage" -#: participation/models.py:904 +#: participation/models.py:905 msgid "reporter oral note" msgstr "note d'oral du rapportage" -#: participation/models.py:910 +#: participation/models.py:911 msgid "observer note" msgstr "note de l'observation" -#: participation/models.py:939 +#: participation/models.py:940 #, python-brace-format msgid "Notes of {jury} for {passage}" msgstr "Notes de {jury} pour le {passage}" -#: participation/models.py:946 +#: participation/models.py:947 msgid "note" msgstr "note" -#: participation/models.py:947 +#: participation/models.py:948 msgid "notes" msgstr "notes" @@ -1090,7 +1091,6 @@ msgstr "Rejoindre" #: participation/templates/participation/update_team.html:12 #: registration/templates/registration/update_user.html:16 #: registration/templates/registration/user_detail.html:186 -#: registration/templates/registration/user_detail.html:223 msgid "Update" msgstr "Modifier" @@ -1498,7 +1498,7 @@ msgid "Invalidate" msgstr "Invalider" #: participation/templates/participation/team_detail.html:186 -#: participation/views.py:323 +#: participation/views.py:329 msgid "Upload motivation letter" msgstr "Envoyer la lettre de motivation" @@ -1507,7 +1507,7 @@ msgid "Update team" msgstr "Modifier l'équipe" #: participation/templates/participation/team_detail.html:196 -#: participation/views.py:432 +#: participation/views.py:438 msgid "Leave team" msgstr "Quitter l'équipe" @@ -1641,7 +1641,7 @@ msgstr "Vous êtes déjà dans une équipe." msgid "Join team" msgstr "Rejoindre une équipe" -#: participation/views.py:152 participation/views.py:470 +#: participation/views.py:152 participation/views.py:476 msgid "You don't participate, so you don't have any team." msgstr "Vous ne participez pas, vous n'avez donc pas d'équipe." @@ -1677,95 +1677,95 @@ msgstr "Vous n'êtes pas un⋅e organisateur⋅rice du tournoi." msgid "This team has no pending validation." msgstr "L'équipe n'a pas de validation en attente." -#: participation/views.py:266 +#: participation/views.py:272 msgid "You must specify if you validate the registration or not." msgstr "Vous devez spécifier si vous validez l'inscription ou non." -#: participation/views.py:301 +#: participation/views.py:307 #, python-brace-format msgid "Update team {trigram}" msgstr "Mise à jour de l'équipe {trigram}" -#: participation/views.py:362 participation/views.py:418 +#: participation/views.py:368 participation/views.py:424 #, python-brace-format msgid "Motivation letter of {team}.{ext}" msgstr "Lettre de motivation de {team}.{ext}" -#: participation/views.py:393 +#: participation/views.py:399 #, python-brace-format msgid "Photo authorization of {participant}.{ext}" msgstr "Autorisation de droit à l'image de {participant}.{ext}" -#: participation/views.py:399 +#: participation/views.py:405 #, python-brace-format msgid "Parental authorization of {participant}.{ext}" msgstr "Autorisation parentale de {participant}.{ext}" -#: participation/views.py:406 +#: participation/views.py:412 #, python-brace-format msgid "Health sheet of {participant}.{ext}" msgstr "Fiche sanitaire de {participant}.{ext}" -#: participation/views.py:412 +#: participation/views.py:418 #, python-brace-format msgid "Vaccine sheet of {participant}.{ext}" msgstr "Carnet de vaccination de {participant}.{ext}" -#: participation/views.py:422 +#: participation/views.py:428 #, python-brace-format msgid "Photo authorizations of team {trigram}.zip" msgstr "Autorisations de droit à l'image de l'équipe {trigram}.zip" -#: participation/views.py:440 +#: participation/views.py:446 msgid "The team is already validated or the validation is pending." msgstr "La validation de l'équipe est déjà faite ou en cours." -#: participation/views.py:484 +#: participation/views.py:490 msgid "The team is not validated yet." msgstr "L'équipe n'est pas encore validée." -#: participation/views.py:498 +#: participation/views.py:504 #, python-brace-format msgid "Participation of team {trigram}" msgstr "Participation de l'équipe {trigram}" -#: participation/views.py:634 +#: participation/views.py:640 msgid "You can't upload a solution after the deadline." msgstr "Vous ne pouvez pas envoyer de solution après la date limite." -#: participation/views.py:742 +#: participation/views.py:748 #, python-brace-format msgid "Solutions for pool {pool} of tournament {tournament}.zip" msgstr "Solutions pour la poule {pool} du tournoi {tournament}.zip" -#: participation/views.py:743 +#: participation/views.py:749 #, python-brace-format msgid "Syntheses for pool {pool} of tournament {tournament}.zip" msgstr "Notes de synthèses pour la poule {pool} du tournoi {tournament}.zip" -#: participation/views.py:761 +#: participation/views.py:767 #, python-brace-format msgid "Jurys of {pool}" msgstr "Juré⋅es de la {pool}" -#: participation/views.py:788 +#: participation/views.py:794 msgid "New TFJM² jury account" msgstr "Nouveau compte de juré⋅e pour le TFJM²" -#: participation/views.py:801 +#: participation/views.py:807 #, python-brace-format msgid "The jury {name} has been successfully added!" msgstr "{name} a été ajouté⋅e avec succès en tant que juré⋅e !" -#: participation/views.py:838 +#: participation/views.py:844 msgid "The following user is not registered as a jury:" msgstr "L'utilisateur⋅rice suivant n'est pas inscrit⋅e en tant que juré⋅e :" -#: participation/views.py:852 +#: participation/views.py:858 msgid "Notes were successfully uploaded." msgstr "Les notes ont bien été envoyées." -#: participation/views.py:1516 +#: participation/views.py:1522 msgid "You can't upload a synthesis after the deadline." msgstr "Vous ne pouvez pas envoyer de note de synthèse après la date limite." @@ -1799,7 +1799,7 @@ msgstr "encadrant⋅e" msgid "Pending" msgstr "En attente" -#: registration/forms.py:245 +#: registration/forms.py:244 registration/forms.py:277 msgid "You must upload your receipt." msgstr "Vous devez envoyer votre justificatif." @@ -1848,6 +1848,7 @@ msgid "Male" msgstr "Homme" #: registration/models.py:155 +#: registration/templates/registration/payment_form.html:73 msgid "Other" msgstr "Autre" @@ -2162,11 +2163,17 @@ msgstr "type" msgid "No payment" msgstr "Pas de paiement" +#: registration/models.py:529 +#: registration/templates/registration/payment_form.html:56 +msgid "Credit card" +msgstr "Carte bancaire" + #: registration/models.py:530 msgid "Scholarship" msgstr "Notification de bourse" #: registration/models.py:531 +#: registration/templates/registration/payment_form.html:61 msgid "Bank transfer" msgstr "Virement bancaire" @@ -2207,7 +2214,7 @@ msgstr "paiement valide" #: registration/models.py:571 #, python-brace-format msgid "Payment of {registrations}" -msgstr "Paiements de {registration}" +msgstr "Paiements de {registrations}" #: registration/models.py:574 msgid "payment" @@ -2378,6 +2385,54 @@ msgstr "" msgid "Reset my password" 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." + +#: registration/templates/registration/payment_form.html:13 +msgid "This price includes the registrations of all members of your team." +msgstr "Ce prix inclut les inscriptions de tous les membres de votre équipe." + +#: registration/templates/registration/payment_form.html:17 +msgid "" +"This price includes only your own registration. You are exempt from payment " +"if you have a scholarship, but you must then send us a proof of your " +"scholarship." +msgstr "" +"Ce prix inclut seulement votre propre inscription. Vous êtes exempté⋅e de " +"paiement si vous avez une bourse, mais vous devez alors nous envoyer un " +"justificatif de votre bourse." + +#: registration/templates/registration/payment_form.html:27 +msgid "" +"You want finally that each member pays its own registration? Then click on " +"the button:" +msgstr "" +"Vous voulez finalement que chaque membre paie sa propre inscription ? Alors " +"cliquez sur le bouton :" + +#: registration/templates/registration/payment_form.html:32 +msgid "Back to single payments" +msgstr "Retour aux paiements individuels" + +#: registration/templates/registration/payment_form.html:36 +msgid "" +"You want to pay for the registrations of all members of your team, or your " +"school will pay for all registrations? Then click on the button:" +msgstr "" +"Vous voulez payer pour les inscriptions de tous les membres de votre équipe, " +"ou votre école paiera pour toutes les inscriptions ? Alors cliquez sur le " +"bouton :" + +#: registration/templates/registration/payment_form.html:42 +msgid "Group the payments of my team" +msgstr "Regrouper les paiements de mon équipe" + +#: registration/templates/registration/payment_form.html:67 +msgid "I have a scholarship" +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 @@ -2526,7 +2581,7 @@ msgid "valid:" msgstr "valide :" #: registration/templates/registration/user_detail.html:163 -#: registration/templates/registration/user_detail.html:222 +#: registration/views.py:458 msgid "Update payment" msgstr "Modifier le paiement" @@ -2597,30 +2652,30 @@ msgstr "Détails de l'utilisateur⋅rice {user}" msgid "Update user {user}" msgstr "Mise à jour de l'utilisateur⋅rice {user}" -#: registration/views.py:492 +#: registration/views.py:503 #, python-brace-format msgid "Photo authorization of {student}.{ext}" msgstr "Autorisation de droit à l'image de {student}.{ext}" -#: registration/views.py:515 +#: registration/views.py:526 #, python-brace-format msgid "Health sheet of {student}.{ext}" msgstr "Fiche sanitaire de {student}.{ext}" -#: registration/views.py:538 +#: registration/views.py:549 #, python-brace-format msgid "Vaccine sheet of {student}.{ext}" msgstr "Carnet de vaccination de {student}.{ext}" -#: registration/views.py:561 +#: registration/views.py:572 #, python-brace-format msgid "Parental authorization of {student}.{ext}" msgstr "Autorisation parentale de {student}.{ext}" -#: registration/views.py:583 +#: registration/views.py:594 #, python-brace-format -msgid "Scholarship attestation of {user}.{ext}" -msgstr "Notification de bourse de {user}.{ext}" +msgid "Payment receipt of {user}.{ext}" +msgstr "Justificatif de paiement de {user}.{ext}" #: tfjm/settings.py:164 msgid "English" @@ -2783,3 +2838,7 @@ msgstr "Aucun résultat." #: tfjm/templates/sidebar.html:10 tfjm/templates/sidebar.html:21 msgid "Informations" msgstr "Informations" + +#, python-brace-format +#~ msgid "Scholarship attestation of {user}.{ext}" +#~ msgstr "Notification de bourse de {user}.{ext}" diff --git a/registration/forms.py b/registration/forms.py index 3d09225..a25d573 100644 --- a/registration/forms.py +++ b/registration/forms.py @@ -219,7 +219,7 @@ class VolunteerRegistrationForm(forms.ModelForm): fields = ('professional_activity', 'admin', 'give_contact_to_animath', 'email_confirmed',) -class PaymentForm(forms.ModelForm): +class PaymentAdminForm(forms.ModelForm): """ Indicate payment information """ @@ -228,7 +228,6 @@ class PaymentForm(forms.ModelForm): self.fields["valid"].widget.choices[0] = ('unknown', _("Pending")) def clean_receipt(self): - print(self.files) if "receipt" in self.files: file = self.files["receipt"] if file.size > 2e6: @@ -241,7 +240,7 @@ class PaymentForm(forms.ModelForm): cleaned_data = super().clean() if "type" in cleaned_data and cleaned_data['type'] in ["scholarship", "bank_transfer"] \ - and "receipt" not in self.files and not self.instance.scholarship_file: + and "receipt" not in self.files and not self.instance.receipt: self.add_error("receipt", _("You must upload your receipt.")) return cleaned_data @@ -249,3 +248,37 @@ class PaymentForm(forms.ModelForm): class Meta: model = Payment fields = ('type', 'receipt', 'additional_information', 'valid',) + + +class PaymentForm(forms.ModelForm): + """ + Indicate payment information + """ + def __init__(self, payment_type, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['type'].widget = forms.HiddenInput(attrs={'value': payment_type}) + self.fields['receipt'].required = payment_type in ["scholarship", "bank_transfer"] + self.fields['additional_information'].required = payment_type in ["other"] + + def clean_receipt(self): + if "receipt" in self.files: + file = self.files["receipt"] + if file.size > 2e6: + raise ValidationError(_("The uploaded file size must be under 2 Mo.")) + if file.content_type not in ["application/pdf", "image/png", "image/jpeg"]: + raise ValidationError(_("The uploaded file must be a PDF, PNG of JPEG file.")) + return self.cleaned_data["receipt"] + + def clean(self): + cleaned_data = super().clean() + + if "type" in cleaned_data and cleaned_data['type'] in ["scholarship", "bank_transfer"] \ + and "receipt" not in self.files and not self.instance.receipt: + self.add_error("receipt", _("You must upload your receipt.")) + + return cleaned_data + + class Meta: + model = Payment + fields = ('type', 'receipt', 'additional_information',) + diff --git a/registration/migrations/0001_initial.py b/registration/migrations/0001_initial.py index 001c850..a941262 100644 --- a/registration/migrations/0001_initial.py +++ b/registration/migrations/0001_initial.py @@ -113,7 +113,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('type', models.CharField(blank=True, choices=[('', 'No payment'), ('helloasso', 'Hello Asso'), ('scholarship', 'Scholarship'), ('bank_transfer', 'Bank transfer'), ('other', 'Other (please indicate)'), ('free', 'The tournament is free')], default='', max_length=16, verbose_name='type')), - ('scholarship_file', models.FileField(blank=True, default='', help_text='only if you have a scholarship.', upload_to=registration.models.get_scholarship_filename, verbose_name='scholarship file')), + ('scholarship_file', models.FileField(blank=True, default='', help_text='only if you have a scholarship.', upload_to=registration.models.get_receipt_filename, verbose_name='scholarship file')), ('additional_information', models.TextField(blank=True, default='', help_text='To help us to find your payment.', verbose_name='additional information')), ('valid', models.BooleanField(default=False, null=True, verbose_name='valid')), ('registration', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='payment', to='registration.participantregistration', verbose_name='registration')), diff --git a/registration/migrations/0011_remove_payment_registration_and_more.py b/registration/migrations/0011_remove_payment_registration_and_more.py index 6de8358..5dfd939 100644 --- a/registration/migrations/0011_remove_payment_registration_and_more.py +++ b/registration/migrations/0011_remove_payment_registration_and_more.py @@ -60,7 +60,7 @@ class Migration(migrations.Migration): blank=True, default="", help_text="only if you have a scholarship or if you chose a bank transfer.", - upload_to=registration.models.get_scholarship_filename, + upload_to=registration.models.get_receipt_filename, verbose_name="receipt", ), ), diff --git a/registration/models.py b/registration/models.py index 87f95ee..407e5aa 100644 --- a/registration/models.py +++ b/registration/models.py @@ -492,8 +492,8 @@ class VolunteerRegistration(Registration): verbose_name_plural = _("volunteer registrations") -def get_scholarship_filename(instance, filename): - return f"authorization/scholarship/scholarship_{instance.registration.pk}" +def get_receipt_filename(instance, filename): + return f"authorization/receipt/receipt_{instance.id}" class Payment(models.Model): @@ -526,7 +526,7 @@ class Payment(models.Model): max_length=16, choices=[ ('', _("No payment")), - ('helloasso', "Hello Asso"), + ('helloasso', _("Credit card")), ('scholarship', _("Scholarship")), ('bank_transfer', _("Bank transfer")), ('other', _("Other (please indicate)")), @@ -546,7 +546,7 @@ class Payment(models.Model): receipt = models.FileField( verbose_name=_("receipt"), help_text=_("only if you have a scholarship or if you chose a bank transfer."), - upload_to=get_scholarship_filename, + upload_to=get_receipt_filename, blank=True, default="", ) diff --git a/registration/templates/registration/payment_form.html b/registration/templates/registration/payment_form.html index 59366d8..0cab8f3 100644 --- a/registration/templates/registration/payment_form.html +++ b/registration/templates/registration/payment_form.html @@ -3,8 +3,140 @@ {% load crispy_forms_filters i18n %} {% block content %} -+ {% blocktrans trimmed with amount=payment.amount %} + You must pay {{ amount }} € for your registration. + {% endblocktrans %} + {% if payment.grouped %} + {% blocktrans trimmed %} + This price includes the registrations of all members of your team. + {% endblocktrans %} + {% else %} + {% blocktrans trimmed %} + This price includes only your own registration. + You are exempt from payment if you have a scholarship, + but you must then send us a proof of your scholarship. + {% endblocktrans %} + {% endif %} +
+ ++ {% if payment.grouped %} + {% blocktrans trimmed %} + You want finally that each member pays its own registration? Then click on the button: + {% endblocktrans %} +