Only System Manager can run script attached to Customer doctype

I’ve come up against an error where general users can’t run a script that’s working with the doctype “Customer” and my custom doctype “Lease Agreement”.

The only way I can get this to work is if I give the user “System Manager” permissions, which isn’t an option.

I’ve gone to both doctypes and ensured that their role is included in the “Permission Rules” section of the doc. The role includes read/write/create/delete.

The message dialog that pops up is huge:

The code is in a custom js file that is included in my custom app’s hooks file, everything else in this js file runs as expected.

Any suggestions on how to debug this would be greatly appreciated!

// Lease Agreement - Refresh Lease Summary table
frappe.ui.form.on('Customer', {

    // Event handler for the "refresh_lease_summary" event
    refresh_lease_summary(frm) {

        // Display a message indicating that the lease summary is being refreshed
        frappe.show_alert({
            message: __('Lease Summary refreshing...'),
            indicator: 'info'
        });

        // Clear the existing data from the "lease_summary" table
        frm.clear_table("lease_summary");

        // Use the xcall method to get all documents linked to the current "Customer" document
        frappe.xcall(
            "frappe.desk.form.linked_with.get",
            { "doctype": cur_frm.doctype, "docname": cur_frm.docname }
        ).then(r => {

            // Store the linked documents in the "__linked_docs" variable
            frm.__linked_docs = r;

            // Get an array of linked documents and their properties
            const linked_docs = frm.__linked_docs;
            const linked_doc_entries = Object.entries(linked_docs);

            // Loop through the linked documents to find "Lease Agreement" documents
            let x = linked_doc_entries;
            let results = [];

            for (const key in x) {
                if (x[key][0] === "Lease Agreement") {
                    let leaseAgreements = Object.values(x[key][1]);
                    for (let i in leaseAgreements) {
                        let a = leaseAgreements[i];
                        for (let j in a) {
                            let string = a[j].toString().startsWith("LA");
                            if (string) {
                                results.push(a[j]);
                            }
                        }
                    }
                }
            }

            // Loop through the "Lease Agreement" documents found and retrieve information to populate the lease summary table
            for (let i in results) {
                let lease = results[i];
                let location_array = [];
                let auth = [];

                // Get the child table of the "Lease Agreement" document and loop through its entries to get the location and authorized person information
                frappe.model.with_doc("Lease Agreement", lease, function () {
                    var child_table = frappe.model.get_doc("Lease Agreement", lease);
                    let cust = frm.doc.customer_name;

                    $.each(child_table.product_location, function (index, row) {
                        if (!row.cancel_product) {
                            location_array.push(row.location);
                        }
                    });

                    $.each(child_table.authorised_persons, function (index, row) {
                        if (row.customer_name === cust) {
                            auth.push(row.storage_access);
                            auth.push(" (A)")
                        }
                    });

                    $.each(child_table.responsible_persons, function (index, row) {
                        if (row.customer_name === cust) {
                            auth.push(row.update_approval);
                            auth.push(" (R)")
                        }
                    });

                    // Join the location and authorized person information into strings to populate the lease summary table
                    let location_string = location_array.join(", ");
                    let customer = child_table.customer_name;
                    let auth_string = auth.join(" ");

                    if (auth_string.includes("Jointly with Responsible Person #")) {
                        auth_string = auth_string.replace("with Responsible Person #", "")
                    } else if (auth_string.includes("Jointly with Person #")) {
                        auth_string = auth_string.replace(" with Person #", "")
                    } else if (auth_string == "") {
                        auth_string = "Owner"
                    }

                    // Add a new row to the "lease_summary" table with the retrieved information
                    frm.add_child("lease_summary", {
                        lease: lease,
                        location: location_string,
                        owner: customer,
                        role: auth_string
                    });
                });
            }

            // Refresh the "lease_summary" table and save the form
            frm.refresh_fields("lease_summary");
            frm.save();
        });
    }
});

I think I’ve found the issue. The user doesn’t seem to be able to use the method frappe.desk.form.linked_with_get

I’ve tried modifying the code to a general call method, but that gives me the same error:

frappe.call({
    method: "frappe.desk.form.linked_with.get",
    args: {
        doctype: cur_frm.doctype,
        name: cur_frm.docname
    },
    callback: function(r) {
        // Store the linked documents in the "__linked_docs" variable
        frm.__linked_docs = r.message;

        // Get an array of linked documents and their properties
        const linked_docs = frm.__linked_docs;
        const linked_doc_entries = Object.entries(linked_docs);

        // The rest of your code goes here
    }
});

Any thoughts?

Please check if you have selected below check box in “System Settings”

Screen Shot 2023-02-14 at 12.49.01 PM

Hi, thanks for the suggestion.

Strict User Permissions is not selected in my settings.

This is the new role I’ve created and assigned to the user. This role has also been added to the permissions in each doctype:

I feel like the user should now have full permissions to make changes (like a System Manger) to this doctype.

Is it possible that other assigned roles are creating a conflict and restricting access to the document?

Wasn’t able to fix the permission issue. I’ve used a different method to achieve the same result though:

I’ll throw it here, may help someone in the future.

// Lease Agreement - Refresh Lease Summary table
frappe.ui.form.on('Customer', {

    // Event handler for the "refresh_lease_summary" event
    refresh_lease_summary(frm) {

        // Display a message indicating that the lease summary is being refreshed
        // frappe.show_alert({
        //     message: __('Lease Summary refreshing...'),
        //     indicator: 'info'
        // });

        // Clear the existing data from the "lease_summary" table
        frm.clear_table("lease_summary");

        // Use the frappe.db.get_list method to get all "Lease Agreement" documents linked to the current "Customer" document
        let customer_id = frm.doc.name;
        frappe.db.get_list('Dynamic Link', {
            filters: { 'link_doctype': 'Customer', 'link_name': customer_id, 'parenttype': 'Lease Agreement' },
            fields: ['parent'],
            pluck: 'parent',
            parent_doctype: "Lease Agreement"
        }).then(lease_list => {
            console.log(lease_list)
            lease_list = lease_list.filter((item,index) => lease_list.indexOf(item)===index) // remove duplicate leases. Not sure why there are dupes
            // Loop through the "Lease Agreement" documents found and retrieve information to populate the lease summary table
            for (let i in lease_list) {
                let lease = lease_list[i];
                if (lease) {
                    let lease_id = lease.toString();
                    console.log(lease_id);
                    let location_array = [];
                    let auth = [];

                    // Get the child table of the "Lease Agreement" document and loop through its entries to get the location and authorized person information
                    frappe.model.with_doc("Lease Agreement", lease_id, function () {
                        var child_table = frappe.model.get_doc("Lease Agreement", lease_id);
                        let cust = frm.doc.customer_name;

                        $.each(child_table.product_location, function (index, row) {
                            if (!row.cancel_product) {
                                location_array.push(row.location);
                            }
                        });

                        $.each(child_table.authorised_persons, function (index, row) {
                            if (row.customer_name === cust) {
                                auth.push(row.storage_access);
                                auth.push(" (A)")
                            }
                        });

                        $.each(child_table.responsible_persons, function (index, row) {
                            if (row.customer_name === cust) {
                                auth.push(row.update_approval);
                                auth.push(" (R)")
                            }
                        });

                        // Join the location and authorized person information into strings to populate the lease summary table
                        let location_string = location_array.join(", ");
                        let customer = child_table.customer_name;
                        let auth_string = auth.join(" ");

                        if (auth_string.includes("Jointly with Responsible Person #")) {
                            auth_string = auth_string.replace("with Responsible Person #", "")
                        } else if (auth_string.includes("Jointly with Person #")) {
                            auth_string = auth_string.replace(" with Person #", "")
                        } else if (auth_string == "") {
                            auth_string = "Owner"
                        }

                        // Add a new row to the "lease_summary" table with the retrieved information
                        frm.add_child("lease_summary", {
                            lease: lease_id,
                            location: location_string,
                            owner: customer,
                            role: auth_string
                        });
                    });
                }
            }

            // Refresh the "lease_summary" table and save the form
            frm.refresh_fields("lease_summary");
            frm.save();
        });
    }
});