Merge branch 'hotfix'
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 7ee4dee..833ddff 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -4,7 +4,7 @@
 import frappe
 from erpnext.hooks import regional_overrides
 
-__version__ = '8.6.4'
+__version__ = '8.6.5'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json
index 93aca1b..6991da2 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.json
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json
@@ -727,38 +727,6 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "tc_name", 
-   "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": "Terms and Conditions", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "tc_name", 
-   "oldfieldtype": "Link", 
-   "options": "Terms and Conditions", 
-   "permlevel": 0, 
-   "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, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
    "fieldname": "column_break0", 
    "fieldtype": "Column Break", 
    "hidden": 0, 
@@ -788,39 +756,6 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "description": "", 
-   "fieldname": "territory", 
-   "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": "Territory", 
-   "length": 0, 
-   "no_copy": 0, 
-   "oldfieldname": "territory", 
-   "oldfieldtype": "Link", 
-   "options": "Territory", 
-   "permlevel": 0, 
-   "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, 
-   "unique": 0
-  }, 
-  {
-   "allow_bulk_edit": 0, 
-   "allow_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
    "fieldname": "selling_price_list", 
    "fieldtype": "Link", 
    "hidden": 0, 
@@ -853,6 +788,38 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "tc_name", 
+   "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": "Terms and Conditions", 
+   "length": 0, 
+   "no_copy": 0, 
+   "oldfieldname": "tc_name", 
+   "oldfieldtype": "Link", 
+   "options": "Terms and Conditions", 
+   "permlevel": 0, 
+   "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, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "apply_discount", 
    "fieldtype": "Check", 
    "hidden": 0, 
@@ -916,6 +883,129 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "customer_details", 
+   "fieldtype": "Section 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, 
+   "label": "New Customer Details", 
+   "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, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "description": "", 
+   "fieldname": "territory", 
+   "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": "Territory", 
+   "length": 0, 
+   "no_copy": 0, 
+   "oldfieldname": "territory", 
+   "oldfieldtype": "Link", 
+   "options": "Territory", 
+   "permlevel": 0, 
+   "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, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "column_break_31", 
+   "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, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "customer_group", 
+   "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": "Customer Group", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Customer Group", 
+   "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, 
+   "unique": 0
+  }, 
+  {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "section_break_19", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -1201,7 +1291,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-06-16 17:04:33.165676", 
+ "modified": "2017-07-28 03:40:03.253088", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "POS Profile", 
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py
index ef497bf..86682d3 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py
@@ -14,6 +14,7 @@
 		self.check_for_duplicate()
 		self.validate_all_link_fields()
 		self.validate_duplicate_groups()
+		self.validate_customer_territory_group()
 
 	def check_for_duplicate(self):
 		res = frappe.db.sql("""select name, user from `tabPOS Profile`
@@ -48,6 +49,13 @@
 		if len(customer_groups) != len(set(customer_groups)):
 			frappe.throw(_("Duplicate customer group found in the cutomer group table"), title = "Duplicate Customer Group")
 
+	def validate_customer_territory_group(self):
+		if not self.territory:
+			frappe.throw(_("Territory is Required in POS Profile"), title="Mandatory Field")
+
+		if not self.customer_group:
+			frappe.throw(_("Customer Group is Required in POS Profile"), title="Mandatory Field")
+
 	def before_save(self):
 		set_account_for_mode_of_payment(self)
 
diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.js b/erpnext/accounts/doctype/pos_profile/test_pos_profile.js
new file mode 100644
index 0000000..42e5b7f
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.js
@@ -0,0 +1,23 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: POS Profile", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially('POS Profile', [
+		// insert a new POS Profile
+		() => frappe.tests.make([
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
index 9c6a114..534abb6 100644
--- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
@@ -42,6 +42,7 @@
 		"naming_series": "_T-POS Profile-",
 		"selling_price_list": "_Test Price List",
 		"territory": "_Test Territory",
+		"customer_group": frappe.db.get_value('Customer Group', {'is_group': 0}, 'name'),
 		"warehouse": "_Test Warehouse - _TC",
 		"write_off_account": "_Test Write Off - _TC",
 		"write_off_cost_center": "_Test Write Off Cost Center - _TC"
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index f61931a..3c9de12 100644
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -3,6 +3,7 @@
 
 from __future__ import unicode_literals
 import frappe, json
+from frappe import _
 from frappe.utils import nowdate
 from erpnext.setup.utils import get_exchange_rate
 from frappe.core.doctype.communication.email import make
@@ -20,6 +21,7 @@
 
 	if pos_profile.get('name'):
 		pos_profile = frappe.get_doc('POS Profile', pos_profile.get('name'))
+		pos_profile.validate()
 
 	company_data = get_company_data(doc.company)
 	update_pos_profile_data(doc, pos_profile, company_data)
@@ -378,13 +380,27 @@
 	customer_doc.customer_name = data.get('full_name') or data.get('customer')
 	customer_doc.customer_pos_id = data.get('customer_pos_id')
 	customer_doc.customer_type = 'Company'
-	customer_doc.customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group')
-	customer_doc.territory = frappe.db.get_single_value('Selling Settings', 'territory')
+	customer_doc.customer_group = get_customer_group(data)
+	customer_doc.territory = get_territory(data)
 	customer_doc.flags.ignore_mandatory = True
 	customer_doc.save(ignore_permissions = True)
 	frappe.db.commit()
 	return customer_doc.name
 
+def get_territory(data):
+	if data.get('territory'):
+		return data.get('territory')
+
+	return frappe.db.get_single_value('Selling Settings',
+		'territory') or _('All Territories')
+
+def get_customer_group(data):
+	if data.get('customer_group'):
+		return data.get('customer_group')
+
+	return frappe.db.get_single_value('Selling Settings',
+		'customer_group') or frappe.db.get_value('Customer Group', {'is_group': 0}, 'name')
+
 def make_contact(args,customer):
 	if args.get('email_id') or args.get('phone'):
 		name = frappe.db.get_value('Dynamic Link',
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index a5f9b3c..d69a306 100644
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -979,6 +979,8 @@
 	get_prompt_details: function() {
 		this.prompt_details = this.customer_doc.get_values();
 		this.prompt_details['country'] = this.pos_profile_data.country;
+		this.prompt_details['territory'] = this.pos_profile_data["territory"];
+		this.prompt_details['customer_group'] = this.pos_profile_data["customer_group"];
 		this.prompt_details['customer_pos_id'] = this.customer_doc.fields_dict.customer_pos_id.value;
 		return JSON.stringify(this.prompt_details)
 	},
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 005abe6..0f8b92f 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -273,6 +273,7 @@
 	return due_date
 
 def get_credit_days(party_type, party, company):
+	credit_days = 0
 	if party_type and party:
 		if party_type == "Customer":
 			credit_days_based_on, credit_days, customer_group = \
@@ -282,10 +283,10 @@
 				frappe.db.get_value(party_type, party, ["credit_days_based_on", "credit_days", "supplier_type"])
 
 	if not credit_days_based_on:
-		if party_type == "Customer":
+		if party_type == "Customer" and customer_group:
 			credit_days_based_on, credit_days = \
 				frappe.db.get_value("Customer Group", customer_group, ["credit_days_based_on", "credit_days"])
-		else:
+		elif party_type == "Supplier" and supplier_type:
 			credit_days_based_on, credit_days = \
 				frappe.db.get_value("Supplier Type", supplier_type, ["credit_days_based_on", "credit_days"])
 
diff --git a/erpnext/controllers/tests/test_recurring_document.py b/erpnext/controllers/tests/test_recurring_document.py
index e218fa6..d47c5c7 100644
--- a/erpnext/controllers/tests/test_recurring_document.py
+++ b/erpnext/controllers/tests/test_recurring_document.py
@@ -27,8 +27,7 @@
 	base_doc.set(date_field, today)
 
 	if base_doc.doctype == "Sales Order":
-		for d in base_doc.get("items"):
-			d.set("delivery_date", add_days(today, 15))
+		base_doc.set("delivery_date", add_days(today, 15))
 
 	# monthly
 	doc1 = frappe.copy_doc(base_doc)
diff --git a/erpnext/demo/user/sales.py b/erpnext/demo/user/sales.py
index 666e201..ddd36ef 100644
--- a/erpnext/demo/user/sales.py
+++ b/erpnext/demo/user/sales.py
@@ -118,8 +118,7 @@
 		from erpnext.selling.doctype.quotation.quotation import make_sales_order
 		so = frappe.get_doc(make_sales_order(q))
 		so.transaction_date = frappe.flags.current_date
-		for d in so.get("items"):
-			d.delivery_date = frappe.utils.add_days(frappe.flags.current_date, 10)
+		so.delivery_date = frappe.utils.add_days(frappe.flags.current_date, 10)
 		so.insert()
 		frappe.db.commit()
 		so.submit()
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py
index 9533613..022e9f3 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/production_order.py
@@ -273,7 +273,7 @@
 		timesheets = []
 		plan_days = frappe.db.get_single_value("Manufacturing Settings", "capacity_planning_for_days") or 30
 
-		timesheet = make_timesheet(self.name)
+		timesheet = make_timesheet(self.name, self.company)
 		timesheet.set('time_logs', [])
 
 		for i, d in enumerate(self.operations):
@@ -575,10 +575,11 @@
 	return data
 
 @frappe.whitelist()
-def make_timesheet(production_order):
+def make_timesheet(production_order, company):
 	timesheet = frappe.new_doc("Timesheet")
 	timesheet.employee = ""
 	timesheet.production_order = production_order
+	timesheet.company = company
 	return timesheet
 
 @frappe.whitelist()
diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.py b/erpnext/manufacturing/doctype/production_order/test_production_order.py
index 18aa51d..1d555f7 100644
--- a/erpnext/manufacturing/doctype/production_order/test_production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/test_production_order.py
@@ -87,6 +87,7 @@
 
 		name = frappe.db.get_value('Timesheet', {'production_order': prod_order.name}, 'name')
 		time_sheet_doc = frappe.get_doc('Timesheet', name)
+		self.assertEqual(prod_order.company, time_sheet_doc.company)
 		time_sheet_doc.submit()
 		
 
@@ -107,7 +108,7 @@
 		self.assertEqual(prod_order.operations[0].actual_operation_time, 60)
 		self.assertEqual(prod_order.operations[0].actual_operating_cost, 100)
 		
-		time_sheet_doc1 = make_timesheet(prod_order.name)
+		time_sheet_doc1 = make_timesheet(prod_order.name, prod_order.company)
 		self.assertEqual(len(time_sheet_doc1.get('time_logs')), 0)
 
 		time_sheet_doc.cancel()
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index fb8f02e..2923d6d 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -422,5 +422,7 @@
 erpnext.patches.v8_3.set_restrict_to_domain_for_module_def
 erpnext.patches.v8_1.update_expense_claim_status
 erpnext.patches.v8_3.update_company_total_sales
-erpnext.patches.v8_1.set_delivery_date_in_so_item
-erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs
\ No newline at end of file
+erpnext.patches.v8_1.set_delivery_date_in_so_item #2017-07-28
+erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs
+erpnext.patches.v8_5.update_customer_group_in_POS_profile
+erpnext.patches.v8_6.update_timesheet_company_from_PO
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/set_delivery_date_in_so_item.py b/erpnext/patches/v8_1/set_delivery_date_in_so_item.py
index 6840424..963b82a 100644
--- a/erpnext/patches/v8_1/set_delivery_date_in_so_item.py
+++ b/erpnext/patches/v8_1/set_delivery_date_in_so_item.py
@@ -4,10 +4,18 @@
 	frappe.reload_doctype("Sales Order")
 	frappe.reload_doctype("Sales Order Item")
 
-	frappe.db.sql("""update `tabSales Order` set final_delivery_date = delivery_date where docstatus=1""")
+	if "final_delivery_date" in frappe.db.get_table_columns("Sales Order"):
+		frappe.db.sql("""
+			update `tabSales Order`
+			set delivery_date = final_delivery_date
+			where (delivery_date is null or delivery_date = '' or delivery_date = '0000-00-00')
+				and order_type = 'Sales'""")
 
 	frappe.db.sql("""
 		update `tabSales Order` so, `tabSales Order Item` so_item
 		set so_item.delivery_date = so.delivery_date
 		where so.name = so_item.parent
+			and so.order_type = 'Sales'
+			and (so_item.delivery_date is null or so_item.delivery_date = ''
+				or so_item.delivery_date = '0000-00-00')
 	""")
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py b/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py
new file mode 100644
index 0000000..9a5fef9
--- /dev/null
+++ b/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py
@@ -0,0 +1,8 @@
+import frappe
+
+def execute():
+	frappe.reload_doctype('POS Profile')
+	customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group')
+	if customer_group:
+		frappe.db.sql(""" update `tabPOS Profile`
+			set customer_group = %s where customer_group is null """, (customer_group))
\ No newline at end of file
diff --git a/erpnext/patches/v8_6/__init__.py b/erpnext/patches/v8_6/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/patches/v8_6/__init__.py
diff --git a/erpnext/patches/v8_6/update_timesheet_company_from_PO.py b/erpnext/patches/v8_6/update_timesheet_company_from_PO.py
new file mode 100644
index 0000000..5bab961
--- /dev/null
+++ b/erpnext/patches/v8_6/update_timesheet_company_from_PO.py
@@ -0,0 +1,15 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	frappe.reload_doctype('Timesheet')
+	company = frappe.get_all('Company')
+
+	#Check more than one company exists
+	if len(company) > 1:
+		frappe.db.sql(""" update `tabTimesheet` set `tabTimesheet`.company =
+			(select company from `tabProduction Order` where name = `tabTimesheet`.production_order)
+			where production_order is not null and production_order !=''""")
\ No newline at end of file
diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py
index 1db0610..955a2b0 100644
--- a/erpnext/projects/doctype/timesheet/test_timesheet.py
+++ b/erpnext/projects/doctype/timesheet/test_timesheet.py
@@ -14,8 +14,8 @@
 
 class TestTimesheet(unittest.TestCase):
 	def test_timesheet_billing_amount(self):
-		salary_structure = make_salary_structure("_T-Employee-0001")
-		timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable=1)
+		make_salary_structure("_T-Employee-0001")
+		timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=1)
 
 		self.assertEquals(timesheet.total_hours, 2)
 		self.assertEquals(timesheet.total_billable_hours, 2)
@@ -23,6 +23,16 @@
 		self.assertEquals(timesheet.time_logs[0].billing_amount, 100)
 		self.assertEquals(timesheet.total_billable_amount, 100)
 
+	def test_timesheet_billing_amount_not_billable(self):
+		make_salary_structure("_T-Employee-0001")
+		timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=0)
+
+		self.assertEquals(timesheet.total_hours, 2)
+		self.assertEquals(timesheet.total_billable_hours, 0)
+		self.assertEquals(timesheet.time_logs[0].billing_rate, 0)
+		self.assertEquals(timesheet.time_logs[0].billing_amount, 0)
+		self.assertEquals(timesheet.total_billable_amount, 0)
+
 	def test_salary_slip_from_timesheet(self):
 		salary_structure = make_salary_structure("_T-Employee-0001")
 		timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable=1)
@@ -43,7 +53,7 @@
 		self.assertEquals(timesheet.status, 'Submitted')
 
 	def test_sales_invoice_from_timesheet(self):
-		timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable = 1)
+		timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=1)
 		sales_invoice = make_sales_invoice(timesheet.name)
 		sales_invoice.customer = "_Test Customer"
 		sales_invoice.due_date = nowdate()
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index 441ab1a..9b330e7 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -105,7 +105,9 @@
 	},
 
 	billable: function(frm, cdt, cdn) {
-		calculate_billing_costing_amount(frm, cdt, cdn)
+		update_billing_hours(frm, cdt, cdn);
+		update_time_rates(frm, cdt, cdn);
+		calculate_billing_costing_amount(frm, cdt, cdn);
 	},
 
 	activity_type: function(frm, cdt, cdn) {
@@ -148,8 +150,21 @@
 	}
 }
 
+var update_billing_hours = function(frm, cdt, cdn){
+	var child = locals[cdt][cdn];
+	if(!child.billable) frappe.model.set_value(cdt, cdn, 'billing_hours', 0.0);
+}
+
+var update_time_rates = function(frm, cdt, cdn){
+	var child = locals[cdt][cdn];
+	if(!child.billable){
+		frappe.model.set_value(cdt, cdn, 'billing_rate', 0.0);
+		frappe.model.set_value(cdt, cdn, 'costing_rate', 0.0);
+	}
+}
+
 var calculate_billing_costing_amount = function(frm, cdt, cdn){
-	var child = locals[cdt][cdn]
+	var child = locals[cdt][cdn];
 	var billing_amount = 0.0;
 	var costing_amount = 0.0;
 
@@ -160,7 +175,7 @@
 
 	frappe.model.set_value(cdt, cdn, 'billing_amount', billing_amount);
 	frappe.model.set_value(cdt, cdn, 'costing_amount', costing_amount);
-	calculate_time_and_amount(frm)
+	calculate_time_and_amount(frm);
 }
 
 var calculate_time_and_amount = function(frm) {
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index 6416176..bb3d902 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -46,6 +46,7 @@
 
 		for d in self.get("time_logs"):
 			self.update_billing_hours(d)
+			self.update_time_rates(d)
 
 			self.total_hours += flt(d.hours)
 			if d.billable:
@@ -61,8 +62,11 @@
 			self.per_billed = (self.total_billed_amount * 100) / self.total_billable_amount
 
 	def update_billing_hours(self, args):
-		if cint(args.billing_hours) == 0:
-			args.billing_hours = args.hours
+		if args.billable:
+			if flt(args.billing_hours) == 0.0:
+				args.billing_hours = args.hours
+		else:
+			args.billing_hours = 0
 
 	def set_status(self):
 		self.status = {
@@ -263,13 +267,19 @@
 		for data in self.time_logs:
 			if data.activity_type and data.billable:
 				rate = get_activity_cost(self.employee, data.activity_type)
-				hours =  data.billing_hours or 0
+				hours = data.billing_hours or 0
 				if rate:
 					data.billing_rate = flt(rate.get('billing_rate')) if flt(data.billing_rate) == 0 else data.billing_rate
 					data.costing_rate = flt(rate.get('costing_rate')) if flt(data.costing_rate) == 0 else data.costing_rate
 					data.billing_amount = data.billing_rate * hours
 					data.costing_amount = data.costing_rate * hours
 
+	def update_time_rates(self, ts_detail):
+		if not ts_detail.billable:
+			ts_detail.billing_rate = 0.0
+			ts_detail.costing_rate = 0.0
+
+
 @frappe.whitelist()
 def get_projectwise_timesheet_data(project, parent=None):
 	cond = ''
diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py
index 7fb4074..fa69df4 100644
--- a/erpnext/selling/doctype/quotation/test_quotation.py
+++ b/erpnext/selling/doctype/quotation/test_quotation.py
@@ -27,8 +27,7 @@
 		self.assertEquals(sales_order.get("items")[0].prevdoc_docname, quotation.name)
 		self.assertEquals(sales_order.customer, "_Test Customer")
 
-		for d in sales_order.get("items"):
-			d.delivery_date = "2014-01-01"
+		sales_order.delivery_date = "2014-01-01"
 		sales_order.naming_series = "_T-Quotation-"
 		sales_order.transaction_date = "2013-05-12"
 		sales_order.insert()
@@ -54,8 +53,7 @@
 		sales_order = make_sales_order(quotation.name)
 		sales_order.naming_series = "_T-Quotation-"
 		sales_order.transaction_date = "2016-01-01"
-		for d in sales_order.get("items"):
-			d.delivery_date = "2016-01-02"
+		sales_order.delivery_date = "2016-01-02"
 
 		sales_order.insert()
 
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 2e01a08..80dc4f2 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -34,11 +34,20 @@
 
 		erpnext.queries.setup_warehouse_query(frm);
 	},
+	
+	delivery_date: function(frm) {
+		$.each(frm.doc.items || [], function(i, d) {
+			if(!d.delivery_date) d.delivery_date = frm.doc.delivery_date;
+		});
+		refresh_field("items");
+	}
 });
 
 frappe.ui.form.on("Sales Order Item", {
 	delivery_date: function(frm, cdt, cdn) {
-		erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "delivery_date");
+		if(!frm.doc.delivery_date) {
+			erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "delivery_date");
+		}
 	}	
 });
 
@@ -416,8 +425,13 @@
 
 	items_add: function(doc, cdt, cdn) {
 		var row = frappe.get_doc(cdt, cdn);
-		this.frm.script_manager.copy_from_first_row("items", row, ["delivery_date"]);
+		if(doc.delivery_date) {
+			row.delivery_date = doc.delivery_date;
+			refresh_field("delivery_date", cdn, "items");
+		} else {
+			this.frm.script_manager.copy_from_first_row("items", row, ["delivery_date"]);
+		}
 	}
 });
 
-$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm}));
+$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm}));
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index 596bf2f..bf2ccf7 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -367,23 +367,23 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "final_delivery_date", 
+   "fieldname": "delivery_date", 
    "fieldtype": "Date", 
-   "hidden": 1, 
+   "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": "Final Delivery Date", 
+   "label": "Delivery Date", 
    "length": 0, 
    "no_copy": 1, 
    "permlevel": 0, 
    "precision": "", 
-   "print_hide": 1, 
+   "print_hide": 0, 
    "print_hide_if_no_value": 0, 
-   "read_only": 1, 
+   "read_only": 0, 
    "remember_last_selected_value": 0, 
    "report_hide": 0, 
    "reqd": 0, 
@@ -3659,7 +3659,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-07-25 13:45:02.965353", 
+ "modified": "2017-07-28 14:03:33.373347", 
  "modified_by": "Administrator", 
  "module": "Selling", 
  "name": "Sales Order", 
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index fd80dc8..c6dbd70 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -101,20 +101,20 @@
 		super(SalesOrder, self).validate_order_type()
 
 	def validate_delivery_date(self):
-		self.final_delivery_date = None
 		if self.order_type == 'Sales':
-			for d in self.get("items"):
-				if not d.delivery_date:
-					frappe.throw(_("Row #{0}: Please enter Delivery Date against item {1}")
-						.format(d.idx, d.item_code))
+			if not self.delivery_date:
+				self.delivery_date = max([d.delivery_date for d in self.get("items")])
 
-				if getdate(self.transaction_date) > getdate(d.delivery_date):
-					frappe.msgprint(_("Expected Delivery Date should be after Sales Order Date"),
-						indicator='orange', title=_('Warning'))
-
-				if not self.final_delivery_date or \
-					(d.delivery_date and getdate(d.delivery_date) > getdate(self.final_delivery_date)):
-						self.final_delivery_date = d.delivery_date
+			if self.delivery_date:
+				for d in self.get("items"):
+					if not d.delivery_date:
+						d.delivery_date = self.delivery_date
+					
+					if getdate(self.transaction_date) > getdate(d.delivery_date):
+						frappe.msgprint(_("Expected Delivery Date should be after Sales Order Date"),
+							indicator='orange', title=_('Warning'))
+			else:
+				frappe.throw(_("Please enter Delivery Date"))
 
 		self.validate_sales_mntc_quotation()
 
@@ -347,6 +347,9 @@
 
 	def on_recurring(self, reference_doc):
 		mcount = month_map[reference_doc.recurring_type]
+		self.set("delivery_date", get_next_date(reference_doc.delivery_date, mcount,
+			cint(reference_doc.repeat_on_day_of_month)))
+
 		for d in self.get("items"):
 			reference_delivery_date = frappe.db.get_value("Sales Order Item",
 				{"parent": reference_doc.name, "item_code": d.item_code, "idx": d.idx}, "delivery_date")
diff --git a/erpnext/selling/doctype/sales_order/sales_order_list.js b/erpnext/selling/doctype/sales_order/sales_order_list.js
index 0ee9cf3..9751935 100644
--- a/erpnext/selling/doctype/sales_order/sales_order_list.js
+++ b/erpnext/selling/doctype/sales_order/sales_order_list.js
@@ -1,14 +1,14 @@
 frappe.listview_settings['Sales Order'] = {
-	add_fields: ["base_grand_total", "customer_name", "currency", "final_delivery_date",
+	add_fields: ["base_grand_total", "customer_name", "currency", "delivery_date",
 		"per_delivered", "per_billed", "status", "order_type", "name"],
 	get_indicator: function(doc) {
 		if(doc.status==="Closed"){
 			return [__("Closed"), "green", "status,=,Closed"];
 
 		} else if (doc.order_type !== "Maintenance"
-			&& flt(doc.per_delivered, 2) < 100 && frappe.datetime.get_diff(doc.final_delivery_date) < 0) {
+			&& flt(doc.per_delivered, 2) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
 			// to bill & overdue
-			return [__("Overdue"), "red", "per_delivered,<,100|final_delivery_date,<,Today|status,!=,Closed"];
+			return [__("Overdue"), "red", "per_delivered,<,100|delivery_date,<,Today|status,!=,Closed"];
 
 		} else if (doc.order_type !== "Maintenance"
 			&& flt(doc.per_delivered, 2) < 100 && doc.status!=="Closed") {
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.js b/erpnext/selling/doctype/sales_order/test_sales_order.js
new file mode 100644
index 0000000..87f0e96
--- /dev/null
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.js
@@ -0,0 +1,59 @@
+/* eslint-disable */
+// rename this file from _test_[name] to test_[name] to activate
+// and remove above this line
+
+QUnit.test("test: Sales Order", function (assert) {
+	assert.expect(2);
+	let done = assert.async();
+	let delivery_date = frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1);
+
+	frappe.run_serially([
+		// insert a new Sales Order
+		() => {
+			return frappe.tests.make('Sales Order', [
+				{customer: "Test Customer 1"},
+				{delivery_date: delivery_date},
+				{order_type: 'Sales'},
+				{items: [
+					[
+						{"item_code": "Test Product 1"},
+						{"qty": 5},
+						{'rate': 100},
+					]]
+				}
+			])
+		},
+		() => {
+			assert.ok(cur_frm.doc.items[0].delivery_date == delivery_date);
+		},
+		() => frappe.timeout(1),
+		// make SO without delivery date in parent, 
+		// parent delivery date should be set based on final delivery date entered in item
+		() => {
+			return frappe.tests.make('Sales Order', [
+				{customer: "Test Customer 1"},
+				{order_type: 'Sales'},
+				{items: [
+					[
+						{"item_code": "Test Product 1"},
+						{"qty": 5},
+						{'rate': 100},
+						{'delivery_date': delivery_date}
+					],
+					[
+						{"item_code": "Test Product 2"},
+						{"qty": 5},
+						{'rate': 100},
+						{'delivery_date': frappe.datetime.add_days(delivery_date, 5)}
+					]]
+				}
+			])
+		},
+		() => cur_frm.save(),
+		() => frappe.timeout(1),
+		() => {
+			assert.ok(cur_frm.doc.delivery_date == frappe.datetime.add_days(delivery_date, 5));
+		},
+		() => done()
+	]);
+});
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 8c07118..ce8c18a 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -532,8 +532,7 @@
 			"rate": args.rate or 100
 		})
 
-	for d in so.get("items"):
-		d.delivery_date = add_days(so.transaction_date, 10)
+	so.delivery_date = add_days(so.transaction_date, 10)
 
 	if not args.do_not_save:
 		so.insert()
diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
index f14f50d..47bc1b6 100644
--- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json
+++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json
@@ -220,7 +220,7 @@
    "no_copy": 1, 
    "permlevel": 0, 
    "precision": "", 
-   "print_hide": 0, 
+   "print_hide": 1, 
    "print_hide_if_no_value": 0, 
    "read_only": 0, 
    "remember_last_selected_value": 0, 
@@ -1963,7 +1963,7 @@
  "istable": 1, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2017-07-18 18:26:36.870342", 
+ "modified": "2017-07-28 14:04:04.289428", 
  "modified_by": "Administrator", 
  "module": "Selling", 
  "name": "Sales Order Item", 
diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt
index 42233dc..40b1c59 100644
--- a/erpnext/tests/ui/tests.txt
+++ b/erpnext/tests/ui/tests.txt
@@ -2,4 +2,5 @@
 erpnext/accounts/doctype/account/test_account.js
 erpnext/crm/doctype/lead/test_lead.js
 erpnext/crm/doctype/opportunity/test_opportunity.js
-erpnext/selling/doctype/quotation/test_quotation.js
\ No newline at end of file
+erpnext/selling/doctype/quotation/test_quotation.js
+erpnext/selling/doctype/sales_order/test_sales_order.js
\ No newline at end of file