Merge branch 'master' into staging-fixes
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index c00d90e..0d5ac9d 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
 from erpnext.hooks import regional_overrides
 from frappe.utils import getdate
 
-__version__ = '10.1.73'
+__version__ = '10.1.74'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
index 86023aa..eb95e45 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
+++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
@@ -70,12 +70,14 @@
 				net_pl_balance += flt(acc.balance_in_company_currency)
 
 		if net_pl_balance:
+			cost_center = frappe.db.get_value("Company", self.company, "cost_center")
 			gl_entries.append(self.get_gl_dict({
 				"account": self.closing_account_head,
 				"debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
 				"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
 				"credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
-				"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0
+				"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0,
+				"cost_center": cost_center
 			}))
 
 		from erpnext.accounts.general_ledger import make_gl_entries
diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
index 9ef66ed..eb02d97 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
+++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
@@ -72,6 +72,7 @@
 			"company": "_Test Company",
 			"fiscal_year": get_fiscal_year(today(), company="_Test Company")[0],
 			"posting_date": today(),
+			"cost_center": "_Test Cost Center - _TC",
 			"remarks": "test"
 		})
 		pcv.insert()
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index 995efee..e4f37c4 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -21,8 +21,6 @@
 		from erpnext.stock.get_item_details import get_item_details
 		from frappe import MandatoryError
 
-
-
 		test_record = {
 			"doctype": "Pricing Rule",
 			"title": "_Test Pricing Rule",
@@ -93,7 +91,7 @@
 
 		args.item_code = "_Test Item 2"
 		details = get_item_details(args)
-		self.assertEqual(details.get("discount_percentage"), 15)
+		self.assertEquals(details.get("discount_percentage"), 15)
 
 	def test_pricing_rule_for_margin(self):
 		from erpnext.stock.get_item_details import get_item_details
@@ -137,8 +135,8 @@
 			"name": None
 		})
 		details = get_item_details(args)
-		self.assertEqual(details.get("margin_type"), "Percentage")
-		self.assertEqual(details.get("margin_rate_or_amount"), 10)
+		self.assertEquals(details.get("margin_type"), "Percentage")
+		self.assertEquals(details.get("margin_rate_or_amount"), 10)
 
 	def test_pricing_rule_for_variants(self):
 		from erpnext.stock.get_item_details import get_item_details
@@ -253,6 +251,7 @@
 		self.assertEqual(so.items[0].rate, 100)
 
 	def test_pricing_rule_with_margin_and_discount(self):
+		frappe.delete_doc_if_exists('Pricing Rule', '_Test Pricing Rule')
 		make_pricing_rule(selling=1, margin_type="Percentage", margin_rate_or_amount=10, discount_percentage=10)
 		si = create_sales_invoice(do_not_save=True)
 		si.items[0].price_list_rate = 1000
@@ -260,12 +259,11 @@
 		si.insert(ignore_permissions=True)
 
 		item = si.items[0]
-		self.assertEqual(item.margin_rate_or_amount, 10)
-		self.assertEqual(item.rate_with_margin, 1100)
+		self.assertEquals(item.margin_rate_or_amount, 10)
+		self.assertEquals(item.rate_with_margin, 1100)
 		self.assertEqual(item.discount_percentage, 10)
-		self.assertEqual(item.discount_amount, 110)
-		self.assertEqual(item.rate, 990)
-
+		self.assertEquals(item.discount_amount, 110)
+		self.assertEquals(item.rate, 990)
 
 def make_pricing_rule(**args):
 	args = frappe._dict(args)
@@ -295,4 +293,4 @@
 
 	applicable_for = doc.applicable_for.replace(' ', '_').lower()
 	if args.get(applicable_for):
-		doc.db_set(applicable_for, args.get(applicable_for))
\ No newline at end of file
+		doc.db_set(applicable_for, args.get(applicable_for))
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index a441025..5bbef18 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -65,6 +65,7 @@
 
 				if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item']:
 					item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item)
+
 					if flt(item.rate_with_margin) > 0:
 						item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))
 						item.discount_amount = item.rate_with_margin - item.rate
@@ -647,4 +648,4 @@
 	# Rounding based on tax_amount precision
 	for taxes in itemised_tax.values():
 		for tax_account in taxes:
-			taxes[tax_account]["tax_amount"] = flt(taxes[tax_account]["tax_amount"], precision)
\ No newline at end of file
+			taxes[tax_account]["tax_amount"] = flt(taxes[tax_account]["tax_amount"], precision)
diff --git a/erpnext/education/doctype/assessment_result/assessment_result.js b/erpnext/education/doctype/assessment_result/assessment_result.js
index 5f13e3e..84865ca 100644
--- a/erpnext/education/doctype/assessment_result/assessment_result.js
+++ b/erpnext/education/doctype/assessment_result/assessment_result.js
@@ -38,6 +38,12 @@
 frappe.ui.form.on("Assessment Result Detail", {
 	score: function(frm, cdt, cdn) {
 		var d  = locals[cdt][cdn];
+
+		if(!d.maximum_score || !frm.doc.grading_scale) {
+			d.score = "";
+			frappe.throw(__("Please fill in all the details to generate Assessment Result."));
+		}
+
 		if (d.score > d.maximum_score) {
 			frappe.throw(__("Score cannot be greater than Maximum Score"));
 		}
diff --git a/erpnext/public/js/utils/item_quick_entry.js b/erpnext/public/js/utils/item_quick_entry.js
index b12e3b8..62b82ac 100644
--- a/erpnext/public/js/utils/item_quick_entry.js
+++ b/erpnext/public/js/utils/item_quick_entry.js
@@ -320,7 +320,7 @@
 						["attribute_value", "like", e.target.value + "%"]
 					],
 					fields: ["attribute_value"],
-					parent: "Item"
+					parent: "Item Attribute"
 				},
 				callback: function(r) {
 					if (r.message) {
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index b3141e8..a26da7f 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -513,7 +513,7 @@
 							fields: ["attribute_value"],
 							limit_start: 0,
 							limit_page_length: 500,
-							parent: "Item",
+							parent: "Item Attribute",
 							order_by: "idx"
 						}
 					}).then((r) => {
@@ -651,7 +651,7 @@
 					frappe.call({
 						method:"erpnext.stock.doctype.item.item.get_item_attribute",
 						args:{
-							parent: i,
+							parent: "Item Attribute",
 							attribute_value: term
 						},
 						callback: function(r) {
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index 3b20b1c..6b5bb28 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -181,7 +181,7 @@
 				frappe.throw(_("Valuation Rate required for Item in row {0}").format(row.idx))
 
 			if ((previous_sle and row.qty == previous_sle.get("qty_after_transaction")
-				and row.valuation_rate == previous_sle.get("valuation_rate"))
+				and (row.valuation_rate == previous_sle.get("valuation_rate") or row.qty == 0))
 				or (not previous_sle and not row.qty)):
 					continue
 
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 0c83529..0ef2afa 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -178,7 +178,7 @@
 		# rounding as per precision
 		self.stock_value = flt(self.stock_value, self.precision)
 
-		if self.prev_stock_value < 0 and self.stock_value >= 0:
+		if self.prev_stock_value < 0 and self.stock_value >= 0 and sle.voucher_type != 'Stock Reconciliation':
 			stock_value_difference = sle.actual_qty * self.valuation_rate
 		else:
 			stock_value_difference = self.stock_value - self.prev_stock_value