Merge branch 'develop' into fix-student-email-id
diff --git a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
index 0fe57c3..2754633 100644
--- a/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
@@ -91,15 +91,11 @@
 		self.assertEqual(frappe.db.get_value("Bank Transaction", bank_transaction.name, "unallocated_amount"), 0)
 		self.assertTrue(frappe.db.get_value("Sales Invoice Payment", dict(parent=payment.name), "clearance_date") is not None)
 
-def add_transactions():
-	if frappe.flags.test_bank_transactions_created:
-		return
-
-	frappe.set_user("Administrator")
+def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
 	try:
 		frappe.get_doc({
 			"doctype": "Bank",
-			"bank_name":"Citi Bank",
+			"bank_name":bank_name,
 		}).insert()
 	except frappe.DuplicateEntryError:
 		pass
@@ -108,12 +104,19 @@
 		frappe.get_doc({
 			"doctype": "Bank Account",
 			"account_name":"Checking Account",
-			"bank": "Citi Bank",
-			"account": "_Test Bank - _TC"
+			"bank": bank_name,
+			"account": account_name
 		}).insert()
 	except frappe.DuplicateEntryError:
 		pass
 
+def add_transactions():
+	if frappe.flags.test_bank_transactions_created:
+		return
+
+	frappe.set_user("Administrator")
+	create_bank_account()
+
 	doc = frappe.get_doc({
 		"doctype": "Bank Transaction",
 		"description":"1512567 BG/000002918 OPSKATTUZWXXX AT776000000098709837 Herr G",
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 0a385d0..34c262e 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -1023,7 +1023,7 @@
 	return journal_entry.as_dict()
 
 @frappe.whitelist()
-def make_reverse_journal_entry(source_name, target_doc=None, ignore_permissions=False):
+def make_reverse_journal_entry(source_name, target_doc=None):
 	from frappe.model.mapper import get_mapped_doc
 
 	def update_accounts(source, target, source_parent):
@@ -1049,6 +1049,6 @@
 			},
 			"postprocess": update_accounts,
 		},
-	}, target_doc, ignore_permissions=ignore_permissions)
+	}, target_doc)
 
 	return doclist
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 842c64f..bb312bf 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -1172,30 +1172,23 @@
 	from frappe.model.mapper import get_mapped_doc
 	def set_missing_values(source, target):
 		target.payment_order_type = "Payment Entry"
+		target.append('references', dict(
+			reference_doctype="Payment Entry",
+			reference_name=source.name,
+			bank_account=source.party_bank_account,
+			amount=source.paid_amount,
+			account=source.paid_to,
+			supplier=source.party,
+			mode_of_payment=source.mode_of_payment,
+		))
 
-	def update_item(source_doc, target_doc, source_parent):
-		target_doc.bank_account = source_parent.party_bank_account
-		target_doc.amount = source_doc.allocated_amount
-		target_doc.account = source_parent.paid_to
-		target_doc.payment_entry = source_parent.name
-		target_doc.supplier = source_parent.party
-		target_doc.mode_of_payment = source_parent.mode_of_payment
-
-
-	doclist = get_mapped_doc("Payment Entry", source_name,	{
+	doclist = get_mapped_doc("Payment Entry", source_name, {
 		"Payment Entry": {
 			"doctype": "Payment Order",
 			"validation": {
 				"docstatus": ["=", 1]
-			}
-		},
-		"Payment Entry Reference": {
-			"doctype": "Payment Order Reference",
-			"validation": {
-				"docstatus": ["=", 1]
 			},
-			"postprocess": update_item
-		},
+		}
 
 	}, target_doc, set_missing_values)
 
diff --git a/erpnext/accounts/doctype/payment_order/payment_order.py b/erpnext/accounts/doctype/payment_order/payment_order.py
index e5880aa..8d29ae7 100644
--- a/erpnext/accounts/doctype/payment_order/payment_order.py
+++ b/erpnext/accounts/doctype/payment_order/payment_order.py
@@ -21,10 +21,15 @@
 		if cancel:
 			status = 'Initiated'
 
-		ref_field = "status" if self.payment_order_type == "Payment Request" else "payment_order_status"
+		if self.payment_order_type == "Payment Request":
+			ref_field = "status"
+			ref_doc_field = frappe.scrub(self.payment_order_type)
+		else:
+			ref_field = "payment_order_status"
+			ref_doc_field = "reference_name"
 
 		for d in self.references:
-			frappe.db.set_value(self.payment_order_type, d.get(frappe.scrub(self.payment_order_type)), ref_field, status)
+			frappe.db.set_value(self.payment_order_type, d.get(ref_doc_field), ref_field, status)
 
 @frappe.whitelist()
 @frappe.validate_and_sanitize_search_inputs
diff --git a/erpnext/accounts/doctype/payment_order/test_payment_order.py b/erpnext/accounts/doctype/payment_order/test_payment_order.py
index 711c4cc..1c23e2a 100644
--- a/erpnext/accounts/doctype/payment_order/test_payment_order.py
+++ b/erpnext/accounts/doctype/payment_order/test_payment_order.py
@@ -5,6 +5,45 @@
 
 import frappe
 import unittest
+from frappe.utils import getdate
+from erpnext.accounts.doctype.bank_transaction.test_bank_transaction import create_bank_account
+from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry, make_payment_order
+from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
 
 class TestPaymentOrder(unittest.TestCase):
-	pass
+	def setUp(self):
+		create_bank_account()
+
+	def tearDown(self):
+		for bt in frappe.get_all("Payment Order"):
+			doc = frappe.get_doc("Payment Order", bt.name)
+			doc.cancel()
+			doc.delete()
+
+	def test_payment_order_creation_against_payment_entry(self):
+		purchase_invoice = make_purchase_invoice()
+		payment_entry = get_payment_entry("Purchase Invoice", purchase_invoice.name, bank_account="_Test Bank - _TC")
+		payment_entry.reference_no = "_Test_Payment_Order"
+		payment_entry.reference_date = getdate()
+		payment_entry.party_bank_account = "Checking Account - Citi Bank"
+		payment_entry.insert()
+		payment_entry.submit()
+
+		doc = create_payment_order_against_payment_entry(payment_entry, "Payment Entry")
+		reference_doc = doc.get("references")[0]
+		self.assertEquals(reference_doc.reference_name, payment_entry.name)
+		self.assertEquals(reference_doc.reference_doctype, "Payment Entry")
+		self.assertEquals(reference_doc.supplier, "_Test Supplier")
+		self.assertEquals(reference_doc.amount, 250)
+
+def create_payment_order_against_payment_entry(ref_doc, order_type):
+	payment_order = frappe.get_doc(dict(
+		doctype="Payment Order",
+		company="_Test Company",
+		payment_order_type=order_type,
+		company_bank_account="Checking Account - Citi Bank"
+	))
+	doc = make_payment_order(ref_doc.name, payment_order)
+	doc.save()
+	doc.submit()
+	return doc
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json b/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json
index db0b761..d94ba74 100644
--- a/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json
+++ b/erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "creation": "2018-07-20 16:38:06.630813",
  "doctype": "DocType",
  "editable_grid": 1,
@@ -10,7 +11,6 @@
   "column_break_4",
   "supplier",
   "payment_request",
-  "payment_entry",
   "mode_of_payment",
   "bank_account_details",
   "bank_account",
@@ -103,17 +103,12 @@
    "no_copy": 1,
    "print_hide": 1,
    "read_only": 1
-  },
-  {
-   "fieldname": "payment_entry",
-   "fieldtype": "Link",
-   "label": "Payment Entry",
-   "options": "Payment Entry",
-   "read_only": 1
   }
  ],
+ "index_web_pages_for_search": 1,
  "istable": 1,
- "modified": "2019-05-08 13:56:25.724557",
+ "links": [],
+ "modified": "2020-09-04 08:29:51.014390",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Payment Order Reference",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 4f6be59..2bfa4a5 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -25,6 +25,12 @@
 				this.frm.set_df_property("credit_to", "print_hide", 0);
 			}
 		}
+
+		// Trigger supplier event on load if supplier is available
+		// The reason for this is PI can be created from PR or PO and supplier is pre populated
+		if (this.frm.doc.supplier) {
+			this.frm.trigger('supplier');
+		}
 	},
 
 	refresh: function(doc) {
@@ -135,6 +141,8 @@
 				}
 			});
 		}
+
+		this.frm.set_df_property("tax_withholding_category", "hidden", doc.apply_tds ? 0 : 1);
 	},
 
 	unblock_invoice: function() {
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 7b1062f..b4ee7c9 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -132,6 +132,11 @@
 		if not self.due_date:
 			self.due_date = get_due_date(self.posting_date, "Supplier", self.supplier, self.company,  self.bill_date)
 
+		tds_category = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category")
+		if tds_category and not for_validate:
+			self.apply_tds = 1
+			self.tax_withholding_category = tds_category
+
 		super(PurchaseInvoice, self).set_missing_values(for_validate)
 
 	def check_conversion_rate(self):
diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
index 219871b..d011689 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
@@ -256,7 +256,7 @@
 	"""accumulate children's values in parent accounts"""
 	for d in reversed(accounts):
 		if d.parent_account:
-			account = d.parent_account.split('-')[0].strip()
+			account = d.parent_account.split(' - ')[0].strip()
 			if not accounts_by_name.get(account):
 				continue
 
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 0bd03a8..9d08d92 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -146,7 +146,7 @@
 			'assets': assets,
 			'purpose': 'Receipt',
 			'company': self.company,
-			'transaction_date': getdate(nowdate()),
+			'transaction_date': getdate(self.purchase_date),
 			'reference_doctype': reference_doctype,
 			'reference_name': reference_docname
 		}).insert()
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index 0dc9878..9feac78 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -255,7 +255,7 @@
 				args['second_source_condition'] = """ + ifnull((select sum(%(second_source_field)s)
 					from `tab%(second_source_dt)s`
 					where `%(second_join_field)s`="%(detail_id)s"
-					and (`tab%(second_source_dt)s`.docstatus=1) %(second_source_extra_cond)s), 0) """ % args
+					and (`tab%(second_source_dt)s`.docstatus=1) %(second_source_extra_cond)s FOR UPDATE), 0)""" % args
 
 			if args['detail_id']:
 				if not args.get("extra_cond"): args["extra_cond"] = ""
diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py
index 45b7060..373b940 100644
--- a/erpnext/hr/doctype/attendance/attendance.py
+++ b/erpnext/hr/doctype/attendance/attendance.py
@@ -98,7 +98,8 @@
 		e = {
 			"name": d.name,
 			"doctype": "Attendance",
-			"date": d.attendance_date,
+			"start": d.attendance_date,
+			"end": d.attendance_date,
 			"title": cstr(d.status),
 			"docstatus": d.docstatus
 		}
diff --git a/erpnext/hr/doctype/attendance/attendance_calendar.js b/erpnext/hr/doctype/attendance/attendance_calendar.js
index 104f09d..4566489 100644
--- a/erpnext/hr/doctype/attendance/attendance_calendar.js
+++ b/erpnext/hr/doctype/attendance/attendance_calendar.js
@@ -1,12 +1,6 @@
 // Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
 // For license information, please see license.txt
 frappe.views.calendar["Attendance"] = {
-	field_map: {
-		"start": "attendance_date",
-		"end": "attendance_date",
-		"id": "name",
-		"docstatus": 1
-	},
 	options: {
 		header: {
 			left: 'prev,next today',
diff --git a/erpnext/hr/doctype/shift_assignment/shift_assignment.py b/erpnext/hr/doctype/shift_assignment/shift_assignment.py
index f8b7334..2c385e8 100644
--- a/erpnext/hr/doctype/shift_assignment/shift_assignment.py
+++ b/erpnext/hr/doctype/shift_assignment/shift_assignment.py
@@ -103,7 +103,7 @@
 			"doctype": "Shift Assignment",
 			"start_date": d.start_date,
 			"end_date": d.end_date if d.end_date else nowdate(),
-			"title": cstr(d.employee_name) + \
+			"title": cstr(d.employee_name) + ": "+ \
 				cstr(d.shift_type),
 			"docstatus": d.docstatus
 		}
diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py
index e2e27dd..d1b7589 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -240,15 +240,19 @@
 		unpledge_request = create_loan_security_unpledge(security_map, pledge_doc.loan,
 			pledge_doc.company, pledge_doc.applicant_type, pledge_doc.applicant)
 
-	if approve:
-		unpledge_request.status = 'Approved'
-
 	if save:
 		unpledge_request.save()
 
 	if submit:
 		unpledge_request.submit()
 
+	if approve:
+		if unpledge_request.docstatus == 1:
+			unpledge_request.status = 'Approved'
+			unpledge_request.save()
+		else:
+			frappe.throw(_('Only submittted unpledge requests can be approved'))
+
 	if as_dict:
 		return unpledge_request
 	else:
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index f225409..5a4a19a 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -317,6 +317,11 @@
 		self.assertEqual(loan.status, 'Closed')
 		self.assertEquals(sum(pledged_qty.values()), 0)
 
+		amounts = amounts = calculate_amounts(loan.name, add_days(last_date, 6), "Regular Repayment")
+		self.assertEqual(amounts['pending_principal_amount'], 0)
+		self.assertEqual(amounts['payable_principal_amount'], 0)
+		self.assertEqual(amounts['interest_amount'], 0)
+
 	def test_disbursal_check_with_shortfall(self):
 		pledges = [{
 			"loan_security": "Test Security 2",
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index 47fb885..97dbc44 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -327,7 +327,7 @@
 		if not final_due_date:
 			final_due_date = add_days(due_date, loan_type_details.grace_period_in_days)
 
-	if against_loan_doc.status in ('Disbursed', 'Loan Closure Requested'):
+	if against_loan_doc.status in ('Disbursed', 'Loan Closure Requested', 'Closed'):
 		pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
 	else:
 		pending_principal_amount = against_loan_doc.disbursed_amount
diff --git a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py
index a87d832..b3eb600 100644
--- a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py
+++ b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py
@@ -20,9 +20,6 @@
 		self.update_loan_status(cancel=1)
 		self.db_set('status', 'Requested')
 
-	def on_submit(self):
-		self.approve()
-
 	def validate_duplicate_securities(self):
 		security_list = []
 		for d in self.securities:
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index aa7996e..6c58f2f 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -697,7 +697,7 @@
 execute:frappe.delete_doc("Report", "Department Analytics")
 execute:frappe.rename_doc("Desk Page", "Loan Management", "Loan", force=True)
 erpnext.patches.v12_0.update_uom_conversion_factor
-execute:frappe.delete_doc_if_exists("Page", "pos") #29-05-2020
+erpnext.patches.v13_0.replace_pos_page_with_point_of_sale_page
 erpnext.patches.v13_0.delete_old_purchase_reports
 erpnext.patches.v12_0.set_italian_import_supplier_invoice_permissions
 erpnext.patches.v13_0.update_subscription
diff --git a/erpnext/patches/v13_0/replace_pos_page_with_point_of_sale_page.py b/erpnext/patches/v13_0/replace_pos_page_with_point_of_sale_page.py
new file mode 100644
index 0000000..390e217
--- /dev/null
+++ b/erpnext/patches/v13_0/replace_pos_page_with_point_of_sale_page.py
@@ -0,0 +1,6 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	if frappe.db.exists("Page", "point-of-sale"):
+		frappe.rename_doc("Page", "pos", "point-of-sale", 1, 1)
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.py b/erpnext/payroll/doctype/additional_salary/additional_salary.py
index ef174bd..e3dc907 100644
--- a/erpnext/payroll/doctype/additional_salary/additional_salary.py
+++ b/erpnext/payroll/doctype/additional_salary/additional_salary.py
@@ -5,8 +5,8 @@
 from __future__ import unicode_literals
 import frappe
 from frappe.model.document import Document
-from frappe import _
-from frappe.utils import getdate, date_diff
+from frappe import _, bold
+from frappe.utils import getdate, date_diff, comma_and, formatdate
 
 class AdditionalSalary(Document):
 
@@ -22,9 +22,37 @@
 
 	def validate(self):
 		self.validate_dates()
+		self.validate_recurring_additional_salary_overlap()
 		if self.amount < 0:
 			frappe.throw(_("Amount should not be less than zero."))
 
+	def validate_recurring_additional_salary_overlap(self):
+		if self.is_recurring:
+			additional_salaries = frappe.db.sql("""
+				SELECT
+					name
+				FROM `tabAdditional Salary`
+				WHERE
+					employee=%s
+					AND name <> %s
+					AND docstatus=1
+					AND is_recurring=1
+					AND salary_component = %s
+					AND to_date >= %s
+					AND from_date <= %s""",
+				(self.employee, self.name, self.salary_component, self.from_date, self.to_date), as_dict = 1)
+
+			additional_salaries = [salary.name for salary in additional_salaries]
+
+			if additional_salaries and len(additional_salaries):
+				frappe.throw(_("Additional Salary: {0} already exist for Salary Component: {1} for period {2} and {3}").format(
+					bold(comma_and(additional_salaries)),
+					bold(self.salary_component),
+					bold(formatdate(self.from_date)),
+					bold(formatdate(self.to_date)
+				)))
+
+
 	def validate_dates(self):
 		date_of_joining, relieving_date = frappe.db.get_value("Employee", self.employee,
 			["date_of_joining", "relieving_date"])
diff --git a/erpnext/portal/product_configurator/utils.py b/erpnext/portal/product_configurator/utils.py
index 9eef16b..9ba4cdc 100644
--- a/erpnext/portal/product_configurator/utils.py
+++ b/erpnext/portal/product_configurator/utils.py
@@ -13,13 +13,15 @@
 	for f in fields:
 		doctype = f.get_link_doctype()
 
-		# apply enable/disable filter
+		# apply enable/disable/show_in_website filter
 		meta = frappe.get_meta(doctype)
 		filters = {}
 		if meta.has_field('enabled'):
 			filters['enabled'] = 1
 		if meta.has_field('disabled'):
 			filters['disabled'] = 0
+		if meta.has_field('show_in_website'):
+			filters['show_in_website'] = 1
 
 		values = [d.name for d in frappe.get_all(doctype, filters)]
 		filter_data.append([f, values])
diff --git a/erpnext/regional/report/irs_1099/irs_1099.py b/erpnext/regional/report/irs_1099/irs_1099.py
index 67834d1..d3509e5 100644
--- a/erpnext/regional/report/irs_1099/irs_1099.py
+++ b/erpnext/regional/report/irs_1099/irs_1099.py
@@ -16,9 +16,15 @@
 
 def execute(filters=None):
 	filters = filters if isinstance(filters, _dict) else _dict(filters)
+
 	if not filters:
 		filters.setdefault('fiscal_year', get_fiscal_year(nowdate())[0])
 		filters.setdefault('company', frappe.db.get_default("company"))
+
+	region = frappe.db.get_value("Company", fieldname = ["country"], filters = { "name": filters.company })
+	if region != 'United States':
+		return [],[]
+
 	data = []
 	columns = get_columns()
 	data = frappe.db.sql("""
diff --git a/erpnext/regional/united_states/test_united_states.py b/erpnext/regional/united_states/test_united_states.py
index 688f145..ad95010 100644
--- a/erpnext/regional/united_states/test_united_states.py
+++ b/erpnext/regional/united_states/test_united_states.py
@@ -24,7 +24,7 @@
 
     def test_irs_1099_report(self):
         make_payment_entry_to_irs_1099_supplier()
-        filters = frappe._dict({"fiscal_year": "_Test Fiscal Year 2016", "company": "_Test Company"})
+        filters = frappe._dict({"fiscal_year": "_Test Fiscal Year 2016", "company": "_Test Company 1"})
         columns, data = execute_1099_report(filters)
         print(columns, data)
         expected_row = {'supplier': '_US 1099 Test Supplier',
@@ -42,10 +42,10 @@
 
     pe = frappe.new_doc("Payment Entry")
     pe.payment_type = "Pay"
-    pe.company = "_Test Company"
+    pe.company = "_Test Company 1"
     pe.posting_date = "2016-01-10"
-    pe.paid_from = "_Test Bank USD - _TC"
-    pe.paid_to = "_Test Payable USD - _TC"
+    pe.paid_from = "_Test Bank USD - _TC1"
+    pe.paid_to = "_Test Payable USD - _TC1"
     pe.paid_amount = 100
     pe.received_amount = 100
     pe.reference_no = "For IRS 1099 testing"
diff --git a/erpnext/stock/desk_page/stock/stock.json b/erpnext/stock/desk_page/stock/stock.json
index 1bf81f7..2fba5fa 100644
--- a/erpnext/stock/desk_page/stock/stock.json
+++ b/erpnext/stock/desk_page/stock/stock.json
@@ -33,7 +33,7 @@
   {
    "hidden": 0,
    "label": "Key Reports",
-   "links": "[\n    {\n        \"dependencies\": [\n            \"Item Price\"\n        ],\n        \"doctype\": \"Item Price\",\n        \"is_query_report\": false,\n        \"label\": \"Item-wise Price List Rate\",\n        \"name\": \"Item-wise Price List Rate\",\n        \"onboard\": 1,\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Stock Entry\"\n        ],\n        \"doctype\": \"Stock Entry\",\n        \"is_query_report\": true,\n        \"label\": \"Stock Analytics\",\n        \"name\": \"Stock Analytics\",\n        \"onboard\": 1,\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Delivery Note\"\n        ],\n        \"doctype\": \"Delivery Note\",\n        \"is_query_report\": true,\n        \"label\": \"Delivery Note Trends\",\n        \"name\": \"Delivery Note Trends\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Purchase Receipt\"\n        ],\n        \"doctype\": \"Purchase Receipt\",\n        \"is_query_report\": true,\n        \"label\": \"Purchase Receipt Trends\",\n        \"name\": \"Purchase Receipt Trends\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Order Analysis\",\n        \"name\": \"Sales Order Analysis\",\n        \"type\": \"report\"\n    },\n   {\n         \"dependencies\": [\n            \"Purchase Order\"\n        ],\n        \"doctype\": \"Purchase Order\",\n        \"is_query_report\": true,\n        \"label\": \"Purchase Order Analysis\",\n        \"name\": \"Purchase Order Analysis\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Bin\"\n        ],\n        \"doctype\": \"Bin\",\n        \"is_query_report\": true,\n        \"label\": \"Item Shortage Report\",\n        \"name\": \"Item Shortage Report\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Batch\"\n        ],\n        \"doctype\": \"Batch\",\n        \"is_query_report\": true,\n        \"label\": \"Batch-Wise Balance History\",\n        \"name\": \"Batch-Wise Balance History\",\n        \"type\": \"report\"\n    }\n]"
+   "links": "[\n    {\n        \"dependencies\": [\n            \"Item Price\"\n        ],\n        \"doctype\": \"Item Price\",\n        \"is_query_report\": false,\n        \"label\": \"Item-wise Price List Rate\",\n        \"name\": \"Item-wise Price List Rate\",\n        \"onboard\": 1,\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Stock Entry\"\n        ],\n        \"doctype\": \"Stock Entry\",\n        \"is_query_report\": true,\n        \"label\": \"Stock Analytics\",\n        \"name\": \"Stock Analytics\",\n        \"onboard\": 1,\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\"\n        ],\n        \"doctype\": \"Item\",\n        \"is_query_report\": true,\n        \"label\": \"Stock Qty vs Serial No Count\",\n        \"name\": \"Stock Qty vs Serial No Count\",\n        \"onboard\": 1,\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Delivery Note\"\n        ],\n        \"doctype\": \"Delivery Note\",\n        \"is_query_report\": true,\n        \"label\": \"Delivery Note Trends\",\n        \"name\": \"Delivery Note Trends\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Purchase Receipt\"\n        ],\n        \"doctype\": \"Purchase Receipt\",\n        \"is_query_report\": true,\n        \"label\": \"Purchase Receipt Trends\",\n        \"name\": \"Purchase Receipt Trends\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Order Analysis\",\n        \"name\": \"Sales Order Analysis\",\n        \"type\": \"report\"\n    },\n   {\n         \"dependencies\": [\n            \"Purchase Order\"\n        ],\n        \"doctype\": \"Purchase Order\",\n        \"is_query_report\": true,\n        \"label\": \"Purchase Order Analysis\",\n        \"name\": \"Purchase Order Analysis\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Bin\"\n        ],\n        \"doctype\": \"Bin\",\n        \"is_query_report\": true,\n        \"label\": \"Item Shortage Report\",\n        \"name\": \"Item Shortage Report\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Batch\"\n        ],\n        \"doctype\": \"Batch\",\n        \"is_query_report\": true,\n        \"label\": \"Batch-Wise Balance History\",\n        \"name\": \"Batch-Wise Balance History\",\n        \"type\": \"report\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -58,7 +58,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Stock",
- "modified": "2020-05-30 17:32:11.062681",
+ "modified": "2020-08-11 17:29:32.626067",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock",
diff --git a/erpnext/stock/report/stock_qty_vs_serial_no_count/__init__.py b/erpnext/stock/report/stock_qty_vs_serial_no_count/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/report/stock_qty_vs_serial_no_count/__init__.py
diff --git a/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.js b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.js
new file mode 100644
index 0000000..2a0fd40
--- /dev/null
+++ b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.js
@@ -0,0 +1,42 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Stock Qty vs Serial No Count"] = {
+	"filters": [
+		{
+			"fieldname":"company",
+			"label": __("Company"),
+			"fieldtype": "Link",
+			"options": "Company",
+			"default": frappe.defaults.get_user_default("Company"),
+			"reqd": 1
+		},
+		{
+			"fieldname":"warehouse",
+			"label": __("Warehouse"),
+			"fieldtype": "Link",
+			"options": "Warehouse",
+			"get_query": function() {
+				const company = frappe.query_report.get_filter_value('company');
+				return {
+					filters: { 'company': company }
+				}
+			},
+			"reqd": 1
+		},
+	],
+
+	"formatter": function (value, row, column, data, default_formatter) {
+		value = default_formatter(value, row, column, data);
+		if (column.fieldname == "difference" && data) {
+			if (data.difference > 0) {
+				value = "<span style='color:red'>" + value + "</span>";
+			}
+			else if (data.difference < 0) {
+				value = "<span style='color:red'>" + value + "</span>";
+			}
+		}
+		return value;
+	}
+};
diff --git a/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.json b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.json
new file mode 100644
index 0000000..c7108b5
--- /dev/null
+++ b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.json
@@ -0,0 +1,27 @@
+{
+ "add_total_row": 0,
+ "creation": "2020-07-23 19:31:32.395011",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2020-07-23 19:32:02.168185",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Stock Qty vs Serial No Count",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Item",
+ "report_name": "Stock Qty vs Serial No Count",
+ "report_type": "Script Report",
+ "roles": [
+  {
+   "role": "Stock Manager"
+  },
+  {
+   "role": "Stock User"
+  }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.py b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.py
new file mode 100644
index 0000000..55f041c
--- /dev/null
+++ b/erpnext/stock/report/stock_qty_vs_serial_no_count/stock_qty_vs_serial_no_count.py
@@ -0,0 +1,80 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+
+def execute(filters=None):
+	columns = get_columns()
+	data = get_data(filters.warehouse)
+	return columns, data
+
+def get_columns():
+	columns = [
+		{
+			"label": _("Item Code"),
+			"fieldname": "item_code",
+			"fieldtype": "Link",
+			"options": "Item",
+			"width": 200
+		},
+		{
+			"label": _("Item Name"),
+			"fieldname": "item_name",
+			"fieldtype": "Data",
+			"width": 200
+		},
+		{
+			"label": _("Serial No Count"),
+			"fieldname": "total",
+			"fieldtype": "Float",
+			"width": 150
+		},
+		{
+			"label": _("Stock Qty"),
+			"fieldname": "stock_qty",
+			"fieldtype": "Float",
+			"width": 150
+		},
+		{
+			"label": _("Difference"),
+			"fieldname": "difference",
+			"fieldtype": "Float",
+			"width": 150
+		},
+	]
+
+	return columns
+
+def get_data(warehouse):
+	serial_item_list = frappe.get_all("Item", filters={
+		'has_serial_no': True,
+	}, fields=['item_code', 'item_name'])
+	
+	status_list = ['Active', 'Expired']
+	data = []
+	for item in serial_item_list:
+		total_serial_no = frappe.db.count("Serial No", 
+			filters={"item_code": item.item_code, "status": ("in", status_list), "warehouse": warehouse})
+
+		actual_qty = frappe.db.get_value('Bin', fieldname=['actual_qty'], 
+			filters={"warehouse": warehouse, "item_code": item.item_code})
+
+		# frappe.db.get_value returns null if no record exist.
+		if not actual_qty:
+			actual_qty = 0
+
+		difference = total_serial_no - actual_qty
+
+		row = {
+			"item_code": item.item_code,
+			"item_name": item.item_name,
+			"total": total_serial_no,
+			"stock_qty": actual_qty,
+			"difference": difference,
+		}
+
+		data.append(row)
+
+	return data
\ No newline at end of file