Halting workflow state via script

Hi
On Purchase Orders, I have an additional state called “Verified”. This state is when
a particular supporting doc is attached to the PO after the doc was approved. But if
the attachment is not detected , I don’t want the workflow_state to change to “Verified”.

I wrote some code and it detects correctly that there is no attachment, but it does
not halt he change in workflow state.

Would appreciate assistance…

frappe.ui.form.on('Purchase Order', {
    after_save: function(frm) {
        debugger;
        if (!frm.doc.custom_po_barcode) {
            debugger;
            frm.set_value("custom_po_barcode", frm.doc.name);
            frm.refresh_field("custom_po_barcode");
            frm.save();
        }
    },
    before_workflow_action: function(frm) {
        if (frm.doc.workflow_state == "Approved") {
            frappe.call({
                method: 'frappe.client.get_list',
                args: {
                    doctype: 'File',
                    filters: {
                        attached_to_doctype: 'Purchase Order',
                        attached_to_name: frm.doc.name
                    },
                    fields: ['name']
                },
                async: false,  
                callback: function(response) {
                    if (!response.message.length) {
                        frappe.throw(__('You must attach a Pro Forma Invoice before verifying.'));
                    }
                }
            });
        }
    }   
});

@trainingacademy try this with the frappe.throw :
validated=false;
frappe.dom.unfreeze();
frappe.throw(__(“You must attach a Pro Forma Invoice before verifying.”))

1 Like

Thank you @bahaou for your response and also thank you to @Pejay that responded
when I replied on an existing thread that handled a similar issue.

I am afraid the workflow change is still being permitted. I did this …
and for “validated” I used both “validated” and “frappe.validated”…

frappe.ui.form.on('Purchase Order', {
    after_save: function(frm) {
        debugger;
        if (!frm.doc.custom_po_barcode) {
            debugger;
            frm.set_value("custom_po_barcode", frm.doc.name);
            frm.refresh_field("custom_po_barcode");
            frm.save();
        }
    },
    before_workflow_action: function(frm) {
        if (frm.doc.workflow_state == "Approved") {
            frappe.call({
                method: 'frappe.client.get_list',
                args: {
                    doctype: 'File',
                    filters: {
                        attached_to_doctype: 'Purchase Order',
                        attached_to_name: frm.doc.name
                    },
                    fields: ['name']
                },
                async: false,  
                callback: function(response) {
                    if (!response.message.length) {
                        debugger;
                        frappe.validated=false;
                        frappe.dom.unfreeze();
                        frappe.throw(__('You must attach a Pro Forma Invoice before verifying.'));
                    }
                }
            });
        }
    }
});
1 Like

@trainingacademy do you see the message and then it continue , or you see nothing ?

I do see the frappe.throw message popping up.
I also inserted a break-point to ensure that the code is executing.

I found this thread …

https://discuss.frappe.io/t/jquery-return-false-not-stopping-form-submit/28203

Should I perhaps replace the frappe.throw message with "return false " ?

@trainingacademy you should indeed add return false after the frappe throw . this is my working code :

Thank you @bahaou for all your effort

I had another look at your code , which is working and the only difference i can find is your use of “async” in the actual trigger i.e.

before_workflow_action : async (frm) => {

This is mine

frappe.ui.form.on('Purchase Order', {
    after_save: function(frm) {
        debugger;
        if (!frm.doc.custom_po_barcode) {
            debugger;
            frm.set_value("custom_po_barcode", frm.doc.name);
            frm.refresh_field("custom_po_barcode");
            frm.save();
        }
    },
    before_workflow_action: function(frm) {
        if (frm.doc.workflow_state == "Approved") {
            frappe.call({
                method: 'frappe.client.get_list',
                args: {
                    doctype: 'File',
                    filters: {
                        attached_to_doctype: 'Purchase Order',
                        attached_to_name: frm.doc.name
                    },
                    fields: ['name']
                },
                async: false,  // Ensures the check is completed before proceeding
                callback: function(response) {
                    if (!response.message.length) {
                        debugger;
                        validated=false;
                        frappe.dom.unfreeze();
                        frappe.throw(__('You must attach a Pro Forma Invoice before verifying.'));
                        return false;
                    }
                }
            });
        }
    }
});

and I also tried …

    before_workflow_action: async (frm) => {
        if (frm.doc.workflow_state == "Approved") {
            frappe.call({
                method: 'frappe.client.get_list',
                args: {
                    doctype: 'File',
                    filters: {
                        attached_to_doctype: 'Purchase Order',
                        attached_to_name: frm.doc.name
                    },
                    fields: ['name']
                },
                async: false,  // Ensures the check is completed before proceeding
                callback: function(response) {
                    if (!response.message.length) {
                        debugger;
                        validated=false;
                        frappe.dom.unfreeze();
                        frappe.throw(__('You must attach a Pro Forma Invoice before verifying.'));
                        return false;
                    }
                }
            });
        }
    } 

and still the workflow change is permitted.

I wonder if it is not a version related problem ?
I am on version 15.40.0

Update.

I think I found the problem.
I suspect it was because I was returning from within the frappe.call

This seems to work.

    before_workflow_action: function(frm) { 
        if (frm.doc.workflow_state == "Approved") { 
            let has_attachment = false; 

            frappe.call({
                method: 'frappe.client.get_list',
                args: {
                    doctype: 'File',
                    filters: {
                        attached_to_doctype: 'Purchase Order',
                        attached_to_name: frm.doc.name
                    },
                    fields: ['name']
                },
                async: false, 
                callback: function(response) {
                    has_attachment = response.message.length > 0;
                }
            });

            if (!has_attachment) {
                debugger;
                validated=false;
                frappe.dom.unfreeze();
                frappe.throw(__('You must attach a Pro Forma Invoice before proceeding to the next state.'));
                return false; 
            }
        }
    }

Thanks for your time @bahaou . Appreciate