Commit 9880c119 authored by Jean-Paul Smets's avatar Jean-Paul Smets

Some more ideas where BPM is heading to

git-svn-id: https://svn.erp5.org/repos/public/erp5/sandbox/amount_generator@35585 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent e31f2aef
...@@ -34,42 +34,12 @@ from AccessControl import ClassSecurityInfo ...@@ -34,42 +34,12 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Path import Path from Products.ERP5.Document.Path import Path
from Products.ERP5.Document.Predicate import Predicate from Products.ERP5.Document.Predicate import Predicate
from Products.ERP5.ExplanationCache import _getExplanationCache
import zope.interface import zope.interface
from zLOG import LOG from zLOG import LOG
class ExplanationCache:
"""ExplanationCache provides a central access to
all parameters and values which are needed to process
an explanation. It is based on the idea that a value is calculated
once and once only, as a way to accelerate performance of algorithms
related to an explanation.
'explanation_uid': self._getExplanationUidList(explanation) # XXX-JPS why do we need explanation_uid ? and why a list
'simulation_path': simulation_path,
explanation_uid = self._getExplanationUidList(explanation) # A hint value to reduce the size of the tree
simulation_path = '/erp5/p.../%' # A list of path
"""
def __init__(self, explanation):
"""
"""
self.explanation = explanation
def getRootExplanationUidList(self):
"""
"""
def getSimulationPathPatternList(self):
"""
"""
def _getExplanationCache(explanation):
# XXX-JPS Cache this in a transaction variable or better
return ExplanationCache(explanation)
class BusinessPath(Path, Predicate): class BusinessPath(Path, Predicate):
""" """
The BusinessPath class embeds all information related to The BusinessPath class embeds all information related to
...@@ -175,6 +145,12 @@ class BusinessPath(Path, Predicate): ...@@ -175,6 +145,12 @@ class BusinessPath(Path, Predicate):
#'destination_transport' #'destination_transport'
) )
# Helper Methods
def _getExplanationRelatedSimulationMovementValueList(self, explanation):
explanation_cache = _getExplanationCache(explanation)
return explanation_cache.getBusinessPathRelatedSimulationMovementValueList(self)
# XXX-JPS UNkonwn ?
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getArrowCategoryDict') 'getArrowCategoryDict')
def getArrowCategoryDict(self, context=None, **kw): # XXX-JPS do we need it in API ? def getArrowCategoryDict(self, context=None, **kw): # XXX-JPS do we need it in API ?
...@@ -271,6 +247,22 @@ class BusinessPath(Path, Predicate): ...@@ -271,6 +247,22 @@ class BusinessPath(Path, Predicate):
method_id = self.getCompletionDateMethodId() method_id = self.getCompletionDateMethodId()
method = getattr(movement, method_id) # We wish to raise if it does not exist method = getattr(movement, method_id) # We wish to raise if it does not exist
return method() return method()
def getCompletionDate(self, explanation):
"""Returns the date of completion of the movemnet
based on paremeters of the business path. This complete date can be
the start date, the stop date, the date of a given workflow transition
on the explaining delivery, etc.
XXX - DOC
movement -- a Simulation Movement
"""
date_list = []
for movement in self._getExplanationRelatedSimulationMovementValueList(explanation):
date_list.append(self.getMovementCompletionDate(movement))
return max(date_list)
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getExpectedQuantity') 'getExpectedQuantity')
...@@ -363,6 +355,15 @@ class BusinessPath(Path, Predicate): ...@@ -363,6 +355,15 @@ class BusinessPath(Path, Predicate):
return False return False
return True return True
def isDelivered(self, explanation):
"""XXX
"""
for simulation_movement in self._getExplanationRelatedSimulationMovementValueList(
explanation):
if not simulation_movement.getDelivery():
return False
return True
def build(self, explanation): def build(self, explanation):
"""Builds all related movements in the simulation using the builders """Builds all related movements in the simulation using the builders
defined on the Business Path. defined on the Business Path.
......
This diff is collapsed.
...@@ -51,12 +51,12 @@ class ExplanationCache: ...@@ -51,12 +51,12 @@ class ExplanationCache:
""" """
# Define share properties # Define share properties
self.explanation = explanation self.explanation = explanation
self.portal_catalog = getToolByName(explanation 'portal_catalog') self.portal_catalog = getToolByName(explanation, 'portal_catalog')
self.simulation_movement_cache = {} # Simulation Movement Cache self.simulation_movement_cache = {} # Simulation Movement Cache
self.explanation_uid_cache = [] self.explanation_uid_cache = []
self.explanation_path_pattern_cache = [] self.explanation_path_pattern_cache = []
def getDeliveryMovementList(self): def _getDeliveryMovementList(self):
"""Returns self is explanation is a delivery line """Returns self is explanation is a delivery line
of the list of explanation delivery lines if explanation of the list of explanation delivery lines if explanation
is a delivery is a delivery
...@@ -80,7 +80,7 @@ class ExplanationCache: ...@@ -80,7 +80,7 @@ class ExplanationCache:
return self.explanation_uid_cache return self.explanation_uid_cache
result = set() result = set()
# For each delivery movement # For each delivery movement
for movement in self.getDeliveryMovementList(): for movement in self._getDeliveryMovementList():
# For each simulation movement # For each simulation movement
for simulation_movement in movement.getDeliveryRelatedValueList(): for simulation_movement in movement.getDeliveryRelatedValueList():
result.add(simulation_movement.getExplanationUid()) # XXX-JPS use new API later result.add(simulation_movement.getExplanationUid()) # XXX-JPS use new API later
...@@ -117,7 +117,7 @@ class ExplanationCache: ...@@ -117,7 +117,7 @@ class ExplanationCache:
local_path_dict[simulation_movement_id] = simulation_movement local_path_dict[simulation_movement_id] = simulation_movement
# For each delivery movement # For each delivery movement
for movement in self.getDeliveryMovementList(): for movement in self._getDeliveryMovementList():
# For each simulation movement # For each simulation movement
for simulation_movement in movement.getDeliveryRelatedValueList(): for simulation_movement in movement.getDeliveryRelatedValueList():
updatePathDict(simulation_movement) updatePathDict(simulation_movement)
...@@ -133,7 +133,7 @@ class ExplanationCache: ...@@ -133,7 +133,7 @@ class ExplanationCache:
else: else:
browsePathDict('%s/%s' % (prefix, key), value) # Recursing with string append is slow XXX-JPS browsePathDict('%s/%s' % (prefix, key), value) # Recursing with string append is slow XXX-JPS
browsePathDict('', path_dict) browsePathDict('/', path_dict)
self.explanation_path_pattern_cache = result self.explanation_path_pattern_cache = result
return result return result
...@@ -143,7 +143,7 @@ class ExplanationCache: ...@@ -143,7 +143,7 @@ class ExplanationCache:
""" """
return self.getSimulationMovementList(causality_uid=business_path.getUid()) return self.getSimulationMovementList(causality_uid=business_path.getUid())
def getSimulationMovementList(self, **kw) def getSimulationMovementList(self, **kw):
"""Search Simulation Movements related to our explanation. """Search Simulation Movements related to our explanation.
Cache result so that the second time we saarch for the same Cache result so that the second time we saarch for the same
list we need not involve the catalog again. list we need not involve the catalog again.
...@@ -157,9 +157,48 @@ class ExplanationCache: ...@@ -157,9 +157,48 @@ class ExplanationCache:
**kw) **kw)
return self.simulation_movement_cache[kw_tuple] return self.simulation_movement_cache[kw_tuple]
def geBusinessPathClosure(business_path):
"""Creates a Business Process by filtering out all Business Path
in self which are not related to a simulation movement
which is either or parent or a child of explanation simulations movements
caused by 'business_path'
cache keys: business_path (simple) then path_set
XXX-JPS PSEUDO CODE
"""
new_business_process = BusinessProcess()
accepted_path = []
explanation_cache = _getExplanationCache(explanation)
path_list = explanation_cache.getSimulationPathPatternList()
path_list = map(lambda x:x[0:-1], path_list) # Remove trailing %
path_set = set()
for simulation_movement in business_path.\
_getExplanationRelatedSimulationMovementValueList(explanation):
simulation_path = simulation_movement.getPath()
for path in path_list:
if simulation_path.startswith(path):
path_set.add(path) # This selection path is part of explanation
for business_path in self.getBusinessPathValueList():
if business_path.hasMovementsIn(explanation, path_set):
accepted_path.append(business_path)
new_business_process.addValueList(business_path)
return new_business_process
def _getExplanationCache(explanation): def _getExplanationCache(explanation):
if explanation.isinstance(ExplanationCache):
return explanation
# Return cached value if any # Return cached value if any
tv = getTransactionalVariable(explanation) tv = getTransactionalVariable(explanation)
if tv.get('explanation_cache', None) is None: if tv.get('explanation_cache', None) is None:
tv['explanation_cache'] = ExplanationCache(explanation) tv['explanation_cache'] = ExplanationCache(explanation)
return tv.get('explanation_cache') return tv.get('explanation_cache')
def _getBusinessPathClosure(explanation, business_path):
"""Returns a
"""
explanation_cache = _getExplanationCache(explanation)
return explanation_cache.getBusinessPathClosure(business_path)
...@@ -59,6 +59,15 @@ class IBusinessPath(Interface): ...@@ -59,6 +59,15 @@ class IBusinessPath(Interface):
movement -- a Simulation Movement movement -- a Simulation Movement
""" """
def getCompletionDate(explanation):
"""Returns the date of completion of the movemnet
based on paremeters of the business path. This completion date can be
the start date, the stop date, the date of a given workflow transition
on the explaining delivery, etc.
XXXXXXXXXXXXXXXx
"""
def getExpectedQuantity(amount): def getExpectedQuantity(amount):
"""Returns the new quantity for the provided amount taking """Returns the new quantity for the provided amount taking
into account the efficiency or the quantity defined on the business path. into account the efficiency or the quantity defined on the business path.
...@@ -116,6 +125,10 @@ class IBusinessPath(Interface): ...@@ -116,6 +125,10 @@ class IBusinessPath(Interface):
not yet completed (ex. in 'delivered' state). not yet completed (ex. in 'delivered' state).
""" """
def isDelivered(explanation):
"""XXX
"""
def build(explanation): def build(explanation):
"""Builds all related movements in the simulation using the builders """Builds all related movements in the simulation using the builders
defined on the Business Path defined on the Business Path
......
...@@ -231,7 +231,7 @@ class ITradeStateProcess(Interface): ...@@ -231,7 +231,7 @@ class ITradeStateProcess(Interface):
implicitely defines a simulation subtree implicitely defines a simulation subtree
""" """
def getLatestPartiallyCompletedTradeState(explanation): def getLatestPartiallyCompletedTradeStateList(explanation):
"""Returns the list of completed trade states which predecessor """Returns the list of completed trade states which predecessor
states are completed and for which no successor state states are completed and for which no successor state
is partially completed in the context of given explanation. is partially completed in the context of given explanation.
......
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