Browse Source

[12.0][imp][account_tax_balance] improve performance

The tax balance report searches using a m2m field, which kills performance
in large databases. We need direct SQL queries in order to work around
this issue. See odoo/odoo#30350
pull/769/head
Jordi Ballester 3 years ago
committed by Mateu Griful
parent
commit
37359a22be
  1. 139
      account_tax_balance/models/account_tax.py

139
account_tax_balance/models/account_tax.py

@ -121,58 +121,103 @@ class AccountTax(models.Model):
state = []
return state
def get_move_line_partial_domain(self, from_date, to_date, company_id):
return [
('date', '<=', to_date),
('date', '>=', from_date),
('company_id', '=', company_id),
]
def compute_balance(self, tax_or_base='tax', move_type=None):
def get_move_line_partial_where(self, from_date, to_date, company_ids):
query = "aml.date <= %s AND aml.date >= %s AND aml.company_id IN %s"
params = [to_date, from_date, tuple(company_ids)]
return query, params
def compute_balance(self, tax_or_base="tax", move_type=None):
# There's really bad performace in m2m fields.
# So we better do a direct query.
# See https://github.com/odoo/odoo/issues/30350
self.ensure_one()
domain = self.get_move_lines_domain(
tax_or_base=tax_or_base, move_type=move_type)
# balance is debit - credit whereas on tax return you want to see what
# vat has to be paid so:
# VAT on sales (credit) - VAT on purchases (debit).
balance = self.env['account.move.line'].\
read_group(domain, ['balance'], [])[0]['balance']
return balance and -balance or 0
def get_balance_domain(self, state_list, type_list):
domain = [
('move_id.state', 'in', state_list),
('tax_line_id', '=', self.id),
('tax_exigible', '=', True)
]
query, params = self.get_move_lines_query(
tax_or_base=tax_or_base, move_type=move_type
)
_select = "sum(aml.balance)"
query = query.format(select_clause=_select)
self.env.cr.execute(query, params) # pylint: disable=E8103
res = self.env.cr.fetchone()
balance = 0.0
if res:
balance = res[0]
return balance and -balance or 0.0
def get_move_lines_query(self, tax_or_base="tax", move_type=None):
from_date, to_date, company_ids, target_move = self.get_context_values()
state_list = self.get_target_state_list(target_move)
type_list = self.get_target_type_list(move_type)
base_query = self.get_move_lines_base_query()
_where = ""
_joins = ""
_params = []
where, params = self.get_move_line_partial_where(
from_date, to_date, company_ids
)
_where += where
_params += params
if tax_or_base == "tax":
where, params = self.get_balance_where(state_list, type_list)
_where += where
_params += params
elif tax_or_base == "base":
joins, where, params = self.get_base_balance_where(state_list, type_list)
_where += where
_joins += joins
_params += params
query = base_query.format(
select_clause="{select_clause}",
where_clause=_where,
additional_joins=_joins,
)
return query, _params
def get_move_lines_base_query(self):
return (
"SELECT {select_clause} FROM account_move_line AS aml "
"INNER JOIN account_move AS am ON aml.move_id = am.id "
"{additional_joins}"
" WHERE {where_clause}"
)
def get_balance_where(self, state_list, type_list):
where = (
" AND am.state IN %s AND "
"aml.tax_line_id = %s AND "
"aml.tax_exigible = True"
)
params = [tuple(state_list), self.id]
if type_list:
domain.append(('move_id.move_type', 'in', type_list))
return domain
where += " AND am.move_type IN %s"
params += [tuple(type_list)]
return where, params
def get_base_balance_where(self, state_list, type_list):
joins = (
" INNER JOIN account_move_line_account_tax_rel AS rel "
"ON aml.id = rel.account_move_line_id"
" INNER JOIN account_tax as tax "
"ON tax.id = rel.account_tax_id"
)
def get_base_balance_domain(self, state_list, type_list):
domain = [
('move_id.state', 'in', state_list),
('tax_ids', 'in', self.id),
('tax_exigible', '=', True)
]
where = " AND am.state IN %s" " AND tax.id = %s" " AND aml.tax_exigible = True "
params = [tuple(state_list), self.id]
if type_list:
domain.append(('move_id.move_type', 'in', type_list))
return domain
where += " AND am.move_type IN %s"
params += [tuple(type_list)]
return joins, where, params
def get_move_lines_domain(self, tax_or_base='tax', move_type=None):
from_date, to_date, company_id, target_move = self.get_context_values()
state_list = self.get_target_state_list(target_move)
type_list = self.get_target_type_list(move_type)
domain = self.get_move_line_partial_domain(
from_date, to_date, company_id)
balance_domain = []
if tax_or_base == 'tax':
balance_domain = self.get_balance_domain(state_list, type_list)
elif tax_or_base == 'base':
balance_domain = self.get_base_balance_domain(
state_list, type_list)
domain.extend(balance_domain)
def get_move_lines_domain(self, tax_or_base="tax", move_type=None):
query, params = self.get_move_lines_query(
tax_or_base=tax_or_base, move_type=move_type
)
_select = "aml.id"
query = query.format(select_clause=_select)
self.env.cr.execute(query, params) # pylint: disable=E8103
amls = []
for (aml_id,) in self.env.cr.fetchall():
amls.append(aml_id)
domain = [("id", "in", amls)]
return domain
def get_lines_action(self, tax_or_base='tax', move_type=None):

Loading…
Cancel
Save