From 590dedce13e04a91d13a3ce4f096f8a334c46ae4 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 18 Apr 2019 23:08:33 +1000 Subject: [PATCH 1/6] Add some helper functions --- InvenTree/InvenTree/helpers.py | 9 +++++++++ InvenTree/InvenTree/models.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py index ba3f3525d5..872c4fe458 100644 --- a/InvenTree/InvenTree/helpers.py +++ b/InvenTree/InvenTree/helpers.py @@ -4,6 +4,15 @@ from wsgiref.util import FileWrapper from django.http import StreamingHttpResponse +def str2bool(text, test=True): + """ Test if a string 'looks' like a boolean value + """ + if test: + return str(text).lower() in ['1', 'y', 'yes', 't', 'true', 'ok', ] + else: + return str(text).lower() in ['0', 'n', 'no', 'none', 'f', 'false',] + + def WrapWithQuotes(text): # TODO - Make this better if not text.startswith('"'): diff --git a/InvenTree/InvenTree/models.py b/InvenTree/InvenTree/models.py index 4c25be2fe6..b7468cd7cb 100644 --- a/InvenTree/InvenTree/models.py +++ b/InvenTree/InvenTree/models.py @@ -183,7 +183,7 @@ def FilterChildren(queryset, parent): if not parent: return queryset - elif str(parent).lower() in ['none', 'false', 'null', 'top', '0']: + elif str2bool(parent, False): return queryset.filter(parent=None) else: try: From deaaa48b7d15fd8f90d1ed91e494c8156018edf4 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 18 Apr 2019 23:12:29 +1000 Subject: [PATCH 2/6] Add ability to 'copy' a part - Launch a PartCreate form - initialize form data with the existing part (if it exists!) - use model_to_dict to pass data around --- InvenTree/part/views.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 31bedc5c56..38e26468f4 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -5,6 +5,7 @@ from django.shortcuts import get_object_or_404 from django.urls import reverse_lazy from django.views.generic import DetailView, ListView +from django.forms.models import model_to_dict from company.models import Company from .models import PartCategory, Part, BomItem @@ -77,7 +78,18 @@ class PartCreate(AjaxCreateView): # Pre-fill the category field if a valid category is provided def get_initial(self): - initials = super(PartCreate, self).get_initial().copy() + # Is the client attempting to copy an existing part? + part_to_copy = self.request.GET.get('copy_part', None) + + if part_to_copy: + try: + original = Part.objects.get(pk=part_to_copy) + initials = model_to_dict(original) + except Part.DoesNotExist: + initials = super(PartCreate, self).get_initial() + + else: + initials = super(PartCreate, self).get_initial() if self.get_category_id(): initials['category'] = get_object_or_404(PartCategory, pk=self.get_category_id()) From 6de58edd41c199d698d4f7a17d020425e9d240fb Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 18 Apr 2019 23:17:21 +1000 Subject: [PATCH 3/6] Add button on part page to duplicate part - Opens modal form - Takes user to created page --- InvenTree/part/templates/part/part_base.html | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index c97423ed86..36283caeca 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -32,7 +32,7 @@ {{ part.URL }} {% endif %} - + @@ -95,4 +95,17 @@ } ); }); + + $("#duplicate-part").click(function() { + launchModalForm( + "{% url 'part-create' %}", + { + follow: true, + data: { + copy_part: {{ part.id }}, + }, + } + ); + }); + {% endblock %} \ No newline at end of file From 05beb26c82c508114126c6557125d25809f54ffb Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 18 Apr 2019 23:22:58 +1000 Subject: [PATCH 4/6] Change form title if part is being copied --- InvenTree/part/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 38e26468f4..031bb3ed60 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -50,8 +50,7 @@ class PartCreate(AjaxCreateView): """ model = Part form_class = EditPartForm - template_name = 'part/create.html' - + ajax_form_title = 'Create new part' ajax_template_name = 'modal_form.html' @@ -85,6 +84,7 @@ class PartCreate(AjaxCreateView): try: original = Part.objects.get(pk=part_to_copy) initials = model_to_dict(original) + self.ajax_form_title = "Copy Part '{p}'".format(p=original.name) except Part.DoesNotExist: initials = super(PartCreate, self).get_initial() From 8040ad8a6abf457b3fca98f63d09d9878009c103 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 18 Apr 2019 23:28:46 +1000 Subject: [PATCH 5/6] Add function to duplicate stock item --- InvenTree/part/templates/part/part_base.html | 2 +- InvenTree/part/views.py | 2 +- InvenTree/stock/templates/stock/item.html | 14 ++++++++++++++ InvenTree/stock/views.py | 16 +++++++++++++++- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index 36283caeca..df19003b21 100644 --- a/InvenTree/part/templates/part/part_base.html +++ b/InvenTree/part/templates/part/part_base.html @@ -102,7 +102,7 @@ { follow: true, data: { - copy_part: {{ part.id }}, + copy: {{ part.id }}, }, } ); diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 031bb3ed60..2778a6a806 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -78,7 +78,7 @@ class PartCreate(AjaxCreateView): def get_initial(self): # Is the client attempting to copy an existing part? - part_to_copy = self.request.GET.get('copy_part', None) + part_to_copy = self.request.GET.get('copy', None) if part_to_copy: try: diff --git a/InvenTree/stock/templates/stock/item.html b/InvenTree/stock/templates/stock/item.html index f1f0a5db1d..aee40d513d 100644 --- a/InvenTree/stock/templates/stock/item.html +++ b/InvenTree/stock/templates/stock/item.html @@ -13,6 +13,7 @@