Data in childtable not getting saved

I have a usecase where i need to populate data to a childtable that’s shown in parent doctype on click of a button which calls server script and gets the data

frappe.ui.form.on("Physical Audit", {
    refresh: function (frm) {
        // Check if docstatus is "Inventory Pending"
        if (frm.doc.docstatus === 0 && frm.doc.workflow_state === "Inventory Check Pending") {
            frm.add_custom_button("Fetch Inventory", () => {
                frappe.confirm(
                    "This will fetch data from Redshift and update the Inventory Details table. Are you sure?",
                    () => {
                        frappe.call({
                            method: "audit.audit.doctype.physical_audit.physical_audit.fetch_and_populate_inventory",
                            args: { doc: frm.doc },
                            callback: function (response) {
                                console.log("Response from server:", response);
                                if (response.message && response.message.inventory_details) {
                                    console.log("Setting child table data:", response.message.inventory_details);

                                    // Clear existing child table data
                                    frm.clear_table("inventory_details");

                                    // Add rows dynamically with proper flags
                                    response.message.inventory_details.forEach((row) => {
                                        let child = frm.add_child("inventory_details");
                                        frappe.model.set_value(child.doctype, child.name, "material_id", row.material_id);
                                        frappe.model.set_value(child.doctype, child.name, "material_name", row.material_name);
                                        frappe.model.set_value(child.doctype, child.name, "system_qty", row.system_qty);
                                        frappe.model.set_value(child.doctype, child.name, "physical_qty", row.physical_qty);
                                    });

                                    // Refresh the field to reflect the changes in the UI
                                    frm.refresh_field("inventory_details");

                                    frappe.show_alert({
                                        message: `${response.message.inventory_details.length} rows added to Inventory Details.`,
                                        indicator: "green"
                                    });
                                } else {
                                    frappe.msgprint("No inventory data returned.");
                                }
                            },
                            error: function (error) {
                                console.error("Error occurred:", error);
                                frappe.msgprint({
                                    title: "Error",
                                    message: error.message || "An error occurred while fetching data.",
                                    indicator: "red"
                                });
                            }
                        });
                    }
                );
            });
        }
    }
});

above client script is working fine and injecting data to childtable and shown to the user but when the parent doctype is saved the injected data is not getting saved.
Not sure what i am missing

Hi ,

I’m not sure if it’s needed : Database API

I was trying to trigger a server script with the above client script by showing a button which gets the data from Redshift (External data source) and gives response to where clientscript is doing frm.add_child and inserting data to the child table

Can you share a video of that, if possible?

https://streamable.com/mi5gpl

@Abdeali above is the video link

Hello,

I am not sure, but there is one error when you are fetching that data, may be that causing problem.

In network tab view savedoc API’s request and response at saving, also check getdoc API’s request and response.

In that check your child table is correct or not.

I have made the server script to inject the data to the child table by fetching the data from external source and it was working , the error which was shown in video was related to client script.

In savedoc api payload the childtable data was not getting passed for some reason i.e why on save action the injected data is getting cleared.

I solved this by setting frm.dirty(); in client script

Reference Script

frappe.ui.form.on("Physical Audit", {
    refresh: function (frm) {
        if (frm.doc.workflow_state === "Inventory Check Pending" && frm.doc.docstatus === 0) {
            frm.add_custom_button("Fetch Inventory", () => {
                frappe.confirm(
                    "This will fetch data from Redshift and update the Inventory Details table. Are you sure?",
                    async () => {
                        try {
                            const response = await frappe.call({
                                method: "audit.audit.doctype.physical_audit.physical_audit.fetch_and_save_inventory",
                                args: { docname: frm.doc.name }
                            });

                            // Fix: Navigate through the nested structure of the response
                            const inventoryDetails =
                                response.message && response.message.message
                                    ? response.message.message.inventory_details
                                    : null;

                            if (inventoryDetails) {
                                console.log("Inventory details returned:", inventoryDetails);

                                // Clear existing data in child table
                                frm.clear_table("inventory_details");

                                // Inject new data into the child table
                                inventoryDetails.forEach(row => {
                                    frm.add_child("inventory_details", row);
                                });

                                // Refresh the field to reflect the changes in the UI
                                frm.refresh_field("inventory_details");

                                // Explicitly mark the form as dirty
                                frm.dirty();

                                frappe.show_alert({
                                    message: `${inventoryDetails.length} rows added to Inventory Details.`,
                                    indicator: "green"
                                });
                            } else {
                                frappe.msgprint({
                                    title: "Notice",
                                    message: "No inventory data was returned from the server.",
                                    indicator: "orange"
                                });
                            }
                        } catch (error) {
                            console.error("Error occurred while fetching inventory:", error);
                            frappe.msgprint({
                                title: "Error",
                                message: error.message || "An error occurred while fetching data.",
                                indicator: "red"
                            });
                        }
                    }
                );
            });
        }
    }
});

1 Like