Want a formula field without the use of a custom script

Greetings everyone,

in purchase invoice, i have made a custom fieldtype “Currency” by the name of “audit_amount”. I am trying to avoid the custom script because that option has already been discovered, but is there any way that we can use some sort of JS coding in the default field where i can create a difference between “grand_total” and “audit_amount”?

will Highly appreciate your feedback…

Regards,
Muhammad Shoaib Saeed

Which field will contain the formula? I assume it’s not audit_amount because that’s part of the formula.

This can be done in a custom HTML field in the print designer using Jinja. This won’t add it to the database though.

well, i was hoping for this to happen in the database though, but a client script seems to be working for me.

let me share it.

frappe.listview_settings[‘Purchase Invoice’] = {
add_fields: [“workflow_state”],
onload: function(listview) {
// Button 1: Set Individual Audit Amounts
listview.page.add_inner_button(__(‘Set Individual Audit Amounts’), function() {
// Get selected items
const selected_docs = listview.get_checked_items();

        // Ensure at least one document is selected
        if (!selected_docs.length) {
            frappe.msgprint(__('Please select documents first.'));
            return;
        }

        // Fetch details (grand_total, bill_no) for all selected documents
        let promises = selected_docs.map(doc => {
            return new Promise((resolve, reject) => {
                frappe.call({
                    method: "frappe.client.get",
                    args: {
                        doctype: "Purchase Invoice",
                        name: doc.name
                    },
                    callback: function(r) {
                        if (r && r.message) {
                            resolve({
                                name: doc.name,
                                grand_total: r.message.grand_total,
                                bill_no: r.message.bill_no
                            });
                        } else {
                            reject();
                        }
                    }
                });
            });
        });

        // After fetching the details, show the dialog
        Promise.all(promises).then(results => {
            let fields = [];

            results.forEach(doc => {
                fields.push({
                    label: __('Bill No: {0}, Grand Total: {1}', [doc.bill_no, format_currency(doc.grand_total)]),
                    fieldname: `audit_amount_${doc.name}`,
                    fieldtype: 'Currency',
                    reqd: 0,  // Changed to optional so we can handle missing input
                    default: doc.grand_total  // Set default value to grand total
                });
            });

            // Create a dialog with individual audit amount fields for each selected document
            let dialog = new frappe.ui.Dialog({
                title: __('Enter Audit Amounts'),
                fields: fields,
                primary_action_label: __('Submit'),
                primary_action(values) {
                    // Loop through selected documents and update audit amount for each
                    results.forEach((doc) => {
                        // Get the audit amount value entered by the user or default it to the grand total
                        let audit_amount = values[`audit_amount_${doc.name}`] || doc.grand_total;

                        // First, update custom_audit_amount field for each document
                        frappe.call({
                            method: "frappe.client.set_value",
                            args: {
                                doctype: "Purchase Invoice",
                                name: doc.name,
                                fieldname: "custom_audit_amount",
                                value: audit_amount
                            },
                            callback: function(response) {
                                if (!response.exc) {
                                    frappe.msgprint(__('Audit amount set for Bill No: {0}', [doc.bill_no]));

                                    // Calculate the difference: grand_total - custom_audit_amount
                                    let difference = doc.grand_total - audit_amount;

                                    // Update custom_difference_bw_grand__audit with the calculated difference
                                    frappe.call({
                                        method: "frappe.client.set_value",
                                        args: {
                                            doctype: "Purchase Invoice",
                                            name: doc.name,
                                            fieldname: "custom_difference_bw_grand__audit",
                                            value: difference
                                        },
                                        callback: function() {
                                            frappe.msgprint(__('Difference set for Bill No: {0}', [doc.bill_no]));
                                        }
                                    });
                                }
                            }
                        });
                    });

                    // Close the dialog and refresh the list view after updating
                    dialog.hide();
                    listview.refresh();
                }
            });

            // Show the dialog
            dialog.show();
        }).catch(() => {
            frappe.msgprint(__('Failed to fetch data for some Purchase Invoices.'));
        });
    });

    // Button 2: Update Workflow Dates
    listview.page.add_inner_button(__('Update Workflow Dates'), function() {
        const selected_docs = listview.get_checked_items();
        if (selected_docs.length > 0) {
            process_invoices(selected_docs);
        } else {
            frappe.msgprint(__('Please select at least one Purchase Invoice.'));
        }
    });
}

};

function process_invoices(invoices) {
let current_index = 0;

function show_prompt_for_invoice() {
    if (current_index >= invoices.length) {
        frappe.msgprint(__('All selected Purchase Invoices have been processed.'));
        return;
    }

    const invoice = invoices[current_index];
    frappe.call({
        method: 'frappe.client.get',
        args: {
            doctype: 'Purchase Invoice',
            name: invoice.name
        },
        callback: function(r) {
            if (!r.exc) {
                const doc = r.message;
                frappe.prompt([
                    {
                        label: `On Hold Date for ${doc.supplier} (Invoice: ${doc.bill_no}, Total: ${doc.grand_total})`,
                        fieldname: 'custom_on_hold_date',
                        fieldtype: 'Date',
                        description: 'Enter On Hold Date'
                    },
                    {
                        label: `On Query Date for ${doc.supplier} (Invoice: ${doc.bill_no}, Total: ${doc.grand_total})`,
                        fieldname: 'custom_on_query_date',
                        fieldtype: 'Date',
                        description: 'Enter On Query Date'
                    },
                    {
                        label: `Director's Signing Date for ${doc.supplier} (Invoice: ${doc.bill_no}, Total: ${doc.grand_total})`,
                        fieldname: 'custom_directors_signing_date',
                        fieldtype: 'Date',
                        description: "Enter Director's Signing Date"
                    },
                    {
                        label: `Audit Date for ${doc.supplier} (Invoice: ${doc.bill_no}, Total: ${doc.grand_total})`,
                        fieldname: 'custom_audit_date',
                        fieldtype: 'Date',
                        description: 'Enter Audit Date'
                    },
                    {
                        label: `Signing Date for ${doc.supplier} (Invoice: ${doc.bill_no}, Total: ${doc.grand_total})`,
                        fieldname: 'custom_signing_date',
                        fieldtype: 'Date',
                        description: 'Enter Signing Date'
                    },
                    {
                        label: `Entry Date for ${doc.supplier} (Invoice: ${doc.bill_no}, Total: ${doc.grand_total})`,
                        fieldname: 'custom_entry_date',
                        fieldtype: 'Date',
                        description: 'Enter Entry Date'
                    }
                ], function(data) {
                    // Save the updated values to the document
                    frappe.call({
                        method: 'frappe.client.set_value',
                        args: {
                            doctype: 'Purchase Invoice',
                            name: doc.name,
                            fieldname: {
                                custom_on_hold_date: data.custom_on_hold_date,
                                custom_on_query_date: data.custom_on_query_date,
                                custom_directors_signing_date: data.custom_directors_signing_date,
                                custom_audit_date: data.custom_audit_date,
                                custom_signing_date: data.custom_signing_date,
                                custom_entry_date: data.custom_entry_date
                            }
                        },
                        callback: function() {
                            current_index++;
                            show_prompt_for_invoice();  // Proceed to the next invoice
                        }
                    });
                }, __('Enter Workflow Dates for ' + doc.name), __('Next'));
            }
        }
    });
}

show_prompt_for_invoice();

}