|
@ -87,28 +87,45 @@ class BaseExceptionMethod(models.AbstractModel): |
|
|
def detect_exceptions(self): |
|
|
def detect_exceptions(self): |
|
|
"""List all exception_ids applied on self |
|
|
"""List all exception_ids applied on self |
|
|
Exception ids are also written on records |
|
|
Exception ids are also written on records |
|
|
If self is empty, check exceptions on all active records. |
|
|
|
|
|
""" |
|
|
""" |
|
|
rules = self.env['exception.rule'].sudo().search( |
|
|
rules = self.env['exception.rule'].sudo().search( |
|
|
self._rule_domain()) |
|
|
self._rule_domain()) |
|
|
all_exception_ids = [] |
|
|
all_exception_ids = [] |
|
|
|
|
|
rules_to_remove = {} |
|
|
|
|
|
rules_to_add = {} |
|
|
for rule in rules: |
|
|
for rule in rules: |
|
|
records_with_exception = self._detect_exceptions(rule) |
|
|
records_with_exception = self._detect_exceptions(rule) |
|
|
reverse_field = self._reverse_field() |
|
|
reverse_field = self._reverse_field() |
|
|
if self: |
|
|
|
|
|
main_records = self._get_main_records() |
|
|
main_records = self._get_main_records() |
|
|
commons = main_records & rule[reverse_field] |
|
|
commons = main_records & rule[reverse_field] |
|
|
to_remove = commons - records_with_exception |
|
|
to_remove = commons - records_with_exception |
|
|
to_add = records_with_exception - commons |
|
|
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: |
|
|
if records_with_exception: |
|
|
all_exception_ids.append(rule.id) |
|
|
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 |
|
|
return all_exception_ids |
|
|
|
|
|
|
|
|
@api.model |
|
|
@api.model |
|
@ -149,16 +166,12 @@ class BaseExceptionMethod(models.AbstractModel): |
|
|
|
|
|
|
|
|
@api.multi |
|
|
@api.multi |
|
|
def _get_base_domain(self): |
|
|
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 |
|
|
@api.multi |
|
|
def _detect_exceptions_by_py_code(self, rule): |
|
|
def _detect_exceptions_by_py_code(self, rule): |
|
|
""" |
|
|
""" |
|
|
Find exceptions found on self. |
|
|
Find exceptions found on self. |
|
|
If self is empty, check on all records. |
|
|
|
|
|
""" |
|
|
""" |
|
|
domain = self._get_base_domain() |
|
|
domain = self._get_base_domain() |
|
|
records = self.search(domain) |
|
|
records = self.search(domain) |
|
@ -172,7 +185,6 @@ class BaseExceptionMethod(models.AbstractModel): |
|
|
def _detect_exceptions_by_domain(self, rule): |
|
|
def _detect_exceptions_by_domain(self, rule): |
|
|
""" |
|
|
""" |
|
|
Find exceptions found on self. |
|
|
Find exceptions found on self. |
|
|
If self is empty, check on all records. |
|
|
|
|
|
""" |
|
|
""" |
|
|
base_domain = self._get_base_domain() |
|
|
base_domain = self._get_base_domain() |
|
|
rule_domain = rule._get_domain() |
|
|
rule_domain = rule._get_domain() |
|
|