feat: add checkbox to reserve qty on sales return
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json
index 2abb169..7e2d1c7 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.json
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.json
@@ -20,6 +20,7 @@
   "editable_price_list_rate",
   "validate_selling_price",
   "editable_bundle_item_rates",
+  "dont_reserve_sales_order_qty_on_sales_return",
   "sales_transactions_settings_section",
   "so_required",
   "dn_required",
@@ -172,6 +173,12 @@
    "fieldname": "enable_discount_accounting",
    "fieldtype": "Check",
    "label": "Enable Discount Accounting for Selling"
+  },
+  {
+   "default": "0",
+   "fieldname": "dont_reserve_sales_order_qty_on_sales_return",
+   "fieldtype": "Check",
+   "label": "Don't Reserve Sales Order Qty on Sales Return"
   }
  ],
  "icon": "fa fa-cog",
@@ -179,7 +186,7 @@
  "index_web_pages_for_search": 1,
  "issingle": 1,
  "links": [],
- "modified": "2022-05-31 19:39:48.398738",
+ "modified": "2022-06-17 12:30:57.221570",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Selling Settings",
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index ce90eec..8dd2d11 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -1064,11 +1064,23 @@
 
 		self.assertEqual(dn.items[0].rate, rate)
 
-	def test_reserved_qty(self):
+	def test_reserve_qty_on_sales_return(self):
+		frappe.db.set_single_value("Selling Settings", "dont_reserve_sales_order_qty_on_sales_return", 0)
+		self.reserved_qty_check()
+
+	def test_dont_reserve_qty_on_sales_return(self):
+		frappe.db.set_single_value("Selling Settings", "dont_reserve_sales_order_qty_on_sales_return", 1)
+		self.reserved_qty_check()
+
+	def reserved_qty_check(self):
 		from erpnext.controllers.sales_and_purchase_return import make_return_doc
 		from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
 		from erpnext.stock.stock_balance import get_reserved_qty
 
+		dont_reserve_qty = frappe.db.get_single_value(
+			"Selling Settings", "dont_reserve_sales_order_qty_on_sales_return"
+		)
+
 		item = make_item().name
 		warehouse = "_Test Warehouse - _TC"
 		qty_to_reserve = 5
@@ -1093,8 +1105,8 @@
 		returned = frappe.get_doc("Delivery Note", dn_return.name)
 		returned.update_prevdoc_status()
 
-		# Test that item qty is not reserved on sales return.
-		self.assertEqual(get_reserved_qty(item, warehouse), 0)
+		# Test that item qty is not reserved on sales return, if selling setting don't reserve qty is checked.
+		self.assertEqual(get_reserved_qty(item, warehouse), 0 if dont_reserve_qty else qty_to_reserve)
 
 
 def create_delivery_note(**args):
diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py
index 2f5bac9..fbb5bf8 100644
--- a/erpnext/stock/stock_balance.py
+++ b/erpnext/stock/stock_balance.py
@@ -98,10 +98,6 @@
 
 
 def get_reserved_qty(item_code, warehouse):
-	SalesOrder = DocType("Sales Order")
-	SalesOrderItem = DocType("Sales Order Item")
-	PackedItem = DocType("Packed Item")
-
 	def append_open_so_query(q: QueryBuilder, child_table: Table) -> QueryBuilder:
 		return (
 			q.inner_join(SalesOrder)
@@ -110,19 +106,29 @@
 			.where(SalesOrder.status != "Closed")
 		)
 
+	SalesOrder = DocType("Sales Order")
+	SalesOrderItem = DocType("Sales Order Item")
+	PackedItem = DocType("Packed Item")
+
+	dont_reserve_qty_on_sales_return = frappe.db.get_single_value(
+		"Selling Settings", "dont_reserve_sales_order_qty_on_sales_return"
+	)
+
 	tab = (
 		frappe.qb.from_(SalesOrderItem)
-		.select(
-			SalesOrderItem.stock_qty.as_("dnpi_qty"),
-			SalesOrderItem.qty.as_("so_item_qty"),
-			SalesOrderItem.delivered_qty.as_("so_item_delivered_qty"),
-			SalesOrderItem.returned_qty.as_("so_item_returned_qty"),
-			SalesOrderItem.parent,
-			SalesOrderItem.name,
-		)
 		.where(SalesOrderItem.item_code == item_code)
 		.where(SalesOrderItem.warehouse == warehouse)
 	)
+	for field, cond in [
+		(SalesOrderItem.stock_qty.as_("dnpi_qty"), 1),
+		(SalesOrderItem.qty.as_("so_item_qty"), 1),
+		(SalesOrderItem.delivered_qty.as_("so_item_delivered_qty"), 1),
+		(SalesOrderItem.returned_qty.as_("so_item_returned_qty"), dont_reserve_qty_on_sales_return),
+		(SalesOrderItem.parent, 1),
+		(SalesOrderItem.name, 1),
+	]:
+		if cond:
+			tab = tab.select(field)
 	tab = append_open_so_query(tab, SalesOrderItem)
 
 	dnpi = (
@@ -131,28 +137,23 @@
 		.where(PackedItem.item_code == item_code)
 		.where(PackedItem.warehouse == warehouse)
 	)
-	dnpi = append_open_so_query(dnpi, PackedItem)
+	append_open_so_query(dnpi, PackedItem)
 
-	qty_queries = {}
-	for key, so_item_field in [
-		("so_item_qty", "qty"),
-		("so_item_delivered_qty", "delivered_qty"),
-		("so_item_returned_qty", "returned_qty"),
+	dnpi_parent = frappe.qb.from_(dnpi).select(dnpi.qty.as_("dnpi_qty"))
+	for key, so_item_field, cond in [
+		("so_item_qty", "qty", 1),
+		("so_item_delivered_qty", "delivered_qty", 1),
+		("so_item_returned_qty", "returned_qty", dont_reserve_qty_on_sales_return),
 	]:
-		qty_queries.update(
-			{
-				key: (
+		if cond:
+			dnpi_parent = dnpi_parent.select(
+				(
 					frappe.qb.from_(SalesOrderItem)
 					.select(SalesOrderItem[so_item_field])
 					.where(SalesOrderItem.name == dnpi.parent_detail_docname)
 					.where(SalesOrderItem.delivered_by_supplier == 0)
-				)
-			}
-		)
-
-	dnpi_parent = frappe.qb.from_(dnpi).select(dnpi.qty.as_("dnpi_qty"))
-	for key, query in qty_queries.items():
-		dnpi_parent = dnpi_parent.select(query.as_(key))
+				).as_(key)
+			)
 	dnpi_parent = dnpi_parent.select(dnpi.parent, dnpi.name)
 
 	dnpi_parent = dnpi_parent + tab
@@ -166,7 +167,7 @@
 					(
 						dnpi_parent.so_item_qty
 						- dnpi_parent.so_item_delivered_qty
-						- dnpi_parent.so_item_returned_qty
+						- (dnpi_parent.so_item_returned_qty if dont_reserve_qty_on_sales_return else 0)
 					)
 					/ dnpi_parent.so_item_qty
 				)