Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

test_offers.py 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. from decimal import Decimal as D, ROUND_HALF_UP
  2. from django.test import TestCase, RequestFactory
  3. from django.urls import reverse
  4. from django.conf import settings
  5. from oscar.core.loading import get_model, get_class, get_classes
  6. from oscar.test.factories import UserFactory
  7. Basket = get_model("basket", "Basket")
  8. Product = get_model("catalogue", "Product")
  9. factory = RequestFactory()
  10. Applicator = get_class("offer.applicator", "Applicator")
  11. Selector, UK = get_classes("partner.strategy", ["Selector", "UK"])
  12. class UKSelector(Selector):
  13. def strategy(self, request=None, user=None, **kwargs):
  14. return UK(request)
  15. def money(amount):
  16. return amount.quantize(D("0.01"), ROUND_HALF_UP)
  17. def get_user_basket(user, request):
  18. editable_baskets = Basket.objects.filter(status__in=["Open", "Saved"])
  19. basket, __ = editable_baskets.get_or_create(owner=user)
  20. basket.strategy = UKSelector().strategy(request=request, user=user)
  21. basket.reset_offer_applications()
  22. if not basket.is_empty:
  23. Applicator().apply(basket, user, request)
  24. request.session[settings.OSCAR_BASKET_COOKIE_OPEN] = basket.pk
  25. request.session.save()
  26. return basket
  27. class OfferTest(TestCase):
  28. fixtures = ["catalogue", "offer"]
  29. def check_general_truths(self, basket):
  30. inverse_tax_multiplier = D(1) / (D(1) + UK.rate)
  31. calculated_total_excl_tax = money(
  32. inverse_tax_multiplier * basket.total_incl_tax
  33. )
  34. self.assertEqual(
  35. calculated_total_excl_tax,
  36. basket.total_excl_tax,
  37. "The total price without tax should conform to the standard "
  38. "formula for calculating tax (as a percentage)",
  39. )
  40. self.assertAlmostEqual(
  41. basket.total_excl_tax_excl_discounts / basket.total_incl_tax_excl_discounts,
  42. basket.total_excl_tax / basket.total_incl_tax,
  43. 4,
  44. "The ratio of price with tax and without tax should be the same for the "
  45. "price with and without discounts. If that is not the case people would "
  46. "be able to change the tax they must pay by gaming the discount.",
  47. )
  48. self.assertNotAlmostEqual(
  49. basket.total_excl_tax_excl_discounts - basket.total_excl_tax,
  50. basket.total_incl_tax_excl_discounts - basket.total_incl_tax,
  51. 2,
  52. "The discount over the total excluding tax can never be the same as "
  53. "the discount over the total including tax. Otherwise our tax rate"
  54. "would not be linear over the amount.",
  55. )
  56. self.assertEqual(
  57. basket.total_excl_tax + basket.total_tax,
  58. basket.total_incl_tax,
  59. "The tax summation should amount to the total_incl_tax"
  60. )
  61. def test_offer_incl_tax(self):
  62. "The offer should be calculated as if it was declared including tax"
  63. with self.settings(OSCAR_OFFERS_INCL_TAX=True):
  64. self.assertEqual(Basket.objects.count(), 0)
  65. admin = UserFactory()
  66. self.client.force_login(admin)
  67. # throw an item in the basket
  68. basket_add_url = reverse("basket:add", args=(2,))
  69. body = {"quantity": 1}
  70. response = self.client.post(basket_add_url, body)
  71. # throw another item in the basket so the offer activates
  72. basket_add_url = reverse("basket:add", args=(3,))
  73. body = {"quantity": 2}
  74. response = self.client.post(basket_add_url, body)
  75. request = factory.post(basket_add_url, body)
  76. request.user = admin
  77. request.session = self.client.session
  78. basket = get_user_basket(admin, request)
  79. self.assertEqual(response.status_code, 302)
  80. self.assertEqual(Basket.objects.count(), 1)
  81. # now go and check if the offer was applied correctly
  82. self.assertEqual(
  83. basket.total_incl_tax_excl_discounts - basket.total_incl_tax,
  84. D("10.00"),
  85. "The offer should be a flat 10 pound discount on the total "
  86. "including tax",
  87. )
  88. self.assertEqual(
  89. basket.total_discount,
  90. D("10.00"),
  91. "The total discount property should properly reflect the discount"
  92. "applied.",
  93. )
  94. self.check_general_truths(basket)
  95. def test_offer_excl_tax(self):
  96. "The offer should be calculated as if it was declared excluding tax"
  97. with self.settings(OSCAR_OFFERS_INCL_TAX=False):
  98. self.assertEqual(Basket.objects.count(), 0)
  99. admin = UserFactory()
  100. self.client.force_login(admin)
  101. # throw an item in the basket
  102. basket_add_url = reverse("basket:add", args=(2,))
  103. body = {"quantity": 1}
  104. response = self.client.post(basket_add_url, body)
  105. # throw another item in the basket so the offer activates
  106. basket_add_url = reverse("basket:add", args=(3,))
  107. body = {"quantity": 2}
  108. response = self.client.post(basket_add_url, body)
  109. # now go and check if dat offer was handled correctly
  110. request = factory.post(basket_add_url, body)
  111. request.user = admin
  112. request.session = self.client.session
  113. basket = get_user_basket(admin, request)
  114. self.assertEqual(response.status_code, 302)
  115. self.assertEqual(Basket.objects.count(), 1)
  116. # now go and check if the offer was applied correctly
  117. self.assertEqual(
  118. basket.total_excl_tax_excl_discounts - basket.total_excl_tax,
  119. D("10.00"),
  120. "The offer should be a flat 10 pound discount on the total "
  121. "excluding tax",
  122. )
  123. self.assertEqual(
  124. basket.total_discount,
  125. D("10.00"),
  126. "The total discount property should properly reflect the discount"
  127. "applied.",
  128. )
  129. self.check_general_truths(basket)