Adds simply endpoint for BOM duplication

This commit is contained in:
Oliver 2021-12-21 17:16:27 +11:00
parent 09777c5764
commit 0c8a047bc2
8 changed files with 102 additions and 111 deletions

View File

@ -454,6 +454,26 @@ class PartSerialNumberDetail(generics.RetrieveAPIView):
return Response(data)
class PartCopyBOM(generics.CreateAPIView):
"""
API endpoint for duplicating a BOM
"""
queryset = Part.objects.all()
serializer_class = part_serializers.PartCopyBOMSerializer
def get_serializer_context(self):
ctx = super().get_serializer_context()
try:
ctx['part'] = Part.objects.get(pk=self.kwargs.get('pk', None))
except:
pass
return ctx
class PartDetail(generics.RetrieveUpdateDestroyAPIView):
""" API endpoint for detail view of a single Part object """
@ -1585,6 +1605,9 @@ part_api_urls = [
# Endpoint for extra serial number information
url(r'^serial-numbers/', PartSerialNumberDetail.as_view(), name='api-part-serial-number-detail'),
# Endpoint for duplicating a BOM
url(r'^copy-bom/', PartCopyBOM.as_view(), name='api-part-copy-bom'),
# Part detail endpoint
url(r'^.*$', PartDetail.as_view(), name='api-part-detail'),
])),

View File

@ -55,39 +55,6 @@ class PartImageDownloadForm(HelperForm):
]
class BomDuplicateForm(HelperForm):
"""
Simple confirmation form for BOM duplication.
Select which parent to select from.
"""
parent = PartModelChoiceField(
label=_('Parent Part'),
help_text=_('Select parent part to copy BOM from'),
queryset=Part.objects.filter(is_template=True),
)
clear = forms.BooleanField(
required=False, initial=True,
help_text=_('Clear existing BOM items')
)
confirm = forms.BooleanField(
required=False, initial=False,
label=_('Confirm'),
help_text=_('Confirm BOM duplication')
)
class Meta:
model = Part
fields = [
'parent',
'clear',
'confirm',
]
class BomValidateForm(HelperForm):
""" Simple confirmation form for BOM validation.
User is presented with a single checkbox input,

View File

@ -9,6 +9,7 @@ from django.urls import reverse_lazy
from django.db import models
from django.db.models import Q
from django.db.models.functions import Coalesce
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from sql_util.utils import SubqueryCount, SubquerySum
@ -636,3 +637,53 @@ class CategoryParameterTemplateSerializer(InvenTreeModelSerializer):
'parameter_template',
'default_value',
]
class PartCopyBOMSerializer(serializers.Serializer):
"""
Serializer for copying a BOM from another part
"""
class Meta:
fields = [
'part',
'remove_existing',
]
part = serializers.PrimaryKeyRelatedField(
queryset=Part.objects.all(),
many=False,
required=True,
allow_null=False,
label=_('Part'),
help_text=_('Select part to copy BOM from'),
)
def validate_part(self, part):
"""
Check that a 'valid' part was selected
"""
# Check if the BOM can be copied from the provided part
base_part = self.context['part']
return part
remove_existing = serializers.BooleanField(
label=_('Remove Existing Data'),
help_text=_('Remove existing BOM items before copying')
)
def save(self):
"""
Actually duplicate the BOM
"""
base_part = self.context['part']
data = self.validated_data
part = data['part']
clear = data.get('remove_existing', True)
base_part.copy_bom_from(part, clear=clear)

View File

@ -1,17 +0,0 @@
{% extends "modal_form.html" %}
{% load i18n %}
{% block pre_form_content %}
<p>
{% trans "Select parent part to copy BOM from" %}
</p>
{% if part.has_bom %}
<div class='alert alert-block alert-danger'>
<strong>{% trans "Warning" %}</strong><br>
{% trans "This part already has a Bill of Materials" %}<br>
</div>
{% endif %}
{% endblock %}

View File

@ -580,14 +580,10 @@
});
$('#bom-duplicate').click(function() {
launchModalForm(
"{% url 'duplicate-bom' part.id %}",
{
success: function() {
$('#bom-table').bootstrapTable('refresh');
}
}
);
duplicateBom({{ part.pk }}, {
});
});
$("#bom-item-new").click(function () {

View File

@ -40,7 +40,6 @@ part_detail_urls = [
url(r'^pricing/', views.PartPricing.as_view(), name='part-pricing'),
url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'),
url(r'^bom-duplicate/?', views.BomDuplicate.as_view(), name='duplicate-bom'),
url(r'^qr_code/?', views.PartQRCode.as_view(), name='part-qr'),

View File

@ -694,58 +694,6 @@ class PartImageSelect(AjaxUpdateView):
return self.renderJsonResponse(request, form, data)
class BomDuplicate(AjaxUpdateView):
"""
View for duplicating BOM from a parent item.
"""
model = Part
context_object_name = 'part'
ajax_form_title = _('Duplicate BOM')
ajax_template_name = 'part/bom_duplicate.html'
form_class = part_forms.BomDuplicateForm
def get_form(self):
form = super().get_form()
# Limit choices to parents of the current part
parents = self.get_object().get_ancestors()
form.fields['parent'].queryset = parents
return form
def get_initial(self):
initials = super().get_initial()
parents = self.get_object().get_ancestors()
if parents.count() == 1:
initials['parent'] = parents[0]
return initials
def validate(self, part, form):
confirm = str2bool(form.cleaned_data.get('confirm', False))
if not confirm:
form.add_error('confirm', _('Confirm duplication of BOM from parent'))
def save(self, part, form):
"""
Duplicate BOM from the specified parent
"""
parent = form.cleaned_data.get('parent', None)
clear = str2bool(form.cleaned_data.get('clear', True))
if parent:
part.copy_bom_from(parent, clear=clear)
class BomValidate(AjaxUpdateView):
"""
Modal form view for validating a part BOM

View File

@ -21,6 +21,7 @@
*/
/* exported
duplicateBom,
duplicatePart,
editCategory,
editPart,
@ -428,6 +429,29 @@ function toggleStar(options) {
}
/* Duplicate a BOM */
function duplicateBom(part_id, options={}) {
constructForm(`/api/part/${part_id}/copy-bom/`, {
method: 'POST',
fields: {
part: {
icon: 'fa-shapes',
filters: {
assembly: true,
ancestor: part_id,
}
},
remove_existing: {
value: true,
},
},
confirm: true,
title: '{% trans "Copy Bill of Materials" %}',
});
}
function partStockLabel(part, options={}) {
if (part.in_stock) {