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:
commit
7164271925
@ -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
|
||||||
|
|
||||||
|
@ -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),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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 %}
|
||||||
|
@ -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))
|
||||||
|
@ -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>
|
||||||
|
@ -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>`;
|
||||||
|
|
||||||
|
@ -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" %}', {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user