From 42aa14cd08466211f5d041bd5156d24894bc7e43 Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 10 Oct 2024 09:25:05 +1100 Subject: [PATCH] Sales Order Allocation (#244) * Add SalesOrderAllocation model * Update tasks.py * Update version number * Update unit test * Update unit test --- inventree/base.py | 2 +- inventree/sales_order.py | 48 ++++++++++++++++++++++++++++++++++++---- tasks.py | 4 ++-- test/test_order.py | 11 ++++++++- 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/inventree/base.py b/inventree/base.py index e166a6a..216de7a 100644 --- a/inventree/base.py +++ b/inventree/base.py @@ -6,7 +6,7 @@ from . import api as inventree_api -INVENTREE_PYTHON_VERSION = "0.17.0" +INVENTREE_PYTHON_VERSION = "0.17.1" logger = logging.getLogger('inventree') diff --git a/inventree/sales_order.py b/inventree/sales_order.py index e96fadc..b12c99e 100644 --- a/inventree/sales_order.py +++ b/inventree/sales_order.py @@ -6,6 +6,7 @@ import inventree.company import inventree.part import inventree.report +import inventree.stock class SalesOrder( @@ -190,6 +191,35 @@ def getOrder(self): return SalesOrder(self._api, self.order) +class SalesOrderAllocation( + inventree.base.InventreeObject +): + """Class representing the SalesOrderAllocation database model.""" + + URL = 'order/so-allocation' + + def getOrder(self): + """Return the SalesOrder to which this SalesOrderAllocation belongs.""" + return SalesOrder(self._api, self.order) + + def getShipment(self): + """Return the SalesOrderShipment to which this SalesOrderAllocation belongs.""" + from sales_order import SalesOrderShipment + return SalesOrderShipment(self._api, self.shipment) + + def getLineItem(self): + """Return the SalesOrderLineItem to which this SalesOrderAllocation belongs.""" + return SalesOrderLineItem(self._api, self.line) + + def getStockItem(self): + """Return the StockItem to which this SalesOrderAllocation belongs.""" + return inventree.stock.StockItem(self._api, self.item) + + def getPart(self): + """Return the Part to which this SalesOrderAllocation belongs.""" + return inventree.part.Part(self._api, self.part) + + class SalesOrderShipment( inventree.base.InventreeObject, inventree.base.StatusMixin, @@ -200,9 +230,7 @@ class SalesOrderShipment( URL = 'order/so/shipment' def getOrder(self): - """ - Return the SalesOrder to which this SalesOrderShipment belongs - """ + """Return the SalesOrder to which this SalesOrderShipment belongs.""" return SalesOrder(self._api, self.order) def allocateItems(self, items=[]): @@ -219,7 +247,7 @@ def allocateItems(self, items=[]): } """ - # Customise URL + # Customize URL url = f'order/so/{self.getOrder().pk}/allocate' # Create data from given inputs @@ -237,6 +265,18 @@ def allocateItems(self, items=[]): # Return return response + def getAllocations(self): + """Return the allocations associated with this shipment""" + return SalesOrderAllocation.list(self._api, shipment=self.pk) + + @property + def allocations(self): + """Return the allocations associated with this shipment. + + Note: This is an overload of getAllocations() method, for legacy compatibility. + """ + return self.getAllocations() + def complete( self, shipment_date=None, diff --git a/tasks.py b/tasks.py index 9e745ea..5733b6c 100644 --- a/tasks.py +++ b/tasks.py @@ -34,9 +34,9 @@ def reset_data(c, debug=False): hide = None if debug else 'both' - c.run("docker-compose -f test/docker-compose.yml run --rm inventree-py-test-server invoke delete-data -f", hide=hide) + c.run("docker-compose -f test/docker-compose.yml run --rm inventree-py-test-server invoke dev.delete-data -f", hide=hide) c.run("docker-compose -f test/docker-compose.yml run --rm inventree-py-test-server invoke migrate", hide=hide) - c.run("docker-compose -f test/docker-compose.yml run --rm inventree-py-test-server invoke import-fixtures", hide=hide) + c.run("docker-compose -f test/docker-compose.yml run --rm inventree-py-test-server invoke dev.import-fixtures", hide=hide) @task(post=[reset_data]) diff --git a/test/test_order.py b/test/test_order.py index fd06bb0..c823f2d 100644 --- a/test/test_order.py +++ b/test/test_order.py @@ -674,16 +674,25 @@ def test_so_shipment(self): # Make sure date is not None self.assertIsNotNone(shipment_2.shipment_date) + # SalesOrderAllocations are broken prior to server API version 267 + if self.api.api_version < 267: + return + # Try to complete this order # Ship remaining shipments first for shp in so.getShipments(): + + allocations = shp.getAllocations() + # Delete shipment if it has no allocations - if len(shp.allocations) == 0: + if len(allocations) == 0: shp.delete() continue + # If the shipment has no date, try to mark it shipped if shp.shipment_date is None: shp.ship() + so.complete() self.assertEqual(so.status, 20) self.assertEqual(so.status_text, 'Shipped')