2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-29 20:16:44 +00:00

Merge remote-tracking branch 'inventree/master'

This commit is contained in:
Oliver Walters 2020-08-09 21:37:06 +10:00
commit 3b01614a38
9 changed files with 114 additions and 22 deletions

View File

@ -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']},
),
]

View File

@ -79,6 +79,9 @@ class Company(models.Model):
is_manufacturer: boolean value, is this company a manufacturer is_manufacturer: boolean value, is this company a manufacturer
""" """
class Meta:
ordering = ['name', ]
name = models.CharField(max_length=100, blank=False, unique=True, name = models.CharField(max_length=100, blank=False, unique=True,
help_text=_('Company name'), help_text=_('Company name'),
verbose_name=_('Company name')) verbose_name=_('Company name'))

View File

@ -26,7 +26,8 @@
}, },
buttons: [ buttons: [
'#stock-options', '#stock-options',
] ],
filterKey: "companystock",
}); });
$("#stock-export").click(function() { $("#stock-export").click(function() {

View File

@ -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'},
),
]

View File

@ -71,8 +71,8 @@ class PartCategory(InvenTreeTree):
return reverse('category-detail', kwargs={'pk': self.id}) return reverse('category-detail', kwargs={'pk': self.id})
class Meta: class Meta:
verbose_name = "Part Category" verbose_name = _("Part Category")
verbose_name_plural = "Part Categories" verbose_name_plural = _("Part Categories")
def get_parts(self, cascade=True): def get_parts(self, cascade=True):
""" Return a queryset for all parts under this category. """ Return a queryset for all parts under this category.
@ -239,6 +239,7 @@ class Part(MPTTModel):
class Meta: class Meta:
verbose_name = _("Part") verbose_name = _("Part")
verbose_name_plural = _("Parts") verbose_name_plural = _("Parts")
ordering = ['name', ]
class MPTTMeta: class MPTTMeta:
# For legacy reasons the 'variant_of' field is used to indicate the MPTT parent # For legacy reasons the 'variant_of' field is used to indicate the MPTT parent
@ -1490,7 +1491,7 @@ class BomItem(models.Model):
pass pass
class Meta: class Meta:
verbose_name = "BOM Item" verbose_name = _("BOM Item")
# Prevent duplication of parent/child rows # Prevent duplication of parent/child rows
unique_together = ('part', 'sub_part') unique_together = ('part', 'sub_part')

View File

@ -477,6 +477,17 @@ class StockList(generics.ListCreateAPIView):
if customer: if customer:
queryset = queryset.filter(customer=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? # Filter by "serialized" status?
serialized = params.get('serialized', None) serialized = params.get('serialized', None)
@ -507,6 +518,7 @@ class StockList(generics.ListCreateAPIView):
if serial_number_lte is not None: if serial_number_lte is not None:
queryset = queryset.filter(serial__lte=serial_number_lte) queryset = queryset.filter(serial__lte=serial_number_lte)
# Filter by "in_stock" status
in_stock = params.get('in_stock', None) in_stock = params.get('in_stock', None)
if in_stock is not None: if in_stock is not None:
@ -539,10 +551,21 @@ class StockList(generics.ListCreateAPIView):
active = str2bool(active) active = str2bool(active)
queryset = queryset.filter(part__active=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 # Filter by internal part number
IPN = params.get('IPN', None) IPN = params.get('IPN', None)
if IPN: if IPN is not None:
queryset = queryset.filter(part__IPN=IPN) queryset = queryset.filter(part__IPN=IPN)
# Does the client wish to filter by the Part ID? # Does the client wish to filter by the Part ID?

View File

@ -32,6 +32,7 @@
<input class='numberinput' <input class='numberinput'
min='0' min='0'
{% if stock_action == 'take' or stock_action == 'move' %} max='{{ item.quantity }}' {% endif %} {% if stock_action == 'take' or stock_action == 'move' %} max='{{ item.quantity }}' {% endif %}
{% if item.serialized %} disabled='true' title='{% trans "Stock item is serialized and quantity cannot be adjusted" %}' {% endif %}
value='{% decimal item.new_quantity %}' type='number' name='stock-id-{{ item.id }}' id='stock-id-{{ item.id }}'/> value='{% decimal item.new_quantity %}' type='number' name='stock-id-{{ item.id }}' id='stock-id-{{ item.id }}'/>
{% if item.error %} {% if item.error %}
<br><span class='help-inline'>{{ item.error }}</span> <br><span class='help-inline'>{{ item.error }}</span>

View File

@ -1,4 +1,5 @@
{% load i18n %} {% load i18n %}
{% load status_codes %}
/* Stock API functions /* Stock API functions
* Requires api.js to be loaded first * Requires api.js to be loaded first
@ -460,12 +461,30 @@ function loadStockTable(table, options) {
var html = renderLink(val, `/stock/item/${row.pk}/`); var html = renderLink(val, `/stock/item/${row.pk}/`);
if (row.allocated) { if (row.allocated) {
html += `<span class='fas fa-bookmark label-right' title='{% trans "StockItem has been allocated" %}'></span>`; html += `<span class='fas fa-bookmark label-right' title='{% trans "Stock item has been allocated" %}'></span>`;
} }
if (row.customer) {
html += `<span class='fas fa-user-tie label-right' title='{% trans "Stock item has been assigned to customer" %}'></span>`;
} else if (row.build_order) {
html += `<span class='fas fa-tools label-right' title='{% trans "Stock item was assigned to a build order" %}'></span>`;
} else if (row.sales_order) {
html += `<span class='fas fa-dollar-sign label-right' title='{% trans "Stock item was assigned to a sales order" %}'></span>`;
}
// Special stock status codes
// 65 = "REJECTED"
if (row.status == 65) {
html += `<span class='fas fa-times-circle label-right' title='{% trans "Stock item has been rejected" %}'></span>`;
}
// 70 = "LOST" // 70 = "LOST"
if (row.status == 70) { else if (row.status == 70) {
html += `<span class='fas fa-question-circle label-right' title='{% trans "StockItem is lost" %}'></span>`; html += `<span class='fas fa-question-circle label-right' title='{% trans "Stock item is lost" %}'></span>`;
}
if (row.quantity <= 0) {
html += `<span class='label label-right label-danger'>{% trans "Depleted" %}</span>`;
} }
return html; return html;

View File

@ -32,30 +32,35 @@ function getAvailableTableFilters(tableKey) {
// Filters for the "Stock" table // Filters for the "Stock" table
if (tableKey == 'stock') { if (tableKey == 'stock') {
return { return {
in_stock: { active: {
type: 'bool', type: 'bool',
title: '{% trans "In Stock" %}', title: '{% trans "Active parts" %}',
description: '{% trans "Show items which are in stock" %}', description: '{% trans "Show stock for active parts" %}',
},
allocated: {
type: 'bool',
title: '{% trans "Is allocated" %}',
description: '{% trans "Item has been alloacted" %}',
}, },
cascade: { cascade: {
type: 'bool', type: 'bool',
title: '{% trans "Include sublocations" %}', title: '{% trans "Include sublocations" %}',
description: '{% trans "Include stock in sublocations" %}', description: '{% trans "Include stock in sublocations" %}',
}, },
active: { depleted: {
type: 'bool', type: 'bool',
title: '{% trans "Active parts" %}', title: '{% trans "Depleted" %}',
description: '{% trans "Show stock for active parts" %}', description: '{% trans "Show stock items which are depleted" %}',
}, },
status: { in_stock: {
options: stockCodes,
title: '{% trans "Stock status" %}',
description: '{% trans "Stock status" %}',
},
allocated: {
type: 'bool', type: 'bool',
title: '{% trans "Is allocated" %}', title: '{% trans "In Stock" %}',
description: '{% trans "Item has been alloacted" %}', 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: { serialized: {
type: 'bool', type: 'bool',
@ -69,6 +74,11 @@ function getAvailableTableFilters(tableKey) {
title: "{% trans "Serial number LTE" %}", title: "{% trans "Serial number LTE" %}",
description: "{% trans "Serial number less than or equal to" %}", description: "{% trans "Serial number less than or equal to" %}",
}, },
status: {
options: stockCodes,
title: '{% trans "Stock status" %}',
description: '{% trans "Stock status" %}',
},
}; };
} }