fix(Utils): Do not add duplicate items (#17896)

* fix: do not add duplicate items

* Update erpnext/public/js/utils.js

Co-Authored-By: Rohan <Alchez@users.noreply.github.com>

* fix: compare warehouses, batch and qty for an item

* fix: code fixes

* Update utils.js

* fix: check required_date and delivery_date

* Update utils.js

* fix: mixed tabs and spaces
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index f4bb64a..64b96b5 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -563,6 +563,7 @@
 				if(!r.exc) {
 					var doc = frappe.model.sync(r.message);
 					cur_frm.dirty();
+					erpnext.utils.clear_duplicates();
 					cur_frm.refresh();
 				}
 			}
@@ -593,6 +594,27 @@
 	}
 }
 
+erpnext.utils.clear_duplicates = function() {
+	const unique_items = new Map();
+	/*
+		Create a Map of items with
+		item_code => [qty, warehouse, batch_no]
+	*/
+	let items = [];
+
+	for (let item of cur_frm.doc.items) {
+		if (!(unique_items.has(item.item_code) && unique_items.get(item.item_code)[0] === item.qty &&
+			unique_items.get(item.item_code)[1] === item.warehouse && unique_items.get(item.item_code)[2] === item.batch_no &&
+			unique_items.get(item.item_code)[3] === item.delivery_date && unique_items.get(item.item_code)[4] === item.required_date &&
+			unique_items.get(item.item_code)[5] === item.rate)) {
+
+			unique_items.set(item.item_code, [item.qty, item.warehouse, item.batch_no, item.delivery_date, item.required_date, item.rate]);
+			items.push(item);
+		}
+	}
+	cur_frm.doc.items = items;
+}
+
 frappe.form.link_formatters['Item'] = function(value, doc) {
 	if(doc && doc.item_name && doc.item_name !== value) {
 		return value? value + ': ' + doc.item_name: doc.item_name;