Merge branch 'staging-fixes' into staging
diff --git a/README.md b/README.md
index 3b3be96..f4a08be 100644
--- a/README.md
+++ b/README.md
@@ -4,12 +4,16 @@
     <p align="center">
         <p>ERP made simple</p>
     </p>
-</div>
 
-[![Build Status](https://travis-ci.com/frappe/erpnext.png)](https://travis-ci.com/frappe/erpnext) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/frappe/erpnext?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Open Source Helpers](https://www.codetriage.com/frappe/erpnext/badges/users.svg)](https://www.codetriage.com/frappe/erpnext)
+[![Build Status](https://travis-ci.com/frappe/erpnext.png)](https://travis-ci.com/frappe/erpnext)
+[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/frappe/erpnext?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 
+[![Open Source Helpers](https://www.codetriage.com/frappe/erpnext/badges/users.svg)](https://www.codetriage.com/frappe/erpnext)
+[![Coverage Status](https://coveralls.io/repos/github/frappe/erpnext/badge.svg?branch=develop)](https://coveralls.io/github/frappe/erpnext?branch=develop)
 
 [https://erpnext.com](https://erpnext.com)
 
+</div>
+
 Includes: Accounting, Inventory, Manufacturing, CRM, Sales, Purchase, Project Management, HRMS. Requires MariaDB.
 
 ERPNext is built on the [Frappe](https://github.com/frappe/frappe) Framework, a full-stack web app framework in Python & JavaScript.
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 1af7e91..217d091 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
 from erpnext.hooks import regional_overrides
 from frappe.utils import getdate
 
-__version__ = '10.1.53'
+__version__ = '10.1.54'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index eef85de..635a8c2 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -12,6 +12,11 @@
 
 class Account(NestedSet):
 	nsm_parent_field = 'parent_account'
+	def on_update(self):
+		if frappe.local.flags.ignore_on_update:
+			return
+		else:
+			super().on_update()
 
 	def onload(self):
 		frozen_accounts_modifier = frappe.db.get_value("Accounts Settings", "Accounts Settings",
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
index f4cf6fa..9b812a8 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
@@ -6,6 +6,7 @@
 from frappe.utils import cstr
 from unidecode import unidecode
 from six import iteritems
+from frappe.utils.nestedset import rebuild_tree
 
 def create_charts(company, chart_template=None, existing_company=None):
 	chart = get_chart(chart_template, existing_company)
@@ -53,7 +54,12 @@
 
 					_import_accounts(child, account.name, root_type)
 
+		# Rebuild NestedSet HSM tree for Account Doctype
+		# after all accounts are already inserted.
+		frappe.local.flags.ignore_on_update = True
 		_import_accounts(chart, None, None, root_account=True)
+		rebuild_tree("Account", "parent_account")
+		frappe.local.flags.ignore_on_update = False
 
 def add_suffix_if_duplicate(account_name, account_number, accounts):
 	if account_number:
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index 4ec97c4..f2a5c16 100755
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -572,7 +572,7 @@
 			frappe.db.commit()
 			name_list.append(name)
 	except Exception:
-		frappe.log_error(frappe.get_traceback())
 		frappe.db.rollback()
+		frappe.log_error(frappe.get_traceback())
 
 	return name_list
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 22c9257..a11f63f 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -12,7 +12,7 @@
 source_link = "https://github.com/frappe/erpnext"
 
 develop_version = '11.x.x-develop'
-staging_version = '11.0.2'
+staging_version = '11.0.3'
 
 error_report_email = "support@erpnext.com"
 
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 c91bb8f..3f6cb44 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.py
@@ -16,16 +16,23 @@
 		self.update_new_bom()
 		bom_list = self.get_parent_boms(self.new_bom)
 		updated_bom = []
+
 		for bom in bom_list:
-			bom_obj = frappe.get_doc("BOM", bom)
-			bom_obj.get_doc_before_save()
-			updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom)
-			bom_obj.calculate_cost()
-			bom_obj.update_parent_cost()
-			bom_obj.db_update()
-			if (getattr(bom_obj.meta, 'track_changes', False)
-				and bom_obj._doc_before_save and not bom_obj.flags.ignore_version):
-				bom_obj.save_version()
+			try:
+				bom_obj = frappe.get_doc("BOM", bom)
+				bom_obj.get_doc_before_save()
+				updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom)
+				bom_obj.calculate_cost()
+				bom_obj.update_parent_cost()
+				bom_obj.db_update()
+				if (getattr(bom_obj.meta, 'track_changes', False)
+					and bom_obj._doc_before_save and not bom_obj.flags.ignore_version):
+					bom_obj.save_version()
+
+				frappe.db.commit()
+			except Exception:
+				frappe.db.rollback()
+				frappe.log_error(frappe.get_traceback())
 
 	def validate_bom(self):
 		if cstr(self.current_bom) == cstr(self.new_bom):
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index bd01ec9..d285704 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -214,8 +214,9 @@
 			"ifnull(to_date, '2500-01-01')": [">=", today()]})
 
 	for loyalty_program in loyalty_programs:
-		customer_groups = [d.value for d in get_children("Customer Group", loyalty_program.customer_group)]
-		customer_territories = [d.value for d in get_children("Territory", loyalty_program.customer_territory)]
+		customer_groups = [d.value for d in get_children("Customer Group", loyalty_program.customer_group)] + [loyalty_program.customer_group]
+		customer_territories = [d.value for d in get_children("Territory", loyalty_program.customer_territory)] + [loyalty_program.customer_territory]
+
 		if (not loyalty_program.customer_group or doc.customer_group in customer_groups)\
 			and (not loyalty_program.customer_territory or doc.territory in customer_territories):
 			lp_details.append(loyalty_program.name)
diff --git a/erpnext/selling/doctype/sales_team/sales_team.json b/erpnext/selling/doctype/sales_team/sales_team.json
index c77f9f4..04027b2 100644
--- a/erpnext/selling/doctype/sales_team/sales_team.json
+++ b/erpnext/selling/doctype/sales_team/sales_team.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
  "allow_import": 0, 
  "allow_rename": 0, 
  "beta": 0, 
@@ -9,18 +10,24 @@
  "doctype": "DocType", 
  "document_type": "Setup", 
  "editable_grid": 1, 
+ "engine": "InnoDB", 
  "fields": [
   {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "sales_person", 
    "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
-   "in_filter": 1, 
+   "in_filter": 0, 
+   "in_global_search": 0, 
    "in_list_view": 1, 
+   "in_standard_filter": 0, 
    "label": "Sales Person", 
    "length": 0, 
    "no_copy": 0, 
@@ -32,24 +39,31 @@
    "print_hide_if_no_value": 0, 
    "print_width": "200px", 
    "read_only": 0, 
+   "remember_last_selected_value": 0, 
    "report_hide": 0, 
    "reqd": 1, 
    "search_index": 1, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0, 
    "width": "200px"
   }, 
   {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "contact_no", 
    "fieldtype": "Data", 
    "hidden": 1, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
    "in_filter": 0, 
+   "in_global_search": 0, 
    "in_list_view": 1, 
+   "in_standard_filter": 0, 
    "label": "Contact No.", 
    "length": 0, 
    "no_copy": 0, 
@@ -60,24 +74,31 @@
    "print_hide_if_no_value": 0, 
    "print_width": "100px", 
    "read_only": 0, 
+   "remember_last_selected_value": 0, 
    "report_hide": 0, 
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0, 
    "width": "100px"
   }, 
   {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "allocated_percentage", 
    "fieldtype": "Float", 
    "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": "Contribution (%)", 
    "length": 0, 
    "no_copy": 0, 
@@ -88,24 +109,31 @@
    "print_hide_if_no_value": 0, 
    "print_width": "100px", 
    "read_only": 0, 
+   "remember_last_selected_value": 0, 
    "report_hide": 0, 
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0, 
    "width": "100px"
   }, 
   {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "allocated_amount", 
    "fieldtype": "Currency", 
    "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": "Contribution to Net Total", 
    "length": 0, 
    "no_copy": 0, 
@@ -117,24 +145,63 @@
    "print_hide_if_no_value": 0, 
    "print_width": "120px", 
    "read_only": 1, 
+   "remember_last_selected_value": 0, 
    "report_hide": 0, 
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
+   "translatable": 0, 
    "unique": 0, 
    "width": "120px"
   }, 
   {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "commission_rate", 
+   "fieldtype": "Data", 
+   "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": "Commission Rate", 
+   "length": 0, 
+   "no_copy": 0, 
+   "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
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "incentives", 
    "fieldtype": "Currency", 
    "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": "Incentives", 
    "length": 0, 
    "no_copy": 0, 
@@ -145,24 +212,26 @@
    "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
   }
  ], 
+ "has_web_view": 0, 
  "hide_heading": 0, 
  "hide_toolbar": 0, 
  "idx": 1, 
  "image_view": 0, 
  "in_create": 0, 
-
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2016-07-11 03:28:08.421297", 
+ "modified": "2018-09-17 13:03:14.755974", 
  "modified_by": "Administrator", 
  "module": "Selling", 
  "name": "Sales Team", 
@@ -171,5 +240,8 @@
  "quick_entry": 1, 
  "read_only": 0, 
  "read_only_onload": 0, 
- "track_seen": 0
+ "show_name_in_global_search": 0, 
+ "track_changes": 1, 
+ "track_seen": 0, 
+ "track_views": 0
 }
\ No newline at end of file
diff --git a/__init__.py b/erpnext/selling/report/sales_person_commission_summary/__init__.py
similarity index 100%
rename from __init__.py
rename to erpnext/selling/report/sales_person_commission_summary/__init__.py
diff --git a/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.js b/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.js
new file mode 100644
index 0000000..ba6ee78
--- /dev/null
+++ b/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.js
@@ -0,0 +1,54 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Sales Person Commission Summary"] = {
+	"filters": [
+
+		{
+			fieldname: "sales_person",
+			label: __("Sales Person"),
+			fieldtype: "Link",
+			options: "Sales Person"
+		},
+		{
+			fieldname: "doc_type",
+			label: __("Document Type"),
+			fieldtype: "Select",
+			options: "Sales Order\nDelivery Note\nSales Invoice",
+			default: "Sales Order"
+		},
+		{
+			fieldname: "from_date",
+			label: __("From Date"),
+			fieldtype: "Date",
+			default: frappe.defaults.get_user_default("year_start_date"),
+		},
+		{
+			fieldname:"to_date",
+			label: __("To Date"),
+			fieldtype: "Date",
+			default: frappe.datetime.get_today()
+		},
+		{
+			fieldname:"company",
+			label: __("Company"),
+			fieldtype: "Link",
+			options: "Company",
+			default: frappe.defaults.get_user_default("Company")
+		},
+		{
+			fieldname:"customer",
+			label: __("Customer"),
+			fieldtype: "Link",
+			options: "Customer",
+		},
+		{
+			fieldname:"territory",
+			label: __("Territory"),
+			fieldtype: "Link",
+			options: "Territory",
+		},
+
+	]
+}
diff --git a/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.json b/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.json
new file mode 100644
index 0000000..d5ad9f1
--- /dev/null
+++ b/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.json
@@ -0,0 +1,26 @@
+{
+ "add_total_row": 1, 
+ "creation": "2018-09-11 17:49:27.256304", 
+ "disabled": 0, 
+ "docstatus": 0, 
+ "doctype": "Report", 
+ "idx": 0, 
+ "is_standard": "Yes", 
+ "modified": "2018-09-11 17:49:27.256304", 
+ "modified_by": "Administrator", 
+ "module": "Selling", 
+ "name": "Sales Person Commission Summary", 
+ "owner": "Administrator", 
+ "prepared_report": 0, 
+ "ref_doctype": "Sales Order", 
+ "report_name": "Sales Person Commission Summary", 
+ "report_type": "Script Report", 
+ "roles": [
+  {
+   "role": "Sales Manager"
+  }, 
+  {
+   "role": "Maintenance User"
+  }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py b/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py
new file mode 100644
index 0000000..0c84909
--- /dev/null
+++ b/erpnext/selling/report/sales_person_commission_summary/sales_person_commission_summary.py
@@ -0,0 +1,142 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import msgprint, _
+from frappe.utils import flt
+
+
+def execute(filters=None):
+	if not filters: filters = {}
+
+	columns = get_columns(filters)
+	entries = get_entries(filters)
+	data = []
+
+	for d in entries:
+		data.append([
+			d.name, d.customer, d.territory, d.posting_date,
+			d.base_net_amount, d.sales_person, d.allocated_percentage, d.commission_rate, d.allocated_amount,d.incentives
+		])
+
+	if data:
+		total_row = [""]*len(data[0])
+		data.append(total_row)
+
+	return columns, data
+
+def get_columns(filters):
+	if not filters.get("doc_type"):
+		msgprint(_("Please select the document type first"), raise_exception=1)
+
+	columns =[
+		{
+			"label": _(filters["doc_type"]),
+			"options": filters["doc_type"],
+			"fieldname": filters['doc_type'],
+			"fieldtype": "Link",
+			"width": 140
+		},
+		{
+			"label": _("Customer"),
+			"options": "Customer",
+			"fieldname": "customer",
+			"fieldtype": "Link",
+			"width": 140
+		},
+		{
+			"label": _("Territory"),
+			"options": "Territory",
+			"fieldname": "territory",
+			"fieldtype": "Link",
+			"width": 100
+		},
+		{
+			"label": _("Posting Date"),
+			"fieldname": "posting_date",
+			"fieldtype": "Date",
+			"width": 100
+		},
+		{
+			"label": _("Amount"),
+			"fieldname": "amount",
+			"fieldtype": "Currency",
+			"width": 120
+		},
+		{
+			"label": _("Sales Person"),
+			"options": "Sales Person",
+			"fieldname": "sales_person",
+			"fieldtype": "Link",
+			"width": 140
+		},
+		{
+			"label": _("Contribution %"),
+			"fieldname": "contribution_percentage",
+			"fieldtype": "Data",
+			"width": 110
+		},
+		{
+			"label": _("Commission Rate %"),
+			"fieldname": "commission_rate",
+			"fieldtype": "Data",
+			"width": 100
+		},
+		{
+			"label": _("Contribution Amount"),
+			"fieldname": "contribution_amount",
+			"fieldtype": "Currency",
+			"width": 120
+		},
+		{
+			"label": _("Incentives"),
+			"fieldname": "incentives",
+			"fieldtype": "Currency",
+			"width": 120
+		}
+	]
+
+	return columns
+
+def get_entries(filters):
+	date_field = filters["doc_type"] == "Sales Order" and "transaction_date" or "posting_date"
+	
+	conditions, values = get_conditions(filters, date_field)
+	entries = frappe.db.sql("""
+		select
+			dt.name, dt.customer, dt.territory, dt.%s as posting_date,dt.base_net_total as base_net_amount,
+			st.commission_rate,st.sales_person, st.allocated_percentage, st.allocated_amount, st.incentives
+		from
+			`tab%s` dt, `tabSales Team` st
+		where
+			st.parent = dt.name and st.parenttype = %s
+			and dt.docstatus = 1 %s order by dt.name desc,st.sales_person 
+		""" %(date_field, filters["doc_type"], '%s', conditions),
+			tuple([filters["doc_type"]] + values), as_dict=1)
+
+	return entries
+
+def get_conditions(filters, date_field):
+	conditions = [""]
+	values = []
+
+	for field in ["company", "customer", "territory"]:
+		if filters.get(field):
+			conditions.append("dt.{0}=%s".format(field))
+			values.append(filters[field])
+
+	if filters.get("sales_person"):
+		conditions.append("st.sales_person = '{0}'".format(filters.get("sales_person")))
+
+	if filters.get("from_date"):
+		conditions.append("dt.{0}>=%s".format(date_field))
+		values.append(filters["from_date"])
+
+	if filters.get("to_date"):
+		conditions.append("dt.{0}<=%s".format(date_field))
+		values.append(filters["to_date"])
+
+	return " and ".join(conditions), values
+
+
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index 325f08a..b7b186a 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -12,6 +12,8 @@
 erpnext.selling.SellingController = erpnext.TransactionController.extend({
 	setup: function() {
 		this._super();
+		this.frm.add_fetch("sales_partner", "commission_rate", "commission_rate");
+		this.frm.add_fetch("sales_person", "commission_rate", "commission_rate");
 	},
 
 	onload: function() {
@@ -29,8 +31,6 @@
 	setup_queries: function() {
 		var me = this;
 
-		this.frm.add_fetch("sales_partner", "commission_rate", "commission_rate");
-
 		$.each([["customer", "customer"],
 			["lead", "lead"]],
 			function(i, opts) {
@@ -171,17 +171,26 @@
 
 	allocated_percentage: function(doc, cdt, cdn) {
 		var sales_person = frappe.get_doc(cdt, cdn);
-
 		if(sales_person.allocated_percentage) {
+
 			sales_person.allocated_percentage = flt(sales_person.allocated_percentage,
 				precision("allocated_percentage", sales_person));
+
 			sales_person.allocated_amount = flt(this.frm.doc.base_net_total *
 				sales_person.allocated_percentage / 100.0,
 				precision("allocated_amount", sales_person));
+				refresh_field(["allocated_amount"], sales_person);
 
-			refresh_field(["allocated_percentage", "allocated_amount"], sales_person.name,
+			this.calculate_incentive(sales_person);
+			refresh_field(["allocated_percentage", "allocated_amount", "commission_rate","incentives"], sales_person.name,
 				sales_person.parentfield);
-		}
+		}	
+	},
+
+	sales_person: function(doc, cdt, cdn) {
+		var row = frappe.get_doc(cdt, cdn);
+		this.calculate_incentive(row);
+		refresh_field("incentives",row.name,row.parentfield);
 	},
 
 	warehouse: function(doc, cdt, cdn) {
@@ -250,6 +259,15 @@
 		});
 	},
 
+	calculate_incentive: function(row) {
+		if(row.allocated_amount)
+		{
+			row.incentives = flt(
+					row.allocated_amount * row.commission_rate / 100.0,
+					precision("incentives", sales_person));
+		}
+	},
+
 	batch_no: function(doc, cdt, cdn) {
 		var me = this;
 		var item = frappe.get_doc(cdt, cdn);
diff --git a/erpnext/setup/doctype/sales_person/sales_person.js b/erpnext/setup/doctype/sales_person/sales_person.js
index 2388739..584f879 100644
--- a/erpnext/setup/doctype/sales_person/sales_person.js
+++ b/erpnext/setup/doctype/sales_person/sales_person.js
@@ -1,6 +1,15 @@
 // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
 // License: GNU General Public License v3. See license.txt
 
+frappe.ui.form.on('Sales Person', {
+	refresh: function(frm) {
+		if(frm.doc.__onload && frm.doc.__onload.dashboard_info) {
+			var info = frm.doc.__onload.dashboard_info;
+			frm.dashboard.add_indicator(__('Total Contribution Amount: {0}',
+				[format_currency(info.allocated_amount, info.currency)]), 'blue');
+		}
+	}
+});
 
 cur_frm.cscript.refresh = function(doc, cdt, cdn) {
 	cur_frm.cscript.set_root_readonly(doc);
diff --git a/erpnext/setup/doctype/sales_person/sales_person.json b/erpnext/setup/doctype/sales_person/sales_person.json
index 715d8da..7eeb500 100644
--- a/erpnext/setup/doctype/sales_person/sales_person.json
+++ b/erpnext/setup/doctype/sales_person/sales_person.json
@@ -1,6 +1,6 @@
 {
  "allow_copy": 0, 
- "allow_guest_to_view": 0,
+ "allow_guest_to_view": 0, 
  "allow_import": 1, 
  "allow_rename": 1, 
  "autoname": "field:sales_person_name", 
@@ -15,7 +15,8 @@
  "engine": "InnoDB", 
  "fields": [
   {
-   "allow_bulk_edit": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -42,11 +43,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
-   "allow_bulk_edit": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -74,11 +76,12 @@
    "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
-   "unique": 0
+   "translatable": 0, 
+   "unique": 1
   }, 
   {
-   "allow_bulk_edit": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -108,11 +111,44 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
-   "allow_bulk_edit": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "commission_rate", 
+   "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": "Commission Rate", 
+   "length": 0, 
+   "no_copy": 0, 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 1, 
+   "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
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -141,47 +177,49 @@
    "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
-   "allow_bulk_edit": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "default": "1",
-   "fieldname": "enabled",
-   "fieldtype": "Check",
-   "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": "Enabled",
-   "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,
+   "default": "1", 
+   "fieldname": "enabled", 
+   "fieldtype": "Check", 
+   "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": "Enabled", 
+   "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
-  },
+  }, 
   {
-   "allow_bulk_edit": 0,
-   "allow_on_submit": 0,
-   "bold": 0,
-   "collapsible": 0,
-   "columns": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "cb0", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -202,11 +240,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
-   "allow_bulk_edit": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -233,18 +272,19 @@
    "reqd": 1, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
-   "allow_bulk_edit": 0,
+   "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",
+   "fetch_from": "employee.department", 
+   "fieldname": "department", 
+   "fieldtype": "Link", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
    "ignore_xss_filter": 0, 
@@ -252,25 +292,26 @@
    "in_global_search": 0, 
    "in_list_view": 0, 
    "in_standard_filter": 0, 
-   "label": "Department",
+   "label": "Department", 
    "length": 0, 
    "no_copy": 0, 
-   "options": "Department",
+   "options": "Department", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
    "print_hide_if_no_value": 0, 
-   "read_only": 1,
+   "read_only": 1, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
-   "allow_bulk_edit": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -298,11 +339,12 @@
    "reqd": 0, 
    "search_index": 1, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
-   "allow_bulk_edit": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -330,11 +372,12 @@
    "reqd": 0, 
    "search_index": 1, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
-   "allow_bulk_edit": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -362,11 +405,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
-   "allow_bulk_edit": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -395,11 +439,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
-   "allow_bulk_edit": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -428,11 +473,12 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }, 
   {
-   "allow_bulk_edit": 0,
+   "allow_bulk_edit": 0, 
+   "allow_in_quick_entry": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -462,11 +508,11 @@
    "reqd": 0, 
    "search_index": 0, 
    "set_only_once": 0, 
-   "translatable": 0,
+   "translatable": 0, 
    "unique": 0
   }
  ], 
- "has_web_view": 0,
+ "has_web_view": 0, 
  "hide_heading": 0, 
  "hide_toolbar": 0, 
  "icon": "icon-user", 
@@ -477,7 +523,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2018-05-17 09:44:18.203325",
+ "modified": "2018-09-12 16:41:06.378899", 
  "modified_by": "Administrator", 
  "module": "Setup", 
  "name": "Sales Person", 
@@ -541,12 +587,13 @@
    "write": 1
   }
  ], 
- "quick_entry": 0, 
+ "quick_entry": 1, 
  "read_only": 0, 
  "read_only_onload": 0, 
  "search_fields": "parent_sales_person", 
  "show_name_in_global_search": 1, 
  "sort_order": "ASC", 
- "track_changes": 0, 
- "track_seen": 0
+ "track_changes": 1, 
+ "track_seen": 0, 
+ "track_views": 0
 }
\ No newline at end of file
diff --git a/erpnext/setup/doctype/sales_person/sales_person.py b/erpnext/setup/doctype/sales_person/sales_person.py
index 816ee84..ab65f74 100644
--- a/erpnext/setup/doctype/sales_person/sales_person.py
+++ b/erpnext/setup/doctype/sales_person/sales_person.py
@@ -6,9 +6,10 @@
 from frappe import _
 from frappe.utils import flt
 from frappe.utils.nestedset import NestedSet
+from erpnext import get_default_currency
 
 class SalesPerson(NestedSet):
-	nsm_parent_field = 'parent_sales_person';
+	nsm_parent_field = 'parent_sales_person'
 
 	def validate(self):
 		for d in self.get('targets') or []:
@@ -16,6 +17,24 @@
 				frappe.throw(_("Either target qty or target amount is mandatory."))
 		self.validate_employee_id()
 
+	def onload(self):
+		self.load_dashboard_info()
+
+	def load_dashboard_info(self):
+		company_default_currency = get_default_currency() 
+
+		allocated_amount = frappe.db.sql("""
+			select sum(allocated_amount)
+			from `tabSales Team` 
+			where sales_person = %s and docstatus=1 and parenttype = 'Sales Order'
+		""",(self.sales_person_name))
+
+		info = {}
+		info["allocated_amount"] = flt(allocated_amount[0][0]) if allocated_amount else 0
+		info["currency"] = company_default_currency
+		
+		self.set_onload('dashboard_info', info)
+
 	def on_update(self):
 		super(SalesPerson, self).on_update()
 		self.validate_one_root()
@@ -35,4 +54,48 @@
 			frappe.throw(_("Another Sales Person {0} exists with the same Employee id").format(sales_person))
 
 def on_doctype_update():
-	frappe.db.add_index("Sales Person", ["lft", "rgt"])
\ No newline at end of file
+	frappe.db.add_index("Sales Person", ["lft", "rgt"])
+
+def get_timeline_data(doctype, name):
+
+	out = {}
+
+	out.update(dict(frappe.db.sql('''select
+			unix_timestamp(dt.transaction_date), count(st.parenttype)
+		from
+			`tabSales Order` dt, `tabSales Team` st
+		where
+			st.sales_person = %s and st.parent = dt.name and dt.transaction_date > date_sub(curdate(), interval 1 year) 
+			group by dt.transaction_date ''', name)))
+
+	sales_invoice = dict(frappe.db.sql('''select
+			unix_timestamp(dt.posting_date), count(st.parenttype)
+		from
+			`tabSales Invoice` dt, `tabSales Team` st
+		where
+			st.sales_person = %s and st.parent = dt.name and dt.posting_date > date_sub(curdate(), interval 1 year)
+			group by dt.posting_date ''', name))
+	
+	for key in sales_invoice:
+		if out.get(key):
+			out[key] += sales_invoice[key]
+		else:
+			out[key] = sales_invoice[key]
+
+	delivery_note = dict(frappe.db.sql('''select
+			unix_timestamp(dt.posting_date), count(st.parenttype)
+		from
+			`tabDelivery Note` dt, `tabSales Team` st
+		where
+			st.sales_person = %s and st.parent = dt.name and dt.posting_date > date_sub(curdate(), interval 1 year)
+			group by dt.posting_date ''', name))
+
+	for key in delivery_note:
+		if out.get(key):
+			out[key] += delivery_note[key]
+		else:
+			out[key] = delivery_note[key]
+
+	return out
+
+	
diff --git a/erpnext/setup/doctype/sales_person/sales_person_dashboard.py b/erpnext/setup/doctype/sales_person/sales_person_dashboard.py
new file mode 100644
index 0000000..42528d8
--- /dev/null
+++ b/erpnext/setup/doctype/sales_person/sales_person_dashboard.py
@@ -0,0 +1,14 @@
+from frappe import _
+
+def get_data():
+	return {
+		'heatmap': True,
+		'heatmap_message': _('This is based on transactions against this Sales Person. See timeline below for details'),
+		'fieldname': 'sales_person',
+		'transactions': [
+			{
+				'label': _('Sales'),
+				'items': ['Sales Order', 'Delivery Note', 'Sales Invoice']
+			},
+		]
+	}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index 872daba..598504a 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -191,14 +191,14 @@
 	update_serial_nos(sle, item_det)
 
 def validate_serial_no(sle, item_det):
+	serial_nos = get_serial_nos(sle.serial_no) if sle.serial_no else []
 
 	if item_det.has_serial_no==0:
-		if sle.serial_no:
+		if serial_nos:
 			frappe.throw(_("Item {0} is not setup for Serial Nos. Column must be blank").format(sle.item_code),
 				SerialNoNotRequiredError)
 	elif sle.is_cancelled == "No":
-		if sle.serial_no:
-			serial_nos = get_serial_nos(sle.serial_no)
+		if serial_nos:
 			if cint(sle.actual_qty) != flt(sle.actual_qty):
 				frappe.throw(_("Serial No {0} quantity {1} cannot be a fraction").format(sle.item_code, sle.actual_qty))
 
@@ -285,6 +285,12 @@
 		elif sle.actual_qty < 0 or not item_det.serial_no_series:
 			frappe.throw(_("Serial Nos Required for Serialized Item {0}").format(sle.item_code),
 				SerialNoRequiredError)
+	elif serial_nos:
+		for serial_no in serial_nos:
+			sr = frappe.db.get_value("Serial No", serial_no, ["name", "warehouse"], as_dict=1)
+			if sr and sle.actual_qty < 0 and sr.warehouse != sle.warehouse:
+				frappe.throw(_("Cannot cancel {0} {1} because Serial No {2} does not belong to the warehouse {3}")
+					.format(sle.voucher_type, sle.voucher_no, serial_no, sle.warehouse))
 
 def validate_so_serial_no(sr, sales_order,):
 	if not sr.sales_order or sr.sales_order!= sales_order: