Merge pull request #555 from SchrodingersGat/new-loc

PO Features
This commit is contained in:
Oliver 2019-09-23 19:52:44 +10:00 committed by GitHub
commit cc1e580538
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 77 additions and 30 deletions

View File

@ -8,8 +8,11 @@ from __future__ import unicode_literals
from django import forms
from django.utils.translation import ugettext as _
from mptt.fields import TreeNodeChoiceField
from InvenTree.forms import HelperForm
from stock.models import StockLocation
from .models import PurchaseOrder, PurchaseOrderLineItem
@ -35,6 +38,17 @@ class CancelPurchaseOrderForm(HelperForm):
]
class ReceivePurchaseOrderForm(HelperForm):
location = TreeNodeChoiceField(queryset=StockLocation.objects.all(), required=True, help_text=_('Receive parts to this location'))
class Meta:
model = PurchaseOrder
fields = [
'location',
]
class EditPurchaseOrderForm(HelperForm):
""" Form for editing a PurchaseOrder object """

View File

@ -108,14 +108,12 @@ InvenTree | {{ order }}
<th data-sortable='true'>Received</th>
{% endif %}
<th>Note</th>
{% if order.status == OrderStatus.PENDING %}
<th></th>
{% endif %}
</tr>
</thead>
<tbody>
{% for line in order.lines.all %}
<tr>
<tr{% if order.status == OrderStatus.PLACED %} class={% if line.received < line.quantity %}'rowinvalid'{% else %}'rowvalid'{% endif %}{% endif %}>
<td>
{{ forloop.counter }}
</td>
@ -137,18 +135,23 @@ InvenTree | {{ order }}
<td>
{{ line.notes }}
</td>
{% if order.status == OrderStatus.PENDING %}
<td>
<div class='btn-group'>
{% if order.status == OrderStatus.PENDING %}
<button class='btn btn-default btn-glyph' line='{{ line.id }}' id='edit-line-item-{{ line.id }} title='Edit line item' onclick='editPurchaseOrderLineItem()'>
<span url="{% url 'po-line-item-edit' line.id %}" line='{{ line.id }}' class='glyphicon glyphicon-edit'></span>
</button>
<button class='btn btn-default btn-glyph' line='{{ line.id }}' id='remove-line-item-{{ line.id }' title='Remove line item' type='button' onclick='removePurchaseOrderLineItem()'>
<span url="{% url 'po-line-item-delete' line.id %}" line='{{ line.id }}' class='glyphicon glyphicon-remove'></span>
</button>
{% endif %}
{% if order.status == OrderStatus.PLACED and line.received < line.quantity %}
<button class='btn btn-default btn-glyph line-receive' pk='{{ line.pk }}' title='Receive item(s)'>
<span class='glyphicon glyphicon-check'></span>
</button>
{% endif %}
</div>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
@ -187,9 +190,31 @@ $("#cancel-order").click(function() {
});
});
$("#po-lines-table").on('click', ".line-receive", function() {
var button = $(this);
console.log('clicked! ' + button.attr('pk'));
launchModalForm("{% url 'purchase-order-receive' order.id %}", {
reload: true,
data: {
line: button.attr('pk')
}
});
});
$("#receive-order").click(function() {
launchModalForm("{% url 'purchase-order-receive' order.id %}", {
reload: true,
secondary: [
{
field: 'location',
label: 'New Location',
title: 'Create new stock location',
url: "{% url 'stock-location-create' %}",
},
]
});
});

View File

@ -8,23 +8,6 @@ Receive outstanding parts for <b>{{ order }}</b> - <i>{{ order.description }}</i
{% csrf_token %}
{% load crispy_forms_tags %}
<div class='control-group'>
<label class='control-label requiredField'>Location</label>
<div class='controls'>
<select class='select' name='receive_location'>
<option value=''>---------</option>
{% for loc in locations %}
<option value='{{ loc.id }}' {% if destination.id == loc.id %}selected='selected'{% endif %}>{{ loc.pathstring }} - {{ loc.description }}</option>
{% endfor %}
</select>
{% if not destination %}
<span class='help-inline'>Select location to receive parts</span>
{% else %}
<p class='help-block'>Location of received parts</p>
{% endif %}
</div>
</div>
<label class='control-label'>Parts</label>
<p class='help-block'>Select parts to receive against this order.</p>
@ -64,6 +47,8 @@ Receive outstanding parts for <b>{{ order }}</b> - <i>{{ order.description }}</i
</tr>
{% endfor %}
</table>
{% crispy form %}
</form>
{% endblock %}

View File

@ -206,7 +206,7 @@ class PurchaseOrderExport(AjaxView):
return DownloadFile(filedata, filename)
class PurchaseOrderReceive(AjaxView):
class PurchaseOrderReceive(AjaxUpdateView):
""" View for receiving parts which are outstanding against a PurchaseOrder.
Any parts which are outstanding are listed.
@ -214,6 +214,7 @@ class PurchaseOrderReceive(AjaxView):
"""
form_class = order_forms.ReceivePurchaseOrderForm
ajax_form_title = "Receive Parts"
ajax_template_name = "order/receive_parts.html"
@ -225,12 +226,34 @@ class PurchaseOrderReceive(AjaxView):
ctx = {
'order': self.order,
'lines': self.lines,
'locations': StockLocation.objects.all(),
'destination': self.destination,
}
return ctx
def get_lines(self):
"""
Extract particular line items from the request,
or default to *all* pending line items if none are provided
"""
lines = None
if 'line' in self.request.GET:
line_id = self.request.GET.get('line')
try:
lines = PurchaseOrderLineItem.objects.filter(pk=line_id)
except (PurchaseOrderLineItem.DoesNotExist, ValueError):
pass
# TODO - Option to pass multiple lines?
# No lines specified - default selection
if lines is None:
lines = self.order.pending_line_items()
return lines
def get(self, request, *args, **kwargs):
""" Respond to a GET request. Determines which parts are outstanding,
and presents a list of these parts to the user.
@ -239,13 +262,13 @@ class PurchaseOrderReceive(AjaxView):
self.request = request
self.order = get_object_or_404(PurchaseOrder, pk=self.kwargs['pk'])
self.lines = self.order.pending_line_items()
self.lines = self.get_lines()
for line in self.lines:
# Pre-fill the remaining quantity
line.receive_quantity = line.remaining()
return self.renderJsonResponse(request)
return self.renderJsonResponse(request, form=self.get_form())
def post(self, request, *args, **kwargs):
""" Respond to a POST request. Data checking and error handling.
@ -260,8 +283,8 @@ class PurchaseOrderReceive(AjaxView):
self.destination = None
# Extract the destination for received parts
if 'receive_location' in request.POST:
pk = request.POST['receive_location']
if 'location' in request.POST:
pk = request.POST['location']
try:
self.destination = StockLocation.objects.get(id=pk)
except (StockLocation.DoesNotExist, ValueError):
@ -316,7 +339,7 @@ class PurchaseOrderReceive(AjaxView):
'success': 'Items marked as received',
}
return self.renderJsonResponse(request, data=data)
return self.renderJsonResponse(request, data=data, form=self.get_form())
@transaction.atomic
def receive_parts(self):