I need to perform a range of simple calculations on an Invoice model object, which has a number of Order children associated with it that hold the order quantity and order value etc. This is all managed through the admin form for Invoice (with order as inlines)
The code I’m working with now performs these calcs like this:
Invoice (models.py)
def save():
#get the total of all associated orders
for order in self.invoice_orders.all():
self.invoice_net_total += order.order_value
super(Invoice, self).save()
Which causes a few problems when changing a child order quantity and then saving the form – I get the previous total instead of the new total, only when I save again does the total correct itself. Perhaps due to the way Django saves parent and child objects?
Other option I toyed with was moving this calculation to the child order object (prepare for horrible code):
Order (models.py)
def save():
if not self.id:
self.invoice.invoice_net_total += self.order_value
elif self.id:
#grab old instance
old = Order.objects.get(pk=self.id)
#remove that old total
self.invoice.invoice_net_total -= old.order_value
self.invoice.save()
#add new total
self.invoice.invoice_net_value += self.order_value
self.invoice.save()
Though that’s not very effective either.
Wondering if anyone could guide me to a straightforward way of ensuring these calcs perform as they should? Thought of signals (relatively new to me) but wondered if that was overkill. I’m probably overthinking this!
Thank you
On a different thought, consider not even explicitly saving the invoice total. Instead, it may be dynamically recalculated each time you query for an invoice.
I think this is better modeling as it avoid redundant and possibly inconsistent data. SQL and Django are smart enough to compute you invoice total without much overhead each time you need it. Esp. you don’t do the summation in you program if you use an aggregation function