diff --git a/InvenTree/InvenTree/api_version.py b/InvenTree/InvenTree/api_version.py index 0867ef8b0c..5797d31e3c 100644 --- a/InvenTree/InvenTree/api_version.py +++ b/InvenTree/InvenTree/api_version.py @@ -2,11 +2,14 @@ # InvenTree API version -INVENTREE_API_VERSION = 147 +INVENTREE_API_VERSION = 148 """ Increment this API version number whenever there is a significant change to the API that any clients need to know about +v148 -> 2023-11-06 : https://github.com/inventree/InvenTree/pull/5872 + - Allow "quantity" to be specified when installing an item into another item + v147 -> 2023-11-04: https://github.com/inventree/InvenTree/pull/5860 - Adds "completed_lines" field to SalesOrder API endpoint - Adds "completed_lines" field to PurchaseOrder API endpoint diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index 21453536d0..593065f9ef 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -489,6 +489,14 @@ class InstallStockItemSerializer(serializers.Serializer): help_text=_('Select stock item to install'), ) + quantity = serializers.IntegerField( + min_value=1, + default=1, + required=False, + label=_('Quantity to Install'), + help_text=_('Enter the quantity of items to install'), + ) + note = serializers.CharField( label=_('Note'), help_text=_('Add transaction note (optional)'), @@ -496,26 +504,47 @@ class InstallStockItemSerializer(serializers.Serializer): allow_blank=True, ) + def validate_quantity(self, quantity): + """Validate the quantity value.""" + + if quantity < 1: + raise ValidationError(_("Quantity to install must be at least 1")) + + return quantity + def validate_stock_item(self, stock_item): """Validate the selected stock item.""" if not stock_item.in_stock: # StockItem must be in stock to be "installed" raise ValidationError(_("Stock item is unavailable")) - # Extract the "parent" item - the item into which the stock item will be installed parent_item = self.context['item'] parent_part = parent_item.part + # Check if the selected part is in the Bill of Materials of the parent item if not parent_part.check_if_part_in_bom(stock_item.part): raise ValidationError(_("Selected part is not in the Bill of Materials")) return stock_item + def validate(self, data): + """Ensure that the provided dataset is valid""" + + stock_item = data['stock_item'] + + quantity = data.get('quantity', stock_item.quantity) + + if quantity > stock_item.quantity: + raise ValidationError(_("Quantity to install must not exceed available quantity")) + + return data + def save(self): """Install the selected stock item into this one.""" data = self.validated_data stock_item = data['stock_item'] + quantity_to_install = data.get('quantity', stock_item.quantity) note = data.get('note', '') parent_item = self.context['item'] @@ -523,7 +552,7 @@ class InstallStockItemSerializer(serializers.Serializer): parent_item.installStockItem( stock_item, - stock_item.quantity, + quantity_to_install, request.user, note, ) diff --git a/InvenTree/templates/js/translated/stock.js b/InvenTree/templates/js/translated/stock.js index ce8207863e..88613f09bc 100644 --- a/InvenTree/templates/js/translated/stock.js +++ b/InvenTree/templates/js/translated/stock.js @@ -3217,6 +3217,12 @@ function installStockItem(stock_item_id, part_id, options={}) { in_stock: true, tracked: true, }, + onSelect: function(data, field, opts) { + // Adjust the 'quantity' field + if ('quantity' in data) { + updateFieldValue('quantity', data.quantity, opts); + } + }, adjustFilters: function(filters, opts) { var part = getFormFieldValue('part', {}, opts); @@ -3226,7 +3232,8 @@ function installStockItem(stock_item_id, part_id, options={}) { return filters; } - } + }, + quantity: {}, }, confirm: true, title: '{% trans "Install Stock Item" %}',