Commit dfec1c6c authored by Jean-Paul Smets's avatar Jean-Paul Smets

Blind commit with various changes to make build work if erp5_bpm installed

git-svn-id: https://svn.erp5.org/repos/public/erp5/sandbox/amount_generator@37443 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent dc99420c
......@@ -4,7 +4,7 @@
# Copyright (c) 2009 Nexedi SA and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@nexedi.com>
# Yusuke Muraoka <yusuke@nexedi.com>
# Łukasz Nowak <luke@nexedi.com>
# ?ukasz Nowak <luke@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
......@@ -231,13 +231,15 @@ class BusinessLink(Path, Predicate):
implicitely defines a simulation subtree and a union
business process.
"""
LOG('Entering BusinessLink.isDelivered ',0, repr(explanation))
for simulation_movement in self._getExplanationRelatedSimulationMovementValueList(
explanation):
LOG('in isDelivered with ',0, repr(simulation_movement))
if not simulation_movement.getDelivery():
return False
return True
def build(self, explanation):
def build(self, explanation=None):
"""Builds all related movements in the simulation using the builders
defined on the Business Link.
......@@ -246,11 +248,8 @@ class BusinessLink(Path, Predicate):
business process.
"""
builder_list = self.getDeliveryBuilderValueList()
explanation_cache = _getExplanationCache(explanation)
for builder in builder_list:
for builder in builder_list: # XXX-JPS Do we really need a builder list ? wouldn't predicate be more useful ?
# Call build on each builder
# Provide 2 parameters: self and and explanation_cache
builder.build(select_method_dict={
'business_link': self,
'explanation_cache': explanation_cache,
})
LOG('Invoking Builder', 0, repr((builder, self, explanation)))
builder.build(explanation=explanation, business_link=self)
......@@ -37,6 +37,7 @@ from Products.ERP5.MovementCollectionDiff import _getPropertyAndCategoryList
import zope.interface
from zLOG import LOG
class BusinessProcess(Path, XMLObject):
"""The BusinessProcess class is a container class which is used
......@@ -129,9 +130,8 @@ class BusinessProcess(Path, XMLObject):
**kw -- same arguments as those passed to searchValues / contentValues
"""
if trade_phase is None:
trade_phase = set()
elif not isinstance(trade_phase, (list, tuple)):
if trade_phase is not None:
if not isinstance(trade_phase, (list, tuple)):
trade_phase = (trade_phase,)
trade_phase = set([x.split('trade_phase/', 1)[-1] \
for x in trade_phase])
......@@ -141,6 +141,12 @@ class BusinessProcess(Path, XMLObject):
if kw.get('sort_on', None) is None:
kw['sort_on'] = 'int_index'
original_path_list = self.objectValues(**kw) # Why Object Values ??? XXX-JPS
LOG('self', 0, repr(self))
LOG('objectValues', 0, repr(self.objectValues()))
LOG('portal_type', 0, repr(kw['portal_type']))
LOG('objectValues kw', 0, repr(self.objectValues(**kw)))
LOG('trade_phase', 0, trade_phase)
LOG('original_path_list', 0, original_path_list)
# Separate the selection of trade model paths into two steps
# for easier debugging.
# First, collect trade model paths which can be applicable to a given context.
......@@ -151,6 +157,7 @@ class BusinessProcess(Path, XMLObject):
accept_path = False # Filter our business path which trade phase does not match
if accept_path:
path_list.append(path)
LOG('path_list', 0, path_list)
# Then, filter trade model paths by Predicate API.
# FIXME: Ideally, we should use the Domain Tool to search business paths,
# and avoid using the low level Predicate API. But the Domain Tool does
......@@ -158,6 +165,7 @@ class BusinessProcess(Path, XMLObject):
for path in path_list:
if path.test(context):
result.append(path)
LOG('result', 0, result)
return result
security.declareProtected(Permissions.AccessContentsInformation, 'getExpectedTradeModelPathStartAndStopDate')
......@@ -189,6 +197,7 @@ class BusinessProcess(Path, XMLObject):
raise ValueError('a reference date method must be defined on every Trade Model Path')
explanation_cache = _getExplanationCache(explanation)
LOG('calling explanation_cache.getReferenceDate', 0, '%s %s %s %s' % (explanation, self, trade_date, reference_date_method_id))
reference_date = explanation_cache.getReferenceDate(self, trade_date, reference_date_method_id)
# Computer start_date and stop_date (XXX-JPS this could be cached and accelerated)
......@@ -221,9 +230,8 @@ class BusinessProcess(Path, XMLObject):
**kw -- same arguments as those passed to searchValues / contentValues
"""
if trade_phase is None:
trade_phase = set()
elif not isinstance(trade_phase, (list, tuple)):
if trade_phase is not None:
if not isinstance(trade_phase, (list, tuple)):
trade_phase = set((trade_phase,))
else:
trade_phase = set(trade_phase)
......@@ -251,6 +259,10 @@ class BusinessProcess(Path, XMLObject):
# FIXME: Ideally, we should use the Domain Tool to search business links,
# and avoid using the low level Predicate API. But the Domain Tool does
# support the condition above without scripting?
LOG('business_link_list', 0, repr(business_link_list))
if context is None:
LOG('context is None', 0, repr(business_link_list))
return business_link_list
for business_link in business_link_list:
if business_link.test(context):
result.append(business_link)
......@@ -266,6 +278,7 @@ class BusinessProcess(Path, XMLObject):
business_link -- a Business Link document
"""
LOG('In isBusinessLinkCompleted', 0, repr(business_link))
# Return False if Business Link is not completed
if not business_link.isCompleted(explanation):
return False
......@@ -365,12 +378,14 @@ class BusinessProcess(Path, XMLObject):
business_link -- a Business Link document
"""
# If everything is delivered, no need to build
LOG('In isBusinessLinkBuildable', 0, repr(business_link))
if business_link.isDelivered(explanation):
LOG('In isBusinessLinkBuildable', 0, 'business link is delivered and thus False')
return False
# We must take the closure cause only way to combine business process
closure_process = _getBusinessLinkClosure(self, explanation, business_link)
predecessor = business_link.getPredecessor()
return closure_process.isTradeStateCompleted(predecessor)
return closure_process.isTradeStateCompleted(explanation, predecessor)
security.declareProtected(Permissions.AccessContentsInformation, 'isBusinessLinkPartiallyBuildable')
def isBusinessLinkPartiallyBuildable(self, explanation, business_link):
......@@ -523,8 +538,10 @@ class BusinessProcess(Path, XMLObject):
trade_state -- a Trade State category
"""
LOG('In isTradeStateCompleted', 0, repr(trade_state))
for business_link in self.getBusinessLinkValueList(successor=trade_state):
if not self.isBusinessLinkCompleted(explanation, business_link):
LOG('A business link is not completed', 0, repr(business_link))
return False
return True
......@@ -693,6 +710,9 @@ class BusinessProcess(Path, XMLObject):
kw = self._getPropertyAndCategoryDict(explanation, amount, trade_model_path, delay_mode=delay_mode)
kw.update(update_property_dict)
movement._edit(**kw)
business_link = self.getBusinessLinkValueList(trade_phase=trade_phase, context=movement)
business_link = map(lambda x: x.getRelativeUrl(), business_link)
movement._setCausalityList(business_link + movement.getCausalityList())
result.append(movement)
# result can not be empty
......@@ -781,6 +801,7 @@ class BusinessProcess(Path, XMLObject):
# Set causality to trade model path
property_dict['causality'] = trade_model_path.getRelativeUrl() # XXX-JPS Will not work if we do not use real object
#(ie. if we use kind of 'temp')
# Set trade_phase to the trade phase of trade_model_path
property_dict['trade_phase'] = trade_model_path.getTradePhase()
......@@ -826,5 +847,6 @@ class BusinessProcess(Path, XMLObject):
"""
Build whatever is buildable
"""
LOG('In business process build', 0, repr(explanation))
for business_link in self.getBuildableBusinessLinkValueList(explanation):
business_link.build(explanation)
business_link.build(explanation=explanation)
......@@ -586,7 +586,7 @@ class SimulationMovement(Movement, PropertyRecordableMixin, ExplainableMixin):
if business_link is None or explanation_value is None:
return True
predecessor_state = business_path.getPredecessorValue()
predecessor_state = business_link.getPredecessorValue()
if predecessor_state is None:
# first one, can be built
return True # XXX-JPS wrong cause root is marked
......
......@@ -64,8 +64,8 @@ class ExplanationCache:
self.union_cache = None
def _getDeliveryMovementList(self):
"""Returns self is explanation is a delivery line
of the list of explanation delivery lines if explanation
"""Returns self if explanation is a delivery line
or the list of explanation delivery lines if explanation
is a delivery
"""
explanation = self.explanation
......@@ -92,8 +92,8 @@ class ExplanationCache:
for simulation_movement in movement.getDeliveryRelatedValueList():
result.add(simulation_movement.getExplanationUid()) # XXX-JPS use new API later
# Return result
self.explanation_uid_cache = result
return tuple(result)
self.explanation_uid_cache = tuple(result)
return self.explanation_uid_cache
def getSimulationPathPatternList(self):
"""Return the list of root path of simulation tree which are
......@@ -119,6 +119,8 @@ class ExplanationCache:
simulation_movement_id = simulation_movement.getId()
insert_movement = True
for path_id in container_path:
LOG('path_dict', 0, repr(path_dict))
LOG('local_path_dict', 0, repr(local_path_dict))
local_path_dict = local_path_dict.setdefault(path_id, {})
if type(local_path_dict) is not types.DictType:
# A movement was already inserted
......@@ -126,6 +128,7 @@ class ExplanationCache:
break
if insert_movement:
local_path_dict[simulation_movement_id] = simulation_movement
LOG('path_dict result', 0, repr(path_dict))
# For each delivery movement
for movement in self._getDeliveryMovementList():
......@@ -137,15 +140,21 @@ class ExplanationCache:
# assembling path '/erp5/portal_simulation/1/34/23/43%'
result = []
def browsePathDict(prefix, local_path_dict):
LOG('browsePathDict result in', 0, repr(result))
LOG('browsePathDict local_path_dict in', 0, repr(local_path_dict))
for key, value in local_path_dict.items():
if type(value) is not types.DictType:
# We have a real root
result.append('%s/%s%' % (prefix, key))
result.append('%s/%s' % (prefix, key))
result.append('%s/%s/%%' % (prefix, key))
# XXX-JPS here we must add all parent movements XXX-JPS
else:
browsePathDict('%s/%s' % (prefix, key), value) # Recursing with string append is slow XXX-JPS
LOG('browsePathDict result out', 0, repr(result))
browsePathDict('/', path_dict)
# path_dict is typically like this:
# {'': {'erp5': {'portal_simulation': {'3': {'4': <SimulationMovement at /erp5/portal_simulation/3/4>}}}}}
browsePathDict('', path_dict[''])
self.explanation_path_pattern_cache = result
return result
......@@ -204,6 +213,7 @@ class ExplanationCache:
kw['path'] = self.getSimulationPathPatternList() # XXX-JPS Explicit Query is better
if kw.get('explanation_uid', None) is None:
kw['explanation_uid'] = self.getRootExplanationUidList()
LOG('lookup movements', 0, repr(kw))
self.simulation_movement_cache[kw_tuple] = \
self.portal_catalog(portal_type="Simulation Movement",
**kw)
......@@ -308,6 +318,7 @@ class ExplanationCache:
tv = getTransactionalVariable(self)
reference_date_key = (trade_phase, reference_date_method_id, delay_mode, business_process.getPhysicalPath())
reference_date_key = repr(reference_date_key)
LOG('key', 0, reference_date_key)
if tv.get(reference_date_key, _UNDEFINED) is _UNDEFINED:
tv[reference_date_key] = _INFINITE_LOOP
else:
......@@ -334,6 +345,7 @@ class ExplanationCache:
# whenever trade model path define time constraints within the same
# movement generator (ie. transformation with multiple phases)
path_list = business_process.getTradeModelPathValueList(trade_phase=trade_phase)
LOG('path_list', 0, '%s' % trade_phase)
if not len(path_list):
raise ValueError('No Trade Model Path defines a reference data.')
......
......@@ -102,6 +102,8 @@ class MovementGeneratorMixin:
result = []
folder = self._applied_rule
# Build a list of movement and business path
LOG('_getInputMovementList', 0, repr(self._getInputMovementList(movement_list=movement_list,
rounding=rounding)))
for input_movement in self._getInputMovementList(movement_list=movement_list,
rounding=rounding):
# Merge movement and business path properties (core implementation)
......@@ -109,7 +111,6 @@ class MovementGeneratorMixin:
business_process = input_movement.asComposedDocument()
explanation = self._applied_rule # We use applied rule as local explanation
trade_phase = self._getTradePhaseList(input_movement, business_process) # XXX-JPS not convenient to handle
# XXX-JPS trade phase of movement should be provided by movement
update_property_dict = self._getUpdatePropertyDict(input_movement)
result.extend(business_process.getTradePhaseMovementList(explanation, input_movement,
trade_phase=trade_phase, delay_mode=None,
......
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