Commit 356bfc19 authored by Romain Courteaud's avatar Romain Courteaud

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
parent 7abbf29c
...@@ -88,6 +88,55 @@ class SupplyChain(Path, XMLObject): ...@@ -88,6 +88,55 @@ class SupplyChain(Path, XMLObject):
str(self.getRelativeUrl()) str(self.getRelativeUrl())
return result 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): def getPreviousSupplyLinkList(self, current_supply_link):
""" """
Return the previous SupplyLink list. Return the previous SupplyLink list.
...@@ -100,7 +149,7 @@ class SupplyChain(Path, XMLObject): ...@@ -100,7 +149,7 @@ class SupplyChain(Path, XMLObject):
current_node_value = current_supply_link.getCurrentNodeValue() current_node_value = current_supply_link.getCurrentNodeValue()
previous_supply_link_list = [ previous_supply_link_list = [
x for x in supply_link_list if\ x for x in supply_link_list if\
x.getDestinationValue() == current_node_value] x.getNextNodeValue() == current_node_value]
# Prevent infinite loop # Prevent infinite loop
if current_supply_link in previous_supply_link_list: if current_supply_link in previous_supply_link_list:
previous_supply_link_list.remove(current_supply_link) previous_supply_link_list.remove(current_supply_link)
......
...@@ -97,46 +97,65 @@ class SupplyLink(Path, XMLObject): ...@@ -97,46 +97,65 @@ class SupplyLink(Path, XMLObject):
node = self.getSourceValue() node = self.getSourceValue()
return node 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') security.declareProtected(Permissions.View, 'test')
def test(self, movement, concurrent_supply_link_list): def test(self, movement, concurrent_supply_link_list):
""" """
Test if the current link can expand this movement. Test if the current link can expand this movement.
Futur implementation have to return properties value Futur implementation have to return properties value
(like quantity) calculated. (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 result = 0
resource = movement.getResource() # Test if the movement correspond to the resource to produced
if resource.find('operation/') == -1: ind_phase_list = movement.getIndustrialPhaseValueList()
# XXX reject operation if ind_phase_list != []:
if concurrent_supply_link_list == []: # Is this SupplyLink in the route to the previous production node ?
result = 1 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: else:
# Test if the movement correspond to the resource to produced # Check if raw material is create by a production link or a packing
ind_phase_list = movement.getIndustrialPhaseValueList() # list link.
if ind_phase_list != []: supply_chain = self.getParent()
# Is this SupplyLink in the route to the previous production node ? 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() supply_chain = self.getParent()
previous_ind_phase_list =\ previous_ind_phase_list =\
supply_chain.getPreviousProductionIndustrialPhaseList(self) supply_chain.getPreviousProductionIndustrialPhaseList(self)
for ind_phase in ind_phase_list: if len(previous_ind_phase_list) == 0:
if ind_phase in previous_ind_phase_list: result = 1
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
return result return result
security.declareProtected(Permissions.View, 'getStartDate') security.declareProtected(Permissions.View, 'getStartDate')
......
...@@ -264,22 +264,7 @@ class TransformationRule(Rule): ...@@ -264,22 +264,7 @@ class TransformationRule(Rule):
category_list = parent_movement.getVariationCategoryList( category_list = parent_movement.getVariationCategoryList(
base_category_list=base_category_list) base_category_list=base_category_list)
# Get the transformation to use # Get the transformation to use
production_order_movement = applied_rule.getRootSimulationMovement().\ transformation = self.getTransformation(applied_rule)
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())
# Generate the fake context # Generate the fake context
tmp_context = parent_movement.asContext( tmp_context = parent_movement.asContext(
context=parent_movement, context=parent_movement,
......
...@@ -92,6 +92,29 @@ class TransformationSourcingRuleMixin(ExtensionClass.Base): ...@@ -92,6 +92,29 @@ class TransformationSourcingRuleMixin(ExtensionClass.Base):
# Update movement properties # Update movement properties
movement.edit(**(movement_dict[movement_id])) 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): class TransformationSourcingRule(Rule):
""" """
Transformation Sourcing Rule object make sure Transformation Sourcing Rule object make sure
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment