2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-30 20:46:47 +00:00

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): class CompleteBuildForm(HelperForm):
""" Form for marking a Build as complete """ """ 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) - If there are multiple StockItems available, ignore (leave up to the user)
Returns: 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(): for item in self.part.bom_items.all():
@ -151,12 +151,17 @@ class Build(models.Model):
# Are there any parts available? # Are there any parts available?
if stock_item.quantity > 0: if stock_item.quantity > 0:
# Only take as many as are available # Only take as many as are available
if stock_item.quantity < q_required: if stock_item.quantity < q_required:
q_required = stock_item.quantity q_required = stock_item.quantity
# Add the item to the allocations list allocation = {
allocations[stock_item] = q_required 'stock_item': stock_item,
'quantity': q_required,
}
allocations.append(allocation)
return allocations return allocations
@ -164,6 +169,13 @@ class Build(models.Model):
def autoAllocate(self): def autoAllocate(self):
""" Run auto-allocation routine to allocate StockItems to this Build. """ 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() See: getAutoAllocations()
""" """
@ -173,8 +185,8 @@ class Build(models.Model):
# Create a new allocation # Create a new allocation
build_item = BuildItem( build_item = BuildItem(
build=self, build=self,
stock_item=item, stock_item=item['stock_item'],
quantity=allocations[item]) quantity=item['quantity'])
build_item.save() build_item.save()

View File

@ -18,7 +18,8 @@ InvenTree | Allocate Parts
</div> </div>
<div class='col-sm-6'> <div class='col-sm-6'>
<div class='btn-group' style='float: right;'> <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> </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 %} {% 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> <hr>
{% if taking %} {% if taking %}
The following items will be removed from stock: The following items will be removed from stock:
<ul> <ul class='list-group'>
{% for item in taking %} {% for item in taking %}
<li>{{ item.quantity }} x {{ item.stock_item.part.name }} from {{ item.stock_item.location }}</li> <li>{{ item.quantity }} x {{ item.stock_item.part.name }} from {{ item.stock_item.location }}</li>
{% endfor %} {% endfor %}

View File

@ -21,6 +21,7 @@ build_detail_urls = [
url(r'^allocate/?', views.BuildAllocate.as_view(), name='build-allocate'), url(r'^allocate/?', views.BuildAllocate.as_view(), name='build-allocate'),
url(r'^cancel/?', views.BuildCancel.as_view(), name='build-cancel'), url(r'^cancel/?', views.BuildCancel.as_view(), name='build-cancel'),
url(r'^complete/?', views.BuildComplete.as_view(), name='build-complete'), 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'), 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 part.models import Part
from .models import Build, BuildItem 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 stock.models import StockLocation, StockItem
from InvenTree.views import AjaxView, AjaxUpdateView, AjaxCreateView, AjaxDeleteView 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): class BuildComplete(AjaxUpdateView):
""" View to mark a build as Complete. """ View to mark a build as Complete.