mirror of
https://gitlab.crans.org/bde/nk20
synced 2024-11-30 04:13:01 +00:00
a6b479db19
- /apps/activity/api/serializers.py - /apps/activity/api/urls.py - /apps/activity/api/views.py - /apps/activity/tests/test_activities.py - /apps/activity/__init__.py - /apps/activity/admin.py - /apps/activity/apps.py - /apps/activity/forms.py - /apps/activity/tables.py - /apps/activity/urls.py - /apps/activity/views.py - /apps/api/__init__.py - /apps/api/apps.py - /apps/api/serializers.py - /apps/api/tests.py - /apps/api/urls.py - /apps/api/views.py - /apps/api/viewsets.py - /apps/logs/signals.py - /apps/logs/apps.py - /apps/logs/__init__.py - /apps/logs/api/serializers.py - /apps/logs/api/urls.py - /apps/logs/api/views.py - /apps/member/api/serializers.py - /apps/member/api/urls.py - /apps/member/api/views.py - /apps/member/templatetags/memberinfo.py - /apps/member/__init__.py - /apps/member/admin.py - /apps/member/apps.py - /apps/member/auth.py - /apps/member/forms.py - /apps/member/hashers.py - /apps/member/signals.py - /apps/member/tables.py - /apps/member/urls.py - /apps/member/views.py - /apps/note/api/serializers.py - /apps/note/api/urls.py - /apps/note/api/views.py - /apps/note/models/__init__.py - /apps/note/static/note/js/consos.js - /apps/note/templates/note/mails/negative_balance.txt - /apps/note/templatetags/getenv.py - /apps/note/templatetags/pretty_money.py - /apps/note/tests/test_transactions.py - /apps/note/__init__.py - /apps/note/admin.py - /apps/note/apps.py - /apps/note/forms.py - /apps/note/signals.py - /apps/note/tables.py - /apps/note/urls.py - /apps/note/views.py - /apps/permission/api/serializers.py - /apps/permission/api/urls.py - /apps/permission/api/views.py - /apps/permission/templatetags/perms.py - /apps/permission/tests/test_oauth2.py - /apps/permission/tests/test_permission_denied.py - /apps/permission/tests/test_permission_queries.py - /apps/permission/tests/test_rights_page.py - /apps/permission/__init__.py - /apps/permission/admin.py - /apps/permission/backends.py - /apps/permission/apps.py - /apps/permission/decorators.py - /apps/permission/permissions.py - /apps/permission/scopes.py - /apps/permission/signals.py - /apps/permission/tables.py - /apps/permission/urls.py - /apps/permission/views.py - /apps/registration/tests/test_registration.py - /apps/registration/__init__.py - /apps/registration/apps.py - /apps/registration/forms.py - /apps/registration/tables.py - /apps/registration/tokens.py - /apps/registration/urls.py - /apps/registration/views.py - /apps/treasury/api/serializers.py - /apps/treasury/api/urls.py - /apps/treasury/api/views.py - /apps/treasury/templatetags/escape_tex.py - /apps/treasury/tests/test_treasury.py - /apps/treasury/__init__.py - /apps/treasury/admin.py - /apps/treasury/apps.py - /apps/treasury/forms.py - /apps/treasury/signals.py - /apps/treasury/tables.py - /apps/treasury/urls.py - /apps/treasury/views.py - /apps/wei/api/serializers.py - /apps/wei/api/urls.py - /apps/wei/api/views.py - /apps/wei/forms/surveys/__init__.py - /apps/wei/forms/surveys/base.py - /apps/wei/forms/surveys/wei2021.py - /apps/wei/forms/surveys/wei2022.py - /apps/wei/forms/surveys/wei2023.py - /apps/wei/forms/__init__.py - /apps/wei/forms/registration.py - /apps/wei/management/commands/export_wei_registrations.py - /apps/wei/management/commands/import_scores.py - /apps/wei/management/commands/wei_algorithm.py - /apps/wei/templates/wei/weilist_sample.tex - /apps/wei/tests/test_wei_algorithm_2021.py - /apps/wei/tests/test_wei_algorithm_2022.py - /apps/wei/tests/test_wei_algorithm_2023.py - /apps/wei/tests/test_wei_registration.py - /apps/wei/__init__.py - /apps/wei/admin.py - /apps/wei/apps.py - /apps/wei/tables.py - /apps/wei/urls.py - /apps/wei/views.py - /note_kfet/settings/__init__.py - /note_kfet/settings/base.py - /note_kfet/settings/development.py - /note_kfet/settings/secrets_example.py - /note_kfet/static/js/base.js - /note_kfet/admin.py - /note_kfet/inputs.py - /note_kfet/middlewares.py - /note_kfet/urls.py - /note_kfet/views.py - /note_kfet/wsgi.py - /entrypoint.sh
437 lines
18 KiB
Python
437 lines
18 KiB
Python
# Copyright (C) 2018-2024 by BDE ENS Paris-Saclay
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
from api.tests import TestAPI
|
|
from member.models import Club, Membership
|
|
from django.contrib.auth.models import User
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.test import TestCase
|
|
from django.urls import reverse
|
|
from django.utils import timezone
|
|
from permission.models import Role
|
|
|
|
from ..api.views import AliasViewSet, ConsumerViewSet, NotePolymorphicViewSet, TemplateCategoryViewSet,\
|
|
TransactionTemplateViewSet, TransactionViewSet
|
|
from ..models import NoteUser, Transaction, TemplateCategory, TransactionTemplate, RecurrentTransaction, \
|
|
MembershipTransaction, SpecialTransaction, NoteSpecial, Alias, Note
|
|
|
|
|
|
class TestTransactions(TestCase):
|
|
fixtures = ('initial', )
|
|
|
|
def setUp(self) -> None:
|
|
self.user = User.objects.create_superuser(
|
|
username="toto",
|
|
password="totototo",
|
|
email="toto@example.com",
|
|
)
|
|
|
|
sess = self.client.session
|
|
sess["permission_mask"] = 42
|
|
sess.save()
|
|
self.client.force_login(self.user)
|
|
|
|
membership = Membership.objects.create(club=Club.objects.get(name="BDE"), user=self.user)
|
|
membership.roles.add(Role.objects.get(name="Respo info"))
|
|
membership.save()
|
|
Membership.objects.create(club=Club.objects.get(name="Kfet"), user=self.user)
|
|
self.user.note.refresh_from_db()
|
|
|
|
self.second_user = User.objects.create(
|
|
username="toto2",
|
|
)
|
|
# Non superusers have no note until the registration get validated
|
|
NoteUser.objects.create(user=self.second_user)
|
|
|
|
self.club = Club.objects.create(
|
|
name="clubtoto",
|
|
)
|
|
|
|
self.transaction = Transaction.objects.create(
|
|
source=self.second_user.note,
|
|
destination=self.user.note,
|
|
amount=4200,
|
|
reason="Test transaction",
|
|
)
|
|
self.user.note.refresh_from_db()
|
|
self.second_user.note.refresh_from_db()
|
|
|
|
self.category = TemplateCategory.objects.create(name="Test")
|
|
self.template = TransactionTemplate.objects.create(
|
|
name="Test",
|
|
destination=self.club.note,
|
|
category=self.category,
|
|
amount=100,
|
|
description="Test template",
|
|
)
|
|
|
|
def test_admin_pages(self):
|
|
"""
|
|
Load some admin pages to check that they render successfully.
|
|
"""
|
|
response = self.client.get(reverse("admin:index") + "note/note/")
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.get(reverse("admin:index") + "note/transaction/")
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.get(reverse("admin:index") + "note/transaction/" + str(self.transaction.pk) + "/change/")
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.get(reverse("admin:index") + "note/transaction/add/?ct_id="
|
|
+ str(ContentType.objects.get_for_model(Transaction).id))
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.get(reverse("admin:index") + "note/transaction/add/?ct_id="
|
|
+ str(ContentType.objects.get_for_model(RecurrentTransaction).id))
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.get(reverse("admin:index") + "note/transaction/add/?ct_id="
|
|
+ str(ContentType.objects.get_for_model(MembershipTransaction).id))
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.get(reverse("admin:index") + "note/transaction/add/?ct_id="
|
|
+ str(ContentType.objects.get_for_model(SpecialTransaction).id))
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.get(reverse("admin:index") + "note/transactiontemplate/")
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.get(reverse("admin:index") + "note/templatecategory/")
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_render_transfer_page(self):
|
|
response = self.client.get(reverse("note:transfer"))
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_transfer_api(self):
|
|
old_user_balance = self.user.note.balance
|
|
old_second_user_balance = self.second_user.note.balance
|
|
quantity = 3
|
|
amount = 314
|
|
total = quantity * amount
|
|
response = self.client.post("/api/note/transaction/transaction/", data=dict(
|
|
quantity=quantity,
|
|
amount=amount,
|
|
reason="Transaction through API",
|
|
valid=True,
|
|
polymorphic_ctype=ContentType.objects.get_for_model(Transaction).id,
|
|
resourcetype="Transaction",
|
|
source=self.user.note.id,
|
|
source_alias=self.user.username,
|
|
destination=self.second_user.note.id,
|
|
destination_alias=self.second_user.username,
|
|
))
|
|
self.assertEqual(response.status_code, 201) # 201 = Created
|
|
self.assertTrue(Transaction.objects.filter(reason="Transaction through API").exists())
|
|
|
|
self.user.note.refresh_from_db()
|
|
self.second_user.note.refresh_from_db()
|
|
|
|
self.assertTrue(self.user.note.balance == old_user_balance - total)
|
|
self.assertTrue(self.second_user.note.balance == old_second_user_balance + total)
|
|
|
|
self.test_render_transfer_page()
|
|
|
|
def test_credit_api(self):
|
|
old_user_balance = self.user.note.balance
|
|
amount = 4242
|
|
special_type = NoteSpecial.objects.first()
|
|
response = self.client.post("/api/note/transaction/transaction/", data=dict(
|
|
quantity=1,
|
|
amount=amount,
|
|
reason="Credit through API",
|
|
valid=True,
|
|
polymorphic_ctype=ContentType.objects.get_for_model(SpecialTransaction).id,
|
|
resourcetype="SpecialTransaction",
|
|
source=special_type.id,
|
|
source_alias=str(special_type),
|
|
destination=self.user.note.id,
|
|
destination_alias=self.user.username,
|
|
last_name="TOTO",
|
|
first_name="Toto",
|
|
))
|
|
|
|
self.assertEqual(response.status_code, 201) # 201 = Created
|
|
self.assertTrue(Transaction.objects.filter(reason="Credit through API").exists())
|
|
self.user.note.refresh_from_db()
|
|
self.assertTrue(self.user.note.balance == old_user_balance + amount)
|
|
|
|
self.test_render_transfer_page()
|
|
|
|
def test_debit_api(self):
|
|
old_user_balance = self.user.note.balance
|
|
amount = 4242
|
|
special_type = NoteSpecial.objects.first()
|
|
response = self.client.post("/api/note/transaction/transaction/", data=dict(
|
|
quantity=1,
|
|
amount=amount,
|
|
reason="Debit through API",
|
|
valid=True,
|
|
polymorphic_ctype=ContentType.objects.get_for_model(SpecialTransaction).id,
|
|
resourcetype="SpecialTransaction",
|
|
source=self.user.note.id,
|
|
source_alias=self.user.username,
|
|
destination=special_type.id,
|
|
destination_alias=str(special_type),
|
|
last_name="TOTO",
|
|
first_name="Toto",
|
|
))
|
|
self.assertEqual(response.status_code, 201) # 201 = Created
|
|
self.assertTrue(Transaction.objects.filter(reason="Debit through API").exists())
|
|
self.user.note.refresh_from_db()
|
|
self.assertTrue(self.user.note.balance == old_user_balance - amount)
|
|
|
|
self.test_render_transfer_page()
|
|
|
|
def test_render_consos_page(self):
|
|
response = self.client.get(reverse("note:consos"))
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_consumption_api(self):
|
|
old_user_balance = self.user.note.balance
|
|
old_club_balance = self.club.note.balance
|
|
quantity = 2
|
|
template = self.template
|
|
total = quantity * template.amount
|
|
response = self.client.post("/api/note/transaction/transaction/", data=dict(
|
|
quantity=quantity,
|
|
amount=template.amount,
|
|
reason="Consumption through API (" + template.name + ")",
|
|
valid=True,
|
|
polymorphic_ctype=ContentType.objects.get_for_model(RecurrentTransaction).id,
|
|
resourcetype="RecurrentTransaction",
|
|
source=self.user.note.id,
|
|
source_alias=self.user.username,
|
|
destination=self.club.note.id,
|
|
destination_alias=self.second_user.username,
|
|
template=template.id,
|
|
))
|
|
self.assertEqual(response.status_code, 201) # 201 = Created
|
|
self.assertTrue(Transaction.objects.filter(destination=self.club.note).exists())
|
|
|
|
self.user.note.refresh_from_db()
|
|
self.club.note.refresh_from_db()
|
|
|
|
self.assertTrue(self.user.note.balance == old_user_balance - total)
|
|
self.assertTrue(self.club.note.balance == old_club_balance + total)
|
|
|
|
self.test_render_consos_page()
|
|
|
|
def test_invalidate_transaction(self):
|
|
old_second_user_balance = self.second_user.note.balance
|
|
old_user_balance = self.user.note.balance
|
|
total = self.transaction.total
|
|
response = self.client.patch("/api/note/transaction/transaction/" + str(self.transaction.pk) + "/", data=dict(
|
|
valid=False,
|
|
resourcetype="Transaction",
|
|
invalidity_reason="Test invalidate",
|
|
), content_type="application/json")
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue(Transaction.objects.filter(valid=False, invalidity_reason="Test invalidate").exists())
|
|
|
|
self.second_user.note.refresh_from_db()
|
|
self.user.note.refresh_from_db()
|
|
|
|
self.assertTrue(self.second_user.note.balance == old_second_user_balance + total)
|
|
self.assertTrue(self.user.note.balance == old_user_balance - total)
|
|
|
|
self.test_render_transfer_page()
|
|
self.test_render_consos_page()
|
|
|
|
# Now we check if we can revalidate
|
|
old_second_user_balance = self.second_user.note.balance
|
|
old_user_balance = self.user.note.balance
|
|
total = self.transaction.total
|
|
response = self.client.patch("/api/note/transaction/transaction/" + str(self.transaction.pk) + "/", data=dict(
|
|
valid=True,
|
|
resourcetype="Transaction",
|
|
), content_type="application/json")
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue(Transaction.objects.filter(valid=True, pk=self.transaction.pk).exists())
|
|
|
|
self.second_user.note.refresh_from_db()
|
|
self.user.note.refresh_from_db()
|
|
|
|
self.assertTrue(self.second_user.note.balance == old_second_user_balance - total)
|
|
self.assertTrue(self.user.note.balance == old_user_balance + total)
|
|
|
|
self.test_render_transfer_page()
|
|
self.test_render_consos_page()
|
|
|
|
def test_render_template_list(self):
|
|
response = self.client.get(reverse("note:template_list") + "?search=test")
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_render_template_create(self):
|
|
response = self.client.get(reverse("note:template_create"))
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.post(reverse("note:template_create"), data=dict(
|
|
name="Test create button",
|
|
destination=self.club.note.pk,
|
|
category=self.category.pk,
|
|
amount=4200,
|
|
description="We have created a button",
|
|
highlighted=True,
|
|
display=True,
|
|
))
|
|
self.assertRedirects(response, reverse("note:template_list"), 302, 200)
|
|
self.assertTrue(TransactionTemplate.objects.filter(name="Test create button").exists())
|
|
|
|
def test_render_template_update(self):
|
|
response = self.client.get(self.template.get_absolute_url())
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.post(self.template.get_absolute_url(), data=dict(
|
|
name="Test update button",
|
|
destination=self.club.note.pk,
|
|
category=self.category.pk,
|
|
amount=4200,
|
|
description="We have updated a button",
|
|
highlighted=True,
|
|
display=True,
|
|
))
|
|
self.assertRedirects(response, reverse("note:template_list"), 302, 200)
|
|
self.assertTrue(TransactionTemplate.objects.filter(name="Test update button", pk=self.template.pk).exists())
|
|
|
|
# Check that the price history renders properly
|
|
response = self.client.post(self.template.get_absolute_url(), data=dict(
|
|
name="Test price history",
|
|
destination=self.club.note.pk,
|
|
category=self.category.pk,
|
|
amount=4200,
|
|
description="We have updated a button",
|
|
highlighted=True,
|
|
display=True,
|
|
))
|
|
self.assertRedirects(response, reverse("note:template_list"), 302, 200)
|
|
self.assertTrue(TransactionTemplate.objects.filter(name="Test price history", pk=self.template.pk).exists())
|
|
response = self.client.get(reverse("note:template_update", args=(self.template.pk,)))
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_render_search_transactions(self):
|
|
response = self.client.get(reverse("note:transactions", args=(self.user.note.pk,)), data=dict(
|
|
source=self.second_user.note.alias.first().id,
|
|
destination=self.user.note.alias.first().id,
|
|
type=[ContentType.objects.get_for_model(Transaction).id],
|
|
reason="test",
|
|
valid=True,
|
|
amount_gte=0,
|
|
amount_lte=42424242,
|
|
created_after="2000-01-01 00:00",
|
|
created_before="2042-12-31 21:42",
|
|
))
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_delete_transaction(self):
|
|
# Transactions can't be deleted with a normal usage, but it is possible through the admin interface.
|
|
old_second_user_balance = self.second_user.note.balance
|
|
old_user_balance = self.user.note.balance
|
|
total = self.transaction.total
|
|
|
|
self.transaction.delete()
|
|
self.second_user.note.refresh_from_db()
|
|
self.user.note.refresh_from_db()
|
|
|
|
self.assertTrue(self.second_user.note.balance == old_second_user_balance + total)
|
|
self.assertTrue(self.user.note.balance == old_user_balance - total)
|
|
|
|
def test_calculate_last_negative_duration(self):
|
|
self.assertIsNone(self.user.note.last_negative_duration)
|
|
self.assertIsNotNone(self.second_user.note.last_negative_duration)
|
|
self.assertIsNone(self.club.note.last_negative_duration)
|
|
|
|
Transaction.objects.create(
|
|
source=self.club.note,
|
|
destination=self.user.note,
|
|
amount=2 * self.club.note.balance + 100,
|
|
reason="Club balance is negative",
|
|
)
|
|
|
|
self.club.note.refresh_from_db()
|
|
self.assertIsNotNone(self.club.note.last_negative_duration)
|
|
|
|
def test_api_search(self):
|
|
response = self.client.get("/api/note/note/")
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.get("/api/note/alias/?alias=.*")
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.get("/api/note/consumer/")
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.get("/api/note/transaction/transaction/")
|
|
self.assertEqual(response.status_code, 200)
|
|
response = self.client.get("/api/note/transaction/template/")
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
def test_api_alias(self):
|
|
response = self.client.post("/api/note/alias/", data=dict(
|
|
name="testalias",
|
|
note=self.user.note.id,
|
|
))
|
|
self.assertEqual(response.status_code, 201)
|
|
self.assertTrue(Alias.objects.filter(name="testalias").exists())
|
|
alias = Alias.objects.get(name="testalias")
|
|
response = self.client.patch("/api/note/alias/" + str(alias.pk) + "/", dict(name="test_updated_alias"),
|
|
content_type="application/json")
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue(Alias.objects.filter(name="test_updated_alias").exists())
|
|
response = self.client.delete("/api/note/alias/" + str(alias.pk) + "/")
|
|
self.assertEqual(response.status_code, 204)
|
|
|
|
|
|
class TestNoteAPI(TestAPI):
|
|
def setUp(self) -> None:
|
|
super().setUp()
|
|
|
|
membership = Membership.objects.create(club=Club.objects.get(name="BDE"), user=self.user)
|
|
membership.roles.add(Role.objects.get(name="Respo info"))
|
|
membership.save()
|
|
Membership.objects.create(club=Club.objects.get(name="Kfet"), user=self.user)
|
|
self.user.note.last_negative = timezone.now()
|
|
self.user.note.save()
|
|
|
|
self.transaction = Transaction.objects.create(
|
|
source=Note.objects.first(),
|
|
destination=self.user.note,
|
|
amount=4200,
|
|
reason="Test transaction",
|
|
)
|
|
self.user.note.refresh_from_db()
|
|
Alias.objects.create(note=self.user.note, name="I am a ¢omplex alias")
|
|
|
|
self.category = TemplateCategory.objects.create(name="Test")
|
|
self.template = TransactionTemplate.objects.create(
|
|
name="Test",
|
|
destination=Club.objects.get(name="BDE").note,
|
|
category=self.category,
|
|
amount=100,
|
|
description="Test template",
|
|
)
|
|
|
|
def test_alias_api(self):
|
|
"""
|
|
Load Alias API page and test all filters and permissions
|
|
"""
|
|
self.check_viewset(AliasViewSet, "/api/note/alias/")
|
|
|
|
def test_consumer_api(self):
|
|
"""
|
|
Load Consumer API page and test all filters and permissions
|
|
"""
|
|
self.check_viewset(ConsumerViewSet, "/api/note/consumer/")
|
|
|
|
def test_note_api(self):
|
|
"""
|
|
Load Note API page and test all filters and permissions
|
|
"""
|
|
self.check_viewset(NotePolymorphicViewSet, "/api/note/note/")
|
|
|
|
def test_template_category_api(self):
|
|
"""
|
|
Load TemplateCategory API page and test all filters and permissions
|
|
"""
|
|
self.check_viewset(TemplateCategoryViewSet, "/api/note/transaction/category/")
|
|
|
|
def test_transaction_template_api(self):
|
|
"""
|
|
Load TemplateTemplate API page and test all filters and permissions
|
|
"""
|
|
self.check_viewset(TransactionTemplateViewSet, "/api/note/transaction/template/")
|
|
|
|
def test_transaction_api(self):
|
|
"""
|
|
Load Transaction API page and test all filters and permissions
|
|
"""
|
|
self.check_viewset(TransactionViewSet, "/api/note/transaction/transaction/")
|