mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge remote-tracking branch 'inventree/master'
This commit is contained in:
commit
d0ad3f0e37
@ -103,6 +103,7 @@ def GetExportFormats():
|
||||
'xls',
|
||||
'xlsx',
|
||||
'json',
|
||||
'yaml',
|
||||
]
|
||||
|
||||
|
||||
|
@ -23,6 +23,7 @@ class CompanyResource(ModelResource):
|
||||
model = Company
|
||||
skip_unchanged = True
|
||||
report_skipped = False
|
||||
clean_model_instances = True
|
||||
|
||||
|
||||
class CompanyAdmin(ImportExportModelAdmin):
|
||||
@ -43,6 +44,7 @@ class SupplierPartResource(ModelResource):
|
||||
model = SupplierPart
|
||||
skip_unchanged = True
|
||||
report_skipped = False
|
||||
clean_model_instances = True
|
||||
|
||||
|
||||
class SupplierPartAdmin(ImportExportModelAdmin):
|
||||
@ -63,6 +65,7 @@ class SupplierPriceBreakResource(ModelResource):
|
||||
model = SupplierPriceBreak
|
||||
skip_unchanged = True
|
||||
report_skipped = False
|
||||
clean_model_instances = True
|
||||
|
||||
|
||||
class SupplierPriceBreakAdmin(ImportExportModelAdmin):
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
<div id='button-bar'>
|
||||
<div class='btn-group'>
|
||||
<button class='btn btn-primary' type='button' id='company-order-2' title='Create new purchase order'>New Purchase Order</button>
|
||||
<button class='btn btn-primary' type='button' id='company-order2' title='Create new purchase order'>New Purchase Order</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
newOrder();
|
||||
});
|
||||
|
||||
$("#company-order-2").click(function() {
|
||||
$("#company-order2").click(function() {
|
||||
newOrder();
|
||||
});
|
||||
|
||||
|
@ -2,8 +2,12 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
from import_export.admin import ImportExportModelAdmin
|
||||
|
||||
from import_export.resources import ModelResource
|
||||
from import_export.fields import Field
|
||||
|
||||
from .models import PurchaseOrder, PurchaseOrderLineItem
|
||||
|
||||
|
||||
@ -18,8 +22,28 @@ class PurchaseOrderAdmin(ImportExportModelAdmin):
|
||||
)
|
||||
|
||||
|
||||
class POLineItemResource(ModelResource):
|
||||
""" Class for managing import / export of POLineItem data """
|
||||
|
||||
part_name = Field(attribute='part__part__name', readonly=True)
|
||||
|
||||
manufacturer = Field(attribute='part__manufacturer', readonly=True)
|
||||
|
||||
MPN = Field(attribute='part__MPN', readonly=True)
|
||||
|
||||
SKU = Field(attribute='part__SKU', readonly=True)
|
||||
|
||||
class Meta:
|
||||
model = PurchaseOrderLineItem
|
||||
skip_unchanged = True
|
||||
report_skipped = False
|
||||
clean_model_instances = True
|
||||
|
||||
|
||||
class PurchaseOrderLineItemAdmin(ImportExportModelAdmin):
|
||||
|
||||
resource_class = POLineItemResource
|
||||
|
||||
list_display = (
|
||||
'order',
|
||||
'part',
|
||||
|
@ -12,7 +12,6 @@ from django.contrib.auth.models import User
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
import tablib
|
||||
from datetime import datetime
|
||||
|
||||
from stock.models import StockItem
|
||||
@ -126,54 +125,6 @@ class PurchaseOrder(Order):
|
||||
related_name='+'
|
||||
)
|
||||
|
||||
def export_to_file(self, **kwargs):
|
||||
""" Export order information to external file """
|
||||
|
||||
file_format = kwargs.get('format', 'csv').lower()
|
||||
|
||||
data = tablib.Dataset(headers=[
|
||||
'Line',
|
||||
'Part',
|
||||
'Description',
|
||||
'Manufacturer',
|
||||
'MPN',
|
||||
'Order Code',
|
||||
'Quantity',
|
||||
'Received',
|
||||
'Reference',
|
||||
'Notes',
|
||||
])
|
||||
|
||||
idx = 0
|
||||
|
||||
for item in self.lines.all():
|
||||
|
||||
line = []
|
||||
|
||||
line.append(idx)
|
||||
|
||||
if item.part:
|
||||
line.append(item.part.part.name)
|
||||
line.append(item.part.part.description)
|
||||
|
||||
line.append(item.part.manufacturer)
|
||||
line.append(item.part.MPN)
|
||||
line.append(item.part.SKU)
|
||||
|
||||
else:
|
||||
line += [[] * 5]
|
||||
|
||||
line.append(item.quantity)
|
||||
line.append(item.received)
|
||||
line.append(item.reference)
|
||||
line.append(item.notes)
|
||||
|
||||
idx += 1
|
||||
|
||||
data.append(line)
|
||||
|
||||
return data.export(file_format)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('purchase-order-detail', kwargs={'pk': self.id})
|
||||
|
||||
|
@ -139,13 +139,3 @@ class OrderTest(TestCase):
|
||||
order.receive_line_item(line, loc, line.quantity, user=None)
|
||||
|
||||
self.assertEqual(order.status, OrderStatus.COMPLETE)
|
||||
|
||||
def test_export(self):
|
||||
""" Test order exporting """
|
||||
|
||||
order = PurchaseOrder.objects.get(pk=1)
|
||||
|
||||
output = order.export_to_file(format='csv')
|
||||
|
||||
self.assertIn('M2x4 LPHS', output)
|
||||
self.assertIn('Line,Part,Description', output)
|
||||
|
@ -14,6 +14,7 @@ from django.forms import HiddenInput
|
||||
import logging
|
||||
|
||||
from .models import PurchaseOrder, PurchaseOrderLineItem
|
||||
from .admin import POLineItemResource
|
||||
from build.models import Build
|
||||
from company.models import Company, SupplierPart
|
||||
from stock.models import StockItem, StockLocation
|
||||
@ -165,7 +166,9 @@ class PurchaseOrderExport(AjaxView):
|
||||
fmt=export_format
|
||||
)
|
||||
|
||||
filedata = order.export_to_file(format=export_format)
|
||||
dataset = POLineItemResource().export(queryset=order.lines.all())
|
||||
|
||||
filedata = dataset.export(format=export_format)
|
||||
|
||||
return DownloadFile(filedata, filename)
|
||||
|
||||
|
@ -31,6 +31,8 @@ class PartResource(ModelResource):
|
||||
|
||||
variant_of = Field(attribute='variant_of', widget=widgets.ForeignKeyWidget(Part))
|
||||
|
||||
suppliers = Field(attribute='supplier_count', readonly=True)
|
||||
|
||||
# Extra calculated meta-data (readonly)
|
||||
in_stock = Field(attribute='total_stock', readonly=True, widget=widgets.IntegerWidget())
|
||||
|
||||
@ -46,6 +48,7 @@ class PartResource(ModelResource):
|
||||
model = Part
|
||||
skip_unchanged = True
|
||||
report_skipped = False
|
||||
clean_model_instances = True
|
||||
exclude = [
|
||||
'bom_checksum', 'bom_checked_by', 'bom_checked_date'
|
||||
]
|
||||
@ -89,6 +92,7 @@ class PartCategoryResource(ModelResource):
|
||||
model = PartCategory
|
||||
skip_unchanged = True
|
||||
report_skipped = False
|
||||
clean_model_instances = True
|
||||
|
||||
exclude = [
|
||||
# Exclude MPTT internal model fields
|
||||
@ -127,12 +131,21 @@ class BomItemResource(ModelResource):
|
||||
|
||||
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part))
|
||||
|
||||
sub_part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part))
|
||||
part_name = Field(attribute='part__full_name', readonly=True)
|
||||
|
||||
sub_part = Field(attribute='sub_part', widget=widgets.ForeignKeyWidget(Part))
|
||||
|
||||
sub_part_name = Field(attribute='sub_part__full_name', readonly=True)
|
||||
|
||||
stock = Field(attribute='sub_part__total_stock', readonly=True)
|
||||
|
||||
class Meta:
|
||||
model = BomItem
|
||||
skip_unchanged = True
|
||||
report_skipped = False
|
||||
clean_model_instances = True
|
||||
|
||||
exclude = ('checksum')
|
||||
|
||||
|
||||
class BomItemAdmin(ImportExportModelAdmin):
|
||||
@ -163,6 +176,7 @@ class ParameterResource(ModelResource):
|
||||
model = PartParameter
|
||||
skip_unchanged = True
|
||||
report_skipped = False
|
||||
clean_model_instance = True
|
||||
|
||||
|
||||
class ParameterAdmin(ImportExportModelAdmin):
|
||||
|
@ -10,13 +10,16 @@ import os
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from InvenTree.helpers import DownloadFile
|
||||
from InvenTree.helpers import DownloadFile, GetExportFormats
|
||||
|
||||
from .admin import BomItemResource
|
||||
from .models import BomItem
|
||||
|
||||
|
||||
def IsValidBOMFormat(fmt):
|
||||
""" Test if a file format specifier is in the valid list of BOM file formats """
|
||||
|
||||
return fmt.strip().lower() in ['csv', 'xls', 'xlsx', 'tsv']
|
||||
return fmt.strip().lower() in GetExportFormats()
|
||||
|
||||
|
||||
def MakeBomTemplate(fmt):
|
||||
@ -27,21 +30,33 @@ def MakeBomTemplate(fmt):
|
||||
if not IsValidBOMFormat(fmt):
|
||||
fmt = 'csv'
|
||||
|
||||
fields = [
|
||||
'Part',
|
||||
'Quantity',
|
||||
'Overage',
|
||||
'Reference',
|
||||
'Notes'
|
||||
]
|
||||
query = BomItem.objects.filter(pk=None)
|
||||
dataset = BomItemResource().export(queryset=query)
|
||||
|
||||
data = tablib.Dataset(headers=fields).export(fmt)
|
||||
data = dataset.export(fmt)
|
||||
|
||||
filename = 'InvenTree_BOM_Template.' + fmt
|
||||
|
||||
return DownloadFile(data, filename)
|
||||
|
||||
|
||||
def ExportBom(part, fmt='csv'):
|
||||
""" Export a BOM (Bill of Materials) for a given part.
|
||||
"""
|
||||
|
||||
if not IsValidBOMFormat(fmt):
|
||||
fmt = 'csv'
|
||||
|
||||
bom_items = part.bom_items.all().order_by('id')
|
||||
|
||||
dataset = BomItemResource().export(queryset=bom_items)
|
||||
data = dataset.export(fmt)
|
||||
|
||||
filename = '{n}_BOM.{fmt}'.format(n=part.full_name, fmt=fmt)
|
||||
|
||||
return DownloadFile(data, filename)
|
||||
|
||||
|
||||
class BomUploadManager:
|
||||
""" Class for managing an uploaded BOM file """
|
||||
|
||||
|
@ -7,8 +7,6 @@ from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
|
||||
import tablib
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.urls import reverse
|
||||
@ -857,76 +855,6 @@ class Part(models.Model):
|
||||
|
||||
self.save()
|
||||
|
||||
def export_bom(self, **kwargs):
|
||||
""" Export Bill of Materials to a spreadsheet file.
|
||||
Includes a row for each item in the BOM.
|
||||
Also includes extra information such as supplier data.
|
||||
"""
|
||||
|
||||
items = self.bom_items.all().order_by('id')
|
||||
|
||||
supplier_names = set()
|
||||
|
||||
headers = [
|
||||
'Part',
|
||||
'Description',
|
||||
'Quantity',
|
||||
'Overage',
|
||||
'Reference',
|
||||
'Note',
|
||||
'',
|
||||
'In Stock',
|
||||
]
|
||||
|
||||
# Contstruct list of suppliers for each part
|
||||
for item in items:
|
||||
part = item.sub_part
|
||||
supplier_parts = part.supplier_parts.all()
|
||||
item.suppliers = {}
|
||||
|
||||
for sp in supplier_parts:
|
||||
name = sp.supplier.name
|
||||
supplier_names.add(name)
|
||||
item.suppliers[name] = sp
|
||||
|
||||
if len(supplier_names) > 0:
|
||||
headers.append('')
|
||||
for name in supplier_names:
|
||||
headers.append(name)
|
||||
|
||||
data = tablib.Dataset(headers=headers)
|
||||
|
||||
for it in items:
|
||||
line = []
|
||||
|
||||
# Information about each BOM item
|
||||
line.append(it.sub_part.full_name)
|
||||
line.append(it.sub_part.description)
|
||||
line.append(it.quantity)
|
||||
line.append(it.overage)
|
||||
line.append(it.reference)
|
||||
line.append(it.note)
|
||||
|
||||
# Extra information about the part
|
||||
line.append('')
|
||||
line.append(it.sub_part.available_stock)
|
||||
|
||||
if len(supplier_names) > 0:
|
||||
line.append('') # Blank column separates supplier info
|
||||
|
||||
for name in supplier_names:
|
||||
sp = it.suppliers.get(name, None)
|
||||
if sp:
|
||||
line.append(sp.SKU)
|
||||
else:
|
||||
line.append('')
|
||||
|
||||
data.append(line)
|
||||
|
||||
file_format = kwargs.get('format', 'csv').lower()
|
||||
|
||||
return data.export(file_format)
|
||||
|
||||
@property
|
||||
def attachment_count(self):
|
||||
""" Count the number of attachments for this part.
|
||||
|
@ -32,15 +32,6 @@ class BomItemTest(TestCase):
|
||||
|
||||
self.assertIn(self.orphan, parts)
|
||||
|
||||
def test_bom_export(self):
|
||||
parts = self.bob.required_parts()
|
||||
|
||||
data = self.bob.export_bom(format='csv')
|
||||
|
||||
for p in parts:
|
||||
self.assertIn(p.name, data)
|
||||
self.assertIn(p.description, data)
|
||||
|
||||
def test_used_in(self):
|
||||
self.assertEqual(self.bob.used_in_count, 0)
|
||||
self.assertEqual(self.orphan.used_in_count, 1)
|
||||
|
@ -14,8 +14,6 @@ from django.views.generic import DetailView, ListView, FormView
|
||||
from django.forms.models import model_to_dict
|
||||
from django.forms import HiddenInput, CheckboxInput
|
||||
|
||||
import tablib
|
||||
|
||||
from fuzzywuzzy import fuzz
|
||||
from decimal import Decimal
|
||||
|
||||
@ -28,7 +26,9 @@ from common.models import Currency
|
||||
from company.models import SupplierPart
|
||||
|
||||
from . import forms as part_forms
|
||||
from .bom import MakeBomTemplate, BomUploadManager
|
||||
from .bom import MakeBomTemplate, BomUploadManager, ExportBom, IsValidBOMFormat
|
||||
|
||||
from .admin import PartResource
|
||||
|
||||
from InvenTree.views import AjaxView, AjaxCreateView, AjaxUpdateView, AjaxDeleteView
|
||||
from InvenTree.views import QRCodeView
|
||||
@ -1216,108 +1216,9 @@ class PartExport(AjaxView):
|
||||
|
||||
parts = self.get_parts(request)
|
||||
|
||||
headers = [
|
||||
'ID',
|
||||
'Name',
|
||||
'Description',
|
||||
'Category',
|
||||
'Category ID',
|
||||
'IPN',
|
||||
'Revision',
|
||||
'URL',
|
||||
'Keywords',
|
||||
'Notes',
|
||||
'Assembly',
|
||||
'Component',
|
||||
'Template',
|
||||
'Trackable',
|
||||
'Purchaseable',
|
||||
'Salable',
|
||||
'Active',
|
||||
'Virtual',
|
||||
dataset = PartResource().export(queryset=parts)
|
||||
|
||||
# Part meta-data
|
||||
'Used In',
|
||||
|
||||
# Stock Information
|
||||
'Stock Info',
|
||||
'In Stock',
|
||||
'Allocated',
|
||||
'Building',
|
||||
'On Order',
|
||||
]
|
||||
|
||||
# Construct list of suppliers for each part
|
||||
supplier_names = set()
|
||||
|
||||
for part in parts:
|
||||
supplier_parts = part.supplier_parts.all()
|
||||
part.suppliers = {}
|
||||
|
||||
for sp in supplier_parts:
|
||||
name = sp.supplier.name
|
||||
supplier_names.add(name)
|
||||
part.suppliers[name] = sp
|
||||
|
||||
if len(supplier_names) > 0:
|
||||
headers.append('Suppliers')
|
||||
for name in supplier_names:
|
||||
headers.append(name)
|
||||
|
||||
data = tablib.Dataset(headers=headers)
|
||||
|
||||
for part in parts:
|
||||
line = []
|
||||
|
||||
line.append(part.pk)
|
||||
line.append(part.name)
|
||||
line.append(part.description)
|
||||
|
||||
if part.category:
|
||||
line.append(str(part.category))
|
||||
line.append(part.category.pk)
|
||||
else:
|
||||
line.append('')
|
||||
line.append('')
|
||||
|
||||
line.append(part.IPN)
|
||||
line.append(part.revision)
|
||||
line.append(part.URL)
|
||||
line.append(part.keywords)
|
||||
line.append(part.notes)
|
||||
line.append(part.assembly)
|
||||
line.append(part.component)
|
||||
line.append(part.is_template)
|
||||
line.append(part.trackable)
|
||||
line.append(part.purchaseable)
|
||||
line.append(part.salable)
|
||||
line.append(part.active)
|
||||
line.append(part.virtual)
|
||||
|
||||
# Part meta-data
|
||||
line.append(part.used_in_count)
|
||||
|
||||
# Stock information
|
||||
line.append('')
|
||||
line.append(part.total_stock)
|
||||
line.append(part.allocation_count)
|
||||
line.append(part.quantity_being_built)
|
||||
line.append(part.on_order)
|
||||
|
||||
# Supplier Information
|
||||
if len(supplier_names) > 0:
|
||||
line.append('')
|
||||
|
||||
for name in supplier_names:
|
||||
sp = part.suppliers.get(name, None)
|
||||
if sp:
|
||||
line.append(sp.SKU)
|
||||
else:
|
||||
line.append('')
|
||||
|
||||
data.append(line)
|
||||
|
||||
csv = data.export('csv')
|
||||
csv = dataset.export('csv')
|
||||
return DownloadFile(csv, 'InvenTree_Parts.csv')
|
||||
|
||||
|
||||
@ -1348,12 +1249,10 @@ class BomDownload(AjaxView):
|
||||
|
||||
export_format = request.GET.get('format', 'csv')
|
||||
|
||||
# Placeholder to test file export
|
||||
filename = '"' + part.name + '_BOM.' + export_format + '"'
|
||||
if not IsValidBOMFormat(export_format):
|
||||
export_format = 'csv'
|
||||
|
||||
filedata = part.export_bom(format=export_format)
|
||||
|
||||
return DownloadFile(filedata, filename)
|
||||
return ExportBom(part, fmt=export_format)
|
||||
|
||||
def get_data(self):
|
||||
return {
|
||||
|
@ -28,6 +28,7 @@ class LocationResource(ModelResource):
|
||||
model = StockLocation
|
||||
skip_unchanged = True
|
||||
report_skipped = False
|
||||
clean_model_instances = True
|
||||
|
||||
exclude = [
|
||||
# Exclude MPTT internal model fields
|
||||
@ -57,10 +58,16 @@ class StockItemResource(ModelResource):
|
||||
# Custom manaegrs for ForeignKey fields
|
||||
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part))
|
||||
|
||||
part_name = Field(attribute='part__name', readonly=True)
|
||||
part_name = Field(attribute='part__full_ame', readonly=True)
|
||||
|
||||
supplier_part = Field(attribute='supplier_part', widget=widgets.ForeignKeyWidget(SupplierPart))
|
||||
|
||||
supplier = Field(attribute='supplier_part__supplier__id', readonly=True)
|
||||
|
||||
supplier_name = Field(attribute='supplier_part__supplier__name', readonly=True)
|
||||
|
||||
status_label = Field(attribute='status_label', readonly=True)
|
||||
|
||||
location = Field(attribute='location', widget=widgets.ForeignKeyWidget(StockLocation))
|
||||
|
||||
location_name = Field(attribute='location__name', readonly=True)
|
||||
@ -82,6 +89,7 @@ class StockItemResource(ModelResource):
|
||||
model = StockItem
|
||||
skip_unchanged = True
|
||||
report_skipped = False
|
||||
clean_model_instance = True
|
||||
|
||||
|
||||
class StockItemAdmin(ImportExportModelAdmin):
|
||||
|
@ -140,6 +140,11 @@ class StockItem(models.Model):
|
||||
system=True
|
||||
)
|
||||
|
||||
@property
|
||||
def status_label(self):
|
||||
|
||||
return StockStatus.label(self.status)
|
||||
|
||||
@property
|
||||
def serialized(self):
|
||||
""" Return True if this StockItem is serialized """
|
||||
|
@ -18,17 +18,16 @@ from InvenTree.views import AjaxView
|
||||
from InvenTree.views import AjaxUpdateView, AjaxDeleteView, AjaxCreateView
|
||||
from InvenTree.views import QRCodeView
|
||||
|
||||
from InvenTree.status_codes import StockStatus
|
||||
from InvenTree.helpers import str2bool, DownloadFile, GetExportFormats
|
||||
from InvenTree.helpers import ExtractSerialNumbers
|
||||
from datetime import datetime
|
||||
|
||||
import tablib
|
||||
|
||||
from company.models import Company
|
||||
from part.models import Part
|
||||
from .models import StockItem, StockLocation, StockItemTracking
|
||||
|
||||
from .admin import StockItemResource
|
||||
|
||||
from .forms import EditStockLocationForm
|
||||
from .forms import CreateStockItemForm
|
||||
from .forms import EditStockItemForm
|
||||
@ -226,75 +225,9 @@ class StockExport(AjaxView):
|
||||
# Pre-fetch related fields to reduce DB queries
|
||||
stock_items = stock_items.prefetch_related('part', 'supplier_part__supplier', 'location', 'purchase_order', 'build')
|
||||
|
||||
# Column headers
|
||||
headers = [
|
||||
_('Stock ID'),
|
||||
_('Part ID'),
|
||||
_('Part'),
|
||||
_('Supplier Part ID'),
|
||||
_('Supplier ID'),
|
||||
_('Supplier'),
|
||||
_('Location ID'),
|
||||
_('Location'),
|
||||
_('Quantity'),
|
||||
_('Batch'),
|
||||
_('Serial'),
|
||||
_('Status'),
|
||||
_('Notes'),
|
||||
_('Review Needed'),
|
||||
_('Last Updated'),
|
||||
_('Last Stocktake'),
|
||||
_('Purchase Order ID'),
|
||||
_('Build ID'),
|
||||
]
|
||||
dataset = StockItemResource().export(queryset=stock_items)
|
||||
|
||||
data = tablib.Dataset(headers=headers)
|
||||
|
||||
for item in stock_items:
|
||||
line = []
|
||||
|
||||
line.append(item.pk)
|
||||
line.append(item.part.pk)
|
||||
line.append(item.part.full_name)
|
||||
|
||||
if item.supplier_part:
|
||||
line.append(item.supplier_part.pk)
|
||||
line.append(item.supplier_part.supplier.pk)
|
||||
line.append(item.supplier_part.supplier.name)
|
||||
else:
|
||||
line.append('')
|
||||
line.append('')
|
||||
line.append('')
|
||||
|
||||
if item.location:
|
||||
line.append(item.location.pk)
|
||||
line.append(item.location.name)
|
||||
else:
|
||||
line.append('')
|
||||
line.append('')
|
||||
|
||||
line.append(item.quantity)
|
||||
line.append(item.batch)
|
||||
line.append(item.serial)
|
||||
line.append(StockStatus.label(item.status))
|
||||
line.append(item.notes)
|
||||
line.append(item.review_needed)
|
||||
line.append(item.updated)
|
||||
line.append(item.stocktake_date)
|
||||
|
||||
if item.purchase_order:
|
||||
line.append(item.purchase_order.pk)
|
||||
else:
|
||||
line.append('')
|
||||
|
||||
if item.build:
|
||||
line.append(item.build.pk)
|
||||
else:
|
||||
line.append('')
|
||||
|
||||
data.append(line)
|
||||
|
||||
filedata = data.export(export_format)
|
||||
filedata = dataset.export(export_format)
|
||||
|
||||
return DownloadFile(filedata, filename)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user