fix(pos): remove returned sr. nos. from pos reserved sr. nos. list
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json
index 0c6e7ed..b850027 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json
@@ -264,7 +264,6 @@
    "print_hide": 1
   },
   {
-   "allow_on_submit": 1,
    "default": "0",
    "fieldname": "is_return",
    "fieldtype": "Check",
@@ -1573,7 +1572,7 @@
  "icon": "fa fa-file-text",
  "is_submittable": 1,
  "links": [],
- "modified": "2021-10-05 12:11:53.871828",
+ "modified": "2022-03-22 13:00:24.166684",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "POS Invoice",
@@ -1623,6 +1622,7 @@
  "show_name_in_global_search": 1,
  "sort_field": "modified",
  "sort_order": "DESC",
+ "states": [],
  "timeline_field": "customer",
  "title_field": "title",
  "track_changes": 1,
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
index 9e6b7ce..7239dee 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
@@ -16,7 +16,11 @@
 )
 from erpnext.accounts.party import get_due_date, get_party_account
 from erpnext.stock.doctype.batch.batch import get_batch_qty, get_pos_reserved_batch_qty
-from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos, get_serial_nos
+from erpnext.stock.doctype.serial_no.serial_no import (
+	get_delivered_serial_nos,
+	get_pos_reserved_serial_nos,
+	get_serial_nos,
+)
 
 
 class POSInvoice(SalesInvoice):
@@ -145,12 +149,7 @@
 						.format(item.idx, bold_invalid_batch_no, bold_item_name, bold_extra_batch_qty_needed), title=_("Item Unavailable"))
 
 	def validate_delivered_serial_nos(self, item):
-		serial_nos = get_serial_nos(item.serial_no)
-		delivered_serial_nos = frappe.db.get_list('Serial No', {
-			'item_code': item.item_code,
-			'name': ['in', serial_nos],
-			'sales_invoice': ['is', 'set']
-		}, pluck='name')
+		delivered_serial_nos = get_delivered_serial_nos(item.serial_no)
 
 		if delivered_serial_nos:
 			bold_delivered_serial_nos = frappe.bold(', '.join(delivered_serial_nos))
diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
index cf8affd..a76ae12 100644
--- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
@@ -610,6 +610,78 @@
 			pos_inv.delete()
 			pr.delete()
 
+	def test_delivered_serial_no_case(self):
+		from erpnext.accounts.doctype.pos_invoice_merge_log.test_pos_invoice_merge_log import (
+			init_user_and_profile,
+		)
+		from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
+		from erpnext.stock.doctype.serial_no.test_serial_no import get_serial_nos
+		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
+
+		frappe.db.savepoint('before_test_delivered_serial_no_case')
+		try:
+			se = make_serialized_item()
+			serial_no = get_serial_nos(se.get("items")[0].serial_no)[0]
+
+			dn = create_delivery_note(
+					item_code="_Test Serialized Item With Series", serial_no=serial_no
+			)
+
+			delivery_document_no = frappe.db.get_value("Serial No", serial_no, "delivery_document_no")
+			self.assertEquals(delivery_document_no, dn.name)
+
+			init_user_and_profile()
+
+			pos_inv = create_pos_invoice(
+					item_code="_Test Serialized Item With Series",
+					serial_no=serial_no,
+					qty=1,
+					rate=100,
+					do_not_submit=True
+			)
+
+			self.assertRaises(frappe.ValidationError, pos_inv.submit)
+
+		finally:
+			frappe.db.rollback(save_point='before_test_delivered_serial_no_case')
+			frappe.set_user("Administrator")
+
+	def test_returned_serial_no_case(self):
+		from erpnext.accounts.doctype.pos_invoice_merge_log.test_pos_invoice_merge_log import (
+			init_user_and_profile,
+		)
+		from erpnext.stock.doctype.serial_no.serial_no import get_pos_reserved_serial_nos
+		from erpnext.stock.doctype.serial_no.test_serial_no import get_serial_nos
+		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
+
+		frappe.db.savepoint('before_test_returned_serial_no_case')
+		try:
+			se = make_serialized_item()
+			serial_no = get_serial_nos(se.get("items")[0].serial_no)[0]
+
+			init_user_and_profile()
+
+			pos_inv = create_pos_invoice(
+					item_code="_Test Serialized Item With Series",
+					serial_no=serial_no,
+					qty=1,
+					rate=100,
+			)
+
+			pos_return = make_sales_return(pos_inv.name)
+			pos_return.flags.ignore_validate = True
+			pos_return.insert()
+			pos_return.submit()
+
+			pos_reserved_serial_nos = get_pos_reserved_serial_nos({
+				'item_code': '_Test Serialized Item With Series',
+				'warehouse': '_Test Warehouse - _TC'
+			})
+			self.assertTrue(serial_no not in pos_reserved_serial_nos)
+
+		finally:
+			frappe.db.rollback(save_point='before_test_returned_serial_no_case')
+			frappe.set_user("Administrator")
 
 def create_pos_invoice(**args):
 	args = frappe._dict(args)
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index bf62f50..df872af 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -585,25 +585,65 @@
 
 	return [d.get('name') for d in serial_numbers]
 
+def get_delivered_serial_nos(serial_nos):
+	'''
+	Returns serial numbers that delivered from the list of serial numbers
+	'''
+	from frappe.query_builder.functions import Coalesce
+
+	SerialNo = frappe.qb.DocType("Serial No")
+	serial_nos = get_serial_nos(serial_nos)
+	query = (
+		frappe.qb
+			.from_(SerialNo)
+			.select(SerialNo.name)
+			.where(
+				(SerialNo.name.isin(serial_nos))
+				& (Coalesce(SerialNo.delivery_document_type, "") != "")
+			)
+	)
+
+	result = query.run()
+	if result and len(result) > 0:
+		delivered_serial_nos = [row[0] for row in result]
+		return delivered_serial_nos
+
 @frappe.whitelist()
 def get_pos_reserved_serial_nos(filters):
 	if isinstance(filters, str):
 		filters = json.loads(filters)
 
-	pos_transacted_sr_nos = frappe.db.sql("""select item.serial_no as serial_no
-		from `tabPOS Invoice` p, `tabPOS Invoice Item` item
-		where p.name = item.parent
-		and p.consolidated_invoice is NULL
-		and p.docstatus = 1
-		and item.docstatus = 1
-		and item.item_code = %(item_code)s
-		and item.warehouse = %(warehouse)s
-		and item.serial_no is NOT NULL and item.serial_no != ''
-		""", filters, as_dict=1)
+	POSInvoice = frappe.qb.DocType("POS Invoice")
+	POSInvoiceItem = frappe.qb.DocType("POS Invoice Item")
+	query = frappe.qb.from_(
+		POSInvoice
+	).from_(
+		POSInvoiceItem
+	).select(
+		POSInvoice.is_return,
+		POSInvoiceItem.serial_no
+	).where(
+		(POSInvoice.name == POSInvoiceItem.parent)
+		& (POSInvoice.docstatus == 1)
+		& (POSInvoiceItem.docstatus == 1)
+		& (POSInvoiceItem.item_code == filters.get('item_code'))
+		& (POSInvoiceItem.warehouse == filters.get('warehouse'))
+		& (POSInvoiceItem.serial_no.isnotnull())
+		& (POSInvoiceItem.serial_no != '')
+	)
+
+	pos_transacted_sr_nos = query.run(as_dict=True)
 
 	reserved_sr_nos = []
+	returned_sr_nos = []
 	for d in pos_transacted_sr_nos:
-		reserved_sr_nos += get_serial_nos(d.serial_no)
+		if d.is_return == 0:
+			reserved_sr_nos += get_serial_nos(d.serial_no)
+		elif d.is_return == 1:
+			returned_sr_nos += get_serial_nos(d.serial_no)
+
+	for sr_no in returned_sr_nos:
+		reserved_sr_nos.remove(sr_no)
 
 	return reserved_sr_nos