Add payment interface tests

Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
Emmy D'Anello 2024-02-24 23:05:21 +01:00
parent 2a2786ba6d
commit 207af441a0
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
5 changed files with 380 additions and 7 deletions

View File

@ -4,10 +4,11 @@
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, StudentRegistration from registration.models import CoachRegistration, Payment, StudentRegistration
from .models import Participation, Team, Tournament from .models import Participation, Team, Tournament
@ -515,6 +516,365 @@ 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.assertEquals(response.status_code, 200)
response = self.client.get(reverse('registration:user_detail', args=(self.user.pk,)))
self.assertEquals(response.status_code, 200)
response = self.client.get(reverse('participation:tournament_payments', args=(self.tournament.pk,)))
self.assertEquals(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.assertEquals(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.assertEquals(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.assertEquals(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.assertEquals(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.assertEquals(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.assertEquals(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.assertEquals(response.status_code, 200)
self.assertFormError(response.context['form'], 'receipt',
["The uploaded file size must be under 2 Mo."])
self.assertFalse(payment.valid)
self.assertEquals(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.assertEquals(payment.type, "bank_transfer")
self.assertEquals(payment.additional_information, "This is a bank transfer")
self.assertIsNotNone(payment.receipt)
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEquals(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.assertEquals(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.assertEquals(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.assertEquals(payment.type, "")
self.assertEquals(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.assertEquals(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.assertEquals(payment.type, "")
self.assertEquals(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.assertEquals(response.status_code, 200)
self.assertFormError(response.context['form'], 'receipt',
["The uploaded file size must be under 2 Mo."])
self.assertFalse(payment.valid)
self.assertEquals(payment.type, "")
self.assertEquals(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.assertEquals(payment.type, "scholarship")
self.assertEquals(payment.additional_information, "I don't have to pay because I have a scholarship")
self.assertIsNotNone(payment.receipt)
self.assertEquals(payment.amount, 0)
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEquals(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.assertEquals(response.status_code, 200)
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'type': "other"})
self.assertEquals(response.status_code, 200)
self.assertFormError(response.context['form'], 'additional_information',
["This field is required."])
payment.refresh_from_db()
self.assertFalse(payment.valid)
self.assertEquals(payment.type, "")
self.assertEquals(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.assertEquals(payment.type, "other")
self.assertEquals(payment.additional_information, "Why should I pay")
self.assertIsNotNone(payment.receipt)
self.assertEquals(payment.amount, self.tournament.price)
response = self.client.get(reverse('registration:update_payment', args=(payment.pk,)))
self.assertEquals(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.assertEquals(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.assertEquals(Payment.objects.count(), 1)
self.assertIn(self.user.registration, payment.registrations.all())
self.assertIn(self.second_user.registration, payment.registrations.all())
self.assertEquals(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.assertEquals(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.assertEquals(Payment.objects.count(), 2)
self.assertIn(self.user.registration, payment.registrations.all())
self.assertNotIn(self.second_user.registration, payment.registrations.all())
self.assertEquals(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.assertEquals(response.status_code, 403)
response = self.client.get(reverse('registration:update_payment_group_mode', args=(payment2.pk,)))
self.assertEquals(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.assertEquals(response.status_code, 200)
response = self.client.post(reverse('registration:update_payment', args=(payment.pk,)),
data={'valid': True})
self.assertEquals(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.assertEquals(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.signals import create_admin_registration, \ from registration import signals
set_username, send_email_link pre_save.connect(signals.set_username, 'auth.User')
pre_save.connect(set_username, "auth.User") pre_save.connect(signals.send_email_link, 'auth.User')
pre_save.connect(send_email_link, "auth.User") pre_save.connect(signals.update_payment_amount, 'registration.Payment')
post_save.connect(create_admin_registration, "auth.User") post_save.connect(signals.create_admin_registration, 'auth.User')

View File

@ -226,6 +226,9 @@ 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 self.payment.valid is None: elif 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,3 +41,13 @@ 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