Multiselect dialog for getting items (#8583)

* Concatenate docnames and send to mapper

* Multiselect with checkboxes

* set setters as separate filters

* Map filter fields to target_doc

* Get items from quotation (in SO) working

* [major] Set dialog setters for all forms

* Add date field

* Specify non-default date_fields

* [minor] add test_mapper.py

* [minor] remove cur_frm

* [minor][fix] test

* [minor] fix test with make_test_records
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 3762b48..63de878 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -49,29 +49,37 @@
 		}
 
 		if(doc.docstatus===0) {
-			cur_frm.add_custom_button(__('Purchase Order'), function() {
+			var me = this;
+			this.frm.add_custom_button(__('Purchase Order'), function() {
 				erpnext.utils.map_current_doc({
 					method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice",
 					source_doctype: "Purchase Order",
+					target: me.frm,
+					setters: {
+						supplier: me.frm.doc.supplier || undefined,
+					},
 					get_query_filters: {
-						supplier: cur_frm.doc.supplier || undefined,
 						docstatus: 1,
 						status: ["!=", "Closed"],
 						per_billed: ["<", 99.99],
-						company: cur_frm.doc.company
+						company: me.frm.doc.company
 					}
 				})
 			}, __("Get items from"));
 
-			cur_frm.add_custom_button(__('Purchase Receipt'), function() {
+			this.frm.add_custom_button(__('Purchase Receipt'), function() {
 				erpnext.utils.map_current_doc({
 					method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice",
 					source_doctype: "Purchase Receipt",
+					target: me.frm,
+					date_field: "posting_date",
+					setters: {
+						supplier: me.frm.doc.supplier || undefined,
+					},
 					get_query_filters: {
-						supplier: cur_frm.doc.supplier || undefined,
 						docstatus: 1,
 						status: ["!=", "Closed"],
-						company: cur_frm.doc.company
+						company: me.frm.doc.company
 					}
 				})
 			}, __("Get items from"));
@@ -120,7 +128,7 @@
 		hide_fields(this.frm.doc);
 		if(cint(this.frm.doc.is_paid)) {
 			if(!this.frm.doc.company) {
-				cur_frm.set_value("is_paid", 0)
+				this.frm.set_value("is_paid", 0)
 				msgprint(__("Please specify Company to proceed"));
 			}
 		}
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index e8163f0..f235722 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -112,33 +112,43 @@
 	},
 
 	sales_order_btn: function() {
-		this.$sales_order_btn = cur_frm.add_custom_button(__('Sales Order'),
+		var me = this;
+		this.$sales_order_btn = this.frm.add_custom_button(__('Sales Order'),
 			function() {
 				erpnext.utils.map_current_doc({
 					method: "erpnext.selling.doctype.sales_order.sales_order.make_sales_invoice",
 					source_doctype: "Sales Order",
+					target: me.frm,
+					setters: {
+						customer: me.frm.doc.customer || undefined,
+					},
 					get_query_filters: {
 						docstatus: 1,
 						status: ["!=", "Closed"],
 						per_billed: ["<", 99.99],
-						customer: cur_frm.doc.customer || undefined,
-						company: cur_frm.doc.company
+						company: me.frm.doc.company
 					}
 				})
 			}, __("Get items from"));
 	},
 
 	delivery_note_btn: function() {
-		this.$delivery_note_btn = cur_frm.add_custom_button(__('Delivery Note'),
+		var me = this;
+		this.$delivery_note_btn = this.frm.add_custom_button(__('Delivery Note'),
 			function() {
 				erpnext.utils.map_current_doc({
 					method: "erpnext.stock.doctype.delivery_note.delivery_note.make_sales_invoice",
 					source_doctype: "Delivery Note",
+					target: me.frm,
+					date_field: "posting_date",
+					setters: {
+						company: me.frm.doc.company
+					},
 					get_query: function() {
 						var filters = {
-							company: cur_frm.doc.company
+							docstatus: 1,
 						};
-						if(cur_frm.doc.customer) filters["customer"] = cur_frm.doc.customer;
+						if(me.frm.doc.customer) filters["customer"] = me.frm.doc.customer;
 						return {
 							query: "erpnext.controllers.queries.get_delivery_notes_to_be_billed",
 							filters: filters
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 85a6329..cfd3336 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -153,30 +153,37 @@
 	},
 
 	add_from_mappers: function() {
-		cur_frm.add_custom_button(__('Material Request'),
+		var me = this;
+		this.frm.add_custom_button(__('Material Request'),
 			function() {
 				erpnext.utils.map_current_doc({
 					method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order",
 					source_doctype: "Material Request",
+					target: me.frm,
+					setters: {
+						company: me.frm.doc.company
+					},
 					get_query_filters: {
 						material_request_type: "Purchase",
 						docstatus: 1,
 						status: ["!=", "Stopped"],
 						per_ordered: ["<", 99.99],
-						company: cur_frm.doc.company
 					}
 				})
 			}, __("Add items from"));
 
-		cur_frm.add_custom_button(__('Supplier Quotation'),
+		this.frm.add_custom_button(__('Supplier Quotation'),
 			function() {
 				erpnext.utils.map_current_doc({
 					method: "erpnext.buying.doctype.supplier_quotation.supplier_quotation.make_purchase_order",
 					source_doctype: "Supplier Quotation",
+					target: me.frm,
+					setters: {
+						company: me.frm.doc.company
+					},
 					get_query_filters: {
 						docstatus: 1,
 						status: ["!=", "Stopped"],
-						company: cur_frm.doc.company
 					}
 				})
 			}, __("Add items from"));
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
index 92600b7..593f667 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -48,7 +48,7 @@
 				});
 			});
 		}
-		
+
 	},
 
 	make_suppplier_quotation: function(frm) {
@@ -124,24 +124,28 @@
 
 erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.extend({
 	refresh: function() {
+		var me = this;
 		this._super();
 		if (this.frm.doc.docstatus===0) {
-			cur_frm.add_custom_button(__('Material Request'),
+			this.frm.add_custom_button(__('Material Request'),
 				function() {
 					erpnext.utils.map_current_doc({
 						method: "erpnext.stock.doctype.material_request.material_request.make_request_for_quotation",
 						source_doctype: "Material Request",
+						target: me.frm,
+						setters: {
+							company: me.frm.doc.company
+						},
 						get_query_filters: {
 							material_request_type: "Purchase",
 							docstatus: 1,
 							status: ["!=", "Stopped"],
-							per_ordered: ["<", 99.99],
-							company: cur_frm.doc.company
+							per_ordered: ["<", 99.99]
 						}
 					})
 				}, __("Get items from"));
 				// Get items from open Material Requests based on supplier
-				cur_frm.add_custom_button(__('Possible Supplier'), function() {
+				this.frm.add_custom_button(__('Possible Supplier'), function() {
 					// Create a dialog window for the user to pick their supplier
 					var d = new frappe.ui.Dialog({
 						title: __('Select Possible Supplier'),
@@ -150,32 +154,35 @@
 						{fieldname: 'ok_button', fieldtype:'Button', label:'Get Items from Material Requests'},
 						]
 					});
-					
+
 					// On the user clicking the ok button
 					d.fields_dict.ok_button.input.onclick = function() {
 						var btn = d.fields_dict.ok_button.input;
 						var v = d.get_values();
 						if(v) {
 							$(btn).set_working();
-							
+
 							erpnext.utils.map_current_doc({
 								method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.get_item_from_material_requests_based_on_supplier",
 								source_name: v.supplier,
+								target: me.frm,
+								setters: {
+									company: me.frm.doc.company
+								},
 								get_query_filters: {
 									material_request_type: "Purchase",
 									docstatus: 1,
 									status: ["!=", "Stopped"],
-									per_ordered: ["<", 99.99],
-									company: cur_frm.doc.company
+									per_ordered: ["<", 99.99]
 								}
 							});
 							$(btn).done_working();
 							d.hide();
 						}
-					}	
+					}
 					d.show();
 				}, __("Get items from"));
-				
+
 		}
 	},
 
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
index 1e2379e..6bcbdba 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
@@ -14,6 +14,7 @@
 
 erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({
 	refresh: function() {
+		var me = this;
 		this._super();
 		if (this.frm.doc.docstatus === 1) {
 			cur_frm.add_custom_button(__("Purchase Order"), this.make_purchase_order,
@@ -24,18 +25,21 @@
 
 		}
 		else if (this.frm.doc.docstatus===0) {
-			
-			cur_frm.add_custom_button(__('Material Request'),
+
+			this.frm.add_custom_button(__('Material Request'),
 				function() {
 					erpnext.utils.map_current_doc({
 						method: "erpnext.stock.doctype.material_request.material_request.make_supplier_quotation",
 						source_doctype: "Material Request",
+						target: me.frm,
+						setters: {
+							company: me.frm.doc.company
+						},
 						get_query_filters: {
 							material_request_type: "Purchase",
 							docstatus: 1,
 							status: ["!=", "Stopped"],
-							per_ordered: ["<", 99.99],
-							company: cur_frm.doc.company
+							per_ordered: ["<", 99.99]
 						}
 					})
 				}, __("Get items from"));
diff --git a/erpnext/controllers/tests/test_mapper.py b/erpnext/controllers/tests/test_mapper.py
new file mode 100644
index 0000000..0e2d6d0
--- /dev/null
+++ b/erpnext/controllers/tests/test_mapper.py
@@ -0,0 +1,73 @@
+from __future__ import unicode_literals
+import unittest
+import frappe
+
+import random, json
+import frappe.utils
+from frappe.utils import nowdate
+from frappe.model import mapper
+from frappe.test_runner import make_test_records
+
+class TestMapper(unittest.TestCase):
+	def test_map_docs(self):
+		'''Test mapping of multiple source docs on a single target doc'''
+
+		make_test_records("Item")
+		items = frappe.get_all("Item", fields = ["name", "item_code"], filters = {'is_sales_item': 1, 'has_variants': 0})
+		customers = frappe.get_all("Customer")
+		if items and customers:
+			# Make source docs (quotations) and a target doc (sales order)
+			customer = random.choice(customers).name
+			qtn1, item_list_1 = self.make_quotation(items, customer)
+			qtn2, item_list_2 = self.make_quotation(items, customer)
+			so, item_list_3 = self.make_sales_order()
+
+		# Map source docs to target with corresponding mapper method
+		method = "erpnext.selling.doctype.quotation.quotation.make_sales_order"
+		updated_so = mapper.map_docs(method, json.dumps([qtn1.name, qtn2.name]), so)
+
+		# Assert that all inserted items are present in updated sales order
+		src_items = item_list_1 + item_list_2 + item_list_3
+		self.assertEqual(set([d.item_code for d in src_items]),
+			set([d.item_code for d in updated_so.items]))
+
+	def get_random_items(self, items, limit):
+		'''Get a number of random items from a list of given items'''
+		random_items = []
+		for i in range(0, limit):
+			random_items.append(random.choice(items))
+		return random_items
+
+	def make_quotation(self, items, customer):
+		item_list = self.get_random_items(items, 3)
+		qtn = frappe.get_doc({
+			"doctype": "Quotation",
+			"quotation_to": "Customer",
+			"customer": customer,
+			"order_type": "Sales"
+		})
+		for item in item_list:
+			qtn.append("items", {"qty": "2", "item_code": item.item_code})
+
+		qtn.submit()
+		return qtn, item_list
+
+	def make_sales_order(self):
+		item = frappe.get_doc({
+			"base_amount": 1000.0,
+			"base_rate": 100.0,
+			"description": "CPU",
+			"doctype": "Sales Order Item",
+			"item_code": "_Test Item Home Desktop 100",
+			"item_name": "CPU",
+			"parentfield": "items",
+			"qty": 10.0,
+			"rate": 100.0,
+			"warehouse": "_Test Warehouse - _TC",
+			"stock_uom": "_Test UOM",
+			"conversion_factor": 1.0,
+			"uom": "_Test UOM"
+		})
+		so = frappe.get_doc(frappe.get_test_records('Sales Order')[0])
+		so.insert(ignore_permissions=True)
+		return so, [item]
diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js
index 9639e7f..da7d133 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js
+++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js
@@ -33,10 +33,13 @@
 					erpnext.utils.map_current_doc({
 						method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_schedule",
 						source_doctype: "Sales Order",
+						target: me.frm,
+						setters: {
+							customer: me.frm.doc.customer || undefined,
+							order_type: me.frm.doc.order_type,
+						},
 						get_query_filters: {
 							docstatus: 1,
-							order_type: me.frm.doc.order_type,
-							customer: me.frm.doc.customer || undefined,
 							company: me.frm.doc.company
 						}
 					});
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
index 62cdf86..e1f501b 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
@@ -27,41 +27,53 @@
 	refresh: function() {
 		frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'}
 
+		var me = this;
+
 		if (this.frm.doc.docstatus===0) {
-			cur_frm.add_custom_button(__('Maintenance Schedule'),
+			this.frm.add_custom_button(__('Maintenance Schedule'),
 				function() {
 					erpnext.utils.map_current_doc({
 						method: "erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule.make_maintenance_visit",
 						source_doctype: "Maintenance Schedule",
+						target: me.frm,
+						setters: {
+							customer: me.frm.doc.customer || undefined,
+						},
 						get_query_filters: {
 							docstatus: 1,
-							customer: cur_frm.doc.customer || undefined,
-							company: cur_frm.doc.company
+							company: me.frm.doc.company
 						}
 					})
 				}, __("Get items from"));
-			cur_frm.add_custom_button(__('Warranty Claim'),
+			this.frm.add_custom_button(__('Warranty Claim'),
 				function() {
 					erpnext.utils.map_current_doc({
 						method: "erpnext.support.doctype.warranty_claim.warranty_claim.make_maintenance_visit",
 						source_doctype: "Warranty Claim",
+						target: me.frm,
+						date_field: "complaint_date",
+						setters: {
+							customer: me.frm.doc.customer || undefined,
+						},
 						get_query_filters: {
 							status: ["in", "Open, Work in Progress"],
-							customer: cur_frm.doc.customer || undefined,
-							company: cur_frm.doc.company
+							company: me.frm.doc.company
 						}
 					})
 				}, __("Get items from"));
-			cur_frm.add_custom_button(__('Sales Order'),
+			this.frm.add_custom_button(__('Sales Order'),
 				function() {
 					erpnext.utils.map_current_doc({
 						method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_visit",
 						source_doctype: "Sales Order",
+						target: me.frm,
+						setters: {
+							customer: me.frm.doc.customer || undefined,
+						},
 						get_query_filters: {
 							docstatus: 1,
-							order_type: cur_frm.doc.order_type,
-							customer: cur_frm.doc.customer || undefined,
-							company: cur_frm.doc.company
+							company: me.frm.doc.company,
+							order_type: me.frm.doc.order_type,
 						}
 					})
 				}, __("Get items from"));
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 8865b50..3a2254e 100644
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -114,63 +114,68 @@
 		}
 	}
 	var _map = function() {
-		// remove first item row if empty
 		if($.isArray(cur_frm.doc.items) && cur_frm.doc.items.length > 0) {
+			// remove first item row if empty
 			if(!cur_frm.doc.items[0].item_code) {
 				cur_frm.doc.items = cur_frm.doc.items.splice(1);
 			}
 
 			// find the doctype of the items table
 			var items_doctype = frappe.meta.get_docfield(cur_frm.doctype, 'items').options;
-			
+
 			// find the link fieldname from items table for the given
 			// source_doctype
 			var link_fieldname = null;
-			frappe.get_meta(items_doctype).fields.forEach(function(d) { 
+			frappe.get_meta(items_doctype).fields.forEach(function(d) {
 				if(d.options===opts.source_doctype) link_fieldname = d.fieldname; });
 
 			// search in existing items if the source_name is already set and full qty fetched
 			var already_set = false;
 			var item_qty_map = {};
-			
-			$.each(cur_frm.doc.items, function(i, d) {
-				if(d[link_fieldname]==opts.source_name) {
-					already_set = true;
-					if (item_qty_map[d.item_code])
-						item_qty_map[d.item_code] += flt(d.qty);
-					else
-						item_qty_map[d.item_code] = flt(d.qty);
-				}
-			});
-			
-			if(already_set) {
-				frappe.model.with_doc(opts.source_doctype, opts.source_name, function(r) {
-					var source_doc = frappe.model.get_doc(opts.source_doctype, opts.source_name);
-					$.each(source_doc.items || [], function(i, row) {
-						if(row.qty > flt(item_qty_map[row.item_code])) {
-							already_set = false;
-							return false;
-						}
-					})
-				})
 
-				if(already_set) {
-					frappe.msgprint(__("You have already selected items from {0} {1}", 
-						[opts.source_doctype, opts.source_name]));
-					return;
-				}
+			$.each(cur_frm.doc.items, function(i, d) {
+				opts.source_name.forEach(function(src) {
+					if(d[link_fieldname]==src) {
+						already_set = true;
+						if (item_qty_map[d.item_code])
+							item_qty_map[d.item_code] += flt(d.qty);
+						else
+							item_qty_map[d.item_code] = flt(d.qty);
+					}
+				});
+			});
+
+			if(already_set) {
+				opts.source_name.forEach(function(src) {
+					frappe.model.with_doc(opts.source_doctype, src, function(r) {
+						var source_doc = frappe.model.get_doc(opts.source_doctype, src);
+						$.each(source_doc.items || [], function(i, row) {
+							if(row.qty > flt(item_qty_map[row.item_code])) {
+								already_set = false;
+								return false;
+							}
+						})
+					})
+
+					if(already_set) {
+						frappe.msgprint(__("You have already selected items from {0} {1}",
+							[opts.source_doctype, src]));
+						return;
+					}
+
+				})
 			}
 		}
 
-
 		return frappe.call({
 			// Sometimes we hit the limit for URL length of a GET request
 			// as we send the full target_doc. Hence this is a POST request.
 			type: "POST",
-			method: opts.method,
+			method: 'frappe.model.mapper.map_docs',
 			args: {
-				"source_name": opts.source_name,
-				"target_doc": cur_frm.doc
+				"method": opts.method,
+				"source_names": opts.source_name,
+				"target_doc": cur_frm.doc,
 			},
 			callback: function(r) {
 				if(!r.exc) {
@@ -181,29 +186,26 @@
 		});
 	}
 	if(opts.source_doctype) {
-		var d = new frappe.ui.Dialog({
-			title: __("Get From ") + __(opts.source_doctype),
-			fields: [
-				{
-					fieldtype: "Link",
-					label: __(opts.source_doctype),
-					fieldname: opts.source_doctype,
-					options: opts.source_doctype,
-					get_query: opts.get_query,
-					reqd:1
-				},
-			]
+		var d = new frappe.ui.form.MultiSelectDialog({
+			doctype: opts.source_doctype,
+			target: opts.target,
+			date_field: opts.date_field || undefined,
+			setters: opts.setters,
+			get_query: opts.get_query,
+			action: function(selections, args) {
+				let values = selections;
+				if(values.length === 0){
+					frappe.msgprint(__("Please select Quotations"))
+					return;
+				}
+				opts.source_name = values;
+				opts.setters = args;
+				d.dialog.hide();
+				_map();
+			},
 		});
-		d.set_primary_action(__('Get Items'), function() {
-			var values = d.get_values();
-			if(!values)
-				return;
-			opts.source_name = values[opts.source_doctype];
-			d.hide();
-			_map();
-		})
-		d.show();
 	} else if(opts.source_name) {
+		opts.source_name = [opts.source_name];
 		_map();
 	}
 }
diff --git a/erpnext/selling/doctype/installation_note/installation_note.js b/erpnext/selling/doctype/installation_note/installation_note.js
index d4b2179..9aff74a 100644
--- a/erpnext/selling/doctype/installation_note/installation_note.js
+++ b/erpnext/selling/doctype/installation_note/installation_note.js
@@ -42,18 +42,23 @@
 	},
 
 	refresh: function() {
+		var me = this;
 		if (this.frm.doc.docstatus===0) {
-			cur_frm.add_custom_button(__('From Delivery Note'),
+			this.frm.add_custom_button(__('From Delivery Note'),
 				function() {
 					erpnext.utils.map_current_doc({
 						method: "erpnext.stock.doctype.delivery_note.delivery_note.make_installation_note",
 						source_doctype: "Delivery Note",
+						target: me.frm,
+						date_field: "posting_date",
+						setters: {
+							customer: me.frm.doc.customer || undefined,
+						},
 						get_query_filters: {
 							docstatus: 1,
 							status: ["not in", ["Stopped", "Closed"]],
 							per_installed: ["<", 99.99],
-							customer: cur_frm.doc.customer || undefined,
-							company: cur_frm.doc.company
+							company: me.frm.doc.company
 						}
 					})
 				}, "fa fa-download", "btn-default"
diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js
index 9c37365..940daaa 100644
--- a/erpnext/selling/doctype/quotation/quotation.js
+++ b/erpnext/selling/doctype/quotation/quotation.js
@@ -25,6 +25,8 @@
 	refresh: function(doc, dt, dn) {
 		this._super(doc, dt, dn);
 
+		var me = this;
+
 		if(doc.docstatus == 1 && doc.status!=='Lost') {
 			cur_frm.add_custom_button(__('Make Sales Order'),
 				cur_frm.cscript['Make Sales Order']);
@@ -36,17 +38,24 @@
 		}
 
 		if (this.frm.doc.docstatus===0) {
-			cur_frm.add_custom_button(__('Opportunity'),
+			this.frm.add_custom_button(__('Opportunity'),
 				function() {
+					var setters = {};
+					if(me.frm.doc.customer) {
+						setters.customer = me.frm.doc.customer || undefined;
+					} else if (me.frm.doc.lead) {
+						setters.lead = me.frm.doc.lead || undefined;
+					}
 					erpnext.utils.map_current_doc({
 						method: "erpnext.crm.doctype.opportunity.opportunity.make_quotation",
 						source_doctype: "Opportunity",
+						target: me.frm,
+						setters: setters,
 						get_query_filters: {
 							status: ["not in", ["Lost", "Closed"]],
-							enquiry_type: cur_frm.doc.order_type,
-							customer: cur_frm.doc.customer || undefined,
-							lead: cur_frm.doc.lead || undefined,
-							company: cur_frm.doc.company
+							company: me.frm.doc.company,
+							// cannot set enquiry_type as setter, as the fieldname is order_type
+							enquiry_type: me.frm.doc.order_type,
 						}
 					})
 				}, __("Get items from"), "btn-default");
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index d32fe77..b5b24f8 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -102,7 +102,7 @@
 		target.run_method("calculate_taxes_and_totals")
 
 	def update_item(obj, target, source_parent):
-		target.stock_qty = flt(obj.qty) * flt(obj.conversion_factor)	
+		target.stock_qty = flt(obj.qty) * flt(obj.conversion_factor)
 
 	doclist = get_mapped_doc("Quotation", source_name, {
 			"Quotation": {
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 0175976..5a4de0b 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -136,12 +136,15 @@
 					erpnext.utils.map_current_doc({
 						method: "erpnext.selling.doctype.quotation.quotation.make_sales_order",
 						source_doctype: "Quotation",
+						target: me.frm,
+						setters: {
+							customer: me.frm.doc.customer || undefined,
+							order_type: me.frm.doc.order_type,
+						},
 						get_query_filters: {
+							company: me.frm.doc.company,
 							docstatus: 1,
 							status: ["!=", "Lost"],
-							order_type: me.frm.doc.order_type,
-							customer: me.frm.doc.customer || undefined,
-							company: me.frm.doc.company
 						}
 					})
 				}, __("Get items from"));
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index 5236031..eb8a750 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -119,13 +119,16 @@
 						erpnext.utils.map_current_doc({
 							method: "erpnext.selling.doctype.sales_order.sales_order.make_delivery_note",
 							source_doctype: "Sales Order",
+							target: me.frm,
+							setters: {
+								customer: me.frm.doc.customer || undefined,
+							},
 							get_query_filters: {
 								docstatus: 1,
 								status: ["!=", "Closed"],
 								per_delivered: ["<", 99.99],
+								company: me.frm.doc.company,
 								project: me.frm.doc.project || undefined,
-								customer: me.frm.doc.customer || undefined,
-								company: me.frm.doc.company
 							}
 						})
 					}, __("Get items from"));
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index be0b4c2..58c16e1 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -95,16 +95,19 @@
 		}
 
 		if (this.frm.doc.docstatus===0) {
-			cur_frm.add_custom_button(__('Sales Order'),
+			this.frm.add_custom_button(__('Sales Order'),
 				function() {
 					erpnext.utils.map_current_doc({
 						method: "erpnext.selling.doctype.sales_order.sales_order.make_material_request",
 						source_doctype: "Sales Order",
+						target: me.frm,
+						setters: {
+							company: me.frm.doc.company
+						},
 						get_query_filters: {
 							docstatus: 1,
 							status: ["!=", "Closed"],
 							per_delivered: ["<", 99.99],
-							company: cur_frm.doc.company
 						}
 					})
 				}, __("Get items from"));
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 383de01..5c97e7c 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -43,6 +43,7 @@
 	},
 
 	refresh: function() {
+		var me = this;
 		this._super();
 		if(this.frm.doc.docstatus===1) {
 			this.show_stock_ledger();
@@ -53,17 +54,20 @@
 
 		if(!this.frm.doc.is_return && this.frm.doc.status!="Closed") {
 			if(this.frm.doc.docstatus==0) {
-				cur_frm.add_custom_button(__('Purchase Order'),
+				this.frm.add_custom_button(__('Purchase Order'),
 					function() {
 						erpnext.utils.map_current_doc({
 							method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_receipt",
 							source_doctype: "Purchase Order",
+							target: me.frm,
+							setters: {
+								supplier: me.frm.doc.supplier || undefined,
+							},
 							get_query_filters: {
-								supplier: cur_frm.doc.supplier || undefined,
 								docstatus: 1,
 								status: ["!=", "Closed"],
 								per_received: ["<", 99.99],
-								company: cur_frm.doc.company
+								company: me.frm.doc.company
 							}
 						})
 				}, __("Get items from"));