[Fix] POS Closing Voucher, on save collected amount becomes zero issue and added test cases (#14649)

* [Fix] POS Closing Voucher, on save collected amount becomes zero

* Added test cases for the POS Closing Voucher
diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
index d993865..c1b033c 100644
--- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
@@ -51,4 +51,6 @@
 	})
 
 	if not frappe.db.exists("POS Profile", "_Test POS Profile"):
-		pos_profile.insert()
\ No newline at end of file
+		pos_profile.insert()
+
+	return pos_profile
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 3364727..3e8881c 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -691,6 +691,7 @@
 		item = make_item("_Test POS Item")
 		pos = copy.deepcopy(test_records[1])
 		pos['items'][0]['item_code'] = item.name
+		pos['items'][0]['warehouse'] = "_Test Warehouse - _TC"
 		pos["is_pos"] = 1
 		pos["offline_pos_name"] = timestamp
 		pos["update_stock"] = 1
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 1fcd11d..3451c62 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -363,4 +363,4 @@
 						"company": obj.company,
 						"income_account": d.income_account
 					})
-				doc.save()
\ No newline at end of file
+				doc.save(ignore_permissions=True)
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 6c0347f..6f9db34 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -166,6 +166,7 @@
 
 	def calculate_net_total(self):
 		self.doc.total_qty = self.doc.total = self.doc.base_total = self.doc.net_total = self.doc.base_net_total = 0.0
+
 		for item in self.doc.get("items"):
 			self.doc.total += item.amount
 			self.doc.total_qty += item.qty
@@ -175,6 +176,9 @@
 
 		self.doc.round_floats_in(self.doc, ["total", "base_total", "net_total", "base_net_total"])
 
+		if self.doc.doctype == 'Sales Invoice' and self.doc.is_pos:
+			self.doc.pos_total_qty = self.doc.total_qty
+
 	def calculate_taxes(self):
 		self.doc.rounding_adjustment = 0
 		# maintain actual tax rate based on idx
diff --git a/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.py b/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.py
index 2b66419..a4a6e86 100644
--- a/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.py
+++ b/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.py
@@ -9,7 +9,6 @@
 from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data
 import json
 
-
 class POSClosingVoucher(Document):
 	def get_closing_voucher_details(self):
 		filters = {
@@ -21,7 +20,6 @@
 			'user': self.user,
 			'is_pos': 1
 		}
-		frappe.log_error(filters)
 
 		invoice_list = get_invoices(filters)
 		self.set_invoice_list(invoice_list)
@@ -29,8 +27,9 @@
 		sales_summary = get_sales_summary(invoice_list)
 		self.set_sales_summary_values(sales_summary)
 
-		mop = get_mode_of_payment_details(invoice_list)
-		self.set_mode_of_payments(mop)
+		if not self.get('payment_reconciliation'):
+			mop = get_mode_of_payment_details(invoice_list)
+			self.set_mode_of_payments(mop)
 
 		taxes = get_tax_details(invoice_list)
 		self.set_taxes(taxes)
@@ -67,11 +66,10 @@
 				'amount': tax['amount']
 			})
 
-
 	def get_payment_reconciliation_details(self):
 		currency = get_company_currency(self)
-		return frappe.render_template("erpnext/selling/doctype/pos_closing_voucher/closing_voucher_details.html", {"data": self, "currency": currency})
-
+		return frappe.render_template("erpnext/selling/doctype/pos_closing_voucher/closing_voucher_details.html",
+			{"data": self, "currency": currency})
 
 @frappe.whitelist()
 def get_cashiers(doctype, txt, searchfield, start, page_len, filters):
@@ -151,7 +149,6 @@
 
 	return tax_breakup
 
-
 def get_sales_summary(invoice_list):
 	net_total = sum(item['net_total'] for item in invoice_list)
 	grand_total = sum(item['grand_total'] for item in invoice_list)
@@ -163,7 +160,6 @@
 	currency = frappe.db.get_value("Company", doc.company, "default_currency")
 	return frappe.get_doc('Currency', currency)
 
-
 def get_invoices(filters):
 	return frappe.db.sql("""select a.name, a.base_grand_total as grand_total,
 		a.base_net_total as net_total, a.pos_total_qty
diff --git a/erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.py b/erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.py
index 12ddbc2..8899aaf 100644
--- a/erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.py
+++ b/erpnext/selling/doctype/pos_closing_voucher/test_pos_closing_voucher.py
@@ -2,8 +2,82 @@
 # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
 # See license.txt
 from __future__ import unicode_literals
-
+import frappe
 import unittest
+from frappe.utils import nowdate
+from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
+from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
 
 class TestPOSClosingVoucher(unittest.TestCase):
-	pass
+	def test_pos_closing_voucher(self):
+		old_user = frappe.session.user
+		user = 'test@example.com'
+		test_user = frappe.get_doc('User', user)
+
+		roles = ("Accounts Manager", "Accounts User", "Sales Manager")
+		test_user.add_roles(*roles)
+		frappe.set_user(user)
+
+		pos_profile = make_pos_profile()
+		pos_profile.append('applicable_for_users', {
+			'default': 1,
+			'user': user
+		})
+
+		pos_profile.save()
+
+		si1 = create_sales_invoice(is_pos=1, rate=3500, do_not_submit=1)
+		si1.append('payments', {
+			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3500
+		})
+		si1.submit()
+
+		si2 = create_sales_invoice(is_pos=1, rate=3200, do_not_submit=1)
+		si2.append('payments', {
+			'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3200
+		})
+		si2.submit()
+
+		pcv_doc = create_pos_closing_voucher(user=user,
+			pos_profile=pos_profile.name, collected_amount=6700)
+
+		pcv_doc.get_closing_voucher_details()
+
+		self.assertEqual(pcv_doc.total_quantity, 2)
+		self.assertEqual(pcv_doc.net_total, 6700)
+
+		payment = pcv_doc.payment_reconciliation[0]
+		self.assertEqual(payment.mode_of_payment, 'Cash')
+
+		si1.load_from_db()
+		si1.cancel()
+
+		si2.load_from_db()
+		si2.cancel()
+
+		test_user.load_from_db()
+		test_user.remove_roles(*roles)
+
+		frappe.set_user(old_user)
+		frappe.db.sql("delete from `tabPOS Profile`")
+
+def create_pos_closing_voucher(**args):
+	args = frappe._dict(args)
+
+	doc = frappe.get_doc({
+		'doctype': 'POS Closing Voucher',
+		'period_start_date': args.period_start_date or nowdate(),
+		'period_end_date': args.period_end_date or nowdate(),
+		'posting_date': args.posting_date or nowdate(),
+		'company': args.company or "_Test Company",
+		'pos_profile': args.pos_profile,
+		'user': args.user or "Administrator",
+	})
+
+	doc.get_closing_voucher_details()
+	if doc.get('payment_reconciliation'):
+		doc.payment_reconciliation[0].collected_amount = (args.collected_amount or
+			doc.payment_reconciliation[0].expected_amount)
+
+	doc.save()
+	return doc
\ No newline at end of file