1
0
mirror of https://gitlab.com/animath/si/plateforme.git synced 2025-05-19 23:31:21 +00:00

Compare commits

..

No commits in common. "01ba0a1df9d4f14a4ba3648025e2c07ca94cb9cd" and "1d01376703b5cd904b8ca88ce6599b38a691bf6a" have entirely different histories.

8 changed files with 184 additions and 703 deletions

File diff suppressed because it is too large Load Diff

View File

@ -4,11 +4,10 @@
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.sites.models import Site from django.contrib.sites.models import Site
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.management import call_command from django.core.management import call_command
from django.test import TestCase from django.test import TestCase
from django.urls import reverse from django.urls import reverse
from registration.models import CoachRegistration, Payment, StudentRegistration from registration.models import CoachRegistration, StudentRegistration
from .models import Participation, Team, Tournament from .models import Participation, Team, Tournament
@ -516,365 +515,6 @@ class TestStudentParticipation(TestCase):
self.assertEqual(resp.status_code, 403) self.assertEqual(resp.status_code, 403)
class TestPayment(TestCase):
"""
Tests that are relative to a payment
"""
def setUp(self):
self.superuser = User.objects.create_superuser(
username="admin",
email="admin@example.com",
password="admin",
)
self.tournament = Tournament.objects.create(
name="France",
place="Here",
price=21,
)
self.team = Team.objects.create(
name="Super team",
trigram="AAA",
access_code="azerty",
)
self.user = User.objects.create(
first_name="Toto",
last_name="Toto",
email="toto@example.com",
password="toto",
)
StudentRegistration.objects.create(
user=self.user,
team=self.team,
student_class=12,
address="1 Rue de Rivoli",
zip_code=75001,
city="Paris",
school="Earth",
give_contact_to_animath=True,
email_confirmed=True,
)
self.second_user = User.objects.create(
first_name="Lalala",
last_name="Lalala",
email="lalala@example.com",
password="lalala",
)
StudentRegistration.objects.create(
user=self.second_user,
team=self.team,
student_class=11,
address="1 Rue de Rivoli",
zip_code=75001,
city="Paris",
school="Moon",
give_contact_to_animath=True,
email_confirmed=True,
)
self.coach = User.objects.create(
first_name="Coach",
last_name="Coach",
email="coach@example.com",
password="coach",
)
CoachRegistration.objects.create(
user=self.coach,
team=self.team,
address="1 Rue de Rivoli",
zip_code=75001,
city="Paris",
)
self.team.participation.tournament = self.tournament
self.team.participation.valid = True
self.team.participation.save()
self.client.force_login(self.user)
def test_check_payments_exists(self):
"""
Check that users in a validated team have an invalid payment, but not for the final,
and that coaches are not concerned.
"""
self.assertTrue(Payment.objects.filter(final=False, valid=False, type='',
registrations=self.user.registration).exists())
self.assertTrue(Payment.objects.filter(final=False, valid=False, type='',
registrations=self.second_user.registration).exists())
self.assertFalse(Payment.objects.filter(final=False, valid=False, type='',
registrations=self.coach.registration).exists())
self.assertFalse(Payment.objects.filter(final=True, valid=False, type='',
registrations=self.user.registration).exists())
self.assertFalse(Payment.objects.filter(final=True, valid=False, type='',
registrations=self.second_user.registration).exists())
self.assertFalse(Payment.objects.filter(final=True, valid=False, type='',
registrations=self.coach.registration).exists())
def test_load_payment_page(self):
"""
Ensure that the payment page loads correctly.
"""
response = self.client.get(reverse('participation:team_detail', args=(self.team.pk,)))
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse('registration:user_detail', args=(self.user.pk,)))
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse('participation:tournament_payments', args=(self.tournament.pk,)))
self.assertEqual(response.status_code, 403)
payment = Payment.objects.get(registrations=self.user.registration, final=False)
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEqual(response.status_code, 200)
def test_bank_transfer_payment(self):
"""
Try to send a bank transfer.
"""
payment = Payment.objects.get(registrations=self.user.registration, final=False)
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEqual(response.status_code, 200)
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'type': "bank_transfer",
'additional_information': "This is a bank transfer"})
self.assertEqual(response.status_code, 200)
self.assertFormError(response.context['form'], 'receipt',
["This field is required.", "You must upload your receipt."])
payment.refresh_from_db()
self.assertFalse(payment.valid)
self.assertEqual(payment.type, "")
# README is not a valid PDF file
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'type': "bank_transfer",
'additional_information': "This is a bank transfer",
'receipt': open("README.md", "rb")})
self.assertEqual(response.status_code, 200)
self.assertFormError(response.context['form'], 'receipt',
["The uploaded file must be a PDF, PNG of JPEG file."])
self.assertFalse(payment.valid)
self.assertEqual(payment.type, "")
# Don't send too large files
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'type': "bank_transfer",
'additional_information': "This is a bank transfer",
'receipt': SimpleUploadedFile(
"file.pdf",
content=int(0).to_bytes(2000001, "big"),
content_type="application/pdf"),
})
self.assertEqual(response.status_code, 200)
self.assertFormError(response.context['form'], 'receipt',
["The uploaded file size must be under 2 Mo."])
self.assertFalse(payment.valid)
self.assertEqual(payment.type, "")
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'type': "bank_transfer",
'additional_information': "This is a bank transfer",
'receipt': open("tfjm/static/Fiche_sanitaire.pdf", "rb")})
self.assertRedirects(response, reverse('participation:team_detail', args=(self.team.pk,)), 302, 200)
payment.refresh_from_db()
self.assertIsNone(payment.valid)
self.assertEqual(payment.type, "bank_transfer")
self.assertEqual(payment.additional_information, "This is a bank transfer")
self.assertIsNotNone(payment.receipt)
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEqual(response.status_code, 200)
def test_scholarship(self):
"""
Try to don't pay because of a scholarship.
"""
payment = Payment.objects.get(registrations=self.user.registration, final=False)
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEqual(response.status_code, 200)
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'type': "scholarship",
'additional_information': "I don't have to pay because I have a scholarship"})
self.assertEqual(response.status_code, 200)
self.assertFormError(response.context['form'], 'receipt',
["This field is required.", "You must upload your receipt."])
payment.refresh_from_db()
self.assertFalse(payment.valid)
self.assertEqual(payment.type, "")
self.assertEqual(payment.amount, self.tournament.price)
# README is not a valid PDF file
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'type': "scholarship",
'additional_information': "I don't have to pay because I have a scholarship",
'receipt': open("README.md", "rb")})
self.assertEqual(response.status_code, 200)
self.assertFormError(response.context['form'], 'receipt',
["The uploaded file must be a PDF, PNG of JPEG file."])
self.assertFalse(payment.valid)
self.assertEqual(payment.type, "")
self.assertEqual(payment.amount, self.tournament.price)
# Don't send too large files
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'type': "scholarship",
'additional_information': "I don't have to pay because I have a scholarship",
'receipt': SimpleUploadedFile(
"file.pdf",
content=int(0).to_bytes(2000001, "big"),
content_type="application/pdf"),
})
self.assertEqual(response.status_code, 200)
self.assertFormError(response.context['form'], 'receipt',
["The uploaded file size must be under 2 Mo."])
self.assertFalse(payment.valid)
self.assertEqual(payment.type, "")
self.assertEqual(payment.amount, self.tournament.price)
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'type': "scholarship",
'additional_information': "I don't have to pay because I have a scholarship",
'receipt': open("tfjm/static/Fiche_sanitaire.pdf", "rb")})
self.assertRedirects(response, reverse('participation:team_detail', args=(self.team.pk,)), 302, 200)
payment.refresh_from_db()
self.assertIsNone(payment.valid)
self.assertEqual(payment.type, "scholarship")
self.assertEqual(payment.additional_information, "I don't have to pay because I have a scholarship")
self.assertIsNotNone(payment.receipt)
self.assertEqual(payment.amount, 0)
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEqual(response.status_code, 200)
def test_other(self):
"""
Try to send a different type of payment.
"""
payment = Payment.objects.get(registrations=self.user.registration, final=False)
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEqual(response.status_code, 200)
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'type': "other"})
self.assertEqual(response.status_code, 200)
self.assertFormError(response.context['form'], 'additional_information',
["This field is required."])
payment.refresh_from_db()
self.assertFalse(payment.valid)
self.assertEqual(payment.type, "")
self.assertEqual(payment.amount, self.tournament.price)
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'type': "other",
'additional_information': "Why should I pay"})
self.assertRedirects(response, reverse('participation:team_detail', args=(self.team.pk,)), 302, 200)
payment.refresh_from_db()
self.assertIsNone(payment.valid)
self.assertEqual(payment.type, "other")
self.assertEqual(payment.additional_information, "Why should I pay")
self.assertIsNotNone(payment.receipt)
self.assertEqual(payment.amount, self.tournament.price)
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEqual(response.status_code, 200)
def test_group(self):
payment = Payment.objects.get(registrations=self.user.registration, final=False)
self.assertFalse(payment.grouped)
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse('registration:update_payment_group_mode', args=(payment.pk,)))
self.assertRedirects(response, reverse('registration:update_payment', args=(payment.pk,)), 302, 200)
payment.refresh_from_db()
self.assertTrue(payment.grouped)
self.assertEqual(Payment.objects.count(), 1)
self.assertIn(self.user.registration, payment.registrations.all())
self.assertIn(self.second_user.registration, payment.registrations.all())
self.assertEqual(payment.amount, 2 * self.tournament.price)
def test_ungroup(self):
"""
Test to ungroup payments
"""
payment = Payment.objects.get(registrations=self.user.registration, final=False)
self.client.get(reverse('registration:update_payment_group_mode', args=(payment.pk,)))
payment.refresh_from_db()
self.assertTrue(payment.grouped)
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse('registration:update_payment_group_mode', args=(payment.pk,)))
self.assertRedirects(response, reverse('registration:update_payment', args=(payment.pk,)), 302, 200)
payment.refresh_from_db()
self.assertFalse(payment.grouped)
self.assertEqual(Payment.objects.count(), 2)
self.assertIn(self.user.registration, payment.registrations.all())
self.assertNotIn(self.second_user.registration, payment.registrations.all())
self.assertEqual(payment.amount, self.tournament.price)
def test_group_forbidden(self):
"""
Payment grouping is forbidden if at least one payment is already valid.
"""
payment = Payment.objects.get(registrations=self.user.registration, final=False)
payment.valid = True
payment.save()
payment2 = Payment.objects.get(registrations=self.second_user.registration, final=False)
response = self.client.get(reverse('registration:update_payment_group_mode', args=(payment.pk,)))
self.assertEqual(response.status_code, 403)
response = self.client.get(reverse('registration:update_payment_group_mode', args=(payment2.pk,)))
self.assertEqual(response.status_code, 403)
def test_validate_payment(self):
"""
Try to validate a payment.
"""
payment = Payment.objects.get(registrations=self.user.registration, final=False)
payment.type = "other"
payment.valid = None
payment.save()
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEqual(response.status_code, 200)
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'valid': True})
self.assertEqual(response.status_code, 403)
self.assertFalse(payment.valid)
self.client.force_login(self.superuser)
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'valid': True})
self.assertRedirects(response, reverse('participation:team_detail', args=(self.team.pk,)), 302, 200)
payment.refresh_from_db()
self.assertTrue(payment.valid)
def test_invalidate_payment(self):
"""
Try to invalidate a payment.
"""
payment = Payment.objects.get(registrations=self.user.registration, final=False)
payment.type = "other"
payment.valid = None
payment.save()
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEqual(response.status_code, 200)
self.client.force_login(self.superuser)
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'valid': False})
self.assertRedirects(response, reverse('participation:team_detail', args=(self.team.pk,)), 302, 200)
payment.refresh_from_db()
self.assertFalse(payment.valid)
class TestAdmin(TestCase): class TestAdmin(TestCase):
def setUp(self) -> None: def setUp(self) -> None:
self.user = User.objects.create_superuser( self.user = User.objects.create_superuser(

View File

@ -12,8 +12,8 @@ class RegistrationConfig(AppConfig):
name = 'registration' name = 'registration'
def ready(self): def ready(self):
from registration import signals from registration.signals import create_admin_registration, \
pre_save.connect(signals.set_username, 'auth.User') set_username, send_email_link
pre_save.connect(signals.send_email_link, 'auth.User') pre_save.connect(set_username, "auth.User")
pre_save.connect(signals.update_payment_amount, 'registration.Payment') pre_save.connect(send_email_link, "auth.User")
post_save.connect(signals.create_admin_registration, 'auth.User') post_save.connect(create_admin_registration, "auth.User")

View File

@ -226,9 +226,6 @@ class PaymentAdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields["valid"].widget.choices[0] = ('unknown', _("Pending")) self.fields["valid"].widget.choices[0] = ('unknown', _("Pending"))
payment_type = kwargs.get('data', {}).get('type', "")
self.fields['receipt'].required = payment_type in ["scholarship", "bank_transfer"]
self.fields['additional_information'].required = payment_type in ["other"]
def clean_receipt(self): def clean_receipt(self):
if "receipt" in self.files: if "receipt" in self.files:

View File

@ -387,7 +387,7 @@ class StudentRegistration(ParticipantRegistration):
'priority': 3, 'priority': 3,
'content': content, 'content': content,
}) })
elif payment.valid is None: elif self.payment.valid is None:
text = _("Your payment is under approval.") text = _("Your payment is under approval.")
content = text content = text
informations.append({ informations.append({

View File

@ -41,13 +41,3 @@ def create_admin_registration(instance, **_):
""" """
if instance.is_superuser: if instance.is_superuser:
VolunteerRegistration.objects.get_or_create(user=instance, admin=True) VolunteerRegistration.objects.get_or_create(user=instance, admin=True)
def update_payment_amount(instance, **_):
"""
When a payment got created, ensure that the amount is set.
"""
if instance.type == 'free' or instance.type == 'scholarship':
instance.amount = 0
elif instance.pk:
instance.amount = instance.registrations.count() * instance.tournament.price

View File

@ -201,82 +201,13 @@
</div> </div>
</div> </div>
{% else %} {% else %}
{% if user.registration.is_volunteer %} <form method="post" enctype="multipart/form-data">
<form method="post" enctype="multipart/form-data"> <div id="form-content">
<div id="form-content"> {% csrf_token %}
{% csrf_token %} {{ form|crispy }}
{{ form|crispy }} </div>
</div> <button class="btn btn-primary" type="submit">{% trans "Update" %}</button>
<button class="btn btn-primary" type="submit">{% trans "Update" %}</button> </form>
</form>
{% else %}
{% if payment.type == 'helloasso' %}
{% if payment.valid is True %}
<div class="alert alert-success">
{% with order=payment.get_checkout_intent.order %}
{% trans "Your payment by credit card via Hello Asso is successfully validated." %}
{% trans "The paid amount is" %} {% widthratio order.amount.total 100 1 %} €.
{% if grouped %}
{% trans "It includes the registrations of all members of the team." %}
{% endif %}
{% trans "The payer was " %} {{ order.payer.firstName }} {{ order.payer.lastName }}.
{% trans "The payment was done on" %} {{ order.date }}.
{% endwith %}
</div>
{% elif payment.valid is None %}
<div class="alert alert-warning">
{% trans "The payment by credit card via Hello Asso is pending validation." %}
{% trans "It should takes only few minutes. If it takes longer, please contact us." %}
</div>
{% endif %}
{% else %}
{% if payment.valid is True %}
<div class="alert alert-success">
{% trans "Your payment is successfully validated by the organizers." %}
<ul>
<li>{% trans "Type:" %} {{ payment.get_type_display }}</li>
<li>
{% trans "Amount:" %} {{ payment.amount }} €
{% if payment.grouped %}
({% trans "It includes the registrations of all members of the team." %})
{% endif %}
</li>
{% if payment.receipt %}
<li>
{% trans "Receipt:" %}
<a href="{{ payment.receipt.url }}"><i class="fas fa-download"></i> {% trans "Download" %}</a>
</li>
{% endif %}
{% if payment.additional_information %}
<li>{% trans "Additional information:" %} {{ payment.additional_information }}</li>
{% endif %}
</ul>
</div>
{% elif payment.valid is None %}
<div class="alert alert-warning">
{% trans "Your payment is pending validation from the organizers." %}
<ul>
<li>{% trans "Type:" %} {{ payment.get_type_display }}</li>
<li>
{% trans "Amount:" %} {{ payment.amount }} €
{% if payment.grouped %}
({% trans "It includes the registrations of all members of the team." %})
{% endif %}
</li>
{% if payment.receipt %}
<li>
{% trans "Receipt:" %}
<a href="{{ payment.receipt.url }}"><i class="fas fa-download"></i> {% trans "Download" %}</a>
</li>
{% endif %}
{% if payment.additional_information %}
<li>{% trans "Additional information:" %} {{ payment.additional_information }}</li>
{% endif %}
</ul>
</div>
{% endif %}
{% endif %}
{% endif %}
{% endif %} {% endif %}
{% endblock content %} {% endblock content %}

View File

@ -451,7 +451,8 @@ class PaymentUpdateView(LoginRequiredMixin, UpdateView):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
if not self.request.user.is_authenticated or \ if not self.request.user.is_authenticated or \
not self.request.user.registration.is_admin \ not self.request.user.registration.is_admin \
and self.request.user.registration not in self.get_object().registrations.all(): and (self.request.user.registration not in self.get_object().registrations.all()
or self.get_object().valid is not False):
return self.handle_no_permission() return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
@ -476,12 +477,8 @@ class PaymentUpdateView(LoginRequiredMixin, UpdateView):
return context return context
def form_valid(self, form): def form_valid(self, form):
form.instance.valid = None
old_instance = Payment.objects.get(pk=self.object.pk) old_instance = Payment.objects.get(pk=self.object.pk)
if self.request.user.registration.participates:
if old_instance.valid is not False:
raise PermissionDenied(_("This payment is already valid or pending validation."))
else:
form.instance.valid = None
if old_instance.receipt: if old_instance.receipt:
old_instance.receipt.delete() old_instance.receipt.delete()
old_instance.save() old_instance.save()