How create and insert a new document through custom script

I’ve been trying to automate a document creation process by making a doctype which acts as a wizard. I have a script set to take all the inputted values and create the various documents necessary.

My script:

frappe.ui.form.on("Wizard", "validate", function(frm, cdt, cdn) {
        var d = locals[cdt][cdn];
        var contact = frappe.new_doc = ({ 
        	"doctype": "Contact",
	        "person_profile": d.profile, 
        	"first_name": d.first_name, 
        	"last_name": d.last_name, 
        	"gender": d.gender, 
        	"email_id": d.email_id 
        });
        console.log(contact);
        frappe.db.insert(contact);
});

It runs perfectly fine, till the frappe.db.insert() (I have tried contact.insert(), but the do the same thing, literally), where the script then just stops, it doesn’t error, it doesn’t continue with broken values, it just stops. I can re-validate to infinity, but the script always stops there, I don’t know why…
I’ve tried pretty much every way possible to insert this new document including: frappe.run_serially (works, but its not transparent, which is what I would like, and doesnt run well on validations), frappe.call (Not Allowed), frappe.get_doc (no different from new_doc with args), so I’m kida stuck.

I have tried saving a newly created document via JS route but nothing helped. If you can write similar code in Python and call this function in this Custom script then you will be able to do most of the basic ops on files such as create, update, save, submit, cancel.

The best I did was through frappe.run_serial , it works but I think there is a better way to do this.

Very little info on hosted js only document scripts. This script works. Shows parent fields and child fields. It has all the mandatory fields for PO items:

frappe.ui.form.on("Sales Order", "test", function(frm) {

frappe.call({
    method: 'frappe.client.insert',
    args: {
        doc: {doctype: 'Purchase Order',
        supplier: 'Intel',
	items: [{"item_code": "XXX141-C-WF",
		"item_name": "XXX141-C-WF",
		"schedule_date": "2019-03-30",
		"description": "Wafer Test",
		"qty": 12,
		"stock_uom": "EA",
		"uom": "EA",
		"conversion_factor": 1,
		"base_rate": 12,
		"base_amount": 12,}]},
    },
    callback: function(r) {
                console.log(r);
		}
});

});

child data has to be described as JSON array with square brackets.

This should work:

frappe.ui.form.on("Wizard", "validate", function (frm, cdt, cdn) {
    var d = locals[cdt][cdn];
    frappe.db.insert({
        "doctype": "Contact",
        "person_profile": d.profile,
        "first_name": d.first_name,
        "last_name": d.last_name,
        "gender": d.gender,
        "email_id": d.email_id
    }).then(function(doc) {
        console.log(doc);
    });
});

or this:

frappe.db.insert({
    doctype: 'Purchase Order',
    supplier: 'Intel',
    items: [
        {
            'item_code': 'XXX141- C - WF',
            'item_name': 'XXX141 - C - WF',
            'schedule_date': '2019 - 03 - 30',
            'description': 'Wafer Test',
            'qty': 12,
            'stock_uom': 'EA',
            'uom': 'EA',
            'conversion_factor': 1,
            'base_rate': 12,
            'base_amount': 12,
        },
    ]
}).then(function(doc) { 
    console.log(`${doc.doctype} ${doc.name} created on ${doc.creation}`);
});

Also, see here:

4 Likes

Used the same approach as above. I have a very fundamental question.

Is it possible to use the document generated by the above outside the context of the function?

}).then(function(doc) {
newDoc = doc
});

console.log(newDoc.name)

Secondly, I want the user to be able to edit the new document generated. The focus comes back to the current document

JavaScript usually doesn’t work this way; your log statement will be executed before the callback method, without any data in the variable. However, you can wait for the promise to return by using async and await.

Got it, thanks!!

Thank you very much…this method was very helpful for me.
Worked like charm

Can we insert multiple rows with data ?
What if we want to insert one more item to the child-table in here?

Thank you

Maybe this is what you’re looking for:

Not exactly,In the above solution you have inserted childtable like

items: [
{
‘item_code’: ‘XXX141- C - WF’,
.
.
.
}
which means only the 1st row is filled,What i wanted is that to insert one more row with may be item_code as ‘XXX142 - C- WF’ while the time of Creating a new document(using frappe.db.insert({}) )