Merge pull request #10293 from ashwinisave35/knowledge_base_button

Changed Text of Knowledge base button to Help Article
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 070c93f..64bfa0f 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.2'
 
 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..806b489 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
@@ -556,6 +557,12 @@
 
 		self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 161.8)
 
+		link_data = get_dynamic_link_map().get('Sales Invoice', [])
+		link_doctypes = [d.parent for d in link_data]
+
+		# test case for dynamic link order
+		self.assertTrue(link_doctypes.index('GL Entry') > link_doctypes.index('Journal Entry Account'))
+
 		jv.cancel()
 		self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 561.8)
 
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 0f8b92f..5cb04c5 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -15,7 +15,8 @@
 from frappe.contacts.doctype.contact.contact import get_contact_details, get_default_contact
 from erpnext.exceptions import PartyFrozen, PartyDisabled, InvalidAccountCurrency
 from erpnext.accounts.utils import get_fiscal_year
-from erpnext import get_default_currency
+from erpnext import get_default_currency, get_company_currency
+
 
 class DuplicatePartyAccountError(frappe.ValidationError): pass
 
@@ -43,6 +44,7 @@
 		frappe.throw(_("Not permitted for {0}").format(party), frappe.PermissionError)
 
 	party = frappe.get_doc(party_type, party)
+	currency = party.default_currency if party.default_currency else get_company_currency(company)
 
 	set_address_details(out, party, party_type, doctype, company)
 	set_contact_details(out, party, party_type)
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index b269cb8..2dd7b6c 100755
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -14,6 +14,7 @@
  "engine": "InnoDB", 
  "fields": [
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 1, 
    "collapsible": 0, 
@@ -45,6 +46,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -74,6 +76,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -104,6 +107,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -132,6 +136,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 1, 
    "bold": 1, 
    "collapsible": 0, 
@@ -162,6 +167,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 1, 
    "bold": 1, 
    "collapsible": 0, 
@@ -191,6 +197,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 1, 
@@ -220,6 +227,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -252,6 +260,7 @@
    "width": "300px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -279,6 +288,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -308,6 +318,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -338,6 +349,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -366,6 +378,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 1, 
    "collapsible": 0, 
@@ -398,6 +411,7 @@
    "width": "60px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -431,6 +445,7 @@
    "width": "100px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -458,6 +473,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -491,6 +507,7 @@
    "width": "100px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -523,6 +540,7 @@
    "width": "100px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -550,6 +568,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -579,6 +598,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -608,6 +628,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -635,6 +656,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -664,6 +686,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -691,6 +714,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 1, 
    "collapsible": 0, 
@@ -722,6 +746,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -753,6 +778,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -780,6 +806,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -814,6 +841,7 @@
    "width": "100px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -845,6 +873,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -874,6 +903,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -902,6 +932,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -932,6 +963,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -962,6 +994,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -990,6 +1023,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1020,6 +1054,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1050,6 +1085,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1078,6 +1114,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1109,6 +1146,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1138,6 +1176,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1171,6 +1210,7 @@
    "width": "120px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1201,6 +1241,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1231,6 +1272,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1260,6 +1302,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1289,6 +1332,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1318,6 +1362,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1347,6 +1392,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1374,6 +1420,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1406,6 +1453,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1437,6 +1485,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1467,6 +1516,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1499,6 +1549,7 @@
    "width": "100px"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1529,6 +1580,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1559,6 +1611,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1588,6 +1641,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1619,6 +1673,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 1, 
    "bold": 0, 
    "collapsible": 0, 
@@ -1659,7 +1714,7 @@
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
- "modified": "2017-04-25 18:49:08.604055", 
+ "modified": "2017-08-02 22:15:47.411235", 
  "modified_by": "Administrator", 
  "module": "Buying", 
  "name": "Purchase Order Item", 
diff --git a/erpnext/crm/doctype/item/test_item.js b/erpnext/crm/doctype/item/test_item.js
index b48f93a..58cf549 100644
--- a/erpnext/crm/doctype/item/test_item.js
+++ b/erpnext/crm/doctype/item/test_item.js
@@ -117,4 +117,4 @@
 		),
 		() => done()
 	]);
-});
+});
\ No newline at end of file
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/manufacturing/doctype/production_order/test_production_order.js b/erpnext/manufacturing/doctype/production_order/test_production_order.js
index 57299db..0a7745e 100644
--- a/erpnext/manufacturing/doctype/production_order/test_production_order.js
+++ b/erpnext/manufacturing/doctype/production_order/test_production_order.js
@@ -1,8 +1,17 @@
 QUnit.test("test: production order", function (assert) {
-	assert.expect(2);
+	assert.expect(25);
 	let done = assert.async();
 	let laptop_quantity = 5;
-	let single_laptop_cost = 1340; // Calculated in workstation (time * per_hour_cost) for every item
+	let items = ["Screen", "CPU", "Keyboard"];
+	let operation_items = ["CPU", "Keyboard", "Screen"];
+	let click_make = () => {
+		let element = $(`.btn-primary:contains("Make"):visible`);
+		if(!element.length) {
+			throw `did not find any button containing 'Make'`;
+		}
+		element.click();
+		return frappe.timeout(1);
+	};
 
 	frappe.run_serially([
 		// test production order
@@ -24,18 +33,106 @@
 		() => frappe.timeout(1),
 		() => cur_frm.set_value("fg_warehouse", "Finished Goods - RB"),
 		() => cur_frm.save(),
-		() => frappe.timeout(1),
+		() => frappe.timeout(2),
 
 		() => {
-			assert.equal(cur_frm.doc.planned_operating_cost, cur_frm.doc.total_operating_cost, "Total and Planned Cost is equal");
-			assert.equal(cur_frm.doc.planned_operating_cost, laptop_quantity*single_laptop_cost, "Total cost is calculated correctly "+cur_frm.doc.planned_operating_cost);
+			assert.equal(cur_frm.doc.planned_operating_cost, cur_frm.doc.total_operating_cost,
+				"Total and Planned Cost is equal");
+			assert.equal(cur_frm.doc.planned_operating_cost, cur_frm.doc.total_operating_cost,
+				"Total and Planned Cost is equal");
+
+			items.forEach(function(item, index) {
+				assert.equal(item, cur_frm.doc.required_items[index].item_code, `Required item ${item} added`);
+				assert.equal("Stores - RB", cur_frm.doc.required_items[index].source_warehouse, `Item ${item} warhouse verified`);
+				assert.equal("5", cur_frm.doc.required_items[index].required_qty, `Item ${item} quantity verified`);
+			});
+
+			operation_items.forEach(function(operation_item, index) {
+				assert.equal(`Assemble ${operation_item}`, cur_frm.doc.operations[index].operation,
+					`Operation ${operation_item} added`);
+				assert.equal(`${operation_item} assembly workstation`, cur_frm.doc.operations[index].workstation,
+					`Workstation ${operation_item} linked`);
+			});
 		},
 
+		// Submit the production order
 		() => cur_frm.savesubmit(),
 		() => frappe.timeout(1),
 		() => frappe.click_button('Yes'),
 		() => frappe.timeout(1),
 
+		// Confirm the production order timesheet, save and submit it
+		() => frappe.click_link("TS-00"),
+		() => frappe.timeout(1),
+		() => frappe.click_button("Save"),
+		() => frappe.timeout(1),
+		() => frappe.click_button("Submit"),
+		() => frappe.timeout(1),
+		() => frappe.click_button("Yes"),
+		() => frappe.timeout(2),
+
+		// Start the production order process
+		() => frappe.set_route("List", "Production Order"),
+		() => frappe.timeout(2),
+		() => frappe.set_route("List", "Production Order"),
+		() => frappe.timeout(2),
+		() => frappe.click_link("Laptop"),
+		() => frappe.timeout(1),
+		() => frappe.click_button("Start"),
+		() => frappe.timeout(0.5),
+		() => click_make(),
+		() => frappe.click_button("Save"),
+		() => frappe.timeout(0.5),
+
+		() => {
+			assert.equal(cur_frm.doc.total_outgoing_value, cur_frm.doc.total_incoming_value,
+				"Total incoming and outgoing cost is equal");
+			assert.equal(cur_frm.doc.total_outgoing_value, "99000",
+				"Outgoing cost is correct"); // Price of each item x5
+		},
+		// Submit for production
+		() => frappe.click_button("Submit"),
+		() => frappe.timeout(0.5),
+		() => frappe.click_button("Yes"),
+		() => frappe.timeout(0.5),
+
+		// Finish the production order by sending for manufacturing
+		() => frappe.set_route("List", "Production Order"),
+		() => frappe.timeout(1),
+		() => frappe.click_link("Laptop"),
+		() => frappe.timeout(1),
+
+		() => {
+			assert.ok(frappe.tests.is_visible("5 items in progress", 'p'), "Production order initiated");
+			assert.ok(frappe.tests.is_visible("Finish"), "Finish button visible");
+		},
+
+		() => frappe.click_button("Finish"),
+		() => frappe.timeout(0.5),
+		() => click_make(),
+		() => {
+			assert.equal(cur_frm.doc.total_incoming_value, "105700",
+				"Incoming cost is correct"); // Price of each item x5, values are in USD
+			assert.equal(cur_frm.doc.total_outgoing_value, "99000",
+				"Outgoing cost is correct"); // Price of each item x5, values are in USD
+			assert.equal(cur_frm.doc.total_incoming_value - cur_frm.doc.total_outgoing_value, cur_frm.doc.value_difference,
+				"Value difference is correct"); // Price of each item x5, values are in USD
+		},
+		() => frappe.click_button("Save"),
+		() => frappe.timeout(1),
+		() => frappe.click_button("Submit"),
+		() => frappe.timeout(1),
+		() => frappe.click_button("Yes"),
+		() => frappe.timeout(1),
+
+		// Manufacturing finished
+		() => frappe.set_route("List", "Production Order"),
+		() => frappe.timeout(1),
+		() => frappe.click_link("Laptop"),
+		() => frappe.timeout(1),
+
+		() => assert.ok(frappe.tests.is_visible("5 items produced", 'p'), "Production order completed"),
+
 		() => done()
 	]);
-});
+});
\ No newline at end of file
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..03d128d
--- /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 project_type and 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/schools/doctype/program/test_program.js b/erpnext/schools/doctype/program/test_program.js
index 16bc932..a14fe97 100644
--- a/erpnext/schools/doctype/program/test_program.js
+++ b/erpnext/schools/doctype/program/test_program.js
@@ -2,7 +2,7 @@
 QUnit.module('schools');
 
 QUnit.test('Test: Program', function(assert){
-	assert.expect(11);
+	assert.expect(6);
 	let done = assert.async();
 	let fee_structure_code;
 	frappe.run_serially([
@@ -21,45 +21,6 @@
 			]);
 		},
 
-		() => cur_frm.save(),
-		// Setting up Fee Category to select in Program doctype
-		() => {
-			return frappe.tests.make('Fee Category', [
-				{category_name: 'Reservation'},
-				{description: 'Special Provision'}
-			]);
-		},
-		// Setting up Fee Structure to be selected in Program doctype
-		() => {
-			return frappe.tests.make('Fee Structure', [
-				{program: 'Standard Test'},
-				{academic_term: '2016-17 (Semester 1)'},
-				{student_category: 'Reservation'},
-				{components: [
-					[
-						{fees_category: 'Reservation'},
-						{amount: 20000}
-					]
-				]}
-			]);
-		},
-		() => {fee_structure_code = frappe.get_route()[2];}, // Storing naming convention of Fee Structure entry
-		() => frappe.set_route('Form', ('Program/Standard Test')), // Routing to our current Program doctype
-
-		() => $('.shaded-section~ .visible-section+ .visible-section .grid-add-row').trigger('click'), // clicking on Add Row button
-		// Storing data that were inter-dependent
-		() => cur_frm.doc.fees[0].academic_term = '2016-17 (Semester 1)',
-		() => cur_frm.doc.fees[0].student_category = 'Reservation',
-		() => cur_frm.doc.fees[0].due_date = '2016-08-20',
-		() => $('.error').trigger('click'),
-		() => $('.bold.input-sm').trigger('focus'),
-		() => frappe.timeout(1),
-		() => $('.bold.input-sm').trigger('focus'),
-		() => $('.bold.input-sm').val(fee_structure_code),
-		() => $('.bold.input-sm').trigger('focus'),
-		() => frappe.timeout(1),
-		() => cur_frm.save(),
-
 		() => {
 			assert.ok(cur_frm.doc.program_name == 'Standard Test');
 			assert.ok(cur_frm.doc.program_code == 'Standard Test');
@@ -67,11 +28,6 @@
 			assert.ok(cur_frm.doc.program_abbreviation == 'Standard Test');
 			assert.ok(cur_frm.doc.courses[0].course == 'Test_Sub');
 			assert.ok(cur_frm.doc.courses[0].required == true);
-			assert.ok(cur_frm.doc.fees[0].academic_term == '2016-17 (Semester 1)');
-			assert.ok(cur_frm.doc.fees[0].fee_structure == fee_structure_code);
-			assert.ok(cur_frm.doc.fees[0].student_category == 'Reservation');
-			assert.ok(cur_frm.doc.fees[0].due_date == '2016-08-20');
-			assert.ok(cur_frm.doc.fees[0].amount == 20000);
 		},
 		() => done()
 	]);
diff --git a/erpnext/schools/doctype/program_enrollment/program_enrollment.js b/erpnext/schools/doctype/program_enrollment/program_enrollment.js
index d1b703b..8418e85 100644
--- a/erpnext/schools/doctype/program_enrollment/program_enrollment.js
+++ b/erpnext/schools/doctype/program_enrollment/program_enrollment.js
@@ -43,6 +43,7 @@
 	},
 
 	program: function(frm) {
+		frm.events.get_courses(frm);
 		if (frm.doc.program) {
 			frappe.call({
 				method: "erpnext.schools.api.get_fee_schedule",
diff --git a/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_dummy_data.js b/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_dummy_data.js
new file mode 100644
index 0000000..26244ab
--- /dev/null
+++ b/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_dummy_data.js
@@ -0,0 +1,87 @@
+QUnit.module('Admission');
+
+QUnit.test('Make Students', function(assert){
+	assert.expect(0);
+	let done = assert.async();
+	let tasks = [];
+	let loop = [1,2,3,4];
+	let fname;
+
+	frappe.run_serially([
+		// Making School House to be used in this test and later
+		() => frappe.set_route('Form', 'School House/New School House'),
+		() => frappe.timeout(0.5),
+		() => cur_frm.doc.house_name = 'Test_house',
+		() => cur_frm.save(),
+
+		// Making Student Applicant entries
+		() => {
+			loop.forEach(index => {
+				tasks.push(() => {
+					fname = "Fname" + index;
+
+					return frappe.tests.make('Student Applicant', [
+						{first_name: fname},
+						{middle_name: "Mname"},
+						{last_name: "Lname"},
+						{program: "Standard Test"},
+						{student_admission: "2016-17 Admissions"},
+						{date_of_birth: '1995-08-20'},
+						{student_email_id: ('test' + (index+3) + '@testmail.com')},
+						{gender: 'Male'},
+						{student_mobile_number: (9898980000 + index)},
+						{blood_group: 'O+'},
+						{address_line_1: 'Test appt, Test Society,'},
+						{address_line_2: 'Test district, Test city.'},
+						{city: 'Test'},
+						{state: 'Test'},
+						{pincode: '395007'}
+					]);
+				});
+			});
+			return frappe.run_serially(tasks);
+		},
+
+		// Using Program Enrollment Tool to enroll all dummy student at once
+		() => frappe.set_route('Form', 'Program Enrollment Tool'),
+		() => {
+			cur_frm.set_value("get_students_from", "Student Applicants");
+			cur_frm.set_value("academic_year", "2016-17");
+			cur_frm.set_value("program", "Standard Test");
+		},
+		() => frappe.tests.click_button("Get Students"),
+		() => frappe.timeout(1),
+		() => frappe.tests.click_button("Enroll Students"),
+		() => frappe.timeout(1.5),
+		() => frappe.tests.click_button("Close"),
+
+		// Submitting required data for each enrolled Student
+		() => {
+			tasks = [];
+			loop.forEach(index => {
+				tasks.push(
+					() => {fname = "Fname" + index + " Mname Lname";},
+					() => frappe.set_route('List', 'Program Enrollment/List'),
+					() => frappe.timeout(0.6),
+					() => frappe.tests.click_link(fname),
+					() => frappe.timeout(0.4),
+					() => {
+						cur_frm.set_value('program', 'Standard Test');
+						cur_frm.set_value('student_category', 'Reservation');
+						cur_frm.set_value('student_batch_name', 'A');
+						cur_frm.set_value('academic_year', '2016-17');
+						cur_frm.set_value('academic_term', '2016-17 (Semester 1)');
+						cur_frm.set_value('school_house', 'Test_house');
+					},
+					() => cur_frm.save(),
+					() => frappe.timeout(0.5),
+					() => frappe.tests.click_button('Submit'),
+					() => frappe.tests.click_button('Yes'),
+					() => frappe.timeout(0.5)
+				);
+			});
+			return frappe.run_serially(tasks);
+		},
+		() => done()
+	]);
+});
\ No newline at end of file
diff --git a/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js b/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js
index 61f36e2..b983afd 100644
--- a/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js
+++ b/erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js
@@ -2,14 +2,10 @@
 QUnit.module('schools');
 
 QUnit.test('test student applicant', function(assert){
-	assert.expect(12);
+	assert.expect(11);
 	let done = assert.async();
 	let testing_status;
 	frappe.run_serially([
-		() => frappe.set_route('Form', 'School House/New School House'),
-		() => frappe.timeout(0.5),
-		() => cur_frm.doc.house_name = 'Test_house',
-		() => cur_frm.save(),
 		() => frappe.set_route('List', 'Student Applicant'),
 		() => frappe.timeout(0.5),
 		() => {$(`a:contains("Fname Mname Lname"):visible`)[0].click();},
@@ -97,26 +93,15 @@
 			cur_frm.set_value('academic_year', '2016-17');
 			cur_frm.set_value('academic_term', '2016-17 (Semester 1)');
 			cur_frm.set_value('school_house', 'Test_house');
-			$('a:contains("Fees"):visible').click();
-		},
-		() => frappe.timeout(1),
-		() => {
-			cur_frm.doc.fees[0].student_category = "Reservation";
 		},
 		() => cur_frm.save(),
+
 		// Submitting Program Enrollment form for our Test Student
-		() => frappe.timeout(0.5),
+		() => frappe.timeout(1),
 		() => frappe.tests.click_button('Submit'),
 		() => frappe.tests.click_button('Yes'),
 		() => {
-			testing_status = $('.msgprint').text();
-			assert.ok("Fee Records Created" == (testing_status.substring(0,19)), "Fee record created for enrolled student test");
-		},
-		() => frappe.timeout(0.5),
-		() => frappe.tests.click_button('Close'),
-		() => {
-			testing_status = $('h1').text();
-			assert.ok(testing_status.indexOf('Submitted') != -1, "Program enrollment successfully submitted"); // Checking if the program enrollment entry shows submitted or not
+			assert.ok(cur_frm.doc.docstatus == 1, "Program enrollment successfully submitted");
 		},
 		() => done()
 	]);
diff --git a/erpnext/schools/doctype/student_group/test_student_group.js b/erpnext/schools/doctype/student_group/test_student_group.js
new file mode 100644
index 0000000..842d0ba
--- /dev/null
+++ b/erpnext/schools/doctype/student_group/test_student_group.js
@@ -0,0 +1,62 @@
+// Testing Student Module in Schools
+QUnit.module('schools');
+
+QUnit.test('Test: Student Group', function(assert){
+	assert.expect(2);
+	let done = assert.async();
+	let instructor_code;
+	let loop = ["test-batch-wise-group", "test-course-wise-group"];
+	let tasks = [];
+
+	frappe.run_serially([
+		// Saving Instructor code beforehand
+		() => frappe.set_route('List', 'Instructor'),
+		() => frappe.timeout(0.5),
+		() => frappe.tests.click_link('Instructor 1'),
+		() => frappe.timeout(0.5),
+		() => {instructor_code = frappe.get_route()[2];},
+
+		// Creating a Batch and Course based group
+		() => {
+			loop.forEach(index => {
+				tasks.push(() => {
+					return frappe.tests.make('Student Group', [
+						{academic_year: '2016-17'},
+						{academic_term: '2016-17 (Semester 1)'},
+						{program: "Standard Test"},
+						{group_based_on: 'Batch'},
+						{student_group_name: index},
+						{max_strength: 10},
+						{batch: 'A'},
+						{instructors: [
+							[
+								{instructor: instructor_code}
+							]
+						]}
+					]);
+				});
+			});
+			return frappe.run_serially(tasks);
+		},
+
+		// Populating the created group with Students
+		() => {
+			tasks = [];
+			loop.forEach(index => {
+				tasks.push(
+					() => frappe.timeout(0.3),
+					() => frappe.set_route("Form", ('Student Group/' + index)),
+					() => frappe.timeout(0.3),
+					() => frappe.tests.click_button('Get Students'),
+					() => frappe.timeout(0.2),
+					() => {
+						assert.equal(cur_frm.doc.students.length, 5, 'Successfully fetched list of students');
+					},
+				);
+			});
+			return frappe.run_serially(tasks);
+		},
+
+		() => done()
+	]);
+});
\ No newline at end of file
diff --git a/erpnext/schools/doctype/student_group_creation_tool/student_group_creation_tool.js b/erpnext/schools/doctype/student_group_creation_tool/student_group_creation_tool.js
index 146f11c..d0d7afd 100644
--- a/erpnext/schools/doctype/student_group_creation_tool/student_group_creation_tool.js
+++ b/erpnext/schools/doctype/student_group_creation_tool/student_group_creation_tool.js
@@ -8,7 +8,7 @@
 	});
 	frappe.realtime.on("student_group_creation_progress", function(data) {
 		if(data.progress) {
-			frappe.hide_frappe.msgprint(true);
+			frappe.hide_msgprint(true);
 			frappe.show_progress(__("Creating student groups"), data.progress[0],data.progress[1]);
 		}
 	});
diff --git a/erpnext/schools/doctype/student_group_creation_tool/student_group_creation_tool.py b/erpnext/schools/doctype/student_group_creation_tool/student_group_creation_tool.py
index a236508..4a4cec7 100644
--- a/erpnext/schools/doctype/student_group_creation_tool/student_group_creation_tool.py
+++ b/erpnext/schools/doctype/student_group_creation_tool/student_group_creation_tool.py
@@ -64,6 +64,7 @@
 			student_group.program = self.program
 			student_group.course = d.course
 			student_group.batch = d.batch
+			student_group.max_strength = d.max_strength
 			student_group.academic_term = self.academic_term
 			student_group.academic_year = self.academic_year
 			student_group.save()
diff --git a/erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_tool.js b/erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_tool.js
new file mode 100644
index 0000000..c0b4dc8
--- /dev/null
+++ b/erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_tool.js
@@ -0,0 +1,88 @@
+QUnit.module('schools');
+
+QUnit.test('Test: Student Group Creation Tool', function(assert){
+	assert.expect(5);
+	let done = assert.async();
+	let instructor_code;
+
+	frappe.run_serially([
+		// Saving Instructor code beforehand
+		() => frappe.set_route('List', 'Instructor'),
+		() => frappe.timeout(0.5),
+		() => frappe.tests.click_link('Instructor 1'),
+		() => frappe.timeout(0.5),
+		() => {instructor_code = frappe.get_route()[2];},
+
+		// Setting up the creation tool to generate and save Student Group
+		() => frappe.set_route('Form', 'Student Group Creation Tool'),
+		() => frappe.timeout(0.5),
+		() => {
+			cur_frm.set_value("academic_year", "2016-17");
+			cur_frm.set_value("academic_term", "2016-17 (Semester 1)");
+			cur_frm.set_value("program", "Standard Test");
+			frappe.tests.click_button('Get Courses');
+		},
+		() => frappe.timeout(0.5),
+		() => {
+			assert.equal(cur_frm.doc.courses.length, 4, 'Successfully created groups using the tool');
+		},
+
+		() => {
+			let d, grid, grid_row;
+
+			for(d = 0; d < cur_frm.doc.courses.length; d++)
+			{
+				grid = cur_frm.get_field("courses").grid;
+				grid_row = grid.get_row(d).toggle_view(true);
+				if(grid_row.doc.student_group_name == 'Standard Test/A/2016-17 (Semester 1)'){
+					grid_row.doc.max_strength = 10;
+					grid_row.doc.student_group_name = "test-batch-wise-group-2";
+					$(`.octicon.octicon-triangle-up`).click();
+					continue;
+				}
+				else if(grid_row.doc.student_group_name == 'Test_Sub/Standard Test/2016-17 (Semester 1)'){
+					grid_row.doc.max_strength = 10;
+					grid_row.doc.student_group_name = "test-course-wise-group-2";
+					$(`.octicon.octicon-triangle-up`).click();
+					continue;
+				}
+			}
+		},
+
+		// Generating Student Group
+		() => frappe.timeout(0.5),
+		() => frappe.tests.click_button("Create Student Groups"),
+		() => frappe.timeout(0.5),
+		() => frappe.tests.click_button("Close"),
+
+		// Goin to the generated group to set up student and instructor list
+		() => {
+			let loop = ['Student Group/test-batch-wise-group-2', 'Student Group/test-course-wise-group-2'];
+			let tasks = [];
+			loop.forEach(index => {
+				tasks.push(
+					() => frappe.timeout(1),
+					() => frappe.set_route("Form", index),
+					() => frappe.timeout(0.5),
+					() => frappe.tests.click_button("Get Students"),
+					() => frappe.timeout(0.5),
+					() => {
+						assert.equal(cur_frm.doc.students.length, 5, 'Successfully fetched list of students');
+					},
+					() => frappe.timeout(0.5),
+					() => {
+						d = cur_frm.add_child('instructors');
+						d.instructor = instructor_code;
+						cur_frm.save();
+					},
+					() => {
+						assert.equal(cur_frm.doc.instructors.length, 1, 'Instructor detail stored successfully');
+					},
+				);
+			});
+			return frappe.run_serially(tasks);
+		},
+
+		() => done()
+	]);
+});
\ No newline at end of file
diff --git a/erpnext/schools/doctype/student_log/test_student_log.js b/erpnext/schools/doctype/student_log/test_student_log.js
new file mode 100644
index 0000000..6e03976
--- /dev/null
+++ b/erpnext/schools/doctype/student_log/test_student_log.js
@@ -0,0 +1,38 @@
+// Testing Student Module in Schools
+QUnit.module('schools');
+
+QUnit.test('Test: Student Log', function(assert){
+	assert.expect(9);
+	let done = assert.async();
+	let student_code;
+	frappe.run_serially([
+		() => frappe.set_route("List", "Student"),
+		() => frappe.timeout(0.5),
+		() => frappe.tests.click_link('Fname Mname Lname'),
+		() => frappe.timeout(0.5),
+		() => {student_code = frappe.get_route()[2];},
+		() => {
+			return frappe.tests.make("Student Log", [
+				{student: student_code},
+				{academic_year: '2016-17'},
+				{academic_term: '2016-17 (Semester 1)'},
+				{program: "Standard Test"},
+				{date: '2017-07-31'},
+				{student_batch: 'A'},
+				{log: 'This is Test log.'}
+			]);
+		},
+		() => {
+			assert.equal(cur_frm.doc.student, student_code, 'Student code was fetched properly');
+			assert.equal(cur_frm.doc.student_name, 'Fname Mname Lname', 'Student name was correctly auto-fetched');
+			assert.equal(cur_frm.doc.type, 'General', 'Default type selected');
+			assert.equal(cur_frm.doc.academic_year, '2016-17');
+			assert.equal(cur_frm.doc.academic_term, '2016-17 (Semester 1)');
+			assert.equal(cur_frm.doc.program, 'Standard Test', 'Program correctly selected');
+			assert.equal(cur_frm.doc.student_batch, 'A');
+			assert.equal(cur_frm.doc.date, '2017-07-31');
+			assert.equal(cur_frm.doc.log, 'This is Test log.');
+		},
+		() => done()
+	]);
+});
\ No newline at end of file
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/selling/doctype/sales_order/tests/test_sales_order_with_pricing_rule.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_pricing_rule.js
new file mode 100644
index 0000000..e91fb01
--- /dev/null
+++ b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_pricing_rule.js
@@ -0,0 +1,34 @@
+QUnit.module('Sales Order');
+
+QUnit.test("test sales order with shipping rule", function(assert) {
+	assert.expect(2);
+	let done = assert.async();
+	frappe.run_serially([
+		() => {
+			return frappe.tests.make('Sales Order', [
+				{customer: 'Test Customer 3'},
+				{items: [
+					[
+						{'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
+						{'qty': 5},
+						{'item_code': 'Test Product 2'},
+					]
+				]},
+				{customer_address: 'Test1-Billing'},
+				{shipping_address_name: 'Test1-Shipping'},
+				{contact_person: 'Contact 1-Test Customer 1'},
+			]);
+		},
+		() => cur_frm.save(),
+		() => {
+			// get_item_details
+			assert.ok(cur_frm.doc.items[0].item_name=='Test Product 2', "Item name correct");
+			// get grand_total details
+			assert.ok(cur_frm.doc.grand_total== 675, "Grand total correct ");
+		},
+		() => frappe.tests.click_button('Submit'),
+		() => frappe.tests.click_button('Yes'),
+		() => frappe.timeout(0.3),
+		() => done()
+	]);
+});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_shipping_rule.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_shipping_rule.js
new file mode 100644
index 0000000..7d1211f
--- /dev/null
+++ b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_shipping_rule.js
@@ -0,0 +1,35 @@
+QUnit.module('Sales Order');
+
+QUnit.test("test sales order with shipping rule", function(assert) {
+	assert.expect(2);
+	let done = assert.async();
+	frappe.run_serially([
+		() => {
+			return frappe.tests.make('Sales Order', [
+				{customer: 'Test Customer 1'},
+				{items: [
+					[
+						{'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
+						{'qty': 5},
+						{'item_code': 'Test Product 4'},
+					]
+				]},
+				{customer_address: 'Test1-Billing'},
+				{shipping_address_name: 'Test1-Shipping'},
+				{contact_person: 'Contact 1-Test Customer 1'},
+				{shipping_rule:'Next Day Shipping'}
+			]);
+		},
+		() => cur_frm.save(),
+		() => {
+			// get_item_details
+			assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
+			// get grand_total details
+			assert.ok(cur_frm.doc.grand_total== 550, "Grand total correct ");
+		},
+		() => frappe.tests.click_button('Submit'),
+		() => frappe.tests.click_button('Yes'),
+		() => frappe.timeout(0.3),
+		() => done()
+	]);
+});
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
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.json b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.json
index 9df4ff7..dc9a322 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.json
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.json
@@ -452,6 +452,7 @@
    "label": "Difference Amount", 
    "length": 0, 
    "no_copy": 0, 
+   "options": "Company:company:default_currency", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -477,7 +478,7 @@
  "istable": 0, 
  "max_attachments": 1, 
  "menu_index": 0, 
- "modified": "2017-06-16 17:35:54.811500", 
+ "modified": "2017-08-02 23:54:28.516007", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Stock Reconciliation", 
diff --git a/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json b/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json
index 4a19108..0fafe83 100644
--- a/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json
+++ b/erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json
@@ -1,5 +1,6 @@
 {
  "allow_copy": 0, 
+ "allow_guest_to_view": 0, 
  "allow_import": 0, 
  "allow_rename": 0, 
  "beta": 0, 
@@ -12,6 +13,7 @@
  "engine": "InnoDB", 
  "fields": [
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -41,6 +43,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -71,6 +74,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -100,6 +104,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -130,6 +135,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -158,6 +164,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -188,6 +195,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -205,6 +213,7 @@
    "label": "Valuation Rate", 
    "length": 0, 
    "no_copy": 0, 
+   "options": "Company:company:default_currency", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -218,6 +227,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -234,6 +244,7 @@
    "label": "Amount", 
    "length": 0, 
    "no_copy": 0, 
+   "options": "Company:company:default_currency", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -247,6 +258,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -276,6 +288,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -306,6 +319,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -334,6 +348,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -351,6 +366,7 @@
    "label": "Current Valuation Rate", 
    "length": 0, 
    "no_copy": 0, 
+   "options": "Company:company:default_currency", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -364,6 +380,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -381,6 +398,7 @@
    "label": "Current Amount", 
    "length": 0, 
    "no_copy": 0, 
+   "options": "Company:company:default_currency", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -394,6 +412,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -422,6 +441,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -451,6 +471,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -479,6 +500,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -495,6 +517,7 @@
    "label": "Amount Difference", 
    "length": 0, 
    "no_copy": 0, 
+   "options": "Company:company:default_currency", 
    "permlevel": 0, 
    "precision": "", 
    "print_hide": 0, 
@@ -508,18 +531,18 @@
    "unique": 0
   }
  ], 
+ "has_web_view": 0, 
  "hide_heading": 0, 
  "hide_toolbar": 0, 
  "idx": 0, 
  "image_view": 0, 
  "in_create": 0, 
- "in_dialog": 0, 
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 1, 
  "max_attachments": 0, 
  "menu_index": 0, 
- "modified": "2017-02-20 13:32:09.827878", 
+ "modified": "2017-08-03 00:03:40.412071", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Stock Reconciliation Item", 
diff --git a/erpnext/stock/doctype/warehouse/test_warehouse.js b/erpnext/stock/doctype/warehouse/test_warehouse.js
index 3763613..f13bc58 100644
--- a/erpnext/stock/doctype/warehouse/test_warehouse.js
+++ b/erpnext/stock/doctype/warehouse/test_warehouse.js
@@ -16,4 +16,4 @@
 
 		() => done()
 	]);
-});
+});
\ No newline at end of file
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index ec55cec..916adff 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -29,14 +29,28 @@
 	return columns, data
 
 def get_columns():
-	return [_("Date") + ":Datetime:95", _("Item") + ":Link/Item:130", _("Item Name") + "::100", _("Item Group") + ":Link/Item Group:100",
-		_("Brand") + ":Link/Brand:100", _("Description") + "::200", _("Warehouse") + ":Link/Warehouse:100",
-		_("Stock UOM") + ":Link/UOM:100", _("Qty") + ":Float:50", _("Balance Qty") + ":Float:100",
-		_("Incoming Rate") + ":Currency:110", _("Valuation Rate") + ":Currency:110", _("Balance Value") + ":Currency:110",
-		_("Voucher Type") + "::110", _("Voucher #") + ":Dynamic Link/"+_("Voucher Type")+":100", _("Batch") + ":Link/Batch:100",
-		_("Serial #") + ":Link/Serial No:100", _("Company") + ":Link/Company:100"
+	columns = [
+		_("Date") + ":Datetime:95", _("Item") + ":Link/Item:130",
+		_("Item Name") + "::100", _("Item Group") + ":Link/Item Group:100",
+		_("Brand") + ":Link/Brand:100", _("Description") + "::200",
+		_("Warehouse") + ":Link/Warehouse:100", _("Stock UOM") + ":Link/UOM:100",
+		_("Qty") + ":Float:50", _("Balance Qty") + ":Float:100",
+		{"label": _("Incoming Rate"), "fieldtype": "Currency", "width": 110,
+			"options": "Company:company:default_currency"},
+		{"label": _("Valuation Rate"), "fieldtype": "Currency", "width": 110,
+			"options": "Company:company:default_currency"},
+		{"label": _("Balance Value"), "fieldtype": "Currency", "width": 110,
+			"options": "Company:company:default_currency"},
+		_("Voucher Type") + "::110",
+		_("Voucher #") + ":Dynamic Link/" + _("Voucher Type") + ":100",
+		_("Batch") + ":Link/Batch:100",
+		_("Serial #") + ":Link/Serial No:100",
+		{"label": _("Company"), "fieldtype": "Link", "width": 110,
+			"options": "company", "fieldname": "company"}
 	]
 
+	return columns
+
 def get_stock_ledger_entries(filters):
 	return frappe.db.sql("""select concat_ws(" ", posting_date, posting_time) as date,
 			item_code, warehouse, actual_qty, qty_after_transaction, incoming_rate, valuation_rate,
diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt
index fb86b7c..4ce1675 100644
--- a/erpnext/tests/ui/tests.txt
+++ b/erpnext/tests/ui/tests.txt
@@ -16,6 +16,8 @@
 erpnext/selling/doctype/sales_order/tests/test_sales_order_with_multi_uom.js
 erpnext/selling/doctype/sales_order/tests/test_sales_order_with_discount_on_grand_total.js
 erpnext/selling/doctype/sales_order/tests/test_sales_order_with_taxes_and_charges.js
+erpnext/selling/doctype/sales_order/tests/test_sales_order_with_shipping_rule.js
+erpnext/selling/doctype/sales_order/tests/test_sales_order_with_pricing_rule.js
 erpnext/manufacturing/doctype/workstation/test_workstation.js
 erpnext/manufacturing/doctype/operation/test_operation.js
 erpnext/manufacturing/doctype/bom/test_bom.js
@@ -41,7 +43,7 @@
 erpnext/schools/doctype/room/test_room.js
 erpnext/schools/doctype/instructor/test_instructor.js
 erpnext/stock/doctype/warehouse/test_warehouse.js
-erpnext/manufacturing/doctype/production_order/test_production_order.js
+erpnext/manufacturing/doctype/production_order/test_production_order.js #long
 erpnext/accounts/page/pos/test_pos.js
 erpnext/selling/doctype/product_bundle/test_product_bundle.js
 erpnext/schools/doctype/grading_scale/test_grading_scale.js
@@ -51,5 +53,9 @@
 erpnext/schools/doctype/program/test_program.js
 erpnext/schools/doctype/guardian/test_guardian.js
 erpnext/schools/doctype/student_admission/test_student_admission.js
+erpnext/schools/doctype/student_applicant/tests/test_student_applicant_dummy_data.js
 erpnext/schools/doctype/student_applicant/tests/test_student_applicant.js
-erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js
\ No newline at end of file
+erpnext/schools/doctype/student_applicant/tests/test_student_applicant_options.js
+erpnext/schools/doctype/student_log/test_student_log.js
+erpnext/schools/doctype/student_group/test_student_group.js
+erpnext/schools/doctype/student_group_creation_tool/test_student_group_creation_tool.js
\ No newline at end of file