Below is a code snippet from a sale order template. This snippet generates a table that has the sale order items and a separate area for the line order items. In my case, I am modeling this sale order template after a receipt. I would like to include the total of only the sale order items as a "subtotal" at the base of the sale order items portion of the table. The "total" will appear at the bottom off the extra line portion of the table. Currently, a variable to reference that "subtotal" does not exist. Only the order.total_price
variable to get the overall total including extra line items.
<table class='table table-striped table-condensed'>
<thead>
<tr>
<th>{% trans "Item" %}</th>
<th>{% trans "Reference" %}</th>
<th>{% trans "Quantity" %}</th>
<th>{% trans "Unit Price" %}</th>
<th>{% trans "Total Price" %}</th>
</tr>
</thead>
<body>
{% for line in lines.all %}
<tr>
<td>
<div class='thumb-container'>
<img src='{% part_image line.part height=240 %}' alt='' class='part-thumb'>
<span class='part-text'>
{{ line.part.name }}
</span>
</div>
</td>
<td>{{ line.part.IPN }}</td>
<td>{% decimal line.quantity %}</td>
<td>{% render_currency line.price %}</td>
<td>{% render_currency line.total_line_price %}</td>
</tr>
{% endfor %}
<tr>
<td colspan="3"></td>
<th>{% trans "Subtotal" %}</th>
<td>{% render_currency subtotal_variable currency=order.currency %}</td>
</tr>
After looking through the code on Github I think I have narrowed down the two files that would need to be altered to include this "subtotal" variable. The admin.py
and models.py
in InvenTree/src/backend/InvenTree/order/
. I am trying to build a potential solution to this, but my unfamiliarity with the code and all references is making it challenging.
Here are some of the relevant places I think the code would need altering.
class TotalPriceResourceMixin:
"""Mixin for exporting total price data."""
total_price = Field(attribute='total_price', column_name=_('Total Price'))
def dehydrate_total_price(self, order):
"""Return the total price amount, not the object itself."""
if order.total_price:
return order.total_price.amount
return ''
def save(self, *args, **kwargs):
"""Update the total_price field when saved."""
# Recalculate total_price for this order
self.update_total_price(commit=False)
if hasattr(self, '_SAVING_TOTAL_PRICE') and self._SAVING_TOTAL_PRICE:
# Avoid recursion on save
return super().save(*args, **kwargs)
self._SAVING_TOTAL_PRICE = True
# Save the object as we can not access foreign/m2m fields before saving
self.update_total_price(commit=True)
total_price = InvenTreeModelMoneyField(
null=True,
blank=True,
allow_negative=False,
verbose_name=_('Total Price'),
help_text=_('Total price for this order'),
)
def update_total_price(self, commit=True):
"""Recalculate and save the total_price for this order."""
self.total_price = self.calculate_total_price(target_currency=self.currency)
if commit:
self.save()
def calculate_total_price(self, target_currency=None):
"""Calculates the total price of all order lines, and converts to the specified target currency.
If not specified, the default system currency is used.
If currency conversion fails (e.g. there are no valid conversion rates),
then we simply return zero, rather than attempting some other calculation.
"""
# Set default - see B008
if target_currency is None:
target_currency = currency_code_default()
total = Money(0, target_currency)
# Check if the order has been saved (otherwise we can't calculate the total price)
if self.pk is None:
return total
# order items
for line in self.lines.all():
if not line.price:
continue
try:
total += line.quantity * convert_money(line.price, target_currency)
except MissingRate:
# Record the error, try to press on
_1, _2, _3 = sys.exc_info()
log_error('order.calculate_total_price')
logger.exception("Missing exchange rate for '%s'", target_currency)
# Return None to indicate the calculated price is invalid
return None
# extra items
for line in self.extra_lines.all():
if not line.price:
continue
try:
total += line.quantity * convert_money(line.price, target_currency)
except MissingRate:
# Record the error, try to press on
log_error('order.calculate_total_price')
logger.exception("Missing exchange rate for '%s'", target_currency)
# Return None to indicate the calculated price is invalid
return None
# set decimal-places
total.decimal_places = 4
return total
The other way to achieve this is to open the template editor and open the respective sales order. Then create a <p>
or <span>
and manually calculate and insert the value. I was trying to automate this, but this is an option.
No response
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too