mirror of
https://github.com/inventree/InvenTree.git
synced 2025-07-01 11:10:54 +00:00
Update definition for StockItemAllocation model
- Limit foreignkey choices - Error checking - Check if a StockItem is over-allocated - Fix API serialization and filtering
This commit is contained in:
@ -374,10 +374,12 @@ class StockList(generics.ListCreateAPIView):
|
||||
allocated = str2bool(allocated)
|
||||
|
||||
if allocated:
|
||||
stock_list = stock_list.exclude(Q(sales_order_line=None))
|
||||
# Filter StockItem with either build allocations or sales order allocations
|
||||
stock_list = stock_list.filter(Q(sales_order_allocations__isnull=False) | Q(allocations__isnull=False))
|
||||
else:
|
||||
stock_list = stock_list.filter(Q(sales_order_line=None))
|
||||
|
||||
# Filter StockItem without build allocations or sales order allocations
|
||||
stock_list = stock_list.filter(Q(sales_order_allocations__isnull=True) & Q(allocations__isnull=True))
|
||||
|
||||
# Do we wish to filter by "active parts"
|
||||
active = self.request.query_params.get('active', None)
|
||||
|
||||
@ -477,22 +479,10 @@ class StockList(generics.ListCreateAPIView):
|
||||
if manufacturer is not None:
|
||||
stock_list = stock_list.filter(supplier_part__manufacturer=manufacturer)
|
||||
|
||||
# Filter by sales order
|
||||
sales_order = self.request.query_params.get('sales_order', None)
|
||||
|
||||
if sales_order is not None:
|
||||
try:
|
||||
sales_order = SalesOrder.objects.get(pk=sales_order)
|
||||
lines = [line.pk for line in sales_order.lines.all()]
|
||||
stock_list = stock_list.filter(sales_order_line__in=lines)
|
||||
except (SalesOrder.DoesNotExist, ValueError):
|
||||
raise ValidationError({'sales_order': 'Invalid SalesOrder object specified'})
|
||||
|
||||
# Also ensure that we pre-fecth all the related items
|
||||
stock_list = stock_list.prefetch_related(
|
||||
'part',
|
||||
'part__category',
|
||||
'sales_order_line__order',
|
||||
'location'
|
||||
)
|
||||
|
||||
@ -517,7 +507,7 @@ class StockList(generics.ListCreateAPIView):
|
||||
'customer',
|
||||
'belongs_to',
|
||||
'build',
|
||||
'sales_order_line'
|
||||
'sales_order',
|
||||
]
|
||||
|
||||
|
||||
|
@ -11,6 +11,8 @@ from django.core.exceptions import ValidationError
|
||||
from django.urls import reverse
|
||||
|
||||
from django.db import models, transaction
|
||||
from django.db.models import Sum
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.core.validators import MinValueValidator
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models.signals import pre_delete
|
||||
@ -29,7 +31,7 @@ from InvenTree.models import InvenTreeTree
|
||||
from InvenTree.fields import InvenTreeURLField
|
||||
|
||||
from part.models import Part
|
||||
from order.models import PurchaseOrder, SalesOrder
|
||||
from order.models import PurchaseOrder, SalesOrder, SalesOrderAllocation
|
||||
|
||||
|
||||
class StockLocation(InvenTreeTree):
|
||||
@ -391,7 +393,39 @@ class StockItem(MPTTModel):
|
||||
# TODO - For now this only checks if the StockItem is allocated to a SalesOrder
|
||||
# TODO - In future, once the "build" is working better, check this too
|
||||
|
||||
return self.sales_order_line is not None
|
||||
if self.allocations.count() > 0:
|
||||
return True
|
||||
|
||||
if self.sales_order_allocations.count() > 0:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def build_allocation_count(self):
|
||||
"""
|
||||
Return the total quantity allocated to builds
|
||||
"""
|
||||
|
||||
query = self.allocations.aggregate(q=Coalesce(Sum('quantity'), Decimal(0)))
|
||||
|
||||
return query['q']
|
||||
|
||||
def sales_order_allocation_count(self):
|
||||
"""
|
||||
Return the total quantity allocated to SalesOrders
|
||||
"""
|
||||
|
||||
query = self.sales_order_allocations.aggregate(q=Coalesce(Sum('quantity'), Decimal(0)))
|
||||
|
||||
return query['q']
|
||||
|
||||
def allocation_count(self):
|
||||
"""
|
||||
Return the total quantity allocated to builds or orders
|
||||
"""
|
||||
|
||||
return self.build_allocation_count() + self.sales_order_allocation_count()
|
||||
|
||||
|
||||
def can_delete(self):
|
||||
""" Can this stock item be deleted? It can NOT be deleted under the following circumstances:
|
||||
|
@ -67,6 +67,8 @@ class StockItemSerializer(InvenTreeModelSerializer):
|
||||
'supplier_part',
|
||||
'supplier_part__supplier',
|
||||
'supplier_part__manufacturer',
|
||||
'allocations',
|
||||
'sales_order_allocations',
|
||||
'location',
|
||||
'part',
|
||||
'tracking_info',
|
||||
|
@ -15,12 +15,19 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
|
||||
{% block pre_content %}
|
||||
{% include 'stock/loc_link.html' with location=item.location %}
|
||||
|
||||
{% if item.sales_order_line %}
|
||||
{% for allocation in item.sales_order_allocations.all %}
|
||||
<div class='alert alert-block alert-info'>
|
||||
{% trans "This stock item is allocated to Sales Order" %}
|
||||
<a href="{% url 'so-detail' item.sales_order_line.order.id %}"><b>{{ item.sales_order_line.order }}</b></a>
|
||||
<a href="{% url 'so-detail' allocation.line.order.id %}"><b>{{ allcation.line.order }}</b></a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% for allocation in item.allocations.all %}
|
||||
<div class='alert alert-block alert-info'>
|
||||
{% trans "This stock item is allocated to Build" %}
|
||||
<a href="{% url 'build-detail' allocation.build.id %}"><b>{{ allocation.build }}</b></a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% if item.serialized %}
|
||||
<div class='alert alert-block alert-info'>
|
||||
|
Reference in New Issue
Block a user