2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-05-03 13:58:47 +00:00

Merge pull request #1329 from SchrodingersGat/stock-packaging

Stock packaging
This commit is contained in:
Oliver 2021-02-19 12:52:38 +11:00 committed by GitHub
commit 5b549b8dea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 83 additions and 7 deletions

View File

@ -242,6 +242,13 @@ class InvenTreeSetting(models.Model):
'validator': bool,
},
'STOCK_GROUP_BY_PART': {
'name': _('Group by Part'),
'description': _('Group stock items by part reference in table views'),
'default': True,
'validator': bool,
},
'BUILDORDER_REFERENCE_PREFIX': {
'name': _('Build Order Reference Prefix'),
'description': _('Prefix value for build order reference'),

View File

@ -134,6 +134,7 @@ class CreateStockItemForm(HelperForm):
'quantity',
'batch',
'serial_numbers',
'packaging',
'purchase_price',
'expiry_date',
'link',
@ -414,6 +415,7 @@ class EditStockItemForm(HelperForm):
'status',
'expiry_date',
'purchase_price',
'packaging',
'link',
'delete_on_deplete',
'owner',

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.7 on 2021-02-19 00:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('stock', '0057_stock_location_item_owner'),
]
operations = [
migrations.AddField(
model_name='stockitem',
name='packaging',
field=models.CharField(blank=True, help_text='Packaging this stock item is stored in', max_length=50, null=True, verbose_name='Packaging'),
),
]

View File

@ -155,6 +155,7 @@ class StockItem(MPTTModel):
infinite: If True this StockItem can never be exhausted
sales_order: Link to a SalesOrder object (if the StockItem has been assigned to a SalesOrder)
purchase_price: The unit purchase price for this StockItem - this is the unit price at time of purchase (if this item was purchased from an external supplier)
packaging: Description of how the StockItem is packaged (e.g. "reel", "loose", "tape" etc)
"""
# A Query filter which will be re-used in multiple places to determine if a StockItem is actually "in stock"
@ -387,6 +388,13 @@ class StockItem(MPTTModel):
help_text=_('Where is this stock item located?')
)
packaging = models.CharField(
max_length=50,
blank=True, null=True,
verbose_name=_('Packaging'),
help_text=_('Packaging this stock item is stored in')
)
belongs_to = models.ForeignKey(
'self',
verbose_name=_('Installed In'),

View File

@ -198,6 +198,7 @@ class StockItemSerializer(InvenTreeModelSerializer):
'location',
'location_detail',
'notes',
'packaging',
'part',
'part_detail',
'pk',

View File

@ -283,6 +283,13 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
<td>{{ item.batch }}</td>
</tr>
{% endif %}
{% if item.packaging %}
<tr>
<td><span class='fas fa-cube'></span></td>
<td>{% trans "Packaging" %}</td>
<td>{{ item.packaging }}</td>
</tr>
{% endif %}
{% if item.build %}
<tr>
<td><span class='fas fa-tools'></span></td>

View File

@ -15,11 +15,12 @@
<table class='table table-striped table-condensed'>
{% include "InvenTree/settings/header.html" %}
<tbody>
{% include "InvenTree/settings/setting.html" with key="STOCK_ENABLE_EXPIRY" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_STALE_DAYS" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_SALE" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_BUILD" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_OWNERSHIP_CONTROL" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_GROUP_BY_PART" icon="fa-layer-group" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_ENABLE_EXPIRY" icon="fa-stopwatch" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_STALE_DAYS" icon="fa-calendar" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_SALE" icon="fa-truck" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_BUILD" icon="fa-tools" %}
{% include "InvenTree/settings/setting.html" with key="STOCK_OWNERSHIP_CONTROL" icon="fa-users" %}
</tbody>
</table>
{% endblock %}

View File

@ -327,11 +327,13 @@ function loadStockTable(table, options) {
url: options.url || "{% url 'api-stock-list' %}",
queryParams: filters,
customSort: customGroupSorter,
groupBy: true,
name: 'stock',
original: original,
showColumns: true,
{% settings_value 'STOCK_GROUP_BY_PART' as group_by_part %}
{% if group_by_part %}
groupByField: options.groupByField || 'part',
groupBy: true,
groupByFormatter: function(field, id, data) {
var row = data[0];
@ -359,6 +361,29 @@ function loadStockTable(table, options) {
else if (field == 'part_detail.description') {
return row.part_detail.description;
}
else if (field == 'packaging') {
var packaging = [];
data.forEach(function(item) {
var pkg = item.packaging;
if (!pkg) {
pkg = '-';
}
if (!packaging.includes(pkg)) {
packaging.push(pkg);
}
});
if (packaging.length > 1) {
return "...";
} else if (packaging.length == 1) {
return packaging[0];
} else {
return "-";
}
}
else if (field == 'quantity') {
var stock = 0;
var items = 0;
@ -388,7 +413,7 @@ function loadStockTable(table, options) {
// Multiple status codes
if (statii.length > 1) {
return "-";
return "...";
} else if (statii.length == 1) {
return stockStatusDisplay(statii[0]);
} else {
@ -468,6 +493,7 @@ function loadStockTable(table, options) {
return '';
}
},
{% endif %}
columns: [
{
checkbox: true,
@ -619,6 +645,12 @@ function loadStockTable(table, options) {
title: '{% trans "Last Updated" %}',
sortable: true,
},
{
field: 'packaging',
title: '{% trans "Packaging" %}',
sortable: true,
searchable: true,
},
{
field: 'notes',
title: '{% trans "Notes" %}',