diff --git a/InvenTree/part/forms.py b/InvenTree/part/forms.py index 1564c16316..4512859828 100644 --- a/InvenTree/part/forms.py +++ b/InvenTree/part/forms.py @@ -38,24 +38,15 @@ class BomValidateForm(HelperForm): ] -class BomExportForm(HelperForm): +class BomImportForm(HelperForm): + """ Form for importing a BOM. Provides a file input box for upload """ - # TODO - Define these choices somewhere else, and import them here - format_choices = ( - ('csv', 'CSV'), - ('pdf', 'PDF'), - ('xml', 'XML'), - ('xlsx', 'XLSX'), - ('html', 'HTML') - ) - - # Select export type - format = forms.CharField(label='Format', widget=forms.Select(choices=format_choices), required='true', help_text='Select export format') + bom_file = forms.FileField(label='BOM file', required=True, help_text="Select BOM file to upload") class Meta: model = Part fields = [ - 'format', + 'bom_file', ] diff --git a/InvenTree/part/templates/part/bom.html b/InvenTree/part/templates/part/bom.html index 3133aa1706..04101ab995 100644 --- a/InvenTree/part/templates/part/bom.html +++ b/InvenTree/part/templates/part/bom.html @@ -34,6 +34,7 @@
{% if editing_enabled %} + {% else %} @@ -106,6 +107,12 @@ ); }); + $("#bom-upload").click(function() { + launchModalForm( + "{% url 'bom-import' part.id %}", + ); + }); + {% else %} $("#validate-bom").click(function() { diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py index 7dc53372cd..a8f5184972 100644 --- a/InvenTree/part/urls.py +++ b/InvenTree/part/urls.py @@ -22,6 +22,7 @@ part_detail_urls = [ url(r'^edit/?', views.PartEdit.as_view(), name='part-edit'), url(r'^delete/?', views.PartDelete.as_view(), name='part-delete'), url(r'^bom-export/?', views.BomDownload.as_view(), name='bom-export'), + url(r'^bom-import/?', views.BomUpload.as_view(), name='bom-import'), url(r'^validate-bom/', views.BomValidate.as_view(), name='bom-validate'), url(r'^duplicate/', views.PartDuplicate.as_view(), name='part-duplicate'), url(r'^make-variant/', views.MakePartVariant.as_view(), name='make-part-variant'), diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 49fa2bd8dd..12c2b808d8 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -616,6 +616,68 @@ class BomValidate(AjaxUpdateView): return self.renderJsonResponse(request, form, data, context=self.get_context()) +class BomUpload(AjaxView): + """ View for uploading a BOM file, and handling BOM data importing. + + The BOM upload process is as follows: + + 1. (Client) Select and upload BOM file + 2. (Server) Verify that supplied file is a file compatible with tablib library + 3. (Server) Introspect data file, try to find sensible columns / values / etc + 4. (Server) Send suggestions back to the client + 5. (Client) Makes choices based on suggestions: + - Accept automatic matching to parts found in database + - Accept suggestions for 'partial' or 'fuzzy' matches + - Create new parts in case of parts not being available + 6. (Client) Sends updated dataset back to server + 7. (Server) Check POST data for validity, sanity checking, etc. + 8. (Server) Respond to POST request + - If data are valid, proceed to 9. + - If data not valid, return to 4. + 9. (Server) Send confirmation form to user + - Display the actions which will occur + - Provide final "CONFIRM" button + 10. (Client) Confirm final changes + 11. (Server) Apply changes to database, update BOM items. + + During these steps, data are passed between the server/client as JSON objects. + """ + + def get_form(self): + """ Return the correct form for the given step in the upload process """ + + if 1 or self.request.method == 'GET': + form = part_forms.BomImportForm() + + return form + + def get(self, request, *args, **kwargs): + """ Perform the initial 'GET' request. + + Initially returns a form for file upload """ + + # A valid Part object must be supplied. This is the 'parent' part for the BOM + part = get_object_or_404(Part, pk=self.kwargs['pk']) + + form = self.get_form() + + return self.renderJsonResponse(request, form) + + def post(self, request, *args, **kwargs): + """ Perform the various 'POST' requests required. + """ + + data = { + 'form_valid': False, + } + + form = self.get_form() + + form.errors['bom_file'] = ['Nah mate'] + + return self.renderJsonResponse(request, form, data=data) + + class BomDownload(AjaxView): """ Provide raw download of a BOM file.