Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

test_utils.py 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. import pytest
  2. from oscar.apps.offer import models
  3. from oscar.apps.offer.applicator import Applicator
  4. from oscar.test.factories import (
  5. BasketFactory, ConditionalOfferFactory, ProductFactory)
  6. @pytest.fixture
  7. def filled_basket():
  8. basket = BasketFactory()
  9. product1 = ProductFactory()
  10. product2 = ProductFactory()
  11. basket.add_product(product1, quantity=10)
  12. basket.add_product(product2, quantity=20)
  13. return basket
  14. @pytest.fixture
  15. def single_offer():
  16. return ConditionalOfferFactory(
  17. condition__range__includes_all_products=True,
  18. condition__value=1,
  19. benefit__range__includes_all_products=True,
  20. benefit__max_affected_items=1,
  21. name='offer1',
  22. exclusive=False,
  23. )
  24. @pytest.fixture
  25. def multi_offers():
  26. offer1 = ConditionalOfferFactory(
  27. condition__range__includes_all_products=True,
  28. benefit__range__includes_all_products=True,
  29. name='offer1',
  30. exclusive=False,
  31. )
  32. offer2 = ConditionalOfferFactory(
  33. condition__range__includes_all_products=True,
  34. benefit__range__includes_all_products=True,
  35. name='offer2',
  36. exclusive=False
  37. )
  38. offer3 = ConditionalOfferFactory(
  39. condition__range__includes_all_products=True,
  40. benefit__range__includes_all_products=True,
  41. name='offer3',
  42. exclusive=False
  43. )
  44. return offer1, offer2, offer3
  45. @pytest.mark.django_db
  46. class TestLineOfferConsumer:
  47. def test_consumed_no_offer(self, filled_basket):
  48. for line in filled_basket.all_lines():
  49. assert line.consumer.consumed() == 0
  50. def test_available_with_offer(self):
  51. basket = BasketFactory()
  52. product1 = ProductFactory()
  53. product2 = ProductFactory()
  54. basket.add_product(product1, quantity=1)
  55. basket.add_product(product2, quantity=10)
  56. benefit = models.Benefit(
  57. type=models.Benefit.PERCENTAGE,
  58. value=10,
  59. max_affected_items=5,
  60. )
  61. benefit.save()
  62. offer1 = ConditionalOfferFactory(name='offer1', benefit=benefit)
  63. lines = basket.all_lines()
  64. assert lines[0].consumer.available(offer1) == 1
  65. assert lines[1].consumer.available(offer1) == 10
  66. def test_consumed_with_offer(self, filled_basket):
  67. offer1 = ConditionalOfferFactory(name='offer1')
  68. offer2 = ConditionalOfferFactory(name='offer2')
  69. offer1.exclusive = False
  70. offer2.exclusive = False
  71. for line in filled_basket.all_lines():
  72. assert line.consumer.consumed(offer1) == 0
  73. assert line.consumer.consumed(offer2) == 0
  74. line1 = filled_basket.all_lines()[0]
  75. line2 = filled_basket.all_lines()[1]
  76. line1.consumer.consume(1, offer1)
  77. assert line1.consumer.consumed() == 1
  78. assert line1.consumer.consumed(offer1) == 1
  79. assert line1.consumer.consumed(offer2) == 0
  80. line1.consumer.consume(9, offer1)
  81. assert line1.consumer.consumed() == line1.quantity
  82. assert line1.consumer.consumed(offer1) == line1.quantity
  83. assert line1.consumer.consumed(offer2) == 0
  84. line1.consumer.consume(99, offer1)
  85. assert line1.consumer.consumed(offer1) == line1.quantity
  86. assert line1.consumer.consumed(offer2) == 0
  87. line1.consumer.consume(1, offer2)
  88. line2.consumer.consume(1, offer2)
  89. assert line1.consumer.consumed(offer2) == 1
  90. assert line2.consumer.consumed(offer2) == 1
  91. def test_consume(self, filled_basket):
  92. line = filled_basket.all_lines()[0]
  93. line.consume(1)
  94. assert line.quantity_with_discount == 1
  95. line.consume(99)
  96. assert line.quantity_with_discount == 10
  97. def test_consumed_with_exclusive_offer_1(self, filled_basket):
  98. offer1 = ConditionalOfferFactory(name='offer1')
  99. offer2 = ConditionalOfferFactory(name='offer2')
  100. offer3 = ConditionalOfferFactory(name='offer3')
  101. offer1.exclusive = True
  102. offer2.exclusive = False
  103. offer3.exclusive = False
  104. for line in filled_basket.all_lines():
  105. assert line.consumer.consumed(offer1) == 0
  106. assert line.consumer.consumed(offer2) == 0
  107. line1, line2 = list(filled_basket.all_lines())
  108. # exclusive offer consumes one item on line1
  109. line1.consumer.consume(1, offer1)
  110. # offer1 is exclusive so that blocks other offers
  111. assert line1.is_available_for_offer_discount(offer2) is False
  112. line1.consumer.consume(99, offer1)
  113. # ran out of room for offer1
  114. assert line1.is_available_for_offer_discount(offer1) is False
  115. # offer2 was never an option
  116. assert line1.is_available_for_offer_discount(offer2) is False
  117. # exclusivity is per line so line2 is available for offer2
  118. line2.consumer.consume(1, offer2)
  119. # nope: exclusive and non-exclusive don't mix
  120. assert line2.is_available_for_offer_discount(offer1) is False
  121. line2.consumer.consume(99, offer2)
  122. # ran out of room for offer2
  123. assert line2.is_available_for_offer_discount(offer1) is False
  124. # but still room for offer3!
  125. assert line2.is_available_for_offer_discount(offer3) is True
  126. def test_consumed_with_exclusive_offer_2(self, filled_basket):
  127. offer1 = ConditionalOfferFactory(name='offer1')
  128. offer2 = ConditionalOfferFactory(name='offer2')
  129. offer3 = ConditionalOfferFactory(name='offer3')
  130. offer1.exclusive = True
  131. offer2.exclusive = False
  132. offer3.exclusive = False
  133. for line in filled_basket.all_lines():
  134. assert line.consumer.consumed(offer1) == 0
  135. assert line.consumer.consumed(offer2) == 0
  136. line1, line2 = list(filled_basket.all_lines())
  137. # exclusive offer consumes one item on line1
  138. line1.consumer.consume(1, offer1)
  139. remaining1 = line1.quantity - 1
  140. assert line1.quantity_with_offer_discount(offer1) == 1
  141. assert line1.quantity_with_offer_discount(offer2) == 0
  142. assert line1.quantity_with_offer_discount(offer3) == 0
  143. assert line1.quantity_without_offer_discount(offer1) == remaining1
  144. assert line1.quantity_without_offer_discount(offer2) == 0
  145. assert line1.quantity_without_offer_discount(offer3) == 0
  146. # exclusive offer consumes all items on line1
  147. line1.consumer.consume(remaining1, offer1)
  148. assert line1.quantity_with_offer_discount(offer1) == line1.quantity
  149. assert line1.quantity_with_offer_discount(offer2) == 0
  150. assert line1.quantity_with_offer_discount(offer3) == 0
  151. assert line1.quantity_without_offer_discount(offer1) == 0
  152. assert line1.quantity_without_offer_discount(offer2) == 0
  153. assert line1.quantity_without_offer_discount(offer3) == 0
  154. # non-exclusive offer consumes one item on line2
  155. line2.consumer.consume(1, offer2)
  156. remaining2 = line2.quantity - 1
  157. assert line2.quantity_with_offer_discount(offer1) == 0
  158. assert line2.quantity_with_offer_discount(offer2) == 1
  159. assert line2.quantity_with_offer_discount(offer3) == 0
  160. assert line2.quantity_without_offer_discount(offer1) == 0
  161. assert line2.quantity_without_offer_discount(offer2) == remaining2
  162. assert line2.quantity_without_offer_discount(offer3) == line2.quantity
  163. # non-exclusive offer consumes all items on line2
  164. line2.consumer.consume(remaining2, offer2)
  165. assert line2.quantity_with_offer_discount(offer1) == 0
  166. assert line2.quantity_with_offer_discount(offer2) == line2.quantity
  167. assert line2.quantity_with_offer_discount(offer3) == 0
  168. assert line2.quantity_without_offer_discount(offer1) == 0
  169. assert line2.quantity_without_offer_discount(offer2) == 0
  170. assert line2.quantity_without_offer_discount(offer3) == line2.quantity
  171. def test_consumed_by_application(self, filled_basket, single_offer):
  172. basket = filled_basket
  173. Applicator().apply(basket)
  174. assert len(basket.offer_applications.offer_discounts) == 1
  175. assert [x.consumer.consumed() for x in basket.all_lines()] == [1, 0]
  176. def test_consumed_with_combined_offer(self, filled_basket):
  177. offer1 = ConditionalOfferFactory(name='offer1')
  178. offer2 = ConditionalOfferFactory(name='offer2')
  179. offer3 = ConditionalOfferFactory(name='offer3')
  180. offer4 = ConditionalOfferFactory(name='offer4')
  181. offer1.exclusive = True
  182. offer2.exclusive = False
  183. offer3.exclusive = False
  184. offer4.exclusive = False
  185. offer2.combinations.add(offer3)
  186. assert offer3 in offer2.combined_offers
  187. assert offer2 in offer3.combined_offers
  188. for line in filled_basket.all_lines():
  189. assert line.consumer.consumed(offer1) == 0
  190. assert line.consumer.consumed(offer2) == 0
  191. assert line.consumer.consumed(offer3) == 0
  192. line1 = filled_basket.all_lines()[0]
  193. # combinable offer consumes one item of line1
  194. line1.consumer.consume(1, offer2)
  195. remaining1 = line1.quantity - 1
  196. assert line1.quantity_with_offer_discount(offer1) == 0
  197. assert line1.quantity_with_offer_discount(offer2) == 1
  198. assert line1.quantity_with_offer_discount(offer3) == 0
  199. assert line1.quantity_with_offer_discount(offer4) == 0
  200. assert line1.quantity_without_offer_discount(offer1) == 0
  201. assert line1.quantity_without_offer_discount(offer2) == remaining1
  202. assert line1.quantity_without_offer_discount(offer3) == line1.quantity
  203. assert line1.quantity_without_offer_discount(offer4) == 0
  204. # combinable offer consumes one item of line1
  205. line1.consumer.consume(1, offer3)
  206. assert line1.quantity_with_offer_discount(offer1) == 0
  207. assert line1.quantity_with_offer_discount(offer2) == 1
  208. assert line1.quantity_with_offer_discount(offer3) == 1
  209. assert line1.quantity_with_offer_discount(offer4) == 0
  210. assert line1.quantity_without_offer_discount(offer1) == 0
  211. assert line1.quantity_without_offer_discount(offer2) == remaining1
  212. assert line1.quantity_without_offer_discount(offer3) == remaining1
  213. assert line1.quantity_without_offer_discount(offer4) == 0
  214. # combinable offer consumes all items of line1
  215. line1.consumer.consume(remaining1, offer2)
  216. assert line1.quantity_with_offer_discount(offer1) == 0
  217. assert line1.quantity_with_offer_discount(offer2) == line1.quantity
  218. assert line1.quantity_with_offer_discount(offer3) == 1
  219. assert line1.quantity_with_offer_discount(offer4) == 0
  220. assert line1.quantity_without_offer_discount(offer1) == 0
  221. assert line1.quantity_without_offer_discount(offer2) == 0
  222. assert line1.quantity_without_offer_discount(offer3) == remaining1
  223. assert line1.quantity_without_offer_discount(offer4) == 0