diff --git a/InvenTree/order/fixtures/order.yaml b/InvenTree/order/fixtures/order.yaml index bbf2c47a74..6fab8a705d 100644 --- a/InvenTree/order/fixtures/order.yaml +++ b/InvenTree/order/fixtures/order.yaml @@ -20,6 +20,7 @@ # 100 x ACME0001 (M2x4 LPHS) - model: order.purchaseorderlineitem + pk: 1 fields: order: 1 part: 1 @@ -40,4 +41,4 @@ order: 2 part: 3 quantity: 100 - + diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index e1e2a67614..ad8a4c0918 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -52,7 +52,7 @@ class Order(models.Model): def save(self, *args, **kwargs): if not self.creation_date: - self.creation_date = dateimt.now().date() + self.creation_date = datetime.now().date() super().save(*args, **kwargs) @@ -233,6 +233,16 @@ class PurchaseOrder(Order): """ Receive a line item (or partial line item) against this PO """ + if not self.status == OrderStatus.PLACED: + raise ValidationError({"status": _("Lines can only be received against an order marked as 'Placed'")}) + + try: + quantity = int(quantity) + if quantity <= 0: + raise ValidationError({"quantity": _("Quantity must be greater than zero")}) + except ValueError: + raise ValidationError({"quantity": _("Invalid quantity provided")}) + # Create a new stock item if line.part: stock = StockItem( @@ -245,7 +255,7 @@ class PurchaseOrder(Order): # Add a new transaction note to the newly created stock item stock.addTransactionNote("Received items", user, "Received {q} items against order '{po}'".format( - q=line.receive_quantity, + q=quantity, po=str(self)) ) diff --git a/InvenTree/order/tests.py b/InvenTree/order/tests.py index 116b10e89d..872023c885 100644 --- a/InvenTree/order/tests.py +++ b/InvenTree/order/tests.py @@ -1,6 +1,12 @@ from django.test import TestCase +import django.core.exceptions as django_exceptions from part.models import Part +from .models import PurchaseOrder, PurchaseOrderLineItem +from stock.models import StockLocation + +from InvenTree.status_codes import OrderStatus + class OrderTest(TestCase): """ @@ -17,6 +23,18 @@ class OrderTest(TestCase): 'order' ] + def test_basics(self): + + order = PurchaseOrder.objects.get(pk=1) + + self.assertEqual(order.get_absolute_url(), '/order/purchase-order/1/') + + self.assertEqual(str(order), 'PO 1') + + line = PurchaseOrderLineItem.objects.get(pk=1) + + self.assertEqual(str(line), "100 x ACME0001 from ACME (for PO 1)") + def test_on_order(self): """ There should be 3 separate items on order for the M2x4 LPHS part """ @@ -31,3 +49,46 @@ class OrderTest(TestCase): # Test the total on-order quantity self.assertEqual(part.on_order, 400) + + def test_receive(self): + + part = Part.objects.get(name='M2x4 LPHS') + + # Receive some items + line = PurchaseOrderLineItem.objects.get(id=1) + + order = line.order + loc = StockLocation.objects.get(id=1) + + # There should be two lines against this order + self.assertEqual(len(order.pending_line_items()), 2) + + # Should fail, as order is 'PENDING' not 'PLACED" + self.assertEqual(order.status, OrderStatus.PENDING) + + with self.assertRaises(django_exceptions.ValidationError): + order.receive_line_item(line, loc, 50, user=None) + + order.place_order() + + self.assertEqual(order.status, OrderStatus.PLACED) + + order.receive_line_item(line, loc, 50, user=None) + + self.assertEqual(part.on_order, 350) + + # Try to order some invalid things + with self.assertRaises(django_exceptions.ValidationError): + order.receive_line_item(line, loc, -10, user=None) + + with self.assertRaises(django_exceptions.ValidationError): + order.receive_line_item(line, loc, 'not a number', user=None) + + # Receive the rest of the items + order.receive_line_item(line, loc, 50, user=None) + + line = PurchaseOrderLineItem.objects.get(id=2) + order.receive_line_item(line, loc, 2 * line.quantity, user=None) + + self.assertEqual(part.on_order, 100) + self.assertEqual(order.status, OrderStatus.COMPLETE)