mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge branch 'master' of github.com:inventree/InvenTree into multi_part_forms
This commit is contained in:
commit
005063aad6
@ -74,7 +74,7 @@ def validate_build_order_reference(value):
|
||||
match = re.search(pattern, value)
|
||||
|
||||
if match is None:
|
||||
raise ValidationError(_('Reference must match pattern') + f" '{pattern}'")
|
||||
raise ValidationError(_('Reference must match pattern {pattern}').format(pattern=pattern))
|
||||
|
||||
|
||||
def validate_purchase_order_reference(value):
|
||||
@ -88,7 +88,7 @@ def validate_purchase_order_reference(value):
|
||||
match = re.search(pattern, value)
|
||||
|
||||
if match is None:
|
||||
raise ValidationError(_('Reference must match pattern') + f" '{pattern}'")
|
||||
raise ValidationError(_('Reference must match pattern {pattern}').format(pattern=pattern))
|
||||
|
||||
|
||||
def validate_sales_order_reference(value):
|
||||
@ -102,7 +102,7 @@ def validate_sales_order_reference(value):
|
||||
match = re.search(pattern, value)
|
||||
|
||||
if match is None:
|
||||
raise ValidationError(_('Reference must match pattern') + f" '{pattern}'")
|
||||
raise ValidationError(_('Reference must match pattern {pattern}').format(pattern=pattern))
|
||||
|
||||
|
||||
def validate_tree_name(value):
|
||||
|
@ -158,6 +158,8 @@ $('#view-calendar').click(function() {
|
||||
|
||||
$("#build-order-calendar").show();
|
||||
$("#view-list").show();
|
||||
|
||||
calendar.render();
|
||||
});
|
||||
|
||||
$("#view-list").click(function() {
|
||||
|
@ -202,7 +202,7 @@ class CompanyImageDownloadFromURL(AjaxUpdateView):
|
||||
|
||||
# Check for valid response code
|
||||
if not response.status_code == 200:
|
||||
form.add_error('url', f"{_('Invalid response')}: {response.status_code}")
|
||||
form.add_error('url', _('Invalid response: {code}').format(code=response.status_code))
|
||||
return
|
||||
|
||||
response.raw.decode_content = True
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -223,7 +223,7 @@ class PurchaseOrder(Order):
|
||||
return reverse('po-detail', kwargs={'pk': self.id})
|
||||
|
||||
@transaction.atomic
|
||||
def add_line_item(self, supplier_part, quantity, group=True, reference=''):
|
||||
def add_line_item(self, supplier_part, quantity, group=True, reference='', purchase_price=None):
|
||||
""" Add a new line item to this purchase order.
|
||||
This function will check that:
|
||||
|
||||
@ -254,7 +254,12 @@ class PurchaseOrder(Order):
|
||||
if matches.count() > 0:
|
||||
line = matches.first()
|
||||
|
||||
line.quantity += quantity
|
||||
# update quantity and price
|
||||
quantity_new = line.quantity + quantity
|
||||
line.quantity = quantity_new
|
||||
supplier_price = supplier_part.get_price(quantity_new)
|
||||
if line.purchase_price and supplier_price:
|
||||
line.purchase_price = supplier_price / quantity_new
|
||||
line.save()
|
||||
|
||||
return
|
||||
@ -263,7 +268,9 @@ class PurchaseOrder(Order):
|
||||
order=self,
|
||||
part=supplier_part,
|
||||
quantity=quantity,
|
||||
reference=reference)
|
||||
reference=reference,
|
||||
purchase_price=purchase_price,
|
||||
)
|
||||
|
||||
line.save()
|
||||
|
||||
@ -329,7 +336,7 @@ class PurchaseOrder(Order):
|
||||
return self.pending_line_items().count() == 0
|
||||
|
||||
@transaction.atomic
|
||||
def receive_line_item(self, line, location, quantity, user, status=StockStatus.OK):
|
||||
def receive_line_item(self, line, location, quantity, user, status=StockStatus.OK, purchase_price=None):
|
||||
""" Receive a line item (or partial line item) against this PO
|
||||
"""
|
||||
|
||||
@ -353,13 +360,14 @@ class PurchaseOrder(Order):
|
||||
location=location,
|
||||
quantity=quantity,
|
||||
purchase_order=self,
|
||||
status=status
|
||||
status=status,
|
||||
purchase_price=purchase_price,
|
||||
)
|
||||
|
||||
stock.save()
|
||||
|
||||
text = _("Received items")
|
||||
note = f"{_('Received')} {quantity} {_('items against order')} {str(self)}"
|
||||
note = _('Received {n} items against order {name}').format(n=quantity, name=str(self))
|
||||
|
||||
# Add a new transaction note to the newly created stock item
|
||||
stock.addTransactionNote(text, user, note)
|
||||
|
@ -146,6 +146,8 @@ $('#view-calendar').click(function() {
|
||||
|
||||
$("#purchase-order-calendar").show();
|
||||
$("#view-list").show();
|
||||
|
||||
calendar.render();
|
||||
});
|
||||
|
||||
$("#view-list").click(function() {
|
||||
|
@ -141,9 +141,11 @@ $('#view-calendar').click(function() {
|
||||
$(".columns-right").hide();
|
||||
$(".search").hide();
|
||||
$('#filter-list-salesorder').hide();
|
||||
|
||||
|
||||
$("#sales-order-calendar").show();
|
||||
$("#view-list").show();
|
||||
|
||||
calendar.render();
|
||||
});
|
||||
|
||||
$("#view-list").click(function() {
|
||||
|
@ -1183,6 +1183,7 @@ class PurchaseOrderReceive(AjaxUpdateView):
|
||||
line.receive_quantity,
|
||||
self.request.user,
|
||||
status=line.status_code,
|
||||
purchase_price=line.purchase_price,
|
||||
)
|
||||
|
||||
|
||||
@ -1403,6 +1404,14 @@ class OrderParts(AjaxView):
|
||||
part.order_supplier = supplier_part.id if supplier_part else None
|
||||
part.order_quantity = quantity
|
||||
|
||||
# set supplier-price
|
||||
if supplier_part:
|
||||
supplier_price = supplier_part.get_price(quantity)
|
||||
if supplier_price:
|
||||
part.purchase_price = supplier_price / quantity
|
||||
if not hasattr(part, 'purchase_price'):
|
||||
part.purchase_price = None
|
||||
|
||||
self.parts.append(part)
|
||||
|
||||
if supplier_part is None:
|
||||
@ -1502,7 +1511,10 @@ class OrderParts(AjaxView):
|
||||
sp=item.order_supplier))
|
||||
continue
|
||||
|
||||
order.add_line_item(supplier_part, quantity)
|
||||
# get purchase price
|
||||
purchase_price = item.purchase_price
|
||||
|
||||
order.add_line_item(supplier_part, quantity, purchase_price=purchase_price)
|
||||
|
||||
|
||||
class POLineItemCreate(AjaxCreateView):
|
||||
@ -1802,7 +1814,7 @@ class SalesOrderAssignSerials(AjaxView, FormMixin):
|
||||
except StockItem.DoesNotExist:
|
||||
self.form.add_error(
|
||||
'serials',
|
||||
_('No matching item for serial') + f" '{serial}'"
|
||||
_('No matching item for serial {serial}').format(serial=serial)
|
||||
)
|
||||
continue
|
||||
|
||||
@ -1812,7 +1824,7 @@ class SalesOrderAssignSerials(AjaxView, FormMixin):
|
||||
if not stock_item.in_stock:
|
||||
self.form.add_error(
|
||||
'serials',
|
||||
f"'{serial}' " + _("is not in stock")
|
||||
_('{serial} is not in stock').format(serial=serial)
|
||||
)
|
||||
continue
|
||||
|
||||
@ -1820,7 +1832,7 @@ class SalesOrderAssignSerials(AjaxView, FormMixin):
|
||||
if stock_item.is_allocated():
|
||||
self.form.add_error(
|
||||
'serials',
|
||||
f"'{serial}' " + _("already allocated to an order")
|
||||
_('{serial} already allocated to an order').format(serial=serial)
|
||||
)
|
||||
continue
|
||||
|
||||
|
@ -91,7 +91,7 @@
|
||||
{% if part.salable and roles.sales_order.view %}
|
||||
<li class='list-group-item {% if tab == "sales-prices" %}active{% endif %}' title='{% trans "Sales Price Information" %}'>
|
||||
<a href='{% url "part-sale-prices" part.id %}'>
|
||||
<span class='menu-tab-icon fas fa-dollar-sign'></span>
|
||||
<span class='menu-tab-icon fas fa-dollar-sign' style='width: 20px;'></span>
|
||||
{% trans "Sale Price" %}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -2,7 +2,7 @@
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block menubar %}}
|
||||
{% block menubar %}
|
||||
{% include 'part/navbar.html' with tab='sales-prices' %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -884,7 +884,7 @@ class PartImageDownloadFromURL(AjaxUpdateView):
|
||||
|
||||
# Check for valid response code
|
||||
if not response.status_code == 200:
|
||||
form.add_error('url', f"{_('Invalid response')}: {response.status_code}")
|
||||
form.add_error('url', _('Invalid response: {code}').format(code=response.status_code))
|
||||
return
|
||||
|
||||
response.raw.decode_content = True
|
||||
|
@ -198,7 +198,7 @@ class StockItem(MPTTModel):
|
||||
|
||||
if add_note:
|
||||
|
||||
note = f"{_('Created new stock item for')} {str(self.part)}"
|
||||
note = _('Created new stock item for {part}').format(part=str(self.part))
|
||||
|
||||
# This StockItem is being saved for the first time
|
||||
self.addTransactionNote(
|
||||
@ -613,7 +613,7 @@ class StockItem(MPTTModel):
|
||||
item.addTransactionNote(
|
||||
_("Assigned to Customer"),
|
||||
user,
|
||||
notes=_("Manually assigned to customer") + " " + customer.name,
|
||||
notes=_("Manually assigned to customer {name}").format(name=customer.name),
|
||||
system=True
|
||||
)
|
||||
|
||||
@ -626,9 +626,9 @@ class StockItem(MPTTModel):
|
||||
"""
|
||||
|
||||
self.addTransactionNote(
|
||||
_("Returned from customer") + f" {self.customer.name}",
|
||||
_("Returned from customer {name}").format(name=self.customer.name),
|
||||
user,
|
||||
notes=_("Returned to location") + f" {location.name}",
|
||||
notes=_("Returned to location {loc}").format(loc=location.name),
|
||||
system=True
|
||||
)
|
||||
|
||||
@ -789,7 +789,7 @@ class StockItem(MPTTModel):
|
||||
|
||||
# Add a transaction note to the other item
|
||||
stock_item.addTransactionNote(
|
||||
_('Installed into stock item') + ' ' + str(self.pk),
|
||||
_('Installed into stock item {pk}').format(str(self.pk)),
|
||||
user,
|
||||
notes=notes,
|
||||
url=self.get_absolute_url()
|
||||
@ -797,7 +797,7 @@ class StockItem(MPTTModel):
|
||||
|
||||
# Add a transaction note to this item
|
||||
self.addTransactionNote(
|
||||
_('Installed stock item') + ' ' + str(stock_item.pk),
|
||||
_('Installed stock item {pk}').format(str(stock_item.pk)),
|
||||
user, notes=notes,
|
||||
url=stock_item.get_absolute_url()
|
||||
)
|
||||
@ -821,7 +821,7 @@ class StockItem(MPTTModel):
|
||||
|
||||
# Add a transaction note to the parent item
|
||||
self.belongs_to.addTransactionNote(
|
||||
_("Uninstalled stock item") + ' ' + str(self.pk),
|
||||
_("Uninstalled stock item {pk}").format(pk=str(self.pk)),
|
||||
user,
|
||||
notes=notes,
|
||||
url=self.get_absolute_url(),
|
||||
@ -840,7 +840,7 @@ class StockItem(MPTTModel):
|
||||
|
||||
# Add a transaction note!
|
||||
self.addTransactionNote(
|
||||
_('Uninstalled into location') + ' ' + str(location),
|
||||
_('Uninstalled into location {loc}').formaT(loc=str(location)),
|
||||
user,
|
||||
notes=notes,
|
||||
url=url
|
||||
@ -966,7 +966,7 @@ class StockItem(MPTTModel):
|
||||
|
||||
if len(existing) > 0:
|
||||
exists = ','.join([str(x) for x in existing])
|
||||
raise ValidationError({"serial_numbers": _("Serial numbers already exist") + ': ' + exists})
|
||||
raise ValidationError({"serial_numbers": _("Serial numbers already exist: {exists}").format(exists=exists)})
|
||||
|
||||
# Create a new stock item for each unique serial number
|
||||
for serial in serials:
|
||||
@ -1074,7 +1074,7 @@ class StockItem(MPTTModel):
|
||||
new_stock.addTransactionNote(
|
||||
_("Split from existing stock"),
|
||||
user,
|
||||
f"{_('Split')} {helpers.normalize(quantity)} {_('items')}"
|
||||
_('Split {n} items').format(n=helpers.normalize(quantity))
|
||||
)
|
||||
|
||||
# Remove the specified quantity from THIS stock item
|
||||
@ -1131,10 +1131,10 @@ class StockItem(MPTTModel):
|
||||
|
||||
return True
|
||||
|
||||
msg = f"{_('Moved to')} {str(location)}"
|
||||
|
||||
if self.location:
|
||||
msg += f" ({_('from')} {str(self.location)})"
|
||||
msg = _("Moved to {loc_new} (from {loc_old})").format(loc_new=str(location), loc_old=str(self.location))
|
||||
else:
|
||||
msg = _('Moved to {loc_new}').format(loc_new=str(location))
|
||||
|
||||
self.location = location
|
||||
|
||||
@ -1202,9 +1202,7 @@ class StockItem(MPTTModel):
|
||||
|
||||
if self.updateQuantity(count):
|
||||
|
||||
n = helpers.normalize(count)
|
||||
|
||||
text = f"{_('Counted')} {n} {_('items')}"
|
||||
text = _('Counted {n} items').format(n=helpers.normalize(count))
|
||||
|
||||
self.addTransactionNote(
|
||||
text,
|
||||
@ -1236,9 +1234,8 @@ class StockItem(MPTTModel):
|
||||
return False
|
||||
|
||||
if self.updateQuantity(self.quantity + quantity):
|
||||
|
||||
n = helpers.normalize(quantity)
|
||||
text = f"{_('Added')} {n} {_('items')}"
|
||||
|
||||
text = _('Added {n} items').format(n=helpers.normalize(quantity))
|
||||
|
||||
self.addTransactionNote(
|
||||
text,
|
||||
@ -1268,8 +1265,7 @@ class StockItem(MPTTModel):
|
||||
|
||||
if self.updateQuantity(self.quantity - quantity):
|
||||
|
||||
q = helpers.normalize(quantity)
|
||||
text = f"{_('Removed')} {q} {_('items')}"
|
||||
text = _('Removed {n1} items').format(n1=helpers.normalize(quantity))
|
||||
|
||||
self.addTransactionNote(text,
|
||||
user,
|
||||
|
4
tasks.py
4
tasks.py
@ -65,7 +65,7 @@ def manage(c, cmd, pty=False):
|
||||
cmd - django command to run
|
||||
"""
|
||||
|
||||
c.run('cd {path} && python3 manage.py {cmd}'.format(
|
||||
c.run('cd "{path}" && python3 manage.py {cmd}'.format(
|
||||
path=managePyDir(),
|
||||
cmd=cmd
|
||||
), pty=pty)
|
||||
@ -185,7 +185,7 @@ def translate(c):
|
||||
"""
|
||||
|
||||
# Translate applicable .py / .html / .js files
|
||||
manage(c, "makemessages --all -e py,html,js")
|
||||
manage(c, "makemessages --all -e py,html,js --no-wrap")
|
||||
manage(c, "compilemessages")
|
||||
|
||||
path = os.path.join('InvenTree', 'script', 'translation_stats.py')
|
||||
|
Loading…
Reference in New Issue
Block a user