Set Multiple fields using dict JavaScript

Hi!

Is there an easy way to set_values based on a dict var I created?

var docs = [{
    doctype: "Sales Invoice",
    customer: myCustomer,
    posting_date: frm.doc.posting_date,
    posting_time: frm.doc.posting_time,

    set_posting_time: 1,

    items: [*myItems*]

}]

//some code to set_value based on keyname to my doc

I haven’t found one that is only javascript. but have a look at the document mapper python class to see if that can work for you. It is also something that could be done pretty easily with an enumerate and map/filter, where set_value is part of your function.

1 Like

okay! Will post my code here after I see that.

Thanks @tmatteson

@outerlook I find myself in need of this helper this morning also. Did you get anywhere with this over the weekend?

Let’s try this. Note that the object’s keys have to match the destination (child table) field names.

function map_fields(frm, cdt, cdn, field_map){
	Object.entries(field_map).map(([field, value]) =>
		field_map.hasOwnProperty(field) ? frappe.model.set_value(cdt, cdn, field, value) : null);
}
1 Like

I’ve failed to get this by that day.

The temporary plan B i’m using is to insert the document as a whole like this:

        var funcs = docs.map((doc) => {
            frappe.call({
                method: "frappe.client.insert",
                args: {
                    doc: doc // doc object
                },
                callback: function(r) {
                    frappe.set_route("Form", "Sales Invoice", r.message.name)
                }
            })
        })

I’m still not happy with that as this saves the new document as draft, and I would like not to store this as saved draft yet…

If I get this to work I will use frappe.model.get_new_doc and then set all fields.

I plan to work more on this to find a better solution! And then post here.

Oh, now I saw the edit! I will use this and then post here as soon as I go to office, Thanks @tmatteson!

Almost perfectly working! Just one thing is weird to me…

this is the resulting code:

        var newdoc = frappe.model.get_new_doc("Sales Invoice")

        function map_fields(cdt, cdn, field_map) { // I just removed "frm"from yours
            Object.entries(field_map).map(([field, value]) =>
                frappe.model.set_value(cdt, cdn, field, value) 
            )
        }

        map_fields(newdoc.doctype, newdoc.name, docs[0])
        frappe.set_route("Form", "Sales Invoice", newdoc.name)

Funny part is now the fields I included are being set! But fields wich were supposed to be initialized automatically are not. Such as “Series” field, and “amount” from child table

Is it something wrong with using get_new_doc? I tried to use frappe.new_doc(“Sales Invoice”) but I didn’t understand how could I set the new document reference to a variable… it appears to return a Promise object.

This is the textbook example of how to use the frappe.model.mapper class and probably shouldn’t be done in the front end.

The function you want is: frappe.model.make_new_doc_and_get_name

1 Like