Merge branch 'master' into develop
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 1a98835..42f538d 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -4,7 +4,7 @@
 import frappe
 from erpnext.hooks import regional_overrides
 
-__version__ = '9.1.5'
+__version__ = '9.1.6'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index ccf8a84..04f7e1b 100644
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -486,17 +486,21 @@
 		if frappe.message_log: frappe.message_log.pop()
 		frappe.db.rollback()
 		frappe.log_error(frappe.get_traceback())
-		name_list = save_invoice(e, si_doc, name, name_list)
+		name_list = save_invoice(doc, name, name_list)
 
 	return name_list
 
-def save_invoice(e, si_doc, name, name_list):
+def save_invoice(doc, name, name_list):
 	try:
 		if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
-			si_doc.docstatus = 0
-			si_doc.flags.ignore_mandatory = True
-			si_doc.due_date = si_doc.posting_date
-			si_doc.insert()
+			si = frappe.new_doc('Sales Invoice')
+			si.update(doc)
+			si.set_posting_time = 1
+			si.customer = get_customer_id(doc)
+			si.due_date = doc.get('posting_date')
+			si.flags.ignore_mandatory = True
+			si.insert(ignore_permissions=True)
+			frappe.db.commit()
 			name_list.append(name)
 	except Exception:
 		frappe.log_error(frappe.get_traceback())
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 900a6e9..264f027 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -3,8 +3,8 @@
 from __future__ import unicode_literals
 
 import frappe
-import unittest, copy
-from frappe.utils import nowdate, add_days, flt
+import unittest, copy, time
+from frappe.utils import nowdate, add_days, flt, cint
 from frappe.model.dynamic_links import get_dynamic_link_map
 from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
 from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
@@ -665,6 +665,47 @@
 
 		self.pos_gl_entry(si, pos, 330)
 
+	def test_make_pos_invoice_in_draft(self):
+		from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
+		from erpnext.stock.doctype.item.test_item import make_item
+
+		set_perpetual_inventory()
+
+		allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
+		if allow_negative_stock:
+			frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 0)
+
+		make_pos_profile()
+		timestamp = cint(time.time())
+
+		item = make_item("_Test POS Item")
+		pos = copy.deepcopy(test_records[1])
+		pos['items'][0]['item_code'] = item.name
+		pos["is_pos"] = 1
+		pos["offline_pos_name"] = timestamp
+		pos["update_stock"] = 1
+		pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300},
+							{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 330}]
+
+		invoice_data = [{timestamp: pos}]
+		si = make_invoice(invoice_data).get('invoice')
+		self.assertEquals(si[0], timestamp)
+
+		sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp})
+		self.assertEquals(sales_invoice[0].docstatus, 0)
+
+		timestamp = cint(time.time())
+		pos["offline_pos_name"] = timestamp
+		invoice_data = [{timestamp: pos}]
+		si1 = make_invoice(invoice_data).get('invoice')
+		self.assertEquals(si1[0], timestamp)
+
+		sales_invoice1 = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp})
+		self.assertEquals(sales_invoice1[0].docstatus, 0)
+
+		if allow_negative_stock:
+			frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 1)
+
 	def pos_gl_entry(self, si, pos, cash_amount):
 		# check stock ledger entries
 		sle = frappe.db.sql("""select * from `tabStock Ledger Entry`
diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py
index 07f6979..78e3faa 100644
--- a/erpnext/accounts/report/gross_profit/gross_profit.py
+++ b/erpnext/accounts/report/gross_profit/gross_profit.py
@@ -107,6 +107,8 @@
 
 	def process(self):
 		self.grouped = {}
+		self.grouped_data = []
+
 		for row in self.si_list:
 			if self.skip_row(row, self.product_bundles):
 				continue
@@ -150,7 +152,6 @@
 
 	def get_average_rate_based_on_group_by(self):
 		# sum buying / selling totals for group
-		self.grouped_data = []
 		for key in self.grouped.keys():
 			if self.filters.get("group_by") != "Invoice":
 				for i, row in enumerate(self.grouped[key]):
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
index 44068ce..50d6abd 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
@@ -816,7 +816,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-07-21 14:06:46.309322", 
+ "modified": "2017-10-17 17:27:06.281494", 
  "modified_by": "Administrator", 
  "module": "Buying", 
  "name": "Request for Quotation", 
@@ -909,26 +909,6 @@
    "cancel": 0, 
    "create": 0, 
    "delete": 0, 
-   "email": 1, 
-   "export": 0, 
-   "if_owner": 0, 
-   "import": 0, 
-   "permlevel": 0, 
-   "print": 1, 
-   "read": 1, 
-   "report": 1, 
-   "role": "Supplier", 
-   "set_user_permissions": 0, 
-   "share": 0, 
-   "submit": 0, 
-   "write": 0
-  }, 
-  {
-   "amend": 0, 
-   "apply_user_permissions": 0, 
-   "cancel": 0, 
-   "create": 0, 
-   "delete": 0, 
    "email": 0, 
    "export": 0, 
    "if_owner": 0, 
diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py
index 513b97f..8ca4f70 100644
--- a/erpnext/controllers/item_variant.py
+++ b/erpnext/controllers/item_variant.py
@@ -205,9 +205,10 @@
 
 	if item.variant_based_on=='Item Attribute':
 		if variant.attributes:
-			variant.description += "\n"
-			for d in variant.attributes:
-				variant.description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
+			if not variant.description:
+				variant.description += "\n"
+				for d in variant.attributes:
+					variant.description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
 
 def make_variant_item_code(template_item_code, template_item_name, variant):
 	"""Uses template's item code and abbreviations to make variant's item code"""
diff --git a/erpnext/healthcare/doctype/consultation/consultation.py b/erpnext/healthcare/doctype/consultation/consultation.py
index b8155b9..e16c221 100755
--- a/erpnext/healthcare/doctype/consultation/consultation.py
+++ b/erpnext/healthcare/doctype/consultation/consultation.py
@@ -78,7 +78,7 @@
 	create_invoice_items(physician, sales_invoice, company)
 
 	sales_invoice.save(ignore_permissions=True)
-	frappe.db.sql(_("""update tabConsultation set invoice='{0}' where name='{1}'""").format(sales_invoice.name, consultation_id))
+	frappe.db.sql("""update tabConsultation set invoice=%s where name=%s""", (sales_invoice.name, consultation_id))
 	appointment = frappe.db.get_value("Consultation", consultation_id, "appointment")
 	if appointment:
 		frappe.db.set_value("Patient Appointment", appointment, "sales_invoice", sales_invoice.name)
diff --git a/erpnext/healthcare/doctype/lab_test/lab_test.py b/erpnext/healthcare/doctype/lab_test/lab_test.py
index 0daf9cb..6fd9535 100644
--- a/erpnext/healthcare/doctype/lab_test/lab_test.py
+++ b/erpnext/healthcare/doctype/lab_test/lab_test.py
@@ -291,5 +291,5 @@
 
 @frappe.whitelist()
 def get_lab_test_prescribed(patient):
-	return frappe.db.sql(_("""select cp.name, cp.test_code, cp.parent, cp.invoice, ct.physician, ct.consultation_date from tabConsultation ct,
-	`tabLab Prescription` cp where ct.patient='{0}' and cp.parent=ct.name and cp.test_created=0""").format(patient))
+	return frappe.db.sql("""select cp.name, cp.test_code, cp.parent, cp.invoice, ct.physician, ct.consultation_date from tabConsultation ct,
+	`tabLab Prescription` cp where ct.patient=%s and cp.parent=ct.name and cp.test_created=0""", (patient))
diff --git a/erpnext/healthcare/doctype/patient/patient.py b/erpnext/healthcare/doctype/patient/patient.py
index 98526cc..f4d9a43 100644
--- a/erpnext/healthcare/doctype/patient/patient.py
+++ b/erpnext/healthcare/doctype/patient/patient.py
@@ -111,10 +111,10 @@
 
 @frappe.whitelist()
 def get_patient_detail(patient, company=None):
-	patient_dict = frappe.db.sql(_("""select * from tabPatient where name='{0}'""").format(patient), as_dict=1)
+	patient_dict = frappe.db.sql("""select * from tabPatient where name=%s""", (patient), as_dict=1)
 	if not patient_dict:
 		frappe.throw("Patient not found")
-	vital_sign = frappe.db.sql(_("""select * from `tabVital Signs` where patient='{0}' order by signs_date desc limit 1""").format(patient), as_dict=1)
+	vital_sign = frappe.db.sql("""select * from `tabVital Signs` where patient=%s order by signs_date desc limit 1""", (patient), as_dict=1)
 
 	details = patient_dict[0]
 	if vital_sign:
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index eab2f2d..2647034 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -125,7 +125,7 @@
 	create_invoice_items(appointment_id, physician, company, sales_invoice)
 
 	sales_invoice.save(ignore_permissions=True)
-	frappe.db.sql(_("""update `tabPatient Appointment` set sales_invoice='{0}' where name='{1}'""").format(sales_invoice.name, appointment_id))
+	frappe.db.sql("""update `tabPatient Appointment` set sales_invoice=%s where name=%s""", (sales_invoice.name, appointment_id))
 	frappe.db.set_value("Fee Validity", fee_validity.name, "ref_invoice", sales_invoice.name)
 	consultation = frappe.db.exists({
 			"doctype": "Consultation",
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index ead5d33..b140bf5 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -147,22 +147,28 @@
 		if arg.get('scrap_items'):
 			rate = self.get_valuation_rate(arg)
 		elif arg:
-			if self.rm_cost_as_per == 'Valuation Rate':
-				rate = self.get_valuation_rate(arg)
-			elif self.rm_cost_as_per == 'Last Purchase Rate':
-				rate = arg['last_purchase_rate'] \
-					or frappe.db.get_value("Item", arg['item_code'], "last_purchase_rate")
-			elif self.rm_cost_as_per == "Price List":
-				if not self.buying_price_list:
-					frappe.throw(_("Please select Price List"))
-				rate = frappe.db.get_value("Item Price",
-					{"price_list": self.buying_price_list, "item_code": arg["item_code"]}, "price_list_rate")
-				price_list_currency = frappe.db.get_value("Price List", self.buying_price_list, "currency")
-				if price_list_currency != self.company_currency():
-					rate = flt(rate * self.conversion_rate)
-
-			if arg['bom_no'] and (not rate or self.set_rate_of_sub_assembly_item_based_on_bom):
+			if arg.get('bom_no') and self.set_rate_of_sub_assembly_item_based_on_bom:
 				rate = self.get_bom_unitcost(arg['bom_no'])
+			else:
+				if self.rm_cost_as_per == 'Valuation Rate':
+					rate = self.get_valuation_rate(arg)
+				elif self.rm_cost_as_per == 'Last Purchase Rate':
+					rate = arg.get('last_purchase_rate') \
+						or frappe.db.get_value("Item", arg['item_code'], "last_purchase_rate")
+				elif self.rm_cost_as_per == "Price List":
+					if not self.buying_price_list:
+						frappe.throw(_("Please select Price List"))
+					rate = frappe.db.get_value("Item Price", {"price_list": self.buying_price_list,
+						"item_code": arg["item_code"]}, "price_list_rate")
+
+					price_list_currency = frappe.db.get_value("Price List",
+						self.buying_price_list, "currency")
+					if price_list_currency != self.company_currency():
+						rate = flt(rate * self.conversion_rate)
+
+				if not rate:
+					frappe.msgprint(_("{0} not found for Item {1}")
+						.format(self.rm_cost_as_per, arg["item_code"]))
 
 		return flt(rate)
 
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 9492c11..ef34189 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -452,3 +452,4 @@
 erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
 erpnext.patches.v9_0.student_admission_childtable_migrate
 erpnext.patches.v9_0.add_healthcare_domain
+erpnext.patches.v9_0.set_variant_item_description
diff --git a/erpnext/patches/v9_0/set_variant_item_description.py b/erpnext/patches/v9_0/set_variant_item_description.py
new file mode 100644
index 0000000..c844571
--- /dev/null
+++ b/erpnext/patches/v9_0/set_variant_item_description.py
@@ -0,0 +1,45 @@
+import frappe
+from frappe.utils import cstr
+
+def execute():
+	'''
+	Issue:
+		While copying data from template item to variant item,
+		the system appending description multiple times to the respective variant.
+
+	Purpose:
+		Check variant description,
+		if variant have user defined description remove all system appended descriptions
+		else replace multiple system generated descriptions with single description
+
+	Steps:
+		1. Get all variant items
+		2. Create system generated variant description
+		3. If variant have user defined description, remove all system generated descriptions
+		4. If variant description only contains system generated description,
+			replace multiple descriptions by new description.
+	'''
+	for item in frappe.db.sql(""" select name from tabItem
+		where ifnull(variant_of, '') != '' """,as_dict=1):
+			variant = frappe.get_doc("Item", item.name)
+			temp_variant_description = '\n'
+
+			if variant.attributes:
+				for d in variant.attributes:
+					temp_variant_description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
+
+				variant_description = variant.description.replace(temp_variant_description, '').rstrip()
+				if variant_description:
+					splitted_desc = variant.description.strip().split(temp_variant_description)
+
+					if len(splitted_desc) > 2:
+						if splitted_desc[0] == '':
+							variant_description = temp_variant_description + variant_description
+						elif splitted_desc[1] == '' or splitted_desc[1] == '\n':
+							variant_description += temp_variant_description
+						variant.db_set('description', variant_description, update_modified=False)
+					else:
+						variant.db_set('description', variant_description, update_modified=False)
+
+				else:
+					variant.db_set('description', temp_variant_description, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index ba1414c..1ea5962 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -159,9 +159,14 @@
 });
 
 var calculate_end_time = function(frm, cdt, cdn) {
-	var child = locals[cdt][cdn];
+	let child = locals[cdt][cdn];
 
-	var d = moment(child.from_time);
+	if(!child.from_time) {
+		// if from_time value is not available then set the current datetime
+		frappe.model.set_value(cdt, cdn, "from_time", frappe.datetime.get_datetime_as_string());
+	}
+
+	let d = moment(child.from_time);
 	if(child.hours) {
 		d.add(child.hours, "hours");
 		frm._setting_hours = true;