# HG changeset patch # User Sylvain Thénault # Date 1266568586 -3600 # Node ID 021035b9a7ab39f9bae67fe732734b99fee695ee # Parent 921737d2e3a87462e9a23d24d094f10e864b9935 introduce 'go back' transition: transition without destination state will go to the state we were coming from diff -r 921737d2e3a8 -r 021035b9a7ab entities/test/unittest_wfobjs.py --- a/entities/test/unittest_wfobjs.py Fri Feb 19 09:34:14 2010 +0100 +++ b/entities/test/unittest_wfobjs.py Fri Feb 19 09:36:26 2010 +0100 @@ -98,7 +98,7 @@ trs = list(user.possible_transitions()) self.assertEquals(len(trs), 1) self.assertEquals(trs[0].name, u'deactivate') - self.assertEquals(trs[0].destination().name, u'deactivated') + self.assertEquals(trs[0].destination(None).name, u'deactivated') # test a std user get no possible transition cnx = self.login('member') # fetch the entity using the new session @@ -141,6 +141,27 @@ trinfo = self._test_manager_deactivate(user) self.assertEquals(trinfo.transition.name, 'deactivate') + def test_goback_transition(self): + wf = self.session.user.current_workflow + asleep = wf.add_state('asleep') + wf.add_transition('rest', (wf.state_by_name('activated'), wf.state_by_name('deactivated')), + asleep) + wf.add_transition('wake up', asleep) + user = self.create_user('stduser') + user.fire_transition('rest') + self.commit() + user.fire_transition('wake up') + self.commit() + self.assertEquals(user.state, 'activated') + user.fire_transition('deactivate') + self.commit() + user.fire_transition('rest') + self.commit() + user.fire_transition('wake up') + self.commit() + user.clear_all_caches() + self.assertEquals(user.state, 'deactivated') + # XXX test managers can change state without matching transition def _test_stduser_deactivate(self): @@ -207,7 +228,7 @@ state3 = mwf.add_state(u'state3') swftr1 = mwf.add_wftransition(u'swftr1', swf, state1, [(swfstate2, state2), (swfstate3, state3)]) - self.assertEquals(swftr1.destination().eid, swfstate1.eid) + self.assertEquals(swftr1.destination(None).eid, swfstate1.eid) # workflows built, begin test self.group = self.request().create_entity('CWGroup', name=u'grp1') self.commit() diff -r 921737d2e3a8 -r 021035b9a7ab entities/wfobjs.py --- a/entities/wfobjs.py Fri Feb 19 09:34:14 2010 +0100 +++ b/entities/wfobjs.py Fri Feb 19 09:36:26 2010 +0100 @@ -256,8 +256,12 @@ """customized class for Transition entities""" __regid__ = 'Transition' - def destination(self): - return self.destination_state[0] + def destination(self, entity): + try: + return self.destination_state[0] + except IndexError: + return entity.latest_trinfo().previous_state + def parent(self): return self.workflow diff -r 921737d2e3a8 -r 021035b9a7ab hooks/workflow.py --- a/hooks/workflow.py Fri Feb 19 09:34:14 2010 +0100 +++ b/hooks/workflow.py Fri Feb 19 09:36:26 2010 +0100 @@ -232,7 +232,7 @@ raise ValidationError(entity.eid, {'by_transition': msg}) if entity.get('to_state'): deststateeid = entity['to_state'] - if not cowpowers and deststateeid != tr.destination().eid: + if not cowpowers and deststateeid != tr.destination(forentity).eid: msg = session._("transition isn't allowed") raise ValidationError(entity.eid, {'by_transition': msg}) if swtr is None: @@ -241,7 +241,7 @@ msg = session._("state doesn't belong to entity's workflow") raise ValidationError(entity.eid, {'to_state': msg}) else: - deststateeid = tr.destination().eid + deststateeid = tr.destination(forentity).eid # everything is ok, add missing information on the trinfo entity entity['from_state'] = fromstate.eid entity['to_state'] = deststateeid diff -r 921737d2e3a8 -r 021035b9a7ab misc/migration/3.6.1_Any.py --- a/misc/migration/3.6.1_Any.py Fri Feb 19 09:34:14 2010 +0100 +++ b/misc/migration/3.6.1_Any.py Fri Feb 19 09:36:26 2010 +0100 @@ -1,1 +1,2 @@ sync_schema_props_perms(syncprops=False) +sync_schema_props_perms('destination_state', syncperms=False) diff -r 921737d2e3a8 -r 021035b9a7ab schemas/workflow.py --- a/schemas/workflow.py Fri Feb 19 09:34:14 2010 +0100 +++ b/schemas/workflow.py Fri Feb 19 09:36:26 2010 +0100 @@ -97,12 +97,13 @@ class Transition(BaseTransition): """use to define a transition from one or multiple states to a destination - states in workflow's definitions. + states in workflow's definitions. Transition without destination state will + go back to the state from which we arrived to the current state. """ __specializes_schema__ = True destination_state = SubjectRelation( - 'State', cardinality='1*', + 'State', cardinality='?*', constraints=[RQLConstraint('S transition_of WF, O state_of WF', msg=_('state and transition don\'t belong the the same workflow'))], description=_('destination state for this transition'))