More intelligent BuildItem allocation

- Set initial value for quantity based on how many parts are left to allocate
- Auto select the StockItem to take from (if there is only one)
This commit is contained in:
Oliver Walters 2019-05-07 22:46:37 +10:00
parent e58bed41b0
commit 4f84febbd1
3 changed files with 57 additions and 1 deletions

View File

@ -13,9 +13,11 @@ from django.core.exceptions import ValidationError
from django.urls import reverse from django.urls import reverse
from django.db import models, transaction from django.db import models, transaction
from django.db.models import Sum
from django.core.validators import MinValueValidator from django.core.validators import MinValueValidator
from stock.models import StockItem from stock.models import StockItem
from part.models import BomItem
class Build(models.Model): class Build(models.Model):
@ -219,6 +221,38 @@ class Build(models.Model):
self.status = self.COMPLETE self.status = self.COMPLETE
self.save() self.save()
def getAllocatedQuantity(self, part):
""" Calculate the total number of <part> currently allocated to this build
"""
allocated = BuildItem.objects.filter(build=self.id, stock_item__part=part.id).aggregate(Sum('quantity'))
q = allocated['quantity__sum']
if q:
return int(q)
else:
return 0
def getUnallocatedQuantity(self, part):
""" Calculate the quantity of <part> which still needs to be allocated to this build.
Args:
Part - the part to be tested
Returns:
The remaining allocated quantity
"""
try:
bom_item = BomItem.objects.get(part=self.part.id, sub_part=part.id)
except BomItem.DoesNotExist:
return 0
quantity = bom_item.quantity * self.quantity
return quantity - self.getAllocatedQuantity(part)
@property @property
def required_parts(self): def required_parts(self):
""" Returns a dict of parts required to build this part (BOM) """ """ Returns a dict of parts required to build this part (BOM) """

View File

@ -289,6 +289,12 @@ class BuildItemCreate(AjaxCreateView):
query = query.exclude(id__in=[item.stock_item.id for item in BuildItem.objects.filter(build=build_id, stock_item__part=part_id)]) query = query.exclude(id__in=[item.stock_item.id for item in BuildItem.objects.filter(build=build_id, stock_item__part=part_id)])
form.fields['stock_item'].queryset = query form.fields['stock_item'].queryset = query
stocks = query.all()
# If there is only one item selected, select it
if len(stocks) == 1:
form.fields['stock_item'].initial = stocks[0].id
except Part.DoesNotExist: except Part.DoesNotExist:
pass pass
@ -303,10 +309,23 @@ class BuildItemCreate(AjaxCreateView):
initials = super(AjaxCreateView, self).get_initial().copy() initials = super(AjaxCreateView, self).get_initial().copy()
build_id = self.get_param('build') build_id = self.get_param('build')
part_id = self.get_param('part')
if part_id:
try:
part = Part.objects.get(pk=part_id)
except Part.DoesNotExist:
part = None
if build_id: if build_id:
try: try:
initials['build'] = Build.objects.get(pk=build_id) build = Build.objects.get(pk=build_id)
initials['build'] = build
# Try to work out how many parts to allocate
if part:
initials['quantity'] = build.getUnallocatedQuantity(part)
except Build.DoesNotExist: except Build.DoesNotExist:
pass pass

View File

@ -14,6 +14,9 @@
{% crispy form %} {% crispy form %}
{% block form_data %}
{% endblock %}
</form> </form>
{% block post_form_content %} {% block post_form_content %}