[How To] Catch Workflow State Change - Event Trigger

Hi,

i am trying catch workflow state change, because i need disable / not permit / specific workflow state change to user. It can’t be done through user role in my case.

I am trying catch Transition 1 - from Pending to Approved

I created workflow like this:

And I am trying catch workflow in JS:

 validate: function (frm) {	
		console.log(frm.doc.workflow_state);
		console.log("validate");
    },

	after_save: function (frm) {
		console.log(frm.doc.workflow_state);
		console.log("after save");
    },
    workflow_state: function (frm) {
		console.log(frm.doc.workflow_state);
		console.log("workflow_state_change");

    }

and in python also:

def validate(self):
	frappe.msgprint(frappe._("validate!"))
def on_update(self):
	frappe.msgprint(frappe._("update!"))

But any of this event is not triggered. How can i catch this? Thank you very much.

ERPNext: v11.0.3-beta.17 () (develop)
Frappe Framework: v11.0.3-beta.19 () (develop)

You need to use hooks to trigger events at the target DocType you want to control… https://frappe.io/docs/user/en/guides/basics/hooks (see section on Document Hooks)

Hi,

thanks for your answer. But i need to catch workflow state change. How can I do that with hook?

I need to run ideally python (or js - but python is more secure) code when workflow state is changed. This happens when user click on wokflow button Approve. I need to check if user can approve this specific doc. (this is based on custom logic)

Thanks.

@rmehta can you help? Or It is not clear?

THANKS

A search on ‘workflow_state’ ‘change’ and ‘transition’ turns up for eg these for ideas

Hi,
@clarkej thanks for your answer, in these threads is written that workflow state change will trigger validate event.

Here is gif, where in validate event is console.log, but event is not triggered:

https://imgur.com/aLXgmNp

Maybe I miss something. Am I doing something wrong?

I think workflow action (approve, reject…) doesn’t trigger form event, but it should trigger def on_update(self) in python file because workflow itself apply hook on on_update as well.

1 Like

To identify what is going on, set a breakpoint in the client side code for example here:

./sites/assets/js/form.min.js: function () { return this$1.script_manager.trigger(“before_save”); },

Follow this howto Chrome DevTools  |  Chrome for Developers

This notes events to check out

To set a breakpoint on the server add this line import pdb; pbd.set_trace()

Here’s how 9. The Python Debugger

./apps/frappe/frappe/model/document.py: def run_before_save_methods(self):
./apps/frappe/frappe/model/document.py: - validate, before_save for Save.
./apps/frappe/frappe/model/document.py: self.load_doc_before_save()
./apps/frappe/frappe/model/document.py: self.run_method(“before_save”)

1 Like

Hi,

so I solved it. As @magic-overflow mentioned, workflow action doesn’t trigger form event in JS. It trigger on_update event in python. But in my case is workflow state changed also after submit, and then on_update event is not triggered. But i found thread where was written that if some fields are changed after submit, there is:

def on_update_after_submit(self):

which is triggered in this case. So If your workflow state is changing also after submit (or any other field - not only workflow state) this event is triggered.

For recapitulation: workflow state will trigger python events:

def on_update(self):                 # if state is changed before submit

def on_update_after_submit(self):    # if state is changed after submit

Thank you all for help!

5 Likes

is there any idea to capture it in js instead of python?

There is a Client Side Event called before_workflow_action.

1 Like

Everyone may want to check this file:

There are two client-side events for this situation:

before_workflow_action: () => {}
after_workflow_action: () => {}

Regards,

Alirio.

15 Likes

Thanks a lot for this @aliriocastro, it was very helpful

Cheers

3 Likes

I used if statements

hooks.py

# Hook on document methods and events

doc_events = {
    "Expense Entry": {
        "on_update": "expense_request.api.make_journal_entry"
    }
}

api.py

def make_journal_entry(expense_entry, method):
    if expense_entry.status == "Approved":
         # my code goes within the if
1 Like

Great! The advantage of the solution highlighted by @aliriocastro is however that it can be used in a Custom Script (Client Side). Server side scripts are not a convenient solution for most users

Cheers

2 Likes

any way to catch which workflow button is being clicked from client side script?

The form variable (usually passed as frm to the event trigger) should have a property selected_workflow_action. That will tell you which workflow action triggered the change event.

1 Like

Thanks a lot mate. This trigger helps much

Thanks for this.

Thanks for this