mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
More stuff
This commit is contained in:
parent
6ab03bd05a
commit
fd42149f67
@ -42,6 +42,10 @@
|
||||
opacity: 60%;
|
||||
}
|
||||
|
||||
.progress-bar-exceed {
|
||||
background: #eeaa33;
|
||||
}
|
||||
|
||||
.progress-value {
|
||||
width: 100%;
|
||||
color: #333;
|
||||
|
@ -113,11 +113,17 @@ function makeProgressBar(value, maximum, opts) {
|
||||
percent = 100;
|
||||
}
|
||||
|
||||
var extraclass = '';
|
||||
|
||||
if (value > maximum) {
|
||||
extraclass='progress-bar-exceed';
|
||||
}
|
||||
|
||||
var id = opts.id || 'progress-bar';
|
||||
|
||||
return `
|
||||
<div id='${id}' class='progress'>
|
||||
<div class='progress-bar' role='progressbar' aria-valuenow='${percent}' aria-valuemin='0' aria-valuemax='100' style='width:${percent}%'></div>
|
||||
<div class='progress-bar ${extraclass}' role='progressbar' aria-valuenow='${percent}' aria-valuemin='0' aria-valuemax='100' style='width:${percent}%'></div>
|
||||
<div class='progress-value'>${value} / ${maximum}</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -24,7 +24,7 @@ from stock import models as stock_models
|
||||
from company.models import Company, SupplierPart
|
||||
|
||||
from InvenTree.fields import RoundingDecimalField
|
||||
from InvenTree.helpers import decimal2string
|
||||
from InvenTree.helpers import decimal2string, normalize
|
||||
from InvenTree.status_codes import OrderStatus
|
||||
from InvenTree.models import InvenTreeAttachment
|
||||
|
||||
@ -277,6 +277,15 @@ class SalesOrder(Order):
|
||||
|
||||
customer_reference = models.CharField(max_length=64, blank=True, help_text=_("Customer order reference code"))
|
||||
|
||||
def is_fully_allocated(self):
|
||||
""" Return True if all line items are fully allocated """
|
||||
|
||||
for line in self.lines.all():
|
||||
if not line.is_fully_allocated():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class PurchaseOrderAttachment(InvenTreeAttachment):
|
||||
"""
|
||||
@ -385,6 +394,12 @@ class SalesOrderLineItem(OrderLineItem):
|
||||
|
||||
return query['allocated']
|
||||
|
||||
def is_fully_allocated(self):
|
||||
return self.allocated_quantity() >= self.quantity
|
||||
|
||||
def is_over_allocated(self):
|
||||
return self.allocated_quantity() > self.quantity
|
||||
|
||||
|
||||
class SalesOrderAllocation(models.Model):
|
||||
"""
|
||||
@ -457,7 +472,7 @@ class SalesOrderAllocation(models.Model):
|
||||
if self.item.serial and self.quantity == 1:
|
||||
return "# {sn}".format(sn=self.item.serial)
|
||||
else:
|
||||
return self.quantity
|
||||
return normalize(self.quantity)
|
||||
|
||||
def get_location(self):
|
||||
return self.item.location.id if self.item.location else None
|
||||
|
@ -9,6 +9,14 @@
|
||||
InvenTree | {% trans "Sales Order" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block pre_content %}
|
||||
{% if not order.is_fully_allocated %}
|
||||
<div class='alert alert-block alert-danger'>
|
||||
{% trans "This SalesOrder has not been fully allocated" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block thumbnail %}
|
||||
<img class='part-thumb'
|
||||
{% if order.customer.image %}
|
||||
|
@ -190,7 +190,7 @@ $("#so-lines-table").on('load-success.bs.table', function() {
|
||||
var pk = $(this).attr('pk');
|
||||
|
||||
launchModalForm(`/order/sales-order/allocation/new/`, {
|
||||
reload: table,
|
||||
success: reloadTable,
|
||||
data: {
|
||||
line: pk,
|
||||
},
|
||||
|
@ -95,6 +95,9 @@ sales_order_urls = [
|
||||
# URLs for sales order allocations
|
||||
url(r'^allocation/', include([
|
||||
url(r'^new/', views.SalesOrderAllocationCreate.as_view(), name='so-allocation-create'),
|
||||
url(r'(?P<pk>\d+)/', include([
|
||||
url(r'^edit/', views.SalesOrderAllocationEdit.as_view(), name='so-allocation-edit'),
|
||||
])),
|
||||
])),
|
||||
|
||||
url(r'^attachments/', include(sales_order_attachment_urls)),
|
||||
|
@ -1173,11 +1173,33 @@ class SalesOrderAllocationCreate(AjaxCreateView):
|
||||
def get_initial(self):
|
||||
initials = super().get_initial().copy()
|
||||
|
||||
line = self.request.GET.get('line', None)
|
||||
line_id = self.request.GET.get('line', None)
|
||||
|
||||
if line is not None:
|
||||
initials['line'] = SalesOrderLineItem.objects.get(pk=line)
|
||||
if line_id is not None:
|
||||
line = SalesOrderLineItem.objects.get(pk=line_id)
|
||||
|
||||
initials['line'] = line
|
||||
|
||||
# Search for matching stock items, pre-fill if there is only one
|
||||
items = StockItem.objects.filter(part=line.part)
|
||||
|
||||
quantity = line.quantity - line.allocated_quantity()
|
||||
|
||||
if quantity < 0:
|
||||
quantity = 0
|
||||
|
||||
if items.count() == 1:
|
||||
item = items.first()
|
||||
initials['item'] = item
|
||||
|
||||
# Reduce the quantity IF there is not enough stock
|
||||
qmax = item.quantity - item.allocation_count()
|
||||
|
||||
if qmax < quantity:
|
||||
quantity = qmax
|
||||
|
||||
initials['quantity'] = quantity
|
||||
|
||||
return initials
|
||||
|
||||
def get_form(self):
|
||||
@ -1209,3 +1231,18 @@ class SalesOrderAllocationCreate(AjaxCreateView):
|
||||
pass
|
||||
|
||||
return form
|
||||
|
||||
|
||||
class SalesOrderAllocationEdit(AjaxUpdateView):
|
||||
|
||||
model = SalesOrderAllocation
|
||||
ajax_form_title = _('Edit Allocation Quantity')
|
||||
|
||||
def get_form(self):
|
||||
form = super().get_form()
|
||||
|
||||
# Prevent the user from editing particular fields
|
||||
form.fields.pop('item')
|
||||
form.fields.pop('line')
|
||||
|
||||
return form
|
||||
|
Loading…
Reference in New Issue
Block a user