2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-07-01 03:00:54 +00:00

Merged master and updated stock_table.html

This commit is contained in:
eeintech
2021-01-17 13:11:59 -05:00
33 changed files with 4998 additions and 2133 deletions

View File

@ -644,7 +644,7 @@ class StockList(generics.ListCreateAPIView):
queryset = queryset.filter(Q(sales_order_allocations__isnull=True) & Q(allocations__isnull=True))
# Do we wish to filter by "active parts"
active = self.request.query_params.get('active', None)
active = params.get('active', None)
if active is not None:
active = str2bool(active)
@ -683,7 +683,7 @@ class StockList(generics.ListCreateAPIView):
raise ValidationError({"part": "Invalid Part ID specified"})
# Does the client wish to filter by the 'ancestor'?
anc_id = self.request.query_params.get('ancestor', None)
anc_id = params.get('ancestor', None)
if anc_id:
try:
@ -696,9 +696,9 @@ class StockList(generics.ListCreateAPIView):
raise ValidationError({"ancestor": "Invalid ancestor ID specified"})
# Does the client wish to filter by stock location?
loc_id = self.request.query_params.get('location', None)
loc_id = params.get('location', None)
cascade = str2bool(self.request.query_params.get('cascade', True))
cascade = str2bool(params.get('cascade', True))
if loc_id is not None:
@ -718,7 +718,7 @@ class StockList(generics.ListCreateAPIView):
pass
# Does the client wish to filter by part category?
cat_id = self.request.query_params.get('category', None)
cat_id = params.get('category', None)
if cat_id:
try:
@ -729,35 +729,68 @@ class StockList(generics.ListCreateAPIView):
raise ValidationError({"category": "Invalid category id specified"})
# Filter by StockItem status
status = self.request.query_params.get('status', None)
status = params.get('status', None)
if status:
queryset = queryset.filter(status=status)
# Filter by supplier_part ID
supplier_part_id = self.request.query_params.get('supplier_part', None)
supplier_part_id = params.get('supplier_part', None)
if supplier_part_id:
queryset = queryset.filter(supplier_part=supplier_part_id)
# Filter by company (either manufacturer or supplier)
company = self.request.query_params.get('company', None)
company = params.get('company', None)
if company is not None:
queryset = queryset.filter(Q(supplier_part__supplier=company) | Q(supplier_part__manufacturer=company))
# Filter by supplier
supplier = self.request.query_params.get('supplier', None)
supplier = params.get('supplier', None)
if supplier is not None:
queryset = queryset.filter(supplier_part__supplier=supplier)
# Filter by manufacturer
manufacturer = self.request.query_params.get('manufacturer', None)
manufacturer = params.get('manufacturer', None)
if manufacturer is not None:
queryset = queryset.filter(supplier_part__manufacturer=manufacturer)
"""
Filter by the 'last updated' date of the stock item(s):
- updated_before=? : Filter stock items which were last updated *before* the provided date
- updated_after=? : Filter stock items which were last updated *after* the provided date
"""
date_fmt = '%Y-%m-%d' # ISO format date string
updated_before = params.get('updated_before', None)
updated_after = params.get('updated_after', None)
if updated_before:
try:
updated_before = datetime.strptime(str(updated_before), date_fmt).date()
queryset = queryset.filter(updated__lte=updated_before)
print("Before:", updated_before.isoformat())
except (ValueError, TypeError):
# Account for improperly formatted date string
print("After before:", str(updated_before))
pass
if updated_after:
try:
updated_after = datetime.strptime(str(updated_after), date_fmt).date()
queryset = queryset.filter(updated__gte=updated_after)
print("After:", updated_after.isoformat())
except (ValueError, TypeError):
# Account for improperly formatted date string
print("After error:", str(updated_after))
pass
# Also ensure that we pre-fecth all the related items
queryset = queryset.prefetch_related(
'part',

View File

@ -32,6 +32,7 @@ from InvenTree import helpers
import common.models
import report.models
import label.models
from InvenTree.status_codes import StockStatus
from InvenTree.models import InvenTreeTree, InvenTreeAttachment
@ -69,6 +70,13 @@ class StockLocation(InvenTreeTree):
**kwargs
)
@property
def barcode(self):
"""
Brief payload data (e.g. for labels)
"""
return self.format_barcode(brief=True)
def get_stock_items(self, cascade=True):
""" Return a queryset for all stock items under this category.
@ -336,6 +344,13 @@ class StockItem(MPTTModel):
**kwargs
)
@property
def barcode(self):
"""
Brief payload data (e.g. for labels)
"""
return self.format_barcode(brief=True)
uid = models.CharField(blank=True, max_length=128, help_text=("Unique identifier field"))
parent = TreeForeignKey(
@ -1343,14 +1358,31 @@ class StockItem(MPTTModel):
return len(self.available_test_reports()) > 0
def available_labels(self):
"""
Return a list of Label objects which match this StockItem
"""
labels = []
item_query = StockItem.objects.filter(pk=self.pk)
for lbl in label.models.StockItemLabel.objects.filter(enabled=True):
filters = helpers.validateFilterString(lbl.filters)
if item_query.filter(**filters).exists():
labels.append(lbl)
return labels
@property
def has_labels(self):
"""
Return True if there are any label templates available for this stock item
"""
# TODO - Implement this
return True
return len(self.available_labels()) > 0
@receiver(pre_delete, sender=StockItem, dispatch_uid='stock_item_pre_delete_log')

View File

@ -213,6 +213,7 @@ class StockItemSerializer(InvenTreeModelSerializer):
'supplier_part_detail',
'tracking_items',
'uid',
'updated',
]
""" These fields are read-only in this context.

View File

@ -423,12 +423,7 @@ $("#stock-test-report").click(function() {
});
$("#print-label").click(function() {
launchModalForm(
"{% url 'stock-item-label-select' item.id %}",
{
follow: true,
}
)
printStockItemLabels([{{ item.pk }}]);
});
$("#stock-duplicate").click(function() {

View File

@ -43,7 +43,7 @@
<button id='barcode-options' title='{% trans "Barcode actions" %}' class='btn btn-default dropdown-toggle' type='button' data-toggle='dropdown'><span class='fas fa-qrcode'></span> <span class='caret'></span></button>
<ul class='dropdown-menu' role='menu'>
<li><a href='#' id='show-qr-code'><span class='fas fa-qrcode'></span> {% trans "Show QR Code" %}</a></li>
<li class='disabled'><a href='#' id='print-label'><span class='fas fa-tag'></span> {% trans "Print Label" %}</a></li>
<li><a href='#' id='print-label'><span class='fas fa-tag'></span> {% trans "Print Label" %}</a></li>
<li><a href='#' id='barcode-check-in'><span class='fas fa-arrow-right'></span> {% trans "Check-in Items" %}</a></li>
</ul>
</div>
@ -222,6 +222,15 @@
}
});
});
$('#print-label').click(function() {
var locs = [{{ location.pk }}];
printStockLocationLabels(locs);
});
{% endif %}
$('#show-qr-code').click(function() {

View File

@ -30,7 +30,6 @@ stock_item_detail_urls = [
url(r'^add_tracking/', views.StockItemTrackingCreate.as_view(), name='stock-tracking-create'),
url(r'^test-report-select/', views.StockItemTestReportSelect.as_view(), name='stock-item-test-report-select'),
url(r'^label-select/', views.StockItemSelectLabels.as_view(), name='stock-item-label-select'),
url(r'^test/', views.StockItemDetail.as_view(template_name='stock/item_tests.html'), name='stock-item-test-results'),
url(r'^children/', views.StockItemDetail.as_view(template_name='stock/item_childs.html'), name='stock-item-children'),
@ -64,7 +63,6 @@ stock_urls = [
url(r'^item/uninstall/', views.StockItemUninstall.as_view(), name='stock-item-uninstall'),
url(r'^item/test-report-download/', views.StockItemTestReportDownload.as_view(), name='stock-item-test-report-download'),
url(r'^item/print-stock-labels/', views.StockItemPrintLabels.as_view(), name='stock-item-print-labels'),
# URLs for StockItem attachments
url(r'^item/attachment/', include([

View File

@ -33,7 +33,6 @@ from datetime import datetime, timedelta
from company.models import Company, SupplierPart
from part.models import Part
from report.models import TestReport
from label.models import StockItemLabel
from .models import StockItem, StockLocation, StockItemTracking, StockItemAttachment, StockItemTestResult
import common.settings
@ -406,92 +405,6 @@ class StockItemReturnToStock(AjaxUpdateView):
}
class StockItemSelectLabels(AjaxView):
"""
View for selecting a template for printing labels for one (or more) StockItem objects
"""
model = StockItem
ajax_form_title = _('Select Label Template')
role_required = 'stock.view'
def get_form(self):
item = StockItem.objects.get(pk=self.kwargs['pk'])
labels = []
# Construct a list of StockItemLabel objects which are enabled, and the filters match the selected StockItem
for label in StockItemLabel.objects.filter(enabled=True):
if label.matches_stock_item(item):
labels.append(label)
return StockForms.StockItemLabelSelectForm(labels)
def post(self, request, *args, **kwargs):
label = request.POST.get('label', None)
try:
label = StockItemLabel.objects.get(pk=label)
except (ValueError, StockItemLabel.DoesNotExist):
raise ValidationError({'label': _("Select valid label")})
stock_item = StockItem.objects.get(pk=self.kwargs['pk'])
url = reverse('stock-item-print-labels')
url += '?label={pk}'.format(pk=label.pk)
url += '&items[]={pk}'.format(pk=stock_item.pk)
data = {
'form_valid': True,
'url': url,
}
return self.renderJsonResponse(request, self.get_form(), data=data)
class StockItemPrintLabels(AjaxView):
"""
View for printing labels and returning a PDF
Requires the following arguments to be passed as URL params:
items: List of valid StockItem pk values
label: Valid pk of a StockItemLabel template
"""
role_required = 'stock.view'
def get(self, request, *args, **kwargs):
label = request.GET.get('label', None)
try:
label = StockItemLabel.objects.get(pk=label)
except (ValueError, StockItemLabel.DoesNotExist):
raise ValidationError({'label': 'Invalid label ID'})
item_pks = request.GET.getlist('items[]')
items = []
for pk in item_pks:
try:
item = StockItem.objects.get(pk=pk)
items.append(item)
except (ValueError, StockItem.DoesNotExist):
pass
if len(items) == 0:
raise ValidationError({'items': 'Must provide valid stockitems'})
pdf = label.render(items).getbuffer()
return DownloadFile(pdf, 'stock_labels.pdf', content_type='application/pdf')
class StockItemDeleteTestData(AjaxUpdateView):
"""
View for deleting all test data