From ac3dcac64167700ea701c898117aaf71171d57a4 Mon Sep 17 00:00:00 2001
From: eeintech
Date: Mon, 2 Aug 2021 15:05:24 -0400
Subject: [PATCH] Re-enabled installing stock items into others
---
.../build/templates/build/build_base.html | 4 +-
InvenTree/stock/forms.py | 23 +++--
InvenTree/stock/templates/stock/item.html | 19 ++++
.../stock/templates/stock/item_base.html | 24 ++++-
.../stock/templates/stock/item_install.html | 22 ++++-
InvenTree/stock/views.py | 92 +++++++++++++++----
6 files changed, 146 insertions(+), 38 deletions(-)
diff --git a/InvenTree/build/templates/build/build_base.html b/InvenTree/build/templates/build/build_base.html
index 5770777d28..e3119e6fdb 100644
--- a/InvenTree/build/templates/build/build_base.html
+++ b/InvenTree/build/templates/build/build_base.html
@@ -111,8 +111,8 @@ src="{% static 'img/blank_image.png' %}"
{% trans "Cancel Build" %}
{% endif %}
{% if build.status == BuildStatus.CANCELLED and roles.build.delete %}
- {% trans "Delete Build"% }
- {% endif %}
+ {% trans "Delete Build" %}
+ {% endif %}
{% endif %}
diff --git a/InvenTree/stock/forms.py b/InvenTree/stock/forms.py
index b23b71a2d6..b088a6cdef 100644
--- a/InvenTree/stock/forms.py
+++ b/InvenTree/stock/forms.py
@@ -241,16 +241,21 @@ class InstallStockForm(HelperForm):
help_text=_('Stock item to install')
)
- quantity_to_install = RoundingDecimalFormField(
- max_digits=10, decimal_places=5,
- initial=1,
- label=_('Quantity'),
- help_text=_('Stock quantity to assign'),
- validators=[
- MinValueValidator(0.001)
- ]
+ to_install = forms.BooleanField(
+ widget=forms.HiddenInput(),
+ required=False
)
+ # quantity_to_install = RoundingDecimalFormField(
+ # max_digits=10, decimal_places=5,
+ # initial=1,
+ # label=_('Quantity'),
+ # help_text=_('Stock quantity to assign'),
+ # validators=[
+ # MinValueValidator(0.001)
+ # ]
+ # )
+
notes = forms.CharField(
required=False,
help_text=_('Notes')
@@ -261,7 +266,7 @@ class InstallStockForm(HelperForm):
fields = [
'part',
'stock_item',
- 'quantity_to_install',
+ # 'quantity_to_install',
'notes',
]
diff --git a/InvenTree/stock/templates/stock/item.html b/InvenTree/stock/templates/stock/item.html
index 8a00c1c5e6..d380ea3369 100644
--- a/InvenTree/stock/templates/stock/item.html
+++ b/InvenTree/stock/templates/stock/item.html
@@ -119,6 +119,11 @@
{% trans "Installed Stock Items" %}
+
+
+
@@ -128,6 +133,20 @@
{% block js_ready %}
{{ block.super }}
+ $('#stock-item-install').click(function() {
+
+ launchModalForm(
+ "{% url 'stock-item-install' item.pk %}",
+ {
+ data: {
+ 'part': {{ item.part.pk }},
+ 'install_item': true,
+ },
+ reload: true,
+ }
+ );
+ });
+
loadInstalledInTable(
$('#installed-table'),
{
diff --git a/InvenTree/stock/templates/stock/item_base.html b/InvenTree/stock/templates/stock/item_base.html
index b16d9b0b1a..93698e3d05 100644
--- a/InvenTree/stock/templates/stock/item_base.html
+++ b/InvenTree/stock/templates/stock/item_base.html
@@ -127,9 +127,11 @@
{% trans "Return to stock" %}
{% endif %}
{% if item.belongs_to %}
-
- {% trans "Uninstall" %}
-
+ {% trans "Uninstall" %}
+ {% else %}
+ {% if item.part.get_used_in %}
+ {% trans "Install" %}
+ {% endif %}
{% endif %}
@@ -461,13 +463,27 @@ $("#stock-serialize").click(function() {
);
});
+$('#stock-install-in').click(function() {
+
+ launchModalForm(
+ "{% url 'stock-item-install' item.pk %}",
+ {
+ data: {
+ 'part': {{ item.part.pk }},
+ 'install_in': true,
+ },
+ reload: true,
+ }
+ );
+});
+
$('#stock-uninstall').click(function() {
launchModalForm(
"{% url 'stock-item-uninstall' %}",
{
data: {
- 'items[]': [{{ item.pk}}],
+ 'items[]': [{{ item.pk }}],
},
reload: true,
}
diff --git a/InvenTree/stock/templates/stock/item_install.html b/InvenTree/stock/templates/stock/item_install.html
index 04798972d2..8a94f304d3 100644
--- a/InvenTree/stock/templates/stock/item_install.html
+++ b/InvenTree/stock/templates/stock/item_install.html
@@ -3,15 +3,31 @@
{% block pre_form_content %}
+{% if install_item %}
- {% trans "Install another StockItem into this item." %}
+ {% trans "Install another Stock Item into this item." %}
{% trans "Stock items can only be installed if they meet the following criteria" %}:
- - {% trans "The StockItem links to a Part which is in the BOM for this StockItem" %}
- - {% trans "The StockItem is currently in stock" %}
+ - {% trans "The Stock Item links to a Part which is in the BOM for this Stock Item" %}
+ - {% trans "The Stock Item is currently in stock" %}
+ - {% trans "The Stock Item is serialized and does not belong to another item" %}
+{% elif install_in %}
+
+ {% trans "Install this Stock Item in another stock item." %}
+
+
+ {% trans "Stock items can only be installed if they meet the following criteria" %}:
+
+
+ - {% trans "The part associated to this Stock Item belongs to another part's BOM" %}
+ - {% trans "This Stock Item is serialized and does not belong to another item" %}
+
+
+{% endif %}
+
{% endblock %}
\ No newline at end of file
diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py
index 80968e5aa9..25f8cefac1 100644
--- a/InvenTree/stock/views.py
+++ b/InvenTree/stock/views.py
@@ -518,36 +518,73 @@ class StockItemInstall(AjaxUpdateView):
part = None
+ def get_params(self):
+ """ Retrieve GET parameters """
+
+ # Look at GET params
+ self.part_id = self.request.GET.get('part', None)
+ self.install_in = self.request.GET.get('install_in', False)
+ self.install_item = self.request.GET.get('install_item', False)
+
+ if self.part_id is None:
+ # Look at POST params
+ self.part_id = self.request.POST.get('part', None)
+
+ try:
+ self.part = Part.objects.get(pk=self.part_id)
+ except (ValueError, Part.DoesNotExist):
+ self.part = None
+
def get_stock_items(self):
"""
Return a list of stock items suitable for displaying to the user.
Requirements:
- Items must be in stock
-
- Filters:
- - Items can be filtered by Part reference
+ - Items must be in BOM of stock item
+ - Items must be serialized
"""
-
+
+ # Filter items in stock
items = StockItem.objects.filter(StockItem.IN_STOCK_FILTER)
- # Filter by Part association
+ # Filter serialized stock items
+ items = items.exclude(serial__isnull=True).exclude(serial__exact='')
- # Look at GET params
- part_id = self.request.GET.get('part', None)
+ if self.part:
+ # Filter for parts to install this item in
+ if self.install_in:
+ # Get parts using this part
+ allowed_parts = self.part.get_used_in()
+ # Filter
+ items = items.filter(part__in=allowed_parts)
- if part_id is None:
- # Look at POST params
- part_id = self.request.POST.get('part', None)
-
- try:
- self.part = Part.objects.get(pk=part_id)
- items = items.filter(part=self.part)
- except (ValueError, Part.DoesNotExist):
- self.part = None
+ # Filter for parts to install in this item
+ if self.install_item:
+ # Get parts used in this part's BOM
+ bom_items = self.part.get_bom_items()
+ allowed_parts = [item.sub_part for item in bom_items]
+ # Filter
+ items = items.filter(part__in=allowed_parts)
return items
+ def get_context_data(self, **kwargs):
+ """ Retrieve parameters and update context """
+
+ ctx = super().get_context_data(**kwargs)
+
+ # Get request parameters
+ self.get_params()
+
+ ctx.update({
+ 'part': self.part,
+ 'install_in': self.install_in,
+ 'install_item': self.install_item,
+ })
+
+ return ctx
+
def get_initial(self):
initials = super().get_initial()
@@ -558,11 +595,17 @@ class StockItemInstall(AjaxUpdateView):
if items.count() == 1:
item = items.first()
initials['stock_item'] = item.pk
- initials['quantity_to_install'] = item.quantity
+ # initials['quantity_to_install'] = item.quantity
if self.part:
initials['part'] = self.part
+ try:
+ # Is this stock item being installed in the other stock item?
+ initials['to_install'] = self.install_in or not self.install_item
+ except AttributeError:
+ pass
+
return initials
def get_form(self):
@@ -575,6 +618,8 @@ class StockItemInstall(AjaxUpdateView):
def post(self, request, *args, **kwargs):
+ self.get_params()
+
form = self.get_form()
valid = form.is_valid()
@@ -584,13 +629,20 @@ class StockItemInstall(AjaxUpdateView):
data = form.cleaned_data
other_stock_item = data['stock_item']
- quantity = data['quantity_to_install']
+ # quantity = data['quantity_to_install']
+ # Quantity will always be 1 for serialized item
+ quantity = 1
notes = data['notes']
- # Install the other stock item into this one
+ # Get stock item
this_stock_item = self.get_object()
- this_stock_item.installStockItem(other_stock_item, quantity, request.user, notes)
+ if data['to_install']:
+ # Install this stock item into the other stock item
+ other_stock_item.installStockItem(this_stock_item, quantity, request.user, notes)
+ else:
+ # Install the other stock item into this one
+ this_stock_item.installStockItem(other_stock_item, quantity, request.user, notes)
data = {
'form_valid': valid,