From 356bfc19327faffdd62e69849d7d58af57bc6fd1 Mon Sep 17 00:00:00 2001 From: Romain Courteaud <romain@nexedi.com> Date: Wed, 26 Oct 2005 15:02:27 +0000 Subject: [PATCH] Add a new functionality to the configuration of the SupplyChain. Now, if a resource is associated to a Supply Link representing a production, no sourcing will be generated for this resource. git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@4135 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5/Document/SupplyChain.py | 51 ++++++++++++- product/ERP5/Document/SupplyLink.py | 75 ++++++++++++------- product/ERP5/Document/TransformationRule.py | 17 +---- .../Document/TransformationSourcingRule.py | 23 ++++++ 4 files changed, 121 insertions(+), 45 deletions(-) diff --git a/product/ERP5/Document/SupplyChain.py b/product/ERP5/Document/SupplyChain.py index 1f4ea508ef..504936db8a 100755 --- a/product/ERP5/Document/SupplyChain.py +++ b/product/ERP5/Document/SupplyChain.py @@ -88,6 +88,55 @@ class SupplyChain(Path, XMLObject): str(self.getRelativeUrl()) return result + security.declareProtected(Permissions.View, + 'getNextSupplyLinkList') + def getNextSupplyLinkList(self, current_supply_link): + """ + Return the previous SupplyLink list. + """ + supply_link_list = self.objectValues( + portal_type=self.supply_link_portal_type) + # Search next link + next_node_value = current_supply_link.getNextNodeValue() + next_supply_link_list = [x for x in supply_link_list if \ + x.getCurrentNodeValue() == next_node_value] + # Prevent infinite loop + if current_supply_link in next_supply_link_list: + next_supply_link_list.remove(current_supply_link) + # Get only production node in the list, or return the entire list + next_production_list = [x for x in next_supply_link_list \ + if x.isProductionSupplyLink()] + if next_production_list != []: + next_supply_link_list = next_production_list + return next_supply_link_list + + security.declareProtected(Permissions.View, + 'getNextProductionSupplyLinkList') + def getNextProductionSupplyLinkList(self, current_supply_link): + """ + Return the next SupplyLink which represents a production, + if there is one. + No recursion is done. + """ + next_supply_link_list = self.getNextSupplyLinkList(current_supply_link) + return [x for x in next_supply_link_list if x.isProductionSupplyLink()] + + security.declareProtected(Permissions.View, + 'getNextProductionIndustrialPhaseList') + def getNextProductionIndustrialPhaseList(self, current_supply_link): + """ + Return all next industrial phase representing a production. + """ + ind_phase_dict = {} + for link in self.getNextProductionSupplyLinkList(current_supply_link): + for ind_phase in link.getIndustrialPhaseValueList(): + ind_phase_dict[ind_phase] = 1 + # Remove None value, and generate the list + ind_phase_dict.pop(None, None) + return ind_phase_dict.keys() + + security.declareProtected(Permissions.View, + 'getPreviousSupplyLinkList') def getPreviousSupplyLinkList(self, current_supply_link): """ Return the previous SupplyLink list. @@ -100,7 +149,7 @@ class SupplyChain(Path, XMLObject): current_node_value = current_supply_link.getCurrentNodeValue() previous_supply_link_list = [ x for x in supply_link_list if\ - x.getDestinationValue() == current_node_value] + x.getNextNodeValue() == current_node_value] # Prevent infinite loop if current_supply_link in previous_supply_link_list: previous_supply_link_list.remove(current_supply_link) diff --git a/product/ERP5/Document/SupplyLink.py b/product/ERP5/Document/SupplyLink.py index a563cdc5fe..a328f3c26a 100755 --- a/product/ERP5/Document/SupplyLink.py +++ b/product/ERP5/Document/SupplyLink.py @@ -97,46 +97,65 @@ class SupplyLink(Path, XMLObject): node = self.getSourceValue() return node + security.declareProtected(Permissions.View, 'getNextNodeValue') + def getNextNodeValue(self): + """ + Return the node used to find the next SupplyLink + """ + return self.getDestinationValue() + security.declareProtected(Permissions.View, 'test') def test(self, movement, concurrent_supply_link_list): """ Test if the current link can expand this movement. Futur implementation have to return properties value (like quantity) calculated. + This method is called only on packing list supply link. """ - # XXX This method has to be rewritten. - # Predicate must be used. - # Current implementation is enough now for customers. result = 0 - resource = movement.getResource() - if resource.find('operation/') == -1: - # XXX reject operation - if concurrent_supply_link_list == []: - result = 1 + # Test if the movement correspond to the resource to produced + ind_phase_list = movement.getIndustrialPhaseValueList() + if ind_phase_list != []: + # Is this SupplyLink in the route to the previous production node ? + supply_chain = self.getParent() + previous_ind_phase_list =\ + supply_chain.getPreviousProductionIndustrialPhaseList(self) + for ind_phase in ind_phase_list: + if ind_phase in previous_ind_phase_list: + result = 1 + break + else: + # How to delivered raw materials ? + # XXX This method has to be rewritten. + # Predicate must be used. + if len(concurrent_supply_link_list) > 1: + raise "SupplyChainError",\ + "SupplyChain unable to find route." else: - # Test if the movement correspond to the resource to produced - ind_phase_list = movement.getIndustrialPhaseValueList() - if ind_phase_list != []: - # Is this SupplyLink in the route to the previous production node ? + # Check if raw material is create by a production link or a packing + # list link. + supply_chain = self.getParent() + next_industrial_phase_list = \ + supply_chain.getNextProductionIndustrialPhaseList(self) + ind_phase_id_list = [x.getId() for x in next_industrial_phase_list] + + # Get the transformation to use + applied_rule = movement.getParent() + rule = applied_rule.getSpecialiseValue() + transformation = rule.getTransformation(applied_rule) + # Call getAggregatedAmountList + amount_list = transformation.getAggregatedAmountList( + movement.getParent().getParent(), + ind_phase_id_list=ind_phase_id_list) + resource_list = [x.getResourceValue() for x in amount_list] + current_resource = movement.getResourceValue() + if current_resource not in resource_list: + # We can delivered this resource supply_chain = self.getParent() previous_ind_phase_list =\ supply_chain.getPreviousProductionIndustrialPhaseList(self) - for ind_phase in ind_phase_list: - if ind_phase in previous_ind_phase_list: - result = 1 - break - else: - # How to delivered raw materials ? - # First dirty implementation... - if len(concurrent_supply_link_list) > 1: - raise "SupplyChainError",\ - "SupplyChain unable to find route." - else: - supply_chain = self.getParent() - previous_ind_phase_list =\ - supply_chain.getPreviousProductionIndustrialPhaseList(self) - if len(previous_ind_phase_list) == 0: - result = 1 + if len(previous_ind_phase_list) == 0: + result = 1 return result security.declareProtected(Permissions.View, 'getStartDate') diff --git a/product/ERP5/Document/TransformationRule.py b/product/ERP5/Document/TransformationRule.py index f165b6fe5b..7209613fdf 100755 --- a/product/ERP5/Document/TransformationRule.py +++ b/product/ERP5/Document/TransformationRule.py @@ -264,22 +264,7 @@ class TransformationRule(Rule): category_list = parent_movement.getVariationCategoryList( base_category_list=base_category_list) # Get the transformation to use - production_order_movement = applied_rule.getRootSimulationMovement().\ - getOrderValue() - # XXX Acquisition can be use instead - parent_uid = production_order_movement.getParent().getUid() - explanation_uid = production_order_movement.getExplanationUid() - if parent_uid == explanation_uid: - production_order_line = production_order_movement - else: - production_order_line = production_order_movement.getParent() - line_transformation = production_order_line.objectValues( - portal_type=self.getPortalTransformationTypeList()) - if len(line_transformation)==1: - transformation = line_transformation[0] - else: - transformation = production_order_line.getSpecialiseValue( - portal_type=self.getPortalTransformationTypeList()) + transformation = self.getTransformation(applied_rule) # Generate the fake context tmp_context = parent_movement.asContext( context=parent_movement, diff --git a/product/ERP5/Document/TransformationSourcingRule.py b/product/ERP5/Document/TransformationSourcingRule.py index 39bd122422..da67c65c35 100755 --- a/product/ERP5/Document/TransformationSourcingRule.py +++ b/product/ERP5/Document/TransformationSourcingRule.py @@ -92,6 +92,29 @@ class TransformationSourcingRuleMixin(ExtensionClass.Base): # Update movement properties movement.edit(**(movement_dict[movement_id])) + security.declareProtected(Permissions.View, 'getTransformation') + def getTransformation(self, applied_rule): + """ + Get transformation related to used by the applied rule. + """ + production_order_movement = applied_rule.getRootSimulationMovement().\ + getOrderValue() + # XXX Acquisition can be use instead + parent_uid = production_order_movement.getParent().getUid() + explanation_uid = production_order_movement.getExplanationUid() + if parent_uid == explanation_uid: + production_order_line = production_order_movement + else: + production_order_line = production_order_movement.getParent() + line_transformation = production_order_line.objectValues( + portal_type=self.getPortalTransformationTypeList()) + if len(line_transformation)==1: + transformation = line_transformation[0] + else: + transformation = production_order_line.getSpecialiseValue( + portal_type=self.getPortalTransformationTypeList()) + return transformation + class TransformationSourcingRule(Rule): """ Transformation Sourcing Rule object make sure -- 2.30.9