fix: Missing commits from hotfix branch (#17997)

* fix: merge conflict

* fix: restored missing set_gst_state_and_state_number function

* fix: style linting as per codacy

* fix: Fixes related to customer/lead merging

* fix: merge conflict

* fix: Fixes related to customer/lead merging

* fix: Assign isue/opportunity to user

* fix: Assign isue/opportunity to user

* fix: Replaced Invoice type by GST Category

* fix: merge conflict

* fix: merge conflict

* fix: test cases

* fix: test cases
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index f6914b6..f5ecaeb 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -32,8 +32,8 @@
 		return self.__company_currency
 
 	def onload(self):
-		self.get("__onload").make_payment_via_journal_entry \
-			= frappe.db.get_single_value('Accounts Settings', 'make_payment_via_journal_entry')
+		self.set_onload("make_payment_via_journal_entry",
+			frappe.db.get_single_value('Accounts Settings', 'make_payment_via_journal_entry'))
 
 		if self.is_new():
 			relevant_docs = ("Quotation", "Purchase Order", "Sales Order",
@@ -242,6 +242,10 @@
 				parent_dict.update({"document_type": document_type})
 
 			self.set('pricing_rules', [])
+			# party_name field used for customer in quotation
+			if self.doctype == "Quotation" and self.quotation_to == "Customer" and parent_dict.get("party_name"):
+				parent_dict.update({"customer": parent_dict.get("party_name")})
+
 			for item in self.get("items"):
 				if item.get("item_code"):
 					args = parent_dict.copy()
@@ -1006,11 +1010,11 @@
 
 
 def get_advance_payment_entries(party_type, party, party_account, order_doctype,
-		order_list=None, include_unallocated=True, against_all_orders=False, limit=1000):
+		order_list=None, include_unallocated=True, against_all_orders=False, limit=None):
 	party_account_field = "paid_from" if party_type == "Customer" else "paid_to"
 	payment_type = "Receive" if party_type == "Customer" else "Pay"
 	payment_entries_against_order, unallocated_payment_entries = [], []
-	limit_cond = "limit %s" % (limit or 1000)
+	limit_cond = "limit %s" % limit if limit else ""
 
 	if order_list or against_all_orders:
 		if order_list:
diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py
index bfb8432..9152c31 100644
--- a/erpnext/controllers/item_variant.py
+++ b/erpnext/controllers/item_variant.py
@@ -282,7 +282,7 @@
 
 	if 'description' not in allow_fields:
 		if not variant.description:
-			variant.description = ""
+				variant.description = ""
 
 		if item.variant_based_on=='Item Attribute':
 			if variant.attributes:
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index b82987a..8cf11f7 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -205,11 +205,14 @@
 
 def make_return_doc(doctype, source_name, target_doc=None):
 	from frappe.model.mapper import get_mapped_doc
+	company = frappe.db.get_value("Delivery Note", source_name, "company")
+	default_warehouse_for_sales_return = frappe.db.get_value("Company", company, "default_warehouse_for_sales_return")
 	def set_missing_values(source, target):
 		doc = frappe.get_doc(target)
 		doc.is_return = 1
 		doc.return_against = source.name
 		doc.ignore_pricing_rule = 1
+		doc.set_warehouse = ""
 		if doctype == "Sales Invoice":
 			doc.is_pos = source.is_pos
 
@@ -253,7 +256,6 @@
 
 	def update_item(source_doc, target_doc, source_parent):
 		target_doc.qty = -1* source_doc.qty
-		default_return_warehouse = frappe.db.get_single_value("Stock Settings", "default_return_warehouse")
 		if doctype == "Purchase Receipt":
 			target_doc.received_qty = -1* source_doc.received_qty
 			target_doc.rejected_qty = -1* source_doc.rejected_qty
@@ -278,13 +280,16 @@
 			target_doc.so_detail = source_doc.so_detail
 			target_doc.si_detail = source_doc.si_detail
 			target_doc.expense_account = source_doc.expense_account
-			target_doc.warehouse = default_return_warehouse if default_return_warehouse else source_doc.warehouse
+			if default_warehouse_for_sales_return:
+				target_doc.warehouse = default_warehouse_for_sales_return
 		elif doctype == "Sales Invoice":
 			target_doc.sales_order = source_doc.sales_order
 			target_doc.delivery_note = source_doc.delivery_note
 			target_doc.so_detail = source_doc.so_detail
 			target_doc.dn_detail = source_doc.dn_detail
 			target_doc.expense_account = source_doc.expense_account
+			if default_warehouse_for_sales_return:
+				target_doc.warehouse = default_warehouse_for_sales_return
 
 	def update_terms(source_doc, target_doc, source_parent):
 		target_doc.payment_amount = -source_doc.payment_amount
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index ea18004..2cbe596 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -55,14 +55,28 @@
 		self.set_price_list_and_item_details(for_validate=for_validate)
 
 	def set_missing_lead_customer_details(self):
+		customer, lead = None, None
 		if getattr(self, "customer", None):
+			customer = self.customer
+		elif self.doctype == "Opportunity" and self.party_name:
+			if self.opportunity_from == "Customer":
+				customer = self.party_name
+			else:
+				lead = self.party_name
+		elif self.doctype == "Quotation" and self.party_name:
+			if self.quotation_to == "Customer":
+				customer = self.party_name
+			else:
+				lead = self.party_name
+
+		if customer:
 			from erpnext.accounts.party import _get_party_details
 			fetch_payment_terms_template = False
 			if (self.get("__islocal") or
 				self.company != frappe.db.get_value(self.doctype, self.name, 'company')):
 				fetch_payment_terms_template = True
 
-			party_details = _get_party_details(self.customer,
+			party_details = _get_party_details(customer,
 				ignore_permissions=self.flags.ignore_permissions,
 				doctype=self.doctype, company=self.company,
 				fetch_payment_terms_template=fetch_payment_terms_template,
@@ -71,10 +85,9 @@
 				party_details.pop("sales_team")
 			self.update_if_missing(party_details)
 
-		elif getattr(self, "lead", None):
+		elif lead:
 			from erpnext.crm.doctype.lead.lead import get_lead_details
-			self.update_if_missing(get_lead_details(
-				self.lead,
+			self.update_if_missing(get_lead_details(lead,
 				posting_date=self.get('transaction_date') or self.get('posting_date'),
 				company=self.company))
 
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index 42e0a43..f70870b 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -46,9 +46,9 @@
 	"Sales Invoice": [
 		["Draft", None],
 		["Submitted", "eval:self.docstatus==1"],
+		["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"],
 		["Return", "eval:self.is_return==1 and self.docstatus==1"],
-		["Paid", "eval:self.outstanding_amount<=0 and self.docstatus==1 and self.is_return==0"],
-		["Credit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1 and self.is_return==0 and get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"],
+		["Credit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1"],
 		["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"],
 		["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"],
 		["Cancelled", "eval:self.docstatus==2"],
@@ -56,9 +56,9 @@
 	"Purchase Invoice": [
 		["Draft", None],
 		["Submitted", "eval:self.docstatus==1"],
+		["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"],
 		["Return", "eval:self.is_return==1 and self.docstatus==1"],
-		["Paid", "eval:self.outstanding_amount<=0 and self.docstatus==1 and self.is_return==0"],
-		["Debit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1 and self.is_return==0 and get_value('Purchase Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"],
+		["Debit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1"],
 		["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"],
 		["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"],
 		["Cancelled", "eval:self.docstatus==2"],
@@ -99,6 +99,10 @@
 		["Issued", "eval:self.status != 'Stopped' and self.per_ordered == 100 and self.docstatus == 1 and self.material_request_type == 'Material Issue'"],
 		["Received", "eval:self.status != 'Stopped' and self.per_received == 100 and self.docstatus == 1 and self.material_request_type == 'Purchase'"],
 		["Partially Received", "eval:self.status != 'Stopped' and self.per_received > 0 and self.per_received < 100 and self.docstatus == 1 and self.material_request_type == 'Purchase'"]
+	],
+	"Bank Transaction": [
+		["Unreconciled", "eval:self.docstatus == 1 and self.unallocated_amount>0"],
+		["Reconciled", "eval:self.docstatus == 1 and self.unallocated_amount<=0"]
 	]
 }
 
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 3021f18..2d87a98 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -128,7 +128,7 @@
 			reconciliation_purpose = frappe.db.get_value(self.doctype, self.name, "purpose")
 			is_opening = "Yes" if reconciliation_purpose == "Opening Stock" else "No"
 			details = []
-			for voucher_detail_no, sle in sle_map.items():
+			for voucher_detail_no in sle_map:
 				details.append(frappe._dict({
 					"name": voucher_detail_no,
 					"expense_account": default_expense_account,
@@ -362,10 +362,12 @@
 					frappe.throw(_("Row {0}: Quality Inspection rejected for item {1}")
 						.format(d.idx, d.item_code), QualityInspectionRejectedError)
 			elif qa_required :
-				frappe.msgprint(_("Quality Inspection required for Item {0}").format(d.item_code))
-				if self.docstatus==1:
-					raise QualityInspectionRequiredError
-
+				action = frappe.get_doc('Stock Settings').action_if_quality_inspection_is_not_submitted
+				if self.docstatus==1 and action == 'Stop':
+					frappe.throw(_("Quality Inspection required for Item {0} to submit").format(frappe.bold(d.item_code)),
+						exc=QualityInspectionRequiredError)
+				else:
+					frappe.msgprint(_("Create Quality Inspection for Item {0}").format(frappe.bold(d.item_code)))
 
 	def update_blanket_order(self):
 		blanket_orders = list(set([d.blanket_order for d in self.items if d.blanket_order]))
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index d5f86a1..ebbe3d9 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -616,7 +616,7 @@
 
 	return itemised_tax, itemised_taxable_amount
 
-def get_itemised_tax(taxes):
+def get_itemised_tax(taxes, with_tax_account=False):
 	itemised_tax = {}
 	for tax in taxes:
 		if getattr(tax, "category", None) and tax.category=="Valuation":
@@ -641,6 +641,9 @@
 					tax_amount = tax_amount
 				))
 
+				if with_tax_account:
+					itemised_tax[item_code][tax.description].tax_account = tax.account_head
+
 	return itemised_tax
 
 def get_itemised_taxable_amount(items):
diff --git a/erpnext/controllers/tests/test_mapper.py b/erpnext/controllers/tests/test_mapper.py
index 14738c5..d02308d 100644
--- a/erpnext/controllers/tests/test_mapper.py
+++ b/erpnext/controllers/tests/test_mapper.py
@@ -43,7 +43,7 @@
 		qtn = frappe.get_doc({
 			"doctype": "Quotation",
 			"quotation_to": "Customer",
-			"customer": customer,
+			"party_name": customer,
 			"order_type": "Sales",
 			"transaction_date" : nowdate(),
 			"valid_till" : add_months(nowdate(), 1)