mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
"Validate BOM" now uses the API also
This commit is contained in:
parent
70f9a0fe13
commit
2c0da25cbc
@ -474,6 +474,56 @@ class PartCopyBOM(generics.CreateAPIView):
|
|||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
|
class PartValidateBOM(generics.RetrieveUpdateAPIView):
|
||||||
|
"""
|
||||||
|
API endpoint for 'validating' the BOM for a given Part
|
||||||
|
"""
|
||||||
|
|
||||||
|
class BOMValidateSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Part
|
||||||
|
fields = [
|
||||||
|
'checksum',
|
||||||
|
'valid',
|
||||||
|
]
|
||||||
|
|
||||||
|
checksum = serializers.CharField(
|
||||||
|
read_only=True,
|
||||||
|
source='bom_checksum',
|
||||||
|
)
|
||||||
|
|
||||||
|
valid = serializers.BooleanField(
|
||||||
|
write_only=True,
|
||||||
|
default=False,
|
||||||
|
label=_('Valid'),
|
||||||
|
help_text=_('Validate entire Bill of Materials'),
|
||||||
|
)
|
||||||
|
|
||||||
|
def validate_valid(self, valid):
|
||||||
|
if not valid:
|
||||||
|
raise ValidationError(_('This option must be selected'))
|
||||||
|
|
||||||
|
queryset = Part.objects.all()
|
||||||
|
|
||||||
|
serializer_class = BOMValidateSerializer
|
||||||
|
|
||||||
|
def update(self, request, *args, **kwargs):
|
||||||
|
|
||||||
|
part = self.get_object()
|
||||||
|
|
||||||
|
partial = kwargs.pop('partial', False)
|
||||||
|
|
||||||
|
serializer = self.get_serializer(part, data=request.data, partial=partial)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
||||||
|
part.validate_bom(request.user)
|
||||||
|
|
||||||
|
return Response({
|
||||||
|
'checksum': part.bom_checksum,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class PartDetail(generics.RetrieveUpdateDestroyAPIView):
|
class PartDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||||
""" API endpoint for detail view of a single Part object """
|
""" API endpoint for detail view of a single Part object """
|
||||||
|
|
||||||
@ -1605,8 +1655,11 @@ part_api_urls = [
|
|||||||
# Endpoint for extra serial number information
|
# Endpoint for extra serial number information
|
||||||
url(r'^serial-numbers/', PartSerialNumberDetail.as_view(), name='api-part-serial-number-detail'),
|
url(r'^serial-numbers/', PartSerialNumberDetail.as_view(), name='api-part-serial-number-detail'),
|
||||||
|
|
||||||
# Endpoint for duplicating a BOM
|
# Endpoint for duplicating a BOM for the specific Part
|
||||||
url(r'^copy-bom/', PartCopyBOM.as_view(), name='api-part-copy-bom'),
|
url(r'^bom-copy/', PartCopyBOM.as_view(), name='api-part-bom-copy'),
|
||||||
|
|
||||||
|
# Endpoint for validating a BOM for the specific Part
|
||||||
|
url(r'^bom-validate/', PartValidateBOM.as_view(), name='api-part-bom-validate'),
|
||||||
|
|
||||||
# Part detail endpoint
|
# Part detail endpoint
|
||||||
url(r'^.*$', PartDetail.as_view(), name='api-part-detail'),
|
url(r'^.*$', PartDetail.as_view(), name='api-part-detail'),
|
||||||
|
@ -55,21 +55,6 @@ class PartImageDownloadForm(HelperForm):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class BomValidateForm(HelperForm):
|
|
||||||
""" Simple confirmation form for BOM validation.
|
|
||||||
User is presented with a single checkbox input,
|
|
||||||
to confirm that the BOM for this part is valid
|
|
||||||
"""
|
|
||||||
|
|
||||||
validate = forms.BooleanField(required=False, initial=False, label=_('validate'), help_text=_('Confirm that the BOM is correct'))
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Part
|
|
||||||
fields = [
|
|
||||||
'validate'
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class BomMatchItemForm(MatchItemForm):
|
class BomMatchItemForm(MatchItemForm):
|
||||||
""" Override MatchItemForm fields """
|
""" Override MatchItemForm fields """
|
||||||
|
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
{% extends "modal_form.html" %}
|
|
||||||
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block pre_form_content %}
|
|
||||||
{% blocktrans with part.full_name as part %}Confirm that the Bill of Materials (BOM) is valid for:<br><em>{{ part }}</em>{% endblocktrans %}
|
|
||||||
|
|
||||||
<div class='alert alert-warning alert-block'>
|
|
||||||
{% trans 'This will validate each line in the BOM.' %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@ -609,12 +609,10 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
$("#validate-bom").click(function() {
|
$("#validate-bom").click(function() {
|
||||||
launchModalForm(
|
|
||||||
"{% url 'bom-validate' part.id %}",
|
validateBom({{ part.id }}, {
|
||||||
{
|
reload: true
|
||||||
reload: true,
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#download-bom").click(function () {
|
$("#download-bom").click(function () {
|
||||||
|
@ -35,7 +35,6 @@ part_detail_urls = [
|
|||||||
url(r'^delete/?', views.PartDelete.as_view(), name='part-delete'),
|
url(r'^delete/?', views.PartDelete.as_view(), name='part-delete'),
|
||||||
url(r'^bom-export/?', views.BomExport.as_view(), name='bom-export'),
|
url(r'^bom-export/?', views.BomExport.as_view(), name='bom-export'),
|
||||||
url(r'^bom-download/?', views.BomDownload.as_view(), name='bom-download'),
|
url(r'^bom-download/?', views.BomDownload.as_view(), name='bom-download'),
|
||||||
url(r'^validate-bom/', views.BomValidate.as_view(), name='bom-validate'),
|
|
||||||
|
|
||||||
url(r'^pricing/', views.PartPricing.as_view(), name='part-pricing'),
|
url(r'^pricing/', views.PartPricing.as_view(), name='part-pricing'),
|
||||||
|
|
||||||
|
@ -694,48 +694,6 @@ class PartImageSelect(AjaxUpdateView):
|
|||||||
return self.renderJsonResponse(request, form, data)
|
return self.renderJsonResponse(request, form, data)
|
||||||
|
|
||||||
|
|
||||||
class BomValidate(AjaxUpdateView):
|
|
||||||
"""
|
|
||||||
Modal form view for validating a part BOM
|
|
||||||
"""
|
|
||||||
|
|
||||||
model = Part
|
|
||||||
ajax_form_title = _("Validate BOM")
|
|
||||||
ajax_template_name = 'part/bom_validate.html'
|
|
||||||
context_object_name = 'part'
|
|
||||||
form_class = part_forms.BomValidateForm
|
|
||||||
|
|
||||||
def get_context(self):
|
|
||||||
return {
|
|
||||||
'part': self.get_object(),
|
|
||||||
}
|
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
|
|
||||||
form = self.get_form()
|
|
||||||
|
|
||||||
return self.renderJsonResponse(request, form, context=self.get_context())
|
|
||||||
|
|
||||||
def validate(self, part, form, **kwargs):
|
|
||||||
|
|
||||||
confirm = str2bool(form.cleaned_data.get('validate', False))
|
|
||||||
|
|
||||||
if not confirm:
|
|
||||||
form.add_error('validate', _('Confirm that the BOM is valid'))
|
|
||||||
|
|
||||||
def save(self, part, form, **kwargs):
|
|
||||||
"""
|
|
||||||
Mark the BOM as validated
|
|
||||||
"""
|
|
||||||
|
|
||||||
part.validate_bom(self.request.user)
|
|
||||||
|
|
||||||
def get_data(self):
|
|
||||||
return {
|
|
||||||
'success': _('Validated Bill of Materials')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class BomUpload(InvenTreeRoleMixin, FileManagementFormView):
|
class BomUpload(InvenTreeRoleMixin, FileManagementFormView):
|
||||||
""" View for uploading a BOM file, and handling BOM data importing.
|
""" View for uploading a BOM file, and handling BOM data importing.
|
||||||
|
|
||||||
|
@ -207,6 +207,11 @@ function showApiError(xhr, url) {
|
|||||||
title = '{% trans "Error 404: Resource Not Found" %}';
|
title = '{% trans "Error 404: Resource Not Found" %}';
|
||||||
message = '{% trans "The requested resource could not be located on the server" %}';
|
message = '{% trans "The requested resource could not be located on the server" %}';
|
||||||
break;
|
break;
|
||||||
|
// Method not allowed
|
||||||
|
case 405:
|
||||||
|
title = '{% trans "Error 405: Method Not Allowed" %}';
|
||||||
|
message = '{% trans "HTTP method not allowed at URL" %}';
|
||||||
|
break;
|
||||||
// Timeout
|
// Timeout
|
||||||
case 408:
|
case 408:
|
||||||
title = '{% trans "Error 408: Timeout" %}';
|
title = '{% trans "Error 408: Timeout" %}';
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
loadStockPricingChart,
|
loadStockPricingChart,
|
||||||
partStockLabel,
|
partStockLabel,
|
||||||
toggleStar,
|
toggleStar,
|
||||||
|
validateBom,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Part API functions
|
/* Part API functions
|
||||||
@ -429,9 +430,34 @@ function toggleStar(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Validate a BOM */
|
||||||
|
function validateBom(part_id, options={}) {
|
||||||
|
|
||||||
|
var html = `
|
||||||
|
<div class='alert alert-block alert-success'>
|
||||||
|
{% trans "Validating the BOM will mark each line item as valid" %}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
constructForm(`/api/part/${part_id}/bom-validate/`, {
|
||||||
|
method: 'PUT',
|
||||||
|
fields: {
|
||||||
|
valid: {},
|
||||||
|
},
|
||||||
|
preFormContent: html,
|
||||||
|
title: '{% trans "Validate Bill of Materials" %}',
|
||||||
|
reload: options.reload,
|
||||||
|
onSuccess: function(response) {
|
||||||
|
showMessage('{% trans "Validated Bill of Materials" %}');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Duplicate a BOM */
|
/* Duplicate a BOM */
|
||||||
function duplicateBom(part_id, options={}) {
|
function duplicateBom(part_id, options={}) {
|
||||||
constructForm(`/api/part/${part_id}/copy-bom/`, {
|
|
||||||
|
constructForm(`/api/part/${part_id}/bom-copy/`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
fields: {
|
fields: {
|
||||||
part: {
|
part: {
|
||||||
|
Loading…
Reference in New Issue
Block a user