Merge pull request #19955 from deepeshgarg007/employee_advance_return

feat: Capture return amount against Employee Advance via Journal Entry
diff --git a/README.md b/README.md
index 64f8d67..ed57a17 100644
--- a/README.md
+++ b/README.md
@@ -13,9 +13,26 @@
 
 </div>
 
-Includes: Accounting, Inventory, Manufacturing, CRM, Sales, Purchase, Project Management, HRMS. Requires MariaDB.
+ERPNext as a monolith includes the following areas for managing businesses:
 
-ERPNext is built on the [Frappe](https://github.com/frappe/frappe) Framework, a full-stack web app framework in Python & JavaScript.
+1. [Accounting](https://erpnext.com/docs/user/manual/en/accounts)
+1. [Inventory](https://erpnext.com/docs/user/manual/en/stock)
+1. [CRM](https://erpnext.com/docs/user/manual/en/CRM)
+1. [Sales](https://erpnext.com/docs/user/manual/en/selling)
+1. [Purchase](https://erpnext.com/docs/user/manual/en/buying)
+1. [HRMS](https://erpnext.com/docs/user/manual/en/human-resources)
+1. [Project Management](https://erpnext.com/docs/user/manual/en/projects)
+1. [Support](https://erpnext.com/docs/user/manual/en/support)
+1. [Asset Management](https://erpnext.com/docs/user/manual/en/asset)
+1. [Quality Management](https://erpnext.com/docs/user/manual/en/quality-management)
+1. [Manufacturing](https://erpnext.com/docs/user/manual/en/manufacturing)
+1. [Website Management](https://erpnext.com/docs/user/manual/en/website)
+1. [Customize ERPNext](https://erpnext.com/docs/user/manual/en/customize-erpnext)
+1. [And More](https://erpnext.com/docs/user/manual/en/)
+
+ERPNext requires MariaDB.
+
+ERPNext is built on the [Frappe Framework](https://github.com/frappe/frappe), a full-stack web app framework built with Python & JavaScript.
 
 - [User Guide](https://erpnext.com/docs/user)
 - [Discussion Forum](https://discuss.erpnext.com/)
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index 078e058..041e419 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -29,7 +29,6 @@
 		self.validate_and_set_fiscal_year()
 		self.pl_must_have_cost_center()
 		self.validate_cost_center()
-		self.validate_dimensions_for_pl_and_bs()
 
 		if not self.flags.from_repost:
 			self.check_pl_account()
@@ -39,6 +38,7 @@
 	def on_update_with_args(self, adv_adj, update_outstanding = 'Yes', from_repost=False):
 		if not from_repost:
 			self.validate_account_details(adv_adj)
+			self.validate_dimensions_for_pl_and_bs()
 			check_freezing_date(self.posting_date, adv_adj)
 
 		validate_frozen_account(self.account, adv_adj)
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index e25942c..8897337 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -968,7 +968,7 @@
 
 		# The date used to retreive the exchange rate here is the date passed
 		# in as an argument to this function.
-		elif (not exchange_rate or exchange_rate==1) and account_currency and posting_date:
+		elif (not exchange_rate or flt(exchange_rate)==1) and account_currency and posting_date:
 			exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date)
 	else:
 		exchange_rate = 1
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index adf47ed..2192b7b 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -652,14 +652,16 @@
 						(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student")
 					) {
 						if(total_positive_outstanding > total_negative_outstanding)
-							frm.set_value("paid_amount",
-								total_positive_outstanding - total_negative_outstanding);
+							if (!frm.doc.paid_amount)
+								frm.set_value("paid_amount",
+									total_positive_outstanding - total_negative_outstanding);
 					} else if (
 						total_negative_outstanding &&
 						total_positive_outstanding < total_negative_outstanding
 					) {
-						frm.set_value("received_amount",
-							total_negative_outstanding - total_positive_outstanding);
+						if (!frm.doc.received_amount)
+							frm.set_value("received_amount",
+								total_negative_outstanding - total_positive_outstanding);
 					}
 				}
 
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
index 971d308..29d8378 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json
@@ -389,8 +389,7 @@
    "fieldname": "rate_or_discount",
    "fieldtype": "Select",
    "label": "Rate or Discount",
-   "options": "\nRate\nDiscount Percentage\nDiscount Amount",
-   "reqd": 1
+   "options": "\nRate\nDiscount Percentage\nDiscount Amount"
   },
   {
    "default": "Grand Total",
@@ -439,19 +438,20 @@
   },
   {
    "default": "0",
-   "depends_on": "eval:!doc.mixed_conditions",
+   "depends_on": "eval:!doc.mixed_conditions && doc.apply_on != 'Transaction'",
    "fieldname": "same_item",
    "fieldtype": "Check",
    "label": "Same Item"
   },
   {
-   "depends_on": "eval:!doc.same_item || doc.mixed_conditions",
+   "depends_on": "eval:(!doc.same_item || doc.apply_on == 'Transaction') || doc.mixed_conditions",
    "fieldname": "free_item",
    "fieldtype": "Link",
    "label": "Free Item",
    "options": "Item"
   },
   {
+   "default": "0",
    "fieldname": "free_qty",
    "fieldtype": "Float",
    "label": "Qty"
@@ -554,7 +554,7 @@
  ],
  "icon": "fa fa-gift",
  "idx": 1,
- "modified": "2019-10-15 12:39:40.399792",
+ "modified": "2019-12-18 17:29:22.957077",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Pricing Rule",
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index e871d98..3c14819 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -47,6 +47,9 @@
 		if tocheck and not self.get(tocheck):
 			throw(_("{0} is required").format(self.meta.get_label(tocheck)), frappe.MandatoryError)
 
+		if self.price_or_product_discount == 'Price' and not self.rate_or_discount:
+			throw(_("Rate or Discount is required for the price discount."), frappe.MandatoryError)
+
 	def validate_applicable_for_selling_or_buying(self):
 		if not self.selling and not self.buying:
 			throw(_("Atleast one of the Selling or Buying must be selected"))
@@ -182,7 +185,7 @@
 
 def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=False):
 	from erpnext.accounts.doctype.pricing_rule.utils import (get_pricing_rules,
-		get_applied_pricing_rules, get_pricing_rule_items)
+		get_applied_pricing_rules, get_pricing_rule_items, get_product_discount_rule)
 
 	if isinstance(doc, string_types):
 		doc = json.loads(doc)
@@ -241,9 +244,11 @@
 			if pricing_rule.coupon_code_based==1 and args.coupon_code==None:
 				return item_details
 				
-			if (not pricing_rule.validate_applied_rule and
-				pricing_rule.price_or_product_discount == "Price"):
-				apply_price_discount_pricing_rule(pricing_rule, item_details, args)
+			if not pricing_rule.validate_applied_rule:
+				if pricing_rule.price_or_product_discount == "Price":
+					apply_price_discount_rule(pricing_rule, item_details, args)
+				else:
+					get_product_discount_rule(pricing_rule, item_details, doc)
 
 		item_details.has_pricing_rule = 1
 
@@ -293,7 +298,7 @@
 		'child_docname': args.get('child_docname')
 	})
 
-def apply_price_discount_pricing_rule(pricing_rule, item_details, args):
+def apply_price_discount_rule(pricing_rule, item_details, args):
 	item_details.pricing_rule_for = pricing_rule.rate_or_discount
 
 	if ((pricing_rule.margin_type == 'Amount' and pricing_rule.currency == args.currency)
diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py
index 7af6748..87f6822 100644
--- a/erpnext/accounts/doctype/pricing_rule/utils.py
+++ b/erpnext/accounts/doctype/pricing_rule/utils.py
@@ -7,7 +7,7 @@
 import frappe, copy, json
 from frappe import throw, _
 from six import string_types
-from frappe.utils import flt, cint, get_datetime
+from frappe.utils import flt, cint, get_datetime, get_link_to_form, today
 from erpnext.setup.doctype.item_group.item_group import get_child_item_groups
 from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses
 from erpnext.stock.get_item_details import get_conversion_factor
@@ -408,7 +408,8 @@
 	conditions = get_other_conditions(conditions, values, doc)
 
 	pricing_rules = frappe.db.sql(""" Select `tabPricing Rule`.* from `tabPricing Rule`
-		where {conditions} """.format(conditions = conditions), values, as_dict=1)
+		where  {conditions} and `tabPricing Rule`.disable = 0
+	""".format(conditions = conditions), values, as_dict=1)
 
 	if pricing_rules:
 		pricing_rules = filter_pricing_rules_for_qty_amount(doc.total_qty,
@@ -420,39 +421,65 @@
 					doc.set('apply_discount_on', d.apply_discount_on)
 
 				for field in ['additional_discount_percentage', 'discount_amount']:
-					if not d.get(field): continue
-
 					pr_field = ('discount_percentage'
 						if field == 'additional_discount_percentage' else field)
 
+					if not d.get(pr_field): continue
+
 					if d.validate_applied_rule and doc.get(field) < d.get(pr_field):
 						frappe.msgprint(_("User has not applied rule on the invoice {0}")
 							.format(doc.name))
 					else:
 						doc.set(field, d.get(pr_field))
+
+				doc.calculate_taxes_and_totals()
 			elif d.price_or_product_discount == 'Product':
-				apply_pricing_rule_for_free_items(doc, d)
+				item_details = frappe._dict({'parenttype': doc.doctype})
+				get_product_discount_rule(d, item_details, doc)
+				apply_pricing_rule_for_free_items(doc, item_details.free_item_data)
+				doc.set_missing_values()
 
 def get_applied_pricing_rules(item_row):
 	return (item_row.get("pricing_rules").split(',')
 		if item_row.get("pricing_rules") else [])
 
-def apply_pricing_rule_for_free_items(doc, pricing_rule):
-	if pricing_rule.get('free_item'):
+def get_product_discount_rule(pricing_rule, item_details, doc=None):
+	free_item = (pricing_rule.free_item
+		if not pricing_rule.same_item or pricing_rule.apply_on == 'Transaction' else item_details.item_code)
+
+	if not free_item:
+		frappe.throw(_("Free item not set in the pricing rule {0}")
+			.format(get_link_to_form("Pricing Rule", pricing_rule.name)))
+
+	item_details.free_item_data = {
+		'item_code': free_item,
+		'qty': pricing_rule.free_qty or 1,
+		'rate': pricing_rule.free_item_rate or 0,
+		'price_list_rate': pricing_rule.free_item_rate or 0,
+		'is_free_item': 1
+	}
+
+	item_data = frappe.get_cached_value('Item', free_item, ['item_name',
+		'description', 'stock_uom'], as_dict=1)
+
+	item_details.free_item_data.update(item_data)
+	item_details.free_item_data['uom'] = pricing_rule.free_item_uom or item_data.stock_uom
+	item_details.free_item_data['conversion_factor'] = get_conversion_factor(free_item, 
+		item_details.free_item_data['uom']).get("conversion_factor", 1)
+
+	if item_details.get("parenttype") == 'Purchase Order':
+		item_details.free_item_data['schedule_date'] = doc.schedule_date if doc else today()
+
+	if item_details.get("parenttype") == 'Sales Order':
+		item_details.free_item_data['delivery_date'] = doc.delivery_date if doc else today()
+
+def apply_pricing_rule_for_free_items(doc, pricing_rule_args, set_missing_values=False):
+	if pricing_rule_args.get('item_code'):
 		items = [d.item_code for d in doc.items
-			if d.item_code == (d.item_code
-			if pricing_rule.get('same_item') else pricing_rule.get('free_item')) and d.is_free_item]
+			if d.item_code == (pricing_rule_args.get("item_code")) and d.is_free_item]
 
 		if not items:
-			doc.append('items', {
-				'item_code': pricing_rule.get('free_item'),
-				'qty': pricing_rule.get('free_qty'),
-				'uom': pricing_rule.get('free_item_uom'),
-				'rate': pricing_rule.get('free_item_rate') or 0,
-				'is_free_item': 1
-			})
-
-			doc.set_missing_values()
+			doc.append('items', pricing_rule_args)
 
 def get_pricing_rule_items(pr_doc):
 	apply_on_data = []
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index d7e64cf..643de7d 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -382,21 +382,11 @@
 
 cur_frm.fields_dict['credit_to'].get_query = function(doc) {
 	// filter on Account
-	if (doc.supplier) {
-		return {
-			filters: {
-				'account_type': 'Payable',
-				'is_group': 0,
-				'company': doc.company
-			}
-		}
-	} else {
-		return {
-			filters: {
-				'report_type': 'Balance Sheet',
-				'is_group': 0,
-				'company': doc.company
-			}
+	return {
+		filters: {
+			'account_type': 'Payable',
+			'is_group': 0,
+			'company': doc.company
 		}
 	}
 }
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 7f4ae3c..db6ac55 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -556,22 +556,11 @@
 }
 
 cur_frm.set_query("debit_to", function(doc) {
-	// filter on Account
-	if (doc.customer) {
-		return {
-			filters: {
-				'account_type': 'Receivable',
-				'is_group': 0,
-				'company': doc.company
-			}
-		}
-	} else {
-		return {
-			filters: {
-				'report_type': 'Balance Sheet',
-				'is_group': 0,
-				'company': doc.company
-			}
+	return {
+		filters: {
+			'account_type': 'Receivable',
+			'is_group': 0,
+			'company': doc.company
 		}
 	}
 });
diff --git a/erpnext/accounts/doctype/share_transfer/share_transfer.json b/erpnext/accounts/doctype/share_transfer/share_transfer.json
index f17bf04..59a3053 100644
--- a/erpnext/accounts/doctype/share_transfer/share_transfer.json
+++ b/erpnext/accounts/doctype/share_transfer/share_transfer.json
@@ -188,7 +188,7 @@
   }
  ],
  "is_submittable": 1,
- "modified": "2019-11-07 13:31:17.999744",
+ "modified": "2019-12-20 14:48:01.990600",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Share Transfer",
@@ -196,6 +196,7 @@
  "permissions": [
   {
    "amend": 1,
+   "cancel": 1,
    "create": 1,
    "delete": 1,
    "email": 1,
@@ -221,6 +222,7 @@
    "write": 1
   },
   {
+   "cancel": 1,
    "create": 1,
    "delete": 1,
    "email": 1,
@@ -230,6 +232,7 @@
    "report": 1,
    "role": "Accounts Manager",
    "share": 1,
+   "submit": 1,
    "write": 1
   }
  ],
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index feb598a..bb1b7e3 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -90,8 +90,12 @@
 		else:
 			merged_gl_map.append(entry)
 
+	company = gl_map[0].company if gl_map else erpnext.get_default_company()
+	company_currency = erpnext.get_company_currency(company)
+	precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"), company_currency)
+
 	# filter zero debit and credit entries
-	merged_gl_map = filter(lambda x: flt(x.debit, 9)!=0 or flt(x.credit, 9)!=0, merged_gl_map)
+	merged_gl_map = filter(lambda x: flt(x.debit, precision)!=0 or flt(x.credit, precision)!=0, merged_gl_map)
 	merged_gl_map = list(merged_gl_map)
 
 	return merged_gl_map
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 2c53f6e..f82146a 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -171,7 +171,7 @@
 			row.outstanding = flt(row.invoiced - row.paid - row.credit_note, self.currency_precision)
 			row.invoice_grand_total = row.invoiced
 
-			if abs(row.outstanding) > 0.1/10 ** self.currency_precision:
+			if abs(row.outstanding) > 1.0/10 ** self.currency_precision:
 				# non-zero oustanding, we must consider this row
 
 				if self.is_invoice(row) and self.filters.based_on_payment_terms:
@@ -285,7 +285,7 @@
 
 	def set_party_details(self, row):
 		# customer / supplier name
-		party_details = self.get_party_details(row.party)
+		party_details = self.get_party_details(row.party) or {}
 		row.update(party_details)
 		if self.filters.get(scrub(self.filters.party_type)):
 			row.currency = row.account_currency
diff --git a/erpnext/accounts/report/financial_statements.html b/erpnext/accounts/report/financial_statements.html
index 4081723..50947ec 100644
--- a/erpnext/accounts/report/financial_statements.html
+++ b/erpnext/accounts/report/financial_statements.html
@@ -1,5 +1,6 @@
 {%
 	var report_columns = report.get_columns_for_print();
+	report_columns = report_columns.filter(col => !col.hidden);
 
 	if (report_columns.length > 8) {
 		frappe.throw(__("Too many columns. Export the report and print it using a spreadsheet application."));
@@ -15,34 +16,35 @@
 		height: 37px;
 	}
 </style>
-{% var letterhead= filters.letter_head || (frappe.get_doc(":Company", filters.company) && frappe.get_doc(":Company", filters.company).default_letter_head) %}
-{% if(letterhead) { %}
-<div style="margin-bottom: 7px;" class="text-center">
-	{%= frappe.boot.letter_heads[letterhead].header %}
-</div>
-{% } %}
+
 <h2 class="text-center">{%= __(report.report_name) %}</h2>
 <h3 class="text-center">{%= filters.company %}</h3>
+
 {% if 'cost_center' in filters %}
 	<h3 class="text-center">{%= filters.cost_center %}</h3>
 {% endif %}
+
 <h3 class="text-center">{%= filters.fiscal_year %}</h3>
-<h5 class="text-center">{%=  __("Currency") %} : {%= filters.presentation_currency || erpnext.get_currency(filters.company) %} </h4>
+<h5 class="text-center">
+	{%=  __("Currency") %} : {%= filters.presentation_currency || erpnext.get_currency(filters.company) %}
+</h5>
 {% if (filters.from_date) { %}
-	<h4 class="text-center">{%= frappe.datetime.str_to_user(filters.from_date) %} - {%= frappe.datetime.str_to_user(filters.to_date) %}</h3>
+	<h5 class="text-center">
+		{%= frappe.datetime.str_to_user(filters.from_date) %} - {%= frappe.datetime.str_to_user(filters.to_date) %}
+	</h5>
 {% } %}
 <hr>
 <table class="table table-bordered">
 	<thead>
 		<tr>
-			<th style="width: {%= 100 - (report_columns.length - 2) * 13 %}%"></th>
-			{% for(var i=2, l=report_columns.length; i<l; i++) { %}
+			<th style="width: {%= 100 - (report_columns.length - 1) * 13 %}%"></th>
+			{% for (let i=1, l=report_columns.length; i<l; i++) { %}
 				<th class="text-right">{%= report_columns[i].label %}</th>
 			{% } %}
 		</tr>
 	</thead>
 	<tbody>
-		{% for(var j=0, k=data.length-1; j<k; j++) { %}
+		{% for(let j=0, k=data.length-1; j<k; j++) { %}
 			{%
 				var row = data[j];
 				var row_class = data[j].parent_account ? "" : "financial-statements-important";
@@ -52,11 +54,11 @@
 				<td>
 					<span style="padding-left: {%= cint(data[j].indent) * 2 %}em">{%= row.account_name %}</span>
 				</td>
-				{% for(var i=2, l=report_columns.length; i<l; i++) { %}
+				{% for(let i=1, l=report_columns.length; i<l; i++) { %}
 					<td class="text-right">
-						{% var fieldname = report_columns[i].fieldname; %}
+						{% const fieldname = report_columns[i].fieldname; %}
 						{% if (!is_null(row[fieldname])) { %}
-							{%= format_currency(row[fieldname], filters.presentation_currency) %}
+							{%= frappe.format(row[fieldname], report_columns[i], {}, row) %}
 						{% } %}
 					</td>
 				{% } %}
@@ -64,4 +66,6 @@
 		{% } %}
 	</tbody>
 </table>
-<p class="text-right text-muted">Printed On {%= frappe.datetime.str_to_user(frappe.datetime.get_datetime_as_string()) %}</p>
+<p class="text-right text-muted">
+	Printed On {%= frappe.datetime.str_to_user(frappe.datetime.get_datetime_as_string()) %}
+</p>
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index 3c8de60..40d5682 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -264,8 +264,8 @@
 
 def add_total_row(out, root_type, balance_must_be, period_list, company_currency):
 	total_row = {
-		"account_name": "'" + _("Total {0} ({1})").format(_(root_type), _(balance_must_be)) + "'",
-		"account": "'" + _("Total {0} ({1})").format(_(root_type), _(balance_must_be)) + "'",
+		"account_name": _("Total {0} ({1})").format(_(root_type), _(balance_must_be)),
+		"account": _("Total {0} ({1})").format(_(root_type), _(balance_must_be)),
 		"currency": company_currency
 	}
 
diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py
index 0e2821a..afdd31d 100644
--- a/erpnext/accounts/report/sales_register/sales_register.py
+++ b/erpnext/accounts/report/sales_register/sales_register.py
@@ -38,32 +38,46 @@
 		cost_center = list(set(invoice_cc_wh_map.get(inv.name, {}).get("cost_center", [])))
 		warehouse = list(set(invoice_cc_wh_map.get(inv.name, {}).get("warehouse", [])))
 
-		row = [
-			inv.name, inv.posting_date, inv.customer, inv.customer_name
-		]
+		row = {
+			'invoice': inv.name,
+			'posting_date': inv.posting_date,
+			'customer': inv.customer,
+			'customer_name': inv.customer_name
+		}
 
 		if additional_query_columns:
 			for col in additional_query_columns:
-				row.append(inv.get(col))
+				row.update({
+					col: inv.get(col)
+				})
 
-		row +=[
-			inv.get("customer_group"),
-			inv.get("territory"),
-			inv.get("tax_id"),
-			inv.debit_to, ", ".join(mode_of_payments.get(inv.name, [])),
-			inv.project, inv.owner, inv.remarks,
-			", ".join(sales_order), ", ".join(delivery_note),", ".join(cost_center),
-			", ".join(warehouse), company_currency
-		]
+		row.update({
+			'customer_group': inv.get("customer_group"),
+			'territory': inv.get("territory"),
+			'tax_id': inv.get("tax_id"),
+			'receivable_account': inv.debit_to,
+			'mode_of_payment':  ", ".join(mode_of_payments.get(inv.name, [])),
+			'project': inv.project,
+			'owner': inv.owner,
+			'remarks': inv.remarks,
+			'sales_order': ", ".join(sales_order),
+			'delivery_note': ", ".join(delivery_note),
+			'cost_center': ", ".join(cost_center),
+			'warehouse': ", ".join(warehouse),
+			'currency': company_currency
+		})
+
 		# map income values
 		base_net_total = 0
 		for income_acc in income_accounts:
 			income_amount = flt(invoice_income_map.get(inv.name, {}).get(income_acc))
 			base_net_total += income_amount
-			row.append(income_amount)
+			row.update({
+				frappe.scrub(income_acc): income_amount
+			})
 
 		# net total
-		row.append(base_net_total or inv.base_net_total)
+		row.update({'net_total': base_net_total or inv.base_net_total})
 
 		# tax account
 		total_tax = 0
@@ -72,10 +86,18 @@
 				tax_amount_precision = get_field_precision(frappe.get_meta("Sales Taxes and Charges").get_field("tax_amount"), currency=company_currency) or 2
 				tax_amount = flt(invoice_tax_map.get(inv.name, {}).get(tax_acc), tax_amount_precision)
 				total_tax += tax_amount
-				row.append(tax_amount)
+				row.update({
+					frappe.scrub(tax_acc): tax_amount
+				})
 
 		# total tax, grand total, outstanding amount & rounded total
-		row += [total_tax, inv.base_grand_total, inv.base_rounded_total, inv.outstanding_amount]
+
+		row.update({
+			'tax_total': total_tax,
+			'grand_total': inv.base_grand_total,
+			'rounded_total': inv.base_rounded_total,
+			'outstanding_amount': inv.outstanding_amount
+		})
 
 		data.append(row)
 
@@ -84,19 +106,118 @@
 def get_columns(invoice_list, additional_table_columns):
 	"""return columns based on filters"""
 	columns = [
-		_("Invoice") + ":Link/Sales Invoice:120", _("Posting Date") + ":Date:80",
-		_("Customer") + ":Link/Customer:120", _("Customer Name") + "::120"
+		{
+			'label': _("Invoice"),
+			'fieldname': 'invoice',
+			'fieldtype': 'Link',
+			'options': 'Sales Invoice',
+			'width': 120
+		},
+		{
+			'label': _("Posting Date"),
+			'fieldname': 'posting_date',
+			'fieldtype': 'Date',
+			'width': 80
+		},
+		{
+			'label': _("Customer"),
+			'fieldname': 'customer',
+			'fieldtype': 'Link',
+			'options': 'Customer',
+			'width': 120
+		},
+		{
+			'label': _("Customer Name"),
+			'fieldname': 'customer_name',
+			'fieldtype': 'Data',
+			'width': 120
+		},
 	]
 
 	if additional_table_columns:
 		columns += additional_table_columns
 
 	columns +=[
-		_("Customer Group") + ":Link/Customer Group:120", _("Territory") + ":Link/Territory:80",
-		_("Tax Id") + "::80", _("Receivable Account") + ":Link/Account:120", _("Mode of Payment") + "::120",
-		_("Project") +":Link/Project:80", _("Owner") + "::150", _("Remarks") + "::150",
-		_("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100",
-		_("Cost Center") + ":Link/Cost Center:100", _("Warehouse") + ":Link/Warehouse:100",
+		{
+			'label': _("Custmer Group"),
+			'fieldname': 'customer_group',
+			'fieldtype': 'Link',
+			'options': 'Customer Group',
+			'width': 120
+		},
+		{
+			'label': _("Territory"),
+			'fieldname': 'territory',
+			'fieldtype': 'Link',
+			'options': 'Territory',
+			'width': 80
+		},
+		{
+			'label': _("Tax Id"),
+			'fieldname': 'tax_id',
+			'fieldtype': 'Data',
+			'width': 120
+		},
+		{
+			'label': _("Receivable Account"),
+			'fieldname': 'receivable_account',
+			'fieldtype': 'Link',
+			'options': 'Account',
+			'width': 80
+		},
+		{
+			'label': _("Mode Of Payment"),
+			'fieldname': 'mode_of_payment',
+			'fieldtype': 'Data',
+			'width': 120
+		},
+		{
+			'label': _("Project"),
+			'fieldname': 'project',
+			'fieldtype': 'Link',
+			'options': 'project',
+			'width': 80
+		},
+		{
+			'label': _("Owner"),
+			'fieldname': 'owner',
+			'fieldtype': 'Data',
+			'width': 150
+		},
+		{
+			'label': _("Remarks"),
+			'fieldname': 'remarks',
+			'fieldtype': 'Data',
+			'width': 150
+		},
+		{
+			'label': _("Sales Order"),
+			'fieldname': 'sales_order',
+			'fieldtype': 'Link',
+			'options': 'Sales Order',
+			'width': 100
+		},
+		{
+			'label': _("Delivery Note"),
+			'fieldname': 'delivery_note',
+			'fieldtype': 'Link',
+			'options': 'Delivery Note',
+			'width': 100
+		},
+		{
+			'label': _("Cost Center"),
+			'fieldname': 'cost_center',
+			'fieldtype': 'Link',
+			'options': 'Cost Center',
+			'width': 100
+		},
+		{
+			'label': _("Warehouse"),
+			'fieldname': 'warehouse',
+			'fieldtype': 'Link',
+			'options': 'Warehouse',
+			'width': 100
+		},
 		{
 			"fieldname": "currency",
 			"label": _("Currency"),
@@ -105,7 +226,10 @@
 		}
 	]
 
-	income_accounts = tax_accounts = income_columns = tax_columns = []
+	income_accounts = []
+	tax_accounts = []
+	income_columns = []
+	tax_columns = []
 
 	if invoice_list:
 		income_accounts = frappe.db.sql_list("""select distinct income_account
@@ -119,14 +243,65 @@
 			and parent in (%s) order by account_head""" %
 			', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
 
-	income_columns = [(account + ":Currency/currency:120") for account in income_accounts]
+	for account in income_accounts:
+		income_columns.append({
+			"label": account,
+			"fieldname": frappe.scrub(account),
+			"fieldtype": "Currency",
+			"options": 'currency',
+			"width": 120
+		})
+
 	for account in tax_accounts:
 		if account not in income_accounts:
-			tax_columns.append(account + ":Currency/currency:120")
+			tax_columns.append({
+				"label": account,
+				"fieldname": frappe.scrub(account),
+				"fieldtype": "Currency",
+				"options": 'currency',
+				"width": 120
+			})
 
-	columns = columns + income_columns + [_("Net Total") + ":Currency/currency:120"] + tax_columns + \
-		[_("Total Tax") + ":Currency/currency:120", _("Grand Total") + ":Currency/currency:120",
-		_("Rounded Total") + ":Currency/currency:120", _("Outstanding Amount") + ":Currency/currency:120"]
+	net_total_column = [{
+		"label": _("Net Total"),
+		"fieldname": "net_total",
+		"fieldtype": "Currency",
+		"options": 'currency',
+		"width": 120
+	}]
+
+	total_columns = [
+		{
+			"label": _("Tax Total"),
+			"fieldname": "tax_total",
+			"fieldtype": "Currency",
+			"options": 'currency',
+			"width": 120
+		},
+		{
+			"label": _("Grand Total"),
+			"fieldname": "grand_total",
+			"fieldtype": "Currency",
+			"options": 'currency',
+			"width": 120
+		},
+		{
+			"label": _("Rounded Total"),
+			"fieldname": "rounded_total",
+			"fieldtype": "Currency",
+			"options": 'currency',
+			"width": 120
+		},
+		{
+			"label": _("Outstanding Amount"),
+			"fieldname": "outstanding_amount",
+			"fieldtype": "Currency",
+			"options": 'currency',
+			"width": 120
+		}
+	]
+
+	columns = columns + income_columns + net_total_column + tax_columns + total_columns
 
 	return columns, income_accounts, tax_accounts
 
diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py
index 4e1822b..3a08baa 100644
--- a/erpnext/assets/doctype/asset_movement/asset_movement.py
+++ b/erpnext/assets/doctype/asset_movement/asset_movement.py
@@ -110,7 +110,7 @@
 				ORDER BY
 					asm.transaction_date asc
 				""", (d.asset, self.company, 'Receipt'), as_dict=1)
-			if auto_gen_movement_entry[0].get('name') == self.name:
+			if auto_gen_movement_entry and auto_gen_movement_entry[0].get('name') == self.name:
 				frappe.throw(_('{0} will be cancelled automatically on asset cancellation as it was \
 					auto generated for Asset {1}').format(self.name, d.asset))
 
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 5dce349..8cd44c7 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -1,4 +1,5 @@
 {
+ "actions": [],
  "allow_import": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-21 16:16:39",
@@ -47,6 +48,7 @@
   "ignore_pricing_rule",
   "sec_warehouse",
   "set_warehouse",
+  "set_reserve_warehouse",
   "col_break_warehouse",
   "is_subcontracted",
   "supplier_warehouse",
@@ -1039,12 +1041,20 @@
    "fieldtype": "Link",
    "label": "Tax Category",
    "options": "Tax Category"
+  },
+  {
+   "depends_on": "supplied_items",
+   "fieldname": "set_reserve_warehouse",
+   "fieldtype": "Link",
+   "label": "Set Reserve Warehouse",
+   "options": "Warehouse"
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 105,
  "is_submittable": 1,
- "modified": "2019-07-11 18:25:49.509343",
+ "links": [],
+ "modified": "2019-12-18 13:13:22.852412",
  "modified_by": "Administrator",
  "module": "Buying",
  "name": "Purchase Order",
diff --git a/erpnext/buying/onboarding_slide/add_a_few_suppliers/add_a_few_suppliers.json b/erpnext/buying/onboarding_slide/add_a_few_suppliers/add_a_few_suppliers.json
index d3adcb7..ce3d8cf 100644
--- a/erpnext/buying/onboarding_slide/add_a_few_suppliers/add_a_few_suppliers.json
+++ b/erpnext/buying/onboarding_slide/add_a_few_suppliers/add_a_few_suppliers.json
@@ -12,9 +12,10 @@
   }
  ],
  "idx": 0,
- "image_src": "/assets/erpnext/images/illustrations/supplier-onboard.png",
+ "image_src": "",
+ "is_completed": 0,
  "max_count": 3,
- "modified": "2019-12-03 22:53:50.552445",
+ "modified": "2019-12-09 17:54:18.452038",
  "modified_by": "Administrator",
  "name": "Add A Few Suppliers",
  "owner": "Administrator",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 75564af..6150516 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -319,8 +319,8 @@
 					if item.get('discount_amount'):
 						item.rate = item.price_list_rate - item.discount_amount
 
-			elif pricing_rule_args.get('free_item'):
-				apply_pricing_rule_for_free_items(self, pricing_rule_args)
+			elif pricing_rule_args.get('free_item_data'):
+				apply_pricing_rule_for_free_items(self, pricing_rule_args.get('free_item_data'))
 
 		elif pricing_rule_args.get("validate_applied_rule"):
 			for pricing_rule in get_applied_pricing_rules(item):
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 3ec7aff..75b896b 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -265,16 +265,17 @@
 
 			fg_yet_to_be_received = qty_to_be_received_map.get(item_key)
 
-			raw_material_data = backflushed_raw_materials_map.get(item_key, {})
-
-			consumed_qty = raw_material_data.get('qty', 0)
-			consumed_serial_nos = raw_material_data.get('serial_nos', '')
-			consumed_batch_nos = raw_material_data.get('batch_nos', '')
-
 			transferred_batch_qty_map = get_transferred_batch_qty_map(item.purchase_order, item.item_code)
 			backflushed_batch_qty_map = get_backflushed_batch_qty_map(item.purchase_order, item.item_code)
 
 			for raw_material in transferred_raw_materials + non_stock_items:
+				rm_item_key = '{}{}'.format(raw_material.rm_item_code, item.purchase_order)
+				raw_material_data = backflushed_raw_materials_map.get(rm_item_key, {})
+
+				consumed_qty = raw_material_data.get('qty', 0)
+				consumed_serial_nos = raw_material_data.get('serial_nos', '')
+				consumed_batch_nos = raw_material_data.get('batch_nos', '')
+
 				transferred_qty = raw_material.qty
 
 				rm_qty_to_be_consumed = transferred_qty - consumed_qty
diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py
index b6c4c47..f502930 100644
--- a/erpnext/crm/doctype/appointment/appointment.py
+++ b/erpnext/crm/doctype/appointment/appointment.py
@@ -11,7 +11,7 @@
 import frappe
 from frappe import _
 from frappe.model.document import Document
-from frappe.utils import get_url
+from frappe.utils import get_url, getdate
 from frappe.utils.verified_command import verify_request, get_signed_params
 
 
@@ -117,7 +117,7 @@
 		if self._assign:
 			return
 		available_agents = _get_agents_sorted_by_asc_workload(
-			self.scheduled_time.date())
+			getdate(self.scheduled_time))
 		for agent in available_agents:
 			if(_check_agent_availability(agent, self.scheduled_time)):
 				agent = agent[0]
@@ -189,7 +189,7 @@
 		assigned_to = frappe.parse_json(appointment._assign)
 		if not assigned_to:
 			continue
-		if (assigned_to[0] in agent_list) and appointment.scheduled_time.date() == date:
+		if (assigned_to[0] in agent_list) and getdate(appointment.scheduled_time) == date:
 			appointment_counter[assigned_to[0]] += 1
 	sorted_agent_list = appointment_counter.most_common()
 	sorted_agent_list.reverse()
diff --git a/erpnext/education/doctype/student/student.js b/erpnext/education/doctype/student/student.js
index b6e741c..1936dcb 100644
--- a/erpnext/education/doctype/student/student.js
+++ b/erpnext/education/doctype/student/student.js
@@ -31,7 +31,7 @@
 frappe.ui.form.on('Student Guardian', {
 	guardians_add: function(frm){
 		frm.fields_dict['guardians'].grid.get_field('guardian').get_query = function(doc){
-			var guardian_list = [];
+			let guardian_list = [];
 			if(!doc.__islocal) guardian_list.push(doc.guardian);
 			$.each(doc.guardians, function(idx, val){
 				if (val.guardian) guardian_list.push(val.guardian);
@@ -40,3 +40,18 @@
 		};
 	}
 });
+
+
+frappe.ui.form.on('Student Sibling', {
+	siblings_add: function(frm){
+		frm.fields_dict['siblings'].grid.get_field('student').get_query = function(doc){
+			let sibling_list = [frm.doc.name];
+			$.each(doc.siblings, function(idx, val){
+				if (val.student && val.studying_in_same_institute == 'YES') {
+					sibling_list.push(val.student);
+				}
+			});
+			return { filters: [['Student', 'name', 'not in', sibling_list]] };
+		};
+	}
+});
\ No newline at end of file
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 2a5e6d8..c99ae7d 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -180,6 +180,7 @@
 	{"title": _("Admission"), "route": "/admissions", "reference_doctype": "Student Admission", "role": "Student"},
 	{"title": _("Certification"), "route": "/certification", "reference_doctype": "Certification Application", "role": "Non Profit Portal User"},
 	{"title": _("Material Request"), "route": "/material-requests", "reference_doctype": "Material Request", "role": "Customer"},
+	{"title": _("Appointment Booking"), "route": "/book_appointment"},
 ]
 
 default_roles = [
diff --git a/erpnext/hr/doctype/employee/employee.json b/erpnext/hr/doctype/employee/employee.json
index 9291820..a45b41d 100644
--- a/erpnext/hr/doctype/employee/employee.json
+++ b/erpnext/hr/doctype/employee/employee.json
@@ -232,7 +232,6 @@
    "reqd": 1
   },
   {
-   "description": "You can enter any date manually",
    "fieldname": "date_of_birth",
    "fieldtype": "Date",
    "label": "Date of Birth",
@@ -831,4 +830,4 @@
  "sort_order": "DESC",
  "title_field": "employee_name",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.js b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.js
index 996dcdf..c128567 100644
--- a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.js
+++ b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.js
@@ -7,6 +7,14 @@
 		frm.add_fetch("employee_onboarding_template", "department", "department");
 		frm.add_fetch("employee_onboarding_template", "designation", "designation");
 		frm.add_fetch("employee_onboarding_template", "employee_grade", "employee_grade");
+
+		frm.set_query('job_offer', function () {
+			return {
+				filters: {
+					'job_applicant': frm.doc.job_applicant
+				}
+			};
+		});
 	},
 
 	refresh: function(frm) {
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py
index 9aeb7e8..e01e7a4 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.py
@@ -43,9 +43,9 @@
 		}[cstr(self.docstatus or 0)]
 
 		paid_amount = flt(self.total_amount_reimbursed) + flt(self.total_advance_amount)
-		precision = self.precision("total_sanctioned_amount")
+		precision = self.precision("grand_total")
 		if (self.is_paid or (flt(self.total_sanctioned_amount) > 0
-			and flt(self.total_sanctioned_amount, precision) ==  flt(paid_amount, precision))) \
+			and flt(self.grand_total, precision) ==  flt(paid_amount, precision))) \
 			and self.docstatus == 1 and self.approval_status == 'Approved':
 				self.status = "Paid"
 		elif flt(self.total_sanctioned_amount) > 0 and self.docstatus == 1 and self.approval_status == 'Approved':
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 915cea1..5222712 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -54,9 +54,11 @@
 		self.create_leave_ledger_entry()
 		self.reload()
 
+	def before_cancel(self):
+		self.status = "Cancelled"
+
 	def on_cancel(self):
 		self.create_leave_ledger_entry(submit=False)
-		self.status = "Cancelled"
 		# notify leave applier about cancellation
 		self.notify_employee()
 		self.cancel_attendance()
diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.py b/erpnext/hr/doctype/payroll_entry/payroll_entry.py
index 2de01e6..dfd38eb 100644
--- a/erpnext/hr/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.py
@@ -163,7 +163,7 @@
 		"""
 		cond = self.get_filter_condition()
 		return frappe.db.sql(""" select eld.loan_account, eld.loan,
-				eld.interest_income_account, eld.principal_amount, eld.interest_amount, eld.total_payment
+				eld.interest_income_account, eld.principal_amount, eld.interest_amount, eld.total_payment,t1.employee
 			from
 				`tabSalary Slip` t1, `tabSalary Slip Loan` eld
 			where
@@ -246,6 +246,7 @@
 				accounts.append({
 						"account": acc,
 						"debit_in_account_currency": flt(amount, precision),
+						"party_type": '',
 						"cost_center": self.cost_center,
 						"project": self.project
 					})
@@ -257,6 +258,7 @@
 						"account": acc,
 						"credit_in_account_currency": flt(amount, precision),
 						"cost_center": self.cost_center,
+						"party_type": '',
 						"project": self.project
 					})
 
@@ -264,7 +266,9 @@
 			for data in loan_details:
 				accounts.append({
 						"account": data.loan_account,
-						"credit_in_account_currency": data.principal_amount
+						"credit_in_account_currency": data.principal_amount,
+						"party_type": "Employee",
+						"party": data.employee
 					})
 
 				if data.interest_amount and not data.interest_income_account:
@@ -275,14 +279,17 @@
 						"account": data.interest_income_account,
 						"credit_in_account_currency": data.interest_amount,
 						"cost_center": self.cost_center,
-						"project": self.project
+						"project": self.project,
+						"party_type": "Employee",
+						"party": data.employee
 					})
 				payable_amount -= flt(data.total_payment, precision)
 
 			# Payable amount
 			accounts.append({
 				"account": default_payroll_payable_account,
-				"credit_in_account_currency": flt(payable_amount, precision)
+				"credit_in_account_currency": flt(payable_amount, precision),
+				"party_type": '',
 			})
 
 			journal_entry.set("accounts", accounts)
@@ -546,7 +553,6 @@
 		count += 1
 		if publish_progress:
 			frappe.publish_progress(count*100/len(salary_slips), title = _("Submitting Salary Slips..."))
-
 	if submitted_ss:
 		payroll_entry.make_accrual_jv_entry()
 		frappe.msgprint(_("Salary Slip submitted for period from {0} to {1}")
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js
index dd34ef2..9f42c91 100755
--- a/erpnext/hr/doctype/salary_structure/salary_structure.js
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.js
@@ -46,7 +46,7 @@
 		frm.trigger("toggle_fields");
 		frm.fields_dict['earnings'].grid.set_column_disp("default_amount", false);
 		frm.fields_dict['deductions'].grid.set_column_disp("default_amount", false);
-		
+
 		if(frm.doc.docstatus === 1) {
 			frm.add_custom_button(__("Preview Salary Slip"), function() {
 				frm.trigger('preview_salary_slip');
@@ -119,47 +119,52 @@
 			},
 			callback: function(r) {
 				var employees = r.message;
-				var d = new frappe.ui.Dialog({
-					title: __("Preview Salary Slip"),
-					fields: [
-						{
-							"label":__("Employee"),
-							"fieldname":"employee",
-							"fieldtype":"Select",
-							"reqd": true,
-							options: employees
-						}, {
-							fieldname:"fetch",
-							"label":__("Show Salary Slip"),
-							"fieldtype":"Button"
-						}
-					]
-				});
-				d.get_input("fetch").on("click", function() {
-					var values = d.get_values();
-					if(!values) return;
-					var print_format;
-					frm.doc.salary_slip_based_on_timesheet ?
-						print_format="Salary Slip based on Timesheet" :
-						print_format="Salary Slip Standard";
-
-					frappe.call({
-						method: "erpnext.hr.doctype.salary_structure.salary_structure.make_salary_slip",
-						args: {
-							source_name: frm.doc.name,
-							employee: values.employee,
-							as_print: 1,
-							print_format: print_format,
-							for_preview: 1
-						},
-						callback: function(r) {
-							var new_window = window.open();
-							new_window.document.write(r.message);
-							// frappe.msgprint(r.message);
-						}
+				if(!employees) return;
+				if (employees.length == 1){
+					frm.events.open_salary_slip(frm, employees[0]);
+				} else {
+						var d = new frappe.ui.Dialog({
+						title: __("Preview Salary Slip"),
+						fields: [
+							{
+								"label":__("Employee"),
+								"fieldname":"employee",
+								"fieldtype":"Select",
+								"reqd": true,
+								options: employees
+							}, {
+								fieldname:"fetch",
+								"label":__("Show Salary Slip"),
+								"fieldtype":"Button"
+							}
+						]
 					});
-				});
-				d.show();
+					d.get_input("fetch").on("click", function() {
+						var values = d.get_values();
+						if(!values) return;
+							frm.events.open_salary_slip(frm, values.employee)
+
+					});
+					d.show();
+				}
+			}
+		});
+	},
+
+	open_salary_slip: function(frm, employee){
+		var print_format = frm.doc.salary_slip_based_on_timesheet ? "Salary Slip based on Timesheet" : "Salary Slip Standard";
+		frappe.call({
+			method: "erpnext.hr.doctype.salary_structure.salary_structure.make_salary_slip",
+			args: {
+				source_name: frm.doc.name,
+				employee: employee,
+				as_print: 1,
+				print_format: print_format,
+				for_preview: 1
+			},
+			callback: function(r) {
+				var new_window = window.open();
+				new_window.document.write(r.message);
 			}
 		});
 	},
diff --git a/erpnext/hr/notification/training_scheduled/training_scheduled.html b/erpnext/hr/notification/training_scheduled/training_scheduled.html
index b1aeb2c..374038a 100644
--- a/erpnext/hr/notification/training_scheduled/training_scheduled.html
+++ b/erpnext/hr/notification/training_scheduled/training_scheduled.html
@@ -1,9 +1,44 @@
-<h3>{{_("Training Event")}}</h3>
+<table class="panel-header" border="0" cellpadding="0" cellspacing="0" width="100%">
+    <tr height="10"></tr>
+    <tr>
+        <td width="15"></td>
+        <td>
+            <div class="text-medium text-muted">
+                <span>{{_("Training Event:")}} {{ doc.event_name }}</span>
+            </div>
+        </td>
+        <td width="15"></td>
+    </tr>
+    <tr height="10"></tr>
+</table>
 
-<p>{{ doc.introduction }}</p>
-
-<h4>{{_("Details")}}</h4>
-{{_("Event Name")}}: {{ frappe.utils.get_link_to_form(doc.doctype, doc.name) }}
-<br>{{_("Event Location")}}: {{ doc.location }}
-<br>{{_("Start Time")}}: {{ doc.start_time }}
-<br>{{_("End Time")}}: {{ doc.end_time }}
+<table class="panel-body" border="0" cellpadding="0" cellspacing="0" width="100%">
+    <tr height="10"></tr>
+    <tr>
+        <td width="15"></td>
+        <td>
+            <div>
+                {{ doc.introduction }}
+                <ul class="list-unstyled" style="line-height: 1.7">
+                    <li>{{_("Event Location")}}: <b>{{ doc.location }}</b></li>
+                    {% set start = frappe.utils.get_datetime(doc.start_time) %}
+                    {% set end = frappe.utils.get_datetime(doc.end_time) %}
+                    {% if start.date() == end.date() %}
+                    <li>{{_("Date")}}: <b>{{ start.strftime("%A, %d %b %Y") }}</b></li>
+                    <li>
+                        {{_("Timing")}}: <b>{{ start.strftime("%I:%M %p") + ' to ' + end.strftime("%I:%M %p") }}</b>
+                    </li>
+                    {% else %}
+                    <li>{{_("Start Time")}}: <b>{{ start.strftime("%A, %d %b %Y at %I:%M %p") }}</b>
+                    </li>
+                    <li>{{_("End Time")}}: <b>{{ end.strftime("%A, %d %b %Y at %I:%M %p") }}</b>
+                    </li>
+                    {% endif %}
+                    <li>{{ _('Event Link') }}: {{ frappe.utils.get_link_to_form(doc.doctype, doc.name) }}</li>
+                </ul>
+            </div>
+        </td>
+        <td width="15"></td>
+    </tr>
+    <tr height="10"></tr>
+</table>
\ No newline at end of file
diff --git a/erpnext/hr/notification/training_scheduled/training_scheduled.json b/erpnext/hr/notification/training_scheduled/training_scheduled.json
index c07e1a6..966b887 100644
--- a/erpnext/hr/notification/training_scheduled/training_scheduled.json
+++ b/erpnext/hr/notification/training_scheduled/training_scheduled.json
@@ -1,5 +1,7 @@
 {
  "attach_print": 0,
+ "channel": "Email",
+ "condition": "",
  "creation": "2017-08-11 03:13:40.519614",
  "days_in_advance": 0,
  "docstatus": 0,
@@ -9,8 +11,8 @@
  "event": "Submit",
  "idx": 0,
  "is_standard": 1,
- "message": "<h3>{{_(\"Training Event\")}}</h3>\n\n<p>{{ doc.introduction }}</p>\n\n<h4>{{_(\"Details\")}}</h4>\n{{_(\"Event Name\")}}: {{ frappe.utils.get_link_to_form(doc.doctype, doc.name) }}\n<br>{{_(\"Event Location\")}}: {{ doc.location }}\n<br>{{_(\"Start Time\")}}: {{ doc.start_time }}\n<br>{{_(\"End Time\")}}: {{ doc.end_time }}\n",
- "modified": "2017-08-13 22:49:42.338881",
+ "message": "<table class=\"panel-header\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n    <tr height=\"10\"></tr>\n    <tr>\n        <td width=\"15\"></td>\n        <td>\n            <div class=\"text-medium text-muted\">\n                <span>{{_(\"Training Event:\")}} {{ doc.event_name }}</span>\n            </div>\n        </td>\n        <td width=\"15\"></td>\n    </tr>\n    <tr height=\"10\"></tr>\n</table>\n\n<table class=\"panel-body\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n    <tr height=\"10\"></tr>\n    <tr>\n        <td width=\"15\"></td>\n        <td>\n            <div>\n                <ul class=\"list-unstyled\" style=\"line-height: 1.7\">\n                    <li>{{ doc.introduction }}</li>\n                    <li>{{_(\"Event Location\")}}: <b>{{ doc.location }}</b></li>\n                    {% set start = frappe.utils.get_datetime(doc.start_time) %}\n                    {% set end = frappe.utils.get_datetime(doc.end_time) %}\n                    {% if start.date() == end.date() %}\n                    <li>{{_(\"Date\")}}: <b>{{ start.strftime(\"%A, %d %b %Y\") }}</b></li>\n                    <li>\n                        {{_(\"Timing\")}}: <b>{{ start.strftime(\"%I:%M %p\") + ' to ' + end.strftime(\"%I:%M %p\") }}</b>\n                    </li>\n                    {% else %}\n                    <li>{{_(\"Start Time\")}}: <b>{{ start.strftime(\"%A, %d %b %Y at %I:%M %p\") }}</b>\n                    </li>\n                    <li>{{_(\"End Time\")}}: <b>{{ end.strftime(\"%A, %d %b %Y at %I:%M %p\") }}</b>\n                    </li>\n                    {% endif %}\n                </ul>\n                {{ _('Event Link') }}: {{ frappe.utils.get_link_to_form(doc.doctype, doc.name) }}\n            </div>\n        </td>\n        <td width=\"15\"></td>\n    </tr>\n    <tr height=\"10\"></tr>\n</table>",
+ "modified": "2019-11-29 15:38:31.805409",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Training Scheduled",
diff --git a/erpnext/hr/notification/training_scheduled/training_scheduled.md b/erpnext/hr/notification/training_scheduled/training_scheduled.md
index bcadf7d..374038a 100644
--- a/erpnext/hr/notification/training_scheduled/training_scheduled.md
+++ b/erpnext/hr/notification/training_scheduled/training_scheduled.md
@@ -1,9 +1,44 @@
-<h3>{{_("Training Event")}}</h3>
-<p>{{ message }}</p>
+<table class="panel-header" border="0" cellpadding="0" cellspacing="0" width="100%">
+    <tr height="10"></tr>
+    <tr>
+        <td width="15"></td>
+        <td>
+            <div class="text-medium text-muted">
+                <span>{{_("Training Event:")}} {{ doc.event_name }}</span>
+            </div>
+        </td>
+        <td width="15"></td>
+    </tr>
+    <tr height="10"></tr>
+</table>
 
-<h4>{{_("Details")}}</h4>
-{{_("Event Name")}}: <a href="{{ event_link }}">{{ name }}</a>
-<br>{{_("Event Location")}}: {{ location }}
-<br>{{_("Start Time")}}: {{ start_time }}
-<br>{{_("End Time")}}: {{ end_time }}
-<br>{{_("Attendance")}}: {{ attendance }}
+<table class="panel-body" border="0" cellpadding="0" cellspacing="0" width="100%">
+    <tr height="10"></tr>
+    <tr>
+        <td width="15"></td>
+        <td>
+            <div>
+                {{ doc.introduction }}
+                <ul class="list-unstyled" style="line-height: 1.7">
+                    <li>{{_("Event Location")}}: <b>{{ doc.location }}</b></li>
+                    {% set start = frappe.utils.get_datetime(doc.start_time) %}
+                    {% set end = frappe.utils.get_datetime(doc.end_time) %}
+                    {% if start.date() == end.date() %}
+                    <li>{{_("Date")}}: <b>{{ start.strftime("%A, %d %b %Y") }}</b></li>
+                    <li>
+                        {{_("Timing")}}: <b>{{ start.strftime("%I:%M %p") + ' to ' + end.strftime("%I:%M %p") }}</b>
+                    </li>
+                    {% else %}
+                    <li>{{_("Start Time")}}: <b>{{ start.strftime("%A, %d %b %Y at %I:%M %p") }}</b>
+                    </li>
+                    <li>{{_("End Time")}}: <b>{{ end.strftime("%A, %d %b %Y at %I:%M %p") }}</b>
+                    </li>
+                    {% endif %}
+                    <li>{{ _('Event Link') }}: {{ frappe.utils.get_link_to_form(doc.doctype, doc.name) }}</li>
+                </ul>
+            </div>
+        </td>
+        <td width="15"></td>
+    </tr>
+    <tr height="10"></tr>
+</table>
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index e3ece56..f8146bb 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -65,6 +65,7 @@
 		context.parents = [{'name': 'boms', 'title': _('All BOMs') }]
 
 	def on_update(self):
+		frappe.cache().hdel('bom_children', self.name)
 		self.check_recursion()
 		self.update_stock_qty()
 		self.update_exploded_items()
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index 8ca8917..176ca2e 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -605,6 +605,8 @@
 				description: __('Max: {0}', [max]),
 				default: max
 			}, data => {
+				max += (max * (frm.doc.__onload.overproduction_percentage || 0.0)) / 100;
+
 				if (data.qty > max) {
 					frappe.msgprint(__('Quantity must not be more than {0}', [max]));
 					reject();
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index 227ef78..c4238ac 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -38,7 +38,7 @@
 		ms = frappe.get_doc("Manufacturing Settings")
 		self.set_onload("material_consumption", ms.material_consumption)
 		self.set_onload("backflush_raw_materials_based_on", ms.backflush_raw_materials_based_on)
-
+		self.set_onload("overproduction_percentage", ms.overproduction_percentage_for_work_order)
 
 	def validate(self):
 		self.validate_production_item()
@@ -657,8 +657,9 @@
 	wo_doc = frappe.new_doc("Work Order")
 	wo_doc.production_item = item
 	wo_doc.update(item_details)
-	if qty > 0:
-		wo_doc.qty = qty
+
+	if flt(qty) > 0:
+		wo_doc.qty = flt(qty)
 		wo_doc.get_items_and_operations_from_bom()
 
 	return wo_doc
diff --git a/erpnext/patches/v12_0/add_export_type_field_in_party_master.py b/erpnext/patches/v12_0/add_export_type_field_in_party_master.py
index c565b7e..5bb6e3f 100644
--- a/erpnext/patches/v12_0/add_export_type_field_in_party_master.py
+++ b/erpnext/patches/v12_0/add_export_type_field_in_party_master.py
@@ -27,6 +27,8 @@
 		tax_category = inter_state_category.name
 
 	for doctype in ('Sales Taxes and Charges Template', 'Purchase Taxes and Charges Template'):
+		if not frappe.get_meta(doctype).has_field('is_inter_state'): continue
+
 		template = frappe.db.get_value(doctype, {'is_inter_state': 1, 'disabled': 0}, ['name'])
 		if template:
 			frappe.db.set_value(doctype, template, 'tax_category', tax_category)
diff --git a/erpnext/portal/product_configurator/utils.py b/erpnext/portal/product_configurator/utils.py
index 3a373a4..0993e69 100644
--- a/erpnext/portal/product_configurator/utils.py
+++ b/erpnext/portal/product_configurator/utils.py
@@ -52,7 +52,6 @@
 
 
 def get_products_for_website(field_filters=None, attribute_filters=None, search=None):
-
 	if attribute_filters:
 		item_codes = get_item_codes_by_attributes(attribute_filters)
 		items_by_attributes = get_items([['name', 'in', item_codes]])
@@ -302,6 +301,8 @@
 	if isinstance(filters, dict):
 		filters = [['Item', fieldname, '=', value] for fieldname, value in filters.items()]
 
+	enabled_items_filter = get_conditions({ 'disabled': 0 }, 'and')
+
 	show_in_website_condition = ''
 	if products_settings.hide_variants:
 		show_in_website_condition = get_conditions({'show_in_website': 1 }, 'and')
@@ -337,7 +338,8 @@
 	filter_condition = get_conditions(filters, 'and')
 
 	where_conditions = ' and '.join(
-		[condition for condition in [show_in_website_condition, search_condition, filter_condition] if condition]
+		[condition for condition in [enabled_items_filter, show_in_website_condition, \
+			search_condition, filter_condition] if condition]
 	)
 
 	left_joins = []
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 7083d69..45f2681 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -47,11 +47,11 @@
 		if not self.project or frappe.flags.in_test:
 			return
 
-		expected_end_date = getdate(frappe.db.get_value("Project", self.project, "expected_end_date"))
+		expected_end_date = frappe.db.get_value("Project", self.project, "expected_end_date")
 
 		if expected_end_date:
-			validate_project_dates(expected_end_date, self, "exp_start_date", "exp_end_date", "Expected")
-			validate_project_dates(expected_end_date, self, "act_start_date", "act_end_date", "Actual")
+			validate_project_dates(getdate(expected_end_date), self, "exp_start_date", "exp_end_date", "Expected")
+			validate_project_dates(getdate(expected_end_date), self, "act_start_date", "act_end_date", "Actual")
 
 	def validate_status(self):
 		if self.status!=self.get_db_value("status") and self.status == "Completed":
@@ -278,4 +278,4 @@
 		frappe.throw(_("Task's {0} Start Date cannot be after Project's End Date.").format(actual_or_expected_date))
 
 	if task.get(task_end) and date_diff(project_end_date, getdate(task.get(task_end))) < 0:
-		frappe.throw(_("Task's {0} End Date cannot be after Project's End Date.").format(actual_or_expected_date))
\ No newline at end of file
+		frappe.throw(_("Task's {0} End Date cannot be after Project's End Date.").format(actual_or_expected_date))
diff --git a/erpnext/public/images/illustrations/customers-onboard.png b/erpnext/public/images/illustrations/customers-onboard.png
deleted file mode 100644
index 4a517bd..0000000
--- a/erpnext/public/images/illustrations/customers-onboard.png
+++ /dev/null
Binary files differ
diff --git a/erpnext/public/images/illustrations/desk-onboard.png b/erpnext/public/images/illustrations/desk-onboard.png
deleted file mode 100644
index 74b632d..0000000
--- a/erpnext/public/images/illustrations/desk-onboard.png
+++ /dev/null
Binary files differ
diff --git a/erpnext/public/images/illustrations/letterhead-onboard.png b/erpnext/public/images/illustrations/letterhead-onboard.png
deleted file mode 100644
index fdfd16a..0000000
--- a/erpnext/public/images/illustrations/letterhead-onboard.png
+++ /dev/null
Binary files differ
diff --git a/erpnext/public/images/illustrations/products-onboard.png b/erpnext/public/images/illustrations/products-onboard.png
deleted file mode 100644
index 2dee203..0000000
--- a/erpnext/public/images/illustrations/products-onboard.png
+++ /dev/null
Binary files differ
diff --git a/erpnext/public/images/illustrations/supplier-onboard.png b/erpnext/public/images/illustrations/supplier-onboard.png
deleted file mode 100644
index 30335f2..0000000
--- a/erpnext/public/images/illustrations/supplier-onboard.png
+++ /dev/null
Binary files differ
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 46a58fb..6ca0958 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -500,6 +500,9 @@
 								() => {
 									var d = locals[cdt][cdn];
 									me.add_taxes_from_item_tax_template(d.item_tax_rate);
+									if (d.free_item_data) {
+										me.apply_product_discount(d.free_item_data);
+									}
 								},
 								() => me.frm.script_manager.trigger("price_list_rate", cdt, cdn),
 								() => me.toggle_conversion_factor(item),
@@ -1305,6 +1308,10 @@
 				me.remove_pricing_rule(frappe.get_doc(d.doctype, d.name));
 			}
 
+			if (d.free_item_data) {
+				me.apply_product_discount(d.free_item_data);
+			}
+
 			if (d.apply_rule_on_other_items) {
 				items_rule_dict[d.name] = d;
 			}
@@ -1334,6 +1341,20 @@
 		}
 	},
 
+	apply_product_discount: function(free_item_data) {
+		const items = this.frm.doc.items.filter(d => (d.item_code == free_item_data.item_code
+			&& d.is_free_item)) || [];
+
+		if (!items.length) {
+			let row_to_modify = frappe.model.add_child(this.frm.doc,
+				this.frm.doc.doctype + ' Item', 'items');
+
+			for (let key in free_item_data) {
+				row_to_modify[key] = free_item_data[key];
+			}
+		}
+	},
+
 	apply_price_list: function(item, reset_plc_conversion) {
 		// We need to reset plc_conversion_rate sometimes because the call to
 		// `erpnext.stock.get_item_details.apply_price_list` is sensitive to its value
@@ -1754,14 +1775,28 @@
 		}
 	},
 
+	set_reserve_warehouse: function() {
+		this.autofill_warehouse("reserve_warehouse");
+	},
+
 	set_warehouse: function() {
+		this.autofill_warehouse("warehouse");
+	},
+
+	autofill_warehouse : function (warehouse_field) {
+		// set warehouse in all child table rows
 		var me = this;
-		if(this.frm.doc.set_warehouse) {
-			$.each(this.frm.doc.items || [], function(i, item) {
-				frappe.model.set_value(me.frm.doctype + " Item", item.name, "warehouse", me.frm.doc.set_warehouse);
+		let warehouse = (warehouse_field === "warehouse") ? me.frm.doc.set_warehouse : me.frm.doc.set_reserve_warehouse;
+		let child_table = (warehouse_field === "warehouse") ? me.frm.doc.items : me.frm.doc.supplied_items;
+		let doctype = (warehouse_field === "warehouse") ? (me.frm.doctype + " Item") : (me.frm.doctype + " Item Supplied");
+
+		if(warehouse) {
+			$.each(child_table || [], function(i, item) {
+				frappe.model.set_value(doctype, item.name, warehouse_field, warehouse);
 			});
 		}
 	},
+
 	coupon_code: function() {
 		var me = this;
 		frappe.run_serially([
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index d5a78d4..f363999 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -501,6 +501,7 @@
 	frm.doc[opts.child_docname].forEach(d => {
 		dialog.fields_dict.trans_items.df.data.push({
 			"docname": d.name,
+			"name": d.name,
 			"item_code": d.item_code,
 			"qty": d.qty,
 			"rate": d.rate,
diff --git a/erpnext/regional/report/gstr_2/gstr_2.py b/erpnext/regional/report/gstr_2/gstr_2.py
index a362269..f326fe0 100644
--- a/erpnext/regional/report/gstr_2/gstr_2.py
+++ b/erpnext/regional/report/gstr_2/gstr_2.py
@@ -44,12 +44,16 @@
 		for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
 			invoice_details = self.invoices.get(inv)
 			for rate, items in items_based_on_rate.items():
-				row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items)
-				tax_amount = taxable_value * rate / 100
-				if inv in self.igst_invoices:
-					row += [tax_amount, 0, 0]
+				if inv not in self.igst_invoices:
+					rate = rate / 2
+					row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items)
+					tax_amount = taxable_value * rate / 100
+					row += [0, tax_amount, tax_amount]
 				else:
-					row += [0, tax_amount / 2, tax_amount / 2]
+					row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items)
+					tax_amount = taxable_value * rate / 100
+					row += [tax_amount, 0, 0]
+
 
 				row += [
 					self.invoice_cess.get(inv),
diff --git a/erpnext/selling/doctype/customer/customer.js b/erpnext/selling/doctype/customer/customer.js
index cca8efe..aa1b92f 100644
--- a/erpnext/selling/doctype/customer/customer.js
+++ b/erpnext/selling/doctype/customer/customer.js
@@ -5,13 +5,13 @@
 	setup: function(frm) {
 
 		frm.make_methods = {
-			'Quotation': () => erpnext.utils.create_new_doc('Quotation', {
-				'quotation_to': frm.doc.doctype,
-				'party_name': frm.doc.name
+			'Quotation': () => frappe.model.open_mapped_doc({
+				method: "erpnext.selling.doctype.customer.customer.make_quotation",
+				frm: cur_frm
 			}),
-			'Opportunity': () => erpnext.utils.create_new_doc('Opportunity', {
-				'opportunity_from': frm.doc.doctype,
-				'party_name': frm.doc.name
+			'Opportunity': () => frappe.model.open_mapped_doc({
+				method: "erpnext.selling.doctype.customer.customer.make_opportunity",
+				frm: cur_frm
 			})
 		}
 
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index 57308ce..136236c 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -12,6 +12,7 @@
 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
 
 class Customer(TransactionBase):
 	def get_feed(self):
@@ -239,6 +240,66 @@
 	contact.insert()
 
 @frappe.whitelist()
+def make_quotation(source_name, target_doc=None):
+
+	def set_missing_values(source, target):
+		_set_missing_values(source, target)
+
+	target_doc = get_mapped_doc("Customer", source_name,
+		{"Customer": {
+			"doctype": "Quotation",
+			"field_map": {
+				"name":"party_name"
+			}
+		}}, target_doc, set_missing_values)
+
+	target_doc.quotation_to = "Customer"
+	target_doc.run_method("set_missing_values")
+	target_doc.run_method("set_other_charges")
+	target_doc.run_method("calculate_taxes_and_totals")
+
+	price_list = frappe.get_value("Customer", source_name, 'default_price_list')
+	if price_list:
+		target_doc.selling_price_list = price_list
+
+	return target_doc
+
+@frappe.whitelist()
+def make_opportunity(source_name, target_doc=None):
+	def set_missing_values(source, target):
+		_set_missing_values(source, target)
+
+	target_doc = get_mapped_doc("Customer", source_name,
+		{"Customer": {
+			"doctype": "Opportunity",
+			"field_map": {
+				"name": "party_name",
+				"doctype": "opportunity_from",
+			}
+		}}, target_doc, set_missing_values)
+
+	return target_doc
+
+def _set_missing_values(source, target):
+	address = frappe.get_all('Dynamic Link', {
+			'link_doctype': source.doctype,
+			'link_name': source.name,
+			'parenttype': 'Address',
+		}, ['parent'], limit=1)
+
+	contact = frappe.get_all('Dynamic Link', {
+			'link_doctype': source.doctype,
+			'link_name': source.name,
+			'parenttype': 'Contact',
+		}, ['parent'], limit=1)
+
+	if address:
+		target.customer_address = address[0].parent
+
+	if contact:
+		target.contact_person = contact[0].parent
+
+@frappe.whitelist()
 def get_loyalty_programs(doc):
 	''' returns applicable loyalty programs for a customer '''
 	from frappe.desk.treeview import get_children
diff --git a/erpnext/selling/onboarding_slide/add_a_few_customers/add_a_few_customers.json b/erpnext/selling/onboarding_slide/add_a_few_customers/add_a_few_customers.json
index f39fea4..92d00bc 100644
--- a/erpnext/selling/onboarding_slide/add_a_few_customers/add_a_few_customers.json
+++ b/erpnext/selling/onboarding_slide/add_a_few_customers/add_a_few_customers.json
@@ -12,9 +12,10 @@
   }
  ],
  "idx": 0,
- "image_src": "/assets/erpnext/images/illustrations/customers-onboard.png",
+ "image_src": "",
+ "is_completed": 0,
  "max_count": 3,
- "modified": "2019-12-03 22:54:28.959549",
+ "modified": "2019-12-09 17:54:01.686006",
  "modified_by": "Administrator",
  "name": "Add A Few Customers",
  "owner": "Administrator",
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js
index b213a29..33fbc22 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.js
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.js
@@ -286,14 +286,14 @@
 		if (in_list(['serial_no', 'batch_no'], field)) {
 			args[field] = value;
 		}
-
+		
 		// add to cur_frm
 		const item = this.frm.add_child('items', args);
 		frappe.flags.hide_serial_batch_dialog = true;
 
 		frappe.run_serially([
 			() => {
-				this.frm.script_manager.trigger('item_code', item.doctype, item.name)
+				return this.frm.script_manager.trigger('item_code', item.doctype, item.name)
 					.then(() => {
 						this.frm.script_manager.trigger('qty', item.doctype, item.name)
 							.then(() => {
diff --git a/erpnext/setup/doctype/company/company_list.js b/erpnext/setup/doctype/company/company_list.js
new file mode 100644
index 0000000..0172865
--- /dev/null
+++ b/erpnext/setup/doctype/company/company_list.js
@@ -0,0 +1,10 @@
+frappe.listview_settings['Company'] = {
+    onload: () => {
+        frappe.breadcrumbs.add({
+            type: 'Custom',
+            module: __('Accounts'),
+            label: __('Accounts'),
+            route: '#modules/Accounts'
+        });
+    }
+}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/company/delete_company_transactions.py b/erpnext/setup/doctype/company/delete_company_transactions.py
index 637e655..1503adb 100644
--- a/erpnext/setup/doctype/company/delete_company_transactions.py
+++ b/erpnext/setup/doctype/company/delete_company_transactions.py
@@ -106,7 +106,10 @@
 		frappe.db.sql("""update tabCustomer set lead_name=NULL where lead_name in ({leads})""".format(leads=",".join(leads)))
 
 def delete_communications(doctype, company_name, company_fieldname):
-		frappe.db.sql("""
-			DELETE FROM `tabCommunication` WHERE reference_doctype = %s AND
-			EXISTS (SELECT name FROM `tab{0}` WHERE {1} = %s AND `tabCommunication`.reference_name = name)
-			""".format(doctype, company_fieldname), (doctype, company_name))
+		reference_docs = frappe.get_all(doctype, filters={company_fieldname:company_name})
+		reference_doc_names = [r.name for r in reference_docs]
+		
+		communications = frappe.get_all("Communication", filters={"reference_doctype":doctype,"reference_name":["in", reference_doc_names]})
+		communication_names = [c.name for c in communications]
+
+		frappe.delete_doc("Communication", communication_names)
diff --git a/erpnext/setup/doctype/company/test_company.py b/erpnext/setup/doctype/company/test_company.py
index 8d9c23a..1664b66 100644
--- a/erpnext/setup/doctype/company/test_company.py
+++ b/erpnext/setup/doctype/company/test_company.py
@@ -88,6 +88,57 @@
 					self.delete_mode_of_payment(template)
 					frappe.delete_doc("Company", template)
 
+	def test_delete_communication(self):
+		from erpnext.setup.doctype.company.delete_company_transactions import delete_communications
+		company = create_child_company()
+		lead = create_test_lead_in_company(company)
+		communication = create_company_communication("Lead", lead)
+		delete_communications("Lead", "Test Company", "company")
+		self.assertFalse(frappe.db.exists("Communcation", communication))
+		self.assertFalse(frappe.db.exists({"doctype":"Comunication Link", "link_name": communication}))
+
 	def delete_mode_of_payment(self, company):
 		frappe.db.sql(""" delete from `tabMode of Payment Account`
 			where company =%s """, (company))
+
+def create_company_communication(doctype, docname):
+	comm = frappe.get_doc({
+			"doctype": "Communication",
+			"communication_type": "Communication",
+			"content": "Deduplication of Links",
+			"communication_medium": "Email",
+			"reference_doctype":doctype,
+			"reference_name":docname
+		})
+	comm.insert()
+
+def create_child_company():
+	child_company = frappe.db.exists("Company", "Test Company")
+	if not child_company:
+		child_company = frappe.get_doc({
+			"doctype":"Company",
+			"company_name":"Test Company",
+			"abbr":"test_company",
+			"default_currency":"INR"
+		})
+		child_company.insert()
+	else:
+		child_company = frappe.get_doc("Company", child_company)
+	
+	return child_company.name
+
+def create_test_lead_in_company(company):
+	lead = frappe.db.exists("Lead", "Test Lead in new company")
+	if not lead:
+		lead = frappe.get_doc({
+			"doctype": "Lead",
+			"lead_name": "Test Lead in new company",
+			"scompany": company
+		})
+		lead.insert()
+	else:
+		lead = frappe.get_doc("Lead", lead)
+		lead.company = company
+		lead.save()
+	return lead.name
+
diff --git "a/erpnext/setup/onboarding_slide/welcome_back_to_erpnext\041/welcome_back_to_erpnext\041.json" "b/erpnext/setup/onboarding_slide/welcome_back_to_erpnext\041/welcome_back_to_erpnext\041.json"
index bf330d0..f00dc94 100644
--- "a/erpnext/setup/onboarding_slide/welcome_back_to_erpnext\041/welcome_back_to_erpnext\041.json"
+++ "b/erpnext/setup/onboarding_slide/welcome_back_to_erpnext\041/welcome_back_to_erpnext\041.json"
@@ -7,10 +7,10 @@
  "domains": [],
  "help_links": [],
  "idx": 0,
- "image_src": "/assets/erpnext/images/illustrations/desk-onboard.png",
+ "image_src": "",
  "is_completed": 0,
  "max_count": 3,
- "modified": "2019-12-04 19:21:39.995776",
+ "modified": "2019-12-09 17:53:53.849953",
  "modified_by": "Administrator",
  "name": "Welcome back to ERPNext!",
  "owner": "Administrator",
diff --git "a/erpnext/setup/onboarding_slide/welcome_to_erpnext\041/welcome_to_erpnext\041.json" "b/erpnext/setup/onboarding_slide/welcome_to_erpnext\041/welcome_to_erpnext\041.json"
index 4ea6985..37eb67b 100644
--- "a/erpnext/setup/onboarding_slide/welcome_to_erpnext\041/welcome_to_erpnext\041.json"
+++ "b/erpnext/setup/onboarding_slide/welcome_to_erpnext\041/welcome_to_erpnext\041.json"
@@ -7,13 +7,14 @@
  "domains": [],
  "help_links": [],
  "idx": 0,
- "image_src": "/assets/erpnext/images/illustrations/desk-onboard.png",
+ "image_src": "",
+ "is_completed": 0,
  "max_count": 0,
- "modified": "2019-12-03 22:49:12.871260",
+ "modified": "2019-12-22 21:26:28.414597",
  "modified_by": "Administrator",
  "name": "Welcome to ERPNext!",
  "owner": "Administrator",
- "slide_desc": "Setting up an ERP can be overwhelming. But don't worry, we have got your back!\nLet's setup your company.\nThis wizard will help you onboard to ERPNext in a short time!",
+ "slide_desc": "<div class=\"text center\">Setting up an ERP can be overwhelming. But don't worry, we have got your back! This wizard will help you onboard to ERPNext in a short time!</div>",
  "slide_fields": [],
  "slide_module": "Setup",
  "slide_order": 1,
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index a2aab3f..af8e132 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -135,8 +135,7 @@
   "publish_in_hub",
   "hub_category_to_publish",
   "hub_warehouse",
-  "synced_with_hub",
-  "manufacturers"
+  "synced_with_hub"
  ],
  "fields": [
   {
@@ -1017,12 +1016,6 @@
    "read_only": 1
   },
   {
-   "fieldname": "manufacturers",
-   "fieldtype": "Table",
-   "label": "Manufacturers",
-   "options": "Item Manufacturer"
-  },
-  {
    "depends_on": "eval:!doc.__islocal",
    "fieldname": "over_delivery_receipt_allowance",
    "fieldtype": "Float",
@@ -1049,7 +1042,7 @@
  "idx": 2,
  "image_field": "image",
  "max_attachments": 1,
- "modified": "2019-10-09 17:05:59.576119",
+ "modified": "2019-12-13 12:15:56.197246",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item",
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 189261c..151be11 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -125,7 +125,6 @@
 		self.validate_auto_reorder_enabled_in_stock_settings()
 		self.cant_change()
 		self.update_show_in_website()
-		self.validate_manufacturer()
 
 		if not self.get("__islocal"):
 			self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
@@ -145,13 +144,6 @@
 		if cint(frappe.db.get_single_value('Stock Settings', 'clean_description_html')):
 			self.description = clean_html(self.description)
 
-	def validate_manufacturer(self):
-		list_man = [(x.manufacturer, x.manufacturer_part_no) for x in self.get('manufacturers')]
-		set_man = set(list_man)
-
-		if len(list_man) != len(set_man):
-			frappe.throw(_("Duplicate entry in Manufacturers table"))
-
 	def validate_customer_provided_part(self):
 		if self.is_customer_provided_item:
 			if self.is_purchase_item:
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 00d27ef..1b9660e 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -372,7 +372,7 @@
 			elif d.t_warehouse and not d.basic_rate:
 				d.basic_rate = get_valuation_rate(d.item_code, d.t_warehouse,
 					self.doctype, self.name, d.allow_zero_valuation_rate,
-					currency=erpnext.get_company_currency(self.company))
+					currency=erpnext.get_company_currency(self.company), company=self.company)
 
 	def set_actual_qty(self):
 		allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock"))
diff --git a/erpnext/stock/onboarding_slide/add_a_few_products_you_buy_or_sell/add_a_few_products_you_buy_or_sell.json b/erpnext/stock/onboarding_slide/add_a_few_products_you_buy_or_sell/add_a_few_products_you_buy_or_sell.json
index 27a3062..5ee3167 100644
--- a/erpnext/stock/onboarding_slide/add_a_few_products_you_buy_or_sell/add_a_few_products_you_buy_or_sell.json
+++ b/erpnext/stock/onboarding_slide/add_a_few_products_you_buy_or_sell/add_a_few_products_you_buy_or_sell.json
@@ -7,9 +7,10 @@
  "domains": [],
  "help_links": [],
  "idx": 0,
- "image_src": "/assets/erpnext/images/illustrations/products-onboard.png",
+ "image_src": "",
+ "is_completed": 0,
  "max_count": 3,
- "modified": "2019-12-03 22:54:07.558632",
+ "modified": "2019-12-09 17:54:09.602885",
  "modified_by": "Administrator",
  "name": "Add A Few Products You Buy Or Sell",
  "owner": "Administrator",
diff --git a/erpnext/www/book_appointment/index.js b/erpnext/www/book_appointment/index.js
index c8dd501..262e31b 100644
--- a/erpnext/www/book_appointment/index.js
+++ b/erpnext/www/book_appointment/index.js
@@ -24,20 +24,15 @@
 }
 
 function setup_timezone_selector() {
-    /**
-     * window.timezones is a dictionary with the following structure
-     * { IANA name: Pretty name}
-     * For example : { Asia/Kolkata : "India Time - Asia/Kolkata"}
-     */
     let timezones_element = document.getElementById('appointment-timezone');
-    let offset = new Date().getTimezoneOffset();
-    Object.keys(window.timezones).forEach((timezone) => {
+    let local_timezone = moment.tz.guess()
+    window.timezones.forEach(timezone => {
         let opt = document.createElement('option');
         opt.value = timezone;
-        if (timezone == moment.tz.guess()) {
+        if (timezone == local_timezone) {
             opt.selected = true;
         }
-        opt.innerHTML = window.timezones[timezone]
+        opt.innerHTML = timezone;
         timezones_element.appendChild(opt)
     });
 }
@@ -114,7 +109,7 @@
         timeslot_div.classList.add('unavailable')
     }
     timeslot_div.innerHTML = get_slot_layout(start_time);
-    timeslot_div.id = timeslot.time.substr(11, 20);
+    timeslot_div.id = timeslot.time.substring(11, 19);
     timeslot_div.addEventListener('click', select_time);
     return timeslot_div
 }
diff --git a/erpnext/www/book_appointment/index.py b/erpnext/www/book_appointment/index.py
index 5b60dd5..7bfac89 100644
--- a/erpnext/www/book_appointment/index.py
+++ b/erpnext/www/book_appointment/index.py
@@ -25,18 +25,8 @@
 
 @frappe.whitelist(allow_guest=True)
 def get_timezones():
-	from babel.dates import get_timezone, get_timezone_name, Locale
-	from frappe.utils.momentjs import get_all_timezones
-
-	translated_dict = {}
-	locale = Locale.parse(frappe.local.lang, sep="-")
-
-	for tz in get_all_timezones():
-		timezone_name = get_timezone_name(get_timezone(tz), locale=locale, width='short')
-		if timezone_name:
-			translated_dict[tz] = timezone_name + ' - ' + tz
-
-	return translated_dict
+	import pytz
+	return pytz.all_timezones
 
 @frappe.whitelist(allow_guest=True)
 def get_appointment_slots(date, timezone):
@@ -90,7 +80,7 @@
 
 @frappe.whitelist(allow_guest=True)
 def create_appointment(date, time, tz, contact):
-	format_string = '%Y-%m-%d %H:%M:%S%z'
+	format_string = '%Y-%m-%d %H:%M:%S'
 	scheduled_time = datetime.datetime.strptime(date + " " + time, format_string)
 	# Strip tzinfo from datetime objects since it's handled by the doctype
 	scheduled_time = scheduled_time.replace(tzinfo = None)