Merge pull request #22198 from scmmishra/membership-fixes

fix: verification for razorpay hooks
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.js b/erpnext/hr/doctype/employee_advance/employee_advance.js
index 6cc49cf..cba8ee9 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.js
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.js
@@ -139,13 +139,13 @@
 	employee: function (frm) {
 		if (frm.doc.employee) {
 			return frappe.call({
-				method: "erpnext.hr.doctype.employee_advance.employee_advance.get_due_advance_amount",
+				method: "erpnext.hr.doctype.employee_advance.employee_advance.get_pending_amount",
 				args: {
 					"employee": frm.doc.employee,
 					"posting_date": frm.doc.posting_date
 				},
 				callback: function(r) {
-					frm.set_value("due_advance_amount",r.message);
+					frm.set_value("pending_amount",r.message);
 				}
 			});
 		}
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.json b/erpnext/hr/doctype/employee_advance/employee_advance.json
index 8c5ce42..0d90913 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.json
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.json
@@ -19,7 +19,7 @@
   "column_break_11",
   "advance_amount",
   "paid_amount",
-  "due_advance_amount",
+  "pending_amount",
   "claimed_amount",
   "return_amount",
   "section_break_7",
@@ -103,14 +103,6 @@
    "read_only": 1
   },
   {
-   "depends_on": "eval:cur_frm.doc.employee",
-   "fieldname": "due_advance_amount",
-   "fieldtype": "Currency",
-   "label": "Due Advance Amount",
-   "options": "Company:company:default_currency",
-   "read_only": 1
-  },
-  {
    "fieldname": "claimed_amount",
    "fieldtype": "Currency",
    "label": "Claimed Amount",
@@ -177,11 +169,19 @@
    "fieldname": "repay_unclaimed_amount_from_salary",
    "fieldtype": "Check",
    "label": "Repay unclaimed amount from salary"
+  },
+  {
+   "depends_on": "eval:cur_frm.doc.employee",
+   "fieldname": "pending_amount",
+   "fieldtype": "Currency",
+   "label": "Pending Amount",
+   "options": "Company:company:default_currency",
+   "read_only": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-03-06 15:11:33.747535",
+ "modified": "2020-06-12 12:42:39.833818",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Employee Advance",
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py
index db39eff..a49dfcf 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.py
@@ -95,7 +95,7 @@
 		frappe.db.set_value("Employee Advance", self.name, "status", self.status)
 
 @frappe.whitelist()
-def get_due_advance_amount(employee, posting_date):
+def get_pending_amount(employee, posting_date):
 	employee_due_amount = frappe.get_all("Employee Advance", \
 		filters = {"employee":employee, "docstatus":1, "posting_date":("<=", posting_date)}, \
 		fields = ["advance_amount", "paid_amount"])
diff --git a/erpnext/hr/doctype/leave_application/leave_application.js b/erpnext/hr/doctype/leave_application/leave_application.js
index 15ce468..fb1f2c0 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.js
+++ b/erpnext/hr/doctype/leave_application/leave_application.js
@@ -46,6 +46,7 @@
 
 	make_dashboard: function(frm) {
 		var leave_details;
+		let lwps;
 		if (frm.doc.employee) {
 			frappe.call({
 				method: "erpnext.hr.doctype.leave_application.leave_application.get_leave_details",
@@ -61,6 +62,7 @@
 					if (!r.exc && r.message['leave_approver']) {
 						frm.set_value('leave_approver', r.message['leave_approver']);
 					}
+					lwps = r.message["lwps"];
 				}
 			});
 			$("div").remove(".form-dashboard-section.custom");
@@ -70,12 +72,17 @@
 				})
 			);
 			frm.dashboard.show();
+			let allowed_leave_types =  Object.keys(leave_details);
+
+			// lwps should be allowed, lwps don't have any allocation
+			allowed_leave_types = allowed_leave_types.concat(lwps);
+
 			frm.set_query('leave_type', function(){
 				return {
 					filters : [
-						['leave_type_name', 'in', Object.keys(leave_details)]
+						['leave_type_name', 'in', allowed_leave_types]
 					]
-				}
+				};
 			});
 		}
 	},
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index c2b4cdf..0423824 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -19,7 +19,6 @@
 
 from frappe.model.document import Document
 class LeaveApplication(Document):
-
 	def get_feed(self):
 		return _("{0}: From {0} of type {1}").format(self.employee_name, self.leave_type)
 
@@ -463,9 +462,14 @@
 			"pending_leaves": leaves_pending,
 			"remaining_leaves": remaining_leaves}
 
+	#is used in set query
+	lwps = frappe.get_list("Leave Type", filters = {"is_lwp": 1})
+	lwps = [lwp.name for lwp in lwps]
+
 	ret = {
 		'leave_allocation': leave_allocation,
-		'leave_approver': get_leave_approver(employee)
+		'leave_approver': get_leave_approver(employee),
+		'lwps': lwps
 	}
 
 	return ret
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index b0421f4..1f5d4d5 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -680,6 +680,7 @@
 erpnext.patches.v12_0.retain_permission_rules_for_video_doctype
 erpnext.patches.v12_0.remove_duplicate_leave_ledger_entries #2020-05-22
 erpnext.patches.v13_0.patch_to_fix_reverse_linking_in_additional_salary_encashment_and_incentive
+erpnext.patches.v12_0.move_due_advance_amount_to_pending_amount
 execute:frappe.delete_doc_if_exists("Page", "appointment-analytic")
 execute:frappe.rename_doc("Desk Page", "Getting Started", "Home", force=True)
 erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price
@@ -694,4 +695,4 @@
 execute:frappe.rename_doc("Desk Page", "Loan Management", "Loan", force=True)
 erpnext.patches.v12_0.update_uom_conversion_factor
 erpnext.patches.v13_0.delete_old_purchase_reports
-erpnext.patches.v12_0.set_italian_import_supplier_invoice_permissions
\ No newline at end of file
+erpnext.patches.v12_0.set_italian_import_supplier_invoice_permissions
diff --git a/erpnext/patches/v12_0/move_due_advance_amount_to_pending_amount.py b/erpnext/patches/v12_0/move_due_advance_amount_to_pending_amount.py
new file mode 100644
index 0000000..f1ffaf9
--- /dev/null
+++ b/erpnext/patches/v12_0/move_due_advance_amount_to_pending_amount.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+    ''' Move from due_advance_amount to pending_amount '''
+    frappe.db.sql(''' UPDATE `tabEmployee Advance` SET pending_amount=due_advance_amount ''')
diff --git a/erpnext/patches/v13_0/set_company_field_in_healthcare_doctypes.py b/erpnext/patches/v13_0/set_company_field_in_healthcare_doctypes.py
index a7d4c66..be5e30f 100644
--- a/erpnext/patches/v13_0/set_company_field_in_healthcare_doctypes.py
+++ b/erpnext/patches/v13_0/set_company_field_in_healthcare_doctypes.py
@@ -7,4 +7,4 @@
 	for entry in doctypes:
 		if frappe.db.exists('DocType', entry):
 			frappe.reload_doc('Healthcare', 'doctype', entry)
-			frappe.db.sql("update `tab{dt}` set company = '{company}' where ifnull(company, '') = ''".format(dt=entry, company=company))
+			frappe.db.sql("update `tab{dt}` set company = {company} where ifnull(company, '') = ''".format(dt=entry, company=frappe.db.escape(company)))
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index a6889e0..ac3bc20 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -3,16 +3,19 @@
 
 from __future__ import unicode_literals
 import frappe
+import json
 from frappe.model.naming import set_name_by_naming_series
-from frappe import _, msgprint, throw
+from frappe import _, msgprint
 import frappe.defaults
-from frappe.utils import flt, cint, cstr, today
+from frappe.utils import flt, cint, cstr, today, get_formatted_email
 from frappe.desk.reportview import build_match_conditions, get_filters_cond
 from erpnext.utilities.transaction_base import TransactionBase
 from erpnext.accounts.party import validate_party_accounts, get_dashboard_info, get_timeline_data # keep this
 from frappe.contacts.address_and_contact import load_address_and_contact, delete_contact_and_address
 from frappe.model.rename_doc import update_linked_doctypes
 from frappe.model.mapper import get_mapped_doc
+from frappe.utils.user import get_users_with_role
+
 
 class Customer(TransactionBase):
 	def get_feed(self):
@@ -378,10 +381,45 @@
 			.format(customer, customer_outstanding, credit_limit))
 
 		# If not authorized person raise exception
-		credit_controller = frappe.db.get_value('Accounts Settings', None, 'credit_controller')
-		if not credit_controller or credit_controller not in frappe.get_roles():
-			throw(_("Please contact to the user who have Sales Master Manager {0} role")
-				.format(" / " + credit_controller if credit_controller else ""))
+		credit_controller_role = frappe.db.get_single_value('Accounts Settings', 'credit_controller')
+		if not credit_controller_role or credit_controller_role not in frappe.get_roles():
+			# form a list of emails for the credit controller users
+			credit_controller_users = get_users_with_role(credit_controller_role or "Sales Master Manager")
+
+			# form a list of emails and names to show to the user
+			credit_controller_users_list = [user for user in credit_controller_users if frappe.db.exists("Employee", {"prefered_email": user})]
+			credit_controller_users = [get_formatted_email(user).replace("<", "(").replace(">", ")") for user in credit_controller_users_list]
+
+			if not credit_controller_users:
+				frappe.throw(_("Please contact your administrator to extend the credit limits for {0}.".format(customer)))
+
+			message = """Please contact any of the following users to extend the credit limits for {0}:
+				<br><br><ul><li>{1}</li></ul>""".format(customer, '<li>'.join(credit_controller_users))
+
+			# if the current user does not have permissions to override credit limit,
+			# prompt them to send out an email to the controller users
+			frappe.msgprint(message,
+				title="Notify",
+				raise_exception=1,
+				primary_action={
+					'label': 'Send Email',
+					'server_action': 'erpnext.selling.doctype.customer.customer.send_emails',
+					'args': {
+						'customer': customer,
+						'customer_outstanding': customer_outstanding,
+						'credit_limit': credit_limit,
+						'credit_controller_users_list': credit_controller_users_list
+					}
+				}
+			)
+
+@frappe.whitelist()
+def send_emails(args):
+	args = json.loads(args)
+	subject = (_("Credit limit reached for customer {0}").format(args.get('customer')))
+	message = (_("Credit limit has been crossed for customer {0} ({1}/{2})")
+			.format(args.get('customer'), args.get('customer_outstanding'), args.get('credit_limit')))
+	frappe.sendmail(recipients=[args.get('credit_controller_users_list')], subject=subject, message=message)
 
 def get_customer_outstanding(customer, company, ignore_outstanding_sales_order=False, cost_center=None):
 	# Outstanding based on GL Entries
diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py
index af99780..723ed5c 100644
--- a/erpnext/stock/report/stock_ageing/stock_ageing.py
+++ b/erpnext/stock/report/stock_ageing/stock_ageing.py
@@ -180,10 +180,10 @@
 				qty_to_pop = abs(d.actual_qty)
 				while qty_to_pop:
 					batch = fifo_queue[0] if fifo_queue else [0, None]
-					if 0 < batch[0] <= qty_to_pop:
+					if 0 < flt(batch[0]) <= qty_to_pop:
 						# if batch qty > 0
 						# not enough or exactly same qty in current batch, clear batch
-						qty_to_pop -= batch[0]
+						qty_to_pop -= flt(batch[0])
 						transferred_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0))
 					else:
 						# all from current batch
@@ -262,4 +262,4 @@
 			]
 		},
 		"type" : "bar"
-	}
\ No newline at end of file
+	}