resolved merge conflicts
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 070c93f..4d6cccf 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -4,7 +4,7 @@
 import frappe
 from erpnext.hooks import regional_overrides
 
-__version__ = '8.7.0'
+__version__ = '8.7.1'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/account/account.js b/erpnext/accounts/doctype/account/account.js
index ed7e39a..ca46d6b0 100644
--- a/erpnext/accounts/doctype/account/account.js
+++ b/erpnext/accounts/doctype/account/account.js
@@ -68,7 +68,8 @@
 					}
 				});
 			});
-		} else if (cint(frm.doc.is_group) == 0) {
+		} else if (cint(frm.doc.is_group) == 0
+			&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
 			cur_frm.add_custom_button(__('Ledger'), function () {
 				frappe.route_options = {
 					"account": frm.doc.name,
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json
index b1a4129..76e66d0 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.json
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json
@@ -718,7 +718,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-04-27 13:18:06.617940", 
+ "modified": "2017-08-03 12:40:09.611951", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "GL Entry", 
@@ -786,7 +786,7 @@
   }
  ], 
  "quick_entry": 1, 
- "read_only": 1, 
+ "read_only": 0, 
  "read_only_onload": 0, 
  "search_fields": "voucher_no,account,posting_date,against_voucher", 
  "show_name_in_global_search": 0, 
diff --git a/erpnext/accounts/doctype/gl_entry/test_gl_entry.js b/erpnext/accounts/doctype/gl_entry/test_gl_entry.js
new file mode 100644
index 0000000..2986e5e
--- /dev/null
+++ b/erpnext/accounts/doctype/gl_entry/test_gl_entry.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: GL Entry", function (assert) {
+	let done = assert.async();
+
+	// number of asserts
+	assert.expect(1);
+
+	frappe.run_serially('GL Entry', [
+		// insert a new GL Entry
+		() => frappe.tests.make([
+			// values to be set
+			{key: 'value'}
+		]),
+		() => {
+			assert.equal(cur_frm.doc.key, 'value');
+		},
+		() => done()
+	]);
+
+});
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index e768c27..589bc40 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -510,7 +510,7 @@
 
 				i += 1
 
-		if self.update_stock and valuation_tax:
+		if self.auto_accounting_for_stock and self.update_stock and valuation_tax:
 			for cost_center, amount in valuation_tax.items():
 				gl_entries.append(
 					self.get_gl_dict({
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 62d9a1e..0c4b951 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -5,6 +5,7 @@
 import frappe
 import unittest, copy
 from frappe.utils import nowdate, add_days, flt
+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
 from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
@@ -119,6 +120,10 @@
 		pe.insert()
 		pe.submit()
 
+		link_data = get_dynamic_link_map().get('Sales Invoice', [])
+		link_doctypes = [d.parent for d in link_data]
+		self.assertEquals(link_doctypes[-1], 'GL Entry')
+
 		unlink_payment_on_cancel_of_invoice(0)
 		si = frappe.get_doc('Sales Invoice', si.name)
 		self.assertRaises(frappe.LinkExistsError, si.cancel)
diff --git a/erpnext/hr/doctype/process_payroll/process_payroll.py b/erpnext/hr/doctype/process_payroll/process_payroll.py
index 287ce61..7575ee4 100644
--- a/erpnext/hr/doctype/process_payroll/process_payroll.py
+++ b/erpnext/hr/doctype/process_payroll/process_payroll.py
@@ -339,7 +339,12 @@
 					"debit_in_account_currency": total_salary_amount.rounded_total
 				})	
 			journal_entry.set("accounts", account_amt_list)
-		return journal_entry.as_dict()
+			return journal_entry.as_dict()
+		else:
+			frappe.msgprint(
+				_("There are no submitted Salary Slips to process."),
+				title="Error", indicator="red"
+			)
 
 	def update_salary_slip_status(self, jv_name = None):
 		ss_list = self.get_sal_slip_list(ss_status=1)
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 64cf5d0..b6d29d8 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -429,4 +429,6 @@
 erpnext.patches.v8_5.update_existing_data_in_project_type
 erpnext.patches.v8_5.set_default_mode_of_payment
 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
+erpnext.patches.v8_6.update_timesheet_company_from_PO
+erpnext.patches.v8_6.set_write_permission_for_quotation_for_sales_manager
+erpnext.patches.v8_5.remove_project_type_property_setter
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py b/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py
index 2ae74cd..5dedc81 100644
--- a/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py
+++ b/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py
@@ -26,7 +26,7 @@
 		if not sales_invoice or not serial_nos:
 			continue
 
-		serial_nos = ["'%s'"%no for no in serial_nos.split("\n")]
+		serial_nos = ["'%s'"%frappe.db.escape(no) for no in serial_nos.split("\n")]
 
 		frappe.db.sql("""
 			UPDATE 
@@ -36,7 +36,7 @@
 			WHERE
 				name in ({serial_nos})
 			""".format(
-				sales_invoice=sales_invoice,
+				sales_invoice=frappe.db.escape(sales_invoice),
 				serial_nos=",".join(serial_nos)
 			)
 		)
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/remove_project_type_property_setter.py b/erpnext/patches/v8_5/remove_project_type_property_setter.py
new file mode 100644
index 0000000..11db783
--- /dev/null
+++ b/erpnext/patches/v8_5/remove_project_type_property_setter.py
@@ -0,0 +1,17 @@
+import frappe
+
+def execute():
+	ps = frappe.db.get_value('Property Setter', dict(doc_type='Project', field_name='project_type',
+		property='options'))
+	if ps:
+		frappe.delete_doc('Property Setter', ps)
+
+	project_types = frappe.db.sql_list('select distinct project_type from tabProject')
+
+	for project_type in project_types:
+		if not frappe.db.exists("Project Type", project_type):
+			p_type = frappe.get_doc({
+				"doctype": "Project Type",
+				"project_type": project_type
+			})
+			p_type.insert()
\ No newline at end of file
diff --git a/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py b/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py
new file mode 100644
index 0000000..c2320ec
--- /dev/null
+++ b/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py
@@ -0,0 +1,11 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+	# Set write permission to permlevel 1 for sales manager role in Quotation doctype
+	frappe.db.sql(""" update `tabCustom DocPerm` set `tabCustom DocPerm`.write = 1
+		where `tabCustom DocPerm`.parent = 'Quotation' and `tabCustom DocPerm`.role = 'Sales Manager'
+		and `tabCustom DocPerm`.permlevel = 1 """)
diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json
index 33eed19..16ea578 100644
--- a/erpnext/selling/doctype/quotation/quotation.json
+++ b/erpnext/selling/doctype/quotation/quotation.json
@@ -2602,7 +2602,7 @@
  "istable": 0, 
  "max_attachments": 1, 
  "menu_index": 0, 
- "modified": "2017-07-25 08:14:35.355019", 
+ "modified": "2017-08-02 18:15:38.198698", 
  "modified_by": "Administrator", 
  "module": "Selling", 
  "name": "Quotation", 
@@ -2668,7 +2668,7 @@
    "set_user_permissions": 0, 
    "share": 0, 
    "submit": 0, 
-   "write": 0
+   "write": 1
   }, 
   {
    "amend": 1, 
diff --git a/erpnext/shopping_cart/product.py b/erpnext/shopping_cart/product.py
index 1999a4a..912467f 100644
--- a/erpnext/shopping_cart/product.py
+++ b/erpnext/shopping_cart/product.py
@@ -85,7 +85,7 @@
 
 			if pricing_rule:
 				if pricing_rule.pricing_rule_for == "Discount Percentage":
-					price[0].price_list_rate = flt(price[0].price_list_rate * (1.0 - (pricing_rule.discount_percentage / 100.0)))
+					price[0].price_list_rate = flt(price[0].price_list_rate * (1.0 - (flt(pricing_rule.discount_percentage) / 100.0)))
 
 				if pricing_rule.pricing_rule_for == "Price":
 					price[0].price_list_rate = pricing_rule.price_list_rate