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.