mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 21:25:42 +00:00 
			
		
		
		
	Pack quantity improvements (#3661)
* Specify serializer label * Add units to part grid view * improve display of stock units in part table * Add units display to stock on part page * Display units in supplier part table * Simplify stock quantity display in stock table
This commit is contained in:
		| @@ -165,11 +165,8 @@ class RoundingDecimalField(models.DecimalField): | |||||||
|  |  | ||||||
|     def formfield(self, **kwargs): |     def formfield(self, **kwargs): | ||||||
|         """Return a Field instance for this field.""" |         """Return a Field instance for this field.""" | ||||||
|         defaults = { |  | ||||||
|             'form_class': RoundingDecimalFormField |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         defaults.update(kwargs) |         kwargs['form_class'] = RoundingDecimalFormField | ||||||
|  |  | ||||||
|         return super().formfield(**kwargs) |         return super().formfield(**kwargs) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -239,7 +239,7 @@ class SupplierPartSerializer(InvenTreeModelSerializer): | |||||||
|  |  | ||||||
|     pretty_name = serializers.CharField(read_only=True) |     pretty_name = serializers.CharField(read_only=True) | ||||||
|  |  | ||||||
|     pack_size = serializers.FloatField() |     pack_size = serializers.FloatField(label=_('Pack Quantity')) | ||||||
|  |  | ||||||
|     def __init__(self, *args, **kwargs): |     def __init__(self, *args, **kwargs): | ||||||
|         """Initialize this serializer with extra detail fields as required""" |         """Initialize this serializer with extra detail fields as required""" | ||||||
|   | |||||||
| @@ -198,14 +198,14 @@ | |||||||
|         <tr> |         <tr> | ||||||
|             <td><span class='fas fa-flag'></span></td> |             <td><span class='fas fa-flag'></span></td> | ||||||
|             <td>{% trans "Minimum Stock" %}</td> |             <td>{% trans "Minimum Stock" %}</td> | ||||||
|             <td>{{ part.minimum_stock }}</td> |             <td>{{ part.minimum_stock }} {{ part.units }}</td> | ||||||
|         </tr> |         </tr> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|         {% if on_order > 0 %} |         {% if on_order > 0 %} | ||||||
|         <tr> |         <tr> | ||||||
|             <td><span class='fas fa-shopping-cart'></span></td> |             <td><span class='fas fa-shopping-cart'></span></td> | ||||||
|             <td>{% trans "On Order" %}</td> |             <td>{% trans "On Order" %}</td> | ||||||
|             <td>{% decimal on_order %}</td> |             <td>{% decimal on_order %} {{ part.units }}</td> | ||||||
|         </tr> |         </tr> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|         {% if part.component %} |         {% if part.component %} | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| {% load inventree_extras %} | {% load inventree_extras %} | ||||||
| {% load i18n %} | {% load i18n %} | ||||||
|  |  | ||||||
| {% decimal total_stock %} | {% decimal total_stock %} {{ part.units }} | ||||||
|  |  | ||||||
| {% if total_stock == 0 %} | {% if total_stock == 0 %} | ||||||
| <span class='badge badge-right rounded-pill bg-danger'>{% trans "No Stock" %}</span> | <span class='badge badge-right rounded-pill bg-danger'>{% trans "No Stock" %}</span> | ||||||
|   | |||||||
| @@ -995,6 +995,15 @@ function loadSupplierPartTable(table, url, options) { | |||||||
|                 field: 'pack_size', |                 field: 'pack_size', | ||||||
|                 title: '{% trans "Pack Quantity" %}', |                 title: '{% trans "Pack Quantity" %}', | ||||||
|                 sortable: true, |                 sortable: true, | ||||||
|  |                 formatter: function(value, row) { | ||||||
|  |                     var output = `${value}`; | ||||||
|  |  | ||||||
|  |                     if (row.part_detail) { | ||||||
|  |                         output += ` ${row.part_detail.units}`; | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     return output; | ||||||
|  |                 } | ||||||
|             }, |             }, | ||||||
|             { |             { | ||||||
|                 field: 'link', |                 field: 'link', | ||||||
|   | |||||||
| @@ -1324,22 +1324,23 @@ function partGridTile(part) { | |||||||
|     // Rows for table view |     // Rows for table view | ||||||
|     var rows = ''; |     var rows = ''; | ||||||
|  |  | ||||||
|     var stock = `${part.in_stock}`; |     var units = part.units; | ||||||
|  |     var stock = `${part.in_stock} ${part.units}`; | ||||||
|  |  | ||||||
|     if (!part.in_stock) { |     if (!part.in_stock) { | ||||||
|         stock = `<span class='badge rounded-pill bg-danger'>{% trans "No Stock" %}</span>`; |         stock = `<span class='badge rounded-pill bg-danger'>{% trans "No Stock" %}</span>`; | ||||||
|     } else if (!part.unallocated_stock) { |     } else if (!part.unallocated_stock) { | ||||||
|         stock = `<span class='badge rounded-pill bg-warning'>{% trans "Not available" %}</span>`; |         stock = `<span class='badge rounded-pill bg-warning'>{% trans "No Stock" %}</span>`; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     rows += `<tr><td><b>{% trans "Stock" %}</b></td><td>${stock}</td></tr>`; |     rows += `<tr><td><b>{% trans "Stock" %}</b></td><td>${stock}</td></tr>`; | ||||||
|  |  | ||||||
|     if (part.ordering) { |     if (part.ordering) { | ||||||
|         rows += `<tr><td><b>{% trans "On Order" %}</b></td><td>${part.ordering}</td></tr>`; |         rows += `<tr><td><b>{% trans "On Order" %}</b></td><td>${part.ordering} ${units}</td></tr>`; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (part.building) { |     if (part.building) { | ||||||
|         rows += `<tr><td><b>{% trans "Building" %}</b></td><td>${part.building}</td></tr>`; |         rows += `<tr><td><b>{% trans "Building" %}</b></td><td>${part.building} ${units}</td></tr>`; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     var html = ` |     var html = ` | ||||||
| @@ -1356,10 +1357,10 @@ function partGridTile(part) { | |||||||
|             </div> |             </div> | ||||||
|             <div class='panel-content'> |             <div class='panel-content'> | ||||||
|                 <div class='row'> |                 <div class='row'> | ||||||
|                     <div class='col-sm-6'> |                     <div class='col-sm-4'> | ||||||
|                         <img src='${part.thumbnail}' class='card-thumb' onclick='showModalImage("${part.image}")'> |                         <img src='${part.thumbnail}' style='width: 100%;' class='card-thumb' onclick='showModalImage("${part.image}")'> | ||||||
|                     </div> |                     </div> | ||||||
|                     <div class='col-sm-6'> |                     <div class='col-sm-8'> | ||||||
|                         <table class='table table-striped table-condensed'> |                         <table class='table table-striped table-condensed'> | ||||||
|                             ${rows} |                             ${rows} | ||||||
|                         </table> |                         </table> | ||||||
| @@ -1505,11 +1506,7 @@ function loadPartTable(table, url, options={}) { | |||||||
|                 total_stock += row.variant_stock; |                 total_stock += row.variant_stock; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (row.unallocated_stock != row.in_stock) { |             var text = `${total_stock}`; | ||||||
|                 text = `${row.unallocated_stock} / ${total_stock}`; |  | ||||||
|             } else { |  | ||||||
|                 text = `${total_stock}`; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             // Construct extra informational badges |             // Construct extra informational badges | ||||||
|             var badges = ''; |             var badges = ''; | ||||||
| @@ -1538,6 +1535,18 @@ function loadPartTable(table, url, options={}) { | |||||||
|                 badges += `<span class='fas fa-info-circle float-right' title='{% trans "Includes variant stock" %}'></span>`; |                 badges += `<span class='fas fa-info-circle float-right' title='{% trans "Includes variant stock" %}'></span>`; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             if (row.allocated_to_build_orders > 0) { | ||||||
|  |                 badges += `<span class='fas fa-bookmark icon-yellow float-right' title='{% trans "Allocated to build orders" %}: ${row.allocated_to_build_orders}'></span>`; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (row.allocated_to_sales_orders > 0) { | ||||||
|  |                 badges += `<span class='fas fa-bookmark icon-yellow float-right' title='{% trans "Allocated to sales orders" %}: ${row.allocated_to_sales_orders}'></span>`; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (row.units) { | ||||||
|  |                 text += ` <small>${row.units}</small>`; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             text = renderLink(text, `/part/${row.pk}/?display=part-stock`); |             text = renderLink(text, `/part/${row.pk}/?display=part-stock`); | ||||||
|             text += badges; |             text += badges; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1757,20 +1757,16 @@ function loadStockTable(table, options) { | |||||||
|  |  | ||||||
|             var val = ''; |             var val = ''; | ||||||
|  |  | ||||||
|             var available = Math.max(0, (row.quantity || 0) - (row.allocated || 0)); |  | ||||||
|  |  | ||||||
|             if (row.serial && row.quantity == 1) { |             if (row.serial && row.quantity == 1) { | ||||||
|                 // If there is a single unit with a serial number, use the serial number |                 // If there is a single unit with a serial number, use the serial number | ||||||
|                 val = '# ' + row.serial; |                 val = '# ' + row.serial; | ||||||
|             } else if (row.quantity != available) { |  | ||||||
|                 // Some quantity is available, show available *and* quantity |  | ||||||
|                 var ava = formatDecimal(available); |  | ||||||
|                 var tot = formatDecimal(row.quantity); |  | ||||||
|  |  | ||||||
|                 val = `${ava} / ${tot}`; |  | ||||||
|             } else { |             } else { | ||||||
|                 // Format floating point numbers with this one weird trick |                 // Format floating point numbers with this one weird trick | ||||||
|                 val = formatDecimal(value); |                 val = formatDecimal(value); | ||||||
|  |  | ||||||
|  |                 if (row.part_detail) { | ||||||
|  |                     val += ` ${row.part_detail.units}`; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             var html = renderLink(val, `/stock/item/${row.pk}/`); |             var html = renderLink(val, `/stock/item/${row.pk}/`); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user