diff --git a/boutique/models.py b/boutique/models.py index d6c2e63ac517f47a122f907138b9c825896f9360..87ae9088991019c66e7b1059551727efe95fb2c4 100644 --- a/boutique/models.py +++ b/boutique/models.py @@ -90,6 +90,10 @@ class Item(models.Model): return True return False + @property + def is_cotiz(self) -> bool: + return self.action in {"full_cotiz", "half_cotiz"} + @property def post_payment(self) -> Callable[["OrderItem"], None]: actions_methods = { @@ -238,6 +242,10 @@ class Order(models.Model): except Payment.DoesNotExist: return False + @property + def contains_cotiz(self) -> bool: + return any(i.item.is_cotiz for i in self.items.all()) + def compute_price(self) -> None: self.price = Decimal("0.00") for item in self.items.all(): @@ -339,7 +347,8 @@ class OrderItem(models.Model): def get_final_price(self) -> Decimal: is_contributor = Contributor.is_contributor(self.order.user) - if is_contributor: + # If the order contains a cotiz, we should treat it as a contributor too + if is_contributor or self.order.contains_cotiz: return self.get_price_contributor() else: return self.get_price() diff --git a/boutique/tests/test_models.py b/boutique/tests/test_models.py index d24b6e165e145a5eeafffcc0d9e81020e569e0c9..26c528bbbe957c0a44c1854e4682c4d85474ca47 100644 --- a/boutique/tests/test_models.py +++ b/boutique/tests/test_models.py @@ -31,6 +31,28 @@ class ItemTest(PaymentTestCase, OrderItemTestCase): pack = self.create_pack() self.assertTrue(pack.is_pack) + def test_is_cotiz(self) -> None: + """ + Tests that Item.is_cotiz is only true when the action is full_cotiz or half_cotiz + """ + item = self.create_item() + + for action in {"no", "event"}: + with self.subTest(action=action): + item.action = action + self.assertFalse(item.is_cotiz) + item.save() + item.refresh_from_db() + self.assertFalse(item.is_cotiz) + + for action in {"full_cotiz", "half_cotiz"}: + with self.subTest(action=action): + item.action = action + self.assertTrue(item.is_cotiz) + item.save() + item.refresh_from_db() + self.assertTrue(item.is_cotiz) + def test_single_product_is_not_pack(self) -> None: """Tests that Item.is_pack is false when Item is not a pack""" product = self.create_item() @@ -572,8 +594,23 @@ class OrderItemTest(OrderItemTestCase): oi.refresh_from_db() self.assertEqual(oi.get_final_price(), oi.get_price_contributor()) + cotiz = self.create_item() + cotiz.action = "half_cotiz" + cotiz.save() + + cotiz.add_to_order(self.order) + self.order.refresh_from_db() + oi.refresh_from_db() + + self.assertEqual(oi.get_final_price(), oi.get_price_contributor()) + def test_get_final_price_non_contributor(self) -> None: - """Tests OrderItem.get_final_price for a non contributor""" + """ + Tests OrderItem.get_final_price for a non contributor + + Tests with and without a cotiz in the order + With cotiz should apply contributor price + """ item = self.create_item() oi = OrderItemTest.create_orderitem(self.order, item) @@ -584,6 +621,16 @@ class OrderItemTest(OrderItemTestCase): oi.refresh_from_db() self.assertEqual(oi.get_final_price(), oi.get_price()) + cotiz = self.create_item() + cotiz.action = "half_cotiz" + cotiz.save() + + cotiz.add_to_order(self.order) + self.order.refresh_from_db() + oi.refresh_from_db() + + self.assertEqual(oi.get_final_price(), oi.get_price_contributor()) + def test_post_payment(self) -> None: item = self.create_item() oi = self.create_orderitem(self.order, item) @@ -624,6 +671,42 @@ class OrderTest(PaymentTestCase, OrderItemTestCase): self.assertTrue(self.order.paid) + def test_contains_cotiz_single_items(self) -> None: + """Tests that Order.contains_cotiz is able to detect single cotiz""" + item = self.create_item() + cotiz = self.create_item() + cotiz.action = "full_cotiz" + cotiz.save() + cotiz.refresh_from_db() + + self.assertFalse(self.order.contains_cotiz) + + item.add_to_order(self.order) + self.assertFalse(self.order.contains_cotiz) + + cotiz.add_to_order(self.order) + self.assertTrue(self.order.contains_cotiz) + + def test_contains_cotiz_packs(self) -> None: + """Tests that Order.contains_cotiz is able to detect cotiz in packs""" + pack = self.create_pack() + cpack = self.create_item() + cotiz = self.create_item() + cotiz.action = "full_cotiz" + cotiz.save() + cotiz.refresh_from_db() + cpack.children.add(cotiz) + cpack.save() + cpack.refresh_from_db() + + self.assertFalse(self.order.contains_cotiz) + + pack.add_to_order(self.order) + self.assertFalse(self.order.contains_cotiz) + + cpack.add_to_order(self.order) + self.assertTrue(self.order.contains_cotiz) + @patch("boutique.models.OrderItem.post_payment") def test_post_payment(self, oi_post_payment) -> None: item = self.create_item() diff --git a/boutique/tests/test_views.py b/boutique/tests/test_views.py index 465f8104103e4aafeb033e78dc62423470b6c263..0dcee9c0ca82a179b178fecad74f0cfa46fc59eb 100644 --- a/boutique/tests/test_views.py +++ b/boutique/tests/test_views.py @@ -3,6 +3,7 @@ from datetime import timedelta from decimal import Decimal from os import path from typing import Tuple +from unittest.mock import Mock from django.urls import reverse from django.utils import timezone @@ -23,6 +24,7 @@ from ..views import DeliveryView from ..views import ItemCreateView from ..views import ItemEditView from ..views import ItemListView +from ..views import OrderEditView class ItemListViewTest(ItemTestCase, UserTestCase): @@ -394,6 +396,111 @@ class ManageCategoryViewTest(UserTestCase): self.assertTrue(len(form.errors) > 0) +class OrderEditViewTest(OrderItemTestCase): + def test_get_object(self) -> None: + view = OrderEditView() + view.request = Mock() + view.request.user = self.user + + self.assertEqual(view.get_object(), Order.objects.get_current_order(self.user)) + + @user_logged_in + def test_context_data_user(self) -> None: + url = reverse('boutique:order_edit') + + # Empty order + resp = self.client.get(url) + context = resp.context + + self.assertNotIn("form", context) + self.assertIn("formset", context) + self.assertIn("total_price", context) + self.assertIn("is_contributor", context) + + self.assertFalse(context["is_contributor"]) + + # Item in order + item = self.create_item() + item.add_to_user(self.user) + + resp = self.client.get(url) + context = resp.context + + self.assertNotIn("form", context) + self.assertIn("formset", context) + self.assertIn("total_price", context) + self.assertIn("is_contributor", context) + + self.assertEqual(context["total_price"], item.price) + self.assertFalse(context["is_contributor"]) + + # Cotiz in order + cotiz = self.create_item() + cotiz.action = "full_cotiz" + cotiz.save() + cotiz.refresh_from_db() + cotiz.add_to_user(self.user) + + resp = self.client.get(url) + context = resp.context + + self.assertNotIn("form", context) + self.assertIn("formset", context) + self.assertIn("total_price", context) + self.assertIn("is_contributor", context) + + self.assertEqual(context["total_price"], cotiz.price_contributor + item.price_contributor) + self.assertTrue(context["is_contributor"]) + + @contrib_user_logged_in + def test_context_data_contrib_user(self) -> None: + url = reverse('boutique:order_edit') + + # Empty order + resp = self.client.get(url) + context = resp.context + + self.assertNotIn("form", context) + self.assertIn("formset", context) + self.assertIn("total_price", context) + self.assertIn("is_contributor", context) + + self.assertTrue(context["is_contributor"]) + + # Item in order + item = self.create_item() + item.add_to_user(self.contributor_user) + + resp = self.client.get(url) + context = resp.context + + self.assertNotIn("form", context) + self.assertIn("formset", context) + self.assertIn("total_price", context) + self.assertIn("is_contributor", context) + + self.assertEqual(context["total_price"], item.price_contributor) + self.assertTrue(context["is_contributor"]) + + # Cotiz in order + cotiz = self.create_item() + cotiz.action = "full_cotiz" + cotiz.save() + cotiz.refresh_from_db() + cotiz.add_to_user(self.contributor_user) + + resp = self.client.get(url) + context = resp.context + + self.assertNotIn("form", context) + self.assertIn("formset", context) + self.assertIn("total_price", context) + self.assertIn("is_contributor", context) + + self.assertEqual(context["total_price"], cotiz.price_contributor + item.price_contributor) + self.assertTrue(context["is_contributor"]) + + class DeliveryViewTest(PaymentTestCase, OrderItemTestCase): """Tests for views.DeliveryView""" diff --git a/boutique/views.py b/boutique/views.py index c9a6fdf8c64c5f9ee01aefddaf429024c823fd53..310374bc8138336faf10fc4287260850792074ce 100644 --- a/boutique/views.py +++ b/boutique/views.py @@ -325,7 +325,7 @@ class OrderEditView(LoginRequiredMixin, UpdateView): kwargs["total_price"] = self.object.price kwargs["is_contributor"] = bde.models.Contributor.is_contributor( self.request.user - ) + ) or self.object.contains_cotiz return kwargs