diff --git a/InvenTree/company/migrations/0023_auto_20200808_0715.py b/InvenTree/company/migrations/0023_auto_20200808_0715.py
new file mode 100644
index 0000000000..22097e8e2b
--- /dev/null
+++ b/InvenTree/company/migrations/0023_auto_20200808_0715.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.0.7 on 2020-08-08 07:15
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('company', '0022_auto_20200613_1045'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='company',
+ options={'ordering': ['name']},
+ ),
+ ]
diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py
index 2179897263..a06ddd94bf 100644
--- a/InvenTree/company/models.py
+++ b/InvenTree/company/models.py
@@ -79,6 +79,9 @@ class Company(models.Model):
is_manufacturer: boolean value, is this company a manufacturer
"""
+ class Meta:
+ ordering = ['name', ]
+
name = models.CharField(max_length=100, blank=False, unique=True,
help_text=_('Company name'),
verbose_name=_('Company name'))
diff --git a/InvenTree/company/templates/company/detail_stock.html b/InvenTree/company/templates/company/detail_stock.html
index c33179d454..e994d5834b 100644
--- a/InvenTree/company/templates/company/detail_stock.html
+++ b/InvenTree/company/templates/company/detail_stock.html
@@ -26,7 +26,8 @@
},
buttons: [
'#stock-options',
- ]
+ ],
+ filterKey: "companystock",
});
$("#stock-export").click(function() {
diff --git a/InvenTree/part/migrations/0047_auto_20200808_0715.py b/InvenTree/part/migrations/0047_auto_20200808_0715.py
new file mode 100644
index 0000000000..4fc3d5a7d9
--- /dev/null
+++ b/InvenTree/part/migrations/0047_auto_20200808_0715.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.0.7 on 2020-08-08 07:15
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('part', '0046_auto_20200804_0107'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='part',
+ options={'ordering': ['name'], 'verbose_name': 'Part', 'verbose_name_plural': 'Parts'},
+ ),
+ ]
diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py
index 01768b4bb3..308808fbdd 100644
--- a/InvenTree/part/models.py
+++ b/InvenTree/part/models.py
@@ -71,8 +71,8 @@ class PartCategory(InvenTreeTree):
return reverse('category-detail', kwargs={'pk': self.id})
class Meta:
- verbose_name = "Part Category"
- verbose_name_plural = "Part Categories"
+ verbose_name = _("Part Category")
+ verbose_name_plural = _("Part Categories")
def get_parts(self, cascade=True):
""" Return a queryset for all parts under this category.
@@ -239,6 +239,7 @@ class Part(MPTTModel):
class Meta:
verbose_name = _("Part")
verbose_name_plural = _("Parts")
+ ordering = ['name', ]
class MPTTMeta:
# For legacy reasons the 'variant_of' field is used to indicate the MPTT parent
@@ -1490,7 +1491,7 @@ class BomItem(models.Model):
pass
class Meta:
- verbose_name = "BOM Item"
+ verbose_name = _("BOM Item")
# Prevent duplication of parent/child rows
unique_together = ('part', 'sub_part')
diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py
index 018b588c1f..7284f8d5cd 100644
--- a/InvenTree/stock/api.py
+++ b/InvenTree/stock/api.py
@@ -477,6 +477,17 @@ class StockList(generics.ListCreateAPIView):
if customer:
queryset = queryset.filter(customer=customer)
+ # Filter if items have been sent to a customer (any customer)
+ sent_to_customer = params.get('sent_to_customer', None)
+
+ if sent_to_customer is not None:
+ sent_to_customer = str2bool(sent_to_customer)
+
+ if sent_to_customer:
+ queryset = queryset.exclude(customer=None)
+ else:
+ queryset = queryset.filter(customer=None)
+
# Filter by "serialized" status?
serialized = params.get('serialized', None)
@@ -507,6 +518,7 @@ class StockList(generics.ListCreateAPIView):
if serial_number_lte is not None:
queryset = queryset.filter(serial__lte=serial_number_lte)
+ # Filter by "in_stock" status
in_stock = params.get('in_stock', None)
if in_stock is not None:
@@ -539,10 +551,21 @@ class StockList(generics.ListCreateAPIView):
active = str2bool(active)
queryset = queryset.filter(part__active=active)
+ # Filter by 'depleted' status
+ depleted = params.get('depleted', None)
+
+ if depleted is not None:
+ depleted = str2bool(depleted)
+
+ if depleted:
+ queryset = queryset.filter(quantity__lte=0)
+ else:
+ queryset = queryset.exclude(quantity__lte=0)
+
# Filter by internal part number
IPN = params.get('IPN', None)
- if IPN:
+ if IPN is not None:
queryset = queryset.filter(part__IPN=IPN)
# Does the client wish to filter by the Part ID?
diff --git a/InvenTree/stock/templates/stock/stock_adjust.html b/InvenTree/stock/templates/stock/stock_adjust.html
index a72407f735..8385fb5039 100644
--- a/InvenTree/stock/templates/stock/stock_adjust.html
+++ b/InvenTree/stock/templates/stock/stock_adjust.html
@@ -32,6 +32,7 @@
{% if item.error %}
{{ item.error }}
diff --git a/InvenTree/templates/js/stock.html b/InvenTree/templates/js/stock.html
index adaf07b4f6..11cf6a94e3 100644
--- a/InvenTree/templates/js/stock.html
+++ b/InvenTree/templates/js/stock.html
@@ -1,4 +1,5 @@
{% load i18n %}
+{% load status_codes %}
/* Stock API functions
* Requires api.js to be loaded first
@@ -460,12 +461,30 @@ function loadStockTable(table, options) {
var html = renderLink(val, `/stock/item/${row.pk}/`);
if (row.allocated) {
- html += ``;
+ html += ``;
}
+ if (row.customer) {
+ html += ``;
+ } else if (row.build_order) {
+ html += ``;
+ } else if (row.sales_order) {
+ html += ``;
+ }
+
+ // Special stock status codes
+
+ // 65 = "REJECTED"
+ if (row.status == 65) {
+ html += ``;
+ }
// 70 = "LOST"
- if (row.status == 70) {
- html += ``;
+ else if (row.status == 70) {
+ html += ``;
+ }
+
+ if (row.quantity <= 0) {
+ html += `{% trans "Depleted" %}`;
}
return html;
diff --git a/InvenTree/templates/js/table_filters.html b/InvenTree/templates/js/table_filters.html
index e2138ef6b3..9050edba6f 100644
--- a/InvenTree/templates/js/table_filters.html
+++ b/InvenTree/templates/js/table_filters.html
@@ -32,30 +32,35 @@ function getAvailableTableFilters(tableKey) {
// Filters for the "Stock" table
if (tableKey == 'stock') {
return {
- in_stock: {
+ active: {
type: 'bool',
- title: '{% trans "In Stock" %}',
- description: '{% trans "Show items which are in stock" %}',
+ title: '{% trans "Active parts" %}',
+ description: '{% trans "Show stock for active parts" %}',
+ },
+ allocated: {
+ type: 'bool',
+ title: '{% trans "Is allocated" %}',
+ description: '{% trans "Item has been alloacted" %}',
},
cascade: {
type: 'bool',
title: '{% trans "Include sublocations" %}',
description: '{% trans "Include stock in sublocations" %}',
},
- active: {
+ depleted: {
type: 'bool',
- title: '{% trans "Active parts" %}',
- description: '{% trans "Show stock for active parts" %}',
+ title: '{% trans "Depleted" %}',
+ description: '{% trans "Show stock items which are depleted" %}',
},
- status: {
- options: stockCodes,
- title: '{% trans "Stock status" %}',
- description: '{% trans "Stock status" %}',
- },
- allocated: {
+ in_stock: {
type: 'bool',
- title: '{% trans "Is allocated" %}',
- description: '{% trans "Item has been alloacted" %}',
+ title: '{% trans "In Stock" %}',
+ description: '{% trans "Show items which are in stock" %}',
+ },
+ sent_to_customer: {
+ type: 'bool',
+ title: '{% trans "Sent to customer" %}',
+ description: '{% trans "Show items which have been assigned to a customer" %}',
},
serialized: {
type: 'bool',
@@ -69,6 +74,11 @@ function getAvailableTableFilters(tableKey) {
title: "{% trans "Serial number LTE" %}",
description: "{% trans "Serial number less than or equal to" %}",
},
+ status: {
+ options: stockCodes,
+ title: '{% trans "Stock status" %}',
+ description: '{% trans "Stock status" %}',
+ },
};
}