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 2022-04-15 19:12:36 +10:00
commit 7164271925
9 changed files with 104 additions and 22 deletions

View File

@ -12,11 +12,14 @@ import common.models
INVENTREE_SW_VERSION = "0.7.0 dev" INVENTREE_SW_VERSION = "0.7.0 dev"
# InvenTree API version # InvenTree API version
INVENTREE_API_VERSION = 37 INVENTREE_API_VERSION = 38
""" """
Increment this API version number whenever there is a significant change to the API that any clients need to know about Increment this API version number whenever there is a significant change to the API that any clients need to know about
v38 -> 2022-04-14 : https://github.com/inventree/InvenTree/pull/2828
- Adds the ability to include stock test results for "installed items"
v37 -> 2022-04-07 : https://github.com/inventree/InvenTree/pull/2806 v37 -> 2022-04-07 : https://github.com/inventree/InvenTree/pull/2806
- Adds extra stock availability information to the BomItem serializer - Adds extra stock availability information to the BomItem serializer

View File

@ -1313,19 +1313,31 @@ class Part(MPTTModel):
return quantity return quantity
def build_order_allocations(self): def build_order_allocations(self, **kwargs):
""" """
Return all 'BuildItem' objects which allocate this part to Build objects Return all 'BuildItem' objects which allocate this part to Build objects
""" """
return BuildModels.BuildItem.objects.filter(stock_item__part__id=self.id) include_variants = kwargs.get('include_variants', True)
def build_order_allocation_count(self): queryset = BuildModels.BuildItem.objects.all()
if include_variants:
variants = self.get_descendants(include_self=True)
queryset = queryset.filter(
stock_item__part__in=variants,
)
else:
queryset = queryset.filter(stock_item__part=self)
return queryset
def build_order_allocation_count(self, **kwargs):
""" """
Return the total amount of this part allocated to build orders Return the total amount of this part allocated to build orders
""" """
query = self.build_order_allocations().aggregate( query = self.build_order_allocations(**kwargs).aggregate(
total=Coalesce( total=Coalesce(
Sum( Sum(
'quantity', 'quantity',
@ -1343,7 +1355,19 @@ class Part(MPTTModel):
Return all sales-order-allocation objects which allocate this part to a SalesOrder Return all sales-order-allocation objects which allocate this part to a SalesOrder
""" """
queryset = OrderModels.SalesOrderAllocation.objects.filter(item__part__id=self.id) include_variants = kwargs.get('include_variants', True)
queryset = OrderModels.SalesOrderAllocation.objects.all()
if include_variants:
# Include allocations for all variants
variants = self.get_descendants(include_self=True)
queryset = queryset.filter(
item__part__in=variants,
)
else:
# Only look at this part
queryset = queryset.filter(item__part=self)
# Default behaviour is to only return *pending* allocations # Default behaviour is to only return *pending* allocations
pending = kwargs.get('pending', True) pending = kwargs.get('pending', True)
@ -1381,7 +1405,7 @@ class Part(MPTTModel):
return query['total'] return query['total']
def allocation_count(self): def allocation_count(self, **kwargs):
""" """
Return the total quantity of stock allocated for this part, Return the total quantity of stock allocated for this part,
against both build orders and sales orders. against both build orders and sales orders.
@ -1389,8 +1413,8 @@ class Part(MPTTModel):
return sum( return sum(
[ [
self.build_order_allocation_count(), self.build_order_allocation_count(**kwargs),
self.sales_order_allocation_count(), self.sales_order_allocation_count(**kwargs),
], ],
) )

View File

@ -252,7 +252,6 @@
</tr> </tr>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if not part.is_template %}
{% if part.assembly %} {% if part.assembly %}
<tr> <tr>
<td><span class='fas fa-tools'></span></td> <td><span class='fas fa-tools'></span></td>
@ -266,7 +265,6 @@
<td>{% decimal quantity_being_built %}</td> <td>{% decimal quantity_being_built %}</td>
</tr> </tr>
{% endif %} {% endif %}
{% endif %}
{% endif %} {% endif %}
</table> </table>
{% endblock details_right %} {% endblock details_right %}

View File

@ -1105,7 +1105,6 @@ class StockItemTestResultList(generics.ListCreateAPIView):
] ]
filter_fields = [ filter_fields = [
'stock_item',
'test', 'test',
'user', 'user',
'result', 'result',
@ -1114,6 +1113,38 @@ class StockItemTestResultList(generics.ListCreateAPIView):
ordering = 'date' ordering = 'date'
def filter_queryset(self, queryset):
params = self.request.query_params
queryset = super().filter_queryset(queryset)
# Filter by stock item
item = params.get('stock_item', None)
if item is not None:
try:
item = StockItem.objects.get(pk=item)
items = [item]
# Do we wish to also include test results for 'installed' items?
include_installed = str2bool(params.get('include_installed', False))
if include_installed:
# Include items which are installed "underneath" this item
# Note that this function is recursive!
installed_items = item.get_installed_items(cascade=True)
items += [it for it in installed_items]
queryset = queryset.filter(stock_item__in=items)
except (ValueError, StockItem.DoesNotExist):
pass
return queryset
def get_serializer(self, *args, **kwargs): def get_serializer(self, *args, **kwargs):
try: try:
kwargs['user_detail'] = str2bool(self.request.query_params.get('user_detail', False)) kwargs['user_detail'] = str2bool(self.request.query_params.get('user_detail', False))

View File

@ -24,6 +24,7 @@
{% include "InvenTree/settings/setting.html" with key="ENABLE_PLUGINS_URL" icon="fa-link" %} {% include "InvenTree/settings/setting.html" with key="ENABLE_PLUGINS_URL" icon="fa-link" %}
{% include "InvenTree/settings/setting.html" with key="ENABLE_PLUGINS_NAVIGATION" icon="fa-sitemap" %} {% include "InvenTree/settings/setting.html" with key="ENABLE_PLUGINS_NAVIGATION" icon="fa-sitemap" %}
{% include "InvenTree/settings/setting.html" with key="ENABLE_PLUGINS_APP" icon="fa-rocket" %} {% include "InvenTree/settings/setting.html" with key="ENABLE_PLUGINS_APP" icon="fa-rocket" %}
{% include "InvenTree/settings/setting.html" with key="PLUGIN_ON_STARTUP" %}
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -34,8 +34,8 @@
// Should the ID be rendered for this string // Should the ID be rendered for this string
function renderId(title, pk, parameters={}) { function renderId(title, pk, parameters={}) {
// Default = true // Default = do not display
var render = true; var render = false;
if ('render_pk' in parameters) { if ('render_pk' in parameters) {
render = parameters['render_pk']; render = parameters['render_pk'];
@ -192,7 +192,7 @@ function renderPart(name, data, parameters={}, options={}) {
<small> <small>
${stock_data} ${stock_data}
${extra} ${extra}
${renderId('{% trans "Part ID" $}', data.pk, parameters)} ${renderId('{% trans "Part ID" %}', data.pk, parameters)}
</small> </small>
</span>`; </span>`;

View File

@ -373,6 +373,9 @@ function duplicatePart(pk, options={}) {
// Override the "variant_of" field // Override the "variant_of" field
data.variant_of = pk; data.variant_of = pk;
// By default, disable "is_template" when making a variant *of* a template
data.is_template = false;
} }
constructForm('{% url "api-part-list" %}', { constructForm('{% url "api-part-list" %}', {

View File

@ -1331,14 +1331,27 @@ function loadStockTestResultsTable(table, options) {
}); });
// Once the test template data are loaded, query for test results // Once the test template data are loaded, query for test results
var filters = loadTableFilters(filterKey);
var query_params = {
stock_item: options.stock_item,
user_detail: true,
attachment_detail: true,
ordering: '-date',
};
if ('result' in filters) {
query_params.result = filters.result;
}
if ('include_installed' in filters) {
query_params.include_installed = filters.include_installed;
}
inventreeGet( inventreeGet(
'{% url "api-stock-test-result-list" %}', '{% url "api-stock-test-result-list" %}',
{ query_params,
stock_item: options.stock_item,
user_detail: true,
attachment_detail: true,
ordering: '-date',
},
{ {
success: function(data) { success: function(data) {
// Iterate through the returned test data // Iterate through the returned test data

View File

@ -265,7 +265,16 @@ function getAvailableTableFilters(tableKey) {
// Filters for the 'stock test' table // Filters for the 'stock test' table
if (tableKey == 'stocktests') { if (tableKey == 'stocktests') {
return {}; return {
result: {
type: 'bool',
title: '{% trans "Test Passed" %}',
},
include_installed: {
type: 'bool',
title: '{% trans "Include Installed Items" %}',
}
};
} }
// Filters for the 'part test template' table // Filters for the 'part test template' table