Merge pull request #22985 from deepeshgarg007/accounting_period_cancellation

fix: Cancellation of accounting transactions within closed accounting period
diff --git a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py
index f28a074..88e1055 100644
--- a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py
+++ b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py
@@ -27,4 +27,4 @@
 	for col in column_list:
 		sanitize_searchfield(col) 
 	return frappe.db.sql(''' select {columns} from `tab{doctype}` where name=%s'''
-		.format(columns=", ".join(json.loads(column_list)), doctype=doctype), docname, as_dict=1)[0]
+		.format(columns=", ".join(column_list), doctype=doctype), docname, as_dict=1)[0]
diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.js b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.js
index 0b7cff3..2235298 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.js
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.js
@@ -135,7 +135,7 @@
 			callback: function(r) {
 				if(!r.exc) {
 					clearInterval(frm.page["interval"]);
-					frm.page.set_indicator(__('Import Successfull'), 'blue');
+					frm.page.set_indicator(__('Import Successful'), 'blue');
 					create_reset_button(frm);
 				}
 			}
diff --git a/erpnext/accounts/doctype/coupon_code/test_coupon_code.py b/erpnext/accounts/doctype/coupon_code/test_coupon_code.py
index 3a0d416..340b9dd 100644
--- a/erpnext/accounts/doctype/coupon_code/test_coupon_code.py
+++ b/erpnext/accounts/doctype/coupon_code/test_coupon_code.py
@@ -9,6 +9,8 @@
 from erpnext.stock.get_item_details import get_item_details
 from frappe.test_runner import make_test_objects
 
+test_dependencies = ['Item']
+
 def test_create_test_data():
 	frappe.set_user("Administrator")
 	# create test item
@@ -95,7 +97,6 @@
 		})
 		coupon_code.insert()
 
-
 class TestCouponCode(unittest.TestCase):
 	def setUp(self):
 		test_create_test_data()
diff --git a/erpnext/accounts/doctype/dunning/dunning.py b/erpnext/accounts/doctype/dunning/dunning.py
index 3e372af..1a6dbed 100644
--- a/erpnext/accounts/doctype/dunning/dunning.py
+++ b/erpnext/accounts/doctype/dunning/dunning.py
@@ -93,6 +93,7 @@
 
 def calculate_interest_and_amount(posting_date, outstanding_amount, rate_of_interest, dunning_fee, overdue_days):
 	interest_amount = 0
+	grand_total = 0
 	if rate_of_interest:
 		interest_per_year = flt(outstanding_amount) * flt(rate_of_interest) / 100
 		interest_amount = (interest_per_year * cint(overdue_days)) / 365 
diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year_dashboard.py b/erpnext/accounts/doctype/fiscal_year/fiscal_year_dashboard.py
index c7604ec..58480df 100644
--- a/erpnext/accounts/doctype/fiscal_year/fiscal_year_dashboard.py
+++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year_dashboard.py
@@ -13,7 +13,7 @@
 			},
 			{
 				'label': _('References'),
-				'items': ['Period Closing Voucher', 'Request for Quotation', 'Tax Withholding Category']
+				'items': ['Period Closing Voucher', 'Tax Withholding Category']
 			},
 			{
 				'label': _('Target Details'),
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
index 8680b71..ba68df7 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
@@ -21,7 +21,7 @@
 class POSInvoice(SalesInvoice):
 	def __init__(self, *args, **kwargs):
 		super(POSInvoice, self).__init__(*args, **kwargs)
-	
+
 	def validate(self):
 		if not cint(self.is_pos):
 			frappe.throw(_("POS Invoice should have {} field checked.").format(frappe.bold("Include Payment")))
@@ -58,7 +58,7 @@
 		if self.redeem_loyalty_points and self.loyalty_points:
 			self.apply_loyalty_points()
 		self.set_status(update=True)
-	
+
 	def on_cancel(self):
 		# run on cancel method of selling controller
 		super(SalesInvoice, self).on_cancel()
@@ -68,10 +68,10 @@
 			against_psi_doc = frappe.get_doc("POS Invoice", self.return_against)
 			against_psi_doc.delete_loyalty_point_entry()
 			against_psi_doc.make_loyalty_point_entry()
-		
+
 	def validate_stock_availablility(self):
 		allow_negative_stock = frappe.db.get_value('Stock Settings', None, 'allow_negative_stock')
-		
+
 		for d in self.get('items'):
 			if d.serial_no:
 				filters = {
@@ -89,11 +89,11 @@
 				for s in serial_nos:
 					if s in reserved_serial_nos:
 						invalid_serial_nos.append(s)
-				
+
 				if len(invalid_serial_nos):
 					multiple_nos = 's' if len(invalid_serial_nos) > 1 else ''
 					frappe.throw(_("Row #{}: Serial No{}. {} has already been transacted into another POS Invoice. \
-						Please select valid serial no.".format(d.idx, multiple_nos, 
+						Please select valid serial no.".format(d.idx, multiple_nos,
 						frappe.bold(', '.join(invalid_serial_nos)))), title=_("Not Available"))
 			else:
 				if allow_negative_stock:
@@ -105,9 +105,9 @@
 						.format(d.idx, frappe.bold(d.item_code), frappe.bold(d.warehouse))), title=_("Not Available"))
 				elif flt(available_stock) < flt(d.qty):
 					frappe.msgprint(_('Row #{}: Stock quantity not enough for Item Code: {} under warehouse {}. \
-						Available quantity {}.'.format(d.idx, frappe.bold(d.item_code), 
+						Available quantity {}.'.format(d.idx, frappe.bold(d.item_code),
 						frappe.bold(d.warehouse), frappe.bold(d.qty))), title=_("Not Available"))
-	
+
 	def validate_serialised_or_batched_item(self):
 		for d in self.get("items"):
 			serialized = d.get("has_serial_no")
@@ -125,7 +125,7 @@
 			if batched and no_batch_selected:
 				frappe.throw(_('Row #{}: No batch selected against item: {}. Please select a batch or remove it to complete transaction.'
 						.format(d.idx, frappe.bold(d.item_code))), title=_("Invalid Item"))
-	
+
 	def validate_return_items(self):
 		if not self.get("is_return"): return
 
@@ -158,7 +158,7 @@
 				frappe.throw(_("Row #{0} (Payment Table): Amount must be positive").format(entry.idx))
 			if self.is_return and entry.amount > 0:
 				frappe.throw(_("Row #{0} (Payment Table): Amount must be negative").format(entry.idx))
-	
+
 	def validate_pos_return(self):
 		if self.is_pos and self.is_return:
 			total_amount_in_payments = 0
@@ -167,12 +167,12 @@
 			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)))
-	
+
 	def validate_loyalty_transaction(self):
 		if self.redeem_loyalty_points and (not self.loyalty_redemption_account or not self.loyalty_redemption_cost_center):
 			expense_account, cost_center = frappe.db.get_value('Loyalty Program', self.loyalty_program, ["expense_account", "cost_center"])
 			if not self.loyalty_redemption_account:
-				self.loyalty_redemption_account = expense_account 
+				self.loyalty_redemption_account = expense_account
 			if not self.loyalty_redemption_cost_center:
 				self.loyalty_redemption_cost_center = cost_center
 
@@ -212,7 +212,7 @@
 
 		if update:
 			self.db_set('status', self.status, update_modified = update_modified)
-	
+
 	def set_pos_fields(self, for_validate=False):
 		"""Set retail related fields from POS Profiles"""
 		from erpnext.stock.get_item_details import get_pos_profile_item_details, get_pos_profile
@@ -315,25 +315,25 @@
 
 @frappe.whitelist()
 def get_stock_availability(item_code, warehouse):
-	latest_sle = frappe.db.sql("""select qty_after_transaction 
-		from `tabStock Ledger Entry` 
+	latest_sle = frappe.db.sql("""select qty_after_transaction
+		from `tabStock Ledger Entry`
 		where item_code = %s and warehouse = %s
 		order by posting_date desc, posting_time desc
 		limit 1""", (item_code, warehouse), as_dict=1)
-	
+
 	pos_sales_qty = frappe.db.sql("""select sum(p_item.qty) as qty
 		from `tabPOS Invoice` p, `tabPOS Invoice Item` p_item
-		where p.name = p_item.parent 
-		and p.consolidated_invoice is NULL 
+		where p.name = p_item.parent
+		and p.consolidated_invoice is NULL
 		and p.docstatus = 1
 		and p_item.docstatus = 1
 		and p_item.item_code = %s
 		and p_item.warehouse = %s
 		""", (item_code, warehouse), as_dict=1)
-	
+
 	sle_qty = latest_sle[0].qty_after_transaction or 0 if latest_sle else 0
 	pos_sales_qty = pos_sales_qty[0].qty or 0 if pos_sales_qty else 0
-	
+
 	if sle_qty and pos_sales_qty and sle_qty > pos_sales_qty:
 		return sle_qty - pos_sales_qty
 	else:
@@ -360,14 +360,14 @@
 	merge_log = frappe.new_doc("POS Invoice Merge Log")
 	merge_log.posting_date = getdate(nowdate())
 	for inv in invoices:
-		inv_data = frappe.db.get_values("POS Invoice", inv.get('name'), 
+		inv_data = frappe.db.get_values("POS Invoice", inv.get('name'),
 			["customer", "posting_date", "grand_total"], as_dict=1)[0]
 		merge_log.customer = inv_data.customer
 		merge_log.append("pos_invoices", {
 			'pos_invoice': inv.get('name'),
 			'customer': inv_data.customer,
 			'posting_date': inv_data.posting_date,
-			'grand_total': inv_data.grand_total 
+			'grand_total': inv_data.grand_total
 		})
 
 	if merge_log.get('pos_invoices'):
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js
index ef431d7..8ec6a53 100755
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.js
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js
@@ -31,8 +31,7 @@
 		frm.set_query("print_format", function() {
 			return {
 				filters: [
-					['Print Format', 'doc_type', '=', 'Sales Invoice'],
-					['Print Format', 'print_format_type', '=', 'Jinja'],
+					['Print Format', 'doc_type', '=', 'POS Invoice']
 				]
 			};
 		});
@@ -45,10 +44,6 @@
 			};
 		});
 
-		frm.set_query("print_format", function() {
-			return { filters: { doc_type: "Sales Invoice", print_format_type: "JS"} };
-		});
-
 		frm.set_query('company_address', function(doc) {
 			if(!doc.company) {
 				frappe.throw(__('Please set Company'));
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json
index 454c598..d4c1791 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.json
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json
@@ -302,10 +302,10 @@
    "fieldname": "warehouse",
    "fieldtype": "Link",
    "label": "Warehouse",
+   "mandatory_depends_on": "update_stock",
    "oldfieldname": "warehouse",
    "oldfieldtype": "Link",
-   "options": "Warehouse",
-   "reqd": 1
+   "options": "Warehouse"
   },
   {
    "default": "0",
@@ -350,4 +350,4 @@
  ],
  "sort_field": "modified",
  "sort_order": "DESC"
-}
\ No newline at end of file
+}
diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
index 8a4050c..edf8659 100644
--- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
@@ -8,6 +8,8 @@
 from erpnext.stock.get_item_details import get_pos_profile
 from erpnext.accounts.doctype.pos_profile.pos_profile import get_child_nodes
 
+test_dependencies = ['Item']
+
 class TestPOSProfile(unittest.TestCase):
 	def test_pos_profile(self):
 		make_pos_profile()
@@ -88,7 +90,7 @@
 		"write_off_account":  args.write_off_account or "_Test Write Off - _TC",
 		"write_off_cost_center":  args.write_off_cost_center or "_Test Write Off Cost Center - _TC"
 	})
-	
+
 	payments = [{
 		'mode_of_payment': 'Cash',
 		'default': 1
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index cff7d5b..aa6194c 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -1,5 +1,4 @@
 # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# MIT License. See license.txt
 
 # For license information, please see license.txt
 
@@ -208,7 +207,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_product_discount_rule)
+			get_applied_pricing_rules, get_pricing_rule_items, get_product_discount_rule)
 
 	if isinstance(doc, string_types):
 		doc = json.loads(doc)
@@ -237,7 +236,7 @@
 
 	update_args_for_pricing_rule(args)
 
-	pricing_rules = (get_applied_pricing_rules(args)
+	pricing_rules = (get_applied_pricing_rules(args.get('pricing_rules'))
 		if for_validate and args.get("pricing_rules") else get_pricing_rules(args, doc))
 
 	if pricing_rules:
@@ -365,8 +364,9 @@
 			item_details.rate = rate
 
 def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None):
-	from erpnext.accounts.doctype.pricing_rule.utils import get_pricing_rule_items
-	for d in json.loads(pricing_rules):
+	from erpnext.accounts.doctype.pricing_rule.utils import (get_applied_pricing_rules,
+		get_pricing_rule_items)
+	for d in get_applied_pricing_rules(pricing_rules):
 		if not d or not frappe.db.exists("Pricing Rule", d): continue
 		pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
 
diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py
index 3fd316f..53b0cf7b 100644
--- a/erpnext/accounts/doctype/pricing_rule/utils.py
+++ b/erpnext/accounts/doctype/pricing_rule/utils.py
@@ -447,9 +447,14 @@
 				apply_pricing_rule_for_free_items(doc, item_details.free_item_data)
 				doc.set_missing_values()
 
-def get_applied_pricing_rules(item_row):
-	return (json.loads(item_row.get("pricing_rules"))
-		if item_row.get("pricing_rules") else [])
+def get_applied_pricing_rules(pricing_rules):
+	if pricing_rules:
+		if pricing_rules.startswith('['):
+			return json.loads(pricing_rules)
+		else:
+			return pricing_rules.split(',')
+
+	return []
 
 def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None):
 	free_item = pricing_rule.free_item
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/__init__.py b/erpnext/accounts/doctype/process_statement_of_accounts/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/__init__.py
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
new file mode 100644
index 0000000..e1ddeff
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
@@ -0,0 +1,89 @@
+<h1 class="text-center" style="page-break-before:always">{{ filters.party[0] }}</h1>
+<h3 class="text-center">{{ _("Statement of Accounts") }}</h3>
+
+<h5 class="text-center">
+    {{ frappe.format(filters.from_date, 'Date')}}
+	{{ _("to") }}
+	{{ frappe.format(filters.to_date, 'Date')}}
+</h5>
+
+<table class="table table-bordered">
+	<thead>
+		<tr>
+			<th style="width: 12%">{{ _("Date") }}</th>
+			<th style="width: 15%">{{ _("Ref") }}</th>
+			<th style="width: 25%">{{ _("Party") }}</th>
+			<th style="width: 15%">{{ _("Debit") }}</th>
+			<th style="width: 15%">{{ _("Credit") }}</th>
+			<th style="width: 18%">{{ _("Balance (Dr - Cr)") }}</th>
+		</tr>
+	</thead>
+	<tbody>
+        {% for row in data %}
+			<tr>
+			{% if(row.posting_date) %}
+				<td>{{ frappe.format(row.posting_date, 'Date') }}</td>
+				<td>{{ row.voucher_type }}
+					<br>{{ row.voucher_no }}</td>
+				<td>
+					{% if not (filters.party or filters.account)  %}
+						{{ row.party or row.account }}
+						<br>
+					{% endif %}
+
+					{{ _("Against") }}: {{ row.against }}
+					<br>{{ _("Remarks") }}: {{ row.remarks }}
+					{% if row.bill_no %}
+						<br>{{ _("Supplier Invoice No") }}: {{ row.bill_no }}
+					{% endif %}
+					</td>
+					<td style="text-align: right">
+						{{ frappe.utils.fmt_money(row.debit, filters.presentation_currency) }}</td>
+					<td style="text-align: right">
+						{{ frappe.utils.fmt_money(row.credit, filters.presentation_currency) }}</td>
+			{% else %}
+				<td></td>
+				<td></td>
+				<td><b>{{ frappe.format(row.account, {fieldtype: "Link"}) or "&nbsp;" }}</b></td>
+				<td style="text-align: right">
+					{{ row.account and frappe.utils.fmt_money(row.debit, filters.presentation_currency) }}
+				</td>
+				<td style="text-align: right">
+					{{ row.account and frappe.utils.fmt_money(row.credit, filters.presentation_currency) }}
+				</td>
+			{% endif %}
+				<td style="text-align: right">
+					{{ frappe.utils.fmt_money(row.balance, filters.presentation_currency) }}
+				</td>
+			</tr>
+		{% endfor %}
+		</tbody>
+</table>
+<br><br>
+{% if aging %}
+<h3 class="text-center">{{ _("Ageing Report Based On ") }} {{ aging.ageing_based_on }}</h3>
+<h5 class="text-center">
+	{{ _("Up to " ) }}  {{ frappe.format(filters.to_date, 'Date')}}
+</h5>
+<br>
+
+<table class="table table-bordered">
+	<thead>
+		<tr>
+			<th style="width: 12%">30 Days</th>
+			<th style="width: 15%">60 Days</th>
+			<th style="width: 25%">90 Days</th>
+			<th style="width: 15%">120 Days</th>
+		</tr>
+	</thead>
+	<tbody>
+		<tr>
+			<td>{{ aging.range1 }}</td>
+			<td>{{ aging.range2 }}</td>
+			<td>{{ aging.range3 }}</td>
+			<td>{{ aging.range4 }}</td>
+		</tr>
+	</tbody>
+</table>
+{% endif %}
+<p class="text-right text-muted">Printed On {{ frappe.format(frappe.utils.get_datetime(), 'Datetime') }}</p>
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
new file mode 100644
index 0000000..7425132
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js
@@ -0,0 +1,132 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Process Statement Of Accounts', {
+	view_properties: function(frm) {
+		frappe.route_options = {doc_type: 'Customer'};
+		frappe.set_route("Form", "Customize Form");
+	},
+	refresh: function(frm){
+		if(!frm.doc.__islocal) {
+			frm.add_custom_button('Send Emails',function(){
+				frappe.call({
+					method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_emails",
+					args: {
+						"document_name": frm.doc.name,
+					},
+					callback: function(r) {
+						if(r && r.message) {
+							frappe.show_alert({message: __('Emails Queued'), indicator: 'blue'});
+						}
+						else{
+							frappe.msgprint('No Records for these settings.')
+						}
+					}
+				});
+			});
+			frm.add_custom_button('Download',function(){
+				var url = frappe.urllib.get_full_url(
+					'/api/method/erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.download_statements?'
+					+ 'document_name='+encodeURIComponent(frm.doc.name))
+				$.ajax({
+					url: url,
+					type: 'GET',
+					success: function(result) {
+						if(jQuery.isEmptyObject(result)){
+							frappe.msgprint('No Records for these settings.');
+						}
+						else{
+							window.location = url;
+						}
+					}
+				});
+			});
+		}
+	},
+	onload: function(frm) {
+		frm.set_query('currency', function(){
+			return {
+				filters: {
+					'enabled': 1
+				}
+			}
+		});
+		if(frm.doc.__islocal){
+			frm.set_value('from_date', frappe.datetime.add_months(frappe.datetime.get_today(), -1));
+			frm.set_value('to_date', frappe.datetime.get_today());
+		}
+	},
+	customer_collection: function(frm){
+		frm.set_value('collection_name', '');
+		if(frm.doc.customer_collection){
+			frm.get_field('collection_name').set_label(frm.doc.customer_collection);
+		}
+	},
+	frequency: function(frm){
+		if(frm.doc.frequency != ''){
+			frm.set_value('start_date', frappe.datetime.get_today());
+		}
+		else{
+			frm.set_value('start_date', '');
+		}
+	},
+	fetch_customers: function(frm){
+		if(frm.doc.collection_name){
+			frappe.call({
+				method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.fetch_customers",
+				args: {
+					'customer_collection': frm.doc.customer_collection,
+					'collection_name': frm.doc.collection_name,
+					'primary_mandatory': frm.doc.primary_mandatory
+				},
+				callback: function(r) {
+					if(!r.exc) {
+						if(r.message.length){
+							frm.clear_table('customers');
+							for (const customer of r.message){
+								var row = frm.add_child('customers');
+								row.customer = customer.name;
+								row.primary_email = customer.primary_email;
+								row.billing_email = customer.billing_email;
+							}
+							frm.refresh_field('customers');
+						}
+						else{
+							frappe.msgprint('No Customers found with selected options.');
+						}
+					}
+				}
+			});
+		}
+		else {
+			frappe.throw('Enter ' + frm.doc.customer_collection + ' name.');
+		}
+	}
+});
+
+frappe.ui.form.on('Process Statement Of Accounts Customer', {
+	customer: function(frm, cdt, cdn){
+		var row = locals[cdt][cdn];
+		if (!row.customer){
+			return;
+		}
+		frappe.call({
+			method: 'erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.get_customer_emails',
+			args: {
+				'customer_name': row.customer,
+				'primary_mandatory': frm.doc.primary_mandatory
+			},
+			callback: function(r){
+				if(!r.exe){
+					if(r.message.length){
+						frappe.model.set_value(cdt, cdn, "primary_email", r.message[0])
+						frappe.model.set_value(cdt, cdn, "billing_email", r.message[1])
+					}
+					else {
+						return
+					}
+				}
+			}
+		})
+	}
+});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json
new file mode 100644
index 0000000..4be0e2e
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json
@@ -0,0 +1,310 @@
+{
+ "actions": [],
+ "allow_workflow": 1,
+ "autoname": "Prompt",
+ "creation": "2020-05-22 16:46:18.712954",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "section_break_11",
+  "from_date",
+  "company",
+  "account",
+  "group_by",
+  "cost_center",
+  "column_break_14",
+  "to_date",
+  "finance_book",
+  "currency",
+  "project",
+  "section_break_3",
+  "customer_collection",
+  "collection_name",
+  "fetch_customers",
+  "column_break_6",
+  "primary_mandatory",
+  "column_break_17",
+  "customers",
+  "preferences",
+  "orientation",
+  "section_break_14",
+  "include_ageing",
+  "ageing_based_on",
+  "section_break_1",
+  "enable_auto_email",
+  "section_break_18",
+  "frequency",
+  "filter_duration",
+  "column_break_21",
+  "start_date",
+  "section_break_33",
+  "subject",
+  "column_break_28",
+  "cc_to",
+  "section_break_30",
+  "body",
+  "help_text"
+ ],
+ "fields": [
+  {
+   "fieldname": "frequency",
+   "fieldtype": "Select",
+   "label": "Frequency",
+   "options": "Weekly\nMonthly\nQuarterly"
+  },
+  {
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
+  {
+   "depends_on": "eval:doc.enable_auto_email == 0;",
+   "fieldname": "from_date",
+   "fieldtype": "Date",
+   "label": "From Date",
+   "mandatory_depends_on": "eval:doc.frequency == '';"
+  },
+  {
+   "depends_on": "eval:doc.enable_auto_email == 0;",
+   "fieldname": "to_date",
+   "fieldtype": "Date",
+   "label": "To Date",
+   "mandatory_depends_on": "eval:doc.frequency == '';"
+  },
+  {
+   "fieldname": "cost_center",
+   "fieldtype": "Table MultiSelect",
+   "label": "Cost Center",
+   "options": "PSOA Cost Center"
+  },
+  {
+   "fieldname": "project",
+   "fieldtype": "Table MultiSelect",
+   "label": "Project",
+   "options": "PSOA Project"
+  },
+  {
+   "fieldname": "section_break_3",
+   "fieldtype": "Section Break",
+   "label": "Customers"
+  },
+  {
+   "fieldname": "column_break_6",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "section_break_11",
+   "fieldtype": "Section Break",
+   "label": "General Ledger Filters"
+  },
+  {
+   "fieldname": "column_break_14",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_17",
+   "fieldtype": "Section Break",
+   "hide_border": 1
+  },
+  {
+   "fieldname": "customer_collection",
+   "fieldtype": "Select",
+   "label": "Select Customers By",
+   "options": "\nCustomer Group\nTerritory\nSales Partner\nSales Person"
+  },
+  {
+   "depends_on": "eval: doc.customer_collection !== ''",
+   "fieldname": "collection_name",
+   "fieldtype": "Dynamic Link",
+   "label": "Recipient",
+   "options": "customer_collection"
+  },
+  {
+   "fieldname": "section_break_1",
+   "fieldtype": "Section Break",
+   "label": "Email Settings"
+  },
+  {
+   "fieldname": "account",
+   "fieldtype": "Link",
+   "label": "Account",
+   "options": "Account"
+  },
+  {
+   "fieldname": "finance_book",
+   "fieldtype": "Link",
+   "label": "Finance Book",
+   "options": "Finance Book"
+  },
+  {
+   "fieldname": "preferences",
+   "fieldtype": "Section Break",
+   "label": "Print Preferences"
+  },
+  {
+   "fieldname": "orientation",
+   "fieldtype": "Select",
+   "label": "Orientation",
+   "options": "Landscape\nPortrait"
+  },
+  {
+   "default": "Today",
+   "fieldname": "start_date",
+   "fieldtype": "Date",
+   "label": "Start Date"
+  },
+  {
+   "default": "Group by Voucher (Consolidated)",
+   "fieldname": "group_by",
+   "fieldtype": "Select",
+   "label": "Group By",
+   "options": "\nGroup by Voucher\nGroup by Voucher (Consolidated)"
+  },
+  {
+   "fieldname": "currency",
+   "fieldtype": "Link",
+   "label": "Currency",
+   "options": "Currency"
+  },
+  {
+   "default": "0",
+   "fieldname": "include_ageing",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Include Ageing Summary"
+  },
+  {
+   "default": "Due Date",
+   "depends_on": "eval:doc.include_ageing === 1",
+   "fieldname": "ageing_based_on",
+   "fieldtype": "Select",
+   "label": "Ageing Based On",
+   "options": "Due Date\nPosting Date"
+  },
+  {
+   "default": "0",
+   "fieldname": "enable_auto_email",
+   "fieldtype": "Check",
+   "in_list_view": 1,
+   "label": "Enable Auto Email"
+  },
+  {
+   "fieldname": "section_break_14",
+   "fieldtype": "Column Break",
+   "hide_border": 1
+  },
+  {
+   "depends_on": "eval: doc.enable_auto_email ==1",
+   "fieldname": "section_break_18",
+   "fieldtype": "Section Break",
+   "hide_border": 1
+  },
+  {
+   "fieldname": "column_break_21",
+   "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval: doc.customer_collection !== ''",
+   "fieldname": "fetch_customers",
+   "fieldtype": "Button",
+   "label": "Fetch Customers",
+   "options": "fetch_customers",
+   "print_hide": 1,
+   "report_hide": 1
+  },
+  {
+   "default": "1",
+   "fieldname": "primary_mandatory",
+   "fieldtype": "Check",
+   "label": "Send To Primary Contact"
+  },
+  {
+   "fieldname": "cc_to",
+   "fieldtype": "Link",
+   "label": "CC To",
+   "options": "User"
+  },
+  {
+   "default": "1",
+   "fieldname": "filter_duration",
+   "fieldtype": "Int",
+   "label": "Filter Duration (Months)"
+  },
+  {
+   "fieldname": "customers",
+   "fieldtype": "Table",
+   "label": "Customers",
+   "options": "Process Statement Of Accounts Customer",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_28",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "section_break_30",
+   "fieldtype": "Section Break",
+   "hide_border": 1
+  },
+  {
+   "fieldname": "section_break_33",
+   "fieldtype": "Section Break",
+   "hide_border": 1
+  },
+  {
+   "fieldname": "help_text",
+   "fieldtype": "HTML",
+   "label": "Help Text",
+   "options": "<br>\n<h4>Note</h4>\n<ul>\n<li>\nYou can use <a href=\"https://jinja.palletsprojects.com/en/2.11.x/\" target=\"_blank\">Jinja tags</a> in <b>Subject</b> and <b>Body</b> fields for dynamic values.\n</li><li>\n    All fields in this doctype are available under the <b>doc</b> object and all fields for the customer to whom the mail will go to is available under the  <b>customer</b> object.\n</li></ul>\n<h4> Examples</h4>\n<!-- {% raw %} -->\n<ul>\n    <li><b>Subject</b>:<br><br><pre><code>Statement Of Accounts for {{ customer.name }}</code></pre><br></li>\n    <li><b>Body</b>: <br><br>\n<pre><code>Hello {{ customer.name }},<br>PFA your Statement Of Accounts from {{ doc.from_date }} to {{ doc.to_date }}.</code> </pre></li>\n</ul>\n<!-- {% endraw %} -->"
+  },
+  {
+   "fieldname": "subject",
+   "fieldtype": "Data",
+   "label": "Subject"
+  },
+  {
+   "fieldname": "body",
+   "fieldtype": "Text Editor",
+   "label": "Body"
+  }
+ ],
+ "links": [],
+ "modified": "2020-08-08 08:47:09.185728",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Process Statement Of Accounts",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts User",
+   "share": 1,
+   "write": 1
+  },
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Accounts Manager",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
new file mode 100644
index 0000000..d50e4a8
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
@@ -0,0 +1,271 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from erpnext.accounts.report.general_ledger.general_ledger import execute as get_soa
+from erpnext.accounts.report.accounts_receivable_summary.accounts_receivable_summary import execute as get_ageing
+from frappe.core.doctype.communication.email import make
+
+from frappe.utils.print_format import report_to_pdf
+from frappe.utils.pdf import get_pdf
+from frappe.utils import today, add_days, add_months, getdate, format_date
+from frappe.utils.jinja import validate_template
+
+import copy
+from datetime import timedelta
+from frappe.www.printview import get_print_style
+
+class ProcessStatementOfAccounts(Document):
+	def validate(self):
+		if not self.subject:
+			self.subject = 'Statement Of Accounts for {{ customer.name }}'
+		if not self.body:
+			self.body = 'Hello {{ customer.name }},<br>PFA your Statement Of Accounts from {{ doc.from_date }} to {{ doc.to_date }}.'
+
+		validate_template(self.subject)
+		validate_template(self.body)
+
+		if not self.customers:
+			frappe.throw(frappe._('Customers not selected.'))
+
+		if self.enable_auto_email:
+			self.to_date = self.start_date
+			self.from_date = add_months(self.to_date, -1 * self.filter_duration)
+
+
+def get_report_pdf(doc, consolidated=True):
+	statement_dict = {}
+	aging = ''
+	base_template_path = "frappe/www/printview.html"
+	template_path = "erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html"
+
+	for entry in doc.customers:
+		if doc.include_ageing:
+			ageing_filters = frappe._dict({
+				'company': doc.company,
+				'report_date': doc.to_date,
+				'ageing_based_on': doc.ageing_based_on,
+				'range1': 30,
+				'range2': 60,
+				'range3': 90,
+				'range4': 120,
+				'customer': entry.customer
+			})
+			col1, aging = get_ageing(ageing_filters)
+			aging[0]['ageing_based_on'] = doc.ageing_based_on
+
+		tax_id = frappe.get_doc('Customer', entry.customer).tax_id
+
+		filters= frappe._dict({
+			'from_date': doc.from_date,
+			'to_date': doc.to_date,
+			'company': doc.company,
+			'finance_book': doc.finance_book if doc.finance_book else None,
+			"account": doc.account if doc.account else None,
+			'party_type': 'Customer',
+			'party': [entry.customer],
+			'group_by': doc.group_by,
+			'currency': doc.currency,
+			'cost_center': [cc.cost_center_name for cc in doc.cost_center],
+			'project': [p.project_name for p in doc.project],
+			'show_opening_entries': 0,
+			'include_default_book_entries': 0,
+			'show_cancelled_entries': 1,
+			'tax_id': tax_id if tax_id else None
+		})
+		col, res = get_soa(filters)
+
+		for x in [0, -2, -1]:
+			res[x]['account'] = res[x]['account'].replace("'","")
+
+		if len(res) == 3:
+			continue
+		html = frappe.render_template(template_path, \
+			{"filters": filters, "data": res, "aging": aging[0] if doc.include_ageing else None})
+		html = frappe.render_template(base_template_path, {"body": html, \
+			"css": get_print_style(), "title": "Statement For " + entry.customer})
+		statement_dict[entry.customer] = html
+	if not bool(statement_dict):
+		return False
+	elif consolidated:
+		result = ''.join(list(statement_dict.values()))
+		return get_pdf(result, {'orientation': doc.orientation})
+	else:
+		for customer, statement_html in statement_dict.items():
+			statement_dict[customer]=get_pdf(statement_html, {'orientation': doc.orientation})
+		return statement_dict
+
+def get_customers_based_on_territory_or_customer_group(customer_collection, collection_name):
+	fields_dict = {
+		'Customer Group': 'customer_group',
+		'Territory': 'territory',
+	}
+	collection = frappe.get_doc(customer_collection, collection_name)
+	selected = [customer.name for customer in frappe.get_list(customer_collection, filters=[
+			['lft', '>=', collection.lft],
+			['rgt', '<=', collection.rgt]
+		],
+		fields=['name'],
+		order_by='lft asc, rgt desc'
+	)]
+	return frappe.get_list('Customer', fields=['name', 'email_id'], \
+		filters=[[fields_dict[customer_collection], 'IN', selected]])
+
+def get_customers_based_on_sales_person(sales_person):
+	lft, rgt = frappe.db.get_value("Sales Person",
+		sales_person, ["lft", "rgt"])
+	records = frappe.db.sql("""
+		select distinct parent, parenttype
+		from `tabSales Team` steam
+		where parenttype = 'Customer'
+			and exists(select name from `tabSales Person` where lft >= %s and rgt <= %s and name = steam.sales_person)
+	""", (lft, rgt), as_dict=1)
+	sales_person_records = frappe._dict()
+	for d in records:
+		sales_person_records.setdefault(d.parenttype, set()).add(d.parent)
+	customers = frappe.get_list('Customer', fields=['name', 'email_id'], \
+			filters=[['name', 'in', list(sales_person_records['Customer'])]])
+	return customers
+
+def get_recipients_and_cc(customer, doc):
+	recipients = []
+	for clist in doc.customers:
+		if clist.customer == customer:
+			recipients.append(clist.billing_email)
+			if doc.primary_mandatory and clist.primary_email:
+				recipients.append(clist.primary_email)
+	cc = []
+	if doc.cc_to != '':
+		try:
+			cc=[frappe.get_value('User', doc.cc_to, 'email')]
+		except:
+			pass
+
+	return recipients, cc
+
+def get_context(customer, doc):
+	template_doc = copy.deepcopy(doc)
+	del template_doc.customers
+	template_doc.from_date = format_date(template_doc.from_date)
+	template_doc.to_date = format_date(template_doc.to_date)
+	return {
+		'doc': template_doc,
+		'customer': frappe.get_doc('Customer', customer),
+		'frappe': frappe.utils
+	}
+
+@frappe.whitelist()
+def fetch_customers(customer_collection, collection_name, primary_mandatory):
+	customer_list = []
+	customers = []
+
+	if customer_collection == 'Sales Person':
+		customers = get_customers_based_on_sales_person(collection_name)
+		if not bool(customers):
+			frappe.throw('No Customers found with selected options.')
+	else:
+		if customer_collection == 'Sales Partner':
+			customers = frappe.get_list('Customer', fields=['name', 'email_id'], \
+				filters=[['default_sales_partner', '=', collection_name]])
+		else:
+			customers = get_customers_based_on_territory_or_customer_group(customer_collection, collection_name)
+
+	for customer in customers:
+		primary_email = customer.get('email_id') or ''
+		billing_email = get_customer_emails(customer.name, 1, billing_and_primary=False)
+
+		if billing_email == '' or (primary_email == '' and int(primary_mandatory)):
+			continue
+
+		customer_list.append({
+			'name': customer.name,
+			'primary_email': primary_email,
+			'billing_email': billing_email
+		})
+	return customer_list
+
+@frappe.whitelist()
+def get_customer_emails(customer_name, primary_mandatory, billing_and_primary=True):
+	billing_email = frappe.db.sql("""
+		SELECT c.email_id FROM `tabContact` AS c JOIN `tabDynamic Link` AS l ON c.name=l.parent \
+		WHERE l.link_doctype='Customer' and l.link_name='""" + customer_name + """' and \
+		c.is_billing_contact=1 \
+		order by c.creation desc""")
+
+	if len(billing_email) == 0 or (billing_email[0][0] is None):
+		if billing_and_primary:
+			frappe.throw('No billing email found for customer: '+ customer_name)
+		else:
+			return ''
+
+	if billing_and_primary:
+		primary_email =  frappe.get_value('Customer', customer_name, 'email_id')
+		if primary_email is None and int(primary_mandatory):
+			frappe.throw('No primary email found for customer: '+ customer_name)
+		return [primary_email or '', billing_email[0][0]]
+	else:
+		return billing_email[0][0] or ''
+
+@frappe.whitelist()
+def download_statements(document_name):
+	doc = frappe.get_doc('Process Statement Of Accounts', document_name)
+	report = get_report_pdf(doc)
+	if report:
+		frappe.local.response.filename = doc.name + '.pdf'
+		frappe.local.response.filecontent = report
+		frappe.local.response.type = "download"
+
+@frappe.whitelist()
+def send_emails(document_name, from_scheduler=False):
+	doc = frappe.get_doc('Process Statement Of Accounts', document_name)
+	report = get_report_pdf(doc, consolidated=False)
+
+	if report:
+		for customer, report_pdf in report.items():
+			attachments = [{
+				'fname': customer + '.pdf',
+				'fcontent': report_pdf
+			}]
+
+			recipients, cc = get_recipients_and_cc(customer, doc)
+			context = get_context(customer, doc)
+			subject = frappe.render_template(doc.subject, context)
+			message = frappe.render_template(doc.body, context)
+
+			frappe.enqueue(
+				queue='short',
+				method=frappe.sendmail,
+				recipients=recipients,
+				sender=frappe.session.user,
+				cc=cc,
+				subject=subject,
+				message=message,
+				now=True,
+				reference_doctype='Process Statement Of Accounts',
+				reference_name=document_name,
+				attachments=attachments
+			)
+
+		if doc.enable_auto_email and from_scheduler:
+			new_to_date = getdate(today())
+			if doc.frequency == 'Weekly':
+				new_to_date = add_days(new_to_date, 7)
+			else:
+				new_to_date = add_months(new_to_date, 1 if doc.frequency == 'Monthly' else 3)
+			new_from_date = add_months(new_to_date, -1 * doc.filter_duration)
+			doc.add_comment('Comment', 'Emails sent on: ' + frappe.utils.format_datetime(frappe.utils.now()))
+			doc.db_set('to_date', new_to_date, commit=True)
+			doc.db_set('from_date', new_from_date, commit=True)
+		return True
+	else:
+		return False
+
+@frappe.whitelist()
+def send_auto_email():
+	selected = frappe.get_list('Process Statement Of Accounts', filters={'to_date': format_date(today()), 'enable_auto_email': 1})
+	for entry in selected:
+		send_emails(entry.name, from_scheduler=True)
+	return True
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py
new file mode 100644
index 0000000..30efbb3
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestProcessStatementOfAccounts(unittest.TestCase):
+	pass
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts_customer/__init__.py b/erpnext/accounts/doctype/process_statement_of_accounts_customer/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts_customer/__init__.py
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json
new file mode 100644
index 0000000..dd04dc1
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json
@@ -0,0 +1,47 @@
+{
+ "actions": [],
+ "allow_workflow": 1,
+ "creation": "2020-08-03 16:35:21.852178",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "customer",
+  "billing_email",
+  "primary_email"
+ ],
+ "fields": [
+  {
+   "fieldname": "customer",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Customer",
+   "options": "Customer",
+   "reqd": 1
+  },
+  {
+   "fieldname": "primary_email",
+   "fieldtype": "Read Only",
+   "in_list_view": 1,
+   "label": "Primary Contact Email"
+  },
+  {
+   "fieldname": "billing_email",
+   "fieldtype": "Read Only",
+   "in_list_view": 1,
+   "label": "Billing Email"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-08-03 22:55:38.875601",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Process Statement Of Accounts Customer",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py
new file mode 100644
index 0000000..1a76010
--- /dev/null
+++ b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class ProcessStatementOfAccountsCustomer(Document):
+	pass
diff --git a/erpnext/accounts/doctype/psoa_cost_center/__init__.py b/erpnext/accounts/doctype/psoa_cost_center/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/psoa_cost_center/__init__.py
diff --git a/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.json b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.json
new file mode 100644
index 0000000..e292b60
--- /dev/null
+++ b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.json
@@ -0,0 +1,30 @@
+{
+ "actions": [],
+ "creation": "2020-08-03 16:56:45.744905",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "cost_center_name"
+ ],
+ "fields": [
+  {
+   "fieldname": "cost_center_name",
+   "fieldtype": "Link",
+   "label": "Cost Center",
+   "options": "Cost Center"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-08-03 16:56:45.744905",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "PSOA Cost Center",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py
new file mode 100644
index 0000000..0aeef3e
--- /dev/null
+++ b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PSOACostCenter(Document):
+	pass
diff --git a/erpnext/accounts/doctype/psoa_project/__init__.py b/erpnext/accounts/doctype/psoa_project/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/psoa_project/__init__.py
diff --git a/erpnext/accounts/doctype/psoa_project/psoa_project.json b/erpnext/accounts/doctype/psoa_project/psoa_project.json
new file mode 100644
index 0000000..20a03ee
--- /dev/null
+++ b/erpnext/accounts/doctype/psoa_project/psoa_project.json
@@ -0,0 +1,30 @@
+{
+ "actions": [],
+ "creation": "2020-08-03 16:52:14.731978",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "project_name"
+ ],
+ "fields": [
+  {
+   "fieldname": "project_name",
+   "fieldtype": "Link",
+   "label": "Project",
+   "options": "Project"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-08-03 16:53:39.219736",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "PSOA Project",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/psoa_project/psoa_project.py b/erpnext/accounts/doctype/psoa_project/psoa_project.py
new file mode 100644
index 0000000..f4a5dee
--- /dev/null
+++ b/erpnext/accounts/doctype/psoa_project/psoa_project.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PSOAProject(Document):
+	pass
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 2e91c8e..d62e73b 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -180,7 +180,7 @@
    "no_copy": 1,
    "oldfieldname": "naming_series",
    "oldfieldtype": "Select",
-   "options": "ACC-PINV-.YYYY.-",
+   "options": "ACC-PINV-.YYYY.-\nACC-PINV-RET-.YYYY.-",
    "print_hide": 1,
    "reqd": 1,
    "set_only_once": 1
@@ -1334,7 +1334,7 @@
  "idx": 204,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-08-03 12:46:01.411074",
+ "modified": "2020-08-03 23:20:04.466153",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice",
@@ -1396,4 +1396,4 @@
  "timeline_field": "supplier",
  "title_field": "title",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index 52a5be0..f6d76e5 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -1,5 +1,4 @@
 {
- "actions": [],
  "autoname": "hash",
  "creation": "2013-05-22 12:43:10",
  "doctype": "DocType",
@@ -82,6 +81,7 @@
   "item_tax_rate",
   "bom",
   "include_exploded_items",
+  "purchase_invoice_item",
   "col_break6",
   "purchase_order",
   "po_detail",
@@ -769,12 +769,21 @@
    "collapsible": 1,
    "fieldname": "col_break7",
    "fieldtype": "Column Break"
+  },
+  {
+   "depends_on": "eval:parent.update_stock == 1",
+   "fieldname": "purchase_invoice_item",
+   "fieldtype": "Data",
+   "ignore_user_permissions": 1,
+   "label": "Purchase Invoice Item",
+   "no_copy": 1,
+   "print_hide": 1,
+   "read_only": 1
   }
  ],
  "idx": 1,
  "istable": 1,
- "links": [],
- "modified": "2020-04-22 10:37:35.103176",
+ "modified": "2020-08-20 11:48:01.398356",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Purchase Invoice Item",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 4dc81e9..2397b7d 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -1,7 +1,6 @@
 {
  "actions": [],
  "allow_import": 1,
- "allow_workflow": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-24 19:29:05",
  "doctype": "DocType",
@@ -217,7 +216,7 @@
    "no_copy": 1,
    "oldfieldname": "naming_series",
    "oldfieldtype": "Select",
-   "options": "ACC-SINV-.YYYY.-",
+   "options": "ACC-SINV-.YYYY.-\nACC-SINV-RET-.YYYY.-",
    "print_hide": 1,
    "reqd": 1,
    "set_only_once": 1
@@ -448,7 +447,7 @@
   {
    "allow_on_submit": 1,
    "fieldname": "po_no",
-   "fieldtype": "Small Text",
+   "fieldtype": "Data",
    "hide_days": 1,
    "hide_seconds": 1,
    "label": "Customer's Purchase Order",
@@ -1947,7 +1946,7 @@
  "idx": 181,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-07-18 05:07:16.725974",
+ "modified": "2020-08-27 01:56:28.532140",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 3dab054..71f2e12 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1619,22 +1619,23 @@
 
 	for pos_payment_method in pos_profile.get('payments'):
 		pos_payment_method = pos_payment_method.as_dict()
-		
+
 		payment_mode = get_mode_of_payment_info(pos_payment_method.mode_of_payment, doc.company)
-		payment_mode[0].default = pos_payment_method.default
-		append_payment(payment_mode[0])
+		if payment_mode:
+			payment_mode[0].default = pos_payment_method.default
+			append_payment(payment_mode[0])
 
 def get_all_mode_of_payments(doc):
 	return frappe.db.sql("""
-		select mpa.default_account, mpa.parent, mp.type as type 
-		from `tabMode of Payment Account` mpa,`tabMode of Payment` mp 
+		select mpa.default_account, mpa.parent, mp.type as type
+		from `tabMode of Payment Account` mpa,`tabMode of Payment` mp
 		where mpa.parent = mp.name and mpa.company = %(company)s and mp.enabled = 1""",
 	{'company': doc.company}, as_dict=1)
 
 def get_mode_of_payment_info(mode_of_payment, company):
 	return frappe.db.sql("""
-		select mpa.default_account, mpa.parent, mp.type as type 
-		from `tabMode of Payment Account` mpa,`tabMode of Payment` mp 
+		select mpa.default_account, mpa.parent, mp.type as type
+		from `tabMode of Payment Account` mpa,`tabMode of Payment` mp
 		where mpa.parent = mp.name and mpa.company = %s and mp.enabled = 1 and mp.name = %s""",
 	(company, mode_of_payment), as_dict=1)
 
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
index f106928..2980213 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
@@ -13,7 +13,8 @@
 			'Auto Repeat': 'reference_document',
 		},
 		'internal_links': {
-			'Sales Order': ['items', 'sales_order']
+			'Sales Order': ['items', 'sales_order'],
+			'Delivery Note': ['items', 'delivery_note']
 		},
 		'transactions': [
 			{
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 964566a..9660c95 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -206,10 +206,19 @@
 			"rate": 14,
 			'included_in_print_rate': 1
 		})
+		si.append("taxes", {
+			"charge_type": "On Item Quantity",
+			"account_head": "_Test Account Education Cess - _TC",
+			"cost_center": "_Test Cost Center - _TC",
+			"description": "CESS",
+			"rate": 5,
+			'included_in_print_rate': 1
+		})
 		si.insert()
 
 		# with inclusive tax
-		self.assertEqual(si.net_total, 4385.96)
+		self.assertEqual(si.items[0].net_amount, 3947.368421052631)
+		self.assertEqual(si.net_total, 3947.37)
 		self.assertEqual(si.grand_total, 5000)
 
 		si.reload()
@@ -222,8 +231,8 @@
 		si.save()
 
 		# with inclusive tax and additional discount
-		self.assertEqual(si.net_total, 4285.96)
-		self.assertEqual(si.grand_total, 4885.99)
+		self.assertEqual(si.net_total, 3847.37)
+		self.assertEqual(si.grand_total, 4886)
 
 		si.reload()
 
@@ -235,7 +244,7 @@
 		si.save()
 
 		# with inclusive tax and additional discount
-		self.assertEqual(si.net_total, 4298.25)
+		self.assertEqual(si.net_total, 3859.65)
 		self.assertEqual(si.grand_total, 4900.00)
 
 	def test_sales_invoice_discount_amount(self):
diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
index 004d358..fb3dd6a 100644
--- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
+++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
@@ -1,5 +1,4 @@
 {
- "actions": [],
  "autoname": "hash",
  "creation": "2013-06-04 11:02:19",
  "doctype": "DocType",
@@ -87,6 +86,7 @@
   "edit_references",
   "sales_order",
   "so_detail",
+  "sales_invoice_item",
   "column_break_74",
   "delivery_note",
   "dn_detail",
@@ -790,12 +790,22 @@
    "fieldtype": "Link",
    "label": "Project",
    "options": "Project"
-  }
+  },
+  {
+    "depends_on": "eval:parent.update_stock == 1",
+    "fieldname": "sales_invoice_item",
+    "fieldtype": "Data",
+    "ignore_user_permissions": 1,
+    "label": "Sales Invoice Item",
+    "no_copy": 1,
+    "print_hide": 1,
+    "read_only": 1
+   }
  ],
  "idx": 1,
  "istable": 1,
  "links": [],
- "modified": "2020-07-18 12:24:41.749986",
+ "modified": "2020-08-20 11:24:41.749986",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Sales Invoice Item",
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py
index 0e9c808..d825c6f 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template_dashboard.py
@@ -8,7 +8,7 @@
 		'fieldname': 'taxes_and_charges',
 		'non_standard_fieldnames': {
 			'Tax Rule': 'sales_tax_template',
-			'Subscription': 'tax_template',
+			'Subscription': 'sales_tax_template',
 			'Restaurant': 'default_tax_template'
 		},
 		'transactions': [
diff --git a/erpnext/accounts/doctype/shipping_rule/shipping_rule.js b/erpnext/accounts/doctype/shipping_rule/shipping_rule.js
index 53ee08a..d0904ee 100644
--- a/erpnext/accounts/doctype/shipping_rule/shipping_rule.js
+++ b/erpnext/accounts/doctype/shipping_rule/shipping_rule.js
@@ -3,6 +3,22 @@
 
 frappe.ui.form.on('Shipping Rule', {
 	refresh: function(frm) {
+		frm.set_query("cost_center", function() {
+			return {
+				filters: {
+					company: frm.doc.company
+				}
+			}
+		})
+
+		frm.set_query("account", function() {
+			return {
+				filters: {
+					company: frm.doc.company
+				}
+			}
+		})
+
 		frm.trigger('toggle_reqd');
 	},
 	calculate_based_on: function(frm) {
@@ -12,4 +28,4 @@
 		frm.toggle_reqd("shipping_amount", frm.doc.calculate_based_on === 'Fixed');
 		frm.toggle_reqd("conditions", frm.doc.calculate_based_on !== 'Fixed');
 	}
-});
\ No newline at end of file
+});
diff --git a/erpnext/accounts/doctype/tax_category/tax_category.json b/erpnext/accounts/doctype/tax_category/tax_category.json
index 1e3ae45..6f682a0 100644
--- a/erpnext/accounts/doctype/tax_category/tax_category.json
+++ b/erpnext/accounts/doctype/tax_category/tax_category.json
@@ -1,134 +1,66 @@
 {
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
+ "actions": [],
+ "allow_rename": 1,
  "autoname": "field:title",
- "beta": 0,
  "creation": "2018-11-22 23:38:39.668804",
- "custom": 0,
- "docstatus": 0,
  "doctype": "DocType",
- "document_type": "",
  "editable_grid": 1,
  "engine": "InnoDB",
+ "field_order": [
+  "title"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "fieldname": "title",
    "fieldtype": "Data",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
-   "in_list_view": 0,
-   "in_standard_filter": 0,
    "label": "Title",
-   "length": 0,
-   "no_copy": 0,
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
-   "reqd": 0,
-   "search_index": 0,
-   "set_only_once": 0,
-   "translatable": 0,
    "unique": 1
   }
  ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2020-01-15 17:14:28.951793", 
+ "index_web_pages_for_search": 1,
+ "links": [],
+ "modified": "2020-08-30 19:41:25.783852",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Tax Category",
- "name_case": "",
  "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0,
-   "cancel": 0,
    "create": 1,
    "delete": 1,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "System Manager",
-   "set_user_permissions": 0,
    "share": 1,
-   "submit": 0,
    "write": 1
   },
   {
-   "amend": 0,
-   "cancel": 0,
    "create": 1,
    "delete": 1,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "Accounts Manager",
-   "set_user_permissions": 0,
    "share": 1,
-   "submit": 0,
    "write": 1
   },
   {
-   "amend": 0,
-   "cancel": 0,
-   "create": 0,
-   "delete": 0,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "Accounts User",
-   "set_user_permissions": 0,
-   "share": 1,
-   "submit": 0,
-   "write": 0
+   "share": 1
   }
  ],
  "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
  "sort_field": "modified",
  "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 28a6519..2f800bb 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -611,7 +611,7 @@
 			cond = "posting_date <= '{0}'".format(posting_date)
 
 	if company:
-		cond += "and company = '{0}'".format(company)
+		cond += "and company = {0}".format(frappe.db.escape(company))
 
 	data = frappe.db.sql(""" SELECT party, sum({0}) as amount
 		FROM `tabGL Entry`
diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
index c2c7207..219871b 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
@@ -378,7 +378,7 @@
 		if filters and filters.get('presentation_currency') != d.default_currency:
 			currency_info['company'] = d.name
 			currency_info['company_currency'] = d.default_currency
-			convert_to_presentation_currency(gl_entries, currency_info)
+			convert_to_presentation_currency(gl_entries, currency_info, filters.get('company'))
 
 		for entry in gl_entries:
 			key = entry.account_number or entry.account_name
diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
index 2cb10b1..10b32fe 100644
--- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
+++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
@@ -173,7 +173,7 @@
 			from `tabGL Entry` gle
 			{join}
 			where
-				gle.docstatus < 2 and gle.party_type=%(party_type)s and ifnull(gle.party, '') != ''
+				gle.docstatus < 2 and gle.is_cancelled = 0 and gle.party_type=%(party_type)s and ifnull(gle.party, '') != ''
 				and gle.posting_date <= %(to_date)s {conditions}
 			order by gle.posting_date
 		""".format(join=join, join_field=join_field, conditions=conditions), self.filters, as_dict=True)
@@ -248,7 +248,7 @@
 			from
 				`tabGL Entry`
 			where
-				docstatus < 2
+				docstatus < 2 and is_cancelled = 0
 				and (voucher_type, voucher_no) in (
 					select voucher_type, voucher_no from `tabGL Entry` gle, `tabAccount` acc
 					where acc.name = gle.account and acc.account_type = '{income_or_expense}'
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index 3785ebf..1b65a31 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -14,7 +14,7 @@
 from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
 from erpnext.accounts.utils import get_fiscal_year
 from frappe import _
-from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate, cstr)
+from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate, cstr, cint)
 
 from six import itervalues
 from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children
@@ -46,7 +46,7 @@
 	start_date = year_start_date
 	months = get_months(year_start_date, year_end_date)
 
-	for i in range(math.ceil(months / months_to_add)):
+	for i in range(cint(math.ceil(months / months_to_add))):
 		period = frappe._dict({
 			"from_date": start_date
 		})
@@ -423,7 +423,7 @@
 				distributed_cost_center_query=distributed_cost_center_query), gl_filters, as_dict=True) #nosec
 
 		if filters and filters.get('presentation_currency'):
-			convert_to_presentation_currency(gl_entries, get_currency(filters))
+			convert_to_presentation_currency(gl_entries, get_currency(filters), filters.get('company'))
 
 		for entry in gl_entries:
 			gl_entries_by_account.setdefault(entry.account, []).append(entry)
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js
index 1fc0f79..fb0d359 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.js
+++ b/erpnext/accounts/report/general_ledger/general_ledger.js
@@ -147,6 +147,12 @@
 			}
 		},
 		{
+			"fieldname": "include_dimensions",
+			"label": __("Consider Accounting Dimensions"),
+			"fieldtype": "Check",
+			"default": 0
+		},
+		{
 			"fieldname": "show_opening_entries",
 			"label": __("Show Opening Entries"),
 			"fieldtype": "Check"
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index fcd36e4..0599707 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -106,15 +106,20 @@
 	return filters
 
 def get_result(filters, account_details):
-	gl_entries = get_gl_entries(filters)
+	accounting_dimensions = []
+	if filters.get("include_dimensions"):
+		accounting_dimensions = get_accounting_dimensions()
 
-	data = get_data_with_opening_closing(filters, account_details, gl_entries)
+	gl_entries = get_gl_entries(filters, accounting_dimensions)
+
+	data = get_data_with_opening_closing(filters, account_details,
+		accounting_dimensions, gl_entries)
 
 	result = get_result_as_list(data, filters)
 
 	return result
 
-def get_gl_entries(filters):
+def get_gl_entries(filters, accounting_dimensions):
 	currency_map = get_currency(filters)
 	select_fields = """, debit, credit, debit_in_account_currency,
 		credit_in_account_currency """
@@ -128,6 +133,10 @@
 		filters['company_fb'] = frappe.db.get_value("Company",
 			filters.get("company"), 'default_finance_book')
 
+	dimension_fields = ""
+	if accounting_dimensions:
+		dimension_fields = ', '.join(accounting_dimensions) + ','
+
 	distributed_cost_center_query = ""
 	if filters and filters.get('cost_center'):
 		select_fields_with_percentage = """, debit*(DCC_allocation.percentage_allocation/100) as debit, credit*(DCC_allocation.percentage_allocation/100) as credit, debit_in_account_currency*(DCC_allocation.percentage_allocation/100) as debit_in_account_currency,
@@ -141,7 +150,7 @@
 			party_type,
 			party,
 			voucher_type,
-			voucher_no,
+			voucher_no, {dimension_fields}
 			cost_center, project,
 			against_voucher_type,
 			against_voucher,
@@ -160,13 +169,14 @@
 		{conditions}
 		AND posting_date <= %(to_date)s
 		AND cost_center = DCC_allocation.parent
-		""".format(select_fields_with_percentage=select_fields_with_percentage, conditions=get_conditions(filters).replace("and cost_center in %(cost_center)s ", ''))
+		""".format(dimension_fields=dimension_fields,select_fields_with_percentage=select_fields_with_percentage, conditions=get_conditions(filters).replace("and cost_center in %(cost_center)s ", ''))
 
 	gl_entries = frappe.db.sql(
 		"""
 		select
 			name as gl_entry, posting_date, account, party_type, party,
-			voucher_type, voucher_no, cost_center, project,
+			voucher_type, voucher_no, {dimension_fields}
+			cost_center, project,
 			against_voucher_type, against_voucher, account_currency,
 			remarks, against, is_opening, creation {select_fields}
 		from `tabGL Entry`
@@ -174,13 +184,13 @@
 		{distributed_cost_center_query}
 		{order_by_statement}
 		""".format(
-			select_fields=select_fields, conditions=get_conditions(filters), distributed_cost_center_query=distributed_cost_center_query,
+			dimension_fields=dimension_fields, select_fields=select_fields, conditions=get_conditions(filters), distributed_cost_center_query=distributed_cost_center_query,
 			order_by_statement=order_by_statement
 		),
 		filters, as_dict=1)
 
 	if filters.get('presentation_currency'):
-		return convert_to_presentation_currency(gl_entries, currency_map)
+		return convert_to_presentation_currency(gl_entries, currency_map, filters.get('company'))
 	else:
 		return gl_entries
 
@@ -247,12 +257,12 @@
 	return "and {}".format(" and ".join(conditions)) if conditions else ""
 
 
-def get_data_with_opening_closing(filters, account_details, gl_entries):
+def get_data_with_opening_closing(filters, account_details, accounting_dimensions, gl_entries):
 	data = []
 
 	gle_map = initialize_gle_map(gl_entries, filters)
 
-	totals, entries = get_accountwise_gle(filters, gl_entries, gle_map)
+	totals, entries = get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map)
 
 	# Opening for filtered account
 	data.append(totals.opening)
@@ -318,7 +328,7 @@
 	return gle_map
 
 
-def get_accountwise_gle(filters, gl_entries, gle_map):
+def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map):
 	totals = get_totals_dict()
 	entries = []
 	consolidated_gle = OrderedDict()
@@ -350,8 +360,11 @@
 			if filters.get("group_by") != _('Group by Voucher (Consolidated)'):
 				gle_map[gle.get(group_by)].entries.append(gle)
 			elif filters.get("group_by") == _('Group by Voucher (Consolidated)'):
-				key = (gle.get("voucher_type"), gle.get("voucher_no"),
-					gle.get("account"), gle.get("cost_center"))
+				keylist = [gle.get("voucher_type"), gle.get("voucher_no"), gle.get("account")]
+				for dim in accounting_dimensions:
+					keylist.append(gle.get(dim))
+				keylist.append(gle.get("cost_center"))
+				key = tuple(keylist)
 				if key not in consolidated_gle:
 					consolidated_gle.setdefault(key, gle)
 				else:
@@ -478,7 +491,19 @@
 			"options": "Project",
 			"fieldname": "project",
 			"width": 100
-		},
+		}
+	])
+
+	if filters.get("include_dimensions"):
+		for dim in get_accounting_dimensions(as_list = False):
+			columns.append({
+				"label": _(dim.label),
+				"options": dim.label,
+				"fieldname": dim.fieldname,
+				"width": 100
+			})
+
+	columns.extend([
 		{
 			"label": _("Cost Center"),
 			"options": "Cost Center",
diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py
index 4a9af49..9de8d19 100644
--- a/erpnext/accounts/report/utils.py
+++ b/erpnext/accounts/report/utils.py
@@ -6,10 +6,6 @@
 from frappe.utils import cint, get_datetime_str, formatdate, flt
 
 __exchange_rates = {}
-P_OR_L_ACCOUNTS = list(
-	sum(frappe.get_list('Account', fields=['name'], or_filters=[{'root_type': 'Income'}, {'root_type': 'Expense'}], as_list=True), ())
-)
-
 
 def get_currency(filters):
 	"""
@@ -73,18 +69,7 @@
 
 	return rate
 
-
-def is_p_or_l_account(account_name):
-	"""
-	Check if the given `account name` is an `Account` with `root_type` of either 'Income'
-	or 'Expense'.
-	:param account_name:
-	:return: Boolean
-	"""
-	return account_name in P_OR_L_ACCOUNTS
-
-
-def convert_to_presentation_currency(gl_entries, currency_info):
+def convert_to_presentation_currency(gl_entries, currency_info, company):
 	"""
 	Take a list of GL Entries and change the 'debit' and 'credit' values to currencies
 	in `currency_info`.
@@ -96,6 +81,9 @@
 	presentation_currency = currency_info['presentation_currency']
 	company_currency = currency_info['company_currency']
 
+	pl_accounts = [d.name for d in frappe.get_list('Account',
+		filters={'report_type': 'Profit and Loss', 'company': company})]
+
 	for entry in gl_entries:
 		account = entry['account']
 		debit = flt(entry['debit'])
@@ -107,7 +95,7 @@
 		if account_currency != presentation_currency:
 			value = debit or credit
 
-			date = currency_info['report_date'] if not is_p_or_l_account(account) else entry['posting_date']
+			date = entry['posting_date'] if account in pl_accounts else currency_info['report_date']
 			converted_value = convert(value, presentation_currency, company_currency, date)
 
 			if entry.get('debit'):
diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py
index 148357f..34facd8 100644
--- a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py
+++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.py
@@ -11,7 +11,7 @@
 
 class AssetMaintenanceLog(Document):
 	def validate(self):
-		if getdate(self.due_date) < getdate(nowdate()):
+		if getdate(self.due_date) < getdate(nowdate()) and self.maintenance_status not in ["Completed", "Cancelled"]:
 			self.maintenance_status = "Overdue"
 
 		if self.maintenance_status == "Completed" and not self.completion_date:
diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_list.js b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_list.js
index b854413..23000e6 100644
--- a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_list.js
+++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log_list.js
@@ -1,14 +1,15 @@
 frappe.listview_settings['Asset Maintenance Log'] = {
 	add_fields: ["maintenance_status"],
+	has_indicator_for_draft: 1,
 	get_indicator: function(doc) {
-		if(doc.maintenance_status=="Pending") {
-			return [__("Pending"), "orange"];
-		} else if(doc.maintenance_status=="Completed") {
-			return [__("Completed"), "green"];
-		} else if(doc.maintenance_status=="Cancelled") {
-			return [__("Cancelled"), "red"];
-		} else if(doc.maintenance_status=="Overdue") {
-			return [__("Overdue"), "red"];
+		if (doc.maintenance_status=="Planned") {
+			return [__(doc.maintenance_status), "orange", "status,=," + doc.maintenance_status];
+		} else if (doc.maintenance_status=="Completed") {
+			return [__(doc.maintenance_status), "green", "status,=," + doc.maintenance_status];
+		} else if (doc.maintenance_status=="Cancelled") {
+			return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status];
+		} else if (doc.maintenance_status=="Overdue") {
+			return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status];
 		}
 	}
 };
diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
index 155597e..fd702c7 100644
--- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
+++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
@@ -8,6 +8,7 @@
 from frappe.utils import flt, getdate, cint, date_diff, formatdate
 from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
 from frappe.model.document import Document
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts
 
 class AssetValueAdjustment(Document):
 	def validate(self):
@@ -53,17 +54,33 @@
 		je.company = self.company
 		je.remark = "Depreciation Entry against {0} worth {1}".format(self.asset, self.difference_amount)
 
-		je.append("accounts", {
+		credit_entry = {
 			"account": accumulated_depreciation_account,
 			"credit_in_account_currency": self.difference_amount,
 			"cost_center": depreciation_cost_center or self.cost_center
-		})
+		}
 
-		je.append("accounts", {
+		debit_entry = {
 			"account": depreciation_expense_account,
 			"debit_in_account_currency": self.difference_amount,
 			"cost_center": depreciation_cost_center or self.cost_center
-		})
+		}
+
+		accounting_dimensions = get_checks_for_pl_and_bs_accounts()
+
+		for dimension in accounting_dimensions:
+			if dimension.get('mandatory_for_bs'):
+				credit_entry.update({
+					dimension['fieldname']: self.get(dimension['fieldname']) or dimension.get('default_dimension')
+				})
+
+			if dimension.get('mandatory_for_pl'):
+				debit_entry.update({
+					dimension['fieldname']: self.get(dimension['fieldname']) or dimension.get('default_dimension')
+				})
+		
+		je.append("accounts", credit_entry)
+		je.append("accounts", debit_entry)
 
 		je.flags.ignore_permissions = True
 		je.submit()
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 25065ab..9f2b971 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -94,7 +94,7 @@
 				if(this.frm.doc.status !== 'Closed' && flt(this.frm.doc.per_received) < 100 && flt(this.frm.doc.per_billed) < 100) {
 					this.frm.add_custom_button(__('Update Items'), () => {
 						erpnext.utils.update_child_items({
-							frm: frm,
+							frm: this.frm,
 							child_docname: "items",
 							child_doctype: "Purchase Order Detail",
 							cannot_add_row: false,
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 89c38c7..d61e44b 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -325,7 +325,7 @@
 				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):
+			for pricing_rule in get_applied_pricing_rules(item.get('pricing_rules')):
 				pricing_rule_doc = frappe.get_cached_doc("Pricing Rule", pricing_rule)
 				for field in ['discount_percentage', 'discount_amount', 'rate']:
 					if item.get(field) < pricing_rule_doc.get(field):
@@ -479,7 +479,11 @@
 			if d.against_order:
 				allocated_amount = flt(d.amount)
 			else:
-				amount = self.rounded_total or self.grand_total
+				if self.get('party_account_currency') == self.company_currency:
+					amount = self.get('base_rounded_total') or self.base_grand_total
+				else:
+					amount = self.get('rounded_total') or self.grand_total
+
 				allocated_amount = min(amount - advance_allocated, d.amount)
 			advance_allocated += flt(allocated_amount)
 
@@ -802,10 +806,22 @@
 			self.payment_terms_template = ''
 			return
 
+		party_account_currency = self.get('party_account_currency')
+		if not party_account_currency:
+			party_type, party = self.get_party()
+
+			if party_type and party:
+				party_account_currency = get_party_account_currency(party_type, party, self.company)
+
 		posting_date = self.get("bill_date") or self.get("posting_date") or self.get("transaction_date")
 		date = self.get("due_date")
 		due_date = date or posting_date
-		grand_total = self.get("rounded_total") or self.grand_total
+
+		if party_account_currency == self.company_currency:
+			grand_total = self.get("base_rounded_total") or self.base_grand_total
+		else:
+			grand_total = self.get("rounded_total") or self.grand_total
+
 		if self.doctype in ("Sales Invoice", "Purchase Invoice"):
 			grand_total = grand_total - flt(self.write_off_amount)
 
@@ -850,13 +866,25 @@
 	def validate_payment_schedule_amount(self):
 		if self.doctype == 'Sales Invoice' and self.is_pos: return
 
+		party_account_currency = self.get('party_account_currency')
+		if not party_account_currency:
+			party_type, party = self.get_party()
+
+			if party_type and party:
+				party_account_currency = get_party_account_currency(party_type, party, self.company)
+
 		if self.get("payment_schedule"):
 			total = 0
 			for d in self.get("payment_schedule"):
 				total += flt(d.payment_amount)
-			total = flt(total, self.precision("grand_total"))
 
-			grand_total = flt(self.get("rounded_total") or self.grand_total, self.precision('grand_total'))
+			if party_account_currency == self.company_currency:
+				total = flt(total, self.precision("base_grand_total"))
+				grand_total = flt(self.get("base_rounded_total") or self.base_grand_total, self.precision('base_grand_total'))
+			else:
+				total = flt(total, self.precision("grand_total"))
+				grand_total = flt(self.get("rounded_total") or self.grand_total, self.precision('grand_total'))
+
 			if self.get("total_advance"):
 				grand_total -= self.get("total_advance")
 
@@ -957,7 +985,7 @@
 			# all rows about the reffered tax should be inclusive
 			_on_previous_row_error("1 - %d" % (tax.row_id,))
 		elif tax.get("category") == "Valuation":
-			frappe.throw(_("Valuation type charges can not marked as Inclusive"))
+			frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
 
 
 def set_balance_in_account_currency(gl_dict, account_currency=None, conversion_rate=None, company_currency=None):
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 89b48f0..ac567b7 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -276,6 +276,9 @@
 		qty_to_be_received_map = get_qty_to_be_received(purchase_orders)
 
 		for item in self.get('items'):
+			if not item.purchase_order:
+				continue
+
 			# reset raw_material cost
 			item.rm_supp_cost = 0
 
@@ -288,6 +291,12 @@
 
 			fg_yet_to_be_received = qty_to_be_received_map.get(item_key)
 
+			if not fg_yet_to_be_received:
+				frappe.throw(_("Row #{0}: Item {1} is already fully received in Purchase Order {2}")
+					.format(item.idx, frappe.bold(item.item_code),
+						frappe.utils.get_link_to_form("Purchase Order", item.purchase_order)),
+					title=_("Limit Crossed"))
+
 			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)
 
@@ -559,9 +568,19 @@
 						"serial_no": cstr(d.serial_no).strip()
 					})
 					if self.is_return:
-						original_incoming_rate = frappe.db.get_value("Stock Ledger Entry",
-							{"voucher_type": "Purchase Receipt", "voucher_no": self.return_against,
-							"item_code": d.item_code}, "incoming_rate")
+						filters = {
+							"voucher_type": self.doctype,
+							"voucher_no": self.return_against,
+							"item_code": d.item_code
+						}
+
+						if (self.doctype == "Purchase Invoice" and self.update_stock
+							and d.get("purchase_invoice_item")):
+							filters["voucher_detail_no"] = d.purchase_invoice_item
+						elif self.doctype == "Purchase Receipt" and d.get("purchase_receipt_item"):
+							filters["voucher_detail_no"] = d.purchase_receipt_item
+
+						original_incoming_rate = frappe.db.get_value("Stock Ledger Entry", filters, "incoming_rate")
 
 						sle.update({
 							"outgoing_rate": original_incoming_rate
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index babc5bd..c88bf66 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -497,24 +497,18 @@
 	conditions, bin_conditions = [], []
 	filter_dict = get_doctype_wise_filters(filters)
 
-	sub_query = """ select round(`tabBin`.actual_qty, 2) from `tabBin`
-		where `tabBin`.warehouse = `tabWarehouse`.name
-		{bin_conditions} """.format(
-		bin_conditions=get_filters_cond(doctype, filter_dict.get("Bin"),
-			bin_conditions, ignore_permissions=True))
-
 	query = """select `tabWarehouse`.name,
-		CONCAT_WS(" : ", "Actual Qty", ifnull( ({sub_query}), 0) ) as actual_qty
-		from `tabWarehouse`
+		CONCAT_WS(" : ", "Actual Qty", ifnull(round(`tabBin`.actual_qty, 2), 0 )) actual_qty
+		from `tabWarehouse` left join `tabBin`
+		on `tabBin`.warehouse = `tabWarehouse`.name {bin_conditions}
 		where
-		   `tabWarehouse`.`{key}` like {txt}
+			`tabWarehouse`.`{key}` like {txt}
 			{fcond} {mcond}
-		order by
-			`tabWarehouse`.name desc
+		order by ifnull(`tabBin`.actual_qty, 0) desc
 		limit
 			{start}, {page_len}
 		""".format(
-			sub_query=sub_query,
+			bin_conditions=get_filters_cond(doctype, filter_dict.get("Bin"),bin_conditions, ignore_permissions=True),
 			key=searchfield,
 			fcond=get_filters_cond(doctype, filter_dict.get("Warehouse"), conditions),
 			mcond=get_match_cond(doctype),
@@ -613,9 +607,12 @@
 	if not taxes:
 		return frappe.db.sql(""" SELECT name FROM `tabItem Tax Template` """)
 	else:
+		valid_from = filters.get('valid_from')
+		valid_from = valid_from[1] if isinstance(valid_from, list) else valid_from
+
 		args = {
 			'item_code': filters.get('item_code'),
-			'posting_date': filters.get('valid_from'),
+			'posting_date': valid_from,
 			'tax_category': filters.get('tax_category'),
 			'company': filters.get('company')
 		}
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index 3f127a2..a03dee1 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -281,6 +281,8 @@
 			target_doc.rejected_warehouse = source_doc.rejected_warehouse
 			target_doc.po_detail = source_doc.po_detail
 			target_doc.pr_detail = source_doc.pr_detail
+			target_doc.purchase_invoice_item = source_doc.name
+
 		elif doctype == "Delivery Note":
 			target_doc.against_sales_order = source_doc.against_sales_order
 			target_doc.against_sales_invoice = source_doc.against_sales_invoice
@@ -296,6 +298,7 @@
 			target_doc.so_detail = source_doc.so_detail
 			target_doc.dn_detail = source_doc.dn_detail
 			target_doc.expense_account = source_doc.expense_account
+			target_doc.sales_invoice_item = source_doc.name
 			if default_warehouse_for_sales_return:
 				target_doc.warehouse = default_warehouse_for_sales_return
 
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index b696ac3..17f3ae5 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -217,7 +217,9 @@
 							'target_warehouse': p.target_warehouse,
 							'company': self.company,
 							'voucher_type': self.doctype,
-							'allow_zero_valuation': d.allow_zero_valuation_rate
+							'allow_zero_valuation': d.allow_zero_valuation_rate,
+							'sales_invoice_item': d.get("sales_invoice_item"),
+							'delivery_note_item': d.get("dn_detail")
 						}))
 			else:
 				il.append(frappe._dict({
@@ -233,7 +235,9 @@
 					'target_warehouse': d.target_warehouse,
 					'company': self.company,
 					'voucher_type': self.doctype,
-					'allow_zero_valuation': d.allow_zero_valuation_rate
+					'allow_zero_valuation': d.allow_zero_valuation_rate,
+					'sales_invoice_item': d.get("sales_invoice_item"),
+					'delivery_note_item': d.get("dn_detail")
 				}))
 		return il
 
@@ -302,7 +306,11 @@
 					d.conversion_factor = get_conversion_factor(d.item_code, d.uom).get("conversion_factor") or 1.0
 				return_rate = 0
 				if cint(self.is_return) and self.return_against and self.docstatus==1:
-					return_rate = self.get_incoming_rate_for_return(d.item_code, self.return_against)
+					against_document_no = (d.get("sales_invoice_item")
+						if self.doctype == "Sales Invoice" else d.get("delivery_note_item"))
+
+					return_rate = self.get_incoming_rate_for_return(d.item_code,
+						self.return_against, against_document_no)
 
 				# On cancellation or if return entry submission, make stock ledger entry for
 				# target warehouse first, to update serial no values properly
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index e8483da..394883d 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -301,14 +301,19 @@
 
 		return serialized_items
 
-	def get_incoming_rate_for_return(self, item_code, against_document):
+	def get_incoming_rate_for_return(self, item_code, against_document, against_document_no=None):
 		incoming_rate = 0.0
+		cond = ''
 		if against_document and item_code:
+			if against_document_no:
+				cond = " and voucher_detail_no = %s" %(frappe.db.escape(against_document_no))
+
 			incoming_rate = frappe.db.sql("""select abs(stock_value_difference / actual_qty)
 				from `tabStock Ledger Entry`
 				where voucher_type = %s and voucher_no = %s
-					and item_code = %s limit 1""",
+					and item_code = %s {0} limit 1""".format(cond),
 				(self.doctype, against_document, item_code))
+
 			incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0
 
 		return incoming_rate
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 572e1ca..92cfdb7 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -9,6 +9,7 @@
 from erpnext.controllers.accounts_controller import validate_conversion_rate, \
 	validate_taxes_and_charges, validate_inclusive_tax
 from erpnext.stock.get_item_details import _get_item_tax_template
+from erpnext.accounts.doctype.pricing_rule.utils import get_applied_pricing_rules
 
 class calculate_taxes_and_totals(object):
 	def __init__(self, doc):
@@ -161,8 +162,9 @@
 		for item in self.doc.get("items"):
 			item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
 			cumulated_tax_fraction = 0
+			total_inclusive_tax_amount_per_qty = 0
 			for i, tax in enumerate(self.doc.get("taxes")):
-				tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax, item_tax_map)
+				tax.tax_fraction_for_current_item, inclusive_tax_amount_per_qty = self.get_current_tax_fraction(tax, item_tax_map)
 
 				if i==0:
 					tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item
@@ -172,9 +174,12 @@
 						+ tax.tax_fraction_for_current_item
 
 				cumulated_tax_fraction += tax.tax_fraction_for_current_item
+				total_inclusive_tax_amount_per_qty += inclusive_tax_amount_per_qty * flt(item.qty)
 
-			if cumulated_tax_fraction and not self.discount_amount_applied and item.qty:
-				item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction))
+			if not self.discount_amount_applied and item.qty and (cumulated_tax_fraction or total_inclusive_tax_amount_per_qty):
+				amount = flt(item.amount) - total_inclusive_tax_amount_per_qty
+
+				item.net_amount = flt(amount / (1 + cumulated_tax_fraction))
 				item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate"))
 				item.discount_percentage = flt(item.discount_percentage,
 					item.precision("discount_percentage"))
@@ -190,6 +195,7 @@
 			from tax inclusive amount
 		"""
 		current_tax_fraction = 0
+		inclusive_tax_amount_per_qty = 0
 
 		if cint(tax.included_in_print_rate):
 			tax_rate = self._get_tax_rate(tax, item_tax_map)
@@ -205,9 +211,14 @@
 				current_tax_fraction = (tax_rate / 100.0) * \
 					self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
 
-		if getattr(tax, "add_deduct_tax", None):
-			current_tax_fraction *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
-		return current_tax_fraction
+			elif tax.charge_type == "On Item Quantity":
+				inclusive_tax_amount_per_qty = flt(tax_rate)
+
+		if getattr(tax, "add_deduct_tax", None) and tax.add_deduct_tax == "Deduct":
+			current_tax_fraction *= -1.0
+			inclusive_tax_amount_per_qty *= -1.0
+
+		return current_tax_fraction, inclusive_tax_amount_per_qty
 
 	def _get_tax_rate(self, tax, item_tax_map):
 		if tax.account_head in item_tax_map:
@@ -321,7 +332,7 @@
 			current_tax_amount = (tax_rate / 100.0) * \
 				self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_for_current_item
 		elif tax.charge_type == "On Item Quantity":
-			current_tax_amount = tax_rate * item.stock_qty
+			current_tax_amount = tax_rate * item.qty
 
 		self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount)
 
@@ -472,7 +483,7 @@
 			actual_taxes_dict = {}
 
 			for tax in self.doc.get("taxes"):
-				if tax.charge_type == "Actual":
+				if tax.charge_type in ["Actual", "On Item Quantity"]:
 					tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(tax.tax_amount, tax)
 					actual_taxes_dict.setdefault(tax.idx, tax_amount)
 				elif tax.row_id in actual_taxes_dict:
@@ -597,7 +608,7 @@
 		base_rate_with_margin = 0.0
 		if item.price_list_rate:
 			if item.pricing_rules and not self.doc.ignore_pricing_rule:
-				for d in json.loads(item.pricing_rules):
+				for d in get_applied_pricing_rules(item.pricing_rules):
 					pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
 
 					if (pricing_rule.margin_type == 'Amount' and pricing_rule.currency == self.doc.currency)\
diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json
index 545e232..b61cad3 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.json
+++ b/erpnext/crm/doctype/opportunity/opportunity.json
@@ -16,6 +16,7 @@
   "opportunity_from",
   "party_name",
   "customer_name",
+  "source",
   "column_break0",
   "title",
   "opportunity_type",
@@ -49,10 +50,9 @@
   "contact_email",
   "contact_mobile",
   "more_info",
-  "source",
+  "company",
   "campaign",
   "column_break1",
-  "company",
   "transaction_date",
   "amended_from",
   "lost_reasons"
@@ -344,7 +344,7 @@
    "collapsible": 1,
    "fieldname": "more_info",
    "fieldtype": "Section Break",
-   "label": "Source",
+   "label": "More Information",
    "oldfieldtype": "Section Break",
    "options": "fa fa-file-text"
   },
@@ -411,7 +411,7 @@
    "fieldname": "lost_reasons",
    "fieldtype": "Table MultiSelect",
    "label": "Lost Reasons",
-   "options": "Lost Reason Detail",
+   "options": "Opportunity Lost Reason Detail",
    "read_only": 1
   },
   {
@@ -424,7 +424,7 @@
  "icon": "fa fa-info-sign",
  "idx": 195,
  "links": [],
- "modified": "2020-07-14 16:49:15.888503",
+ "modified": "2020-08-11 17:34:35.066961",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Opportunity",
diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py
index 1b071ea..6096053 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.py
+++ b/erpnext/crm/doctype/opportunity/opportunity.py
@@ -119,11 +119,19 @@
 				and q.status not in ('Lost', 'Closed')""", self.name)
 
 	def has_ordered_quotation(self):
-		return frappe.db.sql("""
-			select q.name
-			from `tabQuotation` q, `tabQuotation Item` qi
-			where q.name = qi.parent and q.docstatus=1 and qi.prevdoc_docname =%s
-			and q.status = 'Ordered'""", self.name)
+		if not self.with_items:
+			return frappe.get_all('Quotation',
+				{
+					'opportunity': self.name,
+					'status': 'Ordered',
+					'docstatus': 1
+				}, 'name')
+		else:
+			return frappe.db.sql("""
+				select q.name
+				from `tabQuotation` q, `tabQuotation Item` qi
+				where q.name = qi.parent and q.docstatus=1 and qi.prevdoc_docname =%s
+				and q.status = 'Ordered'""", self.name)
 
 	def has_lost_quotation(self):
 		lost_quotation = frappe.db.sql("""
@@ -317,7 +325,7 @@
 		doc.save()
 
 @frappe.whitelist()
-def make_opportunity_from_communication(communication, ignore_communication_links=False):
+def make_opportunity_from_communication(communication, company, ignore_communication_links=False):
 	from erpnext.crm.doctype.lead.lead import make_lead_from_communication
 	doc = frappe.get_doc("Communication", communication)
 
@@ -329,8 +337,9 @@
 
 	opportunity = frappe.get_doc({
 		"doctype": "Opportunity",
+		"company": company,
 		"opportunity_from": opportunity_from,
-		"lead": lead
+		"party_name": lead
 	}).insert(ignore_permissions=True)
 
 	link_communication_to_document(doc, "Opportunity", opportunity.name, ignore_communication_links)
diff --git a/erpnext/crm/doctype/opportunity_lost_reason_detail/__init__.py b/erpnext/crm/doctype/opportunity_lost_reason_detail/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/crm/doctype/opportunity_lost_reason_detail/__init__.py
diff --git a/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.json b/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.json
new file mode 100644
index 0000000..50620e2
--- /dev/null
+++ b/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.json
@@ -0,0 +1,31 @@
+{
+ "actions": [],
+ "creation": "2020-07-16 16:11:39.830389",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "lost_reason"
+ ],
+ "fields": [
+  {
+   "fieldname": "lost_reason",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Opportunity Lost Reason",
+   "options": "Opportunity Lost Reason"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-07-26 17:58:26.313242",
+ "modified_by": "Administrator",
+ "module": "CRM",
+ "name": "Opportunity Lost Reason Detail",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.py b/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.py
new file mode 100644
index 0000000..8723f1d
--- /dev/null
+++ b/erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class OpportunityLostReasonDetail(Document):
+	pass
diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.js b/erpnext/crm/doctype/social_media_post/social_media_post.js
index 3a14f2d..0ce8b44 100644
--- a/erpnext/crm/doctype/social_media_post/social_media_post.js
+++ b/erpnext/crm/doctype/social_media_post/social_media_post.js
@@ -30,14 +30,14 @@
                 let color = frm.doc.twitter_post_id ? "green" : "red";
                 let status = frm.doc.twitter_post_id ? "Posted" : "Not Posted";
                 html += `<div class="col-xs-6">
-                            <span class="indicator whitespace-nowrap ${color}"><span class="hidden-xs">Twitter : ${status} </span></span>
+                            <span class="indicator whitespace-nowrap ${color}"><span>Twitter : ${status} </span></span>
                         </div>` ;
             }
             if (frm.doc.linkedin){
                 let color = frm.doc.linkedin_post_id ? "green" : "red";
                 let status = frm.doc.linkedin_post_id ? "Posted" : "Not Posted";
                 html += `<div class="col-xs-6">
-                            <span class="indicator whitespace-nowrap ${color}"><span class="hidden-xs">LinkedIn : ${status} </span></span>
+                            <span class="indicator whitespace-nowrap ${color}"><span>LinkedIn : ${status} </span></span>
                         </div>` ;
             }
             html = `<div class="row">${html}</div>`;
diff --git a/erpnext/crm/report/lead_details/lead_details.js b/erpnext/crm/report/lead_details/lead_details.js
new file mode 100644
index 0000000..f92070d
--- /dev/null
+++ b/erpnext/crm/report/lead_details/lead_details.js
@@ -0,0 +1,52 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Lead Details"] = {
+	"filters": [
+		{
+			"fieldname":"company",
+			"label": __("Company"),
+			"fieldtype": "Link",
+			"options": "Company",
+			"default": frappe.defaults.get_user_default("Company"),
+			"reqd": 1
+		},
+		{
+			"fieldname":"from_date",
+			"label": __("From Date"),
+			"fieldtype": "Date",
+			"default": frappe.datetime.add_months(frappe.datetime.get_today(), -12),
+			"reqd": 1
+		},
+		{
+			"fieldname":"to_date",
+			"label": __("To Date"),
+			"fieldtype": "Date",
+			"default": frappe.datetime.get_today(),
+			"reqd": 1
+		},
+		{
+			"fieldname":"status",
+			"label": __("Status"),
+			"fieldtype": "Select",
+			options: [
+				{ "value": "Lead", "label": __("Lead") },
+				{ "value": "Open", "label": __("Open") },
+				{ "value": "Replied", "label": __("Replied") },
+				{ "value": "Opportunity", "label": __("Opportunity") },
+				{ "value": "Quotation", "label": __("Quotation") },
+				{ "value": "Lost Quotation", "label": __("Lost Quotation") },
+				{ "value": "Interested", "label": __("Interested") },
+				{ "value": "Converted", "label": __("Converted") },
+				{ "value": "Do Not Contact", "label": __("Do Not Contact") },
+			],
+		},
+		{
+			"fieldname":"territory",
+			"label": __("Territory"),
+			"fieldtype": "Link",
+			"options": "Territory",
+		}
+	]
+};
\ No newline at end of file
diff --git a/erpnext/crm/report/lead_details/lead_details.json b/erpnext/crm/report/lead_details/lead_details.json
index cdeb6bb..7871d08 100644
--- a/erpnext/crm/report/lead_details/lead_details.json
+++ b/erpnext/crm/report/lead_details/lead_details.json
@@ -7,16 +7,15 @@
  "doctype": "Report",
  "idx": 3,
  "is_standard": "Yes",
- "modified": "2020-01-22 16:51:56.591110",
+ "modified": "2020-07-26 23:59:49.897577",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Lead Details",
  "owner": "Administrator",
  "prepared_report": 0,
- "query": "SELECT\n    `tabLead`.name as \"Lead Id:Link/Lead:120\",\n    `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n\t`tabLead`.notes as \"Notes::360\",\n    `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabDynamic Link` on (\n\t\t`tabDynamic Link`.link_name=`tabLead`.name \n\t\tand `tabDynamic Link`.parenttype = 'Address'\n\t)\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.name=`tabDynamic Link`.parent\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
  "ref_doctype": "Lead",
  "report_name": "Lead Details",
- "report_type": "Query Report",
+ "report_type": "Script Report",
  "roles": [
   {
    "role": "Sales User"
diff --git a/erpnext/crm/report/lead_details/lead_details.py b/erpnext/crm/report/lead_details/lead_details.py
new file mode 100644
index 0000000..eeaaec2
--- /dev/null
+++ b/erpnext/crm/report/lead_details/lead_details.py
@@ -0,0 +1,158 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+from frappe import _
+import frappe
+
+def execute(filters=None):
+	columns, data = get_columns(), get_data(filters)
+	return columns, data
+
+def get_columns():
+	columns = [
+		{
+			"label": _("Lead"),
+			"fieldname": "name",
+			"fieldtype": "Link",
+			"options": "Lead",
+			"width": 150,
+		},
+		{
+			"label": _("Lead Name"),
+			"fieldname": "lead_name",
+			"fieldtype": "Data",
+			"width": 120
+		},
+		{
+			"fieldname":"status",
+			"label": _("Status"),
+			"fieldtype": "Data",
+			"width": 100
+		},
+		{
+			"fieldname":"lead_owner",
+			"label": _("Lead Owner"),
+			"fieldtype": "Link",
+			"options": "User",
+			"width": 100
+		},
+		{
+			"label": _("Territory"),
+			"fieldname": "territory",
+			"fieldtype": "Link",
+			"options": "Territory",
+			"width": 100
+		},
+		{
+			"label": _("Source"),
+			"fieldname": "source",
+			"fieldtype": "Data",
+			"width": 120
+		},
+		{
+			"label": _("Email"),
+			"fieldname": "email_id",
+			"fieldtype": "Data",
+			"width": 120
+		},
+		{
+			"label": _("Mobile"),
+			"fieldname": "mobile_no",
+			"fieldtype": "Data",
+			"width": 120
+		},
+		{
+			"label": _("Phone"),
+			"fieldname": "phone",
+			"fieldtype": "Data",
+			"width": 120
+		},
+		{
+			"label": _("Owner"),
+			"fieldname": "owner",
+			"fieldtype": "Link",
+			"options": "user",
+			"width": 120
+		},
+		{
+			"label": _("Company"),
+			"fieldname": "company",
+			"fieldtype": "Link",
+			"options": "Company",
+			"width": 120
+		},
+		{
+			"fieldname":"address",
+			"label": _("Address"),
+			"fieldtype": "Data",
+			"width": 130
+		},
+		{
+			"fieldname":"state",
+			"label": _("State"),
+			"fieldtype": "Data",
+			"width": 100
+		},
+		{
+			"fieldname":"pincode",
+			"label": _("Postal Code"),
+			"fieldtype": "Data",
+			"width": 90
+		},
+		{
+			"fieldname":"country",
+			"label": _("Country"),
+			"fieldtype": "Link",
+			"options": "Country",
+			"width": 100
+		},
+		
+	]
+	return columns
+
+def get_data(filters):
+	return frappe.db.sql("""
+		SELECT
+			`tabLead`.name,
+			`tabLead`.lead_name,
+			`tabLead`.status,
+			`tabLead`.lead_owner,
+			`tabLead`.territory,
+			`tabLead`.source,
+			`tabLead`.email_id,
+			`tabLead`.mobile_no,
+			`tabLead`.phone,
+			`tabLead`.owner,
+			`tabLead`.company,
+			concat_ws(', ',
+				trim(',' from `tabAddress`.address_line1),
+				trim(',' from tabAddress.address_line2)
+			) AS address,
+			`tabAddress`.state,
+			`tabAddress`.pincode,
+			`tabAddress`.country
+		FROM
+			`tabLead` left join `tabDynamic Link` on (
+			`tabLead`.name = `tabDynamic Link`.link_name and
+			`tabDynamic Link`.parenttype = 'Address')
+			left join `tabAddress` on (
+			`tabAddress`.name=`tabDynamic Link`.parent)
+		WHERE
+			company = %(company)s
+			AND `tabLead`.creation BETWEEN %(from_date)s AND %(to_date)s
+			{conditions}
+		ORDER BY 
+			`tabLead`.creation asc """.format(conditions=get_conditions(filters)), filters, as_dict=1)
+
+def get_conditions(filters) :
+	conditions = []
+
+	if filters.get("territory"):
+		conditions.append(" and `tabLead`.territory=%(territory)s")
+
+	if filters.get("status"):
+		conditions.append(" and `tabLead`.status=%(status)s")
+	
+	return " ".join(conditions) if conditions else ""
+
diff --git a/erpnext/crm/report/lost_opportunity/lost_opportunity.js b/erpnext/crm/report/lost_opportunity/lost_opportunity.js
new file mode 100644
index 0000000..d79f8c8
--- /dev/null
+++ b/erpnext/crm/report/lost_opportunity/lost_opportunity.js
@@ -0,0 +1,67 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Lost Opportunity"] = {
+	"filters": [
+		{
+			"fieldname":"company",
+			"label": __("Company"),
+			"fieldtype": "Link",
+			"options": "Company",
+			"default": frappe.defaults.get_user_default("Company"),
+			"reqd": 1
+		},
+		{
+			"fieldname":"from_date",
+			"label": __("From Date"),
+			"fieldtype": "Date",
+			"default": frappe.datetime.add_months(frappe.datetime.get_today(), -12),
+			"reqd": 1
+		},
+		{
+			"fieldname":"to_date",
+			"label": __("To Date"),
+			"fieldtype": "Date",
+			"default": frappe.datetime.get_today(),
+			"reqd": 1
+		},
+		{
+			"fieldname":"lost_reason",
+			"label": __("Lost Reason"),
+			"fieldtype": "Link",
+			"options": "Opportunity Lost Reason"
+		},
+		{
+			"fieldname":"territory",
+			"label": __("Territory"),
+			"fieldtype": "Link",
+			"options": "Territory"
+		},
+		{
+			"fieldname":"opportunity_from",
+			"label": __("Opportunity From"),
+			"fieldtype": "Link",
+			"options": "DocType",
+			"get_query": function() {
+				return {
+					"filters": {
+						"name": ["in", ["Customer", "Lead"]],
+					}
+				}
+			}
+		},
+		{
+			"fieldname":"party_name",
+			"label": __("Party"),
+			"fieldtype": "Dynamic Link",
+			"options": "opportunity_from"
+		},
+		{
+			"fieldname":"contact_by",
+			"label": __("Next Contact By"),
+			"fieldtype": "Link",
+			"options": "User"
+		},
+	]
+};
\ No newline at end of file
diff --git a/erpnext/crm/report/lost_opportunity/lost_opportunity.json b/erpnext/crm/report/lost_opportunity/lost_opportunity.json
index e7c5068..e7a8e12 100644
--- a/erpnext/crm/report/lost_opportunity/lost_opportunity.json
+++ b/erpnext/crm/report/lost_opportunity/lost_opportunity.json
@@ -1,13 +1,14 @@
 {
  "add_total_row": 0,
  "creation": "2018-12-31 16:30:57.188837",
+ "disable_prepared_report": 0,
  "disabled": 0,
  "docstatus": 0,
  "doctype": "Report",
  "idx": 0,
  "is_standard": "Yes",
  "json": "{\"order_by\": \"`tabOpportunity`.`modified` desc\", \"filters\": [[\"Opportunity\", \"status\", \"=\", \"Lost\"]], \"fields\": [[\"name\", \"Opportunity\"], [\"opportunity_from\", \"Opportunity\"], [\"party_name\", \"Opportunity\"], [\"customer_name\", \"Opportunity\"], [\"opportunity_type\", \"Opportunity\"], [\"status\", \"Opportunity\"], [\"contact_by\", \"Opportunity\"], [\"docstatus\", \"Opportunity\"], [\"lost_reason\", \"Lost Reason Detail\"]], \"add_totals_row\": 0, \"add_total_row\": 0, \"page_length\": 20}",
- "modified": "2019-06-26 16:33:08.083618",
+ "modified": "2020-07-29 15:49:02.848845",
  "modified_by": "Administrator",
  "module": "CRM",
  "name": "Lost Opportunity",
@@ -15,7 +16,7 @@
  "prepared_report": 0,
  "ref_doctype": "Opportunity",
  "report_name": "Lost Opportunity",
- "report_type": "Report Builder",
+ "report_type": "Script Report",
  "roles": [
   {
    "role": "Sales User"
diff --git a/erpnext/crm/report/lost_opportunity/lost_opportunity.py b/erpnext/crm/report/lost_opportunity/lost_opportunity.py
new file mode 100644
index 0000000..1aa4afe
--- /dev/null
+++ b/erpnext/crm/report/lost_opportunity/lost_opportunity.py
@@ -0,0 +1,131 @@
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+from frappe import _
+import frappe
+
+def execute(filters=None):
+	columns, data = get_columns(), get_data(filters)
+	return columns, data
+
+def get_columns():
+	columns = [
+		{
+			"label": _("Opportunity"),
+			"fieldname": "name",
+			"fieldtype": "Link",
+			"options": "Opportunity",
+			"width": 170,
+		},
+		{
+			"label": _("Opportunity From"),
+			"fieldname": "opportunity_from",
+			"fieldtype": "Link",
+			"options": "DocType",
+			"width": 130
+		},
+		{
+			"label": _("Party"),
+			"fieldname":"party_name",
+			"fieldtype": "Dynamic Link",
+			"options": "opportunity_from",
+			"width": 160
+		},
+		{
+			"label": _("Customer/Lead Name"),
+			"fieldname":"customer_name",
+			"fieldtype": "Data",
+			"width": 150
+		},
+		{
+			"label": _("Opportunity Type"),
+			"fieldname": "opportunity_type",
+			"fieldtype": "Data",
+			"width": 130
+		},
+		{
+			"label": _("Lost Reasons"),
+			"fieldname": "lost_reason",
+			"fieldtype": "Data",
+			"width": 220
+		},
+		{
+			"label": _("Sales Stage"),
+			"fieldname": "sales_stage",
+			"fieldtype": "Link",
+			"options": "Sales Stage",
+			"width": 150
+		},
+		{
+			"label": _("Territory"),
+			"fieldname": "territory",
+			"fieldtype": "Link",
+			"options": "Territory",
+			"width": 150
+		},
+		{
+			"label": _("Next Contact By"),
+			"fieldname": "contact_by",
+			"fieldtype": "Link",
+			"options": "User",
+			"width": 150
+		}
+	]
+	return columns
+
+def get_data(filters):
+	return frappe.db.sql("""
+		SELECT
+			`tabOpportunity`.name,
+			`tabOpportunity`.opportunity_from,
+			`tabOpportunity`.party_name,
+			`tabOpportunity`.customer_name,
+			`tabOpportunity`.opportunity_type,
+			`tabOpportunity`.contact_by,
+			GROUP_CONCAT(`tabOpportunity Lost Reason Detail`.lost_reason separator ', ') lost_reason,
+			`tabOpportunity`.sales_stage,
+			`tabOpportunity`.territory
+		FROM
+			`tabOpportunity` 
+			{join}
+		WHERE
+			`tabOpportunity`.status = 'Lost' and `tabOpportunity`.company = %(company)s
+			AND `tabOpportunity`.modified BETWEEN %(from_date)s AND %(to_date)s 
+			{conditions} 
+		GROUP BY 
+			`tabOpportunity`.name 
+		ORDER BY 
+			`tabOpportunity`.creation asc  """.format(conditions=get_conditions(filters), join=get_join(filters)), filters, as_dict=1)
+		
+
+def get_conditions(filters):
+	conditions = []
+
+	if filters.get("territory"):
+		conditions.append(" and `tabOpportunity`.territory=%(territory)s")
+
+	if filters.get("opportunity_from"):
+		conditions.append(" and `tabOpportunity`.opportunity_from=%(opportunity_from)s")
+
+	if filters.get("party_name"):
+		conditions.append(" and `tabOpportunity`.party_name=%(party_name)s")
+
+	if filters.get("contact_by"):
+		conditions.append(" and `tabOpportunity`.contact_by=%(contact_by)s")
+
+	return " ".join(conditions) if conditions else ""
+
+def get_join(filters):
+	join = """LEFT JOIN `tabOpportunity Lost Reason Detail` 
+			ON `tabOpportunity Lost Reason Detail`.parenttype = 'Opportunity' and 
+			`tabOpportunity Lost Reason Detail`.parent = `tabOpportunity`.name"""
+
+	if filters.get("lost_reason"):
+		join = """JOIN `tabOpportunity Lost Reason Detail` 
+			ON `tabOpportunity Lost Reason Detail`.parenttype = 'Opportunity' and 
+			`tabOpportunity Lost Reason Detail`.parent = `tabOpportunity`.name and
+			`tabOpportunity Lost Reason Detail`.lost_reason = '{0}'
+			""".format(filters.get("lost_reason"))
+	
+	return join
\ No newline at end of file
diff --git a/erpnext/education/doctype/fees/test_fees.py b/erpnext/education/doctype/fees/test_fees.py
index b182992..eedc2ae 100644
--- a/erpnext/education/doctype/fees/test_fees.py
+++ b/erpnext/education/doctype/fees/test_fees.py
@@ -7,7 +7,7 @@
 import unittest
 from frappe.utils import nowdate
 from frappe.utils.make_random import get_random
-
+from erpnext.education.doctype.program.test_program import make_program_and_linked_courses
 
 # test_records = frappe.get_test_records('Fees')
 
@@ -15,6 +15,7 @@
 
 	def test_fees(self):
 		student = get_random("Student")
+		program = make_program_and_linked_courses("_Test Program 1", ["_Test Course 1", "_Test Course 2"])
 		fee = frappe.new_doc("Fees")
 		fee.posting_date = nowdate()
 		fee.due_date = nowdate()
@@ -23,6 +24,7 @@
 		fee.income_account = "Sales - _TC"
 		fee.cost_center = "_Test Cost Center - _TC"
 		fee.company = "_Test Company"
+		fee.program = program.name
 
 		fee.extend("components", [
 			{
diff --git a/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py
index 207351f..4ee5f6b 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py
+++ b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py
@@ -7,6 +7,8 @@
 import frappe
 from erpnext.healthcare.doctype.patient_appointment.test_patient_appointment import create_healthcare_docs, create_clinical_procedure_template
 
+test_dependencies = ['Item']
+
 class TestClinicalProcedure(unittest.TestCase):
 	def test_procedure_template_item(self):
 		patient, medical_department, practitioner = create_healthcare_docs()
diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js
index 971e166..60f0f9d 100644
--- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js
+++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.js
@@ -134,7 +134,7 @@
 			{fieldtype: 'Link', label: 'Leave From', fieldname: 'leave_from', options: 'Healthcare Service Unit', reqd: 1, read_only:1},
 			{fieldtype: 'Link', label: 'Service Unit Type', fieldname: 'service_unit_type', options: 'Healthcare Service Unit Type'},
 			{fieldtype: 'Link', label: 'Transfer To', fieldname: 'service_unit', options: 'Healthcare Service Unit', reqd: 1},
-			{fieldtype: 'Datetime', label: 'Check In', fieldname: 'check_in', reqd: 1}
+			{fieldtype: 'Datetime', label: 'Check In', fieldname: 'check_in', reqd: 1, default: frappe.datetime.now_datetime()}
 		],
 		primary_action_label: __('Transfer'),
 		primary_action : function() {
@@ -147,7 +147,12 @@
 			if(dialog.get_value('service_unit')){
 				service_unit = dialog.get_value('service_unit');
 			}
-			if(!check_in){
+			if(check_in > frappe.datetime.now_datetime()){
+				frappe.msgprint({
+					title: __('Not Allowed'),
+					message: __('Check-in time cannot be greater than the current time'),
+					indicator: 'red'
+				});
 				return;
 			}
 			frappe.call({
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
index f7ed31b..2d6b645 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
@@ -226,7 +226,9 @@
 			primary_action_label: __('Book'),
 			primary_action: function() {
 				frm.set_value('appointment_time', selected_slot);
-				frm.set_value('duration', duration);
+				if (!frm.doc.duration) {
+					frm.set_value('duration', duration);
+				}
 				frm.set_value('practitioner', d.get_value('practitioner'));
 				frm.set_value('department', d.get_value('department'));
 				frm.set_value('appointment_date', d.get_value('appointment_date'));
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 95a836f..463ad6c 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -322,7 +322,8 @@
 		"erpnext.crm.doctype.email_campaign.email_campaign.set_email_campaign_status",
 		"erpnext.selling.doctype.quotation.quotation.set_expired_status",
 		"erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_appointment_status",
-		"erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status"
+		"erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status",
+		"erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_auto_email"
 	],
 	"daily_long": [
 		"erpnext.setup.doctype.email_digest.email_digest.send",
diff --git a/erpnext/hr/desk_page/hr/hr.json b/erpnext/hr/desk_page/hr/hr.json
index 0fed8d3..895cf72 100644
--- a/erpnext/hr/desk_page/hr/hr.json
+++ b/erpnext/hr/desk_page/hr/hr.json
@@ -78,7 +78,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "HR",
- "modified": "2020-06-16 19:20:50.976045",
+ "modified": "2020-08-11 17:04:38.655417",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "HR",
@@ -88,7 +88,7 @@
  "pin_to_top": 0,
  "shortcuts": [
   {
-   "color": "#9deca2",
+   "color": "#cef6d1",
    "format": "{} Active",
    "label": "Employee",
    "link_to": "Employee",
@@ -96,12 +96,7 @@
    "type": "DocType"
   },
   {
-   "label": "Attendance",
-   "link_to": "Attendance",
-   "stats_filter": "",
-   "type": "DocType"
-  },
-  {
+   "color": "#ffe8cd",
    "format": "{} Open",
    "label": "Leave Application",
    "link_to": "Leave Application",
@@ -109,6 +104,12 @@
    "type": "DocType"
   },
   {
+   "label": "Attendance",
+   "link_to": "Attendance",
+   "stats_filter": "",
+   "type": "DocType"
+  },
+  {
    "label": "Job Applicant",
    "link_to": "Job Applicant",
    "type": "DocType"
diff --git a/erpnext/hr/doctype/department/department.json b/erpnext/hr/doctype/department/department.json
index a54c1d1..dcb6a74 100644
--- a/erpnext/hr/doctype/department/department.json
+++ b/erpnext/hr/doctype/department/department.json
@@ -17,10 +17,10 @@
   "payroll_cost_center",
   "column_break_9",
   "leave_block_list",
-  "leave_section",
+  "approvers",
   "leave_approvers",
-  "expense_section",
   "expense_approvers",
+  "shift_request_approver",
   "lft",
   "rgt",
   "old_parent"
@@ -33,14 +33,18 @@
    "label": "Department",
    "oldfieldname": "department_name",
    "oldfieldtype": "Data",
-   "reqd": 1
+   "reqd": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "parent_department",
    "fieldtype": "Link",
    "in_list_view": 1,
    "label": "Parent Department",
-   "options": "Department"
+   "options": "Department",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "company",
@@ -48,7 +52,9 @@
    "in_standard_filter": 1,
    "label": "Company",
    "options": "Company",
-   "reqd": 1
+   "reqd": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "bold": 1,
@@ -56,17 +62,23 @@
    "fieldname": "is_group",
    "fieldtype": "Check",
    "in_list_view": 1,
-   "label": "Is Group"
+   "label": "Is Group",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "default": "0",
    "fieldname": "disabled",
    "fieldtype": "Check",
-   "label": "Disabled"
+   "label": "Disabled",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "section_break_4",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "description": "Days for which Holidays are blocked for this department.",
@@ -74,31 +86,25 @@
    "fieldtype": "Link",
    "in_list_view": 1,
    "label": "Leave Block List",
-   "options": "Leave Block List"
+   "options": "Leave Block List",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
-   "fieldname": "leave_section",
-   "fieldtype": "Section Break",
-   "label": "Leave Approvers"
-  },
-  {
-   "description": "The first Leave Approver in the list will be set as the default Leave Approver.",
    "fieldname": "leave_approvers",
    "fieldtype": "Table",
    "label": "Leave Approver",
-   "options": "Department Approver"
+   "options": "Department Approver",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
-   "fieldname": "expense_section",
-   "fieldtype": "Section Break",
-   "label": "Expense Approvers"
-  },
-  {
-   "description": "The first Expense Approver in the list will be set as the default Expense Approver.",
    "fieldname": "expense_approvers",
    "fieldtype": "Table",
    "label": "Expense Approver",
-   "options": "Department Approver"
+   "options": "Department Approver",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "lft",
@@ -106,7 +112,9 @@
    "hidden": 1,
    "label": "lft",
    "print_hide": 1,
-   "read_only": 1
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "rgt",
@@ -114,7 +122,9 @@
    "hidden": 1,
    "label": "rgt",
    "print_hide": 1,
-   "read_only": 1
+   "read_only": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "old_parent",
@@ -122,28 +132,52 @@
    "hidden": 1,
    "ignore_user_permissions": 1,
    "label": "Old Parent",
-   "print_hide": 1
+   "print_hide": 1,
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "column_break_3",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "payroll_cost_center",
    "fieldtype": "Link",
    "label": "Payroll Cost Center",
-   "options": "Cost Center"
+   "options": "Cost Center",
+   "show_days": 1,
+   "show_seconds": 1
   },
   {
    "fieldname": "column_break_9",
-   "fieldtype": "Column Break"
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "description": "The first Approver in the list will be set as the default Approver.",
+   "fieldname": "approvers",
+   "fieldtype": "Section Break",
+   "label": "Approvers",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "shift_request_approver",
+   "fieldtype": "Table",
+   "label": "Shift Request Approver",
+   "options": "Department Approver",
+   "show_days": 1,
+   "show_seconds": 1
   }
  ],
  "icon": "fa fa-sitemap",
  "idx": 1,
  "is_tree": 1,
  "links": [],
- "modified": "2020-05-05 18:49:28.503931",
+ "modified": "2020-06-23 15:42:00.563272",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Department",
diff --git a/erpnext/hr/doctype/department_approver/department_approver.py b/erpnext/hr/doctype/department_approver/department_approver.py
index afd54b8..9b2de0e 100644
--- a/erpnext/hr/doctype/department_approver/department_approver.py
+++ b/erpnext/hr/doctype/department_approver/department_approver.py
@@ -15,12 +15,12 @@
 def get_approvers(doctype, txt, searchfield, start, page_len, filters):
 
 	if not filters.get("employee"):
-		frappe.throw(_("Please select Employee Record first."))
+		frappe.throw(_("Please select Employee first."))
 
 	approvers = []
 	department_details = {}
 	department_list = []
-	employee = frappe.get_value("Employee", filters.get("employee"), ["department", "leave_approver", "expense_approver"], as_dict=True)
+	employee = frappe.get_value("Employee", filters.get("employee"), ["department", "leave_approver", "expense_approver", "shift_request_approver"], as_dict=True)
 
 	employee_department = filters.get("department") or employee.department
 	if employee_department:
@@ -37,13 +37,18 @@
 	if filters.get("doctype") == "Expense Claim" and employee.expense_approver:
 		approvers.append(frappe.db.get_value("User", employee.expense_approver, ['name', 'first_name', 'last_name']))
 
+	if filters.get("doctype") == "Shift Request" and employee.shift_request_approver:
+		approvers.append(frappe.db.get_value("User", employee.shift_request_approver, ['name', 'first_name', 'last_name']))
 
 	if filters.get("doctype") == "Leave Application":
 		parentfield = "leave_approvers"
 		field_name = "Leave Approver"
-	else:
+	elif filters.get("doctype") == "Expense Claim":
 		parentfield = "expense_approvers"
 		field_name = "Expense Approver"
+	elif filters.get("doctype") == "Shift Request":
+		parentfield = "shift_request_approver"
+		field_name = "Shift Request Approver"
 	if department_list:
 		for d in department_list:
 			approvers += frappe.db.sql("""select user.name, user.first_name, user.last_name from
diff --git a/erpnext/hr/doctype/employee/employee.json b/erpnext/hr/doctype/employee/employee.json
index f2afe06..8c02e4f 100644
--- a/erpnext/hr/doctype/employee/employee.json
+++ b/erpnext/hr/doctype/employee/employee.json
@@ -51,10 +51,14 @@
   "column_break_31",
   "grade",
   "branch",
+  "approvers_section",
+  "expense_approver",
+  "leave_approver",
+  "column_break_45",
+  "shift_request_approver",
   "attendance_and_leave_details",
   "leave_policy",
   "attendance_device_id",
-  "leave_approver",
   "column_break_44",
   "holiday_list",
   "default_shift",
@@ -62,7 +66,6 @@
   "salary_mode",
   "payroll_cost_center",
   "column_break_52",
-  "expense_approver",
   "bank_name",
   "bank_ac_no",
   "health_insurance_section",
@@ -806,14 +809,37 @@
    "fieldname": "expense_approver",
    "fieldtype": "Link",
    "label": "Expense Approver",
-   "options": "User"
+   "options": "User",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "approvers_section",
+   "fieldtype": "Section Break",
+   "label": "Approvers",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "column_break_45",
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "shift_request_approver",
+   "fieldtype": "Link",
+   "label": "Shift Request Approver",
+   "options": "User",
+   "show_days": 1,
+   "show_seconds": 1
   }
  ],
  "icon": "fa fa-user",
  "idx": 24,
  "image_field": "image",
  "links": [],
- "modified": "2020-07-03 21:28:04.109189",
+ "modified": "2020-07-28 01:36:04.109189",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Employee",
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim_list.js b/erpnext/hr/doctype/expense_claim/expense_claim_list.js
index 6195ad4..9bafc18 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim_list.js
+++ b/erpnext/hr/doctype/expense_claim/expense_claim_list.js
@@ -1,5 +1,5 @@
 frappe.listview_settings['Expense Claim'] = {
-	add_fields: ["total_claimed_amount", "docstatus"],
+	add_fields: ["total_claimed_amount", "docstatus", "company"],
 	get_indicator: function(doc) {
 		if(doc.status == "Paid") {
 			return [__("Paid"), "green", "status,=,Paid"];
diff --git a/erpnext/hr/doctype/job_offer/job_offer.py b/erpnext/hr/doctype/job_offer/job_offer.py
index e7e1a37..c397a3f 100644
--- a/erpnext/hr/doctype/job_offer/job_offer.py
+++ b/erpnext/hr/doctype/job_offer/job_offer.py
@@ -3,6 +3,7 @@
 
 from __future__ import unicode_literals
 import frappe
+from frappe.utils import cint
 from frappe.model.document import Document
 from frappe.model.mapper import get_mapped_doc
 from frappe import _
@@ -24,8 +25,12 @@
 		check_vacancies = frappe.get_single("HR Settings").check_vacancies
 		if staffing_plan and check_vacancies:
 			job_offers = self.get_job_offer(staffing_plan.from_date, staffing_plan.to_date)
-			if staffing_plan.vacancies - len(job_offers) <= 0:
-				frappe.throw(_("There are no vacancies under staffing plan {0}").format(frappe.bold(get_link_to_form("Staffing Plan", staffing_plan.parent))))
+			if not staffing_plan.get("vacancies") or cint(staffing_plan.vacancies) - len(job_offers) <= 0:
+				error_variable = 'for ' + frappe.bold(self.designation)
+				if staffing_plan.get("parent"):
+					error_variable = frappe.bold(get_link_to_form("Staffing Plan", staffing_plan.parent))
+
+				frappe.throw(_("There are no vacancies under staffing plan {0}").format(error_variable))
 
 	def on_change(self):
 		update_job_applicant(self.status, self.job_applicant)
@@ -60,7 +65,7 @@
 			AND %s between sp.from_date and sp.to_date
 	""", (designation, company, offer_date), as_dict=1)
 
-	return frappe._dict(detail[0]) if detail else None
+	return frappe._dict(detail[0]) if (detail and detail[0].parent) else None
 
 @frappe.whitelist()
 def make_employee(source_name, target_doc=None):
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.js b/erpnext/hr/doctype/leave_allocation/leave_allocation.js
index 210a73c..e9e129c 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.js
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.js
@@ -5,20 +5,23 @@
 
 frappe.ui.form.on("Leave Allocation", {
 	onload: function(frm) {
+		// Ignore cancellation of doctype on cancel all.
+		frm.ignore_doctypes_on_cancel_all = ["Leave Ledger Entry"];
+
 		if(!frm.doc.from_date) frm.set_value("from_date", frappe.datetime.get_today());
 
 		frm.set_query("employee", function() {
 			return {
 				query: "erpnext.controllers.queries.employee_query"
-			}
+			};
 		});
 		frm.set_query("leave_type", function() {
 			return {
 				filters: {
 					is_lwp: 0
 				}
-			}
-		})
+			};
+		});
 	},
 
 	refresh: function(frm) {
diff --git a/erpnext/hr/doctype/leave_application/leave_application.js b/erpnext/hr/doctype/leave_application/leave_application.js
index 4001a45..d62e418 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.js
+++ b/erpnext/hr/doctype/leave_application/leave_application.js
@@ -19,6 +19,10 @@
 		frm.set_query("employee", erpnext.queries.employee);
 	},
 	onload: function(frm) {
+
+		// Ignore cancellation of doctype on cancel all.
+		frm.ignore_doctypes_on_cancel_all = ["Leave Ledger Entry"];
+
 		if (!frm.doc.posting_date) {
 			frm.set_value("posting_date", frappe.datetime.get_today());
 		}
diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.js b/erpnext/hr/doctype/leave_encashment/leave_encashment.js
index 701c2f0..71a3422 100644
--- a/erpnext/hr/doctype/leave_encashment/leave_encashment.js
+++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.js
@@ -2,6 +2,10 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Leave Encashment', {
+	onload: function(frm) {
+		// Ignore cancellation of doctype on cancel all.
+		frm.ignore_doctypes_on_cancel_all = ["Leave Ledger Entry"];
+	},
 	setup: function(frm) {
 		frm.set_query("leave_type", function() {
 			return {
@@ -33,7 +37,7 @@
 				doc: frm.doc,
 				callback: function(r) {
 					frm.refresh_fields();
-					}
+				}
 			});
 		}
 	}
diff --git a/erpnext/hr/doctype/shift_assignment/shift_assignment.json b/erpnext/hr/doctype/shift_assignment/shift_assignment.json
index 72cbba8..ce2a10f 100644
--- a/erpnext/hr/doctype/shift_assignment/shift_assignment.json
+++ b/erpnext/hr/doctype/shift_assignment/shift_assignment.json
@@ -10,9 +10,11 @@
   "employee",
   "employee_name",
   "shift_type",
+  "status",
   "column_break_3",
   "company",
-  "date",
+  "start_date",
+  "end_date",
   "shift_request",
   "department",
   "amended_from"
@@ -60,12 +62,6 @@
    "reqd": 1
   },
   {
-   "fieldname": "date",
-   "fieldtype": "Date",
-   "in_list_view": 1,
-   "label": "Date"
-  },
-  {
    "fieldname": "shift_request",
    "fieldtype": "Link",
    "label": "Shift Request",
@@ -80,11 +76,36 @@
    "options": "Shift Assignment",
    "print_hide": 1,
    "read_only": 1
+  },
+  {
+   "fieldname": "start_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Start Date",
+   "reqd": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "fieldname": "end_date",
+   "fieldtype": "Date",
+   "label": "End Date",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "default": "Active",
+   "fieldname": "status",
+   "fieldtype": "Select",
+   "label": "Status",
+   "options": "Active\nInactive",
+   "show_days": 1,
+   "show_seconds": 1
   }
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2019-12-12 15:49:06.956901",
+ "modified": "2020-06-15 14:27:54.310773",
  "modified_by": "Administrator",
  "module": "HR",
  "name": "Shift Assignment",
diff --git a/erpnext/hr/doctype/shift_assignment/shift_assignment.py b/erpnext/hr/doctype/shift_assignment/shift_assignment.py
index 40c78cd..f8b7334 100644
--- a/erpnext/hr/doctype/shift_assignment/shift_assignment.py
+++ b/erpnext/hr/doctype/shift_assignment/shift_assignment.py
@@ -11,38 +11,63 @@
 from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday
 from datetime import timedelta, datetime
 
-class OverlapError(frappe.ValidationError): pass
-
 class ShiftAssignment(Document):
 	def validate(self):
 		self.validate_overlapping_dates()
 
+		if self.end_date and self.end_date <= self.start_date:
+			frappe.throw(_("End Date must not be lesser than Start Date"))
+
 	def validate_overlapping_dates(self):
-			if not self.name:
-				self.name = "New Shift Assignment"
+		if not self.name:
+			self.name = "New Shift Assignment"
 
-			d = frappe.db.sql("""
-				select
-					name, shift_type, date
-				from `tabShift Assignment`
-				where employee = %(employee)s and docstatus < 2
-				and date = %(date)s
-				and name != %(name)s""", {
-					"employee": self.employee,
-					"shift_type": self.shift_type,
-					"date": self.date,
-					"name": self.name
-				}, as_dict = 1)
+		condition = """and (
+				end_date is null
+				or
+					%(start_date)s between start_date and end_date
+		"""
 
-			for date_overlap in d:
-				if date_overlap['name']:
-					self.throw_overlap_error(date_overlap)
+		if self.end_date:
+			condition  += """ or
+					%(end_date)s between start_date and end_date
+					or
+					start_date between %(start_date)s and %(end_date)s
+				) """
+		else:
+			condition += """ ) """
 
-	def throw_overlap_error(self, d):
-		msg = _("Employee {0} has already applied for {1} on {2} : ").format(self.employee,
-			d['shift_type'], formatdate(d['date'])) \
-			+ """ <b><a href="#Form/Shift Assignment/{0}">{0}</a></b>""".format(d["name"])
-		frappe.throw(msg, OverlapError)
+		assigned_shifts = frappe.db.sql("""
+			select name, shift_type, start_date ,end_date, docstatus, status
+			from `tabShift Assignment`
+			where
+				employee=%(employee)s and docstatus = 1
+				and name != %(name)s
+				and status = "Active"
+				{0}
+		""".format(condition), {
+			"employee": self.employee,
+			"shift_type": self.shift_type,
+			"start_date": self.start_date,
+			"end_date": self.end_date,
+			"name": self.name
+		}, as_dict = 1)
+
+		if len(assigned_shifts):
+			self.throw_overlap_error(assigned_shifts[0])
+
+	def throw_overlap_error(self, shift_details):
+		shift_details = frappe._dict(shift_details)
+		if shift_details.docstatus == 1 and shift_details.status == "Active":
+			msg = _("Employee {0} already has Active Shift {1}: {2}").format(frappe.bold(self.employee), frappe.bold(self.shift_type), frappe.bold(shift_details.name))
+		if shift_details.start_date:
+			msg += _(" from {0}").format(getdate(self.start_date).strftime("%d-%m-%Y"))
+			title = "Ongoing Shift"
+			if shift_details.end_date:
+				msg += _(" to {0}").format(getdate(self.end_date).strftime("%d-%m-%Y"))
+				title = "Active Shift"
+		if msg:
+			frappe.throw(msg, title=title)
 
 @frappe.whitelist()
 def get_events(start, end, filters=None):
@@ -62,19 +87,22 @@
 	return events
 
 def add_assignments(events, start, end, conditions=None):
-	query = """select name, date, employee_name, 
+	query = """select name, start_date, end_date, employee_name,
 		employee, docstatus
 		from `tabShift Assignment` where
-		date <= %(date)s
-		and docstatus < 2"""
+		start_date >= %(start_date)s
+		or end_date <=  %(end_date)s
+		or (%(start_date)s between start_date and end_date and %(end_date)s between start_date and end_date)
+		and docstatus = 1"""
 	if conditions:
 		query += conditions
 
-	for d in frappe.db.sql(query, {"date":start, "date":end}, as_dict=True):
+	for d in frappe.db.sql(query, {"start_date":start, "end_date":end}, as_dict=True):
 		e = {
 			"name": d.name,
 			"doctype": "Shift Assignment",
-			"date": d.date,
+			"start_date": d.start_date,
+			"end_date": d.end_date if d.end_date else nowdate(),
 			"title": cstr(d.employee_name) + \
 				cstr(d.shift_type),
 			"docstatus": d.docstatus
@@ -92,7 +120,16 @@
 	:param next_shift_direction: One of: None, 'forward', 'reverse'. Direction to look for next shift if shift not found on given date.
 	"""
 	default_shift = frappe.db.get_value('Employee', employee, 'default_shift')
-	shift_type_name = frappe.db.get_value('Shift Assignment', {'employee':employee, 'date': for_date, 'docstatus': '1'}, 'shift_type')
+	shift_type_name = None
+	shift_assignment_details = frappe.db.get_value('Shift Assignment', {'employee':employee, 'start_date':('<=', for_date), 'docstatus': '1', 'status': "Active"}, ['shift_type', 'end_date'])
+
+	if shift_assignment_details:
+		shift_type_name = shift_assignment_details[0]
+
+		# if end_date present means that shift is over after end_date else it is a ongoing shift.
+		if shift_assignment_details[1] and for_date >= shift_assignment_details[1] :
+			shift_type_name = None
+
 	if not shift_type_name and consider_default_shift:
 		shift_type_name = default_shift
 	if shift_type_name:
@@ -117,16 +154,20 @@
 			direction = '<' if next_shift_direction == 'reverse' else '>'
 			sort_order = 'desc' if next_shift_direction == 'reverse' else 'asc'
 			dates = frappe.db.get_all('Shift Assignment',
-				'date',
-				{'employee':employee, 'date':(direction, for_date), 'docstatus': '1'},
+				['start_date', 'end_date'],
+				{'employee':employee, 'start_date':(direction, for_date), 'docstatus': '1', "status": "Active"},
 				as_list=True,
-				limit=MAX_DAYS, order_by="date "+sort_order)
-			for date in dates:
-				shift_details = get_employee_shift(employee, date[0], consider_default_shift, None)
-				if shift_details:
-					shift_type_name = shift_details.shift_type.name
-					for_date = date[0]
-					break
+				limit=MAX_DAYS, order_by="start_date "+sort_order)
+
+			if dates:
+				for date in dates:
+					if date[1] and date[1] < for_date:
+						continue
+					shift_details = get_employee_shift(employee, date[0], consider_default_shift, None)
+					if shift_details:
+						shift_type_name = shift_details.shift_type.name
+						for_date = date[0]
+						break
 
 	return get_shift_details(shift_type_name, for_date)
 
@@ -134,7 +175,7 @@
 def get_employee_shift_timings(employee, for_timestamp=now_datetime(), consider_default_shift=False):
 	"""Returns previous shift, current/upcoming shift, next_shift for the given timestamp and employee
 	"""
-	# write and verify a test case for midnight shift. 
+	# write and verify a test case for midnight shift.
 	prev_shift = curr_shift = next_shift = None
 	curr_shift = get_employee_shift(employee, for_timestamp.date(), consider_default_shift, 'forward')
 	if curr_shift:
diff --git a/erpnext/hr/doctype/shift_assignment/shift_assignment_calendar.js b/erpnext/hr/doctype/shift_assignment/shift_assignment_calendar.js
index c2c9bc0..17a986d 100644
--- a/erpnext/hr/doctype/shift_assignment/shift_assignment_calendar.js
+++ b/erpnext/hr/doctype/shift_assignment/shift_assignment_calendar.js
@@ -3,8 +3,8 @@
 
 frappe.views.calendar["Shift Assignment"] = {
 	field_map: {
-		"start": "date",
-		"end": "date",
+		"start": "start_date",
+		"end": "end_date",
 		"id": "name",
 		"docstatus": 1
 	},
diff --git a/erpnext/hr/doctype/shift_assignment/test_shift_assignment.py b/erpnext/hr/doctype/shift_assignment/test_shift_assignment.py
index 7fe80a2..4c3c1ed 100644
--- a/erpnext/hr/doctype/shift_assignment/test_shift_assignment.py
+++ b/erpnext/hr/doctype/shift_assignment/test_shift_assignment.py
@@ -5,7 +5,7 @@
 
 import frappe
 import unittest
-from frappe.utils import nowdate
+from frappe.utils import nowdate, add_days
 
 test_dependencies = ["Shift Type"]
 
@@ -20,8 +20,61 @@
 			"shift_type": "Day Shift",
 			"company": "_Test Company",
 			"employee": "_T-Employee-00001",
-			"date": nowdate()
+			"start_date": nowdate()
 		}).insert()
 		shift_assignment.submit()
 
 		self.assertEqual(shift_assignment.docstatus, 1)
+
+	def test_overlapping_for_ongoing_shift(self):
+		# shift should be Ongoing if Only start_date is present and status = Active
+
+		shift_assignment_1 = frappe.get_doc({
+			"doctype": "Shift Assignment",
+			"shift_type": "Day Shift",
+			"company": "_Test Company",
+			"employee": "_T-Employee-00001",
+			"start_date": nowdate(),
+			"status": 'Active'
+		}).insert()
+		shift_assignment_1.submit()
+
+		self.assertEqual(shift_assignment_1.docstatus, 1)
+
+		shift_assignment = frappe.get_doc({
+			"doctype": "Shift Assignment",
+			"shift_type": "Day Shift",
+			"company": "_Test Company",
+			"employee": "_T-Employee-00001",
+			"start_date": add_days(nowdate(), 2)
+		})
+
+		self.assertRaises(frappe.ValidationError, shift_assignment.save)
+
+	def test_overlapping_for_fixed_period_shift(self):
+		# shift should is for Fixed period if Only start_date and end_date both are present and status = Active
+
+			shift_assignment_1 = frappe.get_doc({
+				"doctype": "Shift Assignment",
+				"shift_type": "Day Shift",
+				"company": "_Test Company",
+				"employee": "_T-Employee-00001",
+				"start_date": nowdate(),
+				"end_date": add_days(nowdate(), 30),
+				"status": 'Active'
+			}).insert()
+			shift_assignment_1.submit()
+
+
+			# it should not allowed within period of any shift.
+			shift_assignment_3 = frappe.get_doc({
+				"doctype": "Shift Assignment",
+				"shift_type": "Day Shift",
+				"company": "_Test Company",
+				"employee": "_T-Employee-00001",
+				"start_date":add_days(nowdate(), 10),
+				"end_date": add_days(nowdate(), 35),
+				"status": 'Active'
+			})
+
+			self.assertRaises(frappe.ValidationError, shift_assignment_3.save)
\ No newline at end of file
diff --git a/erpnext/hr/doctype/shift_request/shift_request.js b/erpnext/hr/doctype/shift_request/shift_request.js
index 1db7c7d..b17a6f3 100644
--- a/erpnext/hr/doctype/shift_request/shift_request.js
+++ b/erpnext/hr/doctype/shift_request/shift_request.js
@@ -2,7 +2,16 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('Shift Request', {
-	refresh: function(frm) {
-
-	}
+	setup: function(frm) {
+		frm.set_query("approver", function() {
+			return {
+				query: "erpnext.hr.doctype.department_approver.department_approver.get_approvers",
+				filters: {
+					employee: frm.doc.employee,
+					doctype: frm.doc.doctype
+				}
+			};
+		});
+		frm.set_query("employee", erpnext.queries.employee);
+	},
 });
diff --git a/erpnext/hr/doctype/shift_request/shift_request.json b/erpnext/hr/doctype/shift_request/shift_request.json
index dd05647..64cbdff 100644
--- a/erpnext/hr/doctype/shift_request/shift_request.json
+++ b/erpnext/hr/doctype/shift_request/shift_request.json
@@ -1,396 +1,155 @@
 {
- "allow_copy": 0, 
- "allow_guest_to_view": 0, 
- "allow_import": 1, 
- "allow_rename": 0, 
- "autoname": "HR-SHR-.YY.-.MM.-.#####", 
- "beta": 0, 
- "creation": "2018-04-13 16:32:27.974273", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "", 
- "editable_grid": 1, 
- "engine": "InnoDB", 
+ "actions": [],
+ "allow_import": 1,
+ "autoname": "HR-SHR-.YY.-.MM.-.#####",
+ "creation": "2018-04-13 16:32:27.974273",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "shift_type",
+  "employee",
+  "employee_name",
+  "department",
+  "status",
+  "column_break_4",
+  "company",
+  "approver",
+  "from_date",
+  "to_date",
+  "amended_from"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "shift_type", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Shift Type", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Shift Type", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "shift_type",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Shift Type",
+   "options": "Shift Type",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "employee", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Employee", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Employee", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "employee",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Employee",
+   "options": "Employee",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_from": "employee.employee_name", 
-   "fieldname": "employee_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Employee Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fetch_from": "employee.employee_name",
+   "fieldname": "employee_name",
+   "fieldtype": "Data",
+   "label": "Employee Name",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fetch_from": "employee.department", 
-   "fieldname": "department", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Department", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Department", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fetch_from": "employee.department",
+   "fieldname": "department",
+   "fieldtype": "Link",
+   "label": "Department",
+   "options": "Department",
+   "read_only": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "column_break_4", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_4",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "company", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 1, 
-   "in_standard_filter": 0, 
-   "label": "Company", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Company", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "from_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "From Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "from_date",
+   "fieldtype": "Date",
+   "label": "From Date",
+   "reqd": 1
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "to_date", 
-   "fieldtype": "Date", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "To Date", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "to_date",
+   "fieldtype": "Date",
+   "label": "To Date"
+  },
   {
-   "allow_bulk_edit": 0, 
-   "allow_in_quick_entry": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
-   "fieldname": "amended_from", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_global_search": 0, 
-   "in_list_view": 0, 
-   "in_standard_filter": 0, 
-   "label": "Amended From", 
-   "length": 0, 
-   "no_copy": 1, 
-   "options": "Shift Request", 
-   "permlevel": 0, 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "remember_last_selected_value": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "translatable": 0, 
-   "unique": 0
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Shift Request",
+   "print_hide": 1,
+   "read_only": 1
+  },
+  {
+   "default": "Draft",
+   "fieldname": "status",
+   "fieldtype": "Select",
+   "label": "Status",
+   "options": "Draft\nApproved\nRejected",
+   "reqd": 1
+  },
+  {
+   "fetch_from": "employee.shift_request_approver",
+   "fetch_if_empty": 1,
+   "fieldname": "approver",
+   "fieldtype": "Link",
+   "label": "Approver",
+   "options": "User",
+   "reqd": 1
   }
- ], 
- "has_web_view": 0, 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
- "is_submittable": 1, 
- "issingle": 0, 
- "istable": 0, 
- "max_attachments": 0, 
- "modified": "2018-08-21 16:15:36.577448", 
- "modified_by": "Administrator", 
- "module": "HR", 
- "name": "Shift Request", 
- "name_case": "", 
- "owner": "Administrator", 
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-08-10 17:59:31.550558",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Shift Request",
+ "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Employee", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 1, 
+   "create": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "Employee",
+   "share": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 1, 
-   "cancel": 1, 
-   "create": 1, 
-   "delete": 1, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "HR Manager", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 1, 
+   "amend": 1,
+   "cancel": 1,
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR Manager",
+   "share": 1,
+   "submit": 1,
    "write": 1
-  }, 
+  },
   {
-   "amend": 0, 
-   "cancel": 0, 
-   "create": 1, 
-   "delete": 0, 
-   "email": 1, 
-   "export": 1, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "HR User", 
-   "set_user_permissions": 0, 
-   "share": 1, 
-   "submit": 1, 
+   "create": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "HR User",
+   "share": 1,
+   "submit": 1,
    "write": 1
   }
- ], 
- "quick_entry": 0, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "show_name_in_global_search": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "title_field": "employee_name", 
- "track_changes": 1, 
- "track_seen": 0, 
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "employee_name",
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/hr/doctype/shift_request/shift_request.py b/erpnext/hr/doctype/shift_request/shift_request.py
index ff5de08..1c2801b 100644
--- a/erpnext/hr/doctype/shift_request/shift_request.py
+++ b/erpnext/hr/doctype/shift_request/shift_request.py
@@ -14,19 +14,26 @@
 	def validate(self):
 		self.validate_dates()
 		self.validate_shift_request_overlap_dates()
+		self.validate_approver()
+		self.validate_default_shift()
 
 	def on_submit(self):
-		date_list = self.get_working_days(self.from_date, self.to_date)
-		for date in date_list:
+		if self.status not in ["Approved", "Rejected"]:
+			frappe.throw(_("Only Shift Request with status 'Approved' and 'Rejected' can be submitted"))
+		if self.status == "Approved":
 			assignment_doc = frappe.new_doc("Shift Assignment")
 			assignment_doc.company = self.company
 			assignment_doc.shift_type = self.shift_type
 			assignment_doc.employee = self.employee
-			assignment_doc.date = date
+			assignment_doc.start_date = self.from_date
+			if self.to_date:
+				assignment_doc.end_date = self.to_date
 			assignment_doc.shift_request = self.name
 			assignment_doc.insert()
 			assignment_doc.submit()
 
+			frappe.msgprint(_("Shift Assignment: {0} created for Employee: {1}").format(frappe.bold(assignment_doc.name), frappe.bold(self.employee)))
+
 	def on_cancel(self):
 		shift_assignment_list = frappe.get_list("Shift Assignment", {'employee': self.employee, 'shift_request': self.name})
 		if shift_assignment_list:
@@ -34,6 +41,19 @@
 				shift_assignment_doc = frappe.get_doc("Shift Assignment", shift['name'])
 				shift_assignment_doc.cancel()
 
+	def validate_default_shift(self):
+		default_shift = frappe.get_value("Employee", self.employee, "default_shift")
+		if self.shift_type == default_shift:
+			frappe.throw(_("You can not request for your Default Shift: {0}").format(frappe.bold(self.shift_type)))
+
+	def validate_approver(self):
+		department = frappe.get_value("Employee", self.employee, "department")
+		shift_approver = frappe.get_value("Employee", self.employee, "shift_request_approver")
+		approvers = frappe.db.sql("""select approver from `tabDepartment Approver` where parent= %s and parentfield = 'shift_request_approver'""", (department))
+		approvers = [approver[0] for approver in approvers]
+		approvers.append(shift_approver)
+		if self.approver not in approvers:
+			frappe.throw(_("Only Approvers can Approve this Request."))
 
 	def validate_dates(self):
 		if self.from_date and self.to_date and (getdate(self.to_date) < getdate(self.from_date)):
@@ -68,28 +88,4 @@
 		msg = _("Employee {0} has already applied for {1} between {2} and {3} : ").format(self.employee,
 			d['shift_type'], formatdate(d['from_date']), formatdate(d['to_date'])) \
 			+ """ <b><a href="#Form/Shift Request/{0}">{0}</a></b>""".format(d["name"])
-		frappe.throw(msg, OverlapError)
-
-	def get_working_days(self, start_date, end_date):
-		start_date, end_date = getdate(start_date), getdate(end_date)
-
-		from datetime import timedelta
-
-		date_list = []
-		employee_holiday_list = []
-
-		employee_holidays = frappe.db.sql("""select holiday_date from `tabHoliday`
-								where parent in (select holiday_list from `tabEmployee`
-								where name = %s)""",self.employee,as_dict=1)
-
-		for d in employee_holidays:
-			employee_holiday_list.append(d.holiday_date)
-
-		reference_date = start_date
-		
-		while reference_date <= end_date:
-			if reference_date not in employee_holiday_list:
-				date_list.append(reference_date)
-			reference_date += timedelta(days=1)
-
-		return date_list
\ No newline at end of file
+		frappe.throw(msg, OverlapError)
\ No newline at end of file
diff --git a/erpnext/hr/doctype/shift_request/test_shift_request.py b/erpnext/hr/doctype/shift_request/test_shift_request.py
index 1d0cf71..3dcfcbf 100644
--- a/erpnext/hr/doctype/shift_request/test_shift_request.py
+++ b/erpnext/hr/doctype/shift_request/test_shift_request.py
@@ -5,7 +5,7 @@
 
 import frappe
 import unittest
-from frappe.utils import nowdate
+from frappe.utils import nowdate, add_days
 
 class TestShiftRequest(unittest.TestCase):
 	def setUp(self):
@@ -13,14 +13,20 @@
 			frappe.db.sql("delete from `tab{doctype}`".format(doctype=doctype))
 
 	def test_make_shift_request(self):
+		department = frappe.get_value("Employee", "_T-Employee-00001", 'department')
+		set_shift_approver(department)
+		approver = frappe.db.sql("""select approver from `tabDepartment Approver` where parent= %s and parentfield = 'shift_request_approver'""", (department))[0][0]
+
 		shift_request = frappe.get_doc({
 			"doctype": "Shift Request",
 			"shift_type": "Day Shift",
 			"company": "_Test Company",
 			"employee": "_T-Employee-00001",
 			"employee_name": "_Test Employee",
-			"start_date": nowdate(),
-			"end_date": nowdate()
+			"from_date": nowdate(),
+			"to_date": add_days(nowdate(), 10),
+			"approver": approver,
+			"status": "Approved"
 		})
 		shift_request.insert()
 		shift_request.submit()
@@ -34,4 +40,10 @@
 			self.assertEqual(shift_request.employee, employee)
 			shift_request.cancel()
 			shift_assignment_doc = frappe.get_doc("Shift Assignment", {"shift_request": d.get('shift_request')})
-			self.assertEqual(shift_assignment_doc.docstatus, 2)
\ No newline at end of file
+			self.assertEqual(shift_assignment_doc.docstatus, 2)
+
+def set_shift_approver(department):
+	department_doc = frappe.get_doc("Department", department)
+	department_doc.append('shift_request_approver',{'approver': "test1@example.com"})
+	department_doc.save()
+	department_doc.reload()
\ No newline at end of file
diff --git a/erpnext/hr/doctype/shift_type/shift_type.js b/erpnext/hr/doctype/shift_type/shift_type.js
index e633545..ba53312 100644
--- a/erpnext/hr/doctype/shift_type/shift_type.js
+++ b/erpnext/hr/doctype/shift_type/shift_type.js
@@ -4,7 +4,7 @@
 frappe.ui.form.on('Shift Type', {
 	refresh: function(frm) {
 		frm.add_custom_button(
-			'Mark Auto Attendance',
+			'Mark Attendance',
 			() => frm.call({
 				doc: frm.doc,
 				method: 'process_auto_attendance',
diff --git a/erpnext/hr/doctype/shift_type/shift_type.py b/erpnext/hr/doctype/shift_type/shift_type.py
index 1973564..054e7e3 100644
--- a/erpnext/hr/doctype/shift_type/shift_type.py
+++ b/erpnext/hr/doctype/shift_type/shift_type.py
@@ -79,9 +79,10 @@
 				mark_attendance(employee, date, 'Absent', self.name)
 
 	def get_assigned_employee(self, from_date=None, consider_default_shift=False):
-		filters = {'date':('>=', from_date), 'shift_type': self.name, 'docstatus': '1'}
+		filters = {'start_date':('>', from_date), 'shift_type': self.name, 'docstatus': '1'}
 		if not from_date:
-			del filters['date']
+			del filters["start_date"]
+
 		assigned_employees = frappe.get_all('Shift Assignment', 'employee', filters, as_list=True)
 		assigned_employees = [x[0] for x in assigned_employees]
 
diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
index db1d191..1b92358 100644
--- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
+++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
@@ -132,6 +132,9 @@
 	if filters.get('employee'):
 		conditions['name'] = filters.get('employee')
 
+	if filters.get('company'):
+		conditions['company'] = filters.get('company')
+
 	return conditions
 
 def get_department_leave_approver_map(department=None):
diff --git a/erpnext/loan_management/desk_page/loan/loan.json b/erpnext/loan_management/desk_page/loan/loan.json
index 48193b0..3bdd1ce 100644
--- a/erpnext/loan_management/desk_page/loan/loan.json
+++ b/erpnext/loan_management/desk_page/loan/loan.json
@@ -3,7 +3,7 @@
   {
    "hidden": 0,
    "label": "Loan",
-   "links": "[\n    {\n        \"description\": \"Loan Type for interest and penalty rates\",\n        \"label\": \"Loan Type\",\n        \"name\": \"Loan Type\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Loan Applications from customers and employees.\",\n        \"label\": \"Loan Application\",\n        \"name\": \"Loan Application\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Loans provided to customers and employees.\",\n        \"label\": \"Loan\",\n        \"name\": \"Loan\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n    {\n        \"description\": \"Loan Type for interest and penalty rates\",\n        \"label\": \"Loan Type\",\n        \"name\": \"Loan Type\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Loan Applications from customers and employees.\",\n        \"label\": \"Loan Application\",\n        \"name\": \"Loan Application\",\n        \"type\": \"doctype\"\n    },\n    {   \"dependencies\": [\n            \"Loan Type\"\n        ],\n        \"description\": \"Loans provided to customers and employees.\",\n        \"label\": \"Loan\",\n        \"name\": \"Loan\",\n        \"type\": \"doctype\"\n    }\n]"
   },
   {
    "hidden": 0,
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index 23815d598..b75f7bd 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -17,6 +17,7 @@
 from erpnext.loan_management.doctype.loan.loan import create_loan_security_unpledge
 from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty
 from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge
+from erpnext.loan_management.doctype.loan_disbursement.loan_disbursement import get_disbursal_amount
 
 class TestLoan(unittest.TestCase):
 	def setUp(self):
@@ -323,6 +324,56 @@
 		self.assertEqual(loan.status, 'Closed')
 		self.assertEquals(sum(pledged_qty.values()), 0)
 
+	def test_disbursal_check_with_shortfall(self):
+		pledges = [{
+			"loan_security": "Test Security 2",
+			"qty": 8000.00,
+			"haircut": 50,
+		}]
+
+		loan_application = create_loan_application('_Test Company', self.applicant2,
+			'Stock Loan', pledges, "Repay Over Number of Periods", 12)
+
+		create_pledge(loan_application)
+
+		loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_application)
+		loan.submit()
+
+		#Disbursing 7,00,000 from the allowed 10,00,000 according to security pledge
+		make_loan_disbursement_entry(loan.name, 700000)
+
+		frappe.db.sql("""UPDATE `tabLoan Security Price` SET loan_security_price = 100
+			where loan_security='Test Security 2'""")
+
+		create_process_loan_security_shortfall()
+		loan_security_shortfall = frappe.get_doc("Loan Security Shortfall", {"loan": loan.name})
+		self.assertTrue(loan_security_shortfall)
+
+		self.assertEqual(get_disbursal_amount(loan.name), 0)
+
+		frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 250
+			where loan_security='Test Security 2'""")
+
+	def test_disbursal_check_without_shortfall(self):
+		pledges = [{
+			"loan_security": "Test Security 2",
+			"qty": 8000.00,
+			"haircut": 50,
+		}]
+
+		loan_application = create_loan_application('_Test Company', self.applicant2,
+			'Stock Loan', pledges, "Repay Over Number of Periods", 12)
+
+		create_pledge(loan_application)
+
+		loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_application)
+		loan.submit()
+
+		#Disbursing 7,00,000 from the allowed 10,00,000 according to security pledge
+		make_loan_disbursement_entry(loan.name, 700000)
+
+		self.assertEqual(get_disbursal_amount(loan.name), 300000)
+
 
 def create_loan_accounts():
 	if not frappe.db.exists("Account", "Loans and Advances (Assets) - _TC"):
diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.js b/erpnext/loan_management/doctype/loan_application/loan_application.js
index 6cf47bf..1365274 100644
--- a/erpnext/loan_management/doctype/loan_application/loan_application.js
+++ b/erpnext/loan_management/doctype/loan_application/loan_application.js
@@ -33,18 +33,18 @@
 
 			if (frm.doc.is_secured_loan) {
 				frappe.db.get_value("Loan Security Pledge", {"loan_application": frm.doc.name, "docstatus": 1}, "name", (r) => {
-					if (!r) {
+					if (Object.keys(r).length === 0) {
 						frm.add_custom_button(__('Loan Security Pledge'), function() {
-							frm.trigger('create_loan_security_pledge')
+							frm.trigger('create_loan_security_pledge');
 						},__('Create'))
 					}
 				});
 			}
 
 			frappe.db.get_value("Loan", {"loan_application": frm.doc.name, "docstatus": 1}, "name", (r) => {
-				if (!r) {
+				if (Object.keys(r).length === 0) {
 					frm.add_custom_button(__('Loan'), function() {
-						frm.trigger('create_loan')
+						frm.trigger('create_loan');
 					},__('Create'))
 				} else {
 					frm.set_df_property('status', 'read_only', 1);
@@ -54,7 +54,7 @@
 	},
 	create_loan: function(frm) {
 		if (frm.doc.status != "Approved") {
-			frappe.throw(__("Cannot create loan until application is approved"))
+			frappe.throw(__("Cannot create loan until application is approved"));
 		}
 
 		frappe.model.open_mapped_doc({
@@ -112,16 +112,19 @@
 frappe.ui.form.on("Proposed Pledge", {
 	loan_security: function(frm, cdt, cdn) {
 		let row = locals[cdt][cdn];
-		frappe.call({
-			method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price",
-			args: {
-				loan_security: row.loan_security
-			},
-			callback: function(r) {
-				frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message);
-				frm.events.calculate_amounts(frm, cdt, cdn);
-			}
-		})
+
+		if (row.loan_security) {
+			frappe.call({
+				method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price",
+				args: {
+					loan_security: row.loan_security
+				},
+				callback: function(r) {
+					frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message);
+					frm.events.calculate_amounts(frm, cdt, cdn);
+				}
+			})
+		}
 	},
 
 	amount: function(frm, cdt, cdn) {
diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.py b/erpnext/loan_management/doctype/loan_application/loan_application.py
index f051755..bac6e63 100644
--- a/erpnext/loan_management/doctype/loan_application/loan_application.py
+++ b/erpnext/loan_management/doctype/loan_application/loan_application.py
@@ -16,14 +16,16 @@
 
 class LoanApplication(Document):
 	def validate(self):
-
-		validate_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount,
-			self.repayment_periods, self.is_term_loan)
-
-		self.validate_loan_type()
 		self.set_pledge_amount()
 		self.set_loan_amount()
 		self.validate_loan_amount()
+
+		if self.is_term_loan:
+			validate_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount,
+				self.repayment_periods, self.is_term_loan)
+
+		self.validate_loan_type()
+
 		self.get_repayment_details()
 		self.check_sanctioned_amount_limit()
 
@@ -106,7 +108,7 @@
 		if self.is_secured_loan and self.proposed_pledges:
 			self.maximum_loan_amount = 0
 			for security in self.proposed_pledges:
-				self.maximum_loan_amount += security.post_haircut_amount
+				self.maximum_loan_amount += flt(security.post_haircut_amount)
 
 		if not self.loan_amount and self.is_secured_loan and self.proposed_pledges:
 			self.loan_amount = self.maximum_loan_amount
@@ -133,10 +135,7 @@
 			"validation": {
 				"docstatus": ["=", 1]
 			},
-			"postprocess": update_accounts,
-			"field_no_map": [
-				"is_secured_loan"
-			]
+			"postprocess": update_accounts
 		}
 	}, target_doc)
 
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
index d44088b..260fada 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
@@ -10,22 +10,20 @@
 from erpnext.controllers.accounts_controller import AccountsController
 from erpnext.accounts.general_ledger import make_gl_entries
 from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans
+from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty
+from frappe.utils import get_datetime
 
 class LoanDisbursement(AccountsController):
 
 	def validate(self):
 		self.set_missing_values()
 
-	def before_submit(self):
-		self.set_status_and_amounts()
-
-	def before_cancel(self):
-		self.set_status_and_amounts(cancel=1)
-
 	def on_submit(self):
+		self.set_status_and_amounts()
 		self.make_gl_entries()
 
 	def on_cancel(self):
+		self.set_status_and_amounts(cancel=1)
 		self.make_gl_entries(cancel=1)
 		self.ignore_linked_doctypes = ['GL Entry']
 
@@ -45,29 +43,51 @@
 	def set_status_and_amounts(self, cancel=0):
 
 		loan_details = frappe.get_all("Loan",
-			fields = ["loan_amount", "disbursed_amount", "total_principal_paid", "status", "is_term_loan"],
-			filters= { "name": self.against_loan }
-		)[0]
-
-		if loan_details.status == "Disbursed" and not loan_details.is_term_loan:
-			process_loan_interest_accrual_for_demand_loans(posting_date=add_days(self.disbursement_date, -1),
-				loan=self.against_loan)
+			fields = ["loan_amount", "disbursed_amount", "total_payment", "total_principal_paid", "total_interest_payable",
+				"status", "is_term_loan", "is_secured_loan"], filters= { "name": self.against_loan })[0]
 
 		if cancel:
 			disbursed_amount = loan_details.disbursed_amount - self.disbursed_amount
+			total_payment = loan_details.total_payment
+
+			if loan_details.disbursed_amount > loan_details.loan_amount:
+				topup_amount = loan_details.disbursed_amount - loan_details.loan_amount
+				if topup_amount > self.disbursed_amount:
+					topup_amount = self.disbursed_amount
+
+				total_payment = total_payment - topup_amount
+
 			if disbursed_amount == 0:
 				status = "Sanctioned"
-			elif disbursed_amount >= loan_details.disbursed_amount:
+			elif disbursed_amount >= loan_details.loan_amount:
 				status = "Disbursed"
 			else:
 				status = "Partially Disbursed"
 		else:
 			disbursed_amount = self.disbursed_amount + loan_details.disbursed_amount
+			total_payment = loan_details.total_payment
 
-			if flt(disbursed_amount) - flt(loan_details.total_principal_paid) > flt(loan_details.loan_amount):
-				frappe.throw(_("Disbursed Amount cannot be greater than loan amount"))
+			possible_disbursal_amount = get_disbursal_amount(self.against_loan)
 
-			if flt(disbursed_amount) >= loan_details.disbursed_amount:
+			if self.disbursed_amount > possible_disbursal_amount:
+				frappe.throw(_("Disbursed Amount cannot be greater than {0}").format(possible_disbursal_amount))
+
+			if loan_details.status == "Disbursed" and not loan_details.is_term_loan:
+				process_loan_interest_accrual_for_demand_loans(posting_date=add_days(self.disbursement_date, -1),
+					loan=self.against_loan)
+
+			if disbursed_amount > loan_details.loan_amount:
+				topup_amount = disbursed_amount - loan_details.loan_amount
+
+				if topup_amount < 0:
+					topup_amount = 0
+
+				if topup_amount > self.disbursed_amount:
+					topup_amount = self.disbursed_amount
+
+				total_payment = total_payment + topup_amount
+
+			if flt(disbursed_amount) >= loan_details.loan_amount:
 				status = "Disbursed"
 			else:
 				status = "Partially Disbursed"
@@ -75,7 +95,8 @@
 		frappe.db.set_value("Loan", self.against_loan, {
 			"disbursement_date": self.disbursement_date,
 			"disbursed_amount": disbursed_amount,
-			"status": status
+			"status": status,
+			"total_payment": total_payment
 		})
 
 	def make_gl_entries(self, cancel=0, adv_adj=0):
@@ -116,3 +137,53 @@
 
 		if gle_map:
 			make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj)
+
+def get_total_pledged_security_value(loan):
+	update_time = get_datetime()
+
+	loan_security_price_map = frappe._dict(frappe.get_all("Loan Security Price",
+		fields=["loan_security", "loan_security_price"],
+		filters = {
+			"valid_from": ("<=", update_time),
+			"valid_upto": (">=", update_time)
+		}, as_list=1))
+
+	hair_cut_map = frappe._dict(frappe.get_all('Loan Security',
+		fields=["name", "haircut"], as_list=1))
+
+	security_value = 0.0
+	pledged_securities = get_pledged_security_qty(loan)
+
+	for security, qty in pledged_securities.items():
+		security_value += (loan_security_price_map.get(security) * qty * hair_cut_map.get(security))/100
+
+	return security_value
+
+@frappe.whitelist()
+def get_disbursal_amount(loan):
+	loan_details = frappe.get_all("Loan", fields = ["loan_amount", "disbursed_amount", "total_payment",
+		"total_principal_paid", "total_interest_payable", "status", "is_term_loan", "is_secured_loan"],
+		filters= { "name": loan })[0]
+
+	if loan_details.is_secured_loan and frappe.get_all('Loan Security Shortfall', filters={'loan': loan,
+		'status': 'Pending'}):
+		return 0
+
+	if loan_details.status == 'Disbursed':
+		pending_principal_amount = flt(loan_details.total_payment) - flt(loan_details.total_interest_payable) \
+			- flt(loan_details.total_principal_paid)
+	else:
+		pending_principal_amount = flt(loan_details.disbursed_amount)
+
+	security_value = 0.0
+	if loan_details.is_secured_loan:
+		security_value = get_total_pledged_security_value(loan)
+
+	if not security_value and not loan_details.is_secured_loan:
+		security_value = flt(loan_details.loan_amount)
+
+	disbursal_amount = flt(security_value) - flt(pending_principal_amount)
+
+	return disbursal_amount
+
+
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
index e6ceb55..1d3fa71 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
@@ -19,8 +19,8 @@
 		if not self.posting_date:
 			self.posting_date = nowdate()
 
-		if not self.interest_amount:
-			frappe.throw(_("Interest Amount is mandatory"))
+		if not self.interest_amount and not self.payable_principal_amount:
+			frappe.throw(_("Interest Amount or Principal Amount is mandatory"))
 
 
 	def on_submit(self):
@@ -39,37 +39,38 @@
 	def make_gl_entries(self, cancel=0, adv_adj=0):
 		gle_map = []
 
-		gle_map.append(
-			self.get_gl_dict({
-				"account": self.loan_account,
-				"party_type": self.applicant_type,
-				"party": self.applicant,
-				"against": self.interest_income_account,
-				"debit": self.interest_amount,
-				"debit_in_account_currency": self.interest_amount,
-				"against_voucher_type": "Loan",
-				"against_voucher": self.loan,
-				"remarks": _("Against Loan:") + self.loan,
-				"cost_center": erpnext.get_default_cost_center(self.company),
-				"posting_date": self.posting_date
-			})
-		)
+		if self.interest_amount:
+			gle_map.append(
+				self.get_gl_dict({
+					"account": self.loan_account,
+					"party_type": self.applicant_type,
+					"party": self.applicant,
+					"against": self.interest_income_account,
+					"debit": self.interest_amount,
+					"debit_in_account_currency": self.interest_amount,
+					"against_voucher_type": "Loan",
+					"against_voucher": self.loan,
+					"remarks": _("Against Loan:") + self.loan,
+					"cost_center": erpnext.get_default_cost_center(self.company),
+					"posting_date": self.posting_date
+				})
+			)
 
-		gle_map.append(
-			self.get_gl_dict({
-				"account": self.interest_income_account,
-				"party_type": self.applicant_type,
-				"party": self.applicant,
-				"against": self.loan_account,
-				"credit": self.interest_amount,
-				"credit_in_account_currency":  self.interest_amount,
-				"against_voucher_type": "Loan",
-				"against_voucher": self.loan,
-				"remarks": _("Against Loan:") + self.loan,
-				"cost_center": erpnext.get_default_cost_center(self.company),
-				"posting_date": self.posting_date
-			})
-		)
+			gle_map.append(
+				self.get_gl_dict({
+					"account": self.interest_income_account,
+					"party_type": self.applicant_type,
+					"party": self.applicant,
+					"against": self.loan_account,
+					"credit": self.interest_amount,
+					"credit_in_account_currency":  self.interest_amount,
+					"against_voucher_type": "Loan",
+					"against_voucher": self.loan,
+					"remarks": _("Against Loan:") + self.loan,
+					"cost_center": erpnext.get_default_cost_center(self.company),
+					"posting_date": self.posting_date
+				})
+			)
 
 		if gle_map:
 			make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj)
@@ -84,8 +85,11 @@
 	if no_of_days <= 0:
 		return
 
-	pending_principal_amount = loan.total_payment - loan.total_interest_payable \
-		- loan.total_amount_paid
+	if loan.status == 'Disbursed':
+		pending_principal_amount = flt(loan.total_payment) - flt(loan.total_interest_payable) \
+			- flt(loan.total_principal_paid)
+	else:
+		pending_principal_amount = loan.disbursed_amount
 
 	interest_per_day = (pending_principal_amount * loan.rate_of_interest) / (days_in_year(get_datetime(posting_date).year) * 100)
 	payable_interest = interest_per_day * no_of_days
@@ -106,7 +110,7 @@
 
 def make_accrual_interest_entry_for_demand_loans(posting_date, process_loan_interest, open_loans=None, loan_type=None):
 	query_filters = {
-		"status": "Disbursed",
+		"status": ('in', ['Disbursed', 'Partially Disbursed']),
 		"docstatus": 1
 	}
 
@@ -117,8 +121,9 @@
 
 	if not open_loans:
 		open_loans = frappe.get_all("Loan",
-			fields=["name", "total_payment", "total_amount_paid", "loan_account", "interest_income_account", "is_term_loan",
-				"disbursement_date", "applicant_type", "applicant", "rate_of_interest", "total_interest_payable", "repayment_start_date"],
+			fields=["name", "total_payment", "total_amount_paid", "loan_account", "interest_income_account",
+				"is_term_loan", "status", "disbursement_date", "disbursed_amount", "applicant_type", "applicant",
+				"rate_of_interest", "total_interest_payable", "total_principal_paid", "repayment_start_date"],
 			filters=query_filters)
 
 	for loan in open_loans:
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
index 789c129..5942455 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
@@ -173,7 +173,7 @@
   {
    "fieldname": "references_section",
    "fieldtype": "Section Break",
-   "label": "References"
+   "label": "Payment References"
   },
   {
    "fieldname": "reference_number",
@@ -221,7 +221,7 @@
  ],
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-16 18:14:45.166754",
+ "modified": "2020-05-16 09:40:15.581165",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Repayment",
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index 9605045..451ae85 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -281,7 +281,7 @@
 
 		due_date = add_days(entry.posting_date, 1)
 		no_of_late_days = date_diff(posting_date,
-					add_days(due_date, loan_type_details.grace_period_in_days))
+			add_days(due_date, loan_type_details.grace_period_in_days))
 
 		if no_of_late_days > 0 and (not against_loan_doc.repay_from_salary):
 			penalty_amount += (entry.interest_amount * (loan_type_details.penalty_interest_rate / 100) * no_of_late_days)/365
@@ -297,7 +297,10 @@
 		if not final_due_date:
 			final_due_date = add_days(due_date, loan_type_details.grace_period_in_days)
 
-	pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
+	if against_loan_doc.status == 'Disbursed':
+		pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
+	else:
+		pending_principal_amount = against_loan_doc.disbursed_amount
 
 	if payment_type == "Loan Closure":
 		if due_date:
diff --git a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.js b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.js
index 82837b3..11c932f 100644
--- a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.js
+++ b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.js
@@ -22,16 +22,19 @@
 frappe.ui.form.on("Pledge", {
 	loan_security: function(frm, cdt, cdn) {
 		let row = locals[cdt][cdn];
-		frappe.call({
-			method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price",
-			args: {
-				loan_security: row.loan_security
-			},
-			callback: function(r) {
-				frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message);
-				frm.events.calculate_amounts(frm, cdt, cdn);
-			}
-		});
+
+		if (row.loan_security) {
+			frappe.call({
+				method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price",
+				args: {
+					loan_security: row.loan_security
+				},
+				callback: function(r) {
+					frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message);
+					frm.events.calculate_amounts(frm, cdt, cdn);
+				}
+			});
+		}
 	},
 
 	qty: function(frm, cdt, cdn) {
diff --git a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
index 02efe24..0f42bde 100644
--- a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
+++ b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
@@ -4,7 +4,7 @@
 
 from __future__ import unicode_literals
 import frappe
-from frappe.utils import get_datetime
+from frappe.utils import get_datetime, flt
 from frappe.model.document import Document
 from six import iteritems
 from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty
@@ -51,13 +51,19 @@
 			"valid_upto": (">=", update_time)
 		}, as_list=1))
 
-	loans = frappe.get_all('Loan', fields=['name', 'loan_amount', 'total_principal_paid'],
-		filters={'status': 'Disbursed', 'is_secured_loan': 1})
+	loans = frappe.get_all('Loan', fields=['name', 'loan_amount', 'total_principal_paid', 'total_payment',
+		'total_interest_payable', 'disbursed_amount', 'status'],
+		filters={'status': ('in',['Disbursed','Partially Disbursed']), 'is_secured_loan': 1})
 
 	loan_security_map = {}
 
 	for loan in loans:
-		outstanding_amount = loan.loan_amount - loan.total_principal_paid
+		if loan.status == 'Disbursed':
+			outstanding_amount = flt(loan.total_payment) - flt(loan.total_interest_payable) \
+				- flt(loan.total_principal_paid)
+		else:
+			outstanding_amount = loan.disbursed_amount
+
 		pledged_securities = get_pledged_security_qty(loan.name)
 		ltv_ratio = ''
 		security_value = 0.0
diff --git a/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json b/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json
index f46b88c..871e825 100644
--- a/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json
+++ b/erpnext/loan_management/doctype/loan_security_type/loan_security_type.json
@@ -29,6 +29,7 @@
    "unique": 1
   },
   {
+   "description": "Haircut percentage is the percentage difference between market value of the Loan Security and the value ascribed to that Loan Security when used as collateral for that loan.",
    "fieldname": "haircut",
    "fieldtype": "Percent",
    "label": "Haircut %"
@@ -46,13 +47,14 @@
    "fieldtype": "Column Break"
   },
   {
+   "description": "Loan To Value Ratio expresses the ratio of the loan amount to the value of the security pledged. A loan security shortfall will be triggered if this falls below the specified value for any loan ",
    "fieldname": "loan_to_value_ratio",
    "fieldtype": "Percent",
    "label": "Loan To Value Ratio"
   }
  ],
  "links": [],
- "modified": "2020-04-28 14:06:49.046177",
+ "modified": "2020-05-16 09:38:45.988080",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Security Type",
diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.json b/erpnext/loan_management/doctype/loan_type/loan_type.json
index 1dd3710..669490a 100644
--- a/erpnext/loan_management/doctype/loan_type/loan_type.json
+++ b/erpnext/loan_management/doctype/loan_type/loan_type.json
@@ -76,6 +76,7 @@
    "reqd": 1
   },
   {
+   "description": "This account is used for booking loan repayments from the borrower and also disbursing loans to the borrower",
    "fieldname": "payment_account",
    "fieldtype": "Link",
    "label": "Payment Account",
@@ -83,6 +84,7 @@
    "reqd": 1
   },
   {
+   "description": "This account is capital account which is used to allocate capital for loan disbursal account ",
    "fieldname": "loan_account",
    "fieldtype": "Link",
    "label": "Loan Account",
@@ -94,6 +96,7 @@
    "fieldtype": "Column Break"
   },
   {
+   "description": "This account will be used for booking loan interest accruals",
    "fieldname": "interest_income_account",
    "fieldtype": "Link",
    "label": "Interest Income Account",
@@ -101,6 +104,7 @@
    "reqd": 1
   },
   {
+   "description": "This account will be used for booking penalties levied due to delayed repayments",
    "fieldname": "penalty_income_account",
    "fieldtype": "Link",
    "label": "Penalty Income Account",
@@ -109,6 +113,7 @@
   },
   {
    "default": "0",
+   "description": "If this is not checked the loan by default will be considered as a Demand Loan",
    "fieldname": "is_term_loan",
    "fieldtype": "Check",
    "label": "Is Term Loan"
diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
index add7bbf..cba6a2d 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
+++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
@@ -67,16 +67,16 @@
 
 			for key in scheduled_date:
 				description =frappe._("Reference: {0}, Item Code: {1} and Customer: {2}").format(self.name, d.item_code, self.customer)
-				frappe.get_doc({
+				event = frappe.get_doc({
 					"doctype": "Event",
 					"owner": email_map.get(d.sales_person, self.owner),
 					"subject": description,
 					"description": description,
 					"starts_on": cstr(key["scheduled_date"]) + " 10:00:00",
 					"event_type": "Private",
-					"ref_type": self.doctype,
-					"ref_name": self.name
-				}).insert(ignore_permissions=1)
+				})
+				event.add_participant(self.doctype, self.name)
+				event.insert(ignore_permissions=1)
 
 		frappe.db.set(self, 'status', 'Submitted')
 
diff --git a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py
index d8ae17b..3c307e9 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py
+++ b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py
@@ -2,6 +2,7 @@
 # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 # See license.txt
 from __future__ import unicode_literals
+from frappe.utils.data import get_datetime, add_days
 
 import frappe
 import unittest
@@ -9,4 +10,39 @@
 # test_records = frappe.get_test_records('Maintenance Schedule')
 
 class TestMaintenanceSchedule(unittest.TestCase):
-	pass
+	def test_events_should_be_created_and_deleted(self):
+		ms = make_maintenance_schedule()
+		ms.generate_schedule()
+		ms.submit()
+
+		all_events = get_events(ms)
+		self.assertTrue(len(all_events) > 0)
+
+		ms.cancel()
+		events_after_cancel = get_events(ms)
+		self.assertTrue(len(events_after_cancel) == 0)
+
+def get_events(ms):
+	return frappe.get_all("Event Participants", filters={
+			"reference_doctype": ms.doctype,
+			"reference_docname": ms.name,
+			"parenttype": "Event"
+		})
+
+def make_maintenance_schedule():
+	ms = frappe.new_doc("Maintenance Schedule")
+	ms.company = "_Test Company"
+	ms.customer = "_Test Customer"
+	ms.transaction_date = get_datetime()
+
+	ms.append("items", {
+		"item_code": "_Test Item",
+		"start_date": get_datetime(),
+		"end_date": add_days(get_datetime(), 32),
+		"periodicity": "Weekly",
+		"no_of_visits": 4,
+		"sales_person": "Sales Team",
+	})
+	ms.insert(ignore_permissions=True)
+
+	return ms
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index c51f655..3189433 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -494,7 +494,7 @@
 					'image'			: d.image,
 					'stock_uom'		: d.stock_uom,
 					'stock_qty'		: flt(d.stock_qty),
-					'rate'			: flt(d.base_rate) / flt(d.conversion_factor),
+					'rate'			: flt(d.base_rate) / (flt(d.conversion_factor) or 1.0),
 					'include_item_in_manufacturing': d.include_item_in_manufacturing
 				}))
 
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
index e6c10ad..742d18c 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
@@ -90,6 +90,7 @@
 		update_cost()
 
 def replace_bom(args):
+	frappe.db.auto_commit_on_many_writes = 1
 	args = frappe._dict(args)
 
 	doc = frappe.get_doc("BOM Update Tool")
@@ -97,6 +98,8 @@
 	doc.new_bom = args.new_bom
 	doc.replace_bom()
 
+	frappe.db.auto_commit_on_many_writes = 0
+
 def update_cost():
 	frappe.db.auto_commit_on_many_writes = 1
 	bom_list = get_boms_in_bottom_up_order()
diff --git a/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js b/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js
index ff32dbe..f648674 100644
--- a/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js
+++ b/erpnext/manufacturing/report/downtime_analysis/downtime_analysis.js
@@ -8,7 +8,7 @@
 			label: __("From Date"),
 			fieldname:"from_date",
 			fieldtype: "Datetime",
-			default: frappe.datetime.add_months(frappe.datetime.now_datetime(), -1),
+			default: frappe.datetime.convert_to_system_tz(frappe.datetime.add_months(frappe.datetime.now_datetime(), -1)),
 			reqd: 1
 		},
 		{
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index ae20d9e..a8648f5 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -687,6 +687,7 @@
 execute:frappe.rename_doc("Desk Page", "Getting Started", "Home", force=True)
 erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price
 erpnext.patches.v12_0.set_valid_till_date_in_supplier_quotation
+erpnext.patches.v13_0.update_old_loans
 erpnext.patches.v12_0.set_serial_no_status #2020-05-21
 erpnext.patches.v12_0.update_price_list_currency_in_bom
 execute:frappe.delete_doc_if_exists('Dashboard', 'Accounts')
@@ -717,3 +718,8 @@
 erpnext.patches.v12_0.update_item_tax_template_company
 erpnext.patches.v13_0.move_branch_code_to_bank_account
 erpnext.patches.v13_0.healthcare_lab_module_rename_doctypes
+erpnext.patches.v13_0.add_standard_navbar_items #4
+erpnext.patches.v13_0.stock_entry_enhancements
+erpnext.patches.v12_0.update_state_code_for_daman_and_diu
+erpnext.patches.v12_0.rename_lost_reason_detail
+erpnext.patches.v13_0.update_start_end_date_for_old_shift_assignment
diff --git a/erpnext/patches/v12_0/create_irs_1099_field_united_states.py b/erpnext/patches/v12_0/create_irs_1099_field_united_states.py
index 43bd0cc..7feaffd 100644
--- a/erpnext/patches/v12_0/create_irs_1099_field_united_states.py
+++ b/erpnext/patches/v12_0/create_irs_1099_field_united_states.py
@@ -7,6 +7,7 @@
 	frappe.reload_doc('accounts', 'doctype', 'allowed_to_transact_with', force=True)
 	frappe.reload_doc('accounts', 'doctype', 'pricing_rule_detail', force=True)
 	frappe.reload_doc('crm', 'doctype', 'lost_reason_detail', force=True)
+	frappe.reload_doc('setup', 'doctype', 'quotation_lost_reason_detail', force=True)
 
 	company = frappe.get_all('Company', filters = {'country': 'United States'})
 	if not company:
diff --git a/erpnext/patches/v12_0/rename_lost_reason_detail.py b/erpnext/patches/v12_0/rename_lost_reason_detail.py
new file mode 100644
index 0000000..d0dc356
--- /dev/null
+++ b/erpnext/patches/v12_0/rename_lost_reason_detail.py
@@ -0,0 +1,18 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+    if frappe.db.exists("DocType", "Lost Reason Detail"):
+        frappe.reload_doc("crm", "doctype", "opportunity_lost_reason")
+        frappe.reload_doc("crm", "doctype", "opportunity_lost_reason_detail")
+        frappe.reload_doc("setup", "doctype", "quotation_lost_reason_detail")
+
+        frappe.db.sql("""INSERT INTO `tabOpportunity Lost Reason Detail` SELECT * FROM `tabLost Reason Detail` WHERE `parenttype` = 'Opportunity'""")
+
+        frappe.db.sql("""INSERT INTO `tabQuotation Lost Reason Detail` SELECT * FROM `tabLost Reason Detail` WHERE `parenttype` = 'Quotation'""")
+
+        frappe.db.sql("""INSERT INTO `tabQuotation Lost Reason` (`name`, `creation`, `modified`, `modified_by`, `owner`, `docstatus`, `parent`, `parentfield`, `parenttype`, `idx`, `_comments`, `_assign`, `_user_tags`, `_liked_by`, `order_lost_reason`)
+            SELECT o.`name`, o.`creation`, o.`modified`, o.`modified_by`, o.`owner`, o.`docstatus`, o.`parent`, o.`parentfield`, o.`parenttype`, o.`idx`, o.`_comments`, o.`_assign`, o.`_user_tags`, o.`_liked_by`, o.`lost_reason`
+            FROM `tabOpportunity Lost Reason` o LEFT JOIN `tabQuotation Lost Reason` q ON q.name = o.name WHERE q.name IS NULL""")
+
+        frappe.delete_doc("DocType", "Lost Reason Detail")
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/stock_entry_enhancements.py b/erpnext/patches/v12_0/stock_entry_enhancements.py
index d04b3d3..847d928 100644
--- a/erpnext/patches/v12_0/stock_entry_enhancements.py
+++ b/erpnext/patches/v12_0/stock_entry_enhancements.py
@@ -19,7 +19,7 @@
 
 	for purpose in ["Material Issue", "Material Receipt", "Material Transfer",
 		"Material Transfer for Manufacture", "Material Consumption for Manufacture", "Manufacture",
-		"Repack", "Send to Subcontractor", "Send to Warehouse", "Receive at Warehouse"]:
+		"Repack", "Send to Subcontractor"]:
 
 		ste_type = frappe.get_doc({
 			'doctype': 'Stock Entry Type',
diff --git a/erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py b/erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py
new file mode 100644
index 0000000..7450e9c
--- /dev/null
+++ b/erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py
@@ -0,0 +1,22 @@
+import frappe
+from erpnext.regional.india import states
+
+def execute():
+
+	company = frappe.get_all('Company', filters = {'country': 'India'})
+	if not company:
+		return
+
+	# Update options in gst_state custom field
+	gst_state = frappe.get_doc('Custom Field', 'Address-gst_state')
+	gst_state.options = '\n'.join(states)
+	gst_state.save()
+
+	# Update gst_state and state code in existing address
+	frappe.db.sql("""
+		UPDATE `tabAddress`
+		SET
+			gst_state = 'Dadra and Nagar Haveli and Daman and Diu',
+			gst_state_number = 26
+		WHERE gst_state = 'Daman and Diu'
+	""")
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/add_standard_navbar_items.py b/erpnext/patches/v13_0/add_standard_navbar_items.py
new file mode 100644
index 0000000..d05b258
--- /dev/null
+++ b/erpnext/patches/v13_0/add_standard_navbar_items.py
@@ -0,0 +1,7 @@
+from __future__ import unicode_literals
+# import frappe
+from erpnext.setup.install import add_standard_navbar_items
+
+def execute():
+	# Add standard navbar items for ERPNext in Navbar Settings
+	add_standard_navbar_items()
diff --git a/erpnext/patches/v13_0/stock_entry_enhancements.py b/erpnext/patches/v13_0/stock_entry_enhancements.py
new file mode 100644
index 0000000..dcc4f95
--- /dev/null
+++ b/erpnext/patches/v13_0/stock_entry_enhancements.py
@@ -0,0 +1,27 @@
+# Copyright(c) 2020, Frappe Technologies Pvt.Ltd.and Contributors
+# License: GNU General Public License v3.See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+    frappe.reload_doc("stock", "doctype", "stock_entry")
+    if frappe.db.has_column("Stock Entry", "add_to_transit"):
+        frappe.db.sql("""
+            UPDATE `tabStock Entry` SET 
+            stock_entry_type = 'Material Transfer',
+            purpose = 'Material Transfer',
+            add_to_transit = 1 WHERE stock_entry_type = 'Send to Warehouse'
+            """)
+
+        frappe.db.sql("""UPDATE `tabStock Entry` SET 
+            stock_entry_type = 'Material Transfer',
+            purpose = 'Material Transfer'
+            WHERE stock_entry_type = 'Receive at Warehouse'
+            """)
+        
+        frappe.reload_doc("stock", "doctype", "warehouse_type")
+        if not frappe.db.exists('Warehouse Type', 'Transit'):
+            doc = frappe.new_doc('Warehouse Type')
+            doc.name = 'Transit'
+            doc.insert()
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/update_old_loans.py b/erpnext/patches/v13_0/update_old_loans.py
new file mode 100644
index 0000000..7723942
--- /dev/null
+++ b/erpnext/patches/v13_0/update_old_loans.py
@@ -0,0 +1,88 @@
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.utils import nowdate
+from erpnext.accounts.doctype.account.test_account import create_account
+from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
+from erpnext.loan_management.doctype.loan.loan import make_repayment_entry
+
+def execute():
+
+	# Create a penalty account for loan types
+
+	frappe.reload_doc('loan_management', 'doctype', 'loan_type')
+	frappe.reload_doc('loan_management', 'doctype', 'loan')
+	frappe.reload_doc('loan_management', 'doctype', 'repayment_schedule')
+	frappe.reload_doc('loan_management', 'doctype', 'process_loan_interest_accrual')
+	frappe.reload_doc('loan_management', 'doctype', 'loan_repayment')
+	frappe.reload_doc('loan_management', 'doctype', 'loan_repayment_detail')
+	frappe.reload_doc('loan_management', 'doctype', 'loan_interest_accrual')
+	frappe.reload_doc('accounts', 'doctype', 'gl_entry')
+
+	updated_loan_types = []
+
+	loans = frappe.get_all('Loan', fields=['name', 'loan_type', 'company', 'status', 'mode_of_payment',
+		'applicant_type', 'applicant', 'loan_account', 'payment_account', 'interest_income_account'])
+
+	for loan in loans:
+		# Update details in Loan Types and Loan
+		loan_type_company = frappe.db.get_value('Loan Type', loan.loan_type, 'company')
+
+		group_income_account = frappe.get_value('Account', {'company': loan.company,
+			'is_group': 1, 'root_type': 'Income', 'account_name': _('Indirect Income')})
+
+		if not group_income_account:
+			group_income_account = frappe.get_value('Account', {'company': loan.company,
+				'is_group': 1, 'root_type': 'Income'})
+
+		penalty_account = create_account(company=loan.company, account_type='Income Account',
+			account_name='Penalty Account', parent_account=group_income_account)
+
+		if not loan_type_company:
+			loan_type_doc = frappe.get_doc('Loan Type', loan.loan_type)
+			loan_type_doc.is_term_loan = 1
+			loan_type_doc.company = loan.company
+			loan_type_doc.mode_of_payment = loan.mode_of_payment
+			loan_type_doc.payment_account = loan.payment_account
+			loan_type_doc.loan_account = loan.loan_account
+			loan_type_doc.interest_income_account = loan.interest_income_account
+			loan_type_doc.penalty_income_account = penalty_account
+			loan_type_doc.submit()
+			updated_loan_types.append(loan.loan_type)
+
+		if loan.loan_type in updated_loan_types:
+			if loan.status == 'Fully Disbursed':
+				status = 'Disbursed'
+			elif loan.status == 'Repaid/Closed':
+				status = 'Closed'
+			else:
+				status = loan.status
+
+			frappe.db.set_value('Loan', loan.name, {
+				'is_term_loan': 1,
+				'penalty_income_account': penalty_account,
+				'status': status
+			})
+
+			process_loan_interest_accrual_for_term_loans(posting_date=nowdate(), loan_type=loan.loan_type,
+				loan=loan.name)
+
+			payments = frappe.db.sql(''' SELECT j.name, a.debit, a.debit_in_account_currency, j.posting_date
+				FROM `tabJournal Entry` j, `tabJournal Entry Account` a
+				WHERE a.parent = j.name and a.reference_type='Loan' and a.reference_name = %s
+				and account = %s
+			''', (loan.name, loan.loan_account), as_dict=1)
+
+			for payment in payments:
+				repayment_entry = make_repayment_entry(loan.name, loan.loan_applicant_type, loan.applicant,
+					loan.loan_type, loan.company)
+
+				repayment_entry.amount_paid = payment.debit_in_account_currency
+				repayment_entry.posting_date = payment.posting_date
+				repayment_entry.save()
+				repayment_entry.submit()
+
+				jv = frappe.get_doc('Journal Entry', payment.name)
+				jv.flags.ignore_links = True
+				jv.cancel()
+
diff --git a/erpnext/patches/v13_0/update_start_end_date_for_old_shift_assignment.py b/erpnext/patches/v13_0/update_start_end_date_for_old_shift_assignment.py
new file mode 100644
index 0000000..0f521cb
--- /dev/null
+++ b/erpnext/patches/v13_0/update_start_end_date_for_old_shift_assignment.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+
+def execute():
+    frappe.reload_doc('hr', 'doctype', 'shift_assignment')
+    if frappe.db.has_column('Shift Assignment', 'date'):
+        frappe.db.sql("""update `tabShift Assignment`
+            set end_date=date, start_date=date
+            where date IS NOT NULL and start_date IS NULL and end_date IS NULL;""")
diff --git a/erpnext/payroll/desk_page/payroll/payroll.json b/erpnext/payroll/desk_page/payroll/payroll.json
index b5eac46..285e3b3 100644
--- a/erpnext/payroll/desk_page/payroll/payroll.json
+++ b/erpnext/payroll/desk_page/payroll/payroll.json
@@ -8,7 +8,7 @@
   {
    "hidden": 0,
    "label": "Taxation",
-   "links": "[\n    {\n        \"label\": \"Payroll Period\",\n        \"name\": \"Payroll Period\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Income Tax Slab\",\n        \"name\": \"Income Tax Slab\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Declaration\",\n        \"name\": \"Employee Tax Exemption Declaration\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Proof Submission\",\n        \"name\": \"Employee Tax Exemption Proof Submission\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Category\",\n        \"name\": \"Employee Tax Exemption Category\",\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Sub Category\",\n        \"name\": \"Employee Tax Exemption Sub Category\",\n        \"type\": \"doctype\"\n        \n    }\n]"
+   "links": "[\n    {\n        \"label\": \"Payroll Period\",\n        \"name\": \"Payroll Period\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Income Tax Slab\",\n        \"name\": \"Income Tax Slab\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Other Income\",\n        \"name\": \"Employee Other Income\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Declaration\",\n        \"name\": \"Employee Tax Exemption Declaration\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Proof Submission\",\n        \"name\": \"Employee Tax Exemption Proof Submission\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Category\",\n        \"name\": \"Employee Tax Exemption Category\",\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Sub Category\",\n        \"name\": \"Employee Tax Exemption Sub Category\",\n        \"type\": \"doctype\"\n        \n    }\n]"
   },
   {
    "hidden": 0,
@@ -38,7 +38,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Payroll",
- "modified": "2020-06-19 12:23:06.034046",
+ "modified": "2020-08-10 19:38:45.976209",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Payroll",
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index 554484f..30ea432 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -90,7 +90,7 @@
 		cond = ''
 		for f in ['company', 'branch', 'department', 'designation']:
 			if self.get(f):
-				cond += " and t1." + f + " = '" + self.get(f).replace("'", "\'") + "'"
+				cond += " and t1." + f + " = " + frappe.db.escape(self.get(f))
 
 		return cond
 
diff --git a/erpnext/payroll/doctype/salary_detail/salary_detail.json b/erpnext/payroll/doctype/salary_detail/salary_detail.json
index adb54f2..cc87cae 100644
--- a/erpnext/payroll/doctype/salary_detail/salary_detail.json
+++ b/erpnext/payroll/doctype/salary_detail/salary_detail.json
@@ -7,27 +7,30 @@
  "field_order": [
   "salary_component",
   "abbr",
-  "statistical_component",
   "column_break_3",
-  "deduct_full_tax_on_selected_payroll_date",
+  "amount",
+  "section_break_5",
+  "additional_salary",
+  "statistical_component",
   "depends_on_payment_days",
-  "is_tax_applicable",
   "exempted_from_income_tax",
+  "is_tax_applicable",
+  "column_break_11",
   "is_flexible_benefit",
   "variable_based_on_taxable_salary",
+  "do_not_include_in_total",
+  "deduct_full_tax_on_selected_payroll_date",
   "section_break_2",
   "condition",
+  "column_break_18",
   "amount_based_on_formula",
   "formula",
-  "amount",
-  "do_not_include_in_total",
+  "section_break_19",
   "default_amount",
   "additional_amount",
+  "column_break_24",
   "tax_on_flexible_benefit",
-  "tax_on_additional_salary",
-  "section_break_11",
-  "additional_salary",
-  "condition_and_formula_help"
+  "tax_on_additional_salary"
  ],
  "fields": [
   {
@@ -110,9 +113,11 @@
    "read_only": 1
   },
   {
+   "collapsible": 1,
    "depends_on": "eval:doc.is_flexible_benefit != 1",
    "fieldname": "section_break_2",
-   "fieldtype": "Section Break"
+   "fieldtype": "Section Break",
+   "label": "Condtion and formula"
   },
   {
    "allow_on_submit": 1,
@@ -182,22 +187,11 @@
    "read_only": 1
   },
   {
-   "depends_on": "eval:doc.parenttype=='Salary Structure'",
-   "fieldname": "section_break_11",
-   "fieldtype": "Column Break"
-  },
-  {
-   "depends_on": "eval:doc.parenttype=='Salary Structure'",
-   "fieldname": "condition_and_formula_help",
-   "fieldtype": "HTML",
-   "label": "Condition and Formula Help",
-   "options": "<h3>Condition and Formula Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base &lt; 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS &gt; 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
-  },
-  {
    "fieldname": "additional_salary",
    "fieldtype": "Link",
    "label": "Additional Salary ",
-   "options": "Additional Salary"
+   "options": "Additional Salary",
+   "read_only": 1
   },
   {
    "default": "0",
@@ -207,11 +201,43 @@
    "fieldtype": "Check",
    "label": "Exempted from Income Tax",
    "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "section_break_5",
+   "fieldtype": "Section Break",
+   "label": "Component properties and references ",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "column_break_11",
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "section_break_19",
+   "fieldtype": "Section Break",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "column_break_18",
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
+  },
+  {
+   "fieldname": "column_break_24",
+   "fieldtype": "Column Break",
+   "show_days": 1,
+   "show_seconds": 1
   }
  ],
  "istable": 1,
  "links": [],
- "modified": "2020-06-22 23:21:26.300951",
+ "modified": "2020-07-01 12:13:41.956495",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Salary Detail",
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.js b/erpnext/payroll/doctype/salary_slip/salary_slip.js
index 4b623e5..7b69dbe 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.js
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.js
@@ -123,13 +123,13 @@
 			doc: frm.doc,
 			callback: function(r, rt) {
 				frm.refresh();
-				if (frm.doc.absent_days){
+				if (r.message){
 					frm.fields_dict.absent_days.set_description("Unmarked Days is treated as "+ r.message +". You can can change this in " + frappe.utils.get_form_link("Payroll Settings", "Payroll Settings", true));
 				}
 			}
 		});
 	}
-})
+});
 
 frappe.ui.form.on('Salary Slip Timesheet', {
 	time_sheet: function(frm, dt, dn) {
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.json b/erpnext/payroll/doctype/salary_slip/salary_slip.json
index 27a974a..619c45f 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.json
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.json
@@ -20,15 +20,17 @@
   "company",
   "letter_head",
   "section_break_10",
-  "salary_slip_based_on_timesheet",
   "start_date",
   "end_date",
   "salary_structure",
+  "column_break_18",
+  "salary_slip_based_on_timesheet",
   "payroll_frequency",
-  "column_break_15",
+  "section_break_20",
   "total_working_days",
   "unmarked_days",
   "leave_without_pay",
+  "column_break_24",
   "absent_days",
   "payment_days",
   "hourly_wages",
@@ -201,10 +203,6 @@
    "label": "End Date"
   },
   {
-   "fieldname": "column_break_15",
-   "fieldtype": "Column Break"
-  },
-  {
    "fieldname": "salary_structure",
    "fieldtype": "Link",
    "label": "Salary Structure",
@@ -490,13 +488,25 @@
    "fieldtype": "Float",
    "hidden": 1,
    "label": "Unmarked days"
+  },
+  {
+   "fieldname": "section_break_20",
+   "fieldtype": "Section Break"
+  },
+  {
+   "fieldname": "column_break_24",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "column_break_18",
+   "fieldtype": "Column Break"
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 9,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-07-22 12:41:03.659422",
+ "modified": "2020-08-11 17:37:54.274384",
  "modified_by": "Administrator",
  "module": "Payroll",
  "name": "Salary Slip",
diff --git a/erpnext/portal/doctype/homepage/homepage.js b/erpnext/portal/doctype/homepage/homepage.js
index ca34d69..c7c66e0 100644
--- a/erpnext/portal/doctype/homepage/homepage.js
+++ b/erpnext/portal/doctype/homepage/homepage.js
@@ -21,34 +21,6 @@
 });
 
 frappe.ui.form.on('Homepage Featured Product', {
-	item_code: function(frm, cdt, cdn) {
-		var featured_product = frappe.model.get_doc(cdt, cdn);
-		if (featured_product.item_code) {
-			frappe.call({
-				method: 'frappe.client.get_value',
-				args: {
-					'doctype': 'Item',
-					'filters': {'name': featured_product.item_code},
-					'fieldname': [
-						'item_name',
-						'web_long_description',
-						'description',
-						'image',
-						'thumbnail'
-					]
-				},
-				callback: function(r) {
-					if (!r.exc) {
-						$.extend(featured_product, r.message);
-						if (r.message.web_long_description) {
-							featured_product.description = r.message.web_long_description;
-						}
-						frm.refresh_field('products');
-					}
-				}
-			});
-		}
-	},
 
 	view: function(frm, cdt, cdn){
 		var child= locals[cdt][cdn]
diff --git a/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.json b/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.json
index c8b4ae9..01c32ef 100644
--- a/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.json
+++ b/erpnext/portal/doctype/homepage_featured_product/homepage_featured_product.json
@@ -1,301 +1,116 @@
 {
- "allow_copy": 0, 
- "allow_import": 0, 
- "allow_rename": 0, 
- "autoname": "hash", 
- "beta": 0, 
- "creation": "2016-04-22 05:57:06.261401", 
- "custom": 0, 
- "docstatus": 0, 
- "doctype": "DocType", 
- "document_type": "Document", 
- "editable_grid": 1, 
+ "actions": [],
+ "autoname": "hash",
+ "creation": "2016-04-22 05:57:06.261401",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "item_code",
+  "col_break1",
+  "item_name",
+  "view",
+  "section_break_5",
+  "description",
+  "column_break_7",
+  "image",
+  "thumbnail",
+  "route"
+ ],
  "fields": [
   {
-   "allow_on_submit": 0, 
-   "bold": 1, 
-   "collapsible": 0, 
-   "fieldname": "item_code", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 1, 
-   "in_list_view": 1, 
-   "label": "Item Code", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "item_code", 
-   "oldfieldtype": "Link", 
-   "options": "Item", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "print_width": "150px", 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 1, 
-   "set_only_once": 0, 
-   "unique": 0, 
+   "bold": 1,
+   "fieldname": "item_code",
+   "fieldtype": "Link",
+   "in_filter": 1,
+   "in_list_view": 1,
+   "label": "Item Code",
+   "oldfieldname": "item_code",
+   "oldfieldtype": "Link",
+   "options": "Item",
+   "print_width": "150px",
+   "reqd": 1,
+   "search_index": 1,
    "width": "150px"
-  }, 
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "col_break1", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "col_break1",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "item_name", 
-   "fieldtype": "Data", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "Item Name", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "item_name", 
-   "oldfieldtype": "Data", 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 1, 
-   "print_hide_if_no_value": 0, 
-   "print_width": "150", 
-   "read_only": 1, 
-   "report_hide": 0, 
-   "reqd": 1, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0, 
+   "fetch_from": "item_code.item_name",
+   "fetch_if_empty": 1,
+   "fieldname": "item_name",
+   "fieldtype": "Data",
+   "in_list_view": 1,
+   "label": "Item Name",
+   "oldfieldname": "item_name",
+   "oldfieldtype": "Data",
+   "print_hide": 1,
+   "print_width": "150",
+   "read_only": 1,
+   "reqd": 1,
    "width": "150"
-  }, 
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "view", 
-   "fieldtype": "Button", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 1, 
-   "label": "View", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "view",
+   "fieldtype": "Button",
+   "in_list_view": 1,
+   "label": "View"
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 1, 
-   "fieldname": "section_break_5", 
-   "fieldtype": "Section Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "label": "Description", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "collapsible": 1,
+   "fieldname": "section_break_5",
+   "fieldtype": "Section Break",
+   "label": "Description"
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "description", 
-   "fieldtype": "Text Editor", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 1, 
-   "in_list_view": 1, 
-   "label": "Description", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "description", 
-   "oldfieldtype": "Small Text", 
-   "options": "", 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "print_width": "300px", 
-   "read_only": 1, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0, 
+   "fetch_from": "item_code.web_long_description",
+   "fieldname": "description",
+   "fieldtype": "Text Editor",
+   "in_filter": 1,
+   "in_list_view": 1,
+   "label": "Description",
+   "oldfieldname": "description",
+   "oldfieldtype": "Small Text",
+   "print_width": "300px",
    "width": "300px"
-  }, 
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "column_break_7", 
-   "fieldtype": "Column Break", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "column_break_7",
+   "fieldtype": "Column Break"
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "image", 
-   "fieldtype": "Attach Image", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "label": "Image", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fetch_from": "item_code.website_image",
+   "fetch_if_empty": 1,
+   "fieldname": "image",
+   "fieldtype": "Attach Image",
+   "label": "Image"
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "thumbnail", 
-   "fieldtype": "Attach Image", 
-   "hidden": 1, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "label": "Thumbnail", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 0, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
-  }, 
+   "fieldname": "thumbnail",
+   "fieldtype": "Attach Image",
+   "hidden": 1,
+   "label": "Thumbnail"
+  },
   {
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "fieldname": "route", 
-   "fieldtype": "Small Text", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "label": "route", 
-   "length": 0, 
-   "no_copy": 0, 
-   "permlevel": 0, 
-   "precision": "", 
-   "print_hide": 0, 
-   "print_hide_if_no_value": 0, 
-   "read_only": 1, 
-   "report_hide": 0, 
-   "reqd": 0, 
-   "search_index": 0, 
-   "set_only_once": 0, 
-   "unique": 0
+   "fieldname": "route",
+   "fieldtype": "Small Text",
+   "label": "route",
+   "read_only": 1
   }
- ], 
- "hide_heading": 0, 
- "hide_toolbar": 0, 
- "idx": 0, 
- "image_view": 0, 
- "in_create": 0, 
-
- "is_submittable": 0, 
- "issingle": 0, 
- "istable": 1, 
- "max_attachments": 0, 
- "modified": "2016-08-09 06:09:34.731971", 
- "modified_by": "Administrator", 
- "module": "Portal", 
- "name": "Homepage Featured Product", 
- "name_case": "", 
- "owner": "Administrator", 
- "permissions": [], 
- "quick_entry": 1, 
- "read_only": 0, 
- "read_only_onload": 0, 
- "sort_field": "modified", 
- "sort_order": "DESC", 
- "track_seen": 0
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2020-08-25 15:27:49.573537",
+ "modified_by": "Administrator",
+ "module": "Portal",
+ "name": "Homepage Featured Product",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC"
 }
\ No newline at end of file
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index 5de2930..607c3fd 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -94,13 +94,6 @@
 		}
 	},
 
-	company: function(frm) {
-		frappe.db.get_value('Company', { 'company_name' : frm.doc.company }, 'standard_working_hours')
-			.then(({ message }) => {
-				(frappe.working_hours = message.standard_working_hours || 0);
-			});
-	},
-
 	make_invoice: function(frm) {
 		let dialog = new frappe.ui.Dialog({
 			title: __("Select Item (optional)"),
diff --git a/erpnext/public/js/communication.js b/erpnext/public/js/communication.js
index 5316eb4..26e5ab8 100644
--- a/erpnext/public/js/communication.js
+++ b/erpnext/public/js/communication.js
@@ -7,13 +7,13 @@
 	},
 
 	setup_custom_buttons: (frm) => {
-		let confirm_msg = "Are you sure you want to create {0} from this email";
+		let confirm_msg = "Are you sure you want to create {0} from this email?";
 		if(frm.doc.reference_doctype !== "Issue") {
 			frm.add_custom_button(__("Issue"), () => {
 				frappe.confirm(__(confirm_msg, [__("Issue")]), () => {
 					frm.trigger('make_issue_from_communication');
 				})
-			}, "Make");
+			}, "Create");
 		}
 
 		if(!in_list(["Lead", "Opportunity"], frm.doc.reference_doctype)) {
@@ -62,17 +62,36 @@
 	},
 
 	make_opportunity_from_communication: (frm) => {
-		return frappe.call({
-			method: "erpnext.crm.doctype.opportunity.opportunity.make_opportunity_from_communication",
-			args: {
-				communication: frm.doc.name
-			},
-			freeze: true,
-			callback: (r) => {
-				if(r.message) {
-					frm.reload_doc()
+		const fields = [{
+			fieldtype: 'Link',
+			label: __('Select a Company'),
+			fieldname: 'company',
+			options: 'Company',
+			reqd: 1,
+			default: frappe.defaults.get_user_default("Company")
+		}];
+
+		frappe.prompt(fields, data => {
+			frappe.call({
+				method: "erpnext.crm.doctype.opportunity.opportunity.make_opportunity_from_communication",
+				args: {
+					communication: frm.doc.name,
+					company: data.company
+				},
+				freeze: true,
+				callback: (r) => {
+					if(r.message) {
+						frm.reload_doc();
+						frappe.show_alert({
+							message: __("Opportunity {0} created",
+								['<a href="#Form/Opportunity/'+r.message+'">' + r.message + '</a>']),
+							indicator: 'green'
+						});
+					}
 				}
-			}
-		})
+			});
+		},
+		'Create an Opportunity',
+		'Create');
 	}
-});
\ No newline at end of file
+});
diff --git a/erpnext/public/js/conf.js b/erpnext/public/js/conf.js
index 9870f81..2af9140 100644
--- a/erpnext/public/js/conf.js
+++ b/erpnext/public/js/conf.js
@@ -3,32 +3,6 @@
 
 frappe.provide('erpnext');
 
-// add toolbar icon
-$(document).bind('toolbar_setup', function() {
-	frappe.app.name = "ERPNext";
-
-	frappe.help_feedback_link = '<p><a class="text-muted" \
-		href="https://discuss.erpnext.com">Feedback</a></p>'
-
-
-	$('[data-link="docs"]').attr("href", "https://erpnext.com/docs")
-	$('[data-link="issues"]').attr("href", "https://github.com/frappe/erpnext/issues")
-
-
-	// default documentation goes to erpnext
-	// $('[data-link-type="documentation"]').attr('data-path', '/erpnext/manual/index');
-
-	// additional help links for erpnext
-	var $help_menu = $('.dropdown-help ul .documentation-links');
-	$('<li><a data-link-type="forum" href="https://erpnext.com/docs/user/manual" \
-		target="_blank">'+__('Documentation')+'</a></li>').insertBefore($help_menu);
-	$('<li><a data-link-type="forum" href="https://discuss.erpnext.com" \
-		target="_blank">'+__('User Forum')+'</a></li>').insertBefore($help_menu);
-	$('<li><a href="https://github.com/frappe/erpnext/issues" \
-		target="_blank">'+__('Report an Issue')+'</a></li>').insertBefore($help_menu);
-
-});
-
 // preferred modules for breadcrumbs
 $.extend(frappe.breadcrumbs.preferred, {
 	"Item Group": "Stock",
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 405a33c..6951539 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -163,9 +163,11 @@
 		$.each(me.frm.doc["items"] || [], function(n, item) {
 			var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
 			var cumulated_tax_fraction = 0.0;
-
+			var total_inclusive_tax_amount_per_qty = 0;
 			$.each(me.frm.doc["taxes"] || [], function(i, tax) {
-				tax.tax_fraction_for_current_item = me.get_current_tax_fraction(tax, item_tax_map);
+				var current_tax_fraction = me.get_current_tax_fraction(tax, item_tax_map);
+				tax.tax_fraction_for_current_item = current_tax_fraction[0];
+				var inclusive_tax_amount_per_qty = current_tax_fraction[1];
 
 				if(i==0) {
 					tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item;
@@ -176,10 +178,12 @@
 				}
 
 				cumulated_tax_fraction += tax.tax_fraction_for_current_item;
+				total_inclusive_tax_amount_per_qty += inclusive_tax_amount_per_qty * flt(item.qty);
 			});
 
-			if(cumulated_tax_fraction && !me.discount_amount_applied) {
-				item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction));
+			if(!me.discount_amount_applied && item.qty && (total_inclusive_tax_amount_per_qty || cumulated_tax_fraction)) {
+				var amount = flt(item.amount) - total_inclusive_tax_amount_per_qty;
+				item.net_amount = flt(amount / (1 + cumulated_tax_fraction));
 				item.net_rate = item.qty ? flt(item.net_amount / item.qty, precision("net_rate", item)) : 0;
 
 				me.set_in_company_currency(item, ["net_rate", "net_amount"]);
@@ -191,6 +195,7 @@
 		// Get tax fraction for calculating tax exclusive amount
 		// from tax inclusive amount
 		var current_tax_fraction = 0.0;
+		var inclusive_tax_amount_per_qty = 0;
 
 		if(cint(tax.included_in_print_rate)) {
 			var tax_rate = this._get_tax_rate(tax, item_tax_map);
@@ -205,13 +210,16 @@
 			} else if(tax.charge_type == "On Previous Row Total") {
 				current_tax_fraction = (tax_rate / 100.0) *
 					this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_fraction_for_current_item;
+			} else if (tax.charge_type == "On Item Quantity") {
+				inclusive_tax_amount_per_qty = flt(tax_rate);
 			}
 		}
 
-		if(tax.add_deduct_tax) {
-			current_tax_fraction *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
+		if(tax.add_deduct_tax && tax.add_deduct_tax == "Deduct") {
+			current_tax_fraction *= -1;
+			inclusive_tax_amount_per_qty *= -1;
 		}
-		return current_tax_fraction;
+		return [current_tax_fraction, inclusive_tax_amount_per_qty];
 	},
 
 	_get_tax_rate: function(tax, item_tax_map) {
@@ -360,8 +368,9 @@
 		} else if(tax.charge_type == "On Previous Row Total") {
 			current_tax_amount = (tax_rate / 100.0) *
 				this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_for_current_item;
+		} else if (tax.charge_type == "On Item Quantity") {
+			current_tax_amount = tax_rate * item.qty;
 		}
-
 		this.set_item_wise_tax(item, tax, tax_rate, current_tax_amount);
 
 		return current_tax_amount;
@@ -573,7 +582,7 @@
 			var actual_taxes_dict = {};
 
 			$.each(this.frm.doc["taxes"] || [], function(i, tax) {
-				if (tax.charge_type == "Actual") {
+				if (in_list(["Actual", "On Item Quantity"], tax.charge_type)) {
 					var tax_amount = (tax.category == "Valuation") ? 0.0 : tax.tax_amount;
 					tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
 					actual_taxes_dict[tax.idx] = tax_amount;
@@ -586,7 +595,7 @@
 			$.each(actual_taxes_dict, function(key, value) {
 				if (value) total_actual_tax += value;
 			});
-
+			
 			return flt(this.frm.doc.grand_total - total_actual_tax, precision("grand_total"));
 		}
 	},
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 4e50f3d..792235f 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -781,10 +781,23 @@
 		else var date = this.frm.doc.transaction_date;
 
 		if (frappe.meta.get_docfield(this.frm.doctype, "shipping_address") &&
-			in_list(['Purchase Order', 'Purchase Receipt', 'Purchase Invoice'], this.frm.doctype)){
+			in_list(['Purchase Order', 'Purchase Receipt', 'Purchase Invoice'], this.frm.doctype)) {
 			erpnext.utils.get_shipping_address(this.frm, function(){
 				set_party_account(set_pricing);
 			})
+
+			// Get default company billing address in Purchase Invoice, Order and Receipt
+			frappe.call({
+				'method': 'frappe.contacts.doctype.address.address.get_default_address',
+				'args': {
+					'doctype': 'Company',
+					'name': this.frm.doc.company
+				},
+				'callback': function(r) {
+					me.frm.set_value('billing_address', r.message);
+				}
+			});
+
 		} else {
 			set_party_account(set_pricing);
 		}
@@ -1821,7 +1834,6 @@
 	},
 
 	set_query_for_item_tax_template: function(doc, cdt, cdn) {
-
 		var item = frappe.get_doc(cdt, cdn);
 		if(!item.item_code) {
 			frappe.throw(__("Please enter Item Code to get item taxes"));
@@ -1829,7 +1841,7 @@
 
 			let filters = {
 				'item_code': item.item_code,
-				'valid_from': doc.transaction_date || doc.bill_date || doc.posting_date,
+				'valid_from': ["<=", doc.transaction_date || doc.bill_date || doc.posting_date],
 				'item_group': item.item_group,
 			}
 
diff --git a/erpnext/public/less/products.less b/erpnext/public/less/products.less
index 79f57b3..5e744ce 100644
--- a/erpnext/public/less/products.less
+++ b/erpnext/public/less/products.less
@@ -22,6 +22,8 @@
 }
 
 .filter-options {
+	margin-left: -5px;
+	padding-left: 5px;
 	max-height: 300px;
 	overflow: auto;
 }
diff --git a/erpnext/public/less/website.less b/erpnext/public/less/website.less
index 57a0a33..ac878de 100644
--- a/erpnext/public/less/website.less
+++ b/erpnext/public/less/website.less
@@ -297,6 +297,10 @@
 	margin-top: 30px;
 }
 
+.item-group-slideshow {
+	margin-bottom: 1rem;
+}
+
 .product-image-img {
 	border: 1px solid @light-border-color;
 	border-radius: 3px;
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 2d306ba..787d557 100644
--- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
+++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
@@ -234,9 +234,6 @@
 						self.report_dict[supply_type][supply_category][account_map.get(account_type)] += \
 							flt(tax_details.get((account_name, gst_category), {}).get("amount"), 2)
 
-		for k, v in iteritems(account_map):
-			txval -= self.report_dict.get(supply_type, {}).get(supply_category, {}).get(v, 0)
-
 		self.report_dict[supply_type][supply_category]["txval"] += flt(txval, 2)
 
 	def set_inter_state_supply(self, inter_state_supply):
@@ -256,7 +253,7 @@
 	def get_total_taxable_value(self, doctype, reverse_charge):
 
 		return frappe._dict(frappe.db.sql("""
-			select gst_category, sum(base_grand_total) as total
+			select gst_category, sum(net_total) as total
 			from `tab{doctype}`
 			where docstatus = 1 and month(posting_date) = %s
 			and year(posting_date) = %s and reverse_charge = %s
@@ -309,26 +306,27 @@
 			inter_state_supply_tax_mapping.setdefault(d.name, {
 				'place_of_supply': d.place_of_supply,
 				'taxable_value': d.net_total,
+				'gst_category': d.gst_category,
 				'camt': 0.0,
 				'samt': 0.0,
 				'iamt': 0.0,
 				'csamt': 0.0
 			})
 
-			if d.account_head in [d.cgst_account for d in self.account_heads]:
+			if d.account_head in [a.cgst_account for a in self.account_heads]:
 				inter_state_supply_tax_mapping[d.name]['camt'] += d.tax_amount
 
-			if d.account_head in [d.sgst_account for d in self.account_heads]:
+			if d.account_head in [a.sgst_account for a in self.account_heads]:
 				inter_state_supply_tax_mapping[d.name]['samt'] += d.tax_amount
 
-			if d.account_head in [d.igst_account for d in self.account_heads]:
+			if d.account_head in [a.igst_account for a in self.account_heads]:
 				inter_state_supply_tax_mapping[d.name]['iamt'] += d.tax_amount
 
-			if d.account_head in [d.cess_account for d in self.account_heads]:
+			if d.account_head in [a.cess_account for a in self.account_heads]:
 				inter_state_supply_tax_mapping[d.name]['csamt'] += d.tax_amount
 
 		for key, value in iteritems(inter_state_supply_tax_mapping):
-			if d.place_of_supply:
+			if value.get('place_of_supply'):
 				osup_det = self.report_dict["sup_details"]["osup_det"]
 				osup_det["txval"] = flt(osup_det["txval"] + value['taxable_value'], 2)
 				osup_det["iamt"] = flt(osup_det["iamt"] + value['iamt'], 2)
@@ -336,15 +334,15 @@
 				osup_det["samt"] = flt(osup_det["samt"] + value['samt'], 2)
 				osup_det["csamt"] = flt(osup_det["csamt"] + value['csamt'], 2)
 
-				if state_number != d.place_of_supply.split("-")[0]:
-					inter_state_supply_details.setdefault((d.gst_category, d.place_of_supply), {
+				if state_number != value.get('place_of_supply').split("-")[0]:
+					inter_state_supply_details.setdefault((value.get('gst_category'), value.get('place_of_supply')), {
 						"txval": 0.0,
-						"pos": d.place_of_supply.split("-")[0],
+						"pos": value.get('place_of_supply').split("-")[0],
 						"iamt": 0.0
 					})
 
-					inter_state_supply_details[(d.gst_category, d.place_of_supply)]['txval'] += value['taxable_value']
-					inter_state_supply_details[(d.gst_category, d.place_of_supply)]['iamt'] += value['iamt']
+					inter_state_supply_details[(value.get('gst_category'), value.get('place_of_supply'))]['txval'] += value['taxable_value']
+					inter_state_supply_details[(value.get('gst_category'), value.get('place_of_supply'))]['iamt'] += value['iamt']
 
 		return inter_state_supply_details
 
diff --git a/erpnext/regional/india/__init__.py b/erpnext/regional/india/__init__.py
index 0ed98b7..d6221a8 100644
--- a/erpnext/regional/india/__init__.py
+++ b/erpnext/regional/india/__init__.py
@@ -10,8 +10,7 @@
  'Bihar',
  'Chandigarh',
  'Chhattisgarh',
- 'Dadra and Nagar Haveli',
- 'Daman and Diu',
+ 'Dadra and Nagar Haveli and Daman and Diu',
  'Delhi',
  'Goa',
  'Gujarat',
@@ -50,8 +49,7 @@
  "Bihar": "10",
  "Chandigarh": "04",
  "Chhattisgarh": "22",
- "Dadra and Nagar Haveli": "26",
- "Daman and Diu": "25",
+ "Dadra and Nagar Haveli and Daman and Diu": "26",
  "Delhi": "07",
  "Goa": "30",
  "Gujarat": "24",
diff --git a/erpnext/regional/india/gst_state_code_data.json b/erpnext/regional/india/gst_state_code_data.json
index 6dab81d..ff88e0f 100644
--- a/erpnext/regional/india/gst_state_code_data.json
+++ b/erpnext/regional/india/gst_state_code_data.json
@@ -135,14 +135,9 @@
   "state_name": "Delhi"
  },
  {
-  "state_number": "25",
-  "state_code": "DD",
-  "state_name": "Daman and Diu"
- },
- {
   "state_number": "26",
   "state_code": "DN",
-  "state_name": "Dadra and Nagar Haveli"
+  "state_name": "Dadra and Nagar Haveli and Daman and Diu"
  },
  {
   "state_number": "22",
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index fe7e0c8..69e47a4 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -1,6 +1,7 @@
 from __future__ import unicode_literals
 import frappe, re, json
 from frappe import _
+import erpnext
 from frappe.utils import cstr, flt, date_diff, nowdate, round_based_on_smallest_currency_fraction, money_in_words
 from erpnext.regional.india import states, state_numbers
 from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_taxable_amount
@@ -673,25 +674,34 @@
 	if country != 'India':
 		return
 
+	if not doc.total_taxes_and_charges:
+		return
+
 	if doc.reverse_charge == 'Y':
 		gst_accounts = get_gst_accounts(doc.company)
 		gst_account_list = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
 			+ gst_accounts.get('igst_account')
 
+		base_gst_tax = 0
 		gst_tax = 0
+
 		for tax in doc.get('taxes'):
 			if tax.category not in ("Total", "Valuation and Total"):
 				continue
 
 			if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in gst_account_list:
-				gst_tax += tax.base_tax_amount_after_discount_amount
+				base_gst_tax += tax.base_tax_amount_after_discount_amount
+				gst_tax += tax.tax_amount_after_discount_amount
 
 		doc.taxes_and_charges_added -= gst_tax
 		doc.total_taxes_and_charges -= gst_tax
+		doc.base_taxes_and_charges_added -= base_gst_tax
+		doc.base_total_taxes_and_charges -= base_gst_tax
 
-		update_totals(gst_tax, doc)
+		update_totals(gst_tax, base_gst_tax, doc)
 
-def update_totals(gst_tax, doc):
+def update_totals(gst_tax, base_gst_tax, doc):
+	doc.base_grand_total -= base_gst_tax
 	doc.grand_total -= gst_tax
 
 	if doc.meta.get_field("rounded_total"):
@@ -707,13 +717,14 @@
 			doc.outstanding_amount = doc.rounded_total or doc.grand_total
 
 	doc.in_words = money_in_words(doc.grand_total, doc.currency)
+	doc.base_in_words = money_in_words(doc.base_grand_total, erpnext.get_company_currency(doc.company))
 	doc.set_payment_schedule()
 
 def make_regional_gl_entries(gl_entries, doc):
 	country = frappe.get_cached_value('Company', doc.company, 'country')
 
 	if country != 'India':
-		return
+		return gl_entries
 
 	if doc.reverse_charge == 'Y':
 		gst_accounts = get_gst_accounts(doc.company)
@@ -724,6 +735,7 @@
 			if tax.category not in ("Total", "Valuation and Total"):
 				continue
 
+			dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
 			if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in gst_account_list:
 				account_currency = get_account_currency(tax.account_head)
 
@@ -733,8 +745,8 @@
 						"cost_center": tax.cost_center,
 						"posting_date": doc.posting_date,
 						"against": doc.supplier,
-						"credit": tax.base_tax_amount_after_discount_amount,
-						"credits_in_account_currency": tax.base_tax_amount_after_discount_amount \
+						dr_or_cr: tax.base_tax_amount_after_discount_amount,
+						dr_or_cr + "_in_account_currency": tax.base_tax_amount_after_discount_amount \
 							if account_currency==doc.company_currency \
 							else tax.tax_amount_after_discount_amount
 					}, account_currency, item=tax)
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 8885b88..282efe4 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -131,6 +131,9 @@
 					taxable_value += abs(net_amount)
 				elif tax_rate:
 					taxable_value += abs(net_amount)
+				elif not tax_rate and self.filters.get('type_of_business') == 'EXPORT' \
+					and invoice_details.get('export_type') == "Without Payment of Tax":
+					taxable_value += abs(net_amount)
 
 		row += [tax_rate or 0, taxable_value]
 
diff --git a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js
index dfdf9dc..b757d53 100644
--- a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js
+++ b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.js
@@ -46,5 +46,28 @@
 	],
 	onload: (report) => {
 		fetch_gstins(report);
+
+		report.page.add_inner_button(__("Download JSON"), function () {
+			var filters = report.get_values();
+
+			frappe.call({
+				method: 'erpnext.regional.report.hsn_wise_summary_of_outward_supplies.hsn_wise_summary_of_outward_supplies.get_json',
+				args: {
+					data: report.data,
+					report_name: report.report_name,
+					filters: filters
+				},
+				callback: function(r) {
+					if (r.message) {
+						const args = {
+							cmd: 'erpnext.regional.report.hsn_wise_summary_of_outward_supplies.hsn_wise_summary_of_outward_supplies.download_json_file',
+							data: r.message.data,
+							report_name: r.message.report_name
+						};
+						open_url_post(frappe.request.url, args);
+					}
+				}
+			});
+		});
 	}
 };
diff --git a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py
index 222dfa1..59389ce 100644
--- a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py
+++ b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py
@@ -4,9 +4,13 @@
 from __future__ import unicode_literals
 import frappe, erpnext
 from frappe import _
-from frappe.utils import flt
+from frappe.utils import flt, getdate, cstr
 from frappe.model.meta import get_field_precision
 from frappe.utils.xlsxutils import handle_html
+from six import iteritems
+import json
+from erpnext.regional.india.utils import get_gst_accounts
+from erpnext.regional.report.gstr_1.gstr_1 import get_company_gstin_number
 
 def execute(filters=None):
 	return _execute(filters)
@@ -21,21 +25,24 @@
 		itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency)
 
 	data = []
+	added_item = []
 	for d in item_list:
-		row = [d.gst_hsn_code, d.description, d.stock_uom, d.stock_qty]
-		total_tax = 0
-		for tax in tax_columns:
-			item_tax = itemised_tax.get(d.name, {}).get(tax, {})
-			total_tax += flt(item_tax.get("tax_amount"))
+		if (d.parent, d.item_code) not in added_item:
+			row = [d.gst_hsn_code, d.description, d.stock_uom, d.stock_qty]
+			total_tax = 0
+			for tax in tax_columns:
+				item_tax = itemised_tax.get((d.parent, d.item_code), {}).get(tax, {})
+				total_tax += flt(item_tax.get("tax_amount", 0))
 
-		row += [d.base_net_amount + total_tax]
-		row += [d.base_net_amount]
+			row += [d.base_net_amount + total_tax]
+			row += [d.base_net_amount]
 
-		for tax in tax_columns:
-			item_tax = itemised_tax.get(d.name, {}).get(tax, {})
-			row += [item_tax.get("tax_amount", 0)]
+			for tax in tax_columns:
+				item_tax = itemised_tax.get((d.parent, d.item_code), {}).get(tax, {})
+				row += [item_tax.get("tax_amount", 0)]
 
-		data.append(row)
+			data.append(row)
+			added_item.append((d.parent, d.item_code))
 	if data:
 		data = get_merged_data(columns, data) # merge same hsn code data
 	return columns, data
@@ -103,7 +110,7 @@
 		match_conditions = " and {0} ".format(match_conditions)
 
 
-	return frappe.db.sql("""
+	items = frappe.db.sql("""
 		select
 			`tabSales Invoice Item`.name, `tabSales Invoice Item`.base_price_list_rate,
 			`tabSales Invoice Item`.gst_hsn_code, `tabSales Invoice Item`.stock_qty,
@@ -118,10 +125,9 @@
 
 		""" % (conditions, match_conditions), filters, as_dict=1)
 
+	return items
 
-def get_tax_accounts(item_list, columns, company_currency,
-		doctype="Sales Invoice", tax_doctype="Sales Taxes and Charges"):
-	import json
+def get_tax_accounts(item_list, columns, company_currency, doctype="Sales Invoice", tax_doctype="Sales Taxes and Charges"):
 	item_row_map = {}
 	tax_columns = []
 	invoice_item_row = {}
@@ -137,7 +143,7 @@
 
 	tax_details = frappe.db.sql("""
 		select
-			parent, description, item_wise_tax_detail,
+			parent, account_head, item_wise_tax_detail,
 			base_tax_amount_after_discount_amount
 		from `tab%s`
 		where
@@ -149,11 +155,11 @@
 	""" % (tax_doctype, '%s', ', '.join(['%s']*len(invoice_item_row)), conditions),
 		tuple([doctype] + list(invoice_item_row)))
 
-	for parent, description, item_wise_tax_detail, tax_amount in tax_details:
-		description = handle_html(description)
-		if description not in tax_columns and tax_amount:
+	for parent, account_head, item_wise_tax_detail, tax_amount in tax_details:
+
+		if account_head not in tax_columns and tax_amount:
 			# as description is text editor earlier and markup can break the column convention in reports
-			tax_columns.append(description)
+			tax_columns.append(account_head)
 
 		if item_wise_tax_detail:
 			try:
@@ -171,50 +177,113 @@
 					for d in item_row_map.get(parent, {}).get(item_code, []):
 						item_tax_amount = tax_amount
 						if item_tax_amount:
-							itemised_tax.setdefault(d.name, {})[description] = frappe._dict({
+							itemised_tax.setdefault((parent, item_code), {})[account_head] = frappe._dict({
 								"tax_amount": flt(item_tax_amount, tax_amount_precision)
 							})
 			except ValueError:
 				continue
 
 	tax_columns.sort()
-	for desc in tax_columns:
-		columns.append(desc + " Amount:Currency/currency:160")
+	for account_head in tax_columns:
+		columns.append({
+			"label": account_head,
+			"fieldname": frappe.scrub(account_head),
+			"fieldtype": "Float",
+			"width": 110
+		})
 
-	# columns += ["Total Amount:Currency/currency:110"]
 	return itemised_tax, tax_columns
 
 def get_merged_data(columns, data):
 	merged_hsn_dict = {} # to group same hsn under one key and perform row addition
-	add_column_index = [] # store index of columns that needs to be added
-	tax_col = len(get_columns())
-	fields_to_merge = ["stock_qty", "total_amount", "taxable_amount"] # columns for which index needs to be found
-
-	for i,d in enumerate(columns):
-		# check if fieldname in to_merge list and ignore tax-columns
-		if i < tax_col and d["fieldname"] in fields_to_merge:
-			add_column_index.append(i)
+	result = []
 
 	for row in data:
-		if row[0] in merged_hsn_dict:
-			to_add_row = merged_hsn_dict.get(row[0])
+		merged_hsn_dict.setdefault(row[0], {})
+		for i, d in enumerate(columns):
+			if d['fieldtype'] not in ('Int', 'Float', 'Currency'):
+				merged_hsn_dict[row[0]][d['fieldname']] = row[i]
+			else:
+				if merged_hsn_dict.get(row[0], {}).get(d['fieldname'], ''):
+					merged_hsn_dict[row[0]][d['fieldname']] += row[i]
+				else:
+					merged_hsn_dict[row[0]][d['fieldname']] = row[i]
 
-			# add columns from the add_column_index table
-			for k in add_column_index:
-				to_add_row[k] += row[k]
+	for key, value in iteritems(merged_hsn_dict):
+		result.append(value)
 
-			# add tax columns
-			for k in range(len(columns)):
-				if tax_col <= k < len(columns):
-					to_add_row[k] += row[k]
+	return result
 
-			# update hsn dict with the newly added data
-			merged_hsn_dict[row[0]] = to_add_row
-		else:
-			merged_hsn_dict[row[0]] = row
+@frappe.whitelist()
+def get_json(filters, report_name, data):
+	filters = json.loads(filters)
+	report_data = json.loads(data)
+	gstin = filters.get('company_gstin') or get_company_gstin_number(filters["company"])
 
-	# extract data rows to be displayed in report
-	data = [merged_hsn_dict[d] for d in merged_hsn_dict]
+	if not filters.get('from_date') or not filters.get('to_date'):
+		frappe.throw(_("Please enter From Date and To Date to generate JSON"))
+
+	fp = "%02d%s" % (getdate(filters["to_date"]).month, getdate(filters["to_date"]).year)
+
+	gst_json = {"version": "GST2.3.4",
+		"hash": "hash", "gstin": gstin, "fp": fp}
+
+	gst_json["hsn"] = {
+		"data": get_hsn_wise_json_data(filters, report_data)
+	}
+
+	return {
+		'report_name': report_name,
+		'data': gst_json
+	}
+
+@frappe.whitelist()
+def download_json_file():
+	'''download json content in a file'''
+	data = frappe._dict(frappe.local.form_dict)
+	frappe.response['filename'] = frappe.scrub("{0}".format(data['report_name'])) + '.json'
+	frappe.response['filecontent'] = data['data']
+	frappe.response['content_type'] = 'application/json'
+	frappe.response['type'] = 'download'
+
+def get_hsn_wise_json_data(filters, report_data):
+
+	filters = frappe._dict(filters)
+	gst_accounts = get_gst_accounts(filters.company)
+	data = []
+	count = 1
+
+	for hsn in report_data:
+		row = {
+			"num": count,
+			"hsn_sc": hsn.get("gst_hsn_code"),
+			"desc": hsn.get("description"),
+			"uqc": hsn.get("stock_uom").upper(),
+			"qty": hsn.get("stock_qty"),
+			"val": flt(hsn.get("total_amount"), 2),
+			"txval": flt(hsn.get("taxable_amount", 2)),
+			"iamt": 0.0,
+			"camt": 0.0,
+			"samt": 0.0,
+			"csamt": 0.0
+
+		}
+
+		for account in gst_accounts.get('igst_account'):
+			row['iamt'] += flt(hsn.get(frappe.scrub(cstr(account)), 0.0), 2)
+
+		for account in gst_accounts.get('cgst_account'):
+			row['camt'] += flt(hsn.get(frappe.scrub(cstr(account)), 0.0), 2)
+
+		for account in gst_accounts.get('sgst_account'):
+			row['samt'] += flt(hsn.get(frappe.scrub(cstr(account)), 0.0), 2)
+
+		for account in gst_accounts.get('cess_account'):
+			row['csamt'] += flt(hsn.get(frappe.scrub(cstr(account)), 0.0), 2)
+
+		data.append(row)
+		count +=1
 
 	return data
 
+
diff --git a/erpnext/selling/desk_page/retail/retail.json b/erpnext/selling/desk_page/retail/retail.json
index 7b30af2..581e14c 100644
--- a/erpnext/selling/desk_page/retail/retail.json
+++ b/erpnext/selling/desk_page/retail/retail.json
@@ -3,7 +3,7 @@
   {
    "hidden": 0,
    "label": "Retail Operations",
-   "links": "[\n    {\n        \"description\": \"Setup default values for POS Invoices\",\n        \"label\": \"Point-of-Sale Profile\",\n        \"name\": \"POS Profile\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"POS Profile\"\n        ],\n        \"description\": \"Point of Sale\",\n        \"label\": \"POS\",\n        \"name\": \"pos\",\n        \"onboard\": 1,\n        \"type\": \"page\"\n    },\n    {\n        \"description\": \"Cashier Closing\",\n        \"label\": \"Cashier Closing\",\n        \"name\": \"Cashier Closing\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Setup mode of POS (Online / Offline)\",\n        \"label\": \"POS Settings\",\n        \"name\": \"POS Settings\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"To make Customer based incentive schemes.\",\n        \"label\": \"Loyalty Program\",\n        \"name\": \"Loyalty Program\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"To view logs of Loyalty Points assigned to a Customer.\",\n        \"label\": \"Loyalty Point Entry\",\n        \"name\": \"Loyalty Point Entry\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n    {\n        \"description\": \"Setup default values for POS Invoices\",\n        \"label\": \"Point of Sale Profile\",\n        \"name\": \"POS Profile\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n    },\n    {\n        \"dependencies\": [\n            \"POS Profile\"\n        ],\n        \"description\": \"Point of Sale\",\n        \"label\": \"Point of Sale\",\n        \"name\": \"point-of-sale\",\n        \"onboard\": 1,\n        \"type\": \"page\"\n    },\n    {\n        \"description\": \"Setup mode of POS (Online / Offline)\",\n        \"label\": \"POS Settings\",\n        \"name\": \"POS Settings\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Cashier Closing\",\n        \"label\": \"Cashier Closing\",\n        \"name\": \"Cashier Closing\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"To make Customer based incentive schemes.\",\n        \"label\": \"Loyalty Program\",\n        \"name\": \"Loyalty Program\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"To view logs of Loyalty Points assigned to a Customer.\",\n        \"label\": \"Loyalty Point Entry\",\n        \"name\": \"Loyalty Point Entry\",\n        \"type\": \"doctype\"\n    }\n]"
   }
  ],
  "category": "Domains",
@@ -14,10 +14,11 @@
  "docstatus": 0,
  "doctype": "Desk Page",
  "extends_another_page": 0,
+ "hide_custom": 0,
  "idx": 0,
  "is_standard": 1,
  "label": "Retail",
- "modified": "2020-04-26 22:42:39.346750",
+ "modified": "2020-08-20 18:00:07.515691",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Retail",
@@ -25,5 +26,27 @@
  "pin_to_bottom": 0,
  "pin_to_top": 0,
  "restrict_to_domain": "Retail",
- "shortcuts": []
+ "shortcuts": [
+  {
+   "color": "#9deca2",
+   "doc_view": "",
+   "format": "{} Active",
+   "label": "Point of Sale Profile",
+   "link_to": "POS Profile",
+   "stats_filter": "{\n    \"disabled\": 0\n}",
+   "type": "DocType"
+  },
+  {
+   "doc_view": "",
+   "label": "Point of Sale",
+   "link_to": "point-of-sale",
+   "type": "Page"
+  },
+  {
+   "doc_view": "",
+   "label": "POS Settings",
+   "link_to": "POS Settings",
+   "type": "DocType"
+  }
+ ]
 }
\ No newline at end of file
diff --git a/erpnext/selling/desk_page/selling/selling.json b/erpnext/selling/desk_page/selling/selling.json
index 2252382..4c09ee9 100644
--- a/erpnext/selling/desk_page/selling/selling.json
+++ b/erpnext/selling/desk_page/selling/selling.json
@@ -18,7 +18,7 @@
   {
    "hidden": 0,
    "label": "Key Reports",
-   "links": "[\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Analytics\",\n        \"name\": \"Sales Analytics\",\n        \"onboard\": 1,\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Order Analysis\",\n        \"name\": \"Sales Order Analysis\",\n        \"onboard\": 1,\n        \"type\": \"report\"\n    },\n    {\n        \"icon\": \"fa fa-bar-chart\",\n        \"label\": \"Sales Funnel\",\n        \"name\": \"sales-funnel\",\n        \"onboard\": 1,\n        \"type\": \"page\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Order Trends\",\n        \"name\": \"Sales Order Trends\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Quotation\"\n        ],\n        \"doctype\": \"Quotation\",\n        \"is_query_report\": true,\n        \"label\": \"Quotation Trends\",\n        \"name\": \"Quotation Trends\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Customer\"\n        ],\n        \"doctype\": \"Customer\",\n        \"icon\": \"fa fa-bar-chart\",\n        \"is_query_report\": true,\n        \"label\": \"Customer Acquisition and Loyalty\",\n        \"name\": \"Customer Acquisition and Loyalty\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Inactive Customers\",\n        \"name\": \"Inactive Customers\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Person-wise Transaction Summary\",\n        \"name\": \"Sales Person-wise Transaction Summary\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\"\n        ],\n        \"doctype\": \"Item\",\n        \"is_query_report\": true,\n        \"label\": \"Item-wise Sales History\",\n        \"name\": \"Item-wise Sales History\",\n        \"type\": \"report\"\n    }\n]"
+   "links": "[\n    {\n     \n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Analytics\",\n        \"name\": \"Sales Analytics\",\n        \"onboard\": 1,\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Order Analysis\",\n        \"name\": \"Sales Order Analysis\",\n        \"onboard\": 1,\n        \"type\": \"report\"\n    },\n    {\n        \"icon\": \"fa fa-bar-chart\",\n        \"label\": \"Sales Funnel\",\n        \"name\": \"sales-funnel\",\n        \"onboard\": 1,\n        \"type\": \"page\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Order Trends\",\n        \"name\": \"Sales Order Trends\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Quotation\"\n        ],\n        \"doctype\": \"Quotation\",\n        \"is_query_report\": true,\n        \"label\": \"Quotation Trends\",\n        \"name\": \"Quotation Trends\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Customer\"\n        ],\n        \"doctype\": \"Customer\",\n        \"icon\": \"fa fa-bar-chart\",\n        \"is_query_report\": true,\n        \"label\": \"Customer Acquisition and Loyalty\",\n        \"name\": \"Customer Acquisition and Loyalty\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Inactive Customers\",\n        \"name\": \"Inactive Customers\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Sales Order\"\n        ],\n        \"doctype\": \"Sales Order\",\n        \"is_query_report\": true,\n        \"label\": \"Sales Person-wise Transaction Summary\",\n        \"name\": \"Sales Person-wise Transaction Summary\",\n        \"type\": \"report\"\n    },\n    {\n        \"dependencies\": [\n            \"Item\"\n        ],\n        \"doctype\": \"Item\",\n        \"is_query_report\": true,\n        \"label\": \"Item-wise Sales History\",\n        \"name\": \"Item-wise Sales History\",\n        \"type\": \"report\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -44,7 +44,7 @@
  "idx": 0,
  "is_standard": 1,
  "label": "Selling",
- "modified": "2020-06-29 19:26:35.139097",
+ "modified": "2020-08-15 10:12:53.131621",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Selling",
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index ca62488..93d4832 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -184,6 +184,14 @@
 	def validate_credit_limit_on_change(self):
 		if self.get("__islocal") or not self.credit_limits:
 			return
+		
+		past_credit_limits = [d.credit_limit
+			for d in frappe.db.get_all("Customer Credit Limit", filters={'parent': self.name}, fields=["credit_limit"], order_by="company")]
+		
+		current_credit_limits = [d.credit_limit for d in sorted(self.credit_limits, key=lambda k: k.company)]
+
+		if past_credit_limits == current_credit_limits:
+			return
 
 		company_record = []
 		for limit in self.credit_limits:
diff --git a/erpnext/selling/doctype/customer/customer_dashboard.py b/erpnext/selling/doctype/customer/customer_dashboard.py
index 22e30e3..532c11b 100644
--- a/erpnext/selling/doctype/customer/customer_dashboard.py
+++ b/erpnext/selling/doctype/customer/customer_dashboard.py
@@ -12,7 +12,8 @@
 			'Payment Entry': 'party',
 			'Quotation': 'party_name',
 			'Opportunity': 'party_name',
-			'Bank Account': 'party'
+			'Bank Account': 'party',
+			'Subscription': 'party'
 		},
 		'dynamic_links': {
 			'party_name': ['Customer', 'quotation_to']
@@ -32,7 +33,7 @@
 			},
 			{
 				'label': _('Support'),
-				'items': ['Issue']
+				'items': ['Issue', 'Maintenance Visit', 'Installation Note', 'Warranty Claim']
 			},
 			{
 				'label': _('Projects'),
diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json
index 6d34c2a..5b85187 100644
--- a/erpnext/selling/doctype/quotation/quotation.json
+++ b/erpnext/selling/doctype/quotation/quotation.json
@@ -923,7 +923,7 @@
    "fieldname": "lost_reasons",
    "fieldtype": "Table MultiSelect",
    "label": "Lost Reasons",
-   "options": "Lost Reason Detail",
+   "options": "Quotation Lost Reason Detail",
    "read_only": 1
   }
  ],
@@ -932,7 +932,7 @@
  "is_submittable": 1,
  "links": [],
  "max_attachments": 1,
- "modified": "2020-07-18 04:59:09.960118",
+ "modified": "2020-07-26 17:46:19.951223",
  "modified_by": "Administrator",
  "module": "Selling",
  "name": "Quotation",
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index 449a968..20ae19f 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -68,7 +68,7 @@
 
 	def declare_enquiry_lost(self, lost_reasons_list, detailed_reason=None):
 		if not self.has_sales_order():
-			get_lost_reasons = frappe.get_list('Opportunity Lost Reason',
+			get_lost_reasons = frappe.get_list('Quotation Lost Reason',
 			fields = ["name"])
 			lost_reasons_lst = [reason.get('name') for reason in get_lost_reasons]
 			frappe.db.set(self, 'status', 'Lost')
@@ -285,9 +285,17 @@
 						return customer
 					else:
 						raise
-				except frappe.MandatoryError:
+				except frappe.MandatoryError as e:
+					mandatory_fields = e.args[0].split(':')[1].split(',')
+					mandatory_fields = [customer.meta.get_label(field.strip()) for field in mandatory_fields]
+
 					frappe.local.message_log = []
-					frappe.throw(_("Please create Customer from Lead {0}").format(lead_name))
+					lead_link = frappe.utils.get_link_to_form("Lead", lead_name)
+					message = _("Could not auto create Customer due to the following missing mandatory field(s):") + "<br>"
+					message += "<br><ul><li>" + "</li><li>".join(mandatory_fields) + "</li></ul>"
+					message += _("Please create Customer from Lead {0}.").format(lead_link)
+
+					frappe.throw(message, title=_("Mandatory Missing"))
 			else:
 				return customer_name
 		else:
diff --git a/erpnext/selling/doctype/sales_order/sales_order_dashboard.py b/erpnext/selling/doctype/sales_order/sales_order_dashboard.py
index 4126bc6..05a760d 100644
--- a/erpnext/selling/doctype/sales_order/sales_order_dashboard.py
+++ b/erpnext/selling/doctype/sales_order/sales_order_dashboard.py
@@ -10,6 +10,7 @@
 			'Payment Entry': 'reference_name',
 			'Payment Request': 'reference_name',
 			'Auto Repeat': 'reference_document',
+			'Maintenance Visit': 'prevdoc_docname'
 		},
 		'internal_links': {
 			'Quotation': ['items', 'prevdoc_docname']
@@ -17,7 +18,7 @@
 		'transactions': [
 			{
 				'label': _('Fulfillment'),
-				'items': ['Sales Invoice', 'Pick List', 'Delivery Note']
+				'items': ['Sales Invoice', 'Pick List', 'Delivery Note', 'Maintenance Visit']
 			},
 			{
 				'label': _('Purchasing'),
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py
index 9f8410f..83bd71d 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -14,10 +14,9 @@
 def get_items(start, page_length, price_list, item_group, search_value="", pos_profile=None):
 	data = dict()
 	warehouse = ""
-	display_items_in_stock = 0
 
 	if pos_profile:
-		warehouse, display_items_in_stock = frappe.db.get_value('POS Profile', pos_profile, ['warehouse', 'display_items_in_stock'])
+		warehouse = frappe.db.get_value('POS Profile', pos_profile, ['warehouse'])
 
 	if not frappe.db.exists('Item Group', item_group):
 		item_group = get_root_of('Item Group')
@@ -85,7 +84,7 @@
 			item_price = item_prices.get(item_code) or {}
 			item_stock_qty = get_stock_availability(item_code, warehouse)
 
-			if display_items_in_stock and not item_stock_qty:
+			if not item_stock_qty:
 				pass
 			else:
 				row = {}
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
index 483ef78..ae5471b 100644
--- a/erpnext/selling/page/point_of_sale/pos_controller.js
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -35,7 +35,8 @@
 	create_opening_voucher() {
 		const table_fields = [
 			{ fieldname: "mode_of_payment", fieldtype: "Link", in_list_view: 1, label: "Mode of Payment", options: "Mode of Payment", reqd: 1 },
-			{ fieldname: "opening_amount", fieldtype: "Currency", in_list_view: 1, label: "Opening Amount", options: "company:company_currency", reqd: 1 }
+			{ fieldname: "opening_amount", fieldtype: "Currency", default: 0, in_list_view: 1, label: "Opening Amount", 
+				options: "company:company_currency", reqd: 1 }
 		];
 
 		const dialog = new frappe.ui.Dialog({
@@ -66,7 +67,7 @@
 							frappe.db.get_doc("POS Closing Entry", pos_closing_entry.name).then(({ payment_reconciliation }) => {
 								dialog.fields_dict.balance_details.df.data = [];
 								payment_reconciliation.forEach(pay => {
-									const { mode_of_payment, closing_amount } = pay;
+									const { mode_of_payment } = pay;
 									dialog.fields_dict.balance_details.df.data.push({
 										mode_of_payment: mode_of_payment
 									});
@@ -152,7 +153,7 @@
 			},
 			() => this.make_new_invoice(),
 			() => frappe.dom.unfreeze(),
-			() => this.page.set_title(__('Point of Sale Beta')),
+			() => this.page.set_title(__('Point of Sale')),
 		]);
 	}
 
diff --git a/erpnext/selling/page/point_of_sale/pos_item_cart.js b/erpnext/selling/page/point_of_sale/pos_item_cart.js
index c23a6ad..eadeb8f 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_cart.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_cart.js
@@ -356,7 +356,7 @@
 				onchange: function() {
 					if (this.value || this.value == 0) {
 						const frm = me.events.get_frm();
-						frappe.model.set_value(frm.doc.doctype, frm.doc.name, 'additional_discount_percentage', this.value);
+						frappe.model.set_value(frm.doc.doctype, frm.doc.name, 'additional_discount_percentage', flt(this.value));
 						me.hide_discount_control(this.value);
 					}
 				},
@@ -948,4 +948,4 @@
 		show ? this.$component.removeClass('d-none') : this.$component.addClass('d-none');
     }
     
-}
\ No newline at end of file
+}
diff --git a/erpnext/selling/page/point_of_sale/pos_past_order_summary.js b/erpnext/selling/page/point_of_sale/pos_past_order_summary.js
index 24326b2..30e0918 100644
--- a/erpnext/selling/page/point_of_sale/pos_past_order_summary.js
+++ b/erpnext/selling/page/point_of_sale/pos_past_order_summary.js
@@ -86,7 +86,7 @@
         this.$summary_container.append(
             `<div class="summary-btns flex summary-btns justify-between w-full f-shrink-0"></div>`
         )
-        
+
         this.$summary_btns = this.$summary_container.find('.summary-btns');
     }
 
@@ -110,7 +110,10 @@
                 {fieldname:'print', fieldtype:'Data', label:'Print Preview'}
             ],
             primary_action: () => {
-                this.events.get_frm().print_preview.printit(true);
+                const frm = this.events.get_frm();
+                frm.doc = this.doc;
+                frm.print_preview.lang_code = frm.doc.language;
+                frm.print_preview.printit(true);
             },
             primary_action_label: __('Print'),
         });
@@ -174,7 +177,7 @@
                     <div class="flex">
                         <div class="text-md-0 text-dark-grey text-bold w-fit">Tax Charges</div>
                         <div class="flex ml-6 text-dark-grey">
-                        ${	
+                        ${
                             doc.taxes.map((t, i) => {
                                 let margin_left = '';
                                 if (i !== 0) margin_left = 'ml-2';
@@ -271,6 +274,7 @@
             // this.print_dialog.show();
             const frm = this.events.get_frm();
             frm.doc = this.doc;
+            frm.print_preview.lang_code = frm.doc.language;
             frm.print_preview.printit(true);
         });
     }
@@ -284,9 +288,9 @@
             this.$summary_container.find('.print-btn').click();
         });
     }
-    
+
     toggle_component(show) {
-        show ? 
+        show ?
         this.$component.removeClass('d-none') :
         this.$component.addClass('d-none');
     }
@@ -372,9 +376,9 @@
     }
 
     get_condition_btn_map(after_submission) {
-        if (after_submission) 
+        if (after_submission)
             return [{ condition: true, visible_btns: ['Print Receipt', 'Email Receipt', 'New Order'] }];
-        
+
         return [
             { condition: this.doc.docstatus === 0, visible_btns: ['Edit Order'] },
             { condition: !this.doc.is_return && this.doc.docstatus === 1, visible_btns: ['Print Receipt', 'Email Receipt', 'Return']},
@@ -384,7 +388,7 @@
 
     load_summary_of(doc, after_submission=false) {
         this.$summary_wrapper.removeClass("d-none");
-        
+
         after_submission ?
             this.switch_to_post_submit_summary() : this.switch_to_recent_invoice_summary();
 
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index 333a563..002cfe4 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -494,13 +494,18 @@
 		var dialog = new frappe.ui.Dialog({
 			title: __("Set as Lost"),
 			fields: [
-				{"fieldtype": "Table MultiSelect",
-				"label": __("Lost Reasons"),
-				"fieldname": "lost_reason",
-				"options": "Lost Reason Detail",
-				"reqd": 1},
-
-				{"fieldtype": "Text", "label": __("Detailed Reason"), "fieldname": "detailed_reason"},
+				{
+					"fieldtype": "Table MultiSelect",
+					"label": __("Lost Reasons"),
+					"fieldname": "lost_reason",
+					"options": frm.doctype === 'Opportunity' ? 'Opportunity Lost Reason Detail': 'Quotation Lost Reason Detail',
+					"reqd": 1
+				},
+				{
+					"fieldtype": "Text",
+					"label": __("Detailed Reason"),
+					"fieldname": "detailed_reason"
+				},
 			],
 			primary_action: function() {
 				var values = dialog.get_values();
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 7ae5385..f882db6 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -34,6 +34,16 @@
 		frm.set_query("default_buying_terms", function() {
 			return { filters: { buying: 1 } };
 		});
+
+		frm.set_query("default_in_transit_warehouse", function() {
+			return {
+				filters:{
+					'warehouse_type' : 'Transit',
+					'is_group': 0,
+					'company': frm.doc.company
+				}
+			};
+		});
 	},
 
 	company_name: function(frm) {
diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index 221044d..4a26a71 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -25,6 +25,7 @@
   "default_selling_terms",
   "default_buying_terms",
   "default_warehouse_for_sales_return",
+  "default_in_transit_warehouse",
   "column_break_10",
   "country",
   "create_chart_of_accounts_based_on",
@@ -242,7 +243,7 @@
   {
    "fieldname": "default_warehouse_for_sales_return",
    "fieldtype": "Link",
-   "label": "Default warehouse for Sales Return",
+   "label": "Default Warehouse for Sales Return",
    "options": "Warehouse"
   },
   {
@@ -733,6 +734,12 @@
    "fieldname": "enable_perpetual_inventory_for_non_stock_items",
    "fieldtype": "Check",
    "label": "Enable Perpetual Inventory For Non Stock Items"
+  },
+  {
+   "fieldname": "default_in_transit_warehouse",
+   "fieldtype": "Link",
+   "label": "Default In Transit Warehouse",
+   "options": "Warehouse"
   }
  ],
  "icon": "fa fa-building",
@@ -740,7 +747,7 @@
  "image_field": "company_logo",
  "is_tree": 1,
  "links": [],
- "modified": "2020-06-24 12:45:31.462195",
+ "modified": "2020-08-06 00:38:08.311216",
  "modified_by": "Administrator",
  "module": "Setup",
  "name": "Company",
@@ -801,4 +808,4 @@
  "sort_field": "modified",
  "sort_order": "ASC",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index 47b41a9..8e707fe 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -140,7 +140,8 @@
 			{"warehouse_name": _("All Warehouses"), "is_group": 1},
 			{"warehouse_name": _("Stores"), "is_group": 0},
 			{"warehouse_name": _("Work In Progress"), "is_group": 0},
-			{"warehouse_name": _("Finished Goods"), "is_group": 0}]:
+			{"warehouse_name": _("Finished Goods"), "is_group": 0},
+			{"warehouse_name": _("Goods In Transit"), "is_group": 0, "warehouse_type": "Transit"}]:
 
 			if not frappe.db.exists("Warehouse", "{0} - {1}".format(wh_detail["warehouse_name"], self.abbr)):
 				warehouse = frappe.get_doc({
@@ -149,7 +150,8 @@
 					"is_group": wh_detail["is_group"],
 					"company": self.name,
 					"parent_warehouse": "{0} - {1}".format(_("All Warehouses"), self.abbr) \
-						if not wh_detail["is_group"] else ""
+						if not wh_detail["is_group"] else "",
+					"warehouse_type" : wh_detail["warehouse_type"] if "warehouse_type" in wh_detail else None
 				})
 				warehouse.flags.ignore_permissions = True
 				warehouse.flags.ignore_mandatory = True
diff --git a/erpnext/setup/doctype/company/delete_company_transactions.py b/erpnext/setup/doctype/company/delete_company_transactions.py
index 8ecc13b..c94831e 100644
--- a/erpnext/setup/doctype/company/delete_company_transactions.py
+++ b/erpnext/setup/doctype/company/delete_company_transactions.py
@@ -26,7 +26,8 @@
 		tabDocField where fieldtype='Link' and options='Company'"""):
 		if doctype not in ("Account", "Cost Center", "Warehouse", "Budget",
 			"Party Account", "Employee", "Sales Taxes and Charges Template",
-			"Purchase Taxes and Charges Template", "POS Profile", 'BOM'):
+			"Purchase Taxes and Charges Template", "POS Profile", "BOM",
+			"Company", "Bank Account"):
 				delete_for_doctype(doctype, company_name)
 
 	# reset company values
diff --git a/erpnext/setup/doctype/quotation_lost_reason_detail/__init__.py b/erpnext/setup/doctype/quotation_lost_reason_detail/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/setup/doctype/quotation_lost_reason_detail/__init__.py
diff --git a/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.json b/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.json
new file mode 100644
index 0000000..5432141
--- /dev/null
+++ b/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.json
@@ -0,0 +1,31 @@
+{
+ "actions": [],
+ "creation": "2020-07-14 09:21:44.057724",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "lost_reason"
+ ],
+ "fields": [
+  {
+   "fieldname": "lost_reason",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Quotation Lost Reason",
+   "options": "Quotation Lost Reason"
+  }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2020-07-26 17:58:56.373775",
+ "modified_by": "Administrator",
+ "module": "Setup",
+ "name": "Quotation Lost Reason Detail",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.py b/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.py
new file mode 100644
index 0000000..7bb8d02
--- /dev/null
+++ b/erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class QuotationLostReasonDetail(Document):
+	pass
diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py
index aa9fbc0..4f0f572 100644
--- a/erpnext/setup/install.py
+++ b/erpnext/setup/install.py
@@ -7,6 +7,7 @@
 from erpnext.accounts.doctype.cash_flow_mapper.default_cash_flow_mapper import DEFAULT_MAPPERS
 from .default_success_action import get_default_success_action
 from frappe import _
+from frappe.utils import cint
 from frappe.desk.page.setup_wizard.setup_wizard import add_all_roles_to
 from frappe.custom.doctype.custom_field.custom_field import create_custom_field
 from erpnext.setup.default_energy_point_rules import get_default_energy_point_rules
@@ -25,12 +26,13 @@
 	create_default_success_action()
 	create_default_energy_point_rules()
 	add_company_to_session_defaults()
+	add_standard_navbar_items()
 	frappe.db.commit()
 
 
 def check_setup_wizard_not_completed():
-	if frappe.db.get_default('desktop:home_page') != 'setup-wizard':
-		message = """ERPNext can only be installed on a fresh site where the setup wizard is not completed. 
+	if cint(frappe.db.get_single_value('System Settings', 'setup_complete') or 0):
+		message = """ERPNext can only be installed on a fresh site where the setup wizard is not completed.
 You can reinstall this site (after saving your data) using: bench --site [sitename] reinstall"""
 		frappe.throw(message)
 
@@ -103,3 +105,45 @@
 		"ref_doctype": "Company"
 	})
 	settings.save()
+
+def add_standard_navbar_items():
+	navbar_settings = frappe.get_single("Navbar Settings")
+
+	erpnext_navbar_items = [
+		{
+			'item_label': 'Documentation',
+			'item_type': 'Route',
+			'route': 'https://erpnext.com/docs/user/manual',
+			'is_standard': 1
+		},
+		{
+			'item_label': 'User Forum',
+			'item_type': 'Route',
+			'route': 'https://discuss.erpnext.com',
+			'is_standard': 1
+		},
+		{
+			'item_label': 'Report an Issue',
+			'item_type': 'Route',
+			'route': 'https://github.com/frappe/erpnext/issues',
+			'is_standard': 1
+		}
+	]
+
+	current_nabvar_items = navbar_settings.help_dropdown
+	navbar_settings.set('help_dropdown', [])
+
+	for item in erpnext_navbar_items:
+		navbar_settings.append('help_dropdown', item)
+
+	for item in current_nabvar_items:
+		navbar_settings.append('help_dropdown', {
+			'item_label': item.item_label,
+			'item_type': item.item_type,
+			'route': item.route,
+			'action': item.action,
+			'is_standard': item.is_standard,
+			'hidden': item.hidden
+		})
+
+	navbar_settings.save()
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index ad063cf..72ed002 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -95,8 +95,6 @@
 		{'doctype': 'Stock Entry Type', 'name': 'Send to Subcontractor', 'purpose': 'Send to Subcontractor'},
 		{'doctype': 'Stock Entry Type', 'name': 'Material Transfer for Manufacture', 'purpose': 'Material Transfer for Manufacture'},
 		{'doctype': 'Stock Entry Type', 'name': 'Material Consumption for Manufacture', 'purpose': 'Material Consumption for Manufacture'},
-		{'doctype': 'Stock Entry Type', 'name': 'Send to Warehouse', 'purpose': 'Send to Warehouse'},
-		{'doctype': 'Stock Entry Type', 'name': 'Receive at Warehouse', 'purpose': 'Receive at Warehouse'},
 
 		# Designation
 		{'doctype': 'Designation', 'designation_name': _('CEO')},
@@ -244,7 +242,10 @@
 		{"doctype": "Sales Stage", "stage_name": _("Identifying Decision Makers")},
 		{"doctype": "Sales Stage", "stage_name": _("Perception Analysis")},
 		{"doctype": "Sales Stage", "stage_name": _("Proposal/Price Quote")},
-		{"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")}
+		{"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")},
+
+		# Warehouse Type
+		{'doctype': 'Warehouse Type', 'name': 'Transit'},
 	]
 
 	from erpnext.setup.setup_wizard.data.industry_type import get_industry_types
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index 66efcf8..ea385c8 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -175,7 +175,7 @@
    "no_copy": 1,
    "oldfieldname": "naming_series",
    "oldfieldtype": "Select",
-   "options": "MAT-DN-.YYYY.-",
+   "options": "MAT-DN-.YYYY.-\nMAT-DN-RET-.YYYY.-",
    "print_hide": 1,
    "reqd": 1,
    "set_only_once": 1
@@ -1255,7 +1255,7 @@
  "idx": 146,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-07-18 05:13:55.580420",
+ "modified": "2020-08-03 23:18:47.739997",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Delivery Note",
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 45526a3..d07b3dc 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -123,6 +123,7 @@
   "weightage",
   "slideshow",
   "website_image",
+  "website_image_alt",
   "thumbnail",
   "cb72",
   "website_warehouse",
@@ -1054,15 +1055,21 @@
    "fieldtype": "Data",
    "label": "Default Manufacturer Part No",
    "read_only": 1
+  },
+  {
+   "fieldname": "website_image_alt",
+   "fieldtype": "Data",
+   "label": "Image Description"
   }
  ],
  "has_web_view": 1,
  "icon": "fa fa-tag",
  "idx": 2,
  "image_field": "image",
+ "index_web_pages_for_search": 1,
  "links": [],
  "max_attachments": 1,
- "modified": "2020-07-31 21:21:10.956453",
+ "modified": "2020-08-07 14:24:58.384992",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Item",
@@ -1124,4 +1131,4 @@
  "sort_order": "DESC",
  "title_field": "item_name",
  "track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index d7b43bf..d22fda8 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -111,6 +111,7 @@
 		self.synced_with_hub = 0
 
 		self.validate_has_variants()
+		self.validate_attributes_in_variants()
 		self.validate_stock_exists_for_template_item()
 		self.validate_attributes()
 		self.validate_variant_attributes()
@@ -343,7 +344,7 @@
 			if variant:
 				context.variant = frappe.get_doc("Item", variant)
 
-				for fieldname in ("website_image", "web_long_description", "description",
+				for fieldname in ("website_image", "website_image_alt", "web_long_description", "description",
 										"website_specifications"):
 					if context.variant.get(fieldname):
 						value = context.variant.get(fieldname)
@@ -806,6 +807,77 @@
 			if frappe.db.exists("Item", {"variant_of": self.name}):
 				frappe.throw(_("Item has variants."))
 
+	def validate_attributes_in_variants(self):
+		if not self.has_variants or self.get("__islocal"):
+			return
+
+		old_doc = self.get_doc_before_save()
+		old_doc_attributes = set([attr.attribute for attr in old_doc.attributes])
+		own_attributes = [attr.attribute for attr in self.attributes]
+
+		# Check if old attributes were removed from the list
+		# Is old_attrs is a subset of new ones
+		# that means we need not check any changes
+		if old_doc_attributes.issubset(set(own_attributes)):
+			return
+
+		from collections import defaultdict
+
+		# get all item variants
+		items = [item["name"] for item in frappe.get_all("Item", {"variant_of": self.name})]
+
+		# get all deleted attributes
+		deleted_attribute = list(old_doc_attributes.difference(set(own_attributes)))
+
+		# fetch all attributes of these items
+		item_attributes = frappe.get_all(
+			"Item Variant Attribute",
+			filters={
+				"parent": ["in", items],
+				"attribute": ["in", deleted_attribute]
+			},
+			fields=["attribute", "parent"]
+		)
+		not_included = defaultdict(list)
+
+		for attr in item_attributes:
+			if attr["attribute"] not in own_attributes:
+				not_included[attr["parent"]].append(attr["attribute"])
+
+		if not len(not_included):
+			return
+
+		def body(docnames):
+			docnames.sort()
+			return "<br>".join(docnames)
+
+		def table_row(title, body):
+			return """<tr>
+				<td>{0}</td>
+				<td>{1}</td>
+			</tr>""".format(title, body)
+
+		rows = ''
+		for docname, attr_list in not_included.items():
+			link = "<a href='#Form/Item/{0}'>{0}</a>".format(frappe.bold(_(docname)))
+			rows += table_row(link, body(attr_list))
+
+		error_description = _('The following deleted attributes exist in Variants but not in the Template. You can either delete the Variants or keep the attribute(s) in template.')
+
+		message = """
+			<div>{0}</div><br>
+			<table class="table">
+				<thead>
+					<td>{1}</td>
+					<td>{2}</td>
+				</thead>
+				{3}
+			</table>
+		""".format(error_description, _('Variant Items'), _('Attributes'), rows)
+
+		frappe.throw(message, title=_("Variant Attribute Error"), is_minimizable=True, wide=True)
+
+
 	def validate_stock_exists_for_template_item(self):
 		if self.stock_ledger_created() and self._doc_before_save:
 			if (cint(self._doc_before_save.has_variants) != cint(self.has_variants)
diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json
index d1f29e3..44503d2 100644
--- a/erpnext/stock/doctype/material_request/material_request.json
+++ b/erpnext/stock/doctype/material_request/material_request.json
@@ -11,6 +11,7 @@
   "naming_series",
   "title",
   "material_request_type",
+  "transfer_status",
   "customer",
   "column_break_2",
   "schedule_date",
@@ -303,13 +304,22 @@
    "fieldtype": "Link",
    "label": "Set From Warehouse",
    "options": "Warehouse"
+  },
+  {
+   "allow_on_submit": 1,
+   "depends_on": "eval:doc.add_to_transit == 1",
+   "fieldname": "transfer_status",
+   "fieldtype": "Select",
+   "label": "Transfer Status",
+   "options": "\nNot Started\nIn Transit\nCompleted",
+   "read_only": 1
   }
  ],
  "icon": "fa fa-ticket",
  "idx": 70,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-05-01 20:21:09.990867",
+ "modified": "2020-08-10 13:27:54.891058",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Material Request",
diff --git a/erpnext/stock/doctype/material_request/material_request_list.js b/erpnext/stock/doctype/material_request/material_request_list.js
index 614ecb8..0d70958 100644
--- a/erpnext/stock/doctype/material_request/material_request_list.js
+++ b/erpnext/stock/doctype/material_request/material_request_list.js
@@ -1,8 +1,16 @@
 frappe.listview_settings['Material Request'] = {
-	add_fields: ["material_request_type", "status", "per_ordered", "per_received"],
+	add_fields: ["material_request_type", "status", "per_ordered", "per_received", "transfer_status"],
 	get_indicator: function(doc) {
 		if(doc.status=="Stopped") {
 			return [__("Stopped"), "red", "status,=,Stopped"];
+		} else if(doc.transfer_status && doc.docstatus != 2) {
+			if (doc.transfer_status == "Not Started") {
+				return [__("Not Started"), "orange"];
+			} else if (doc.transfer_status == "In Transit") {
+				return [__("In Transit"), "yellow"];
+			} else if (doc.transfer_status == "Completed") {
+				return [__("Completed"), "green"];
+			}
 		} else if(doc.docstatus==1 && flt(doc.per_ordered, 2) == 0) {
 			return [__("Pending"), "orange", "per_ordered,=,0"];
 		}  else if(doc.docstatus==1 && flt(doc.per_ordered, 2) < 100) {
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index 92e33ca..ce54fc8 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -1,7 +1,6 @@
 {
  "actions": [],
  "allow_import": 1,
- "allow_workflow": 1,
  "autoname": "naming_series:",
  "creation": "2013-05-21 16:16:39",
  "doctype": "DocType",
@@ -160,7 +159,7 @@
    "no_copy": 1,
    "oldfieldname": "naming_series",
    "oldfieldtype": "Select",
-   "options": "MAT-PRE-.YYYY.-",
+   "options": "MAT-PRE-.YYYY.-\nMAT-PR-RET-.YYYY.-",
    "print_hide": 1,
    "reqd": 1,
    "set_only_once": 1
@@ -1110,7 +1109,7 @@
  "idx": 261,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-07-18 05:19:12.148115",
+ "modified": "2020-08-03 23:20:26.381024",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Purchase Receipt",
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index d0ba001..4e173ff 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -227,6 +227,14 @@
 					if not stock_value_diff:
 						continue
 
+					# If PR is sub-contracted and fg item rate is zero
+					# in that case if account for shource and target warehouse are same,
+					# then GL entries should not be posted
+					if flt(stock_value_diff) == flt(d.rm_supp_cost) \
+						and warehouse_account.get(self.supplier_warehouse) \
+						and warehouse_account[d.warehouse]["account"] == warehouse_account[self.supplier_warehouse]["account"]:
+							continue
+
 					gl_entries.append(self.get_gl_dict({
 						"account": warehouse_account[d.warehouse]["account"],
 						"against": stock_rbnb,
@@ -242,16 +250,16 @@
 
 					credit_amount = flt(d.base_net_amount, d.precision("base_net_amount")) \
 						if credit_currency == self.company_currency else flt(d.net_amount, d.precision("net_amount"))
-
-					gl_entries.append(self.get_gl_dict({
-						"account":  warehouse_account[d.from_warehouse]['account'] \
-							if d.from_warehouse else stock_rbnb,
-						"against": warehouse_account[d.warehouse]["account"],
-						"cost_center": d.cost_center,
-						"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
-						"debit": -1 * flt(d.base_net_amount, d.precision("base_net_amount")),
-						"debit_in_account_currency": -1 * credit_amount
-					}, credit_currency, item=d))
+					if credit_amount:
+						gl_entries.append(self.get_gl_dict({
+							"account":  warehouse_account[d.from_warehouse]['account'] \
+								if d.from_warehouse else stock_rbnb,
+							"against": warehouse_account[d.warehouse]["account"],
+							"cost_center": d.cost_center,
+							"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
+							"debit": -1 * flt(d.base_net_amount, d.precision("base_net_amount")),
+							"debit_in_account_currency": -1 * credit_amount
+						}, credit_currency, item=d))
 
 					negative_expense_to_be_booked += flt(d.item_tax_amount)
 
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index d97b9e8..67161aa 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -3,6 +3,7 @@
 
 from __future__ import unicode_literals
 import unittest
+import json
 import frappe, erpnext
 import frappe.defaults
 from frappe.utils import cint, flt, cstr, today, random_string
@@ -18,6 +19,28 @@
 		set_perpetual_inventory(0)
 		frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
 
+	def test_reverse_purchase_receipt_sle(self):
+
+		frappe.db.set_value('UOM', '_Test UOM', 'must_be_whole_number', 0)
+
+		pr = make_purchase_receipt(qty=0.5)
+
+		sl_entry = frappe.db.get_all("Stock Ledger Entry", {"voucher_type": "Purchase Receipt",
+			"voucher_no": pr.name}, ['actual_qty'])
+
+		self.assertEqual(len(sl_entry), 1)
+		self.assertEqual(sl_entry[0].actual_qty, 0.5)
+
+		pr.cancel()
+
+		sl_entry_cancelled = frappe.db.get_all("Stock Ledger Entry", {"voucher_type": "Purchase Receipt",
+			"voucher_no": pr.name}, ['actual_qty'], order_by='creation')
+
+		self.assertEqual(len(sl_entry_cancelled), 2)
+		self.assertEqual(sl_entry_cancelled[1].actual_qty, -0.5)
+
+		frappe.db.set_value('UOM', '_Test UOM', 'must_be_whole_number', 1)
+
 	def test_make_purchase_invoice(self):
 		pr = make_purchase_receipt(do_not_save=True)
 		self.assertRaises(frappe.ValidationError, make_purchase_invoice, pr.name)
@@ -121,6 +144,87 @@
 		rm_supp_cost = sum([d.amount for d in pr.get("supplied_items")])
 		self.assertEqual(pr.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2))
 
+	def test_subcontracting_gle_fg_item_rate_zero(self):
+		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
+		set_perpetual_inventory()
+		frappe.db.set_value("Buying Settings", None, "backflush_raw_materials_of_subcontract_based_on", "BOM")
+		make_stock_entry(item_code="_Test Item", target="Work In Progress - TCP1", qty=100, basic_rate=100, company="_Test Company with perpetual inventory")
+		make_stock_entry(item_code="_Test Item Home Desktop 100", target="Work In Progress - TCP1",
+			qty=100, basic_rate=100, company="_Test Company with perpetual inventory")
+		pr = make_purchase_receipt(item_code="_Test FG Item", qty=10, rate=0, is_subcontracted="Yes",
+			company="_Test Company with perpetual inventory", warehouse='Stores - TCP1', supplier_warehouse='Work In Progress - TCP1')
+
+		gl_entries = get_gl_entries("Purchase Receipt", pr.name)
+
+		self.assertFalse(gl_entries)
+
+		set_perpetual_inventory(0)
+
+	def test_subcontracting_over_receipt(self):
+		"""
+			Behaviour: Raise multiple PRs against one PO that in total
+				receive more than the required qty in the PO.
+			Expected Result: Error Raised for Over Receipt against PO.
+		"""
+		from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
+		from erpnext.buying.doctype.purchase_order.test_purchase_order import (update_backflush_based_on,
+			make_subcontracted_item, create_purchase_order)
+		from erpnext.buying.doctype.purchase_order.purchase_order import (make_purchase_receipt,
+			make_rm_stock_entry as make_subcontract_transfer_entry)
+
+		update_backflush_based_on("Material Transferred for Subcontract")
+		item_code = "_Test Subcontracted FG Item 1"
+		make_subcontracted_item(item_code)
+
+		po = create_purchase_order(item_code=item_code, qty=1,
+			is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
+
+		#stock raw materials in a warehouse before transfer
+		make_stock_entry(target="_Test Warehouse - _TC",
+			item_code="_Test Item Home Desktop 100", qty=1, basic_rate=100)
+		make_stock_entry(target="_Test Warehouse - _TC",
+			item_code = "Test Extra Item 1", qty=1, basic_rate=100)
+		make_stock_entry(target="_Test Warehouse - _TC",
+			item_code = "_Test Item", qty=1, basic_rate=100)
+
+		rm_items = [
+			{
+				"item_code": item_code,
+				"rm_item_code": po.supplied_items[0].rm_item_code,
+				"item_name": "_Test Item",
+				"qty": po.supplied_items[0].required_qty,
+				"warehouse": "_Test Warehouse - _TC",
+				"stock_uom": "Nos"
+			},
+			{
+				"item_code": item_code,
+				"rm_item_code": po.supplied_items[1].rm_item_code,
+				"item_name": "Test Extra Item 1",
+				"qty": po.supplied_items[1].required_qty,
+				"warehouse": "_Test Warehouse - _TC",
+				"stock_uom": "Nos"
+			},
+			{
+				"item_code": item_code,
+				"rm_item_code": po.supplied_items[2].rm_item_code,
+				"item_name": "_Test Item Home Desktop 100",
+				"qty": po.supplied_items[2].required_qty,
+				"warehouse": "_Test Warehouse - _TC",
+				"stock_uom": "Nos"
+			}
+		]
+		rm_item_string = json.dumps(rm_items)
+		se = frappe.get_doc(make_subcontract_transfer_entry(po.name, rm_item_string))
+		se.to_warehouse = "_Test Warehouse 1 - _TC"
+		se.save()
+		se.submit()
+
+		pr1 = make_purchase_receipt(po.name)
+		pr2 = make_purchase_receipt(po.name)
+
+		pr1.submit()
+		self.assertRaises(frappe.ValidationError, pr2.submit)
+
 	def test_serial_no_supplier(self):
 		pr = make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1)
 		self.assertEqual(frappe.db.get_value("Serial No", pr.get("items")[0].serial_no, "supplier"),
@@ -688,7 +792,7 @@
 		"received_qty": received_qty,
 		"rejected_qty": rejected_qty,
 		"rejected_warehouse": args.rejected_warehouse or "_Test Rejected Warehouse - _TC" if rejected_qty != 0 else "",
-		"rate": args.rate or 50,
+		"rate": args.rate if args.rate != None else 50,
 		"conversion_factor": args.conversion_factor or 1.0,
 		"serial_no": args.serial_no,
 		"stock_uom": args.stock_uom or "_Test UOM",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 53b986c..9845bc2 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -19,7 +19,6 @@
 				filters: [
 					['Stock Entry', 'docstatus', '=', 1],
 					['Stock Entry', 'per_transferred', '<','100'],
-					['Stock Entry', 'purpose', '=', 'Send to Warehouse']
 				]
 			}
 		});
@@ -171,9 +170,9 @@
 			}
 		}
 
-		if (frm.doc.docstatus === 1 && frm.doc.purpose == 'Send to Warehouse') {
-			if (frm.doc.per_transferred < 100) {
-				frm.add_custom_button(__('Receive at Warehouse Entry'), function() {
+		if (frm.doc.docstatus === 1) {
+			if (frm.doc.add_to_transit && frm.doc.purpose=='Material Transfer' && frm.doc.per_transferred < 100) {
+				frm.add_custom_button('End Transit', function() {
 					frappe.model.open_mapped_doc({
 						method: "erpnext.stock.doctype.stock_entry.stock_entry.make_stock_in_entry",
 						frm: frm
@@ -266,6 +265,7 @@
 	stock_entry_type: function(frm){
 		frm.remove_custom_button('Bill of Materials', "Get items from");
 		frm.events.show_bom_custom_button(frm);
+		frm.trigger('add_to_transit');
 	},
 
 	purpose: function(frm) {
@@ -532,6 +532,26 @@
 
 	target_warehouse_address: function(frm) {
 		erpnext.utils.get_address_display(frm, 'target_warehouse_address', 'target_address_display', false);
+	},
+
+	add_to_transit: function(frm) {
+		if(frm.doc.add_to_transit && frm.doc.purpose=='Material Transfer') {
+			frm.set_value('stock_entry_type', 'Material Transfer');
+			frm.fields_dict.to_warehouse.get_query = function() {
+				return {
+					filters:{
+						'warehouse_type' : 'Transit',
+						'is_group': 0,
+						'company': frm.doc.company
+					}
+				};
+			};
+			frappe.db.get_value('Company', frm.doc.company, 'default_in_transit_warehouse', (r) => {
+				if (r.default_in_transit_warehouse) {
+					frm.set_value('to_warehouse', r.default_in_transit_warehouse);
+				}
+			});
+		}
 	}
 })
 
@@ -754,6 +774,7 @@
 		}
 		erpnext.hide_company();
 		erpnext.utils.add_item(this.frm);
+		this.frm.trigger('add_to_transit');
 	},
 
 	scan_barcode: function() {
@@ -919,8 +940,6 @@
 			doc.purpose!='Material Issue');
 
 		this.frm.fields_dict["items"].grid.set_column_disp("additional_cost", doc.purpose!='Material Issue');
-		this.frm.toggle_reqd("outgoing_stock_entry",
-			doc.purpose == 'Receive at Warehouse' ? 1: 0);
 	},
 
 	supplier: function(doc) {
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json
index 704ae41..61e0df6 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.json
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.json
@@ -13,6 +13,7 @@
   "stock_entry_type",
   "outgoing_stock_entry",
   "purpose",
+  "add_to_transit",
   "work_order",
   "purchase_order",
   "delivery_note_no",
@@ -116,11 +117,12 @@
    "reqd": 1
   },
   {
-   "depends_on": "eval:doc.purpose == 'Receive at Warehouse'",
+   "depends_on": "eval:doc.purpose == 'Material Transfer'",
    "fieldname": "outgoing_stock_entry",
    "fieldtype": "Link",
    "label": "Stock Entry (Outward GIT)",
-   "options": "Stock Entry"
+   "options": "Stock Entry",
+   "read_only": 1
   },
   {
    "bold": 1,
@@ -132,7 +134,7 @@
    "label": "Purpose",
    "oldfieldname": "purpose",
    "oldfieldtype": "Select",
-   "options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor\nSend to Warehouse\nReceive at Warehouse",
+   "options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor",
    "read_only": 1
   },
   {
@@ -630,13 +632,21 @@
   {
    "fieldname": "print_settings_col_break",
    "fieldtype": "Column Break"
+  },
+  {
+   "default": "0",
+   "depends_on": "eval: doc.purpose=='Material Transfer' && !doc.outgoing_stock_entry",
+   "fieldname": "add_to_transit",
+   "fieldtype": "Check",
+   "label": "Add to Transit",
+   "no_copy": 1
   }
  ],
  "icon": "fa fa-file-text",
  "idx": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-23 12:56:52.881752",
+ "modified": "2020-08-11 19:10:07.954981",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Entry",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 229cf02..30bcccd 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -96,6 +96,11 @@
 		self.update_quality_inspection()
 		if self.work_order and self.purpose == "Manufacture":
 			self.update_so_in_serial_number()
+		
+		if self.purpose == 'Material Transfer' and self.add_to_transit:
+			self.set_material_request_transfer_status('In Transit')
+		if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
+			self.set_material_request_transfer_status('Completed')
 
 	def on_cancel(self):
 
@@ -116,6 +121,11 @@
 		self.update_quality_inspection()
 		self.delete_auto_created_batches()
 
+		if self.purpose == 'Material Transfer' and self.add_to_transit:
+			self.set_material_request_transfer_status('Not Started')
+		if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
+			self.set_material_request_transfer_status('In Transit')
+
 	def set_job_card_data(self):
 		if self.job_card and not self.work_order:
 			data = frappe.db.get_value('Job Card',
@@ -133,7 +143,7 @@
 	def validate_purpose(self):
 		valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer",
 			"Material Transfer for Manufacture", "Manufacture", "Repack", "Send to Subcontractor",
-			"Material Consumption for Manufacture", "Send to Warehouse", "Receive at Warehouse"]
+			"Material Consumption for Manufacture"]
 
 		if self.purpose not in valid_purposes:
 			frappe.throw(_("Purpose must be one of {0}").format(comma_or(valid_purposes)))
@@ -199,7 +209,8 @@
 						item.set(f, item_details.get(f))
 
 			if not item.transfer_qty and item.qty:
-				item.transfer_qty = item.qty * item.conversion_factor
+				item.transfer_qty = flt(flt(item.qty) * flt(item.conversion_factor),
+				self.precision("transfer_qty", item))
 
 			if (self.purpose in ("Material Transfer", "Material Transfer for Manufacture")
 				and not item.serial_no
@@ -258,10 +269,10 @@
 		"""perform various (sometimes conditional) validations on warehouse"""
 
 		source_mandatory = ["Material Issue", "Material Transfer", "Send to Subcontractor", "Material Transfer for Manufacture",
-			"Material Consumption for Manufacture", "Send to Warehouse", "Receive at Warehouse"]
+			"Material Consumption for Manufacture"]
 
 		target_mandatory = ["Material Receipt", "Material Transfer", "Send to Subcontractor",
-			"Material Transfer for Manufacture", "Send to Warehouse", "Receive at Warehouse"]
+			"Material Transfer for Manufacture"]
 
 		validate_for_manufacture = any([d.bom_no for d in self.get("items")])
 
@@ -809,7 +820,7 @@
 	def set_items_for_stock_in(self):
 		self.items = []
 
-		if self.outgoing_stock_entry and self.purpose == 'Receive at Warehouse':
+		if self.outgoing_stock_entry and self.purpose == 'Material Transfer':
 			doc = frappe.get_doc('Stock Entry', self.outgoing_stock_entry)
 
 			if doc.per_transferred == 100:
@@ -1210,13 +1221,25 @@
 
 	def validate_with_material_request(self):
 		for item in self.get("items"):
-			if item.material_request:
+			material_request = item.material_request or None
+			material_request_item = item.material_request_item or None
+			if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
+				parent_se = frappe.get_value("Stock Entry Detail", item.ste_detail, ['material_request','material_request_item'],as_dict=True)
+				if parent_se:
+					material_request = parent_se.material_request
+					material_request_item = parent_se.material_request_item
+
+			if material_request:
 				mreq_item = frappe.db.get_value("Material Request Item",
-					{"name": item.material_request_item, "parent": item.material_request},
+					{"name": material_request_item, "parent": material_request},
 					["item_code", "warehouse", "idx"], as_dict=True)
-				if mreq_item.item_code != item.item_code or \
-				mreq_item.warehouse != (item.s_warehouse if self.purpose== "Material Issue" else item.t_warehouse):
-					frappe.throw(_("Item or Warehouse for row {0} does not match Material Request").format(item.idx),
+				if mreq_item.item_code != item.item_code:
+					frappe.throw(_("Item for row {0} does not match Material Request").format(item.idx),
+						frappe.MappingMismatchError)
+				elif self.purpose == "Material Transfer" and self.add_to_transit:
+					continue
+				elif mreq_item.warehouse != (item.s_warehouse if self.purpose == "Material Issue" else item.t_warehouse):
+					frappe.throw(_("Warehouse for row {0} does not match Material Request").format(item.idx),
 						frappe.MappingMismatchError)
 
 	def validate_batch(self):
@@ -1284,7 +1307,7 @@
 						 to fullfill Sales Order {2}.").format(item.item_code, sr, sales_order))
 
 	def update_transferred_qty(self):
-		if self.purpose == 'Receive at Warehouse':
+		if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
 			stock_entries = {}
 			stock_entries_child_list = []
 			for d in self.items:
@@ -1342,6 +1365,20 @@
 						'reference_type': reference_type,
 						'reference_name': reference_name
 					})
+	def set_material_request_transfer_status(self, status):
+		material_requests = []
+		if self.outgoing_stock_entry:
+			parent_se = frappe.get_value("Stock Entry", self.outgoing_stock_entry, 'add_to_transit')
+
+		for item in self.items: 
+			material_request = item.material_request or None
+			if self.purpose == "Material Transfer" and material_request not in material_requests:
+				if self.outgoing_stock_entry and parent_se:
+					material_request = frappe.get_value("Stock Entry Detail", item.ste_detail, 'material_request')
+
+			if material_request and material_request not in material_requests:
+				material_requests.append(material_request)
+				frappe.db.set_value('Material Request', material_request, 'transfer_status', status)
 
 @frappe.whitelist()
 def move_sample_to_retention_warehouse(company, items):
@@ -1381,12 +1418,19 @@
 
 @frappe.whitelist()
 def make_stock_in_entry(source_name, target_doc=None):
+
 	def set_missing_values(source, target):
-		target.purpose = 'Receive at Warehouse'
 		target.set_stock_entry_type()
 
 	def update_item(source_doc, target_doc, source_parent):
 		target_doc.t_warehouse = ''
+
+		if source_doc.material_request_item and source_doc.material_request :
+			add_to_transit = frappe.db.get_value('Stock Entry', source_name, 'add_to_transit')
+			if add_to_transit:
+				warehouse = frappe.get_value('Material Request Item', source_doc.material_request_item, 'warehouse')
+				target_doc.t_warehouse = warehouse
+		
 		target_doc.s_warehouse = source_doc.t_warehouse
 		target_doc.qty = source_doc.qty - source_doc.transferred_qty
 
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index 8e25804..d98870d 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -737,34 +737,6 @@
 		self.assertEqual(se.get("items")[0].allow_zero_valuation_rate, 1)
 		self.assertEqual(se.get("items")[0].amount, 0)
 
-	def test_goods_in_transit(self):
-		from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
-		warehouse = "_Test Warehouse FG 1 - _TC"
-
-		if not frappe.db.exists('Warehouse', warehouse):
-			create_warehouse("_Test Warehouse FG 1")
-
-		outward_entry = make_stock_entry(item_code="_Test Item",
-			purpose="Send to Warehouse",
-			source="_Test Warehouse - _TC",
-			target="_Test Warehouse 1 - _TC", qty=50, basic_rate=100)
-
-		inward_entry1 = make_stock_in_entry(outward_entry.name)
-		inward_entry1.items[0].t_warehouse = warehouse
-		inward_entry1.items[0].qty = 25
-		inward_entry1.submit()
-
-		doc = frappe.get_doc('Stock Entry', outward_entry.name)
-		self.assertEqual(doc.per_transferred, 50)
-
-		inward_entry2 = make_stock_in_entry(outward_entry.name)
-		inward_entry2.items[0].t_warehouse = warehouse
-		inward_entry2.items[0].qty = 25
-		inward_entry2.submit()
-
-		doc = frappe.get_doc('Stock Entry', outward_entry.name)
-		self.assertEqual(doc.per_transferred, 100)
-
 	def test_gle_for_opening_stock_entry(self):
 		mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company="_Test Company with perpetual inventory",qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1", is_opening="Yes", do_not_save=True)
 
diff --git a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json
index edee3c7..0f2b55e 100644
--- a/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json
+++ b/erpnext/stock/doctype/stock_entry_type/stock_entry_type.json
@@ -1,156 +1,83 @@
 {
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
+ "actions": [],
  "autoname": "Prompt",
- "beta": 0,
  "creation": "2019-03-13 16:23:46.636769",
- "custom": 0,
- "docstatus": 0,
  "doctype": "DocType",
- "document_type": "",
  "editable_grid": 1,
  "engine": "InnoDB",
+ "field_order": [
+  "purpose"
+ ],
  "fields": [
   {
-   "allow_bulk_edit": 0,
-   "allow_in_quick_entry": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
    "default": "Material Issue",
-   "fetch_if_empty": 0,
    "fieldname": "purpose",
    "fieldtype": "Select",
-   "hidden": 0,
-   "ignore_user_permissions": 0,
-   "ignore_xss_filter": 0,
-   "in_filter": 0,
-   "in_global_search": 0,
    "in_list_view": 1,
-   "in_standard_filter": 0,
    "label": "Purpose",
-   "length": 0,
-   "no_copy": 0,
-   "options": "\nMaterial Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor\nSend to Warehouse\nReceive at Warehouse",
-   "permlevel": 0,
-   "precision": "",
-   "print_hide": 0,
-   "print_hide_if_no_value": 0,
-   "read_only": 0,
-   "remember_last_selected_value": 0,
-   "report_hide": 0,
+   "options": "\nMaterial Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor",
    "reqd": 1,
-   "search_index": 0,
-   "set_only_once": 1,
-   "translatable": 0,
-   "unique": 0
+   "set_only_once": 1
   }
  ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-03-26 12:02:42.144377",
+ "links": [],
+ "modified": "2020-08-10 23:24:37.160817",
  "modified_by": "Administrator",
  "module": "Stock",
  "name": "Stock Entry Type",
- "name_case": "",
  "owner": "Administrator",
  "permissions": [
   {
-   "amend": 0,
-   "cancel": 0,
    "create": 1,
    "delete": 1,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "System Manager",
-   "set_user_permissions": 0,
    "share": 1,
-   "submit": 0,
    "write": 1
   },
   {
-   "amend": 0,
-   "cancel": 0,
    "create": 1,
    "delete": 1,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "Manufacturing Manager",
-   "set_user_permissions": 0,
    "share": 1,
-   "submit": 0,
    "write": 1
   },
   {
-   "amend": 0,
-   "cancel": 0,
    "create": 1,
    "delete": 1,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "Stock Manager",
-   "set_user_permissions": 0,
    "share": 1,
-   "submit": 0,
    "write": 1
   },
   {
-   "amend": 0,
-   "cancel": 0,
    "create": 1,
    "delete": 1,
    "email": 1,
    "export": 1,
-   "if_owner": 0,
-   "import": 0,
-   "permlevel": 0,
    "print": 1,
    "read": 1,
    "report": 1,
    "role": "Stock User",
-   "set_user_permissions": 0,
    "share": 1,
-   "submit": 0,
    "write": 1
   }
  ],
  "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
  "sort_field": "modified",
  "sort_order": "ASC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "track_changes": 1
 }
\ No newline at end of file
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index e1b3730..f4490f1 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -31,7 +31,7 @@
 				sle['posting_time'] = now_datetime().strftime('%H:%M:%S.%f')
 
 				if cancel:
-					sle['actual_qty'] = -flt(sle.get('actual_qty'), 0)
+					sle['actual_qty'] = -flt(sle.get('actual_qty'))
 
 					if sle['actual_qty'] < 0 and not sle.get('outgoing_rate'):
 						sle['outgoing_rate'] = get_incoming_outgoing_rate_for_cancel(sle.item_code,
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index 9e15757..858564a 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -209,11 +209,11 @@
 
 	frm.dashboard.set_headline_alert(
 		'<div class="row">' +
-			'<div class="col-xs-6">' +
-				'<span class="indicator whitespace-nowrap '+ time_to_respond.indicator +'"><span class="hidden-xs">Time to Respond: '+ time_to_respond.diff_display +'</span></span> ' +
+			'<div class="col-xs-12 col-sm-6">' +
+				'<span class="indicator whitespace-nowrap '+ time_to_respond.indicator +'"><span>Time to Respond: '+ time_to_respond.diff_display +'</span></span> ' +
 			'</div>' +
-			'<div class="col-xs-6">' +
-				'<span class="indicator whitespace-nowrap '+ time_to_resolve.indicator +'"><span class="hidden-xs">Time to Resolve: '+ time_to_resolve.diff_display +'</span></span> ' +
+			'<div class="col-xs-12 col-sm-6">' +
+				'<span class="indicator whitespace-nowrap '+ time_to_resolve.indicator +'"><span>Time to Resolve: '+ time_to_resolve.diff_display +'</span></span> ' +
 			'</div>' +
 		'</div>'
 	);
diff --git a/erpnext/templates/generators/item/item_image.html b/erpnext/templates/generators/item/item_image.html
index 0dd4c35..5d46a45 100644
--- a/erpnext/templates/generators/item/item_image.html
+++ b/erpnext/templates/generators/item/item_image.html
@@ -23,7 +23,7 @@
 	})
 </script>
 {% else %}
-{{ product_image(website_image or image or 'no-image.jpg') }}
+{{ product_image(website_image or image or 'no-image.jpg', alt=website_image_alt or item_name) }}
 {% endif %}
 
 <!-- Simple image preview -->
diff --git a/erpnext/templates/generators/item/item_inquiry.js b/erpnext/templates/generators/item/item_inquiry.js
index 52ddae2..e7db3a3 100644
--- a/erpnext/templates/generators/item/item_inquiry.js
+++ b/erpnext/templates/generators/item/item_inquiry.js
@@ -22,6 +22,13 @@
 			},
 			{
 				fieldtype: 'Data',
+				label: __('Phone Number'),
+				fieldname: 'phone',
+				options: 'Phone',
+				reqd: 1
+			},
+			{
+				fieldtype: 'Data',
 				label: __('Subject'),
 				fieldname: 'subject',
 				reqd: 1
diff --git a/erpnext/templates/generators/item_group.html b/erpnext/templates/generators/item_group.html
index 3f98453..40a064f 100644
--- a/erpnext/templates/generators/item_group.html
+++ b/erpnext/templates/generators/item_group.html
@@ -4,7 +4,7 @@
 
 {% block page_content %}
 <div class="item-group-content" itemscope itemtype="http://schema.org/Product">
-	<div>
+	<div class="item-group-slideshow">
 		{% if slideshow %}<!-- slideshow -->
 		{% include "templates/includes/slideshow.html" %}
 		{% endif %}
diff --git a/erpnext/templates/includes/macros.html b/erpnext/templates/includes/macros.html
index 3c82e90..ea6b00f 100644
--- a/erpnext/templates/includes/macros.html
+++ b/erpnext/templates/includes/macros.html
@@ -7,9 +7,9 @@
 </div>
 {% endmacro %}
 
-{% macro product_image(website_image, css_class="") %}
+{% macro product_image(website_image, css_class="", alt="") %}
     <div class="border text-center rounded h-100 {{ css_class }}" style="overflow: hidden;">
-		<img itemprop="image" class="website-image h-100 w-100" src="{{ frappe.utils.quoted(website_image or 'no-image.jpg') | abs_url }}">
+		<img itemprop="image" class="website-image h-100 w-100" alt="{{ alt }}" src="{{ frappe.utils.quoted(website_image or 'no-image.jpg') | abs_url }}">
     </div>
 {% endmacro %}
 
diff --git a/erpnext/www/support/index.html b/erpnext/www/support/index.html
index 93da503..12b4c2c 100644
--- a/erpnext/www/support/index.html
+++ b/erpnext/www/support/index.html
@@ -9,6 +9,33 @@
 			<p class="hero-subtitle">{{ greeting_subtitle }}</p>
 			{% endif %}
 		</div>
+		<div class="search-container">
+			<div class="website-search" id="search-container">
+				<div class="dropdown">
+					<div class="search-icon">
+						<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
+							fill="none"
+							stroke="currentColor" stroke-width="2" stroke-linecap="round"
+							stroke-linejoin="round"
+							class="feather feather-search">
+							<circle cx="11" cy="11" r="8"></circle>
+							<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
+						</svg>
+					</div>
+					<input type="search" class="form-control" placeholder="Search the docs (Press ? to focus)" />
+					<div class="overflow-hidden shadow dropdown-menu w-100">
+					</div>
+				</div>
+			</div>
+			<button class="navbar-toggler" type="button"
+				data-toggle="collapse"
+				data-target="#navbarSupportedContent"
+				aria-controls="navbarSupportedContent"
+				aria-expanded="false"
+				aria-label="Toggle navigation">
+				<span class="navbar-toggler-icon"></span>
+			</button>
+		</div>
 	</div>
 </section>
 
@@ -54,5 +81,21 @@
 	</div>
 </section>
 {% endif %}
+{% endblock %}
 
-{% endblock %}
\ No newline at end of file
+{%- block script -%}
+<script>
+	frappe.ready(() => {
+		frappe.setup_search('#search-container', 'kb');
+	});
+</script>
+{%- endblock -%}
+
+{%- block style -%}
+<style>
+	.search-container {
+		margin-top: 1.2rem;
+		max-width: 500px;
+	}	
+</style>
+{%- endblock -%}