How open new doc with all data in object

Hello,
I am trying open new purchase invoice form with data stored in object in client script.
This object (new_form_object) is returned by internal erpnext function:

   frappe.call({
        method: 'frappe.model.mapper.map_docs',
        args: {
            method: 'erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice',
            source_names: '["PO-24-00200"]', target_doc:''
    
        },
       callback: (r) => {
            let new_form_object = r.message
		})

  }})

I know about frappe.new_doc, but something like this is not working for child tables (items in this cause):

frappe.new_doc("Purchase Invoice", doc = new_form_object);

Or should I “parse” all tables to format like this? Uf :slight_smile:

let row = frappe.model.add_child(doc, "items");
    row.item_code = new_form_object.items[0].item_code;
    row.item_name = new_form_object.items[0].item_name;
etc...

Thanks for any advice in advance.

Jiri Sir

Hi @Jiri_Sir,

Here I created a sample example of a Purchase Order to Purchase Receipt creation so check it.

Client script:

frappe.ui.form.on('Purchase Order', {
    refresh: function(frm) {
        frm.add_custom_button("Create PR", () => {
            frappe.new_doc("Purchase Receipt", {}, doc => {
                doc.supplier = frm.doc.supplier;
                // Set other fields as needed
                frappe.model.clear_table(doc, "items");

                frm.doc.items.forEach(po_item => {
                    let pr_item = frappe.model.add_child(doc, "items");
                    pr_item.item_code = po_item.item_code;
                    pr_item.qty = po_item.qty;
                    pr_item.rate = po_item.rate;
                    // Set other fields as needed
                });
            });
        });
    }
});

Output:

3 Likes

Hello @NCP,
thank you very much for the quick answer.

So as I see, there is no other way how prepare now form directly from prepared object. Just go through it and setup all necessary values.

For items I will try something like this:

frm.doc.items.forEach(po_item => {
           let pr_item = frappe.model.add_child(doc, "items");
               for (var key in pr_item)
			   {
					pr_item[key] = po_item[key];
			    }
             });
});

Maybe I will try for cycle for all non table values in prepared object.

Thank you any way.
Jiri Sir

Hello,
finally I am using this:

	frappe.call({
        method: 'frappe.model.mapper.map_docs',
        args: {
            method: 'erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice',
            source_names: po_arr,
            target_doc: ''
    },
        // freeze the screen until the request is completed
        freeze: true,
        callback: (r) => {
            frappe.new_doc("Purchase Invoice", {}, doc => {
            
                let  pi = r.message;
                
                //Standard fields w/o child tables
                for (var key in pi)
        	    {
        	        if (!Array.isArray(pi[key]))
        			    doc[key] = pi[key];
        	    }
        	    
        	    //Item child table
        	    frappe.model.clear_table(doc, "items");
        	    
        	    pi.items.forEach(po_item => {
        		    let pi_item = frappe.model.add_child(doc, "items");
                    for (var item_key in po_item)
        			{
        			    pi_item[item_key] = po_item[item_key];
        			}
                });
                
                
                //Custom fields in target doc
                doc.bee_amount = frm.doc.bee_amount;
                doc.purchase_invoice_approval = frm.doc.name;
                doc.posting_date = frm.doc.bill_date;
                doc.custom_bee_variable_symbol = frm.doc.bee_variable_symbol;
            
            });
        }
    });

I have given the reference of the video here, maybe it will help someone.

2 Likes

Upvoting as this is the correct way to do it imo and also works in v15 onwards. Thanks for creating this video tutorial!