From b6a6e2dae79f917828fee98a08ce4bea1949179b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Fri, 28 Jun 2019 10:00:23 +1000 Subject: [PATCH] Change the manner in which active parts are filtered for BOM - Prevented BOM from displaying for an inactive part - Now manually filter the queryset in the form view --- .../migrations/0013_auto_20190628_0951.py | 24 ++++++++++ InvenTree/part/models.py | 2 - InvenTree/part/templates/part/bom.html | 4 +- InvenTree/part/templates/part/part_base.html | 2 +- InvenTree/part/views.py | 45 ++++++++++++++++++- 5 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 InvenTree/part/migrations/0013_auto_20190628_0951.py diff --git a/InvenTree/part/migrations/0013_auto_20190628_0951.py b/InvenTree/part/migrations/0013_auto_20190628_0951.py new file mode 100644 index 0000000000..df9f8fdb14 --- /dev/null +++ b/InvenTree/part/migrations/0013_auto_20190628_0951.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.2 on 2019-06-27 23:51 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0012_auto_20190627_2144'), + ] + + operations = [ + migrations.AlterField( + model_name='bomitem', + name='part', + field=models.ForeignKey(help_text='Select parent part', limit_choices_to={'assembly': True}, on_delete=django.db.models.deletion.CASCADE, related_name='bom_items', to='part.Part'), + ), + migrations.AlterField( + model_name='bomitem', + name='sub_part', + field=models.ForeignKey(help_text='Select part to be used in BOM', limit_choices_to={'component': True}, on_delete=django.db.models.deletion.CASCADE, related_name='used_in', to='part.Part'), + ), + ] diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 5f31e8a912..cc5bfc0db1 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -987,7 +987,6 @@ class BomItem(models.Model): help_text='Select parent part', limit_choices_to={ 'assembly': True, - 'active': True, }) # A link to the child item (sub-part) @@ -996,7 +995,6 @@ class BomItem(models.Model): help_text='Select part to be used in BOM', limit_choices_to={ 'component': True, - 'active': True }) # Quantity required diff --git a/InvenTree/part/templates/part/bom.html b/InvenTree/part/templates/part/bom.html index 1605deda68..2591b986ee 100644 --- a/InvenTree/part/templates/part/bom.html +++ b/InvenTree/part/templates/part/bom.html @@ -37,7 +37,7 @@ - {% else %} + {% elif part.active %} {% if part.is_bom_valid == False %} @@ -125,7 +125,7 @@ }); $("#edit-bom").click(function () { - location.href = "{% url 'part-bom' part.id %}?edit=True"; + location.href = "{% url 'part-bom' part.id %}?edit=1"; }); $(".download-bom").click(function () { diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index 7339b5afb7..27852b5859 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -123,7 +123,7 @@ Total Available {{ part.net_stock }} - {% if part.assembly %} + {% if part.assembly %}

Build Status

diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 07f013d852..99ea6680e3 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -511,13 +511,15 @@ class PartDetail(DetailView): - If '?editing=True', set 'editing_enabled' context variable """ context = super(PartDetail, self).get_context_data(**kwargs) + + part = self.get_object() if str2bool(self.request.GET.get('edit', '')): - context['editing_enabled'] = 1 + # Allow BOM editing if the part is active + context['editing_enabled'] = 1 if part.active else 0 else: context['editing_enabled'] = 0 - part = self.get_object() context['starred'] = part.isStarredBy(self.request.user) context['disabled'] = not part.active @@ -1025,11 +1027,16 @@ class BomItemCreate(AjaxCreateView): try: part = Part.objects.get(id=part_id) + # Only allow active parts to be selected + query = form.fields['part'].queryset.filter(active=True) + form.fields['part'].queryset = query + # Don't allow selection of sub_part objects which are already added to the Bom! query = form.fields['sub_part'].queryset # Don't allow a part to be added to its own BOM query = query.exclude(id=part.id) + query = query.filter(active=True) # Eliminate any options that are already in the BOM! query = query.exclude(id__in=[item.id for item in part.required_parts()]) @@ -1069,6 +1076,40 @@ class BomItemEdit(AjaxUpdateView): ajax_template_name = 'modal_form.html' ajax_form_title = 'Edit BOM item' + def get_form(self): + """ Override get_form() method to reduce Part selection options. + + - Do not allow part to be added to its own BOM + - Remove any Part items that are already in the BOM + """ + + form = super(AjaxCreateView, self).get_form() + + part_id = form['part'].value() + + try: + part = Part.objects.get(id=part_id) + + # Only allow active parts to be selected + query = form.fields['part'].queryset.filter(active=True) + form.fields['part'].queryset = query + + # Don't allow selection of sub_part objects which are already added to the Bom! + query = form.fields['sub_part'].queryset + + # Don't allow a part to be added to its own BOM + query = query.exclude(id=part.id) + query = query.filter(active=True) + + # Eliminate any options that are already in the BOM! + query = query.exclude(id__in=[item.id for item in part.required_parts()]) + + form.fields['sub_part'].queryset = query + except Part.DoesNotExist: + pass + + return form + class BomItemDelete(AjaxDeleteView): """ Delete view for removing BomItem """