diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py index ba3f3525d5..a492ca353d 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..94dee8e95c 100644 --- a/InvenTree/InvenTree/models.py +++ b/InvenTree/InvenTree/models.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals from django.db import models from django.contrib.contenttypes.models import ContentType from rest_framework.exceptions import ValidationError +from .helpers import str2bool from django.db.models.signals import pre_delete from django.dispatch import receiver @@ -183,7 +184,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: diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html index c97423ed86..df19003b21 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.id }}, + }, + } + ); + }); + {% endblock %} \ No newline at end of file diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 31bedc5c56..4f7175301a 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 @@ -49,7 +50,6 @@ 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' @@ -77,7 +77,19 @@ 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', None) + + if part_to_copy: + 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() + + else: + initials = super(PartCreate, self).get_initial() if self.get_category_id(): initials['category'] = get_object_or_404(PartCategory, pk=self.get_category_id()) 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 @@