mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 05:05:42 +00:00 
			
		
		
		
	Merge pull request #1329 from SchrodingersGat/stock-packaging
Stock packaging
This commit is contained in:
		| @@ -242,6 +242,13 @@ class InvenTreeSetting(models.Model): | |||||||
|             'validator': bool, |             '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': { |         'BUILDORDER_REFERENCE_PREFIX': { | ||||||
|             'name': _('Build Order Reference Prefix'), |             'name': _('Build Order Reference Prefix'), | ||||||
|             'description': _('Prefix value for build order reference'), |             'description': _('Prefix value for build order reference'), | ||||||
|   | |||||||
| @@ -134,6 +134,7 @@ class CreateStockItemForm(HelperForm): | |||||||
|             'quantity', |             'quantity', | ||||||
|             'batch', |             'batch', | ||||||
|             'serial_numbers', |             'serial_numbers', | ||||||
|  |             'packaging', | ||||||
|             'purchase_price', |             'purchase_price', | ||||||
|             'expiry_date', |             'expiry_date', | ||||||
|             'link', |             'link', | ||||||
| @@ -414,6 +415,7 @@ class EditStockItemForm(HelperForm): | |||||||
|             'status', |             'status', | ||||||
|             'expiry_date', |             'expiry_date', | ||||||
|             'purchase_price', |             'purchase_price', | ||||||
|  |             'packaging', | ||||||
|             'link', |             'link', | ||||||
|             'delete_on_deplete', |             'delete_on_deplete', | ||||||
|             'owner', |             'owner', | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								InvenTree/stock/migrations/0058_stockitem_packaging.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								InvenTree/stock/migrations/0058_stockitem_packaging.py
									
									
									
									
									
										Normal 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'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @@ -155,6 +155,7 @@ class StockItem(MPTTModel): | |||||||
|         infinite: If True this StockItem can never be exhausted |         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) |         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) |         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" |     # 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?') |         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( |     belongs_to = models.ForeignKey( | ||||||
|         'self', |         'self', | ||||||
|         verbose_name=_('Installed In'), |         verbose_name=_('Installed In'), | ||||||
|   | |||||||
| @@ -198,6 +198,7 @@ class StockItemSerializer(InvenTreeModelSerializer): | |||||||
|             'location', |             'location', | ||||||
|             'location_detail', |             'location_detail', | ||||||
|             'notes', |             'notes', | ||||||
|  |             'packaging', | ||||||
|             'part', |             'part', | ||||||
|             'part_detail', |             'part_detail', | ||||||
|             'pk', |             'pk', | ||||||
|   | |||||||
| @@ -283,6 +283,13 @@ InvenTree | {% trans "Stock Item" %} - {{ item }} | |||||||
|         <td>{{ item.batch }}</td> |         <td>{{ item.batch }}</td> | ||||||
|     </tr> |     </tr> | ||||||
|     {% endif %} |     {% 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 %} |     {% if item.build %} | ||||||
|     <tr> |     <tr> | ||||||
|         <td><span class='fas fa-tools'></span></td> |         <td><span class='fas fa-tools'></span></td> | ||||||
|   | |||||||
| @@ -15,11 +15,12 @@ | |||||||
| <table class='table table-striped table-condensed'> | <table class='table table-striped table-condensed'> | ||||||
|     {% include "InvenTree/settings/header.html" %} |     {% include "InvenTree/settings/header.html" %} | ||||||
|     <tbody> |     <tbody> | ||||||
|         {% include "InvenTree/settings/setting.html" with key="STOCK_ENABLE_EXPIRY" %} |         {% include "InvenTree/settings/setting.html" with key="STOCK_GROUP_BY_PART" icon="fa-layer-group" %} | ||||||
|         {% include "InvenTree/settings/setting.html" with key="STOCK_STALE_DAYS" %} |         {% include "InvenTree/settings/setting.html" with key="STOCK_ENABLE_EXPIRY" icon="fa-stopwatch" %} | ||||||
|         {% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_SALE" %} |         {% include "InvenTree/settings/setting.html" with key="STOCK_STALE_DAYS" icon="fa-calendar" %} | ||||||
|         {% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_BUILD" %} |         {% include "InvenTree/settings/setting.html" with key="STOCK_ALLOW_EXPIRED_SALE" icon="fa-truck" %} | ||||||
| 	{% include "InvenTree/settings/setting.html" with key="STOCK_OWNERSHIP_CONTROL" %} |         {% 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> |     </tbody> | ||||||
| </table> | </table> | ||||||
| {% endblock %} | {% endblock %} | ||||||
|   | |||||||
| @@ -327,11 +327,13 @@ function loadStockTable(table, options) { | |||||||
|         url: options.url || "{% url 'api-stock-list' %}", |         url: options.url || "{% url 'api-stock-list' %}", | ||||||
|         queryParams: filters, |         queryParams: filters, | ||||||
|         customSort: customGroupSorter, |         customSort: customGroupSorter, | ||||||
|         groupBy: true, |  | ||||||
|         name: 'stock', |         name: 'stock', | ||||||
|         original: original, |         original: original, | ||||||
|         showColumns: true, |         showColumns: true, | ||||||
|  |         {% settings_value 'STOCK_GROUP_BY_PART' as group_by_part %} | ||||||
|  |         {% if group_by_part %} | ||||||
|         groupByField: options.groupByField || 'part', |         groupByField: options.groupByField || 'part', | ||||||
|  |         groupBy: true, | ||||||
|         groupByFormatter: function(field, id, data) { |         groupByFormatter: function(field, id, data) { | ||||||
|  |  | ||||||
|             var row = data[0]; |             var row = data[0]; | ||||||
| @@ -359,6 +361,29 @@ function loadStockTable(table, options) { | |||||||
|             else if (field == 'part_detail.description') { |             else if (field == 'part_detail.description') { | ||||||
|                 return row.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') { |             else if (field == 'quantity') { | ||||||
|                 var stock = 0; |                 var stock = 0; | ||||||
|                 var items = 0; |                 var items = 0; | ||||||
| @@ -388,7 +413,7 @@ function loadStockTable(table, options) { | |||||||
|  |  | ||||||
|                 // Multiple status codes |                 // Multiple status codes | ||||||
|                 if (statii.length > 1) { |                 if (statii.length > 1) { | ||||||
|                     return "-"; |                     return "..."; | ||||||
|                 } else if (statii.length == 1) { |                 } else if (statii.length == 1) { | ||||||
|                     return stockStatusDisplay(statii[0]); |                     return stockStatusDisplay(statii[0]); | ||||||
|                 } else { |                 } else { | ||||||
| @@ -468,6 +493,7 @@ function loadStockTable(table, options) { | |||||||
|                 return ''; |                 return ''; | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|  |         {% endif %} | ||||||
|         columns: [ |         columns: [ | ||||||
|             { |             { | ||||||
|                 checkbox: true, |                 checkbox: true, | ||||||
| @@ -619,6 +645,12 @@ function loadStockTable(table, options) { | |||||||
|                 title: '{% trans "Last Updated" %}', |                 title: '{% trans "Last Updated" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|             }, |             }, | ||||||
|  |             { | ||||||
|  |                 field: 'packaging', | ||||||
|  |                 title: '{% trans "Packaging" %}', | ||||||
|  |                 sortable: true, | ||||||
|  |                 searchable: true, | ||||||
|  |             }, | ||||||
|             { |             { | ||||||
|                 field: 'notes', |                 field: 'notes', | ||||||
|                 title: '{% trans "Notes" %}', |                 title: '{% trans "Notes" %}', | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user