diff --git a/product/ERP5/Document/SimulatedDeliveryBuilder.py b/product/ERP5/Document/SimulatedDeliveryBuilder.py index 942c81f52bf77ac8a377df5d316c6bf2e05c5037..0aae5d24a8c28ff9c9e13910cb8c65ea4b4214b9 100644 --- a/product/ERP5/Document/SimulatedDeliveryBuilder.py +++ b/product/ERP5/Document/SimulatedDeliveryBuilder.py @@ -98,7 +98,7 @@ class SimulatedDeliveryBuilder(BuilderMixin): pass @UnrestrictedMethod - def searchMovementList(self, applied_rule_uid=None, business_link_list=None, **kw): + def searchMovementList(self, applied_rule_uid=None, **kw): """ defines how to query all Simulation Movements which meet certain criteria (including the above path path definition). @@ -112,24 +112,18 @@ class SimulatedDeliveryBuilder(BuilderMixin): # Search only child movement from this applied rule if applied_rule_uid is not None: kw['parent_uid'] = applied_rule_uid - if business_link_list is None: - business_link_list = [] # XXX Add profile query # Add resource query if self.getResourcePortalType() not in ('', None): kw['resourceType'] = self.getResourcePortalType() if self.getSimulationSelectMethodId() in ['', None]: - prefilter_movement_list = [x.getObject() for x in self.portal_catalog(**kw)] + movement_list = [x.getObject() for x in self.portal_catalog(**kw)] else: select_method = getattr(self.getPortalObject(), self.getSimulationSelectMethodId()) - prefilter_movement_list = select_method(**kw) + movement_list = select_method(**kw) # XXX Use buildSQLQuery will be better - movement_list = [] - for movement in prefilter_movement_list: - for business_link in business_link_list: - if movement.isBuildable(business_link): - if movement.getDeliveryValueList()==[]: - movement_list.append(movement) + movement_list = [x for x in movement_list if \ + x.getDeliveryValueList()==[] and x.isBuildable()] # XXX Add predicate test # XXX FIXME Check that there is no double in the list # Because we can't trust simulation_select_method diff --git a/product/ERP5/Document/SimulationMovement.py b/product/ERP5/Document/SimulationMovement.py index a2c0f0815fb7075255f35c711e02e76da7b4a74a..82a5a0ef0b510788e10f0b8ab582ef93872a14b1 100644 --- a/product/ERP5/Document/SimulationMovement.py +++ b/product/ERP5/Document/SimulationMovement.py @@ -615,9 +615,19 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): else: return getTreeDelivered(self, ignore_first=ignore_first) + def _getBusinessLinkByPredicate(self): + business_link_list = self.asComposedDocument().getBusinessLinkValueList( + context=self) + if len(business_link_list) > 1: + raise ValueError('Simulation Movement %s composed document matched more ' + 'than one Business Link.' % self.getPath()) + if len(business_link_list) == 0: + return None + return business_link_list[0] + security.declareProtected(Permissions.AccessContentsInformation, 'isBuildable') - def isBuildable(self, business_link): + def isBuildable(self): """Simulation Movement buildable logic""" if self.getDelivery(): # already delivered @@ -625,25 +635,27 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): # might be buildable - business path dependent explanation_value = self.getExplanationValue() - if business_link is None or explanation_value is None: - # without Business Link and explanation it is impossible to check - # precisely if movement is buildable - # Note: It breaks compatilibity with old simulation code which did not - # use Business Process at all, here assumption is inverted - return False + if explanation_value is None: + # Without explanation movements are buildable + return True ## XXX Code below following line has been moved to BusinessPath (cf r37116) #return len(business_path.filterBuildableMovementList([self])) == 1 - predecessor_state = business_link.getPredecessor() + business_link_value = self.getCausalityValue(portal_type='Business Link') + if business_link_value is None: + business_link_value = self._getBusinessLinkByPredicate() + if business_link_value is None: + # No directly on indirectly set Business Link -- old simulation movement + return True + predecessor_state = business_link_value.getPredecessor() if predecessor_state is None: # first one, can be built return True # XXX-JPS wrong cause root is marked # movement is not built, and corresponding business path # has predecessors: check movements related to those predecessors! - composed_document = self.asComposedDocument() - predecessor_link_list = composed_document.getBusinessLinkValueList( + predecessor_link_list = self.asComposedDocument().getBusinessLinkValueList( successor=predecessor_state) def isBuiltAndCompleted(simulation, path): @@ -657,20 +669,14 @@ class SimulationMovement(PropertyRecordableMixin, Movement, ExplainableMixin): causality_dict = {} current = self.getParentValue().getParentValue() while current.getPortalType() == "Simulation Movement": - business_link = current.getCausality(portal_type='Business Link') - if business_link is None: - # no direct business link set on movement, use predicate to find one - business_link_list = composed_document.getBusinessLinkValueList( - context=current) - if len(business_link_list) > 1: - raise ValueError('Business Link predicate matches too many ' - 'movements.') - if len(business_link_list) == 0: - raise ValueError('Simulation Movement has no Business Link related ' - 'and no Business Link from current Business Process matches') - business_link = business_link_list[0].getRelativeUrl() - - causality_dict[business_link] = current + current_business_link = current.getCausality(portal_type='Business Link') + if current_business_link is None: + current_business_link_value = current._getBusinessLinkByPredicate() + if current_business_link_value is None: + raise ValueError('Simulation Movement %s has no Business Link ' + 'related and no Business Link from composed document matches'% + current.getPath()) + causality_dict[current_business_link_value.getRelativeUrl()] = current current = current.getParentValue().getParentValue() remaining_path_set = set() diff --git a/product/ERP5/mixin/builder.py b/product/ERP5/mixin/builder.py index ac818183b0275e85d1753dca5363485a5cc3a0b0..54c226cd1b7b0851c7b016393768be89af8cd63c 100644 --- a/product/ERP5/mixin/builder.py +++ b/product/ERP5/mixin/builder.py @@ -126,7 +126,6 @@ class BuilderMixin(XMLObject, Amount, Predicate): kw['path'] = explanation_cache.getSimulationPathPatternList() if business_link is not None: kw['causality_uid'] = business_link.getUid() - business_link_value_list = [business_link] elif kw.get('causality_uid') is None: business_link_value_list = self.getRelatedBusinessLinkValueList() if len(business_link_value_list) > 0: @@ -135,7 +134,6 @@ class BuilderMixin(XMLObject, Amount, Predicate): movement_list = self.searchMovementList( delivery_relative_url_list=delivery_relative_url_list, applied_rule_uid=applied_rule_uid, - business_link_list=business_link_value_list, **kw) if not movement_list: return [] diff --git a/product/ERP5/mixin/movement_collection_updater.py b/product/ERP5/mixin/movement_collection_updater.py index 4264108c47a4bbe8feb466ed185f7d7a5a42347e..7c316b677fd92bd22736af495ce1a1cd4865d2bc 100644 --- a/product/ERP5/mixin/movement_collection_updater.py +++ b/product/ERP5/mixin/movement_collection_updater.py @@ -189,8 +189,7 @@ class MovementCollectionUpdaterMixin: modified_movement_list.append(movement) for movement in modified_movement_list: # for each touched non buildable movement reset causality_list - if not movement.isBuildable(movement.getCausalityValue( - portal_type='Business Link')): + if not movement.isBuildable(): movement.setCausalityList([q.getRelativeUrl() for q in \ movement.getCausalityValueList() if q.getPortalType() \ not in self.getPortalBusinessLinkTypeList()]) diff --git a/product/ERP5/tests/testTradeModelLine.py b/product/ERP5/tests/testTradeModelLine.py index b1acc8d6279c43caa91b548464f6a46d5ca7c6b5..8108003bd362bb91c7d81215b77f5eac699ba3b4 100644 --- a/product/ERP5/tests/testTradeModelLine.py +++ b/product/ERP5/tests/testTradeModelLine.py @@ -437,7 +437,7 @@ class TestTradeModelLine(TestTradeModelLineMixin): sm = result_dict.pop(use) business_link_list = sm.asComposedDocument().getBusinessLinkValueList(context=sm) self.assertEqual(len(business_link_list), 1) - is_buildable = sm.isBuildable(business_link_list[0]) + is_buildable = sm.isBuildable() self.assertEqual(str(sm.getTotalPrice() or 0.0), str(total_price)) if is_buildable: self.assertEqual(3, len(sm.getCausalityValueList()))