Sales with “subtotal” lines affect performance

When we use lines of type “subtotal” in our sales, we experience a significant performance hit when loading the list of sales.

As I understand it, when the list of sales is loaded, the function “Sale.get_amount” is called. This function contains the loop:

untaxed_amount[] = sum(
    (line.amount for line in sale.lines
        if line.type == 'line'), Decimal(0))

And even if only lines of type “line” are to be taken into account here, you can see that in the getter function for “amount” (“SaleLine.get_amount”) the part in this function for “subtotals” is also called again and again. And this is the part that takes up to 8 seconds on our system, even with just a few (four) sales each with about five “subtotal” lines and about 150 “normal” lines.

I don’t understand why this is so - I suspect it has something to do with the getter for the “amount” field, because if I call “SaleLine.get_amount” directly (as a test) using this code in “Sale.get_amount”:

untaxed_amount[] = sum(
    (line.get_amount('') for line in sale.lines
        if line.type == 'line'), Decimal(0))

the performance problems are gone.

Unfortunately I can’t get any further here - maybe someone can help me?


Calling the getter directly is not that good because it prevents the ORM to pre-compute. The pre-computation is also the problem in this case because the filter on type of line is happening after the instanciation.
One we would be to reinstantiate the lines after the filtering but then again we will loose some pre-computation.
Finally I think the best option would be to have a OneMany for lines with a filter on the type line. As this is this loop only on type line is frequent in the code, it may deserve its own field.

The same would apply to purchase and invoice.