2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-05-07 07:48:50 +00:00

Adds ability to export sales order line table to a file (#4392)

* Adds ability to export sales order line table to a file

* Fix expand / collapse buttons

* Fix other expand / collapse buttons

* Add export functionality for "extra" line items
This commit is contained in:
Oliver 2023-02-23 07:20:03 +11:00 committed by GitHub
parent 71af30f0d2
commit 92a049be96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 79 additions and 25 deletions

View File

@ -26,20 +26,22 @@ from InvenTree.helpers import DownloadFile, str2bool
from InvenTree.mixins import (CreateAPI, ListAPI, ListCreateAPI, from InvenTree.mixins import (CreateAPI, ListAPI, ListCreateAPI,
RetrieveUpdateAPI, RetrieveUpdateDestroyAPI) RetrieveUpdateAPI, RetrieveUpdateDestroyAPI)
from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus
from order.admin import (PurchaseOrderLineItemResource, PurchaseOrderResource, from order.admin import (PurchaseOrderExtraLineResource,
SalesOrderResource) PurchaseOrderLineItemResource, PurchaseOrderResource,
SalesOrderExtraLineResource,
SalesOrderLineItemResource, SalesOrderResource)
from part.models import Part from part.models import Part
from plugin.serializers import MetadataSerializer from plugin.serializers import MetadataSerializer
from users.models import Owner from users.models import Owner
class GeneralExtraLineList: class GeneralExtraLineList(APIDownloadMixin):
"""General template for ExtraLine API classes.""" """General template for ExtraLine API classes."""
def get_serializer(self, *args, **kwargs): def get_serializer(self, *args, **kwargs):
"""Return the serializer instance for this endpoint""" """Return the serializer instance for this endpoint"""
try: try:
params = self.request.query_params params = self.request.query_params3
kwargs['order_detail'] = str2bool(params.get('order_detail', False)) kwargs['order_detail'] = str2bool(params.get('order_detail', False))
except AttributeError: except AttributeError:
@ -606,6 +608,15 @@ class PurchaseOrderExtraLineList(GeneralExtraLineList, ListCreateAPI):
queryset = models.PurchaseOrderExtraLine.objects.all() queryset = models.PurchaseOrderExtraLine.objects.all()
serializer_class = serializers.PurchaseOrderExtraLineSerializer serializer_class = serializers.PurchaseOrderExtraLineSerializer
def download_queryset(self, queryset, export_format):
"""Download this queryset as a file"""
dataset = PurchaseOrderExtraLineResource().export(queryset=queryset)
filedata = dataset.export(export_format)
filename = f"InvenTree_ExtraPurchaseOrderLines.{export_format}"
return DownloadFile(filedata, filename)
class PurchaseOrderExtraLineDetail(RetrieveUpdateDestroyAPI): class PurchaseOrderExtraLineDetail(RetrieveUpdateDestroyAPI):
"""API endpoint for detail view of a PurchaseOrderExtraLine object.""" """API endpoint for detail view of a PurchaseOrderExtraLine object."""
@ -686,6 +697,7 @@ class SalesOrderList(APIDownloadMixin, ListCreateAPI):
def download_queryset(self, queryset, export_format): def download_queryset(self, queryset, export_format):
"""Download this queryset as a file""" """Download this queryset as a file"""
dataset = SalesOrderResource().export(queryset=queryset) dataset = SalesOrderResource().export(queryset=queryset)
filedata = dataset.export(export_format) filedata = dataset.export(export_format)
@ -857,7 +869,7 @@ class SalesOrderLineItemFilter(rest_filters.FilterSet):
return queryset return queryset
class SalesOrderLineItemList(ListCreateAPI): class SalesOrderLineItemList(APIDownloadMixin, ListCreateAPI):
"""API endpoint for accessing a list of SalesOrderLineItem objects.""" """API endpoint for accessing a list of SalesOrderLineItem objects."""
queryset = models.SalesOrderLineItem.objects.all() queryset = models.SalesOrderLineItem.objects.all()
@ -898,6 +910,16 @@ class SalesOrderLineItemList(ListCreateAPI):
return queryset return queryset
def download_queryset(self, queryset, export_format):
"""Download the requested queryset as a file"""
dataset = SalesOrderLineItemResource().export(queryset=queryset)
filedata = dataset.export(export_format)
filename = f"InvenTree_SalesOrderItems.{export_format}"
return DownloadFile(filedata, filename)
filter_backends = [ filter_backends = [
rest_filters.DjangoFilterBackend, rest_filters.DjangoFilterBackend,
filters.SearchFilter, filters.SearchFilter,
@ -924,6 +946,15 @@ class SalesOrderExtraLineList(GeneralExtraLineList, ListCreateAPI):
queryset = models.SalesOrderExtraLine.objects.all() queryset = models.SalesOrderExtraLine.objects.all()
serializer_class = serializers.SalesOrderExtraLineSerializer serializer_class = serializers.SalesOrderExtraLineSerializer
def download_queryset(self, queryset, export_format):
"""Download this queryset as a file"""
dataset = SalesOrderExtraLineResource().export(queryset=queryset)
filedata = dataset.export(export_format)
filename = f"InvenTree_ExtraSalesOrderLines.{export_format}"
return DownloadFile(filedata, filename)
class SalesOrderExtraLineDetail(RetrieveUpdateDestroyAPI): class SalesOrderExtraLineDetail(RetrieveUpdateDestroyAPI):
"""API endpoint for detail view of a SalesOrderExtraLine object.""" """API endpoint for detail view of a SalesOrderExtraLine object."""

View File

@ -31,8 +31,6 @@
<div class='panel-content'> <div class='panel-content'>
<div id='order-toolbar-buttons' class='btn-group' style='float: right;'> <div id='order-toolbar-buttons' class='btn-group' style='float: right;'>
<div class='btn-group'> <div class='btn-group'>
{% include "expand_rows.html" with label="sales-lines" %}
{% include "collapse_rows.html" with label="sales-lines" %}
{% include "filter_list.html" with id="sales-order-lines" %} {% include "filter_list.html" with id="sales-order-lines" %}
</div> </div>
</div> </div>
@ -93,8 +91,6 @@
{% if roles.sales_order.change %} {% if roles.sales_order.change %}
<div id='pending-shipment-toolbar' class='btn-group' style='float: right;'> <div id='pending-shipment-toolbar' class='btn-group' style='float: right;'>
<div class='btn-group' role='group'> <div class='btn-group' role='group'>
{% include "expand_rows.html" with label="pending-shipments" %}
{% include "collapse_rows.html" with label="pending-shipments" %}
{% include "filter_list.html" with id="pending-shipments" %} {% include "filter_list.html" with id="pending-shipments" %}
</div> </div>
</div> </div>
@ -111,8 +107,6 @@
<div class='panel-content'> <div class='panel-content'>
<div id='completed-shipment-toolbar' class='btn-group' style='float: right;'> <div id='completed-shipment-toolbar' class='btn-group' style='float: right;'>
<div class='btn-group' role='group'> <div class='btn-group' role='group'>
{% include "expand_rows.html" with label="completed-shipments" %}
{% include "collapse_rows.html" with label="completed-shipments" %}
{% include "filter_list.html" with id="completed-shipments" %} {% include "filter_list.html" with id="completed-shipments" %}
</div> </div>
</div> </div>

View File

@ -1,5 +0,0 @@
{% load i18n %}
<button id='{{ label }}-collapse' class='btn btn-outline-secondary' type='button' title='{% trans "Collapse all rows" %}'>
<span class='fas fa-compress'></span>
</button>

View File

@ -1,5 +0,0 @@
{% load i18n %}
<button id='{{ label }}-expand' class='btn btn-outline-secondary' type='button' title='{% trans "Expand all rows" %}'>
<span class='fas fa-expand'></span>
</button>

View File

@ -2231,7 +2231,14 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
var target = options.filter_target || '#filter-list-purchase-order-lines'; var target = options.filter_target || '#filter-list-purchase-order-lines';
setupFilterList('purchaseorderlineitem', $(table), target, {download: true}); setupFilterList(
'purchaseorderlineitem',
$(table),
target,
{
download: true
}
);
function setupCallbacks() { function setupCallbacks() {
if (options.allow_edit) { if (options.allow_edit) {
@ -2596,7 +2603,7 @@ function loadPurchaseOrderExtraLineTable(table, options={}) {
var filter_target = options.filter_target || '#filter-list-purchase-order-extra-lines'; var filter_target = options.filter_target || '#filter-list-purchase-order-extra-lines';
setupFilterList('purchaseorderextraline', $(table), filter_target); setupFilterList('purchaseorderextraline', $(table), filter_target, {download: true});
// Table columns to display // Table columns to display
var columns = [ var columns = [
@ -3072,6 +3079,7 @@ function loadSalesOrderShipmentTable(table, options={}) {
showColumns: true, showColumns: true,
detailView: true, detailView: true,
detailViewByClick: false, detailViewByClick: false,
buttons: constructExpandCollapseButtons(table),
detailFilter: function(index, row) { detailFilter: function(index, row) {
return row.allocations.length > 0; return row.allocations.length > 0;
}, },
@ -3871,7 +3879,14 @@ function loadSalesOrderLineItemTable(table, options={}) {
var filter_target = options.filter_target || '#filter-list-sales-order-lines'; var filter_target = options.filter_target || '#filter-list-sales-order-lines';
setupFilterList('salesorderlineitem', $(table), filter_target); setupFilterList(
'salesorderlineitem',
$(table),
filter_target,
{
download: true,
}
);
// Is the order pending? // Is the order pending?
var pending = options.pending; var pending = options.pending;
@ -4333,6 +4348,7 @@ function loadSalesOrderLineItemTable(table, options={}) {
uniqueId: 'pk', uniqueId: 'pk',
detailView: show_detail, detailView: show_detail,
detailViewByClick: false, detailViewByClick: false,
buttons: constructExpandCollapseButtons(table),
detailFilter: function(index, row) { detailFilter: function(index, row) {
if (pending) { if (pending) {
// Order is pending // Order is pending
@ -4395,7 +4411,7 @@ function loadSalesOrderExtraLineTable(table, options={}) {
var filter_target = options.filter_target || '#filter-list-sales-order-extra-lines'; var filter_target = options.filter_target || '#filter-list-sales-order-extra-lines';
setupFilterList('salesorderextraline', $(table), filter_target); setupFilterList('salesorderextraline', $(table), filter_target, {download: true});
// Table columns to display // Table columns to display
var columns = [ var columns = [

View File

@ -12,6 +12,7 @@
reloadtable, reloadtable,
renderLink, renderLink,
reloadTableFilters, reloadTableFilters,
constructExpandCollapseButtons,
constructOrderTableButtons, constructOrderTableButtons,
*/ */
@ -98,6 +99,28 @@ function constructOrderTableButtons(options={}) {
} }
/*
* Construct buttons to expand / collapse all rows in a table
*/
function constructExpandCollapseButtons(table, idx=0) {
return [
{
html: `<button type='button' name='${idx++}' class='btn btn-outline-secondary' title='{% trans "Expand all rows" %}'><span class='fas fa-expand'></span></button>`,
event: function() {
$(table).bootstrapTable('expandAllRows');
}
},
{
html: `<button type='button' name='${idx++}' class='btn btn-outline-secondary' title='{% trans "Collapse all rows" %}'><span class='fas fa-compress'></span></button>`,
event: function() {
$(table).bootstrapTable('collapseAllRows');
}
}
];
}
/* Return the 'selected' data rows from a bootstrap table. /* Return the 'selected' data rows from a bootstrap table.
* If allowEmpty = false, and the returned dataset is empty, * If allowEmpty = false, and the returned dataset is empty,
* then instead try to return *all* the data * then instead try to return *all* the data