Auto-allocation form now working

- Displays a list of stock items which will be allocated
This commit is contained in:
Oliver Walters 2019-05-09 23:55:30 +10:00
parent 793b4f8063
commit 7835562396
7 changed files with 142 additions and 9 deletions

View File

@ -27,6 +27,18 @@ class EditBuildForm(HelperForm):
]
class AutoAllocateBuildForm(HelperForm):
""" Form for auto-allocation of stock to a build """
confirm = forms.BooleanField(required=False, help_text='Confirm stock allocation')
class Meta:
model = Build
fields = [
'confirm'
]
class CompleteBuildForm(HelperForm):
""" Form for marking a Build as complete """

View File

@ -127,10 +127,10 @@ class Build(models.Model):
- If there are multiple StockItems available, ignore (leave up to the user)
Returns:
A dict object containing the StockItem objects to be allocated (and the quantities)
A list object containing the StockItem objects to be allocated (and the quantities)
"""
allocations = {}
allocations = []
for item in self.part.bom_items.all():
@ -151,12 +151,17 @@ class Build(models.Model):
# Are there any parts available?
if stock_item.quantity > 0:
# Only take as many as are available
if stock_item.quantity < q_required:
q_required = stock_item.quantity
# Add the item to the allocations list
allocations[stock_item] = q_required
allocation = {
'stock_item': stock_item,
'quantity': q_required,
}
allocations.append(allocation)
return allocations
@ -164,6 +169,13 @@ class Build(models.Model):
def autoAllocate(self):
""" Run auto-allocation routine to allocate StockItems to this Build.
Returns a list of dict objects with keys like:
{
'stock_item': item,
'quantity': quantity,
}
See: getAutoAllocations()
"""
@ -173,8 +185,8 @@ class Build(models.Model):
# Create a new allocation
build_item = BuildItem(
build=self,
stock_item=item,
quantity=allocations[item])
stock_item=item['stock_item'],
quantity=item['quantity'])
build_item.save()

View File

@ -18,7 +18,8 @@ InvenTree | Allocate Parts
</div>
<div class='col-sm-6'>
<div class='btn-group' style='float: right;'>
<button class='btn btn-warning' type='button' id='complete-build'>Complete Build</button>
<button class='btn btn-primary' type='button' title='Automatic allocation' id='auto-allocate-build'>Auto Allocate</button>
<button class='btn btn-warning' type='button' title='Complete build' id='complete-build'>Complete Build</button>
</div>
</div>
</div>
@ -64,4 +65,13 @@ InvenTree | Allocate Parts
);
});
$("#auto-allocate-build").on('click', function() {
launchModalForm(
"{% url 'build-auto-allocate' build.id %}",
{
reload: true,
}
);
});
{% endblock %}

View File

@ -0,0 +1,43 @@
{% extends "modal_form.html" %}
{% block pre_form_content %}
{{ block.super }}
<b>Build: {{ build.title }}</b> - {{ build.quantity }} x {{ build.part.name }}
<br><br>
Automatically allocate stock to this build?
<hr>
{% if allocations %}
<table class='table table-striped table-condensed'>
<tr>
<th></th>
<th>Part</th>
<th>Quantity</th>
<th>Location</th>
</tr>
{% for item in allocations %}
<tr>
<td>
<a class='hover-icon'>
<img class='hover-img-thumb' src='{{ item.stock_item.part.image.url }}'>
<img class='hover-img-large' src='{{ item.stock_item.part.image.url }}'>
</a>
</td>
<td>
{{ item.stock_item.part.name }}<br>
<i>{{ item.stock_item.part.description }}</i>
</td>
<td>{{ item.quantity }}</td>
<td>{{ item.stock_item.location }}</td>
</tr>
{% endfor %}
</table>
{% else %}
<i>No stock could be selected for automatic build allocation.</i>
{% endif %}
{% endblock %}

View File

@ -7,7 +7,7 @@ Are you sure you want to mark this build as complete?
<hr>
{% if taking %}
The following items will be removed from stock:
<ul>
<ul class='list-group'>
{% for item in taking %}
<li>{{ item.quantity }} x {{ item.stock_item.part.name }} from {{ item.stock_item.location }}</li>
{% endfor %}

View File

@ -21,6 +21,7 @@ build_detail_urls = [
url(r'^allocate/?', views.BuildAllocate.as_view(), name='build-allocate'),
url(r'^cancel/?', views.BuildCancel.as_view(), name='build-cancel'),
url(r'^complete/?', views.BuildComplete.as_view(), name='build-complete'),
url(r'^auto-allocate/?', views.BuildAutoAllocate.as_view(), name='build-auto-allocate'),
url(r'^.*$', views.BuildDetail.as_view(), name='build-detail'),
]

View File

@ -12,7 +12,7 @@ from django.forms import HiddenInput
from part.models import Part
from .models import Build, BuildItem
from .forms import EditBuildForm, EditBuildItemForm, CompleteBuildForm
from .forms import EditBuildForm, EditBuildItemForm, CompleteBuildForm, AutoAllocateBuildForm
from stock.models import StockLocation, StockItem
from InvenTree.views import AjaxView, AjaxUpdateView, AjaxCreateView, AjaxDeleteView
@ -67,6 +67,61 @@ class BuildCancel(AjaxView):
}
class BuildAutoAllocate(AjaxUpdateView):
""" View to auto-allocate parts for a build.
Follows a simple set of rules to automatically allocate StockItem objects.
Ref: build.models.Build.getAutoAllocations()
"""
model = Build
form_class = AutoAllocateBuildForm
context_object_name = 'build'
ajax_form_title = 'Allocate Stock'
ajax_template_name = 'build/auto_allocate.html'
def get_context_data(self, *args, **kwargs):
""" Get the context data for form rendering. """
context = {}
try:
build = Build.objects.get(id=self.kwargs['pk'])
context['build'] = build
context['allocations'] = build.getAutoAllocations()
except Build.DoesNotExist:
context['error'] = 'No matching buidl found'
return context
def post(self, request, *args, **kwargs):
""" Handle POST request. Perform auto allocations.
- If the form validation passes, perform allocations
- Otherwise, the form is passed back to the client
"""
build = self.get_object()
form = self.get_form()
confirm = request.POST.get('confirm', False)
valid = False
if confirm is False:
form.errors['confirm'] = ['Confirm stock allocation']
form.non_field_errors = 'Check the confirmation box at the bottom of the list'
else:
build.autoAllocate()
valid = True
data = {
'form_valid': valid,
}
return self.renderJsonResponse(request, form, data, context=self.get_context_data())
class BuildComplete(AjaxUpdateView):
""" View to mark a build as Complete.