Commit 9e2ab8fb authored by Sebastien Robin's avatar Sebastien Robin

* Move mosts methods of BusinessState to Business Process

* remove usage of business states in testBPMCore
* modify BusinessPath in order to work with successor
  and predecessor as categories instead of business state

git-svn-id: https://svn.erp5.org/repos/public/erp5/sandbox/amount_generator@34839 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 7a6edd5d
...@@ -251,7 +251,7 @@ class BusinessPath(Path, Predicate): ...@@ -251,7 +251,7 @@ class BusinessPath(Path, Predicate):
# #
# Such cases are Business Processes using sequence not related # Such cases are Business Processes using sequence not related
# to simulation tree with much of compensations # to simulation tree with much of compensations
if predecessor.isPartiallyCompleted(explanation): if self.isStatePartiallyCompleted(explanation, predecessor):
return result return result
return False return False
...@@ -437,14 +437,16 @@ class BusinessPath(Path, Predicate): ...@@ -437,14 +437,16 @@ class BusinessPath(Path, Predicate):
if predecessor_date is None: if predecessor_date is None:
node = self.getPredecessorValue() node = self.getPredecessorValue()
if node is not None: if node is not None:
predecessor_date = node.getExpectedCompletionDate(explanation, *args, **kwargs) predecessor_date = self.getParentValue().getExpectedStateCompletionDate(
explanation, node, *args, **kwargs)
if predecessor_date is not None: if predecessor_date is not None:
return predecessor_date + self.getWaitTime() return predecessor_date + self.getWaitTime()
def _getSuccessorExpectedStartDate(self, explanation, *args, **kwargs): def _getSuccessorExpectedStartDate(self, explanation, *args, **kwargs):
node = self.getSuccessorValue() node = self.getSuccessorValue()
if node is not None: if node is not None:
expected_date = node.getExpectedBeginningDate(explanation, *args, **kwargs) expected_date = self.getParentValue().getExpectedStateBeginningDate(
explanation, node, *args, **kwargs)
if expected_date is not None: if expected_date is not None:
return expected_date - self.getLeadTime() return expected_date - self.getLeadTime()
...@@ -474,14 +476,16 @@ class BusinessPath(Path, Predicate): ...@@ -474,14 +476,16 @@ class BusinessPath(Path, Predicate):
def _getPredecessorExpectedStopDate(self, explanation, *args, **kwargs): def _getPredecessorExpectedStopDate(self, explanation, *args, **kwargs):
node = self.getPredecessorValue() node = self.getPredecessorValue()
if node is not None: if node is not None:
expected_date = node.getExpectedCompletionDate(explanation, *args, **kwargs) expected_date = self.getParentValue().getExpectedStateCompletionDate(
explanation, node, *args, **kwargs)
if expected_date is not None: if expected_date is not None:
return expected_date + self.getWaitTime() + self.getLeadTime() return expected_date + self.getWaitTime() + self.getLeadTime()
def _getSuccessorExpectedStopDate(self, explanation, *args, **kwargs): def _getSuccessorExpectedStopDate(self, explanation, *args, **kwargs):
node = self.getSuccessorValue() node = self.getSuccessorValue()
if node is not None: if node is not None:
return node.getExpectedBeginningDate(explanation, *args, **kwargs) return self.getParentValue().getExpectedStateBeginningDate(
explanation, node, *args, **kwargs)
def _getExpectedDate(self, explanation, root_explanation_method, def _getExpectedDate(self, explanation, root_explanation_method,
predecessor_method, successor_method, predecessor_method, successor_method,
......
...@@ -256,3 +256,121 @@ class BusinessProcess(Path, XMLObject): ...@@ -256,3 +256,121 @@ class BusinessProcess(Path, XMLObject):
for next_path in node.getPredecessorRelatedValueList(): for next_path in node.getPredecessorRelatedValueList():
_list += self._getHeadPathValueList(next_path, trade_phase_set) _list += self._getHeadPathValueList(next_path, trade_phase_set)
return _list return _list
def getRemainingTradePhaseList(self, explanation, trade_state, trade_phase_list=None):
"""
Returns the list of remaining trade phase for this
state based on the explanation.
trade_phase_list -- if provide, the result is filtered by it after collected
"""
remaining_trade_phase_list = []
for path in [x for x in self.objectValues(portal_type="Business Path") \
if x.getPredecessorValue() == trade_state]:
# XXX When no simulations related to path, what should path.isCompleted return?
# if True we don't have way to add remaining trade phases to new movement
if not (path.getRelatedSimulationMovementValueList(explanation) and
path.isCompleted(explanation)):
remaining_trade_phase_list += path.getTradePhaseValueList()
# collect to successor direction recursively
state = path.getSuccessorValue()
if state is not None:
remaining_trade_phase_list.extend(
self.getRemainingTradePhaseList(explanation, state, None))
# filter just at once if given
if trade_phase_list is not None:
remaining_trade_phase_list = filter(
lambda x : x.getLogicalPath() in trade_phase_list,
remaining_trade_phase_list)
return remaining_trade_phase_list
def isStatePartiallyCompleted(self, explanation, trade_state):
"""
If all path which reach this state are partially completed
then this state is completed
"""
for path in [x for x in self.objectValues(portal_type="Business Path") \
if x.getSuccessorValue() == trade_state]:
if not path.isPartiallyCompleted(explanation):
return False
return True
def getExpectedStateCompletionDate(self, explanation, trade_state, *args, **kwargs):
"""
Returns the expected completion date for this
state based on the explanation.
explanation -- the document
"""
# Should be re-calculated?
# XXX : what is the purpose of the two following lines ? comment it until there is
# good answer
if 'predecessor_date' in kwargs:
del kwargs['predecessor_date']
successor_list = [x for x in self.objectValues(portal_type="Business Path") \
if x.getSuccessorValue() == trade_state]
date_list = self._getExpectedDateList(explanation,
successor_list,
self._getExpectedCompletionDate,
*args,
**kwargs)
if len(date_list) > 0:
return min(date_list)
def getExpectedStateBeginningDate(self, explanation, trade_state, *args, **kwargs):
"""
Returns the expected beginning date for this
state based on the explanation.
explanation -- the document
"""
# Should be re-calculated?
# XXX : what is the purpose of the two following lines ? comment it until there is
# good answer
if 'predecessor_date' in kwargs:
del kwargs['predecessor_date']
predecessor_list = [x for x in self.objectValues(portal_type="Business Path") \
if x.getPredecessorValue() == trade_state]
date_list = self._getExpectedDateList(explanation,
predecessor_list,
self._getExpectedBeginningDate,
*args,
**kwargs)
if len(date_list) > 0:
return min(date_list)
def _getExpectedBeginningDate(self, path, *args, **kwargs):
expected_date = path.getExpectedStartDate(*args, **kwargs)
if expected_date is not None:
return expected_date - path.getWaitTime()
def _getExpectedDateList(self, explanation, path_list, path_method,
visited=None, *args, **kwargs):
"""
getExpected(Beginning/Completion)Date are same structure
expected date of each path should be returned.
explanation -- the document
path_list -- list of target business path
path_method -- used to get expected date on each path
visited -- only used to prevent infinite recursion internally
"""
if visited is None:
visited = []
expected_date_list = []
for path in path_list:
# filter paths without path of root explanation
if path not in visited or path.isDeliverable():
expected_date = path_method(path, explanation, visited=visited, *args, **kwargs)
if expected_date is not None:
expected_date_list.append(expected_date)
return expected_date_list
def _getExpectedCompletionDate(self, path, *args, **kwargs):
return path.getExpectedStopDate(*args, **kwargs)
...@@ -68,6 +68,9 @@ class TestBPMMixin(ERP5TypeTestCase): ...@@ -68,6 +68,9 @@ class TestBPMMixin(ERP5TypeTestCase):
self.createCategoriesInCategory(category_tool.trade_phase, ['default',]) self.createCategoriesInCategory(category_tool.trade_phase, ['default',])
self.createCategoriesInCategory(category_tool.trade_phase.default, self.createCategoriesInCategory(category_tool.trade_phase.default,
['accounting', 'delivery', 'invoicing', 'discount', 'tax', 'payment']) ['accounting', 'delivery', 'invoicing', 'discount', 'tax', 'payment'])
self.createCategoriesInCategory(category_tool.trade_state,
['ordered', 'invoiced', 'delivered',
'state_a', 'state_b', 'state_c', 'state_d', 'state_e'])
@reindex @reindex
def createBusinessProcess(self, **kw): def createBusinessProcess(self, **kw):
...@@ -88,14 +91,6 @@ class TestBPMMixin(ERP5TypeTestCase): ...@@ -88,14 +91,6 @@ class TestBPMMixin(ERP5TypeTestCase):
portal_type=self.business_path_portal_type, **kw) portal_type=self.business_path_portal_type, **kw)
return business_path return business_path
@reindex
def createBusinessState(self, business_process=None, **kw):
if business_process is None:
business_process = self.createBusinessProcess()
business_path = business_process.newContent(
portal_type=self.business_state_portal_type, **kw)
return business_path
def createMovement(self): def createMovement(self):
# returns a movement for testing # returns a movement for testing
applied_rule = self.portal.portal_simulation.newContent( applied_rule = self.portal.portal_simulation.newContent(
...@@ -348,17 +343,18 @@ class TestBPMImplementation(TestBPMMixin): ...@@ -348,17 +343,18 @@ class TestBPMImplementation(TestBPMMixin):
c c
""" """
# define business process # define business process
category_tool = self.getCategoryTool()
business_process = self.createBusinessProcess() business_process = self.createBusinessProcess()
business_path_a_b = self.createBusinessPath(business_process) business_path_a_b = self.createBusinessPath(business_process)
business_path_b_c = self.createBusinessPath(business_process) business_path_b_c = self.createBusinessPath(business_process)
business_path_b_d = self.createBusinessPath(business_process) business_path_b_d = self.createBusinessPath(business_process)
business_path_c_d = self.createBusinessPath(business_process) business_path_c_d = self.createBusinessPath(business_process)
business_path_d_e = self.createBusinessPath(business_process) business_path_d_e = self.createBusinessPath(business_process)
business_state_a = self.createBusinessState(business_process) business_state_a = category_tool.trade_state.state_a
business_state_b = self.createBusinessState(business_process) business_state_b = category_tool.trade_state.state_b
business_state_c = self.createBusinessState(business_process) business_state_c = category_tool.trade_state.state_c
business_state_d = self.createBusinessState(business_process) business_state_d = category_tool.trade_state.state_d
business_state_e = self.createBusinessState(business_process) business_state_e = category_tool.trade_state.state_e
business_path_a_b.setPredecessorValue(business_state_a) business_path_a_b.setPredecessorValue(business_state_a)
business_path_b_c.setPredecessorValue(business_state_b) business_path_b_c.setPredecessorValue(business_state_b)
business_path_b_d.setPredecessorValue(business_state_b) business_path_b_d.setPredecessorValue(business_state_b)
...@@ -376,11 +372,6 @@ class TestBPMImplementation(TestBPMMixin): ...@@ -376,11 +372,6 @@ class TestBPMImplementation(TestBPMMixin):
business_path_b_d.edit(title="b_d") business_path_b_d.edit(title="b_d")
business_path_c_d.edit(title="c_d") business_path_c_d.edit(title="c_d")
business_path_d_e.edit(title="d_e") business_path_d_e.edit(title="d_e")
business_state_a.edit(title="a")
business_state_b.edit(title="b")
business_state_c.edit(title="c")
business_state_d.edit(title="d")
business_state_e.edit(title="e")
# set trade_phase # set trade_phase
business_path_a_b.edit(trade_phase=['default/discount'], business_path_a_b.edit(trade_phase=['default/discount'],
...@@ -427,23 +418,27 @@ class TestBPMImplementation(TestBPMMixin): ...@@ -427,23 +418,27 @@ class TestBPMImplementation(TestBPMMixin):
trade_phase.invoicing, trade_phase.invoicing,
trade_phase.payment, trade_phase.payment,
trade_phase.accounting]), trade_phase.accounting]),
set(business_state_a.getRemainingTradePhaseList(order))) set(business_process.getRemainingTradePhaseList(order,
business_state_a)))
self.assertEquals(set([trade_phase.delivery, self.assertEquals(set([trade_phase.delivery,
trade_phase.invoicing, trade_phase.invoicing,
trade_phase.payment, trade_phase.payment,
trade_phase.accounting]), trade_phase.accounting]),
set(business_state_b.getRemainingTradePhaseList(order))) set(business_process.getRemainingTradePhaseList(order,
business_state_b)))
self.assertEquals(set([trade_phase.payment, self.assertEquals(set([trade_phase.payment,
trade_phase.accounting]), trade_phase.accounting]),
set(business_state_c.getRemainingTradePhaseList(order))) set(business_process.getRemainingTradePhaseList(order,
business_state_c)))
self.assertEquals(set([trade_phase.accounting]), self.assertEquals(set([trade_phase.accounting]),
set(business_state_d.getRemainingTradePhaseList(order))) set(business_process.getRemainingTradePhaseList(order,
business_state_d)))
# when trade_phase_list is defined in arguments, the result is filtered by base category. # when trade_phase_list is defined in arguments, the result is filtered by base category.
self.assertEquals(set([trade_phase.delivery, self.assertEquals(set([trade_phase.delivery,
trade_phase.accounting]), trade_phase.accounting]),
set(business_state_a\ set(business_process\
.getRemainingTradePhaseList(order, .getRemainingTradePhaseList(order, business_state_a,
trade_phase_list=['default/delivery', trade_phase_list=['default/delivery',
'default/accounting']))) 'default/accounting'])))
...@@ -473,17 +468,18 @@ class TestBPMImplementation(TestBPMMixin): ...@@ -473,17 +468,18 @@ class TestBPMImplementation(TestBPMMixin):
c c
""" """
# define business process # define business process
category_tool = self.getCategoryTool()
business_process = self.createBusinessProcess() business_process = self.createBusinessProcess()
business_path_a_b = self.createBusinessPath(business_process) business_path_a_b = self.createBusinessPath(business_process)
business_path_b_c = self.createBusinessPath(business_process) business_path_b_c = self.createBusinessPath(business_process)
business_path_b_d = self.createBusinessPath(business_process) business_path_b_d = self.createBusinessPath(business_process)
business_path_c_d = self.createBusinessPath(business_process) business_path_c_d = self.createBusinessPath(business_process)
business_path_d_e = self.createBusinessPath(business_process) business_path_d_e = self.createBusinessPath(business_process)
business_state_a = self.createBusinessState(business_process) business_state_a = category_tool.trade_state.state_a
business_state_b = self.createBusinessState(business_process) business_state_b = category_tool.trade_state.state_b
business_state_c = self.createBusinessState(business_process) business_state_c = category_tool.trade_state.state_c
business_state_d = self.createBusinessState(business_process) business_state_d = category_tool.trade_state.state_d
business_state_e = self.createBusinessState(business_process) business_state_e = category_tool.trade_state.state_e
business_path_a_b.setPredecessorValue(business_state_a) business_path_a_b.setPredecessorValue(business_state_a)
business_path_b_c.setPredecessorValue(business_state_b) business_path_b_c.setPredecessorValue(business_state_b)
business_path_b_d.setPredecessorValue(business_state_b) business_path_b_d.setPredecessorValue(business_state_b)
...@@ -496,11 +492,6 @@ class TestBPMImplementation(TestBPMMixin): ...@@ -496,11 +492,6 @@ class TestBPMImplementation(TestBPMMixin):
business_path_d_e.setSuccessorValue(business_state_e) business_path_d_e.setSuccessorValue(business_state_e)
business_process.edit(referential_date='stop_date') business_process.edit(referential_date='stop_date')
business_state_a.edit(title='a')
business_state_b.edit(title='b')
business_state_c.edit(title='c')
business_state_d.edit(title='d')
business_state_e.edit(title='e')
business_path_a_b.edit(title='a_b', lead_time=2, wait_time=1) business_path_a_b.edit(title='a_b', lead_time=2, wait_time=1)
business_path_b_c.edit(title='b_c', lead_time=2, wait_time=1) business_path_b_c.edit(title='b_c', lead_time=2, wait_time=1)
business_path_b_d.edit(title='b_d', lead_time=3, wait_time=1) business_path_b_d.edit(title='b_d', lead_time=3, wait_time=1)
...@@ -635,9 +626,10 @@ class TestBPMDummyDeliveryMovementMixin(TestBPMMixin): ...@@ -635,9 +626,10 @@ class TestBPMDummyDeliveryMovementMixin(TestBPMMixin):
def _createOrderedDeliveredInvoicedBusinessProcess(self): def _createOrderedDeliveredInvoicedBusinessProcess(self):
# simple business process preparation # simple business process preparation
business_process = self.createBusinessProcess() business_process = self.createBusinessProcess()
ordered = self.createBusinessState(business_process) category_tool = self.getCategoryTool()
delivered = self.createBusinessState(business_process) ordered = category_tool.trade_state.ordered
invoiced = self.createBusinessState(business_process) delivered = category_tool.trade_state.delivered
invoiced = category_tool.trade_state.invoiced
# path which is completed, as soon as related simulation movements are in # path which is completed, as soon as related simulation movements are in
# proper state # proper state
...@@ -660,9 +652,10 @@ class TestBPMDummyDeliveryMovementMixin(TestBPMMixin): ...@@ -660,9 +652,10 @@ class TestBPMDummyDeliveryMovementMixin(TestBPMMixin):
def _createOrderedInvoicedDeliveredBusinessProcess(self): def _createOrderedInvoicedDeliveredBusinessProcess(self):
business_process = self.createBusinessProcess() business_process = self.createBusinessProcess()
ordered = self.createBusinessState(business_process) category_tool = self.getCategoryTool()
delivered = self.createBusinessState(business_process) ordered = category_tool.trade_state.ordered
invoiced = self.createBusinessState(business_process) delivered = category_tool.trade_state.delivered
invoiced = category_tool.trade_state.invoiced
self.order_path = self.createBusinessPath(business_process, self.order_path = self.createBusinessPath(business_process,
successor_value = ordered, successor_value = ordered,
......
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