async call to require, more validation
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 1801f5a..03f9f12 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1,8 +1,6 @@
 // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
-frappe.require("assets/erpnext/js/utils/serial_no_batch_selector.js");
-
 erpnext.TransactionController = erpnext.taxes_and_totals.extend({
 	setup: function() {
 		this._super();
@@ -272,8 +270,10 @@
 		if(['Sales Invoice', 'Purchase Invoice'].includes(this.frm.doc.doctype)) {
 			update_stock = cint(me.frm.doc.update_stock);
 			show_batch_dialog = update_stock;
-		} else if(this.frm.doc.doctype === 'Delivery Note') {
-			show_batch_dialog = 1;
+
+		} else if((this.frm.doc.doctype === 'Purchase Receipt' && me.frm.doc.is_return) ||
+			this.frm.doc.doctype === 'Delivery Note') {
+				show_batch_dialog = 1;
 		}
 
 		// clear barcode if setting item (else barcode will take priority)
@@ -323,19 +323,9 @@
 							if(show_batch_dialog) {
 								var d = locals[cdt][cdn];
 								$.each(r.message, function(k, v) {
-									if(!d[k]) {
-										d[k] = v;
-									}
+									if(!d[k]) d[k] = v;
 								});
-								let serial_no_batch_selector = new erpnext.SerialNoBatchSelector({
-									frm: me.frm,
-									item: d,
-									warehouse_details: {
-										type: "Warehouse",
-										name: d.warehouse
-									},
-								});
-								refresh_field("items");
+								erpnext.show_serial_batch_selector(me.frm, d);
 							}
 						}
 					}
@@ -1193,3 +1183,16 @@
 		}
 	},
 });
+
+erpnext.show_serial_batch_selector = function(frm, d) {
+	frappe.require("assets/erpnext/js/utils/serial_no_batch_selector.js", function() {
+		let serial_no_batch_selector = new erpnext.SerialNoBatchSelector({
+			frm: frm,
+			item: d,
+			warehouse_details: {
+				type: "Warehouse",
+				name: d.warehouse
+			},
+		});
+	});
+}
diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js
index 2b90e3e..ceca9ac 100644
--- a/erpnext/public/js/utils/serial_no_batch_selector.js
+++ b/erpnext/public/js/utils/serial_no_batch_selector.js
@@ -31,8 +31,14 @@
 		this.data = this.oldest ? this.oldest : [];
 		let title = "";
 		let fields = [
-			{fieldname: 'item_code', read_only: 1, fieldtype:'Link', options: 'Item',
-				label: __('Item Code'), 'default': me.item_code},
+			{
+				fieldname: 'item_code',
+				read_only: 1,
+				fieldtype:'Link',
+				options: 'Item',
+				label: __('Item Code'),
+				default: me.item_code
+			},
 			{fieldtype:'Column Break'},
 			{
 				fieldname: 'warehouse',
@@ -51,7 +57,13 @@
 				}
 			},
 			{fieldtype:'Column Break'},
-			{fieldname: 'qty', fieldtype:'Float', label: __(me.has_batch ? 'Total Qty' : 'Qty'), 'default': me.qty},
+			{
+				fieldname: 'qty',
+				fieldtype:'Float',
+				read_only: 1,
+				label: __(me.has_batch ? 'Total Qty' : 'Qty'),
+				default: me.qty
+			},
 		];
 
 		if(this.has_batch) {
@@ -226,11 +238,23 @@
 							return {filters: {item: me.item_code }};
 						},
 						onchange: function(e) {
-							if(this.get_value().length === 0) {
+							let val = this.get_value();
+							if(val.length === 0) {
 								this.grid_row.on_grid_fields_dict
 									.available_qty.set_value(0);
 								return;
 							}
+							let selected_batches = this.grid.grid_rows.map((row) => {
+								if(row === this.grid_row) {
+									return "";
+								}
+								return row.on_grid_fields_dict.batch_no.get_value();
+							});
+							if(selected_batches.includes(val)) {
+								this.set_value("");
+								frappe.throw(__(`Batch ${val} already selected.`));
+								return;
+							}
 							if(me.warehouse_details.name) {
 								frappe.call({
 									method: 'erpnext.stock.doctype.batch.batch.get_batch_qty',
@@ -246,6 +270,7 @@
 								});
 
 							} else {
+								this.set_value("");
 								frappe.throw(__(`Please select a warehouse to get available
 									quantities`));
 							}
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 141faeb..04cf5d7 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -1,7 +1,6 @@
 // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt
 
 frappe.provide("erpnext.stock");
-frappe.require("assets/erpnext/js/utils/serial_no_batch_selector.js");
 
 frappe.ui.form.on('Stock Entry', {
 	setup: function(frm) {
@@ -569,9 +568,12 @@
 		return;
 	}
 
-	let serial_no_batch_selector = new erpnext.SerialNoBatchSelector({
-		frm: frm,
-		item: item,
-		warehouse_details: get_warehouse_type_and_name(item),
+	frappe.require("assets/erpnext/js/utils/serial_no_batch_selector.js", function() {
+		let serial_no_batch_selector = new erpnext.SerialNoBatchSelector({
+			frm: frm,
+			item: item,
+			warehouse_details: get_warehouse_type_and_name(item),
+		});
 	});
+
 }