[FIX] account: compute total invoice in batch
The computation of the total_invoiced field did not work in batch mode. When displaying a company in a form view (field invoice_total comptued), the children of this company are present in the cache and the value of the field invoice_total will be prefetched for these children as well (at least in 9.0). Most of the time this is redudant information and the same value is computed for each child while most of the invoices are on the parent. Batching the computation per partner allows to make one global query for all partners. Add test to make sure the total increase correctly after a test invoice confirmation.
This commit is contained in:
@@ -290,31 +290,37 @@ class ResPartner(models.Model):
|
||||
return True
|
||||
|
||||
user_currency_id = self.env.user.company_id.currency_id.id
|
||||
all_partners_and_children = {}
|
||||
all_partner_ids = []
|
||||
for partner in self:
|
||||
all_partner_ids = self.search([('id', 'child_of', partner.id)]).ids
|
||||
|
||||
# searching account.invoice.report via the orm is comparatively expensive
|
||||
# (generates queries "id in []" forcing to build the full table).
|
||||
# In simple cases where all invoices are in the same currency than the user's company
|
||||
# access directly these elements
|
||||
|
||||
# generate where clause to include multicompany rules
|
||||
where_query = account_invoice_report._where_calc([
|
||||
('partner_id', 'in', all_partner_ids), ('state', 'not in', ['draft', 'cancel']), ('company_id', '=', self.env.user.company_id.id),
|
||||
('type', 'in', ('out_invoice', 'out_refund'))
|
||||
])
|
||||
account_invoice_report._apply_ir_rules(where_query, 'read')
|
||||
from_clause, where_clause, where_clause_params = where_query.get_sql()
|
||||
|
||||
query = """
|
||||
SELECT SUM(price_total) as total
|
||||
FROM account_invoice_report account_invoice_report
|
||||
WHERE %s
|
||||
""" % where_clause
|
||||
|
||||
# price_total is in the company currency
|
||||
self.env.cr.execute(query, where_clause_params)
|
||||
partner.total_invoiced = self.env.cr.fetchone()[0]
|
||||
all_partners_and_children[partner] = self.search([('id', 'child_of', partner.id)]).ids
|
||||
all_partner_ids += all_partners_and_children[partner]
|
||||
|
||||
# searching account.invoice.report via the orm is comparatively expensive
|
||||
# (generates queries "id in []" forcing to build the full table).
|
||||
# In simple cases where all invoices are in the same currency than the user's company
|
||||
# access directly these elements
|
||||
|
||||
# generate where clause to include multicompany rules
|
||||
where_query = account_invoice_report._where_calc([
|
||||
('partner_id', 'in', all_partner_ids), ('state', 'not in', ['draft', 'cancel']), ('company_id', '=', self.env.user.company_id.id),
|
||||
('type', 'in', ('out_invoice', 'out_refund'))
|
||||
])
|
||||
account_invoice_report._apply_ir_rules(where_query, 'read')
|
||||
from_clause, where_clause, where_clause_params = where_query.get_sql()
|
||||
|
||||
# price_total is in the company currency
|
||||
query = """
|
||||
SELECT SUM(price_total) as total, partner_id
|
||||
FROM account_invoice_report account_invoice_report
|
||||
WHERE %s
|
||||
GROUP BY partner_id
|
||||
""" % where_clause
|
||||
self.env.cr.execute(query, where_clause_params)
|
||||
price_totals = self.env.cr.dictfetchall()
|
||||
for partner, child_ids in all_partners_and_children.items():
|
||||
partner.total_invoiced = sum(price['total'] for price in price_totals if price['partner_id'] in child_ids)
|
||||
|
||||
@api.multi
|
||||
def _journal_item_count(self):
|
||||
|
||||
@@ -65,6 +65,8 @@ class TestAccountCustomerInvoice(AccountTestUsers):
|
||||
tax = self.env['account.invoice.tax'].create(invoice_tax_line)
|
||||
assert tax, "Tax has not been assigned correctly"
|
||||
|
||||
total_before_confirm = self.partner3.total_invoiced
|
||||
|
||||
# I check that Initially customer invoice is in the "Draft" state
|
||||
self.assertEquals(self.account_invoice_customer0.state, 'draft')
|
||||
|
||||
@@ -92,6 +94,9 @@ class TestAccountCustomerInvoice(AccountTestUsers):
|
||||
# I verify that invoice is now in Paid state
|
||||
assert (self.account_invoice_customer0.state == 'paid'), "Invoice is not in Paid state"
|
||||
|
||||
total_after_confirm = self.partner3.total_invoiced
|
||||
self.assertEquals(total_after_confirm - total_before_confirm, self.account_invoice_customer0.amount_untaxed_signed)
|
||||
|
||||
# I refund the invoice Using Refund Button
|
||||
invoice_refund_obj = self.env['account.invoice.refund']
|
||||
self.account_invoice_refund_0 = invoice_refund_obj.create(dict(
|
||||
|
||||
Reference in New Issue
Block a user