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_order.py 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. from http import client as http_client
  2. from django.conf import settings
  3. from django.urls import reverse
  4. from oscar.apps.order.models import (
  5. Order, OrderNote, PaymentEvent, PaymentEventType)
  6. from oscar.core.loading import get_model
  7. from oscar.test.factories import (
  8. PartnerFactory, ShippingAddressFactory, SourceTypeFactory,
  9. create_basket, create_order)
  10. from oscar.test.testcases import WebTestCase
  11. Basket = get_model('basket', 'Basket')
  12. Partner = get_model('partner', 'Partner')
  13. ShippingAddress = get_model('order', 'ShippingAddress')
  14. class TestOrderListDashboard(WebTestCase):
  15. is_staff = True
  16. def test_redirects_to_detail_page(self):
  17. order = create_order()
  18. page = self.get(reverse('dashboard:order-list'))
  19. form = page.forms['search_form']
  20. form['order_number'] = order.number
  21. response = form.submit()
  22. self.assertEqual(http_client.FOUND, response.status_code)
  23. def test_downloads_to_csv_without_error(self):
  24. address = ShippingAddressFactory()
  25. create_order(shipping_address=address)
  26. page = self.get(reverse('dashboard:order-list'))
  27. form = page.forms['orders_form']
  28. form['selected_order'].checked = True
  29. form.submit('download_selected')
  30. def test_allows_order_number_search(self):
  31. page = self.get(reverse('dashboard:order-list'))
  32. form = page.forms['search_form']
  33. form['order_number'] = '+'
  34. form.submit()
  35. class PermissionBasedDashboardOrderTestsBase(WebTestCase):
  36. permissions = ['partner.dashboard_access', ]
  37. username = 'user1@example.com'
  38. def setUp(self):
  39. """
  40. Creates two orders. order_in has self.user in it's partner users list.
  41. """
  42. super().setUp()
  43. self.address = ShippingAddressFactory()
  44. self.basket_in = create_basket()
  45. self.basket_out = create_basket()
  46. # replace partner with one that has the user in it's users list
  47. self.partner_in = PartnerFactory(users=[self.user])
  48. stockrecord = self.basket_in.lines.all()[0].stockrecord
  49. stockrecord.partner = self.partner_in
  50. stockrecord.save()
  51. self.order_in = create_order(basket=self.basket_in,
  52. shipping_address=self.address)
  53. self.order_out = create_order(basket=self.basket_out,
  54. shipping_address=self.address)
  55. class PermissionBasedDashboardOrderTestsNoStaff(PermissionBasedDashboardOrderTestsBase):
  56. is_staff = False
  57. def test_non_staff_can_only_list_her_orders(self):
  58. # order-list user1
  59. response = self.get(reverse('dashboard:order-list'))
  60. self.assertEqual(set(response.context['orders']),
  61. set([self.order_in]))
  62. # order-detail user2
  63. url = reverse('dashboard:order-detail',
  64. kwargs={'number': self.order_in.number})
  65. self.assertIsOk(self.get(url))
  66. url = reverse('dashboard:order-detail',
  67. kwargs={'number': self.order_out.number})
  68. self.assertNoAccess(self.get(url, status="*"))
  69. # order-line-detail user2
  70. url = reverse('dashboard:order-line-detail',
  71. kwargs={'number': self.order_in.number,
  72. 'line_id': self.order_in.lines.all()[0].pk})
  73. self.assertIsOk(self.get(url))
  74. url = reverse('dashboard:order-line-detail',
  75. kwargs={'number': self.order_out.number,
  76. 'line_id': self.order_out.lines.all()[0].pk})
  77. self.assertNoAccess(self.get(url, status="*"))
  78. # order-shipping-address
  79. url = reverse('dashboard:order-shipping-address',
  80. kwargs={'number': self.order_in.number})
  81. self.assertIsOk(self.get(url))
  82. url = reverse('dashboard:order-shipping-address',
  83. kwargs={'number': self.order_out.number})
  84. self.assertNoAccess(self.get(url, status="*"))
  85. class PermissionBasedDashboardOrderTestsStaff(PermissionBasedDashboardOrderTestsBase):
  86. is_staff = True
  87. def test_staff_user_can_list_all_orders(self):
  88. orders = [self.order_in, self.order_out]
  89. # order-list
  90. response = self.get(reverse('dashboard:order-list'))
  91. self.assertIsOk(response)
  92. self.assertEqual(set(response.context['orders']),
  93. set(orders))
  94. # order-detail
  95. for order in orders:
  96. url = reverse('dashboard:order-detail',
  97. kwargs={'number': order.number})
  98. self.assertIsOk(self.get(url))
  99. class TestOrderListSearch(WebTestCase):
  100. is_staff = True
  101. TEST_CASES = [
  102. ({}, []),
  103. (
  104. {'order_number': 'abcd1234'},
  105. ['Order number starts with "abcd1234"']
  106. ),
  107. (
  108. {'name': 'Bob Smith'},
  109. ['Customer name matches "Bob Smith"']
  110. ),
  111. (
  112. {'product_title': 'The Art of War'},
  113. ['Product name matches "The Art of War"']
  114. ),
  115. (
  116. {'upc': 'abcd1234'},
  117. ['Includes an item with UPC "abcd1234"']
  118. ),
  119. (
  120. {'partner_sku': 'abcd1234'},
  121. ['Includes an item with partner SKU "abcd1234"']
  122. ),
  123. (
  124. {'date_from': '2015-01-01'},
  125. ['Placed after 2015-01-01']
  126. ),
  127. (
  128. {'date_to': '2015-01-01'},
  129. ['Placed before 2015-01-02']
  130. ),
  131. (
  132. {'date_from': '2014-01-02', 'date_to': '2015-03-04'},
  133. ['Placed between 2014-01-02 and 2015-03-04']
  134. ),
  135. (
  136. {'voucher': 'abcd1234'},
  137. ['Used voucher code "abcd1234"']
  138. ),
  139. (
  140. {'payment_method': 'visa'},
  141. ['Paid using Visa']
  142. ),
  143. (
  144. # Assumes that the test settings (OSCAR_ORDER_STATUS_PIPELINE)
  145. # include a state called 'A'
  146. {'status': 'A'},
  147. ['Order status is A']
  148. ),
  149. (
  150. {
  151. 'name': 'Bob Smith',
  152. 'product_title': 'The Art of War',
  153. 'upc': 'upc_abcd1234',
  154. 'partner_sku': 'partner_avcd1234',
  155. 'date_from': '2014-01-02',
  156. 'date_to': '2015-03-04',
  157. 'voucher': 'voucher_abcd1234',
  158. 'payment_method': 'visa',
  159. 'status': 'A'
  160. },
  161. [
  162. 'Customer name matches "Bob Smith"',
  163. 'Product name matches "The Art of War"',
  164. 'Includes an item with UPC "upc_abcd1234"',
  165. 'Includes an item with partner SKU "partner_avcd1234"',
  166. 'Placed between 2014-01-02 and 2015-03-04',
  167. 'Used voucher code "voucher_abcd1234"',
  168. 'Paid using Visa',
  169. 'Order status is A',
  170. ]
  171. ),
  172. ]
  173. def test_search_filter_descriptions(self):
  174. SourceTypeFactory(name='Visa', code='visa')
  175. url = reverse('dashboard:order-list')
  176. for params, expected_filters in self.TEST_CASES:
  177. # Need to provide the order number parameter to avoid
  178. # being short-circuited to "all results".
  179. params.setdefault('order_number', '')
  180. response = self.get(url, params=params)
  181. self.assertEqual(response.status_code, 200)
  182. applied_filters = [
  183. el.text.strip() for el in
  184. response.html.select('.search-filter-list .label')
  185. ]
  186. self.assertEqual(applied_filters, expected_filters)
  187. class TestOrderDetailPage(WebTestCase):
  188. is_staff = True
  189. def setUp(self):
  190. super().setUp()
  191. # ensures that initial statuses are as expected
  192. self.order = create_order()
  193. self.event_type = PaymentEventType.objects.create(name='foo')
  194. url = reverse('dashboard:order-detail',
  195. kwargs={'number': self.order.number})
  196. self.page = self.get(url)
  197. def test_contains_order(self):
  198. self.assertEqual(self.page.context['order'], self.order)
  199. def test_allows_notes_to_be_added(self):
  200. form = self.page.forms['order_note_form']
  201. form['message'] = "boom"
  202. response = form.submit()
  203. self.assertIsRedirect(response)
  204. notes = self.order.notes.all()
  205. self.assertEqual(1, len(notes))
  206. def test_allows_line_status_to_be_changed(self):
  207. line = self.order.lines.all()[0]
  208. self.assertEqual(line.status, settings.OSCAR_INITIAL_LINE_STATUS)
  209. form = self.page.forms['order_lines_form']
  210. form['line_action'] = 'change_line_statuses'
  211. form['new_status'] = new_status = 'b'
  212. form['selected_line'] = [line.pk]
  213. form.submit()
  214. # fetch line again
  215. self.assertEqual(self.order.lines.all()[0].status, new_status)
  216. def test_allows_order_status_to_be_changed(self):
  217. form = self.page.forms['order_status_form']
  218. self.assertEqual(
  219. self.order.status, settings.OSCAR_INITIAL_ORDER_STATUS)
  220. form = self.page.forms['order_status_form']
  221. form['new_status'] = new_status = 'B'
  222. form.submit()
  223. # fetch order again
  224. self.assertEqual(Order.objects.get(pk=self.order.pk).status, new_status)
  225. def test_allows_creating_payment_event(self):
  226. line = self.order.lines.all()[0]
  227. form = self.page.forms['order_lines_form']
  228. form['line_action'] = 'create_payment_event'
  229. form['selected_line'] = [line.pk]
  230. form['payment_event_type'] = self.event_type.code
  231. form.submit()
  232. self.assertTrue(PaymentEvent.objects.exists())
  233. class TestChangingOrderStatus(WebTestCase):
  234. is_staff = True
  235. def setUp(self):
  236. super().setUp()
  237. Order.pipeline = {'A': ('B', 'C'), 'B': ('C', ), 'C': ()}
  238. self.order = create_order(status='A')
  239. url = reverse('dashboard:order-detail',
  240. kwargs={'number': self.order.number})
  241. page = self.get(url)
  242. form = page.forms['order_status_form']
  243. form['new_status'] = 'B'
  244. self.response = form.submit()
  245. def reload_order(self):
  246. return Order.objects.get(number=self.order.number)
  247. def test_works(self):
  248. self.assertIsRedirect(self.response)
  249. self.assertEqual('B', self.reload_order().status)
  250. def test_creates_system_note(self):
  251. notes = self.order.notes.all()
  252. self.assertEqual(1, len(notes))
  253. self.assertEqual(OrderNote.SYSTEM, notes[0].note_type)
  254. class TestChangingOrderStatusFromFormOnOrderListView(WebTestCase):
  255. is_staff = True
  256. def setUp(self):
  257. super().setUp()
  258. Order.pipeline = {'A': ('B', 'C'), 'B': ('A', 'C'), 'C': ('A', 'B')}
  259. self.order = create_order(status='A')
  260. url = reverse('dashboard:order-list')
  261. page = self.get(url)
  262. form = page.forms['orders_form']
  263. form['new_status'] = 'B'
  264. form['selected_order'] = self.order.pk
  265. self.response = form.submit(name='action', value='change_order_statuses')
  266. def reload_order(self):
  267. return Order.objects.get(number=self.order.number)
  268. def test_works(self):
  269. self.assertIsRedirect(self.response)
  270. # Has the order status been changed?
  271. self.assertEqual('B', self.reload_order().status)
  272. # Is a system note created?
  273. notes = self.order.notes.all()
  274. self.assertEqual(1, len(notes))
  275. self.assertEqual(OrderNote.SYSTEM, notes[0].note_type)
  276. class LineDetailTests(WebTestCase):
  277. is_staff = True
  278. def setUp(self):
  279. self.order = create_order()
  280. self.line = self.order.lines.all()[0]
  281. self.url = reverse('dashboard:order-line-detail',
  282. kwargs={'number': self.order.number,
  283. 'line_id': self.line.id})
  284. super().setUp()
  285. def test_line_detail_page_exists(self):
  286. response = self.get(self.url)
  287. self.assertIsOk(response)
  288. def test_line_in_context(self):
  289. response = self.get(self.url)
  290. self.assertInContext(response, 'line')