[Erp5-report] r30409 - /erp5/trunk/products/ERP5/Tool/SolverTool.py
nobody at svn.erp5.org
nobody at svn.erp5.org
Sun Nov 8 18:19:59 CET 2009
Author: jp
Date: Sun Nov 8 18:19:58 2009
New Revision: 30409
URL: http://svn.erp5.org?rev=30409&view=rev
Log:
Pseudo-code for IDivergenceController implementation. This shows in particular how the interface implementation will evolve from 100% ad-hoc (urgent) to fully generic.
Modified:
erp5/trunk/products/ERP5/Tool/SolverTool.py
Modified: erp5/trunk/products/ERP5/Tool/SolverTool.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Tool/SolverTool.py?rev=30409&r1=30408&r2=30409&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Tool/SolverTool.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Tool/SolverTool.py [utf8] Sun Nov 8 18:19:58 2009
@@ -65,6 +65,7 @@
# Declarative interfaces
zope.interface.implements(interfaces.IDeliverySolverFactory,
+ interfaces.IDivergenceController,
)
# Implementation
@@ -81,7 +82,7 @@
""" show the content in the left pane of the ZMI """
return self.objectValues()
- # ISolverTool implementation
+ # IDeliverySolverFactory implementation
def newDeliverySolver(self, class_name, movement_list):
"""
"""
@@ -106,3 +107,154 @@
"""
"""
raise NotImplementedError
+
+ # IDivergenceController implementation
+ def isDivergent(self, delivery_or_movement=None):
+ """
+ Returns True if any of the movements provided
+ in delivery_or_movement is divergent
+
+ delivery_or_movement -- a movement, a delivery,
+ or a list thereof
+ """
+
+ def newSolverProcess(self, delivery_or_movement=None):
+ """
+ Builds a new solver process from the divergence
+ analaysis of delivery_or_movement. All movements
+ which are not divergence are placed in a Solver
+ Decision with no Divergence Tester specified.
+
+ delivery_or_movement -- a movement, a delivery,
+ or a list thereof
+ """
+ # Do not create a new solver process if no divergence
+ if not self.isDivergent(delivery_or_movement=delivery_or_movement):
+ return None
+
+ # We suppose here that delivery_or_movement is a list of
+ # delivery lines. Let group decisions in such way
+ # that a single decision is created per divergence tester instance
+ # and per application level list
+ solver_decision_dict = {}
+ if movement in delivery_or_movement:
+ for simulation_movement in movement.getDeliveryRelatedValueList():
+ simulation_movemet_url = simulation_movement.getRelativeUrl()
+ for divergence_tester in simulation_movement.getParentValue().getDivergenceTesterValueList():
+ application_list = map(lambda x:x.getRelativeUrl(),
+ self.getSolverDecisionApplicationValueList(simulation_movement, divergence_tester))
+ application_list.sort()
+ solver_decision_key = (divergence_tester.getRelativeUrl(), application_list)
+ movement_dict = solver_decision_dict.setdefaults(solver_decision_key, {})
+ movement_dict[simulation_movemet_url] = None
+
+ # Now build the solver process instances based on the previous
+ # grouping
+ new_solver = self.newContent(portal_type='Solver Process')
+ for solver_decision_key, movement_dict in solver_decision_dict.items():
+ new_decision = self.newContent(portal_type='Solver Decision')
+ new_decision._setDeliveryList(movement_url.keys(p))
+ new_decision._setSolver(solver_decision_key[0])
+ # No need to set application_list or....?
+
+ def getSolverProcessValueList(self, delivery_or_movement=None, validation_state=None):
+ """
+ Returns the list of solver processes which are
+ are in a given state and which apply to delivery_or_movement.
+ This method is useful to find applicable solver processes
+ for a delivery.
+
+ delivery_or_movement -- a movement, a delivery,
+ or a list thereof
+
+ validation_state -- a state of a list of states
+ to filter the result
+ """
+
+ def getSolverDecisionValueList(self, delivery_or_movement=None, validation_state=None):
+ """
+ Returns the list of solver decisions which apply
+ to a given movement.
+
+ delivery_or_movement -- a movement, a simulation movement, a delivery,
+ or a list thereof
+
+ validation_state -- a state of a list of states
+ to filter the result
+ """
+
+ def getSolverDecisionApplicationValueList(self, movement, divergence_tester=None):
+ """
+ Returns the list of documents at which a given divergence resolution
+ can be resolved at. For example, in most cases, date divergences can
+ only be resolved at delivery level whereas quantities are usually
+ resolved at cell level.
+
+ The result of this method is a list of ERP5 documents.
+
+ NOTE: renaming probably required. I do not like this name nor the one
+ of the interface definition.
+ """
+ # Short Term Implementation Approach
+ return self.SolverTool_getSolverDecisionApplicationValueList(movement, divergence_tester)
+
+ # Alternate short Term Implementation Approach
+ return divergence_tester.getTypeBasedMethod('getSolverDecisionApplicationValueList')(
+ movement, divergence_tester)
+
+ # Alternate short Term Implementation Approach
+ test_property = divergence_tester.getTestedProperty()
+ application_value = movement
+ while not application_value.hasProperty(test_property):
+ application_value = application_value.getParentValue()
+ return application_value
+
+ # Mid-term implementation (we suppose movement is a delivery)
+ # use delivery builders to find out at which level the given
+ # property can be modified
+ test_property = divergence_tester.getTestedProperty()
+ application_value_level = {}
+ for simulation_movement in movement.getDeliveryRelatedValueList():
+ business_path = simulation_movement.getCausalityValue()
+ for delivery_builder in business_path.getDeliveryBuilderValueList():
+ for movement_group in delivery_builder.contentValues(): # filter missing
+ if test_property in movement_group.getTestedPropertyList():
+ application_value_level[movement_group.getCollectGroupOrder()] = None
+ result = []
+ # Delivery level
+ if 'delivery' in application_value_level:
+ result.append(movement.getDeliveryValue())
+ # Line level
+ if 'line' in application_value_level and not movement.isLine():
+ result.append(movement)
+ elif 'line' in application_value_level and not movement.isLine():
+ result.append(movement.getParentValue())
+ # Cell level
+ if 'cell' in application_value_level and movement.isCell():
+ result.append(movement)
+ # Group of lines level (we try to find the most appropriate enclosing group)
+ if 'group' in application_value_level:
+ application_value = movement
+ while not application_value.hasProperty(test_property):
+ application_value = application_value.getParentValue()
+ if application_value not in result: result.append(application_value)
+ # Group of lines level (we try to find the most appropriate enclosing group)
+ if 'all_group' in application_value_level:
+ application_value = movement
+ while not application_value.hasProperty(test_property):
+ application_value = application_value.getParentValue()
+ if application_value not in result: result.append(application_value)
+ return result
+
+ # Longer-term implementation (we suppose movement is a delivery)
+ # use delivery builders to find out at which level the given
+ # property can be modified
+ test_property = divergence_tester.getTestedProperty()
+ application_value_level = {}
+ for simulation_movement in movement.getDeliveryRelatedValueList():
+ business_path = simulation_movement.getCausalityValue()
+ for delivery_builder in business_path.getDeliveryBuilderValueList():
+ for property_group in delivery_builder.contentValues(portal_type="Property group"):
+ if test_property in property_group.getTestedPropertyList():
+ application_value_level[property_group.getCollectGroupOrder()] = None
+ # etc. same
More information about the Erp5-report
mailing list