Create a quotation from a custom doctype view using a button

Greetings,

I have a custom doctype that records information useful in a quotation,
i want to have a button like the one on leads showing make then when clicked to it can create a quotation taking those data.
Any easy way of doing it?

kr,
Oasis

@Oasis_Agano,

You will need to write the python method to create the Quotation from Your doctype then on button click call that method.

You can use the get_mapped_doc method to map the doctype’s fields to quotation. Please check the make_quotation method in lead.py

I created a custom script looking like this, but im getting this message when i click the button “The resource you are looking for is not available
my folder structure is apps/bsc/bsc/bsc/doctype/site/(site.py,site.js)
JS

frappe.ui.form.on('Site', "refresh", function(frm){
		frm.add_custom_button(__("Generate Quotation"), function() {

		frappe.call({
		method: "bsc.bsc.doctype.site.site.make_quotation",
		"callback": function(r) {
			r.message
		}
	})
    });
});

PY

class Site(Document):
	@frappe.whitelist()
	def make_quotation(self):
		mess = "message"
		print (mess)

		return mess
	pass

@frappe.whitelist()
def make_quotation(source_name, target_doc=None):
	target_doc = get_mapped_doc("Site", source_name,
		{"Site": {
			"doctype": "Quotation",
			"field_map": {
				"name": "lead"
			}
		}}, target_doc)
	target_doc.quotation_to = "Lead"
	target_doc.run_method("set_missing_values")
	target_doc.run_method("set_other_charges")
	target_doc.run_method("calculate_taxes_and_totals")

	return target_doc

any help?!

need to have args

from the client side or the server side?

from the client side

frappe.ui.form.on('Site', "refresh", function(frm){
		frm.add_custom_button(__("Generate Quotation"), function() {

		frappe.call({
		method: "bsc.bsc.doctype.site.site.make_quotation",
	args: {
	   doctype: "Site",
	   customer: frm.doc.customer
	},
		"callback": function(r) {
			r.message
		}
	})
    });
});

i changed the client side to this but im getting an error now saying:

File "/home/oasis/frappe-bench/apps/frappe/frappe/__init__.py", line 913, in call
    return fn(*args, **newargs)
TypeError: make_quotation() takes at least 1 argument (0 given)

Is there any issue in my way of passing arguments?

You are passing the wrong arguments. The right syntax is

args: { "arg1": value_to_be_passed  }

and in the backend, you have to create the parameter of the same name

@frappe.whitelist()
def method(arg1)

No, That didnt work

frappe.ui.form.on('Site', "refresh", function(frm){
		frm.add_custom_button(__("Generate Quotation"), function() {

		frappe.call({
		method: "bsc.bsc.doctype.site.site.make_quotation",
	args: { "customer": frm.doc.customer  },

		"callback": function(r) {
			r.message
		}
	})
    });
});

and the backend

@frappe.whitelist()
def make_quotation(source_name, target_doc=None,args):

	target_doc = get_mapped_doc("Site", source_name,
		{"Site": {
			"doctype": "Quotation",
			"field_map": {
				"name": "customer"
			}
		}}, target_doc)
	target_doc.quotation_to = "Lead"
	target_doc.run_method("set_missing_values")
	target_doc.run_method("set_other_charges")
	target_doc.run_method("calculate_taxes_and_totals")

	return target_doc

Error

File "/home/oasis/frappe-bench/apps/bsc/bsc/bsc/doctype/site/site.py", line 18
    def make_quotation(source_name, target_doc=None,args):
SyntaxError: non-default argument follows default argument

Yes, because you are doing this wrong. You have to keep the arguments name same in the backend and frontend. In the frontend, you are sending “customer” as an argument while in backend there isn’t any argument named as “customer”. [quote=“Oasis_Agano, post:9, topic:25489”]
args: { “customer”: frm.doc.customer },
[/quote]

Change the “customer” into “source_name”[quote=“Oasis_Agano, post:9, topic:25489”]
def make_quotation(source_name, target_doc=None,args):
[/quote]

Remove “args” from here.

can i use another argument other than the source_name?

You can name the arguments whatever you want, as long as they match on the front and back end.

This solved it, Thanks


frappe.ui.form.on('Site', "refresh", function(frm){
    		frm.add_custom_button(__("Generate Quotation"), function() {

    	

    			frappe.model.open_mapped_doc({
    			method: "bsc.bsc.doctype.site.site.make_quotation",
    			frm: cur_frm
    		})

    	
    });

    @frappe.whitelist()
        def make_quotation(source_name, target_doc=None):
        	target_doc = get_mapped_doc("Site", source_name,
        					{"Site": {
        						"doctype": "Quotation",
        						"field_map": {
        							"customer": "title"
        						}
        					}},target_doc)
        	target_doc.quotation_to = "Site"
        	target_doc.run_method("set_missing_values")
        	target_doc.run_method("set_other_charges")
        	target_doc.run_method("calculate_taxes_and_totals")

        	return target_doc