diff --git a/InvenTree/company/templates/company/detail.html b/InvenTree/company/templates/company/detail.html
index b45289eb8c..4a9ac43758 100644
--- a/InvenTree/company/templates/company/detail.html
+++ b/InvenTree/company/templates/company/detail.html
@@ -267,16 +267,8 @@
});
$("#stock-export").click(function() {
- launchModalForm("{% url 'stock-export-options' %}", {
- submit_text: '{% trans "Export" %}',
- success: function(response) {
- var url = "{% url 'stock-export' %}";
-
- url += "?format=" + response.format;
- url += "&supplier={{ company.id }}";
-
- location.href = url;
- },
+ exportStock({
+ supplier: {{ company.id }}
});
});
diff --git a/InvenTree/company/templates/company/supplier_part.html b/InvenTree/company/templates/company/supplier_part.html
index f751665e56..ec85d85af9 100644
--- a/InvenTree/company/templates/company/supplier_part.html
+++ b/InvenTree/company/templates/company/supplier_part.html
@@ -284,18 +284,11 @@ loadStockTable($("#stock-table"), {
});
$("#stock-export").click(function() {
- launchModalForm("{% url 'stock-export-options' %}", {
- submit_text: '{% trans "Export" %}',
- success: function(response) {
- var url = "{% url 'stock-export' %}";
- url += "?format=" + response.format;
- url += "&cascade=" + response.cascade;
- url += "&supplier_part={{ part.id }}";
-
- location.href = url;
- },
+ exportStock({
+ supplier_part: {{ part.pk }},
});
+
});
$("#item-create").click(function() {
diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html
index b057b98209..b4cebe478e 100644
--- a/InvenTree/part/templates/part/detail.html
+++ b/InvenTree/part/templates/part/detail.html
@@ -644,17 +644,9 @@
});
$("#stock-export").click(function() {
- launchModalForm("{% url 'stock-export-options' %}", {
- submit_text: "{% trans 'Export' %}",
- success: function(response) {
- var url = "{% url 'stock-export' %}";
- url += "?format=" + response.format;
- url += "&cascade=" + response.cascade;
- url += "&part={{ part.id }}";
-
- location.href = url;
- },
+ exportStock({
+ part: {{ part.pk }}
});
});
diff --git a/InvenTree/report/models.py b/InvenTree/report/models.py
index c33347f643..db06e1c95b 100644
--- a/InvenTree/report/models.py
+++ b/InvenTree/report/models.py
@@ -357,7 +357,8 @@ class TestReport(ReportTemplateBase):
'serial': stock_item.serial,
'part': stock_item.part,
'results': stock_item.testResultMap(include_installed=self.include_installed),
- 'result_list': stock_item.testResultList(include_installed=self.include_installed)
+ 'result_list': stock_item.testResultList(include_installed=self.include_installed),
+ 'installed_items': stock_item.get_installed_items(cascade=True),
}
diff --git a/InvenTree/report/templates/report/inventree_test_report_base.html b/InvenTree/report/templates/report/inventree_test_report_base.html
index 4c585d531b..d6d9c5644f 100644
--- a/InvenTree/report/templates/report/inventree_test_report_base.html
+++ b/InvenTree/report/templates/report/inventree_test_report_base.html
@@ -56,6 +56,10 @@ content: "{% trans 'Stock Item Test Report' %}";
{% endblock %}
+{% block pre_page_content %}
+
+{% endblock %}
+
{% block page_content %}
@@ -80,6 +84,7 @@ content: "{% trans 'Stock Item Test Report' %}";
+{% if resul_list|length > 0 %}
{% trans "Test Results" %}
@@ -112,5 +117,37 @@ content: "{% trans 'Stock Item Test Report' %}";
+{% endif %}
+
+{% if installed_items|length > 0 %}
+{% trans "Installed Items" %}
+
+
+
+
+
+ {% for sub_item in installed_items %}
+
+
+
+ {{ sub_item.part.full_name }}
+ |
+
+ {% if sub_item.serialized %}
+ {% trans "Serial" %}: {{ sub_item.serial }}
+ {% else %}
+ {% trans "Quantity" %}: {% decimal sub_item.quantity %}
+ {% endif %}
+ |
+
+ {% endfor %}
+
+
+
+{% endif %}
+
+{% endblock %}
+
+{% block post_page_content %}
{% endblock %}
\ No newline at end of file
diff --git a/InvenTree/stock/forms.py b/InvenTree/stock/forms.py
index 0061bbb984..b23b71a2d6 100644
--- a/InvenTree/stock/forms.py
+++ b/InvenTree/stock/forms.py
@@ -13,7 +13,6 @@ from django.core.exceptions import ValidationError
from mptt.fields import TreeNodeChoiceField
-from InvenTree.helpers import GetExportFormats
from InvenTree.forms import HelperForm
from InvenTree.fields import RoundingDecimalFormField
from InvenTree.fields import DatePickerFormField
@@ -226,33 +225,6 @@ class TestReportFormatForm(HelperForm):
template = forms.ChoiceField(label=_('Template'), help_text=_('Select test report template'))
-class ExportOptionsForm(HelperForm):
- """ Form for selecting stock export options """
-
- file_format = forms.ChoiceField(label=_('File Format'), help_text=_('Select output file format'))
-
- include_sublocations = forms.BooleanField(required=False, initial=True, label=_('Include sublocations'), help_text=_("Include stock items in sub locations"))
-
- class Meta:
- model = StockLocation
- fields = [
- 'file_format',
- 'include_sublocations',
- ]
-
- def get_format_choices(self):
- """ File format choices """
-
- choices = [(x, x.upper()) for x in GetExportFormats()]
-
- return choices
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- self.fields['file_format'].choices = self.get_format_choices()
-
-
class InstallStockForm(HelperForm):
"""
Form for manually installing a stock item into another stock item
diff --git a/InvenTree/stock/templates/stock/location.html b/InvenTree/stock/templates/stock/location.html
index 229ad9cfd1..9a5aeb6a7e 100644
--- a/InvenTree/stock/templates/stock/location.html
+++ b/InvenTree/stock/templates/stock/location.html
@@ -227,20 +227,11 @@
{% endif %}
$("#stock-export").click(function() {
- launchModalForm("{% url 'stock-export-options' %}", {
- submit_text: '{% trans "Export" %}',
- success: function(response) {
- var url = "{% url 'stock-export' %}";
- url += "?format=" + response.format;
- url += "&cascade=" + response.cascade;
-
- {% if location %}
- url += "&location={{ location.id }}";
- {% endif %}
-
- location.href = url;
- }
+ exportStock({
+ {% if location %}
+ location: {{ location.pk }}
+ {% endif %}
});
});
diff --git a/InvenTree/stock/urls.py b/InvenTree/stock/urls.py
index bcf180b700..434acde84e 100644
--- a/InvenTree/stock/urls.py
+++ b/InvenTree/stock/urls.py
@@ -56,7 +56,6 @@ stock_urls = [
url(r'^track/', include(stock_tracking_urls)),
- url(r'^export-options/?', views.StockExportOptions.as_view(), name='stock-export-options'),
url(r'^export/?', views.StockExport.as_view(), name='stock-export'),
# Individual stock items
diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py
index 6b64e8b54a..008b209bc8 100644
--- a/InvenTree/stock/views.py
+++ b/InvenTree/stock/views.py
@@ -378,38 +378,6 @@ class StockItemDeleteTestData(AjaxUpdateView):
return self.renderJsonResponse(request, form, data)
-class StockExportOptions(AjaxView):
- """ Form for selecting StockExport options """
-
- model = StockLocation
- ajax_form_title = _('Stock Export Options')
- form_class = StockForms.ExportOptionsForm
-
- def post(self, request, *args, **kwargs):
-
- self.request = request
-
- fmt = request.POST.get('file_format', 'csv').lower()
- cascade = str2bool(request.POST.get('include_sublocations', False))
-
- # Format a URL to redirect to
- url = reverse('stock-export')
-
- url += '?format=' + fmt
- url += '&cascade=' + str(cascade)
-
- data = {
- 'form_valid': True,
- 'format': fmt,
- 'cascade': cascade
- }
-
- return self.renderJsonResponse(self.request, self.form_class(), data=data)
-
- def get(self, request, *args, **kwargs):
- return self.renderJsonResponse(request, self.form_class())
-
-
class StockExport(AjaxView):
""" Export stock data from a particular location.
Returns a file containing stock information for that location.
@@ -471,11 +439,10 @@ class StockExport(AjaxView):
)
if location:
- # CHeck if locations should be cascading
+ # Check if locations should be cascading
cascade = str2bool(request.GET.get('cascade', True))
stock_items = location.get_stock_items(cascade)
else:
- cascade = True
stock_items = StockItem.objects.all()
if part:
diff --git a/InvenTree/templates/js/forms.js b/InvenTree/templates/js/forms.js
index 568ca5ac58..587ea07a16 100644
--- a/InvenTree/templates/js/forms.js
+++ b/InvenTree/templates/js/forms.js
@@ -252,6 +252,11 @@ function constructDeleteForm(fields, options) {
*/
function constructForm(url, options) {
+ // An "empty" form will be defined locally
+ if (url == null) {
+ constructFormBody({}, options);
+ }
+
// Save the URL
options.url = url;
@@ -378,6 +383,11 @@ function constructFormBody(fields, options) {
fields[field].placeholder = field_options.placeholder;
}
+ // Choices
+ if (field_options.choices) {
+ fields[field].choices = field_options.choices;
+ }
+
// Field prefix
if (field_options.prefix) {
fields[field].prefix = field_options.prefix;
diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js
index 1d38b631a5..947e7fb3e9 100644
--- a/InvenTree/templates/js/stock.js
+++ b/InvenTree/templates/js/stock.js
@@ -20,6 +20,55 @@ function stockStatusCodes() {
}
+/*
+ * Export stock table
+ */
+function exportStock(params={}) {
+
+ constructFormBody({}, {
+ title: '{% trans "Export Stock" %}',
+ fields: {
+ format: {
+ label: '{% trans "Format" %}',
+ help_text: '{% trans "Select file format" %}',
+ required: true,
+ type: 'choice',
+ value: 'csv',
+ choices: [
+ { value: 'csv', display_name: 'CSV' },
+ { value: 'tsv', display_name: 'TSV' },
+ { value: 'xls', display_name: 'XLS' },
+ { value: 'xlsx', display_name: 'XLSX' },
+ ]
+ },
+ sublocations: {
+ label: '{% trans "Include Sublocations" %}',
+ help_text: '{% trans "Include stock items in sublocations" %}',
+ type: 'boolean',
+ value: 'true',
+ }
+ },
+ onSubmit: function(fields, form_options) {
+
+ var format = getFormFieldValue('format', fields['format'], form_options);
+ var cascade = getFormFieldValue('sublocations', fields['sublocations'], form_options);
+
+ // Hide the modal
+ $(form_options.modal).modal('hide');
+
+ var url = `{% url "stock-export" %}?format=${format}&cascade=${cascade}`;
+
+ for (var key in params) {
+ url += `&${key}=${params[key]}`;
+ }
+
+ console.log(url);
+ location.href = url;
+ }
+ });
+}
+
+
/**
* Perform stock adjustments
*/