Coverage for website/sales/tests/test_admin.py: 93.75%
366 statements
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
« prev ^ index » next coverage.py v7.6.7, created at 2025-08-14 10:31 +0000
1from django.contrib.admin import AdminSite
2from django.contrib.auth.models import Permission
3from django.contrib.contenttypes.models import ContentType
4from django.test import Client, RequestFactory, TestCase
5from django.urls import reverse
6from django.utils import timezone
8from activemembers.models import Committee, MemberGroupMembership
9from members.models import Member
10from payments.models import Payment
11from payments.services import create_payment
12from sales import payables
13from sales.admin.order_admin import OrderAdmin
14from sales.admin.shift_admin import ShiftAdmin
15from sales.models.order import Order, OrderItem
16from sales.models.product import Product, ProductList
17from sales.models.shift import Shift
20class OrderAdminTest(TestCase):
21 fixtures = [
22 "members.json",
23 "bank_accounts.json",
24 "member_groups.json",
25 "products.json",
26 ]
28 @classmethod
29 def setUpTestData(cls) -> None:
30 """Create the following test data:
32 o0: an empty order
33 o1: an unpaid order of 2 beer
34 o2: an order of 2 soda that doesn't need a payment
35 o3: an unpaid order with 2 beer and 2 wine
36 o4: a paid order with 2 wine
37 o5: a paid order with 2 beer and 2 wine
38 o6: an unpaid order of 2 soda that does need a payment (custom)
39 """
40 payables.register()
42 cls.user = Member.objects.filter(last_name="Wiggers").first()
44 cls.beer = Product.objects.get(name="beer")
45 cls.wine = Product.objects.get(name="wine")
46 cls.soda = Product.objects.get(name="soda")
48 cls.normal = ProductList.objects.get(
49 name="normal",
50 )
51 cls.free = ProductList.objects.get(
52 name="free",
53 )
55 cls.shift = Shift.objects.create(
56 start=timezone.now(),
57 end=timezone.now() + timezone.timedelta(hours=1),
58 product_list=cls.normal,
59 )
61 cls.o0 = Order.objects.create(shift=cls.shift)
62 cls.o1 = Order.objects.create(shift=cls.shift)
63 OrderItem.objects.create(
64 order=cls.o1,
65 product=cls.shift.product_list.product_items.get(product=cls.beer),
66 amount=2,
67 )
68 cls.o2 = Order.objects.create(shift=cls.shift)
69 OrderItem.objects.create(
70 order=cls.o2,
71 product=cls.shift.product_list.product_items.get(product=cls.soda),
72 amount=2,
73 )
74 cls.o3 = Order.objects.create(shift=cls.shift)
75 OrderItem.objects.create(
76 order=cls.o3,
77 product=cls.shift.product_list.product_items.get(product=cls.beer),
78 amount=2,
79 )
80 OrderItem.objects.create(
81 order=cls.o3,
82 product=cls.shift.product_list.product_items.get(product=cls.wine),
83 amount=2,
84 )
85 cls.o4 = Order.objects.create(shift=cls.shift)
86 OrderItem.objects.create(
87 order=cls.o4,
88 product=cls.shift.product_list.product_items.get(product=cls.wine),
89 amount=2,
90 )
91 cls.o5 = Order.objects.create(shift=cls.shift)
92 OrderItem.objects.create(
93 order=cls.o5,
94 product=cls.shift.product_list.product_items.get(product=cls.beer),
95 amount=2,
96 )
97 OrderItem.objects.create(
98 order=cls.o5,
99 product=cls.shift.product_list.product_items.get(product=cls.wine),
100 amount=2,
101 )
102 cls.o4.payment = create_payment(
103 cls.o4, processed_by=cls.user, pay_type=Payment.CASH
104 )
105 cls.o4.save()
106 cls.o5.payment = create_payment(
107 cls.o5, processed_by=cls.user, pay_type=Payment.CASH
108 )
109 cls.o5.save()
110 cls.o6 = Order.objects.create(shift=cls.shift)
111 OrderItem.objects.create(
112 order=cls.o6,
113 product=cls.shift.product_list.product_items.get(product=cls.soda),
114 amount=2,
115 total=1,
116 )
118 cls.cie = Committee.objects.get(pk=1)
119 MemberGroupMembership.objects.create(group=cls.cie, member=cls.user)
120 content_type = ContentType.objects.get_for_model(Order)
121 permission1 = Permission.objects.get(
122 content_type=content_type, codename="add_order"
123 )
124 permission2 = Permission.objects.get(
125 content_type=content_type, codename="change_order"
126 )
127 permission3 = Permission.objects.get(
128 content_type=content_type, codename="delete_order"
129 )
130 permission4 = Permission.objects.get(
131 content_type=content_type, codename="view_order"
132 )
133 cls.cie.permissions.add(permission1)
134 cls.cie.permissions.add(permission2)
135 cls.cie.permissions.add(permission3)
136 cls.cie.permissions.add(permission4)
138 def setUp(self) -> None:
139 self.client = Client()
140 self.client.force_login(self.user)
141 self.factory = RequestFactory()
142 self.site = AdminSite()
143 self.admin = OrderAdmin(Order, admin_site=self.site)
144 self.rf = RequestFactory()
146 self.client.logout()
147 self.client.force_login(self.user)
149 def test_change_form_view_rendering_correctly(self) -> None:
150 for o in [self.o0, self.o1, self.o2, self.o3, self.o4, self.o5, self.o6]:
151 response = self.client.get(f"/admin/sales/order/{o.id}/change/")
152 self.assertEqual(200, response.status_code)
154 def test_change_list_view_rendering_correctly(self) -> None:
155 response = self.client.get("/admin/sales/order/")
156 self.assertEqual(200, response.status_code)
158 def test_view_permissions(self):
159 with self.subTest("View as super user"):
160 request = self.rf.get(
161 reverse("admin:sales_order_change", args=[self.o1.pk])
162 )
163 request.user = self.user
164 request.member = self.user
165 self.assertTrue(self.admin.has_view_permission(request, self.o1))
167 with self.subTest("View without permissions"):
168 self.user.is_superuser = False
169 self.user.save()
170 self.client.logout()
171 self.client.force_login(self.user)
172 request = self.rf.get(
173 reverse("admin:sales_order_change", args=[self.o1.pk])
174 )
175 request.user = self.user
176 request.member = self.user
177 self.assertFalse(self.admin.has_view_permission(request, self.o1))
179 with self.subTest("View as shift manager"):
180 self.shift.managers.add(self.cie)
181 self.shift.save()
182 self.client.logout()
183 self.client.force_login(self.user)
184 request = self.rf.get(
185 reverse("admin:sales_order_change", args=[self.o1.pk])
186 )
187 request.user = self.user
188 request.member = self.user
189 self.assertTrue(self.admin.has_view_permission(request, self.o1))
191 def test_change_permissions(self):
192 with self.subTest("Change as super user"):
193 request = self.rf.get(
194 reverse("admin:sales_order_change", args=[self.o1.pk])
195 )
196 request.user = self.user
197 request.member = self.user
198 self.assertTrue(self.admin.has_change_permission(request, self.o1))
199 self.assertTrue(
200 self.admin.inlines[0].has_change_permission(
201 self.admin, request, self.o1
202 )
203 )
205 with self.subTest("Change without permissions"):
206 self.user.is_superuser = False
207 self.user.save()
208 self.client.logout()
209 self.client.force_login(self.user)
210 request = self.rf.get(
211 reverse("admin:sales_order_change", args=[self.o1.pk])
212 )
213 request.user = self.user
214 request.member = self.user
215 self.assertFalse(self.admin.has_change_permission(request, self.o1))
216 self.assertFalse(
217 self.admin.inlines[0].has_change_permission(
218 self.admin, request, self.o1
219 )
220 )
222 with self.subTest("Change as shift manager"):
223 self.shift.managers.add(self.cie)
224 self.shift.save()
225 self.client.logout()
226 self.client.force_login(self.user)
227 request = self.rf.get(
228 reverse("admin:sales_order_change", args=[self.o1.pk])
229 )
230 request.user = self.user
231 request.member = self.user
232 self.assertTrue(self.admin.has_change_permission(request, self.o1))
233 self.assertTrue(
234 self.admin.inlines[0].has_change_permission(
235 self.admin, request, self.o1
236 )
237 )
239 def test_change_permission_paid(self):
240 request = self.rf.get(reverse("admin:sales_order_change", args=[self.o4.pk]))
241 request.user = self.user
242 request.member = self.user
243 self.assertFalse(self.admin.has_change_permission(request, self.o4))
244 self.assertFalse(
245 self.admin.inlines[0].has_change_permission(self.admin, request, self.o4)
246 )
248 def test_change_permission_locked(self):
249 self.shift.locked = True
250 self.shift.save()
252 request = self.rf.get(reverse("admin:sales_order_change", args=[self.o1.pk]))
253 request.user = self.user
254 request.member = self.user
255 self.assertFalse(self.admin.has_change_permission(request, self.o1))
256 self.assertFalse(self.admin.has_change_permission(request, self.o1))
258 def test_delete_permissions(self):
259 with self.subTest("Delete as super user"):
260 request = self.rf.get(
261 reverse("admin:sales_order_delete", args=[self.o1.pk])
262 )
263 request.user = self.user
264 request.member = self.user
265 self.assertTrue(self.admin.has_delete_permission(request, self.o1))
266 self.assertTrue(
267 self.admin.inlines[0].has_delete_permission(
268 self.admin, request, self.o1
269 )
270 )
272 with self.subTest("Delete without permissions"):
273 self.user.is_superuser = False
274 self.user.save()
275 self.client.logout()
276 self.client.force_login(self.user)
277 request = self.rf.get(
278 reverse("admin:sales_order_delete", args=[self.o1.pk])
279 )
280 request.user = self.user
281 request.member = self.user
282 self.assertFalse(self.admin.has_delete_permission(request, self.o1))
283 self.assertFalse(
284 self.admin.inlines[0].has_delete_permission(
285 self.admin, request, self.o1
286 )
287 )
289 with self.subTest("Delete as shift manager"):
290 self.shift.managers.add(self.cie)
291 self.shift.save()
292 self.client.logout()
293 self.client.force_login(self.user)
294 request = self.rf.get(
295 reverse("admin:sales_order_delete", args=[self.o1.pk])
296 )
297 request.user = self.user
298 request.member = self.user
299 self.assertTrue(self.admin.has_delete_permission(request, self.o1))
300 self.assertTrue(
301 self.admin.inlines[0].has_delete_permission(
302 self.admin, request, self.o1
303 )
304 )
306 def test_delete_permission_paid(self):
307 request = self.rf.get(reverse("admin:sales_order_delete", args=[self.o4.pk]))
308 request.user = self.user
309 request.member = self.user
310 self.assertFalse(self.admin.has_delete_permission(request, self.o4))
311 self.assertFalse(
312 self.admin.inlines[0].has_delete_permission(self.admin, request, self.o4)
313 )
315 def test_delete_permission_locked(self):
316 self.shift.locked = True
317 self.shift.save()
319 request = self.rf.get(reverse("admin:sales_order_delete", args=[self.o1.pk]))
320 request.user = self.user
321 request.member = self.user
322 self.assertFalse(self.admin.has_delete_permission(request, self.o1))
323 self.assertFalse(
324 self.admin.inlines[0].has_delete_permission(self.admin, request, self.o4)
325 )
327 def test_add_permission(self):
328 with self.subTest("Create as super user"):
329 request = self.rf.get(reverse("admin:sales_order_add"))
330 request.user = self.user
331 request.member = self.user
332 self.assertTrue(self.admin.has_add_permission(request))
334 with self.subTest("Create without permissions"):
335 self.user.is_superuser = False
336 self.user.save()
337 self.client.logout()
338 self.client.force_login(self.user)
339 request = self.rf.get(reverse("admin:sales_order_add"))
340 request.user = self.user
341 request.member = self.user
342 self.assertFalse(self.admin.has_add_permission(request))
344 with self.subTest("Create as shift manager"):
345 self.shift.managers.add(self.cie)
346 self.shift.save()
347 self.client.logout()
348 self.client.force_login(self.user)
349 request = self.rf.get(reverse("admin:sales_order_add"))
350 request.user = self.user
351 request.member = self.user
352 self.assertTrue(self.admin.has_add_permission(request))
354 with self.subTest("Create as shift manager no active shift"):
355 self.shift.locked = True
356 self.shift.save()
357 request = self.rf.get(reverse("admin:sales_order_add"))
358 request.user = self.user
359 request.member = self.user
360 self.assertFalse(self.admin.has_add_permission(request))
362 def test_custom_prices_readonly(self):
363 with self.subTest("Custom prices as super user"):
364 request = self.rf.get(reverse("admin:sales_order_add"))
365 request.user = self.user
366 request.member = self.user
368 self.assertFalse("discount" in self.admin.get_readonly_fields(request))
369 self.assertFalse(
370 "total"
371 in self.admin.inlines[0].get_readonly_fields(self.admin, request)
372 )
374 with self.subTest("Custom prices regular user"):
375 self.user.is_superuser = False
376 self.user.save()
377 self.shift.managers.add(self.cie)
378 self.shift.save()
379 self.client.logout()
380 self.client.force_login(self.user)
382 request = self.rf.get(reverse("admin:sales_order_add"))
383 request.user = self.user
384 request.member = self.user
386 self.assertTrue("discount" in self.admin.get_readonly_fields(request))
387 self.assertTrue(
388 "total"
389 in self.admin.inlines[0].get_readonly_fields(self.admin, request)
390 )
393class ShiftAdminTest(TestCase):
394 fixtures = [
395 "members.json",
396 "bank_accounts.json",
397 "member_groups.json",
398 "products.json",
399 ]
401 @classmethod
402 def setUpTestData(cls) -> None:
403 """Create the following test data:
405 o0: an empty order
406 o1: an unpaid order of 2 beer
407 o2: an order of 2 soda that doesn't need a payment
408 o3: an unpaid order with 2 beer and 2 wine
409 o4: a paid order with 2 wine
410 o5: a paid order with 2 beer and 2 wine
411 o6: an unpaid order of 2 soda that does need a payment (custom)
412 """
413 payables.register()
415 cls.user = Member.objects.filter(last_name="Wiggers").first()
417 cls.beer = Product.objects.get(name="beer")
418 cls.wine = Product.objects.get(name="wine")
419 cls.soda = Product.objects.get(name="soda")
421 cls.normal = ProductList.objects.get(
422 name="normal",
423 )
424 cls.free = ProductList.objects.get(
425 name="free",
426 )
428 cls.shift = Shift.objects.create(
429 start=timezone.now(),
430 end=timezone.now() + timezone.timedelta(hours=1),
431 product_list=cls.normal,
432 )
434 cls.o0 = Order.objects.create(shift=cls.shift)
435 cls.o1 = Order.objects.create(shift=cls.shift)
436 OrderItem.objects.create(
437 order=cls.o1,
438 product=cls.shift.product_list.product_items.get(product=cls.beer),
439 amount=2,
440 )
441 cls.o2 = Order.objects.create(shift=cls.shift)
442 OrderItem.objects.create(
443 order=cls.o2,
444 product=cls.shift.product_list.product_items.get(product=cls.soda),
445 amount=2,
446 )
447 cls.o3 = Order.objects.create(shift=cls.shift)
448 OrderItem.objects.create(
449 order=cls.o3,
450 product=cls.shift.product_list.product_items.get(product=cls.beer),
451 amount=2,
452 )
453 OrderItem.objects.create(
454 order=cls.o3,
455 product=cls.shift.product_list.product_items.get(product=cls.wine),
456 amount=2,
457 )
458 cls.o4 = Order.objects.create(shift=cls.shift)
459 OrderItem.objects.create(
460 order=cls.o4,
461 product=cls.shift.product_list.product_items.get(product=cls.wine),
462 amount=2,
463 )
464 cls.o5 = Order.objects.create(shift=cls.shift)
465 OrderItem.objects.create(
466 order=cls.o5,
467 product=cls.shift.product_list.product_items.get(product=cls.beer),
468 amount=2,
469 )
470 OrderItem.objects.create(
471 order=cls.o5,
472 product=cls.shift.product_list.product_items.get(product=cls.wine),
473 amount=2,
474 )
475 cls.o4.payment = create_payment(
476 cls.o4, processed_by=cls.user, pay_type=Payment.CASH
477 )
478 cls.o4.save()
479 cls.o5.payment = create_payment(
480 cls.o5, processed_by=cls.user, pay_type=Payment.CASH
481 )
482 cls.o5.save()
483 cls.o6 = Order.objects.create(shift=cls.shift)
484 OrderItem.objects.create(
485 order=cls.o6,
486 product=cls.shift.product_list.product_items.get(product=cls.soda),
487 amount=2,
488 total=1,
489 )
491 cls.cie = Committee.objects.get(pk=1)
492 MemberGroupMembership.objects.create(group=cls.cie, member=cls.user)
493 content_type = ContentType.objects.get_for_model(Shift)
494 permission1 = Permission.objects.get(
495 content_type=content_type, codename="add_shift"
496 )
497 permission2 = Permission.objects.get(
498 content_type=content_type, codename="change_shift"
499 )
500 permission3 = Permission.objects.get(
501 content_type=content_type, codename="delete_shift"
502 )
503 permission4 = Permission.objects.get(
504 content_type=content_type, codename="view_shift"
505 )
506 cls.cie.permissions.add(permission1)
507 cls.cie.permissions.add(permission2)
508 cls.cie.permissions.add(permission3)
509 cls.cie.permissions.add(permission4)
511 def setUp(self) -> None:
512 self.client = Client()
513 self.client.force_login(self.user)
514 self.factory = RequestFactory()
515 self.site = AdminSite()
516 self.admin = ShiftAdmin(Shift, admin_site=self.site)
517 self.rf = RequestFactory()
519 self.client.logout()
520 self.client.force_login(self.user)
522 def test_change_form_view_rendering_correctly(self) -> None:
523 response = self.client.get(f"/admin/sales/shift/{self.shift.id}/change/")
524 self.assertEqual(200, response.status_code)
526 def test_change_list_view_rendering_correctly(self) -> None:
527 response = self.client.get("/admin/sales/shift/")
528 self.assertEqual(200, response.status_code)
530 def test_view_permissions(self):
531 with self.subTest("View as super user"):
532 request = self.rf.get(
533 reverse("admin:sales_shift_change", args=[self.shift.pk])
534 )
535 request.user = self.user
536 request.member = self.user
537 self.assertTrue(self.admin.has_view_permission(request, self.shift))
539 with self.subTest("View without permissions"):
540 self.user.is_superuser = False
541 self.user.save()
542 self.client.logout()
543 self.client.force_login(self.user)
544 request = self.rf.get(
545 reverse("admin:sales_shift_change", args=[self.shift.pk])
546 )
547 request.user = self.user
548 request.member = self.user
549 self.assertFalse(self.admin.has_view_permission(request, self.shift))
551 with self.subTest("View as shift manager"):
552 self.shift.managers.add(self.cie)
553 self.shift.save()
554 self.client.logout()
555 self.client.force_login(self.user)
556 request = self.rf.get(
557 reverse("admin:sales_shift_change", args=[self.shift.pk])
558 )
559 request.user = self.user
560 request.member = self.user
561 self.assertTrue(self.admin.has_view_permission(request, self.shift))
563 def has_change_permission(self):
564 with self.subTest("Change as super user"):
565 request = self.rf.get(
566 reverse("admin:sales_shift_change", args=[self.shift.pk])
567 )
568 request.user = self.user
569 request.member = self.user
570 self.assertTrue(self.admin.has_change_permission(request, self.shift))
572 with self.subTest("Change without permissions"):
573 self.user.is_superuser = False
574 self.user.save()
575 self.client.logout()
576 self.client.force_login(self.user)
577 request = self.rf.get(
578 reverse("admin:sales_shift_change", args=[self.shift.pk])
579 )
580 request.user = self.user
581 request.member = self.user
582 self.assertFalse(self.admin.has_change_permission(request, self.shift))
584 with self.subTest("Change as shift manager"):
585 self.shift.managers.add(self.cie)
586 self.shift.save()
587 self.client.logout()
588 self.client.force_login(self.user)
589 request = self.rf.get(
590 reverse("admin:sales_shift_change", args=[self.shift.pk])
591 )
592 request.user = self.user
593 request.member = self.user
594 self.assertTrue(self.admin.has_change_permission(request, self.shift))
596 def test_change_permission_locked(self):
597 self.shift.locked = True
598 self.shift.save()
600 request = self.rf.get(reverse("admin:sales_shift_change", args=[self.shift.pk]))
601 request.user = self.user
602 request.member = self.user
603 self.assertFalse(self.admin.has_change_permission(request, self.shift))
605 def test_delete_permissions(self):
606 with self.subTest("Delete as super user"):
607 request = self.rf.get(
608 reverse("admin:sales_shift_delete", args=[self.shift.pk])
609 )
610 request.user = self.user
611 request.member = self.user
612 self.assertTrue(self.admin.has_delete_permission(request, self.shift))
614 with self.subTest("Delete without permissions"):
615 self.user.is_superuser = False
616 self.user.save()
617 self.client.logout()
618 self.client.force_login(self.user)
619 request = self.rf.get(
620 reverse("admin:sales_shift_delete", args=[self.shift.pk])
621 )
622 request.user = self.user
623 request.member = self.user
624 self.assertFalse(self.admin.has_delete_permission(request, self.shift))
626 with self.subTest("Delete as shift manager"):
627 self.shift.managers.add(self.cie)
628 self.shift.save()
629 self.client.logout()
630 self.client.force_login(self.user)
631 request = self.rf.get(
632 reverse("admin:sales_shift_delete", args=[self.shift.pk])
633 )
634 request.user = self.user
635 request.member = self.user
636 self.assertTrue(self.admin.has_delete_permission(request, self.shift))