""" Tests for the Order API """ from datetime import datetime, timedelta from rest_framework import status from django.urls import reverse from InvenTree.api_tester import InvenTreeAPITestCase from .models import PurchaseOrder, SalesOrder class OrderTest(InvenTreeAPITestCase): fixtures = [ 'category', 'part', 'company', 'location', 'supplier_part', 'stock', 'order', 'sales_order', ] roles = [ 'purchase_order.change', 'sales_order.change', ] def setUp(self): super().setUp() def filter(self, filters, count): """ Test API filters """ response = self.get( self.LIST_URL, filters ) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data), count) return response class PurchaseOrderTest(OrderTest): """ Tests for the PurchaseOrder API """ LIST_URL = reverse('api-po-list') def test_po_list(self): # List *ALL* PO items self.filter({}, 7) # Filter by supplier self.filter({'supplier': 1}, 1) self.filter({'supplier': 3}, 5) # Filter by "outstanding" self.filter({'outstanding': True}, 5) self.filter({'outstanding': False}, 2) # Filter by "status" self.filter({'status': 10}, 3) self.filter({'status': 40}, 1) def test_overdue(self): """ Test "overdue" status """ self.filter({'overdue': True}, 0) self.filter({'overdue': False}, 7) order = PurchaseOrder.objects.get(pk=1) order.target_date = datetime.now().date() - timedelta(days=10) order.save() self.filter({'overdue': True}, 1) self.filter({'overdue': False}, 6) def test_po_detail(self): url = '/api/order/po/1/' response = self.get(url) self.assertEqual(response.status_code, 200) data = response.data self.assertEqual(data['pk'], 1) self.assertEqual(data['description'], 'Ordering some screws') def test_po_attachments(self): url = reverse('api-po-attachment-list') response = self.get(url) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_po_operations(self): """ Test that we can create / edit and delete a PurchaseOrder via the API """ n = PurchaseOrder.objects.count() url = reverse('api-po-list') # Initially we do not have "add" permission for the PurchaseOrder model, # so this POST request should return 403 response = self.post( url, { 'supplier': 1, 'reference': '123456789-xyz', 'description': 'PO created via the API', }, expected_code=403 ) # And no new PurchaseOrder objects should have been created self.assertEqual(PurchaseOrder.objects.count(), n) # Ok, now let's give this user the correct permission self.assignRole('purchase_order.add') # Initially we do not have "add" permission for the PurchaseOrder model, # so this POST request should return 403 response = self.post( url, { 'supplier': 1, 'reference': '123456789-xyz', 'description': 'PO created via the API', }, expected_code=201 ) self.assertEqual(PurchaseOrder.objects.count(), n + 1) pk = response.data['pk'] # Try to create a PO with identical reference (should fail!) response = self.post( url, { 'supplier': 1, 'reference': '123456789-xyz', 'description': 'A different description', }, expected_code=400 ) self.assertEqual(PurchaseOrder.objects.count(), n + 1) url = reverse('api-po-detail', kwargs={'pk': pk}) # Get detail info! response = self.get(url) self.assertEqual(response.data['pk'], pk) self.assertEqual(response.data['reference'], '123456789-xyz') # Try to alter (edit) the PurchaseOrder response = self.patch( url, { 'reference': '12345-abc', }, expected_code=200 ) # Reference should have changed self.assertEqual(response.data['reference'], '12345-abc') # Now, let's try to delete it! # Initially, we do *not* have the required permission! response = self.delete(url, expected_code=403) # Now, add the "delete" permission! self.assignRole("purchase_order.delete") response = self.delete(url, expected_code=204) # Number of PurchaseOrder objects should have decreased self.assertEqual(PurchaseOrder.objects.count(), n) # And if we try to access the detail view again, it has gone response = self.get(url, expected_code=404) class SalesOrderTest(OrderTest): """ Tests for the SalesOrder API """ LIST_URL = reverse('api-so-list') def test_so_list(self): # All orders self.filter({}, 5) # Filter by customer self.filter({'customer': 4}, 3) self.filter({'customer': 5}, 2) # Filter by outstanding self.filter({'outstanding': True}, 3) self.filter({'outstanding': False}, 2) # Filter by status self.filter({'status': 10}, 3) # PENDING self.filter({'status': 20}, 1) # SHIPPED self.filter({'status': 99}, 0) # Invalid def test_overdue(self): """ Test "overdue" status """ self.filter({'overdue': True}, 0) self.filter({'overdue': False}, 5) for pk in [1, 2]: order = SalesOrder.objects.get(pk=pk) order.target_date = datetime.now().date() - timedelta(days=10) order.save() self.filter({'overdue': True}, 2) self.filter({'overdue': False}, 3) def test_so_detail(self): url = '/api/order/so/1/' response = self.get(url) data = response.data self.assertEqual(data['pk'], 1) def test_so_attachments(self): url = reverse('api-so-attachment-list') self.get(url) def test_so_operations(self): """ Test that we can create / edit and delete a SalesOrder via the API """ n = SalesOrder.objects.count() url = reverse('api-so-list') # Initially we do not have "add" permission for the SalesOrder model, # so this POST request should return 403 (denied) response = self.post( url, { 'customer': 4, 'reference': '12345', 'description': 'Sales order', }, expected_code=403, ) self.assignRole('sales_order.add') # Now we should be able to create a SalesOrder via the API response = self.post( url, { 'customer': 4, 'reference': '12345', 'description': 'Sales order', }, expected_code=201 ) # Check that the new order has been created self.assertEqual(SalesOrder.objects.count(), n + 1) # Grab the PK for the newly created SalesOrder pk = response.data['pk'] # Try to create a SO with identical reference (should fail) response = self.post( url, { 'customer': 4, 'reference': '12345', 'description': 'Another sales order', }, expected_code=400 ) url = reverse('api-so-detail', kwargs={'pk': pk}) # Extract detail info for the SalesOrder response = self.get(url) self.assertEqual(response.data['reference'], '12345') # Try to alter (edit) the SalesOrder response = self.patch( url, { 'reference': '12345-a', }, expected_code=200 ) # Reference should have changed self.assertEqual(response.data['reference'], '12345-a') # Now, let's try to delete this SalesOrder # Initially, we do not have the required permission response = self.delete(url, expected_code=403) self.assignRole('sales_order.delete') response = self.delete(url, expected_code=204) # Check that the number of sales orders has decreased self.assertEqual(SalesOrder.objects.count(), n) # And the resource should no longer be available response = self.get(url, expected_code=404)