You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_event_handler.py 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. from decimal import Decimal as D
  2. from django.test import TestCase
  3. from oscar.apps.order import exceptions, models
  4. from oscar.apps.order.processing import EventHandler
  5. from oscar.test import factories
  6. from oscar.test.basket import add_product
  7. class TestEventHandler(TestCase):
  8. def setUp(self):
  9. self.order = factories.create_order()
  10. self.handler = EventHandler()
  11. self.shipped = models.ShippingEventType.objects.create(name="Shipped")
  12. self.returned = models.ShippingEventType.objects.create(name="Returned")
  13. def test_creates_shipping_events_correctly(self):
  14. self.handler.handle_shipping_event(
  15. self.order, self.shipped, self.order.lines.all(), [1]
  16. )
  17. events = self.order.shipping_events.all()
  18. self.assertEqual(1, len(events))
  19. event = events[0]
  20. self.assertEqual("Shipped", event.event_type.name)
  21. def test_verifies_lines_has_passed_shipping_event(self):
  22. basket = factories.create_basket(empty=True)
  23. add_product(basket, D("10.00"), 5)
  24. order = factories.create_order(basket=basket)
  25. lines = order.lines.all()
  26. self.handler.handle_shipping_event(order, self.shipped, lines, [4])
  27. self.assertTrue(
  28. self.handler.have_lines_passed_shipping_event(
  29. order, lines, [3], self.shipped
  30. )
  31. )
  32. self.assertTrue(
  33. self.handler.have_lines_passed_shipping_event(
  34. order, lines, [4], self.shipped
  35. )
  36. )
  37. self.assertFalse(
  38. self.handler.have_lines_passed_shipping_event(
  39. order, lines, [5], self.shipped
  40. )
  41. )
  42. def test_prevents_event_quantities_higher_than_original_line(self):
  43. basket = factories.create_basket(empty=True)
  44. add_product(basket, D("10.00"), 5)
  45. order = factories.create_order(basket=basket)
  46. # First shipping event
  47. lines = order.lines.all()
  48. self.handler.handle_shipping_event(order, self.shipped, lines, [4])
  49. with self.assertRaises(exceptions.InvalidShippingEvent):
  50. self.handler.handle_shipping_event(order, self.shipped, lines, [4])
  51. def test_are_stock_allocations_available(self):
  52. product_class = factories.ProductClassFactory(
  53. requires_shipping=False, track_stock=True
  54. )
  55. product = factories.ProductFactory(product_class=product_class)
  56. basket = factories.create_basket(empty=True)
  57. add_product(basket, D("10.00"), 5, product=product)
  58. order = factories.create_order(basket=basket)
  59. line = order.lines.get()
  60. self.assertEqual(
  61. self.handler.are_stock_allocations_available([line], [line.quantity]),
  62. True,
  63. )
  64. self.assertEqual(
  65. self.handler.are_stock_allocations_available([line], [105]),
  66. False,
  67. )
  68. def test_are_stock_allocations_available_track_stock_off(self):
  69. product_class = factories.ProductClassFactory(
  70. requires_shipping=False, track_stock=False
  71. )
  72. product = factories.ProductFactory(product_class=product_class)
  73. basket = factories.create_basket(empty=True)
  74. add_product(basket, D("10.00"), 5, product=product)
  75. order = factories.create_order(basket=basket)
  76. line = order.lines.get()
  77. self.assertEqual(
  78. self.handler.are_stock_allocations_available([line], [105]),
  79. True,
  80. )
  81. def test_consume_stock_allocations_track_stock_on(self):
  82. product_class = factories.ProductClassFactory(
  83. requires_shipping=False, track_stock=True
  84. )
  85. product = factories.ProductFactory(product_class=product_class)
  86. basket = factories.create_basket(empty=True)
  87. add_product(basket, D("10.00"), 5, product=product)
  88. order = factories.create_order(basket=basket)
  89. stockrecord = product.stockrecords.get()
  90. num_in_stock = stockrecord.num_in_stock
  91. num_allocated = stockrecord.num_allocated
  92. lines = order.lines.all()
  93. self.handler.consume_stock_allocations(
  94. order, lines, [line.quantity for line in lines]
  95. )
  96. stockrecord.refresh_from_db()
  97. self.assertEqual(
  98. stockrecord.num_allocated,
  99. num_allocated - 5,
  100. "Allocated stock should have decreased, but didn't.",
  101. )
  102. self.assertEqual(
  103. stockrecord.num_in_stock,
  104. num_in_stock - 5,
  105. "Stock should have decreased, but didn't.",
  106. )
  107. def test_consume_stock_allocations_track_stock_off(self):
  108. product_class = factories.ProductClassFactory(
  109. requires_shipping=False, track_stock=False
  110. )
  111. product = factories.ProductFactory(product_class=product_class)
  112. basket = factories.create_basket(empty=True)
  113. add_product(basket, D("10.00"), 5, product=product)
  114. order = factories.create_order(basket=basket)
  115. stockrecord = product.stockrecords.get()
  116. num_in_stock = stockrecord.num_in_stock
  117. num_allocated = stockrecord.num_allocated
  118. lines = order.lines.all()
  119. self.handler.consume_stock_allocations(
  120. order, lines, [line.quantity for line in lines]
  121. )
  122. stockrecord.refresh_from_db()
  123. self.assertEqual(
  124. stockrecord.num_allocated,
  125. num_allocated,
  126. "Allocated stock shouldn't have changed, but it did.",
  127. )
  128. self.assertEqual(
  129. stockrecord.num_in_stock,
  130. num_in_stock,
  131. "Stock shouldn't have changed, but it did.",
  132. )
  133. def test_consume_stock_allocations_without_line_arguments(self):
  134. product_class = factories.ProductClassFactory(
  135. requires_shipping=False, track_stock=True
  136. )
  137. product = factories.ProductFactory(product_class=product_class)
  138. basket = factories.create_basket(empty=True)
  139. add_product(basket, D("10.00"), 5, product=product)
  140. order = factories.create_order(basket=basket)
  141. stockrecord = product.stockrecords.get()
  142. num_in_stock = stockrecord.num_in_stock
  143. num_allocated = stockrecord.num_allocated
  144. self.handler.consume_stock_allocations(order)
  145. stockrecord.refresh_from_db()
  146. self.assertEqual(
  147. stockrecord.num_allocated,
  148. num_allocated - 5,
  149. "Allocated stock should have decreased, but didn't.",
  150. )
  151. self.assertEqual(
  152. stockrecord.num_in_stock,
  153. num_in_stock - 5,
  154. "Stock should have decreased, but didn't.",
  155. )
  156. def test_cancel_stock_allocations_track_stock_on(self):
  157. product_class = factories.ProductClassFactory(
  158. requires_shipping=False, track_stock=True
  159. )
  160. product = factories.ProductFactory(product_class=product_class)
  161. basket = factories.create_basket(empty=True)
  162. add_product(basket, D("10.00"), 5, product=product)
  163. order = factories.create_order(basket=basket)
  164. stockrecord = product.stockrecords.get()
  165. num_allocated = stockrecord.num_allocated
  166. lines = order.lines.all()
  167. self.handler.cancel_stock_allocations(
  168. order, lines, [line.quantity for line in lines]
  169. )
  170. stockrecord.refresh_from_db()
  171. self.assertEqual(
  172. stockrecord.num_allocated,
  173. num_allocated - 5,
  174. "Allocated stock should have decreased, but didn't.",
  175. )
  176. def test_cancel_stock_allocations_track_stock_off(self):
  177. product_class = factories.ProductClassFactory(
  178. requires_shipping=False, track_stock=False
  179. )
  180. product = factories.ProductFactory(product_class=product_class)
  181. basket = factories.create_basket(empty=True)
  182. add_product(basket, D("10.00"), 5, product=product)
  183. order = factories.create_order(basket=basket)
  184. stockrecord = product.stockrecords.get()
  185. num_allocated = stockrecord.num_allocated
  186. lines = order.lines.all()
  187. self.handler.cancel_stock_allocations(
  188. order, lines, [line.quantity for line in lines]
  189. )
  190. stockrecord.refresh_from_db()
  191. self.assertEqual(
  192. stockrecord.num_allocated,
  193. num_allocated,
  194. "Allocated stock shouldn't have changed, but it did.",
  195. )
  196. def test_cancel_stock_allocations_without_line_arguments(self):
  197. product_class = factories.ProductClassFactory(
  198. requires_shipping=False, track_stock=True
  199. )
  200. product = factories.ProductFactory(product_class=product_class)
  201. basket = factories.create_basket(empty=True)
  202. add_product(basket, D("10.00"), 5, product=product)
  203. order = factories.create_order(basket=basket)
  204. stockrecord = product.stockrecords.get()
  205. num_allocated = stockrecord.num_allocated
  206. self.handler.cancel_stock_allocations(order)
  207. stockrecord.refresh_from_db()
  208. self.assertEqual(
  209. stockrecord.num_allocated,
  210. num_allocated - 5,
  211. "Allocated stock should have decreased, but didn't.",
  212. )
  213. class TestTotalCalculation(TestCase):
  214. def setUp(self):
  215. self.order = factories.create_order()
  216. self.handler = EventHandler()
  217. basket = factories.create_basket(empty=True)
  218. add_product(basket, D("10.00"), 5)
  219. self.order = factories.create_order(basket=basket)
  220. self.settled = models.PaymentEventType.objects.create(name="Settled")
  221. def test_normal_payment_sequence(self):
  222. # First payment event
  223. lines, line_quantities = self.order.lines.all(), [2]
  224. total = self.handler.calculate_payment_event_subtotal(
  225. self.settled, lines, line_quantities
  226. )
  227. self.assertEqual(2 * D("10.00"), total)
  228. self.handler.create_payment_event(
  229. self.order, self.settled, total, lines, line_quantities
  230. )
  231. # Second payment
  232. line_quantities = [3]
  233. total = self.handler.calculate_payment_event_subtotal(
  234. self.settled, lines, line_quantities
  235. )
  236. self.assertEqual(3 * D("10.00"), total)
  237. def test_invalid_payment_sequence(self):
  238. lines, line_quantities = self.order.lines.all(), [2]
  239. total = self.handler.calculate_payment_event_subtotal(
  240. self.settled, lines, line_quantities
  241. )
  242. self.assertEqual(2 * D("10.00"), total)
  243. self.handler.create_payment_event(
  244. self.order, self.settled, total, lines, line_quantities
  245. )
  246. with self.assertRaises(exceptions.InvalidPaymentEvent):
  247. self.handler.calculate_payment_event_subtotal(
  248. self.settled, self.order.lines.all(), [4]
  249. )