diff --git a/product/ERP5/Document/AppliedRule.py b/product/ERP5/Document/AppliedRule.py index 9dffa3a55d97bcae31e43a64153a8aa44d8cbd7a..9fe7e89f09a5a0468591258dde3654471a33f762 100644 --- a/product/ERP5/Document/AppliedRule.py +++ b/product/ERP5/Document/AppliedRule.py @@ -28,8 +28,10 @@ ############################################################################## from collections import deque +import sys +import transaction import zope.interface - +from zExceptions import ExceptionFormatter from AccessControl import ClassSecurityInfo from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter @@ -485,3 +487,38 @@ class AppliedRule(XMLObject, ExplainableMixin): assert str not in map(type, old_dict), old_dict return dict((k, sum(v.values(), [])) for k, v in deleted), delivery_set simulation_tool._delObject(self.getId()) + + def _checkExpand(self): + """Check that expand() would not fail nor do major changes to the subobjects + + Transaction is aborted after 'expand' is called. + + See also SimulationTool._checkExpandAll + """ + property_dict = {'Applied Rule': ('specialise',), + 'Simulation Movement': ('delivery', 'quantity')} + def fillRuleDict(): + rule_dict = {} + object_list = deque((self,)) + while object_list: + document = object_list.popleft() + portal_type = document.getPortalType() + document_dict = {'portal_type': portal_type} + for property in property_dict[portal_type]: + document_dict[property] = document.getProperty(property) + rule_dict[document.getRelativeUrl()] = document_dict + object_list += document.objectValues() + return rule_dict + initial_rule_dict = fillRuleDict() + try: + self.expand() + except ConflictError: + raise + except Exception: + msg = ''.join(ExceptionFormatter.format_exception(*sys.exc_info())[1:]) + else: + final_rule_dict = fillRuleDict() + msg = "%r != %r" % (initial_rule_dict, final_rule_dict) \ + if initial_rule_dict != final_rule_dict else None + transaction.abort() + return msg diff --git a/product/ERP5/Tool/SimulationTool.py b/product/ERP5/Tool/SimulationTool.py index 1fc4c38d89f3a897a6477a269c8a9d6947ef0d04..ace4b77b6bbba0f51e5dde7f6aa56c84e892e3da 100644 --- a/product/ERP5/Tool/SimulationTool.py +++ b/product/ERP5/Tool/SimulationTool.py @@ -2867,6 +2867,18 @@ class SimulationTool(BaseTool): src__=src__)) return sequence + def _checkExpandAll(self, activate_kw={}): + """Check all simulation trees using AppliedRule._checkExpand + """ + portal = self.getPortalObject() + active_process = portal.portal_activities.newActiveProcess().getPath() + kw = dict(priority=3, tag='checkExpand') + kw.update(group_method_cost=1, max_retry=0, + active_process=active_process, **activate_kw) + self._recurseCallMethod('_checkExpand', min_depth=1, max_depth=1, + activate_kw=kw) + return active_process + from Products.ERP5Type.DateUtils import addToDate class SequenceItem: