Merge branch 'develop' into breadcrumbs-module-map-2
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 07494a2..c3c3e26 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -187,9 +187,13 @@
 					method: "erpnext.selling.doctype.quotation.quotation.make_sales_invoice",
 					source_doctype: "Quotation",
 					target: me.frm,
-					setters: {
-						customer: me.frm.doc.customer || undefined,
-					},
+					setters: [{
+						fieldtype: 'Link',
+						label: __('Customer'),
+						options: 'Customer',
+						fieldname: 'party_name',
+						default: me.frm.doc.customer,
+					}],
 					get_query_filters: {
 						docstatus: 1,
 						status: ["!=", "Lost"],
diff --git a/erpnext/accounts/report/cash_flow/cash_flow.js b/erpnext/accounts/report/cash_flow/cash_flow.js
index 0422111..03940f4 100644
--- a/erpnext/accounts/report/cash_flow/cash_flow.js
+++ b/erpnext/accounts/report/cash_flow/cash_flow.js
@@ -8,17 +8,19 @@
 	// The last item in the array is the definition for Presentation Currency
 	// filter. It won't be used in cash flow for now so we pop it. Please take
 	// of this if you are working here.
-	frappe.query_reports["Cash Flow"]["filters"].pop();
 
-	frappe.query_reports["Cash Flow"]["filters"].push({
-		"fieldname": "accumulated_values",
-		"label": __("Accumulated Values"),
-		"fieldtype": "Check"
-	});
+	frappe.query_reports["Cash Flow"]["filters"].splice(5, 1);
 
-	frappe.query_reports["Cash Flow"]["filters"].push({
-		"fieldname": "include_default_book_entries",
-		"label": __("Include Default Book Entries"),
-		"fieldtype": "Check"
-	});
+	frappe.query_reports["Cash Flow"]["filters"].push(
+		{
+			"fieldname": "accumulated_values",
+			"label": __("Accumulated Values"),
+			"fieldtype": "Check"
+		},
+		{
+			"fieldname": "include_default_book_entries",
+			"label": __("Include Default Book Entries"),
+			"fieldtype": "Check"
+		}
+	);
 });
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/update_due_date_in_gle.py b/erpnext/patches/v12_0/update_due_date_in_gle.py
index 4c47a82..3484872 100644
--- a/erpnext/patches/v12_0/update_due_date_in_gle.py
+++ b/erpnext/patches/v12_0/update_due_date_in_gle.py
@@ -13,5 +13,5 @@
             WHERE
                 `tabGL Entry`.voucher_no = `tab{doctype}`.name and `tabGL Entry`.party is not null
                 and `tabGL Entry`.voucher_type in ('Sales Invoice', 'Purchase Invoice', 'Journal Entry')
-                and account in (select name from `tabAccount` where account_type in ('Receivable', 'Payable') )""" #nosec
+                and `tabGL Entry`.account in (select name from `tabAccount` where account_type in ('Receivable', 'Payable'))""" #nosec
             .format(doctype=doctype))
diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js
index 824b8d9..750900e 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -141,6 +141,7 @@
 
 	price_list_rate: function(doc, cdt, cdn) {
 		var item = frappe.get_doc(cdt, cdn);
+
 		frappe.model.round_floats_in(item, ["price_list_rate", "discount_percentage"]);
 
 		let item_rate = item.price_list_rate;
@@ -154,6 +155,8 @@
 
 		if (item.discount_amount) {
 			item.rate = flt((item.price_list_rate) - (item.discount_amount), precision('rate', item));
+		} else {
+			item.rate = item_rate;
 		}
 
 		this.calculate_taxes_and_totals();
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index cf48be4..0cd648e 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -573,7 +573,6 @@
 				if(!r.exc) {
 					var doc = frappe.model.sync(r.message);
 					cur_frm.dirty();
-					erpnext.utils.clear_duplicates();
 					cur_frm.refresh();
 				}
 			}
@@ -604,28 +603,6 @@
 	}
 }
 
-erpnext.utils.clear_duplicates = function() {
-	if(!cur_frm.doc.items) return;
-	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;
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 26ca7c6..39dda92 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -107,7 +107,7 @@
 	refresh: function(doc, dt, dn) {
 		var me = this;
 		this._super();
-		var allow_delivery = false;
+		let allow_delivery = false;
 
 		if(doc.docstatus==1) {
 			if(this.frm.has_perm("submit")) {
@@ -132,6 +132,8 @@
 			if(doc.status !== 'Closed') {
 				if(doc.status !== 'On Hold') {
 
+					allow_delivery = this.frm.doc.items.some(item => item.delivered_by_supplier === 0 && item.qty > flt(item.delivered_qty))
+
 					if (this.frm.has_perm("submit")) {
 						if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed) < 100) {
 							// hold
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index 9d93f37..2d9650c 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -136,7 +136,7 @@
 
 	var time_to_resolve = get_status(frm.doc.resolution_by_variance);
 	if (!frm.doc.resolution_date && frm.doc.agreement_fulfilled === "Ongoing") {
-		time_to_resolve = get_time_left(frm.doc.response_by, frm.doc.agreement_fulfilled);
+		time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_fulfilled);
 	}
 
 	frm.dashboard.set_headline_alert(