mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Form for shipping a SalesOrder
- Returns "False" for now
This commit is contained in:
parent
b45fec221c
commit
77471cb89c
@ -125,7 +125,7 @@ class BuildAutoAllocate(AjaxUpdateView):
|
||||
|
||||
if confirm is False:
|
||||
form.errors['confirm'] = [_('Confirm stock allocation')]
|
||||
form.non_field_errors = _('Check the confirmation box at the bottom of the list')
|
||||
form.non_field_errors = [_('Check the confirmation box at the bottom of the list')]
|
||||
else:
|
||||
build.autoAllocate()
|
||||
valid = True
|
||||
@ -159,7 +159,7 @@ class BuildUnallocate(AjaxUpdateView):
|
||||
|
||||
if confirm is False:
|
||||
form.errors['confirm'] = [_('Confirm unallocation of build stock')]
|
||||
form.non_field_errors = _('Check the confirmation box')
|
||||
form.non_field_errors = [_('Check the confirmation box')]
|
||||
else:
|
||||
build.unallocateStock()
|
||||
valid = True
|
||||
|
@ -63,6 +63,17 @@ class CancelSalesOrderForm(HelperForm):
|
||||
]
|
||||
|
||||
|
||||
class ShipSalesOrderForm(HelperForm):
|
||||
|
||||
confirm = forms.BooleanField(required=False, help_text=_('Ship order'))
|
||||
|
||||
class Meta:
|
||||
model = SalesOrder
|
||||
fields = [
|
||||
'confirm',
|
||||
]
|
||||
|
||||
|
||||
class ReceivePurchaseOrderForm(HelperForm):
|
||||
|
||||
location = TreeNodeChoiceField(queryset=StockLocation.objects.all(), required=True, help_text=_('Receive parts to this location'))
|
||||
|
@ -302,10 +302,21 @@ class SalesOrder(Order):
|
||||
|
||||
return True
|
||||
|
||||
def is_over_allocated(self):
|
||||
""" Return true if any lines in the order are over-allocated """
|
||||
|
||||
for line in self.lines.all():
|
||||
if line.is_over_allocated():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@transaction.atomic
|
||||
def ship_order(self, user):
|
||||
""" Mark this order as 'shipped' """
|
||||
|
||||
return False
|
||||
|
||||
if not self.status == SalesOrderStatus.PENDING:
|
||||
return False
|
||||
|
||||
@ -447,6 +458,10 @@ class SalesOrderLineItem(OrderLineItem):
|
||||
return query['allocated']
|
||||
|
||||
def is_fully_allocated(self):
|
||||
print("Line:", self.pk)
|
||||
print("Allocated:", self.allocated_quantity())
|
||||
print("Quantity:", self.quantity)
|
||||
|
||||
return self.allocated_quantity() >= self.quantity
|
||||
|
||||
def is_over_allocated(self):
|
||||
|
@ -124,4 +124,10 @@ $("#cancel-order").click(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$("#ship-order").click(function() {
|
||||
launchModalForm("{% url 'so-ship' order.id %}", {
|
||||
reload: true,
|
||||
});
|
||||
});
|
||||
|
||||
{% endblock %}
|
@ -4,6 +4,9 @@
|
||||
|
||||
{% block pre_form_content %}
|
||||
|
||||
<div class='alert alert-block alert-warning'>
|
||||
<h4>{% trans "Warning" %}</h4>
|
||||
{% trans "Cancelling this order means that the order will no longer be editable." %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -23,9 +23,13 @@
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
||||
|
||||
function reloadTable() {
|
||||
$("#so-lines-table").bootstrapTable("refresh");
|
||||
}
|
||||
|
||||
$("#new-so-line").click(function() {
|
||||
launchModalForm("{% url 'so-line-item-create' %}", {
|
||||
reload: true,
|
||||
success: reloadTable,
|
||||
data: {
|
||||
order: {{ order.id }},
|
||||
},
|
||||
@ -200,10 +204,6 @@ $("#so-lines-table").inventreeTable({
|
||||
],
|
||||
});
|
||||
|
||||
function reloadTable() {
|
||||
$("#so-lines-table").bootstrapTable("refresh");
|
||||
}
|
||||
|
||||
function setupCallbacks(table) {
|
||||
|
||||
var table = $("#so-lines-table");
|
||||
|
28
InvenTree/order/templates/order/sales_order_ship.html
Normal file
28
InvenTree/order/templates/order/sales_order_ship.html
Normal file
@ -0,0 +1,28 @@
|
||||
{% extends "modal_form.html" %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block pre_form_content %}
|
||||
|
||||
{% if not order.is_fully_allocated %}
|
||||
<div class='alert alert-block alert-danger'>
|
||||
<h4>{% trans "Warning" %}</h4>
|
||||
{% trans "This order has not been fully allocated. If the order is marked as shipped, it can no longer be adjusted." %}
|
||||
<br>
|
||||
{% trans "Ensure that the order allocation is correct before shipping the order." %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if order.is_over_allocated %}
|
||||
<div class='alert alert-block alert-warning'>
|
||||
{% trans "Some line items in this order have been over-allocated" %}
|
||||
<br>
|
||||
{% trans "Ensure that this is correct before shipping the order." %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class='alert alert-block alert-info'>
|
||||
{% trans "Shipping this order means that the order will no longer be editable." %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
14
InvenTree/order/templates/order/so_allocation_delete.html
Normal file
14
InvenTree/order/templates/order/so_allocation_delete.html
Normal file
@ -0,0 +1,14 @@
|
||||
{% extends "modal_delete_form.html" %}
|
||||
{% load i18n %}
|
||||
{% load inventree_extras %}
|
||||
|
||||
{% block pre_form_content %}
|
||||
<div class='alert alert-block alert-warning'>
|
||||
{% trans "This action will unallocate the following stock from the Sales Order" %}:
|
||||
<br>
|
||||
<b>
|
||||
{% decimal allocation.get_allocated %} x {{ allocation.line.part.full_name }}
|
||||
{% if allocation.item.location %} ({{ allocation.get_location }}){% endif %}
|
||||
</b>
|
||||
</div>
|
||||
{% endblock %}
|
@ -1,5 +1,6 @@
|
||||
{% extends "modal_delete_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block pre_form_content %}
|
||||
Are you sure you wish to delete this line item?
|
||||
{% trans "Are you sure you wish to delete this line item?" %}
|
||||
{% endblock %}
|
@ -56,6 +56,7 @@ sales_order_detail_urls = [
|
||||
|
||||
url(r'^edit/', views.SalesOrderEdit.as_view(), name='so-edit'),
|
||||
url(r'^cancel/', views.SalesOrderCancel.as_view(), name='so-cancel'),
|
||||
url(r'^ship/', views.SalesOrderShip.as_view(), name='so-ship'),
|
||||
|
||||
url(r'^attachments/', views.SalesOrderDetail.as_view(template_name='order/so_attachments.html'), name='so-attachments'),
|
||||
url(r'^notes/', views.SalesOrderNotes.as_view(), name='so-notes'),
|
||||
|
@ -416,13 +416,16 @@ class SalesOrderCancel(AjaxUpdateView):
|
||||
else:
|
||||
valid = True
|
||||
|
||||
|
||||
if valid:
|
||||
if not order.cancel_order():
|
||||
form.non_field_errors = [_('Could not cancel order')]
|
||||
valid = False
|
||||
|
||||
data = {
|
||||
'form_valid': valid,
|
||||
}
|
||||
|
||||
if valid:
|
||||
order.cancel_order()
|
||||
|
||||
return self.renderJsonResponse(request, form, data)
|
||||
|
||||
|
||||
@ -495,6 +498,47 @@ class PurchaseOrderComplete(AjaxUpdateView):
|
||||
return self.renderJsonResponse(request, form, data)
|
||||
|
||||
|
||||
|
||||
class SalesOrderShip(AjaxUpdateView):
|
||||
""" View for 'shipping' a SalesOrder """
|
||||
form_class = order_forms.ShipSalesOrderForm
|
||||
model = SalesOrder
|
||||
context_object_name = 'order'
|
||||
ajax_template_name = 'order/sales_order_ship.html'
|
||||
ajax_form_title = _('Ship Order')
|
||||
|
||||
def context_data(self):
|
||||
ctx = super().get_context_data()
|
||||
ctx['order'] = self.get_object()
|
||||
|
||||
return ctx
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
|
||||
order = self.get_object()
|
||||
form = self.get_form()
|
||||
|
||||
confirm = str2bool(request.POST.get('confirm', False))
|
||||
|
||||
valid = False
|
||||
|
||||
if not confirm:
|
||||
form.errors['confirm'] = [_('Confirm order shipment')]
|
||||
else:
|
||||
valid = True
|
||||
|
||||
if valid:
|
||||
if not order.ship_order(request.user):
|
||||
form.non_field_errors = [_('Could not ship order')]
|
||||
valid = False
|
||||
|
||||
data = {
|
||||
'form_valid': valid,
|
||||
}
|
||||
|
||||
return self.renderJsonResponse(request, form, data)
|
||||
|
||||
|
||||
class PurchaseOrderExport(AjaxView):
|
||||
""" File download for a purchase order
|
||||
|
||||
@ -1111,6 +1155,18 @@ class SOLineItemCreate(AjaxCreateView):
|
||||
form_class = order_forms.EditSalesOrderLineItemForm
|
||||
ajax_form_title = _('Add Line Item')
|
||||
|
||||
def get_form(self, *args, **kwargs):
|
||||
|
||||
form = super().get_form(*args, **kwargs)
|
||||
|
||||
# If the order is specified, hide the widget
|
||||
order_id = form['order'].value()
|
||||
|
||||
if SalesOrder.objects.filter(id=order_id).exists():
|
||||
form.fields['order'].widget = HiddenInput()
|
||||
|
||||
return form
|
||||
|
||||
def get_initial(self):
|
||||
"""
|
||||
Extract initial data for this line item:
|
||||
@ -1293,3 +1349,5 @@ class SalesOrderAllocationDelete(AjaxDeleteView):
|
||||
|
||||
model = SalesOrderAllocation
|
||||
ajax_form_title = _("Remove allocation")
|
||||
context_object_name = 'allocation'
|
||||
ajax_template_name = "order/so_allocation_delete.html"
|
||||
|
@ -731,7 +731,7 @@ class StockItemSerialize(AjaxUpdateView):
|
||||
if k in ['quantity', 'destination', 'serial_numbers']:
|
||||
form.errors[k] = messages[k]
|
||||
else:
|
||||
form.non_field_errors = messages[k]
|
||||
form.non_field_errors = [messages[k]]
|
||||
|
||||
valid = False
|
||||
|
||||
|
@ -13,7 +13,11 @@
|
||||
{% if form.non_field_errors %}
|
||||
<div class='alert alert-danger alert-block' role='alert'>
|
||||
<b>Error Submitting Form:</b>
|
||||
{{ form.non_field_errors }}
|
||||
<ul>
|
||||
{% for error in form.non_field_errors %}
|
||||
{{ error }}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
Loading…
Reference in New Issue
Block a user