Browse Source

Merge PR #1648 into 12.0

Signed-off-by yvaucher
12.0
OCA-git-bot 5 years ago
parent
commit
a5c849fcdd
  1. 42
      base_exception/models/base_exception.py

42
base_exception/models/base_exception.py

@ -87,28 +87,45 @@ class BaseExceptionMethod(models.AbstractModel):
def detect_exceptions(self):
"""List all exception_ids applied on self
Exception ids are also written on records
If self is empty, check exceptions on all active records.
"""
rules = self.env['exception.rule'].sudo().search(
self._rule_domain())
all_exception_ids = []
rules_to_remove = {}
rules_to_add = {}
for rule in rules:
records_with_exception = self._detect_exceptions(rule)
reverse_field = self._reverse_field()
if self:
main_records = self._get_main_records()
commons = main_records & rule[reverse_field]
to_remove = commons - records_with_exception
to_add = records_with_exception - commons
to_remove_list = [(3, x.id, _) for x in to_remove]
to_add_list = [(4, x.id, _) for x in to_add]
rule.write({reverse_field: to_remove_list + to_add_list})
else:
rule.write({
reverse_field: [(6, 0, records_with_exception.ids)]
})
# we expect to always work on the same model type
rules_to_remove.setdefault(
rule.id, main_records.browse()
).update(to_remove)
rules_to_add.setdefault(
rule.id, main_records.browse()
).update(to_add)
if records_with_exception:
all_exception_ids.append(rule.id)
# Cumulate all the records to attach to the rule
# before linking. We don't want to call "rule.write()"
# which would:
# * write on write_date so lock the expection.rule
# * trigger the recomputation of "main_exception_id" on
# all the sale orders related to the rule, locking them all
# and preventing concurrent writes
# Reversing the write by writing on SaleOrder instead of
# ExceptionRule fixes the 2 kinds of unexpected locks.
# It should not result in more queries than writing on ExceptionRule:
# the "to remove" part generates one DELETE per rule on the relation
# table
# and the "to add" part generates one INSERT (with unnest) per rule.
for rule_id, records in rules_to_remove.items():
records.write({'exception_ids': [(3, rule_id,)]})
for rule_id, records in rules_to_add.items():
records.write(({'exception_ids': [(4, rule_id,)]}))
return all_exception_ids
@api.model
@ -149,16 +166,12 @@ class BaseExceptionMethod(models.AbstractModel):
@api.multi
def _get_base_domain(self):
domain = [('ignore_exception', '=', False)]
if self:
domain = osv.expression.AND([domain, [('id', 'in', self.ids)]])
return domain
return [('ignore_exception', '=', False), ('id', 'in', self.ids)]
@api.multi
def _detect_exceptions_by_py_code(self, rule):
"""
Find exceptions found on self.
If self is empty, check on all records.
"""
domain = self._get_base_domain()
records = self.search(domain)
@ -172,7 +185,6 @@ class BaseExceptionMethod(models.AbstractModel):
def _detect_exceptions_by_domain(self, rule):
"""
Find exceptions found on self.
If self is empty, check on all records.
"""
base_domain = self._get_base_domain()
rule_domain = rule._get_domain()

Loading…
Cancel
Save