[IMP] account_tax_balance: Optimized computation of move type

Reduced complexity based on `read_group`. This method was prefetching a lot and doing many slow operations.

Executing in a real database for 197361 recs. took 14 minutes before and 1:36 minutes now.

@Tecnativa TT18838
pull/643/head
Jairo Llopis 2019-12-12 10:32:19 +00:00
parent 4fcbae7545
commit f3ddb4fc06
1 changed files with 36 additions and 19 deletions

View File

@ -21,22 +21,39 @@ class AccountMove(models.Model):
@api.multi @api.multi
@api.depends('line_ids.account_id.internal_type', 'line_ids.balance') @api.depends('line_ids.account_id.internal_type', 'line_ids.balance')
def _compute_move_type(self): def _compute_move_type(self):
def _balance_get(line_ids, internal_type): sequence = (
return sum(line_ids.filtered( ("liquidity", lambda balance: "liquidity"),
lambda x: x.account_id.internal_type == internal_type).mapped( ("payable", lambda balance: ('payable' if balance < 0
'balance')) else 'payable_refund')),
("receivable", lambda balance: ('receivable' if balance > 0
for move in self: else 'receivable_refund')),
internal_types = move.line_ids.mapped('account_id.internal_type') (False, lambda balance: "other"),
if 'liquidity' in internal_types: )
move.move_type = 'liquidity' chunked_self = (
elif 'payable' in internal_types: self[i:i + models.PREFETCH_MAX]
balance = _balance_get(move.line_ids, 'payable') for i in range(0, len(self), models.PREFETCH_MAX)
move.move_type = ( )
'payable' if balance < 0 else 'payable_refund') for chunk in chunked_self:
elif 'receivable' in internal_types: move_ids = set(chunk.ids)
balance = _balance_get(move.line_ids, 'receivable') for internal_type, criteria in sequence:
move.move_type = ( if not move_ids:
'receivable' if balance > 0 else 'receivable_refund') break
else: # Find balances of the expected type for this move
move.move_type = 'other' domain = [
("move_id", "in", list(move_ids)),
]
if internal_type:
domain += [
("account_id.internal_type", "=", internal_type),
]
balances = self.env["account.move.line"].read_group(
domain=domain,
fields=["move_id", "balance"],
groupby=["move_id"],
)
for balance in balances:
move = self.browse(balance["move_id"][0])
# Discard the move for next searches
move_ids.discard(move.id)
# Update its type
move.move_type = criteria(balance["balance"])