Merge pull request #20478 from deepeshgarg007/finance-book-filter-new

fix: Do not show any finance book record if no finance book filter is applied
diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py
index 62a8f05..3b6a588 100644
--- a/erpnext/accounts/deferred_revenue.py
+++ b/erpnext/accounts/deferred_revenue.py
@@ -30,7 +30,7 @@
 				frappe.throw(_("Service Stop Date cannot be after Service End Date"))
 
 		if old_stop_dates and old_stop_dates.get(item.name) and item.service_stop_date!=old_stop_dates.get(item.name):
-			frappe.throw(_("Cannot change Service Stop Date for item in row {0}".format(item.idx)))
+			frappe.throw(_("Cannot change Service Stop Date for item in row {0}").format(item.idx))
 
 def convert_deferred_expense_to_expense(start_date=None, end_date=None):
 	# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
diff --git a/erpnext/accounts/doctype/bank_account/test_bank_account.py b/erpnext/accounts/doctype/bank_account/test_bank_account.py
index f3bb086..ed34d17 100644
--- a/erpnext/accounts/doctype/bank_account/test_bank_account.py
+++ b/erpnext/accounts/doctype/bank_account/test_bank_account.py
@@ -31,7 +31,7 @@
 		try:
 			bank_account.validate_iban()
 		except AttributeError:
-			msg = _('BankAccount.validate_iban() failed for empty IBAN')
+			msg = 'BankAccount.validate_iban() failed for empty IBAN'
 			self.fail(msg=msg)
 
 		for iban in valid_ibans:
@@ -39,11 +39,11 @@
 			try:
 				bank_account.validate_iban()
 			except ValidationError:
-				msg = _('BankAccount.validate_iban() failed for valid IBAN {}'.format(iban))
+				msg = 'BankAccount.validate_iban() failed for valid IBAN {}'.format(iban)
 				self.fail(msg=msg)
 
 		for not_iban in invalid_ibans:
 			bank_account.iban = not_iban
-			msg = _('BankAccount.validate_iban() accepted invalid IBAN {}'.format(not_iban))
+			msg = 'BankAccount.validate_iban() accepted invalid IBAN {}'.format(not_iban)
 			with self.assertRaises(ValidationError, msg=msg):
 				bank_account.validate_iban()
diff --git a/erpnext/accounts/doctype/bank_statement_transaction_entry/bank_statement_transaction_entry.py b/erpnext/accounts/doctype/bank_statement_transaction_entry/bank_statement_transaction_entry.py
index 1318cf1..5b6eb9d 100644
--- a/erpnext/accounts/doctype/bank_statement_transaction_entry/bank_statement_transaction_entry.py
+++ b/erpnext/accounts/doctype/bank_statement_transaction_entry/bank_statement_transaction_entry.py
@@ -314,7 +314,7 @@
 			try:
 				reconcile_against_document(lst)
 			except:
-				frappe.throw(_("Exception occurred while reconciling {0}".format(payment.reference_name)))
+				frappe.throw(_("Exception occurred while reconciling {0}").format(payment.reference_name))
 
 	def submit_payment_entries(self):
 		for payment in self.new_transaction_items:
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index b8ebeba..0e45db3 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -49,7 +49,7 @@
 
 			if paid_amount and allocated_amount:
 				if  flt(allocated_amount[0]["allocated_amount"]) > flt(paid_amount):
-					frappe.throw(_("The total allocated amount ({0}) is greated than the paid amount ({1}).".format(flt(allocated_amount[0]["allocated_amount"]), flt(paid_amount))))
+					frappe.throw(_("The total allocated amount ({0}) is greated than the paid amount ({1}).").format(flt(allocated_amount[0]["allocated_amount"]), flt(paid_amount)))
 				else:
 					if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
 						self.clear_simple_entry(payment_entry)
diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py
index b76cdf3..084514c 100644
--- a/erpnext/accounts/doctype/budget/budget.py
+++ b/erpnext/accounts/doctype/budget/budget.py
@@ -210,10 +210,10 @@
 	item_code = args.get('item_code')
 	condition = get_other_condition(args, budget, 'Material Request')
 
-	data = frappe.db.sql(""" select ifnull((sum(mri.stock_qty - mri.ordered_qty) * rate), 0) as amount
-		from `tabMaterial Request Item` mri, `tabMaterial Request` mr where mr.name = mri.parent and
-		mri.item_code = %s and mr.docstatus = 1 and mri.stock_qty > mri.ordered_qty and {0} and
-		mr.material_request_type = 'Purchase' and mr.status != 'Stopped'""".format(condition), item_code, as_list=1)
+	data = frappe.db.sql(""" select ifnull((sum(child.stock_qty - child.ordered_qty) * rate), 0) as amount
+		from `tabMaterial Request Item` child, `tabMaterial Request` parent where parent.name = child.parent and
+		child.item_code = %s and parent.docstatus = 1 and child.stock_qty > child.ordered_qty and {0} and
+		parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format(condition), item_code, as_list=1)
 
 	return data[0][0] if data else 0
 
@@ -221,10 +221,10 @@
 	item_code = args.get('item_code')
 	condition = get_other_condition(args, budget, 'Purchase Order')
 
-	data = frappe.db.sql(""" select ifnull(sum(poi.amount - poi.billed_amt), 0) as amount
-		from `tabPurchase Order Item` poi, `tabPurchase Order` po where
-		po.name = poi.parent and poi.item_code = %s and po.docstatus = 1 and poi.amount > poi.billed_amt
-		and po.status != 'Closed' and {0}""".format(condition), item_code, as_list=1)
+	data = frappe.db.sql(""" select ifnull(sum(child.amount - child.billed_amt), 0) as amount
+		from `tabPurchase Order Item` child, `tabPurchase Order` parent where
+		parent.name = child.parent and child.item_code = %s and parent.docstatus = 1 and child.amount > child.billed_amt
+		and parent.status != 'Closed' and {0}""".format(condition), item_code, as_list=1)
 
 	return data[0][0] if data else 0
 
@@ -233,16 +233,15 @@
 	budget_against_field = frappe.scrub(args.get("budget_against_field"))
 
 	if budget_against_field and args.get(budget_against_field):
-		condition += " and %s = '%s'" %(budget_against_field, args.get(budget_against_field))
+		condition += " and child.%s = '%s'" %(budget_against_field, args.get(budget_against_field))
 
 	if args.get('fiscal_year'):
 		date_field = 'schedule_date' if for_doc == 'Material Request' else 'transaction_date'
 		start_date, end_date = frappe.db.get_value('Fiscal Year', args.get('fiscal_year'),
 			['year_start_date', 'year_end_date'])
 
-		alias = 'mr' if for_doc == 'Material Request' else 'po'
-		condition += """ and %s.%s
-			between '%s' and '%s' """ %(alias, date_field, start_date, end_date)
+		condition += """ and parent.%s
+			between '%s' and '%s' """ %(date_field, start_date, end_date)
 
 	return condition
 
diff --git a/erpnext/accounts/doctype/c_form/c_form.py b/erpnext/accounts/doctype/c_form/c_form.py
index 2dcf958..9b64f81 100644
--- a/erpnext/accounts/doctype/c_form/c_form.py
+++ b/erpnext/accounts/doctype/c_form/c_form.py
@@ -18,7 +18,7 @@
 					`tabSales Invoice` where name = %s and docstatus = 1""", d.invoice_no)
 
 				if inv and inv[0][0] != 'Yes':
-					frappe.throw(_("C-form is not applicable for Invoice: {0}".format(d.invoice_no)))
+					frappe.throw(_("C-form is not applicable for Invoice: {0}").format(d.invoice_no))
 
 				elif inv and inv[0][1] and inv[0][1] != self.name:
 					frappe.throw(_("""Invoice {0} is tagged in another C-form: {1}.
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 8897337..458e4a2 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -616,7 +616,7 @@
 					d.reference_name, ("total_sanctioned_amount", "total_amount_reimbursed"))
 				pending_amount = flt(sanctioned_amount) - flt(reimbursed_amount)
 				if d.debit > pending_amount:
-					frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. Pending Amount is {2}".format(d.idx, d.reference_name, pending_amount)))
+					frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. Pending Amount is {2}").format(d.idx, d.reference_name, pending_amount))
 
 	def validate_credit_debit_note(self):
 		if self.stock_entry:
@@ -624,7 +624,7 @@
 				frappe.throw(_("Stock Entry {0} is not submitted").format(self.stock_entry))
 
 			if frappe.db.exists({"doctype": "Journal Entry", "stock_entry": self.stock_entry, "docstatus":1}):
-				frappe.msgprint(_("Warning: Another {0} # {1} exists against stock entry {2}".format(self.voucher_type, self.name, self.stock_entry)))
+				frappe.msgprint(_("Warning: Another {0} # {1} exists against stock entry {2}").format(self.voucher_type, self.name, self.stock_entry))
 
 	def validate_empty_accounts_table(self):
 		if not self.get('accounts'):
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 214d608..e36e23a 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -1003,7 +1003,7 @@
 
 	# only Purchase Invoice can be blocked individually
 	if doc.doctype == "Purchase Invoice" and doc.invoice_is_blocked():
-		frappe.msgprint(_('{0} is on hold till {1}'.format(doc.name, doc.release_date)))
+		frappe.msgprint(_('{0} is on hold till {1}').format(doc.name, doc.release_date))
 	else:
 		pe.append("references", {
 			'reference_doctype': dt,
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 1aff43c..0fade8c 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -39,8 +39,8 @@
 				ref_amount = get_amount(ref_doc)
 
 				if existing_payment_request_amount + flt(self.grand_total)> ref_amount:
-					frappe.throw(_("Total Payment Request amount cannot be greater than {0} amount"
-						.format(self.reference_doctype)))
+					frappe.throw(_("Total Payment Request amount cannot be greater than {0} amount")
+						.format(self.reference_doctype))
 
 	def validate_currency(self):
 		ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
@@ -53,14 +53,14 @@
 			for subscription_plan in self.subscription_plans:
 				payment_gateway = frappe.db.get_value("Subscription Plan", subscription_plan.plan, "payment_gateway")
 				if payment_gateway != self.payment_gateway_account:
-					frappe.throw(_('The payment gateway account in plan {0} is different from the payment gateway account in this payment request'.format(subscription_plan.name)))
+					frappe.throw(_('The payment gateway account in plan {0} is different from the payment gateway account in this payment request').format(subscription_plan.name))
 
 				rate = get_plan_rate(subscription_plan.plan, quantity=subscription_plan.qty)
 
 				amount += rate
 
 			if amount != self.grand_total:
-				frappe.msgprint(_("The amount of {0} set in this payment request is different from the calculated amount of all payment plans: {1}. Make sure this is correct before submitting the document.".format(self.grand_total, amount)))
+				frappe.msgprint(_("The amount of {0} set in this payment request is different from the calculated amount of all payment plans: {1}. Make sure this is correct before submitting the document.").format(self.grand_total, amount))
 
 	def on_submit(self):
 		if self.payment_request_type == 'Outward':
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index 3c14819..924e108 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -56,12 +56,12 @@
 
 		if not self.selling and self.applicable_for in ["Customer", "Customer Group",
 				"Territory", "Sales Partner", "Campaign"]:
-			throw(_("Selling must be checked, if Applicable For is selected as {0}"
-				.format(self.applicable_for)))
+			throw(_("Selling must be checked, if Applicable For is selected as {0}")
+				.format(self.applicable_for))
 
 		if not self.buying and self.applicable_for in ["Supplier", "Supplier Group"]:
-			throw(_("Buying must be checked, if Applicable For is selected as {0}"
-				.format(self.applicable_for)))
+			throw(_("Buying must be checked, if Applicable For is selected as {0}")
+				.format(self.applicable_for))
 
 	def validate_min_max_qty(self):
 		if self.min_qty and self.max_qty and flt(self.min_qty) > flt(self.max_qty):
@@ -243,7 +243,7 @@
 
 			if pricing_rule.coupon_code_based==1 and args.coupon_code==None:
 				return item_details
-				
+
 			if not pricing_rule.validate_applied_rule:
 				if pricing_rule.price_or_product_discount == "Price":
 					apply_price_discount_rule(pricing_rule, item_details, args)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index d4676ff..4002d7e 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -908,7 +908,7 @@
 
 				if pi:
 					pi = pi[0][0]
-					frappe.throw(_("Supplier Invoice No exists in Purchase Invoice {0}".format(pi)))
+					frappe.throw(_("Supplier Invoice No exists in Purchase Invoice {0}").format(pi))
 
 	def update_billing_status_in_pr(self, update_modified=True):
 		updated_pr = []
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 6e3e43e..d576a66 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -225,7 +225,7 @@
 				total_amount_in_payments += payment.amount
 			invoice_total = self.rounded_total or self.grand_total
 			if total_amount_in_payments < invoice_total:
-				frappe.throw(_("Total payments amount can't be greater than {}".format(-invoice_total)))
+				frappe.throw(_("Total payments amount can't be greater than {}").format(-invoice_total))
 
 	def validate_pos_paid_amount(self):
 		if len(self.payments) == 0 and self.is_pos:
@@ -1041,11 +1041,11 @@
 			si_serial_nos = set(get_serial_nos(serial_nos))
 
 			if si_serial_nos - dn_serial_nos:
-				frappe.throw(_("Serial Numbers in row {0} does not match with Delivery Note".format(item.idx)))
+				frappe.throw(_("Serial Numbers in row {0} does not match with Delivery Note").format(item.idx))
 
 			if item.serial_no and cint(item.qty) != len(si_serial_nos):
-				frappe.throw(_("Row {0}: {1} Serial numbers required for Item {2}. You have provided {3}.".format(
-					item.idx, item.qty, item.item_code, len(si_serial_nos))))
+				frappe.throw(_("Row {0}: {1} Serial numbers required for Item {2}. You have provided {3}.").format(
+					item.idx, item.qty, item.item_code, len(si_serial_nos)))
 
 	def validate_serial_against_sales_invoice(self):
 		""" check if serial number is already used in other sales invoice """
@@ -1064,8 +1064,8 @@
 					and self.name != serial_no_details.sales_invoice:
 					sales_invoice_company = frappe.db.get_value("Sales Invoice", serial_no_details.sales_invoice, "company")
 					if sales_invoice_company == self.company:
-						frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}"
-							.format(serial_no, serial_no_details.sales_invoice)))
+						frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}")
+							.format(serial_no, serial_no_details.sales_invoice))
 
 	def update_project(self):
 		if self.project:
diff --git a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py
index 8c4efbe..1fd340c 100644
--- a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py
+++ b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py
@@ -82,7 +82,7 @@
 			if not shipping_country:
 				frappe.throw(_('Shipping Address does not have country, which is required for this Shipping Rule'))
 			if shipping_country not in [d.country for d in self.countries]:
-				frappe.throw(_('Shipping rule not applicable for country {0}'.format(shipping_country)))
+				frappe.throw(_('Shipping rule not applicable for country {0}').format(shipping_country))
 
 	def add_shipping_rule_to_tax_table(self, doc, shipping_amount):
 		shipping_charge = {
diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json
index 29cb62a..32b97ba 100644
--- a/erpnext/accounts/doctype/subscription/subscription.json
+++ b/erpnext/accounts/doctype/subscription/subscription.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "ACC-SUB-.YYYY.-.#####",
  "creation": "2017-07-18 17:50:43.967266",
  "doctype": "DocType",
@@ -155,7 +156,7 @@
    "fieldname": "apply_additional_discount",
    "fieldtype": "Select",
    "label": "Apply Additional Discount On",
-   "options": "\nGrand Total\nNet total"
+   "options": "\nGrand Total\nNet Total"
   },
   {
    "fieldname": "cb_2",
@@ -196,7 +197,8 @@
    "fieldtype": "Column Break"
   }
  ],
- "modified": "2019-07-25 18:45:38.579579",
+ "links": [],
+ "modified": "2020-01-27 14:37:32.845173",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Subscription",
diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py
index 5482750..0933c7e 100644
--- a/erpnext/accounts/doctype/subscription/subscription.py
+++ b/erpnext/accounts/doctype/subscription/subscription.py
@@ -195,7 +195,7 @@
 				doc = frappe.get_doc('Sales Invoice', current.invoice)
 				return doc
 			else:
-				frappe.throw(_('Invoice {0} no longer exists'.format(current.invoice)))
+				frappe.throw(_('Invoice {0} no longer exists').format(current.invoice))
 
 	def is_new_subscription(self):
 		"""
@@ -280,7 +280,7 @@
 
 		if self.additional_discount_percentage or self.additional_discount_amount:
 			discount_on = self.apply_additional_discount
-			invoice.apply_additional_discount = discount_on if discount_on else 'Grand Total'
+			invoice.apply_discount_on = discount_on if discount_on else 'Grand Total'
 
 		# Subscription period
 		invoice.from_date = self.current_invoice_start
@@ -338,7 +338,7 @@
 
 		# Check invoice dates and make sure it doesn't have outstanding invoices
 		return getdate(nowdate()) >= getdate(self.current_invoice_start) and not self.has_outstanding_invoice()
-	
+
 	def is_current_invoice_paid(self):
 		if self.is_new_subscription():
 			return False
@@ -346,7 +346,7 @@
 		last_invoice = frappe.get_doc('Sales Invoice', self.invoices[-1].invoice)
 		if getdate(last_invoice.posting_date) == getdate(self.current_invoice_start) and last_invoice.status == 'Paid':
 			return True
-		
+
 		return False
 
 	def process_for_active(self):
@@ -388,7 +388,7 @@
 		"""
 		current_invoice = self.get_current_invoice()
 		if not current_invoice:
-			frappe.throw(_('Current invoice {0} is missing'.format(current_invoice.invoice)))
+			frappe.throw(_('Current invoice {0} is missing').format(current_invoice.invoice))
 		else:
 			if self.is_not_outstanding(current_invoice):
 				self.status = 'Active'
diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py
index ff87ba3..e4ebc6d 100644
--- a/erpnext/accounts/doctype/tax_rule/tax_rule.py
+++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py
@@ -95,7 +95,7 @@
 
 		if tax_rule:
 			if tax_rule[0].priority == self.priority:
-				frappe.throw(_("Tax Rule Conflicts with {0}".format(tax_rule[0].name)), ConflictingTaxRule)
+				frappe.throw(_("Tax Rule Conflicts with {0}").format(tax_rule[0].name), ConflictingTaxRule)
 
 	def validate_use_for_shopping_cart(self):
 		'''If shopping cart is enabled and no tax rule exists for shopping cart, enable this one'''
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index 57e8e0e..30c012e 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -175,7 +175,7 @@
 			d = accounts_by_name.get(entry.account)
 			if not d:
 				frappe.msgprint(
-					_("Could not retrieve information for {0}.".format(entry.account)), title="Error",
+					_("Could not retrieve information for {0}.").format(entry.account), title="Error",
 					raise_exception=1
 				)
 			for period in period_list:
@@ -429,7 +429,7 @@
 			children = frappe.get_all("Cost Center", filters={"lft": [">=", lft], "rgt": ["<=", rgt]})
 			all_cost_centers += [c.name for c in children]
 		else:
-			frappe.throw(_("Cost Center: {0} does not exist".format(d)))
+			frappe.throw(_("Cost Center: {0} does not exist").format(d))
 
 	return list(set(all_cost_centers))
 
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 0939354..8bea365 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -373,19 +373,19 @@
 			"width": 180
 		},
 		{
-			"label": _("Debit ({0})".format(currency)),
+			"label": _("Debit ({0})").format(currency),
 			"fieldname": "debit",
 			"fieldtype": "Float",
 			"width": 100
 		},
 		{
-			"label": _("Credit ({0})".format(currency)),
+			"label": _("Credit ({0})").format(currency),
 			"fieldname": "credit",
 			"fieldtype": "Float",
 			"width": 100
 		},
 		{
-			"label": _("Balance ({0})".format(currency)),
+			"label": _("Balance ({0})").format(currency),
 			"fieldname": "balance",
 			"fieldtype": "Float",
 			"width": 130
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 5ad8cb5..4789063 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -513,7 +513,7 @@
 			where reference_type=%s and reference_name=%s
 			and docstatus < 2""", (now(), frappe.session.user, ref_type, ref_no))
 
-		frappe.msgprint(_("Journal Entries {0} are un-linked".format("\n".join(linked_jv))))
+		frappe.msgprint(_("Journal Entries {0} are un-linked").format("\n".join(linked_jv)))
 
 def remove_ref_doc_link_from_pe(ref_type, ref_no):
 	linked_pe = frappe.db.sql_list("""select parent from `tabPayment Entry Reference`
@@ -536,7 +536,7 @@
 				where name=%s""", (pe_doc.total_allocated_amount, pe_doc.base_total_allocated_amount,
 					pe_doc.unallocated_amount, now(), frappe.session.user, pe))
 
-		frappe.msgprint(_("Payment Entries {0} are un-linked".format("\n".join(linked_pe))))
+		frappe.msgprint(_("Payment Entries {0} are un-linked").format("\n".join(linked_pe)))
 
 @frappe.whitelist()
 def get_company_default(company, fieldname):
diff --git a/erpnext/agriculture/doctype/crop_cycle/crop_cycle.py b/erpnext/agriculture/doctype/crop_cycle/crop_cycle.py
index 3e51933..cae150c 100644
--- a/erpnext/agriculture/doctype/crop_cycle/crop_cycle.py
+++ b/erpnext/agriculture/doctype/crop_cycle/crop_cycle.py
@@ -44,7 +44,7 @@
 				self.import_disease_tasks(disease.disease, disease.start_date)
 				disease.tasks_created = True
 
-				frappe.msgprint(_("Tasks have been created for managing the {0} disease (on row {1})".format(disease.disease, disease.idx)))
+				frappe.msgprint(_("Tasks have been created for managing the {0} disease (on row {1})").format(disease.disease, disease.idx))
 
 	def import_disease_tasks(self, disease, start_date):
 		disease_doc = frappe.get_doc('Disease', disease)
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 0df6a6c..759d42a 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -589,7 +589,7 @@
 
 	frappe.db.commit()
 
-	frappe.msgprint(_("Asset Movement record {0} created").format("<a href='#Form/Asset Movement/{0}'>{0}</a>".format(movement_entry.name)))
+	frappe.msgprint(_("Asset Movement record {0} created").format("<a href='#Form/Asset Movement/{0}'>{0}</a>").format(movement_entry.name))
 
 @frappe.whitelist()
 def get_item_details(item_code, asset_category):
@@ -611,7 +611,7 @@
 	if asset:
 		account = get_asset_category_account(account_name, asset=asset,
 				asset_category = asset_category, company = company)
-	
+
 	if not asset and not account:
 		account = get_asset_category_account(account_name, asset_category = asset_category, company = company)
 
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
index 2f0cfa6..455bd68 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -9,7 +9,7 @@
 frappe.ui.form.on("Request for Quotation",{
 	setup: function(frm) {
 		frm.custom_make_buttons = {
-			'Supplier Quotation': 'Supplier Quotation'
+			'Supplier Quotation': 'Create'
 		}
 
 		frm.fields_dict["suppliers"].grid.get_field("contact").get_query = function(doc, cdt, cdn) {
diff --git a/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py b/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py
index 737ddd6..87f1033 100644
--- a/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py
+++ b/erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.py
@@ -43,7 +43,7 @@
 			try:
 				crit.score = min(crit.max_score, max( 0 ,frappe.safe_eval(self.get_eval_statement(crit.formula),  None, {'max':max, 'min': min})))
 			except Exception:
-				frappe.throw(_("Could not solve criteria score function for {0}. Make sure the formula is valid.".format(crit.criteria_name)),frappe.ValidationError)
+				frappe.throw(_("Could not solve criteria score function for {0}. Make sure the formula is valid.").format(crit.criteria_name),frappe.ValidationError)
 				crit.score = 0
 
 	def calculate_score(self):
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 7faf792..56a09c3 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -58,7 +58,7 @@
 					(is_supplier_payment and supplier.hold_type in ['All', 'Payments']):
 				if not supplier.release_date or getdate(nowdate()) <= supplier.release_date:
 					frappe.msgprint(
-						_('{0} is blocked so this transaction cannot proceed'.format(supplier_name)), raise_exception=1)
+						_('{0} is blocked so this transaction cannot proceed').format(supplier_name), raise_exception=1)
 
 	def validate(self):
 		if not self.get('is_return'):
@@ -926,7 +926,7 @@
 			frappe.throw(
 				_("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"))
 		elif not tax.row_id:
-			frappe.throw(_("Please specify a valid Row ID for row {0} in table {1}".format(tax.idx, _(tax.doctype))))
+			frappe.throw(_("Please specify a valid Row ID for row {0} in table {1}").format(tax.idx, _(tax.doctype)))
 		elif tax.row_id and cint(tax.row_id) >= cint(tax.idx):
 			frappe.throw(_("Cannot refer row number greater than or equal to current row number for this Charge type"))
 
@@ -1173,7 +1173,7 @@
 
 		if parent.doctype == "Purchase Order" and flt(d.received_qty):
 			frappe.throw(_("Row #{0}: Cannot delete item {1} which has already been received").format(d.idx, d.item_code))
-		
+
 		if flt(d.billed_amt):
 			frappe.throw(_("Row #{0}: Cannot delete item {1} which has already been billed.").format(d.idx, d.item_code))
 
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 75b896b..69caabd 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -168,7 +168,7 @@
 			if item.item_code and item.qty and item.item_code in stock_and_asset_items:
 				item_proportion = flt(item.base_net_amount) / stock_and_asset_items_amount if stock_and_asset_items_amount \
 					else flt(item.qty) / stock_and_asset_items_qty
-				
+
 				if i == (last_item_idx - 1):
 					item.item_tax_amount = flt(valuation_amount_adjustment,
 						self.precision("item_tax_amount", item))
@@ -500,8 +500,8 @@
 		item_row = item_row.as_dict()
 		for fieldname in field_list:
 			if flt(item_row[fieldname]) < 0:
-				frappe.throw(_("Row #{0}: {1} can not be negative for item {2}".format(item_row['idx'],
-					frappe.get_meta(item_row.doctype).get_label(fieldname), item_row['item_code'])))
+				frappe.throw(_("Row #{0}: {1} can not be negative for item {2}").format(item_row['idx'],
+					frappe.get_meta(item_row.doctype).get_label(fieldname), item_row['item_code']))
 
 	def check_for_on_hold_or_closed_status(self, ref_doctype, ref_fieldname):
 		for d in self.get("items"):
@@ -699,7 +699,7 @@
 					if delete_asset and is_auto_create_enabled:
 						# need to delete movements to delete assets otherwise throws link exists error
 						movements = frappe.db.sql(
-							"""SELECT asm.name 
+							"""SELECT asm.name
 							FROM `tabAsset Movement` asm, `tabAsset Movement Item` asm_item
 							WHERE asm_item.parent=asm.name and asm_item.asset=%s""", asset.name, as_dict=1)
 						for movement in movements:
@@ -872,9 +872,9 @@
 		items = ", ".join([d for d in invalid_items])
 
 		if len(invalid_items) > 1:
-			error_message = _("Following items {0} are not marked as {1} item. You can enable them as {1} item from its Item master".format(items, message))
+			error_message = _("Following items {0} are not marked as {1} item. You can enable them as {1} item from its Item master").format(items, message)
 		else:
-			error_message = _("Following item {0} is not marked as {1} item. You can enable them as {1} item from its Item master".format(items, message))
+			error_message = _("Following item {0} is not marked as {1} item. You can enable them as {1} item from its Item master").format(items, message)
 
 		frappe.throw(error_message)
 
diff --git a/erpnext/crm/doctype/appointment/appointment.js b/erpnext/crm/doctype/appointment/appointment.js
index 8888b56..ca38121 100644
--- a/erpnext/crm/doctype/appointment/appointment.js
+++ b/erpnext/crm/doctype/appointment/appointment.js
@@ -13,5 +13,14 @@
 				frappe.set_route("Form", "Event", frm.doc.calendar_event);
 			});
 		}
+	},
+	onload: function(frm){
+		frm.set_query("appointment_with", function(){
+			return {
+				filters : {
+					"name": ["in", ["Customer", "Lead"]]
+				}
+			};
+		});
 	}
 });
diff --git a/erpnext/crm/doctype/appointment/appointment.json b/erpnext/crm/doctype/appointment/appointment.json
index 32df8ec..8517dde 100644
--- a/erpnext/crm/doctype/appointment/appointment.json
+++ b/erpnext/crm/doctype/appointment/appointment.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "autoname": "format:APMT-{customer_name}-{####}",
  "creation": "2019-08-27 10:48:27.926283",
  "doctype": "DocType",
@@ -15,7 +16,8 @@
   "col_br_2",
   "customer_details",
   "linked_docs_section",
-  "lead",
+  "appointment_with",
+  "party",
   "col_br_3",
   "calendar_event"
  ],
@@ -62,12 +64,6 @@
    "reqd": 1
   },
   {
-   "fieldname": "lead",
-   "fieldtype": "Link",
-   "label": "Lead",
-   "options": "Lead"
-  },
-  {
    "fieldname": "calendar_event",
    "fieldtype": "Link",
    "label": "Calendar Event",
@@ -91,9 +87,22 @@
   {
    "fieldname": "col_br_3",
    "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "appointment_with",
+   "fieldtype": "Link",
+   "label": "Appointment With",
+   "options": "DocType"
+  },
+  {
+   "fieldname": "party",
+   "fieldtype": "Dynamic Link",
+   "label": "Party",
+   "options": "appointment_with"
   }
  ],
- "modified": "2019-10-14 15:23:54.630731",
+ "links": [],
+ "modified": "2020-01-28 16:16:45.447213",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Appointment",
diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py
index f502930..63efeb3 100644
--- a/erpnext/crm/doctype/appointment/appointment.py
+++ b/erpnext/crm/doctype/appointment/appointment.py
@@ -24,6 +24,14 @@
 			return lead_list[0].name
 		return None
 
+	def find_customer_by_email(self):
+		customer_list = frappe.get_list(
+			'Customer', filters={'email_id': self.customer_email}, ignore_permissions=True
+		)
+		if customer_list:
+			return customer_list[0].name
+		return None
+
 	def before_insert(self):
 		number_of_appointments_in_same_slot = frappe.db.count(
 			'Appointment', filters={'scheduled_time': self.scheduled_time})
@@ -32,11 +40,18 @@
 			if (number_of_appointments_in_same_slot >= number_of_agents):
 				frappe.throw('Time slot is not available')
 		# Link lead
-		if not self.lead:
-			self.lead = self.find_lead_by_email()
+		if not self.party:
+			lead = self.find_lead_by_email()
+			customer = self.find_customer_by_email()
+			if customer:
+				self.appointment_with = "Customer"
+				self.party = customer
+			else:
+				self.appointment_with = "Lead"
+				self.party = lead
 
 	def after_insert(self):
-		if self.lead:
+		if self.party:
 			# Create Calendar event
 			self.auto_assign()
 			self.create_calendar_event()
@@ -89,7 +104,7 @@
 
 	def create_lead_and_link(self):
 		# Return if already linked
-		if self.lead:
+		if self.party:
 			return
 		lead = frappe.get_doc({
 			'doctype': 'Lead',
@@ -100,7 +115,7 @@
 		})
 		lead.insert(ignore_permissions=True)
 		# Link lead
-		self.lead = lead.name
+		self.party = lead.name
 
 	def auto_assign(self):
 		from frappe.desk.form.assign_to import add as add_assignemnt
@@ -129,14 +144,14 @@
 			break
 
 	def get_assignee_from_latest_opportunity(self):
-		if not self.lead:
+		if not self.party:
 			return None
-		if not frappe.db.exists('Lead', self.lead):
+		if not frappe.db.exists('Lead', self.party):
 			return None
 		opporutnities = frappe.get_list(
 			'Opportunity',
 			filters={
-				'party_name': self.lead,
+				'party_name': self.party,
 			},
 			ignore_permissions=True,
 			order_by='creation desc')
@@ -159,7 +174,7 @@
 			'status': 'Open',
 			'type': 'Public',
 			'send_reminder': frappe.db.get_single_value('Appointment Booking Settings', 'email_reminders'),
-			'event_participants': [dict(reference_doctype='Lead', reference_docname=self.lead)]
+			'event_participants': [dict(reference_doctype=self.appointment_with, reference_docname=self.party)]
 		})
 		employee = _get_employee_from_user(self._assign)
 		if employee:
diff --git a/erpnext/education/doctype/assessment_plan/assessment_plan.py b/erpnext/education/doctype/assessment_plan/assessment_plan.py
index c957676..16136c1 100644
--- a/erpnext/education/doctype/assessment_plan/assessment_plan.py
+++ b/erpnext/education/doctype/assessment_plan/assessment_plan.py
@@ -37,7 +37,7 @@
 		for d in self.assessment_criteria:
 			max_score += d.maximum_score
 		if self.maximum_assessment_score != max_score:
-			frappe.throw(_("Sum of Scores of Assessment Criteria needs to be {0}.".format(self.maximum_assessment_score)))
+			frappe.throw(_("Sum of Scores of Assessment Criteria needs to be {0}.").format(self.maximum_assessment_score))
 
 	def validate_assessment_criteria(self):
 		assessment_criteria_list = frappe.db.sql_list(''' select apc.assessment_criteria
diff --git a/erpnext/education/doctype/assessment_result/assessment_result.py b/erpnext/education/doctype/assessment_result/assessment_result.py
index 08ae4c6..6b873ec 100644
--- a/erpnext/education/doctype/assessment_result/assessment_result.py
+++ b/erpnext/education/doctype/assessment_result/assessment_result.py
@@ -41,7 +41,7 @@
 		assessment_result = frappe.get_list("Assessment Result", filters={"name": ("not in", [self.name]),
 			"student":self.student, "assessment_plan":self.assessment_plan, "docstatus":("!=", 2)})
 		if assessment_result:
-			frappe.throw(_("Assessment Result record {0} already exists.".format(getlink("Assessment Result",assessment_result[0].name))))
+			frappe.throw(_("Assessment Result record {0} already exists.").format(getlink("Assessment Result",assessment_result[0].name)))
 
 
 
diff --git a/erpnext/education/doctype/course_activity/course_activity.py b/erpnext/education/doctype/course_activity/course_activity.py
index 054b192..e7fc08a 100644
--- a/erpnext/education/doctype/course_activity/course_activity.py
+++ b/erpnext/education/doctype/course_activity/course_activity.py
@@ -16,4 +16,4 @@
 		if frappe.db.exists("Course Enrollment", self.enrollment):
 			return True
 		else:
-			frappe.throw(_("Course Enrollment {0} does not exists".format(self.enrollment)))
\ No newline at end of file
+			frappe.throw(_("Course Enrollment {0} does not exists").format(self.enrollment))
\ No newline at end of file
diff --git a/erpnext/education/doctype/grading_scale/grading_scale.py b/erpnext/education/doctype/grading_scale/grading_scale.py
index e981f9f..6309d02 100644
--- a/erpnext/education/doctype/grading_scale/grading_scale.py
+++ b/erpnext/education/doctype/grading_scale/grading_scale.py
@@ -13,7 +13,7 @@
 		thresholds = []
 		for d in self.intervals:
 			if d.threshold in thresholds:
-				frappe.throw(_("Treshold {0}% appears more than once".format(d.threshold)))
+				frappe.throw(_("Treshold {0}% appears more than once").format(d.threshold))
 			else:
 				thresholds.append(cint(d.threshold))
 		if 0 not in thresholds:
diff --git a/erpnext/education/doctype/question/question.py b/erpnext/education/doctype/question/question.py
index 9a973c7..a7deeab 100644
--- a/erpnext/education/doctype/question/question.py
+++ b/erpnext/education/doctype/question/question.py
@@ -38,7 +38,7 @@
 		options = self.options
 		answers = [item.name for item in options if item.is_correct == True]
 		if len(answers) == 0:
-			frappe.throw(_("No correct answer is set for {0}".format(self.name)))
+			frappe.throw(_("No correct answer is set for {0}").format(self.name))
 			return None
 		elif len(answers) == 1:
 			return answers[0]
diff --git a/erpnext/education/doctype/student_group/student_group.py b/erpnext/education/doctype/student_group/student_group.py
index aba1b5f..aa542dd 100644
--- a/erpnext/education/doctype/student_group/student_group.py
+++ b/erpnext/education/doctype/student_group/student_group.py
@@ -34,15 +34,15 @@
 		students = [d.student for d in program_enrollment] if program_enrollment else []
 		for d in self.students:
 			if not frappe.db.get_value("Student", d.student, "enabled") and d.active and not self.disabled:
-				frappe.throw(_("{0} - {1} is inactive student".format(d.group_roll_number, d.student_name)))
+				frappe.throw(_("{0} - {1} is inactive student").format(d.group_roll_number, d.student_name))
 
 			if (self.group_based_on == "Batch") and cint(frappe.defaults.get_defaults().validate_batch)\
 				and d.student not in students:
-				frappe.throw(_("{0} - {1} is not enrolled in the Batch {2}".format(d.group_roll_number, d.student_name, self.batch)))
+				frappe.throw(_("{0} - {1} is not enrolled in the Batch {2}").format(d.group_roll_number, d.student_name, self.batch))
 
 			if (self.group_based_on == "Course") and cint(frappe.defaults.get_defaults().validate_course)\
 				and (d.student not in students):
-				frappe.throw(_("{0} - {1} is not enrolled in the Course {2}".format(d.group_roll_number, d.student_name, self.course)))
+				frappe.throw(_("{0} - {1} is not enrolled in the Course {2}").format(d.group_roll_number, d.student_name, self.course))
 
 	def validate_and_set_child_table_fields(self):
 		roll_numbers = [d.group_roll_number for d in self.students if d.group_roll_number]
@@ -55,7 +55,7 @@
 				max_roll_no += 1
 				d.group_roll_number = max_roll_no
 			if d.group_roll_number in roll_no_list:
-				frappe.throw(_("Duplicate roll number for student {0}".format(d.student_name)))
+				frappe.throw(_("Duplicate roll number for student {0}").format(d.student_name))
 			else:
 				roll_no_list.append(d.group_roll_number)
 
@@ -77,7 +77,7 @@
 		return []
 
 def get_program_enrollment(academic_year, academic_term=None, program=None, batch=None, student_category=None, course=None):
-	
+
 	condition1 = " "
 	condition2 = " "
 	if academic_term:
@@ -93,9 +93,9 @@
 		condition2 = ", `tabProgram Enrollment Course` pec"
 
 	return frappe.db.sql('''
-		select 
-			pe.student, pe.student_name 
-		from 
+		select
+			pe.student, pe.student_name
+		from
 			`tabProgram Enrollment` pe {condition2}
 		where
 			pe.academic_year = %(academic_year)s  {condition1}
diff --git a/erpnext/education/doctype/student_group_creation_tool/student_group_creation_tool.py b/erpnext/education/doctype/student_group_creation_tool/student_group_creation_tool.py
index 643093e..d7645e3 100644
--- a/erpnext/education/doctype/student_group_creation_tool/student_group_creation_tool.py
+++ b/erpnext/education/doctype/student_group_creation_tool/student_group_creation_tool.py
@@ -74,4 +74,4 @@
 				student_group.append('students', student)
 			student_group.save()
 
-		frappe.msgprint(_("{0} Student Groups created.".format(l)))
\ No newline at end of file
+		frappe.msgprint(_("{0} Student Groups created.").format(l))
\ No newline at end of file
diff --git a/erpnext/education/utils.py b/erpnext/education/utils.py
index e0b278c..cffc396 100644
--- a/erpnext/education/utils.py
+++ b/erpnext/education/utils.py
@@ -185,7 +185,7 @@
 
 	student = get_current_student()
 	if not student:
-		return frappe.throw(_("Student with email {0} does not exist".format(frappe.session.user)), frappe.DoesNotExistError)
+		return frappe.throw(_("Student with email {0} does not exist").format(frappe.session.user), frappe.DoesNotExistError)
 
 	enrollment = get_or_create_course_enrollment(course, program)
 	if content_type == 'Quiz':
@@ -220,7 +220,7 @@
 		quiz = frappe.get_doc("Quiz", quiz_name)
 		questions = quiz.get_questions()
 	except:
-		frappe.throw(_("Quiz {0} does not exist".format(quiz_name)))
+		frappe.throw(_("Quiz {0} does not exist").format(quiz_name))
 		return None
 
 	questions = [{
@@ -347,7 +347,7 @@
 	if not course_enrollment:
 		program_enrollment = get_enrollment('program', program, student.name)
 		if not program_enrollment:
-			frappe.throw(_("You are not enrolled in program {0}".format(program)))
+			frappe.throw(_("You are not enrolled in program {0}").format(program))
 			return
 		return student.enroll_in_course(course_name=course, program_enrollment=get_enrollment('program', program, student.name))
 	else:
diff --git a/erpnext/erpnext_integrations/connectors/shopify_connection.py b/erpnext/erpnext_integrations/connectors/shopify_connection.py
index 3be08a2..ca0e160 100644
--- a/erpnext/erpnext_integrations/connectors/shopify_connection.py
+++ b/erpnext/erpnext_integrations/connectors/shopify_connection.py
@@ -259,6 +259,6 @@
 		{"parent": "Shopify Settings", "shopify_tax": tax_title}, "tax_account")
 
 	if not tax_account:
-		frappe.throw(_("Tax Account not specified for Shopify Tax {0}".format(tax.get("title"))))
+		frappe.throw(_("Tax Account not specified for Shopify Tax {0}").format(tax.get("title")))
 
 	return tax_account
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
index a04d6c5..9211133 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
@@ -63,7 +63,7 @@
 
 	default_gl_account = get_default_bank_cash_account(company, "Bank")
 	if not default_gl_account:
-		frappe.throw(_("Please setup a default bank account for company {0}".format(company)))
+		frappe.throw(_("Please setup a default bank account for company {0}").format(company))
 
 	for account in response["accounts"]:
 		acc_type = frappe.db.get_value("Account Type", account["type"])
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index 7aa41c5..d562245 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -102,7 +102,7 @@
 
 	sales_invoice.save(ignore_permissions=True)
 	sales_invoice.submit()
-	frappe.msgprint(_("Sales Invoice {0} created as paid".format(sales_invoice.name)), alert=True)
+	frappe.msgprint(_("Sales Invoice {0} created as paid").format(sales_invoice.name), alert=True)
 
 def appointment_cancel(appointment_id):
 	appointment = frappe.get_doc("Patient Appointment", appointment_id)
@@ -111,7 +111,7 @@
 		sales_invoice = exists_sales_invoice(appointment)
 		if sales_invoice and cancel_sales_invoice(sales_invoice):
 			frappe.msgprint(
-				_("Appointment {0} and Sales Invoice {1} cancelled".format(appointment.name, sales_invoice.name))
+				_("Appointment {0} and Sales Invoice {1} cancelled").format(appointment.name, sales_invoice.name)
 			)
 		else:
 			validity = validity_exists(appointment.practitioner, appointment.patient)
@@ -121,7 +121,7 @@
 					visited = fee_validity.visited - 1
 					frappe.db.set_value("Fee Validity", fee_validity.name, "visited", visited)
 					frappe.msgprint(
-						_("Appointment cancelled, Please review and cancel the invoice {0}".format(fee_validity.ref_invoice))
+						_("Appointment cancelled, Please review and cancel the invoice {0}").format(fee_validity.ref_invoice)
 					)
 				else:
 					frappe.msgprint(_("Appointment cancelled"))
@@ -203,7 +203,7 @@
 	if employee:
 		# Check if it is Holiday
 		if is_holiday(employee, date):
-			frappe.throw(_("{0} is a company holiday".format(date)))
+			frappe.throw(_("{0} is a company holiday").format(date))
 
 		# Check if He/She on Leave
 		leave_record = frappe.db.sql("""select half_day from `tabLeave Application`
@@ -221,7 +221,7 @@
 			if schedule.schedule:
 				practitioner_schedule = frappe.get_doc("Practitioner Schedule", schedule.schedule)
 			else:
-				frappe.throw(_("{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master".format(practitioner)))
+				frappe.throw(_("{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master").format(practitioner))
 
 			if practitioner_schedule:
 				available_slots = []
@@ -259,7 +259,7 @@
 						"avail_slot":available_slots, 'appointments': appointments})
 
 	else:
-		frappe.throw(_("{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master".format(practitioner)))
+		frappe.throw(_("{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master").format(practitioner))
 
 	if not available_slots and not slot_details:
 		# TODO: return available slots in nearby dates
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py
index 6f9e4a9..a8ebe86 100644
--- a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py
+++ b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py
@@ -32,8 +32,8 @@
 					+ d.qty + self.rooms_booked.get(d.item)
 				total_rooms = self.get_total_rooms(d.item)
 				if total_rooms < rooms_booked:
-					frappe.throw(_("Hotel Rooms of type {0} are unavailable on {1}".format(d.item,
-						frappe.format(day, dict(fieldtype="Date")))), exc=HotelRoomUnavailableError)
+					frappe.throw(_("Hotel Rooms of type {0} are unavailable on {1}").format(d.item,
+						frappe.format(day, dict(fieldtype="Date"))), exc=HotelRoomUnavailableError)
 
 				self.rooms_booked[d.item] += rooms_booked
 
@@ -74,8 +74,8 @@
 					net_rate += day_rate[0][0]
 				else:
 					frappe.throw(
-						_("Please set Hotel Room Rate on {}".format(
-							frappe.format(day, dict(fieldtype="Date")))), exc=HotelRoomPricingNotSetError)
+						_("Please set Hotel Room Rate on {}").format(
+							frappe.format(day, dict(fieldtype="Date"))), exc=HotelRoomPricingNotSetError)
 			d.rate = net_rate
 			d.amount = net_rate * flt(d.qty)
 			self.net_total += d.amount
diff --git a/erpnext/hr/doctype/attendance/attendance.json b/erpnext/hr/doctype/attendance/attendance.json
index bc89b36..ab2dc4a 100644
--- a/erpnext/hr/doctype/attendance/attendance.json
+++ b/erpnext/hr/doctype/attendance/attendance.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-01-10 16:34:13",
@@ -64,6 +65,14 @@
    "oldfieldtype": "Data"
   },
   {
+   "depends_on": "working_hours",
+   "fieldname": "working_hours",
+   "fieldtype": "Float",
+   "label": "Working Hours",
+   "precision": "1",
+   "read_only": 1
+  },
+  {
    "default": "Present",
    "fieldname": "status",
    "fieldtype": "Select",
@@ -72,7 +81,7 @@
    "no_copy": 1,
    "oldfieldname": "status",
    "oldfieldtype": "Select",
-   "options": "\nPresent\nAbsent\nOn Leave\nHalf Day",
+   "options": "\nPresent\nAbsent\nOn Leave\nHalf Day\nWork From Home",
    "reqd": 1,
    "search_index": 1
   },
@@ -127,6 +136,12 @@
    "read_only": 1
   },
   {
+   "fieldname": "shift",
+   "fieldtype": "Link",
+   "label": "Shift",
+   "options": "Shift Type"
+  },
+  {
    "fieldname": "attendance_request",
    "fieldtype": "Link",
    "label": "Attendance Request",
@@ -144,20 +159,6 @@
    "read_only": 1
   },
   {
-   "depends_on": "working_hours",
-   "fieldname": "working_hours",
-   "fieldtype": "Float",
-   "label": "Working Hours",
-   "precision": "1",
-   "read_only": 1
-  },
-  {
-   "fieldname": "shift",
-   "fieldtype": "Link",
-   "label": "Shift",
-   "options": "Shift Type"
-  },
-  {
    "default": "0",
    "fieldname": "late_entry",
    "fieldtype": "Check",
@@ -173,7 +174,8 @@
  "icon": "fa fa-ok",
  "idx": 1,
  "is_submittable": 1,
- "modified": "2019-07-29 20:35:40.845422",
+ "links": [],
+ "modified": "2020-01-27 20:25:29.572281",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Attendance",
diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py
index c3fbed5..9e965db 100644
--- a/erpnext/hr/doctype/attendance/attendance.py
+++ b/erpnext/hr/doctype/attendance/attendance.py
@@ -52,7 +52,7 @@
 
 	def validate(self):
 		from erpnext.controllers.status_updater import validate_status
-		validate_status(self.status, ["Present", "Absent", "On Leave", "Half Day"])
+		validate_status(self.status, ["Present", "Absent", "On Leave", "Half Day", "Work From Home"])
 		self.validate_attendance_date()
 		self.validate_duplicate_record()
 		self.check_leave_record()
diff --git a/erpnext/hr/doctype/attendance/attendance_list.js b/erpnext/hr/doctype/attendance/attendance_list.js
index 1161703..6df3dbd 100644
--- a/erpnext/hr/doctype/attendance/attendance_list.js
+++ b/erpnext/hr/doctype/attendance/attendance_list.js
@@ -1,7 +1,13 @@
 frappe.listview_settings['Attendance'] = {
 	add_fields: ["status", "attendance_date"],
-	get_indicator: function(doc) {
-		return [__(doc.status), doc.status=="Present" ? "green" : "darkgrey", "status,=," + doc.status];
+	get_indicator: function (doc) {
+		if (["Present", "Work From Home"].includes(doc.status)) {
+			return [__(doc.status), "green", "status,=," + doc.status];
+		} else if (["Absent", "On Leave"].includes(doc.status)) {
+			return [__(doc.status), "red", "status,=," + doc.status];
+		} else if (doc.status == "Half Day") {
+			return [__(doc.status), "orange", "status,=," + doc.status];
+		}
 	},
 	onload: function(list_view) {
 		let me = this;
@@ -44,7 +50,7 @@
 						label: __("Status"),
 						fieldtype: "Select",
 						fieldname: "status",
-						options: ["Present", "Absent", "Half Day"],
+						options: ["Present", "Absent", "Half Day", "Work From Home"],
 						hidden:1,
 						reqd: 1,
 
@@ -102,5 +108,4 @@
 			});
 		});
 	}
-
 };
diff --git a/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py b/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py
index 25cda44..1cc2381 100644
--- a/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py
+++ b/erpnext/hr/doctype/daily_work_summary/daily_work_summary.py
@@ -97,9 +97,9 @@
 
 		return dict(replies=replies,
 			original_message=dws_group.message,
-			title=_('Work Summary for {0}'.format(
+			title=_('Work Summary for {0}').format(
 				global_date_format(self.creation)
-			)),
+			),
 			did_not_reply=', '.join(did_not_reply) or '',
 			did_not_reply_title=_('No replies from'))
 
diff --git a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js
index 22ba5ad..3205a92 100644
--- a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js
+++ b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js
@@ -124,8 +124,10 @@
 
 		var mark_employee_toolbar = $('<div class="col-sm-12 bottom-toolbar">\
 			<button class="btn btn-primary btn-mark-present btn-xs"></button>\
-			<button class="btn btn-default btn-mark-absent btn-xs"></button>\
-			<button class="btn btn-default btn-mark-half-day btn-xs"></button></div>')
+			<button class="btn btn-primary btn-mark-work-from-home btn-xs"></button>\
+			<button class="btn btn-warning btn-mark-half-day btn-xs"></button>\
+			<button class="btn btn-danger btn-mark-absent btn-xs"></button>\
+			</div>');
 
 		employee_toolbar.find(".btn-add")
 			.html(__('Check all'))
@@ -224,6 +226,31 @@
 			});
 
 
+		mark_employee_toolbar.find(".btn-mark-work-from-home")
+			.html(__('Mark Work From Home'))
+			.on("click", function() {
+				var employee_work_from_home = [];
+				$(me.wrapper).find('input[type="checkbox"]').each(function(i, check) {
+					if($(check).is(":checked")) {
+						employee_work_from_home.push(employee[i]);
+					}
+				});
+				frappe.call({
+					method: "erpnext.hr.doctype.employee_attendance_tool.employee_attendance_tool.mark_employee_attendance",
+					args:{
+						"employee_list":employee_work_from_home,
+						"status":"Work From Home",
+						"date":frm.doc.date,
+						"company":frm.doc.company
+					},
+
+					callback: function(r) {
+						erpnext.employee_attendance_tool.load_employees(frm);
+
+					}
+				});
+			});
+
 		var row;
 		$.each(employee, function(i, m) {
 			if (i===0 || (i % 4) === 0) {
diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py
index abb82f2..3a12c9c 100644
--- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py
+++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py
@@ -84,7 +84,7 @@
 			pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"])
 		except TypeError:
 			# show the error in tests?
-			frappe.throw(_("Unable to find Salary Component {0}".format(sal_struct_row.salary_component)))
+			frappe.throw(_("Unable to find Salary Component {0}").format(sal_struct_row.salary_component))
 		if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 1:
 			total_pro_rata_max += max_benefit_amount
 	if total_pro_rata_max > 0:
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 555f74c..ea531cb 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -364,11 +364,11 @@
 			return amount
 
 		except NameError as err:
-			frappe.throw(_("Name error: {0}".format(err)))
+			frappe.throw(_("Name error: {0}").format(err))
 		except SyntaxError as err:
-			frappe.throw(_("Syntax error in formula or condition: {0}".format(err)))
+			frappe.throw(_("Syntax error in formula or condition: {0}").format(err))
 		except Exception as e:
-			frappe.throw(_("Error in formula or condition: {0}".format(e)))
+			frappe.throw(_("Error in formula or condition: {0}").format(e))
 			raise
 
 	def add_employee_benefits(self, payroll_period):
@@ -705,11 +705,11 @@
 			if condition:
 				return frappe.safe_eval(condition, self.whitelisted_globals, data)
 		except NameError as err:
-			frappe.throw(_("Name error: {0}".format(err)))
+			frappe.throw(_("Name error: {0}").format(err))
 		except SyntaxError as err:
-			frappe.throw(_("Syntax error in condition: {0}".format(err)))
+			frappe.throw(_("Syntax error in condition: {0}").format(err))
 		except Exception as e:
-			frappe.throw(_("Error in formula or condition: {0}".format(e)))
+			frappe.throw(_("Error in formula or condition: {0}").format(e))
 			raise
 
 	def get_salary_slip_row(self, salary_component):
diff --git a/erpnext/hr/doctype/staffing_plan/staffing_plan.py b/erpnext/hr/doctype/staffing_plan/staffing_plan.py
index 595bcaa..5b84d00 100644
--- a/erpnext/hr/doctype/staffing_plan/staffing_plan.py
+++ b/erpnext/hr/doctype/staffing_plan/staffing_plan.py
@@ -57,8 +57,8 @@
 			and sp.to_date >= %s and sp.from_date <= %s and sp.company = %s
 		""", (staffing_plan_detail.designation, self.from_date, self.to_date, self.company))
 		if overlap and overlap [0][0]:
-			frappe.throw(_("Staffing Plan {0} already exist for designation {1}"
-				.format(overlap[0][0], staffing_plan_detail.designation)))
+			frappe.throw(_("Staffing Plan {0} already exist for designation {1}")
+				.format(overlap[0][0], staffing_plan_detail.designation))
 
 	def validate_with_parent_plan(self, staffing_plan_detail):
 		if not frappe.get_cached_value('Company',  self.company,  "parent_company"):
diff --git a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py
index 9ba6d5e..628255b 100644
--- a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py
+++ b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py
@@ -14,7 +14,7 @@
 class TestStaffingPlan(unittest.TestCase):
 	def test_staffing_plan(self):
 		_set_up()
-		frappe.db.set_value("Company", "_Test Company", "is_group", 1)
+		frappe.db.set_value("Company", "_Test Company 3", "is_group", 1)
 		if frappe.db.exists("Staffing Plan", "Test"):
 			return
 		staffing_plan = frappe.new_doc("Staffing Plan")
@@ -36,7 +36,7 @@
 		if frappe.db.exists("Staffing Plan", "Test 1"):
 			return
 		staffing_plan = frappe.new_doc("Staffing Plan")
-		staffing_plan.company = "_Test Company"
+		staffing_plan.company = "_Test Company 3"
 		staffing_plan.name = "Test 1"
 		staffing_plan.from_date = nowdate()
 		staffing_plan.to_date = add_days(nowdate(), 10)
@@ -52,7 +52,7 @@
 		if frappe.db.exists("Staffing Plan", "Test"):
 			return
 		staffing_plan = frappe.new_doc("Staffing Plan")
-		staffing_plan.company = "_Test Company"
+		staffing_plan.company = "_Test Company 3"
 		staffing_plan.name = "Test"
 		staffing_plan.from_date = nowdate()
 		staffing_plan.to_date = add_days(nowdate(), 10)
@@ -87,10 +87,11 @@
 def make_company():
 	if frappe.db.exists("Company", "_Test Company 10"):
 		return
+
 	company = frappe.new_doc("Company")
 	company.company_name = "_Test Company 10"
 	company.abbr = "_TC10"
-	company.parent_company = "_Test Company"
+	company.parent_company = "_Test Company 3"
 	company.default_currency = "INR"
 	company.country = "Pakistan"
 	company.insert()
\ No newline at end of file
diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
index 94d85f7..5f44d63 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
+++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
@@ -54,7 +54,7 @@
 					email_map[d.sales_person] = sp.get_email_id()
 				except frappe.ValidationError:
 					no_email_sp.append(d.sales_person)
-					
+
 			if no_email_sp:
 				frappe.msgprint(
 					frappe._("Setting Events to {0}, since the Employee attached to the below Sales Persons does not have a User ID{1}").format(
@@ -66,7 +66,7 @@
 				parent=%s""", (d.sales_person, d.item_code, self.name), as_dict=1)
 
 			for key in scheduled_date:
-				description =frappe._("Reference: {0}, Item Code: {1} and Customer: {2}").format(self.name, d.item_code, self.customer)	
+				description =frappe._("Reference: {0}, Item Code: {1} and Customer: {2}").format(self.name, d.item_code, self.customer)
 				frappe.get_doc({
 					"doctype": "Event",
 					"owner": email_map.get(d.sales_person, self.owner),
@@ -146,11 +146,11 @@
 			if not d.item_code:
 				throw(_("Please select item code"))
 			elif not d.start_date or not d.end_date:
-				throw(_("Please select Start Date and End Date for Item {0}".format(d.item_code)))
+				throw(_("Please select Start Date and End Date for Item {0}").format(d.item_code))
 			elif not d.no_of_visits:
 				throw(_("Please mention no of visits required"))
 			elif not d.sales_person:
-				throw(_("Please select a Sales Person for item: {0}".format(d.item_name)))
+				throw(_("Please select a Sales Person for item: {0}").format(d.item_name))
 
 			if getdate(d.start_date) >= getdate(d.end_date):
 				throw(_("Start date should be less than end date for Item {0}").format(d.item_code))
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py
index 9a2aaa5..029db1c 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -8,7 +8,7 @@
 from frappe import _
 from frappe.model.mapper import get_mapped_doc
 from frappe.model.document import Document
-from frappe.utils import (flt, cint, time_diff_in_hours, get_datetime, getdate, 
+from frappe.utils import (flt, cint, time_diff_in_hours, get_datetime, getdate,
 	get_time, add_to_date, time_diff, add_days, get_datetime_str)
 
 from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
@@ -43,7 +43,7 @@
 
 	def get_overlap_for(self, args, check_next_available_slot=False):
 		production_capacity = 1
-	
+
 		if self.workstation:
 			production_capacity = frappe.get_cached_value("Workstation",
 				self.workstation, 'production_capacity') or 1
@@ -195,8 +195,8 @@
 			frappe.throw(_("Total completed qty must be greater than zero"))
 
 		if self.total_completed_qty != self.for_quantity:
-			frappe.throw(_("The total completed qty({0}) must be equal to qty to manufacture({1})"
-				.format(frappe.bold(self.total_completed_qty),frappe.bold(self.for_quantity))))
+			frappe.throw(_("The total completed qty({0}) must be equal to qty to manufacture({1})")
+				.format(frappe.bold(self.total_completed_qty),frappe.bold(self.for_quantity)))
 
 	def update_work_order(self):
 		if not self.work_order:
@@ -372,7 +372,7 @@
 	conditions = get_filters_cond("Job Card", filters, [])
 
 	job_cards = frappe.db.sql(""" SELECT `tabJob Card`.name, `tabJob Card`.work_order,
-			`tabJob Card`.employee_name, `tabJob Card`.status, ifnull(`tabJob Card`.remarks, ''), 
+			`tabJob Card`.employee_name, `tabJob Card`.status, ifnull(`tabJob Card`.remarks, ''),
 			min(`tabJob Card Time Log`.from_time) as from_time,
 			max(`tabJob Card Time Log`.to_time) as to_time
 		FROM `tabJob Card` , `tabJob Card Time Log`
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 8876253..848c53c 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -22,7 +22,7 @@
 	def validate_data(self):
 		for d in self.get('po_items'):
 			if not d.bom_no:
-				frappe.throw(_("Please select BOM for Item in Row {0}".format(d.idx)))
+				frappe.throw(_("Please select BOM for Item in Row {0}").format(d.idx))
 			else:
 				validate_bom_no(d.item_code, d.bom_no)
 
@@ -732,6 +732,6 @@
 				})
 
 			bom_item = bom_data.get(key)
-			bom_item["stock_qty"] += d.stock_qty
+			bom_item["stock_qty"] += d.stock_qty / d.parent_bom_qty
 
 			get_sub_assembly_items(bom_item.get("bom_no"), bom_data)
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index 619b21a..dd4a872 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -461,7 +461,7 @@
 	def validate_operation_time(self):
 		for d in self.operations:
 			if not d.time_in_mins > 0:
-				frappe.throw(_("Operation Time must be greater than 0 for Operation {0}".format(d.operation)))
+				frappe.throw(_("Operation Time must be greater than 0 for Operation {0}").format(d.operation))
 
 	def update_required_items(self):
 		'''
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index bf6e21a..afdb5b7 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -188,7 +188,7 @@
 	def send_welcome_email(self):
 		url = get_url("/project/?name={0}".format(self.name))
 		messages = (
-			_("You have been invited to collaborate on the project: {0}".format(self.name)),
+			_("You have been invited to collaborate on the project: {0}").format(self.name),
 			url,
 			_("Join")
 		)
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 45f2681..d56bb23 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -56,8 +56,8 @@
 	def validate_status(self):
 		if self.status!=self.get_db_value("status") and self.status == "Completed":
 			for d in self.depends_on:
-				if frappe.db.get_value("Task", d.task, "status") != "Completed":
-					frappe.throw(_("Cannot close task {0} as its dependant task {1} is not closed.").format(frappe.bold(self.name), frappe.bold(d.task)))
+				if frappe.db.get_value("Task", d.task, "status") not in ("Completed", "Cancelled"):
+					frappe.throw(_("Cannot complete task {0} as its dependant task {1} are not ccompleted / cancelled.").format(frappe.bold(self.name), frappe.bold(d.task)))
 
 			close_all_assignments(self.doctype, self.name)
 
diff --git a/erpnext/public/js/conf.js b/erpnext/public/js/conf.js
index 095e744..0f88f13 100644
--- a/erpnext/public/js/conf.js
+++ b/erpnext/public/js/conf.js
@@ -50,7 +50,7 @@
 	"Territory": "Selling",
 	"Sales Person": "Selling",
 	"Sales Partner": "Selling",
-	"Brand": "Selling"
+	"Brand": "Stock"
 });
 
 $.extend(frappe.breadcrumbs.module_map, {
diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py
index b4de03e..d29710d 100644
--- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py
+++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py
@@ -15,7 +15,7 @@
 			if process.procedure:
 				doc = frappe.get_doc("Quality Procedure", process.procedure)
 				if doc.parent_quality_procedure:
-					frappe.throw(_("{0} already has a Parent Procedure {1}.".format(process.procedure, doc.parent_quality_procedure)))
+					frappe.throw(_("{0} already has a Parent Procedure {1}.").format(process.procedure, doc.parent_quality_procedure))
 				self.is_group = 1
 
 	def on_update(self):
diff --git a/erpnext/regional/__init__.py b/erpnext/regional/__init__.py
index 630d5fa..faa5912 100644
--- a/erpnext/regional/__init__.py
+++ b/erpnext/regional/__init__.py
@@ -9,7 +9,7 @@
 def check_deletion_permission(doc, method):
 	region = get_region(doc.company)
 	if region in ["Nepal", "France"] and doc.docstatus != 0:
-		frappe.throw(_("Deletion is not permitted for country {0}".format(region)))
+		frappe.throw(_("Deletion is not permitted for country {0}").format(region))
 
 def create_transaction_log(doc, method):
 	"""
diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
index 79dace7..a2b32fe 100644
--- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
+++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
@@ -417,7 +417,7 @@
 		if gst_details:
 			return gst_details[0]
 		else:
-			frappe.throw(_("Please enter GSTIN and state for the Company Address {0}".format(self.company_address)))
+			frappe.throw(_("Please enter GSTIN and state for the Company Address {0}").format(self.company_address))
 
 	def get_account_heads(self):
 
@@ -430,7 +430,7 @@
 		if account_heads:
 			return account_heads
 		else:
-			frappe.throw(_("Please set account heads in GST Settings for Compnay {0}".format(self.company)))
+			frappe.throw(_("Please set account heads in GST Settings for Compnay {0}").format(self.company))
 
 	def get_missing_field_invoices(self):
 
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 0f9156a..3a187ba 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -550,9 +550,9 @@
 
 	for fieldname in reqd_fields:
 		if not doc.get(fieldname):
-			frappe.throw(_('{} is required to generate e-Way Bill JSON'.format(
+			frappe.throw(_('{} is required to generate e-Way Bill JSON').format(
 				doc.meta.get_label(fieldname)
-			)))
+			))
 
 	if len(doc.company_gstin) < 15:
 		frappe.throw(_('You must be a registered supplier to generate e-Way Bill'))
diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py
index 2af72f8..6842fb2 100644
--- a/erpnext/regional/italy/utils.py
+++ b/erpnext/regional/italy/utils.py
@@ -252,7 +252,7 @@
 	else:
 		for row in doc.taxes:
 			if row.rate == 0 and row.tax_amount == 0 and not row.tax_exemption_reason:
-				frappe.throw(_("Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges".format(row.idx)),
+				frappe.throw(_("Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges").format(row.idx),
 					title=_("E-Invoicing Information Missing"))
 
 	for schedule in doc.payment_schedule:
@@ -272,10 +272,10 @@
 	else:
 		for schedule in doc.payment_schedule:
 			if not schedule.mode_of_payment:
-				frappe.throw(_("Row {0}: Please set the Mode of Payment in Payment Schedule".format(schedule.idx)),
+				frappe.throw(_("Row {0}: Please set the Mode of Payment in Payment Schedule").format(schedule.idx),
 					title=_("E-Invoicing Information Missing"))
 			elif not frappe.db.get_value("Mode of Payment", schedule.mode_of_payment, "mode_of_payment_code"):
-				frappe.throw(_("Row {0}: Please set the correct code on Mode of Payment {1}".format(schedule.idx, schedule.mode_of_payment)),
+				frappe.throw(_("Row {0}: Please set the correct code on Mode of Payment {1}").format(schedule.idx, schedule.mode_of_payment),
 					title=_("E-Invoicing Information Missing"))
 
 	prepare_and_attach_invoice(doc)
@@ -355,7 +355,7 @@
 
 	for field in fields:
 		if not data.get(field):
-			frappe.throw(_("Please set {0} for address {1}".format(field.replace('-',''), address_name)),
+			frappe.throw(_("Please set {0} for address {1}").format(field.replace('-',''), address_name),
 				title=_("E-Invoicing Information Missing"))
 
 def get_unamended_name(doc):
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 4f9cc7f..2c5ab7c 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -719,9 +719,9 @@
 	if gstin:
 		return gstin[0]["gstin"]
 	else:
-		frappe.throw(_("Please set valid GSTIN No. in Company Address for company {0}".format(
+		frappe.throw(_("Please set valid GSTIN No. in Company Address for company {0}").format(
 			frappe.bold(company)
-		)))
+		))
 
 @frappe.whitelist()
 def download_json_file():
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 c45571f..bb5f83e 100644
--- a/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.py
+++ b/erpnext/selling/doctype/pos_closing_voucher/pos_closing_voucher.py
@@ -50,8 +50,8 @@
 			})
 
 		if user:
-			frappe.throw(_("POS Closing Voucher alreday exists for {0} between date {1} and {2}"
-				.format(self.user, self.period_start_date, self.period_end_date)))
+			frappe.throw(_("POS Closing Voucher alreday exists for {0} between date {1} and {2}")
+				.format(self.user, self.period_start_date, self.period_end_date))
 
 	def set_invoice_list(self, invoice_list):
 		self.sales_invoices_summary = []
diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py
index d7ebafc..0cb606b 100644
--- a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py
+++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py
@@ -78,19 +78,19 @@
 
 		columns.extend([{
 			"fieldname": target_key,
-			"label": _("Target ({})".format(period.label)),
+			"label": _("Target ({})").format(period.label),
 			"fieldtype": fieldtype,
 			"options": options,
 			"width": 100
 		}, {
 			"fieldname": period.key,
-			"label": _("Achieved ({})".format(period.label)),
+			"label": _("Achieved ({})").format(period.label),
 			"fieldtype": fieldtype,
 			"options": options,
 			"width": 100
 		}, {
 			"fieldname": variance_key,
-			"label": _("Variance ({})".format(period.label)),
+			"label": _("Variance ({})").format(period.label),
 			"fieldtype": fieldtype,
 			"options": options,
 			"width": 100
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index be736d2..0fbe49e 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -4,6 +4,15 @@
 frappe.provide("erpnext.company");
 
 frappe.ui.form.on("Company", {
+	onload: function(frm) {
+		if (frm.doc.__islocal && frm.doc.parent_company) {
+			frappe.db.get_value('Company', frm.doc.parent_company, 'is_group', (r) => {
+				if (!r.is_group) {
+					frm.set_value('parent_company', '');
+				}
+			});
+		}
+	},
 	setup: function(frm) {
 		erpnext.company.setup_queries(frm);
 		frm.set_query("hra_component", function(){
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index ff35154..6aa2c04 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -47,6 +47,7 @@
 		self.validate_perpetual_inventory()
 		self.check_country_change()
 		self.set_chart_of_accounts()
+		self.validate_parent_company()
 
 	def validate_abbr(self):
 		if not self.abbr:
@@ -189,6 +190,13 @@
 			self.create_chart_of_accounts_based_on = "Existing Company"
 			self.existing_company = self.parent_company
 
+	def validate_parent_company(self):
+		if self.parent_company:
+			is_group = frappe.get_value('Company', self.parent_company, 'is_group')
+
+			if not is_group:
+				frappe.throw(_("Parent Company must be a group company"))
+
 	def set_default_accounts(self):
 		default_accounts = {
 			"default_cash_account": "Cash",
diff --git a/erpnext/setup/doctype/company/test_company.py b/erpnext/setup/doctype/company/test_company.py
index 1664b66..af30abd 100644
--- a/erpnext/setup/doctype/company/test_company.py
+++ b/erpnext/setup/doctype/company/test_company.py
@@ -81,7 +81,7 @@
 							filters["is_group"] = 1
 
 						has_matching_accounts = frappe.get_all("Account", filters)
-						error_message = _("No Account matched these filters: {}".format(json.dumps(filters)))
+						error_message = _("No Account matched these filters: {}").format(json.dumps(filters))
 
 						self.assertTrue(has_matching_accounts, msg=error_message)
 				finally:
@@ -124,7 +124,7 @@
 		child_company.insert()
 	else:
 		child_company = frappe.get_doc("Company", child_company)
-	
+
 	return child_company.name
 
 def create_test_lead_in_company(company):
diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py
index 22375ae..9f25882 100644
--- a/erpnext/setup/doctype/item_group/item_group.py
+++ b/erpnext/setup/doctype/item_group/item_group.py
@@ -119,7 +119,7 @@
 				or I.name like %(search)s)"""
 		search = "%" + cstr(search) + "%"
 
-	query += """order by I.weightage desc, in_stock desc, I.modified desc limit %s, %s""" % (start, limit)
+	query += """order by I.weightage desc, in_stock desc, I.modified desc limit %s, %s""" % (cint(start), cint(limit))
 
 	data = frappe.db.sql(query, {"product_group": product_group,"search": search, "today": nowdate()}, as_dict=1)
 	data = adjust_qty_for_expired_items(data)
diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py
index 1a86b79..439e6a5 100644
--- a/erpnext/setup/utils.py
+++ b/erpnext/setup/utils.py
@@ -143,5 +143,5 @@
 
 def welcome_email():
 	site_name = get_default_company()
-	title = _("Welcome to {0}".format(site_name))
+	title = _("Welcome to {0}").format(site_name)
 	return title
diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py
index 813d0dd..1dac9bd 100644
--- a/erpnext/shopping_cart/cart.py
+++ b/erpnext/shopping_cart/cart.py
@@ -431,7 +431,7 @@
 	payment_gateway_account_currency = \
 		frappe.get_doc("Payment Gateway Account", cart_settings.payment_gateway_account).currency
 
-	account_name = _("Debtors ({0})".format(payment_gateway_account_currency))
+	account_name = _("Debtors ({0})").format(payment_gateway_account_currency)
 
 	debtors_account_name = get_account_name("Receivable", "Asset", is_group=0,\
 		account_currency=payment_gateway_account_currency, company=cart_settings.company)
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.json b/erpnext/stock/doctype/delivery_trip/delivery_trip.json
index 1bacf46..879901f 100644
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.json
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.json
@@ -165,6 +165,7 @@
   },
   {
    "fetch_from": "driver.address",
+   "fetch_if_empty": 1,
    "fieldname": "driver_address",
    "fieldtype": "Link",
    "label": "Driver Address",
@@ -179,7 +180,7 @@
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2019-12-06 17:06:59.681952",
+ "modified": "2020-01-26 22:37:14.824021",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Trip",
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
index e2c5b91..a34db45 100644
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
@@ -88,7 +88,7 @@
 			note_doc.save()
 
 		delivery_notes = [get_link_to_form("Delivery Note", note) for note in delivery_notes]
-		frappe.msgprint(_("Delivery Notes {0} updated".format(", ".join(delivery_notes))))
+		frappe.msgprint(_("Delivery Notes {0} updated").format(", ".join(delivery_notes)))
 
 	def process_route(self, optimize):
 		"""
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index a1f06b2..d036a0a 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -814,7 +814,7 @@
 			for d in self.attributes:
 				if d.attribute in attributes:
 					frappe.throw(
-						_("Attribute {0} selected multiple times in Attributes Table".format(d.attribute)))
+						_("Attribute {0} selected multiple times in Attributes Table").format(d.attribute))
 				else:
 					attributes.append(d.attribute)
 
diff --git a/erpnext/stock/doctype/item_alternative/item_alternative.py b/erpnext/stock/doctype/item_alternative/item_alternative.py
index 8e54539..b14683b 100644
--- a/erpnext/stock/doctype/item_alternative/item_alternative.py
+++ b/erpnext/stock/doctype/item_alternative/item_alternative.py
@@ -25,7 +25,7 @@
 	def validate_duplicate(self):
 		if frappe.db.get_value("Item Alternative", {'item_code': self.item_code,
 			'alternative_item_code': self.alternative_item_code, 'name': ('!=', self.name)}):
-			frappe.throw(_("Already record exists for the item {0}".format(self.item_code)))
+			frappe.throw(_("Already record exists for the item {0}").format(self.item_code))
 
 def get_alternative_items(doctype, txt, searchfield, start, page_len, filters):
 	return frappe.db.sql(""" (select alternative_item_code from `tabItem Alternative`
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 6531e09..941f904 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -371,7 +371,7 @@
 	supplier_items = [d.parent for d in frappe.db.get_all("Item Default",
 		{"default_supplier": supplier}, 'parent')]
 	if not supplier_items:
-		frappe.throw(_("{0} is not the default supplier for any items.".format(supplier)))
+		frappe.throw(_("{0} is not the default supplier for any items.").format(supplier))
 
 	material_requests = frappe.db.sql_list("""select distinct mr.name
 		from `tabMaterial Request` mr, `tabMaterial Request Item` mr_item
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.js b/erpnext/stock/report/stock_ledger/stock_ledger.js
index df3bba5..3d5cfdc 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.js
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.js
@@ -83,6 +83,9 @@
 		if (column.fieldname == "out_qty" && data.out_qty < 0) {
 			value = "<span style='color:red'>" + value + "</span>";
 		}
+		else if (column.fieldname == "in_qty" && data.in_qty > 0) {
+			value = "<span style='color:green'>" + value + "</span>";
+		}
 
 		return value;
 	},
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index fc49db5..28d7208 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -38,11 +38,14 @@
 
 			sle.update({
 				"qty_after_transaction": actual_qty,
-				"stock_value": stock_value,
-				"in_qty": max(sle.actual_qty, 0),
-				"out_qty": min(sle.actual_qty, 0)
+				"stock_value": stock_value
 			})
 
+		sle.update({
+			"in_qty": max(sle.actual_qty, 0),
+			"out_qty": min(sle.actual_qty, 0)
+		})
+
 		# get the name of the item that was produced using this item
 		if sle.voucher_type == "Stock Entry":
 			purpose, work_order, fg_completed_qty = frappe.db.get_value(sle.voucher_type, sle.voucher_no, ["purpose", "work_order", "fg_completed_qty"])
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index b748e3f..1ca6de4 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -167,11 +167,11 @@
 
 		if not service_level_agreement:
 			if frappe.db.get_value("Issue", self.name, "service_level_agreement"):
-				frappe.throw(_("Couldn't Set Service Level Agreement {0}.".format(self.service_level_agreement)))
+				frappe.throw(_("Couldn't Set Service Level Agreement {0}.").format(self.service_level_agreement))
 			return
 
 		if (service_level_agreement.customer and self.customer) and not (service_level_agreement.customer == self.customer):
-			frappe.throw(_("This Service Level Agreement is specific to Customer {0}".format(service_level_agreement.customer)))
+			frappe.throw(_("This Service Level Agreement is specific to Customer {0}").format(service_level_agreement.customer))
 
 		self.service_level_agreement = service_level_agreement.name
 		self.priority = service_level_agreement.default_priority if not priority else priority
@@ -238,7 +238,7 @@
 		allotted_days = service_level.get("resolution_time")
 		time_period = service_level.get("resolution_time_period")
 	else:
-		frappe.throw(_("{0} parameter is invalid".format(parameter)))
+		frappe.throw(_("{0} parameter is invalid").format(parameter))
 
 	allotted_hours = 0
 	if time_period == 'Hour':
diff --git a/erpnext/support/doctype/service_level/service_level.py b/erpnext/support/doctype/service_level/service_level.py
index 4e70a01..89fa25c 100644
--- a/erpnext/support/doctype/service_level/service_level.py
+++ b/erpnext/support/doctype/service_level/service_level.py
@@ -22,7 +22,7 @@
 		for priority in self.priorities:
 			# Check if response and resolution time is set for every priority
 			if not (priority.response_time or priority.resolution_time):
-				frappe.throw(_("Set Response Time and Resolution for Priority {0} at index {1}.".format(priority.priority, priority.idx)))
+				frappe.throw(_("Set Response Time and Resolution for Priority {0} at index {1}.").format(priority.priority, priority.idx))
 
 			priorities.append(priority.priority)
 
@@ -44,12 +44,12 @@
 				resolution = priority.resolution_time * 7
 
 			if response > resolution:
-				frappe.throw(_("Response Time for {0} at index {1} can't be greater than Resolution Time.".format(priority.priority, priority.idx)))
+				frappe.throw(_("Response Time for {0} at index {1} can't be greater than Resolution Time.").format(priority.priority, priority.idx))
 
 		# Check if repeated priority
 		if not len(set(priorities)) == len(priorities):
 			repeated_priority = get_repeated(priorities)
-			frappe.throw(_("Priority {0} has been repeated.".format(repeated_priority)))
+			frappe.throw(_("Priority {0} has been repeated.").format(repeated_priority))
 
 		# Check if repeated default priority
 		if not len(set(default_priority)) == len(default_priority):
@@ -81,7 +81,7 @@
 		# Check for repeated workday
 		if not len(set(support_days)) == len(support_days):
 			repeated_days = get_repeated(support_days)
-			frappe.throw(_("Workday {0} has been repeated.".format(repeated_days)))
+			frappe.throw(_("Workday {0} has been repeated.").format(repeated_days))
 
 def get_repeated(values):
 	unique_list = []
diff --git a/erpnext/templates/pages/integrations/gocardless_checkout.py b/erpnext/templates/pages/integrations/gocardless_checkout.py
index e604b94..96a0f42 100644
--- a/erpnext/templates/pages/integrations/gocardless_checkout.py
+++ b/erpnext/templates/pages/integrations/gocardless_checkout.py
@@ -64,7 +64,7 @@
 
 	try:
 		redirect_flow = client.redirect_flows.create(params={
-							"description": _("Pay {0} {1}".format(data['amount'], data['currency'])),
+							"description": _("Pay {0} {1}").format(data['amount'], data['currency']),
 							"session_token": frappe.session.user,
 							"success_redirect_url": success_url,
 							"prefilled_customer": prefilled_customer
diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv
index 5da1e77..3764843 100644
--- a/erpnext/translations/fr.csv
+++ b/erpnext/translations/fr.csv
@@ -5432,7 +5432,7 @@
 apps/erpnext/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py,New Customers,Nouveaux Clients
 apps/erpnext/erpnext/accounts/report/gross_profit/gross_profit.py,Gross Profit %,Bénéfice Brut %
 apps/erpnext/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py,Appointment {0} and Sales Invoice {1} cancelled,Rendez-vous {0} et facture de vente {1} annulés
-apps/erpnext/erpnext/selling/page/sales_funnel/sales_funnel.js,Opportunities by lead source,Opportunités par source de plomb
+apps/erpnext/erpnext/selling/page/sales_funnel/sales_funnel.js,Opportunities by lead source,Opportunités par source de prospect
 DocType: Appraisal Goal,Weightage (%),Poids (%)
 apps/erpnext/erpnext/selling/page/point_of_sale/point_of_sale.js,Change POS Profile,Modifier le profil POS
 DocType: Bank Reconciliation Detail,Clearance Date,Date de Compensation
diff --git a/erpnext/utilities/bot.py b/erpnext/utilities/bot.py
index 23e1dd4..0e5e95d 100644
--- a/erpnext/utilities/bot.py
+++ b/erpnext/utilities/bot.py
@@ -36,4 +36,4 @@
 				return "\n\n".join(out)
 
 			else:
-				return _("Did not find any item called {0}".format(item))
\ No newline at end of file
+				return _("Did not find any item called {0}").format(item)
\ No newline at end of file
diff --git a/erpnext/www/book_appointment/index.js b/erpnext/www/book_appointment/index.js
index 262e31b..377a3cc 100644
--- a/erpnext/www/book_appointment/index.js
+++ b/erpnext/www/book_appointment/index.js
@@ -181,10 +181,32 @@
     navigate_to_page(2)
     let date_container = document.getElementsByClassName('date-span')[0];
     let time_container = document.getElementsByClassName('time-span')[0];
+    setup_search_params();
     date_container.innerHTML = moment(window.selected_date).format("MMM Do YYYY");
     time_container.innerHTML = moment(window.selected_time, "HH:mm:ss").format("LT");
 }
 
+function setup_search_params() {
+    let search_params = new URLSearchParams(window.location.search);
+    let customer_name = search_params.get("name")
+    let customer_email = search_params.get("email")
+    let detail = search_params.get("details")
+    if (customer_name) {
+        let name_input = document.getElementById("customer_name");
+        name_input.value = customer_name;
+        name_input.disabled = true;
+    }
+    if(customer_email) {
+        let email_input = document.getElementById("customer_email");
+        email_input.value = customer_email;
+        email_input.disabled = true;
+    }
+    if(detail) {
+        let detail_input = document.getElementById("customer_notes");
+        detail_input.value = detail;
+        detail_input.disabled = true;
+    }
+}
 async function submit() {
     let button = document.getElementById('submit-button');
     button.disabled = true;
diff --git a/erpnext/www/lms/program.py b/erpnext/www/lms/program.py
index 7badedc..d3b04c2 100644
--- a/erpnext/www/lms/program.py
+++ b/erpnext/www/lms/program.py
@@ -22,7 +22,7 @@
 	try:
 		return frappe.get_doc('Program', program_name)
 	except frappe.DoesNotExistError:
-		frappe.throw(_("Program {0} does not exist.".format(program_name)))
+		frappe.throw(_("Program {0} does not exist.").format(program_name))
 
 def get_course_progress(courses, program):
 	progress = {course.name: utils.get_course_progress(course, program) for course in courses}