Workflow transaction, return to last State

Lets say we have some Wordflow states

  1. Initial

  2. Checked
    3: SomethingElse

  3. Needs Check

If it is possible to make a transaction 1 -> 6, 2 -> 6 & 3 -> 6:

How can I (best) make a state that 'sends them back to their former state' from 6?
So, if someone 'did the check', added some info and ran transaction 'check_over', the state is returned is 'what it was 2 transactions ago'

You can inspect the complete history via History and versioning — Plone Documentation v4.3 and then you can decide what "go back" should do.

Will 'states' be available if versioning is not turned on (would prefer it) ?

I wouldn't think so, but you can try it :slight_smile:

I think what you called "3. Needs Check" must be 6, correct?

I probably would not try jumping around like that. Why not do a "needs check" between 1 and 2, and another between 2 and 3? Each such transition can still call the same underlying code or display the same forms.

Also, you could have these checking transitions verify preconditions. See Introduction To Workflows – Plone Workflow — Plone Training 2023 documentation

The workflow can also store variables, so you could keep your own "came from state" variable.

Hi, I was having a similar discussion: History and versioning — Plone Documentation v4.3

what I am trying to do is have an effective way to return to previous state. In today's WF, in transitions for the "Destination State" there is a ("Remain in State") in the pull down for destination state. This makes it easy to stay in state.

Why not have a "(Previous State") in the same pull-down? This option would have code associated with it that would look at the history and return to the previous state.

Right now, based on discussion in the above link, when i want to 'return' or 'reject' something to previous state, i have a unique transition for each: "return to submitted state", "reject to Closed state".

This will work; however, it is cumbersome and error prone.

Is my above suggestion practical?

There is also a state_change/getHistory expression that you can use. By default this is available to Reviewers.

See for example in the ZMI: http://localhost:8080/Plone/portal_workflow/simple_publication_workflow/variables/review_history/manage_properties

@mtrebron thanks, I'll look into that. I assume from the "getHistory" i could get the previous state.

Having an explicitly created transition means you can protect it with the usual security. Having a general "return to previous state" would perhaps make your application less securable because you wouldn't be able to say "allow role A to do that in state 3 but not in any other state". So "it depends" might be the correct answer here.

Slightly related:
With the transition: (remain in state), is any of this 'triggered'. Also, will such a (no) transition trigger 'content rules' etc?

If you can see a transition in the ZMI (portal_workflows->your_workflow->transitions) then all of those securing mechanisms are available.

The content rule trigger for state change would not be triggered, but the transition can be made to call whatever you want (explicitly).

Slightly off topic, but I want to test / check 'these things', so I add a script to run before (or after the transition).
It look to me that the scripts are not run anymore (Plone 6.1 Classic )

Please file an issue then if you can reproduce this, in Issues · plone/Products.CMFPlone · GitHub

I just cant figure out how to do this.

I am currently trying to do this in an event handler


From there, I have access to object and event

event has 'last_state', but that will be the 'the current state'

From object, I can get workflow_history


But I dont get how to list / find the last state from there dir(object.workflow_history)


Is there a way to check if a state is avalable for the current user?

Do do something like

 mytransaction = 'publish' # (or something else)
 if user_is_allowed_to_do_this_tranaction:
      api.content.transition(obj=object, transition= mytransaction)
    plone.api.portal.show_message(message='Not allowed',type='warning')

UPDATE: Probably this should be a 'guard' of the transaction instead.