Merge branch 'develop'
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index d102c9e..9e586b5 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -2,7 +2,7 @@
 from __future__ import unicode_literals
 import frappe
 
-__version__ = '8.0.22'
+__version__ = '8.0.23'
 
 def get_default_company(user=None):
 	'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 4d58f98..530d08a 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -204,7 +204,7 @@
 		if frappe.db.get_value("Buying Settings", None, "po_required") == 'Yes':
 			for d in self.get('items'):
 				if not d.purchase_order:
-					throw(_("Purchse Order number required for Item {0}").format(d.item_code))
+					throw(_("Purchase Order number required for Item {0}").format(d.item_code))
 
 	def pr_required(self):
 		stock_items = self.get_stock_items()
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index b1fe0be..295f649 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -341,13 +341,23 @@
 		super(SalesInvoice, self).validate_with_previous_doc({
 			"Sales Order": {
 				"ref_dn_field": "sales_order",
-				"compare_fields": [["customer", "="], ["company", "="], ["project", "="],
-					["currency", "="]],
+				"compare_fields": [["customer", "="], ["company", "="], ["project", "="], ["currency", "="]]
+			},
+			"Sales Order Item": {
+				"ref_dn_field": "so_detail",
+				"compare_fields": [["item_code", "="], ["uom", "="], ["conversion_factor", "="]],
+				"is_child_table": True,
+				"allow_duplicate_prev_row_id": True
 			},
 			"Delivery Note": {
 				"ref_dn_field": "delivery_note",
-				"compare_fields": [["customer", "="], ["company", "="], ["project", "="],
-					["currency", "="]],
+				"compare_fields": [["customer", "="], ["company", "="], ["project", "="], ["currency", "="]]
+			},
+			"Delivery Note Item": {
+				"ref_dn_field": "dn_detail",
+				"compare_fields": [["item_code", "="], ["uom", "="], ["conversion_factor", "="]],
+				"is_child_table": True,
+				"allow_duplicate_prev_row_id": True
 			},
 		})
 
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index 4c5535d..c9345f2 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -123,10 +123,10 @@
 
 	debit_credit_diff = flt(debit_credit_diff, precision)
 	
-	if gl_map[0]["voucher_type"] == "Journal Entry":
+	if gl_map[0]["voucher_type"] in ("Journal Entry", "Payment Entry"):
 		allowance = 5.0 / (10**precision)
 	else:
-		allowance = 1
+		allowance = .5
 	
 	if abs(debit_credit_diff) >= allowance:
 		frappe.throw(_("Debit and Credit not equal for {0} #{1}. Difference is {2}.")
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py
index 47f79f1..1a63a9d 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.py
+++ b/erpnext/accounts/report/purchase_register/purchase_register.py
@@ -20,7 +20,7 @@
 	invoice_expense_map, invoice_tax_map = get_invoice_tax_map(invoice_list,
 		invoice_expense_map, expense_accounts)
 	invoice_po_pr_map = get_invoice_po_pr_map(invoice_list)
-	supplier_details = get_supplier_deatils(invoice_list)
+	supplier_details = get_supplier_details(invoice_list)
 	
 	company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
 
@@ -205,7 +205,7 @@
 
 	return account_map
 
-def get_supplier_deatils(invoice_list):
+def get_supplier_details(invoice_list):
 	supplier_details = {}
 	suppliers = list(set([inv.supplier for inv in invoice_list]))
 	for supp in frappe.db.sql("""select name, supplier_type from `tabSupplier`
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 88e7d20..e7b0d1a 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -59,7 +59,8 @@
 			},
 			"Supplier Quotation Item": {
 				"ref_dn_field": "supplier_quotation_item",
-				"compare_fields": [["rate", "="], ["project", "="], ["item_code", "="]],
+				"compare_fields": [["rate", "="], ["project", "="], ["item_code", "="], 
+					["uom", "="], ["conversion_factor", "="]],
 				"is_child_table": True
 			}
 		})
diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json
index 9adb42b..a590f37 100644
--- a/erpnext/buying/doctype/supplier/supplier.json
+++ b/erpnext/buying/doctype/supplier/supplier.json
@@ -15,6 +15,7 @@
  "engine": "InnoDB", 
  "fields": [
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -45,6 +46,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -76,6 +78,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 1, 
    "collapsible": 0, 
@@ -106,6 +109,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -136,6 +140,37 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "tax_id", 
+   "fieldtype": "Data", 
+   "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": "Tax ID", 
+   "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, 
@@ -165,6 +200,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -193,6 +229,7 @@
    "width": "50%"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -224,6 +261,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -254,6 +292,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 1, 
    "collapsible": 0, 
@@ -284,6 +323,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 1, 
@@ -313,6 +353,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -342,6 +383,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -370,6 +412,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -399,6 +442,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 1, 
@@ -428,6 +472,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -458,6 +503,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -487,6 +533,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -518,6 +565,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -546,6 +594,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -574,6 +623,7 @@
    "width": "50%"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -602,6 +652,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 1, 
@@ -631,6 +682,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -662,6 +714,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 1, 
@@ -692,6 +745,7 @@
    "width": "50%"
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -722,6 +776,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -753,6 +808,7 @@
    "unique": 0
   }, 
   {
+   "allow_bulk_edit": 0, 
    "allow_on_submit": 0, 
    "bold": 0, 
    "collapsible": 0, 
@@ -794,7 +850,7 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2017-03-14 17:04:17.785461", 
+ "modified": "2017-05-05 04:24:03.884380", 
  "modified_by": "Administrator", 
  "module": "Buying", 
  "name": "Supplier", 
diff --git a/erpnext/buying/page/purchase_analytics/purchase_analytics.js b/erpnext/buying/page/purchase_analytics/purchase_analytics.js
index 3e6f23b..10d1321 100644
--- a/erpnext/buying/page/purchase_analytics/purchase_analytics.js
+++ b/erpnext/buying/page/purchase_analytics/purchase_analytics.js
@@ -35,11 +35,7 @@
 				item_key: "supplier",
 				parent_field: "parent_supplier_type",
 				formatter: function(item) {
-					// return repl('<a href="#Report/stock-invoices/customer=%(enc_value)s">%(value)s</a>', {
-					// 		value: item.name,
-					// 		enc_value: encodeURIComponent(item.name)
-					// 	});
-					return item.name;
+					return item.supplier_name ? item.supplier_name + " (" + item.name + ")" : item.name;
 				}
 			},
 			"Supplier": {
@@ -47,7 +43,7 @@
 				show: false,
 				item_key: "supplier",
 				formatter: function(item) {
-					return item.name;
+					return item.supplier_name ? item.supplier_name + " (" + item.name + ")" : item.name;
 				}
 			},
 			"Item Group": {
diff --git a/erpnext/buying/utils.py b/erpnext/buying/utils.py
index 9146c58..9ad1c5c 100644
--- a/erpnext/buying/utils.py
+++ b/erpnext/buying/utils.py
@@ -64,7 +64,7 @@
 		validate_end_of_life(d.item_code, item.end_of_life, item.disabled)
 
 		# validate stock item
-		if item.is_stock_item==1 and d.qty and not d.warehouse and not d.delivered_by_supplier:
+		if item.is_stock_item==1 and d.qty and not d.warehouse and not d.get("delivered_by_supplier"):
 			frappe.throw(_("Warehouse is mandatory for stock Item {0} in row {1}").format(d.item_code, d.idx))
 
 		items.append(cstr(d.item_code))
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 88600e8..81c9def 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -360,7 +360,8 @@
 	sub_query = """ select round(`tabBin`.actual_qty, 2) from `tabBin`
 		where `tabBin`.warehouse = `tabWarehouse`.name
 		{bin_conditions} """.format(
-		bin_conditions=get_filters_cond(doctype, filter_dict.get("Bin"), bin_conditions))
+		bin_conditions=get_filters_cond(doctype, filter_dict.get("Bin"), bin_conditions),
+			ignore_permissions=True)
 
 	response = frappe.db.sql("""select `tabWarehouse`.name,
 		CONCAT_WS(" : ", "Actual Qty", ifnull( ({sub_query}), 0) ) as actual_qty
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 1cd705b..10b3607 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -170,7 +170,7 @@
 
 	def validate_selling_price(self):
 		def throw_message(item_name, rate, ref_rate_field):
-			frappe.throw(_("""Selling price for item {0} is lower than its {1}. Selling price should be atleast {2}""")
+			frappe.throw(_("""Selling rate for item {0} is lower than its {1}. Selling rate should be atleast {2}""")
 				.format(item_name, ref_rate_field, rate))
 
 		if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"):
@@ -178,18 +178,19 @@
 
 		for it in self.get("items"):
 			last_purchase_rate, is_stock_item = frappe.db.get_value("Item", it.item_code, ["last_purchase_rate", "is_stock_item"])
-
-			if flt(it.base_rate) < flt(last_purchase_rate):
-				throw_message(it.item_name, last_purchase_rate, "last purchase rate")
+			last_purchase_rate_in_sales_uom = last_purchase_rate / (it.conversion_factor or 1)
+			if flt(it.base_rate) < flt(last_purchase_rate_in_sales_uom):
+				throw_message(it.item_name, last_purchase_rate_in_sales_uom, "last purchase rate")
 
 			last_valuation_rate = frappe.db.sql("""
 				SELECT valuation_rate FROM `tabStock Ledger Entry` WHERE item_code = %s
 				AND warehouse = %s AND valuation_rate > 0
 				ORDER BY posting_date DESC, posting_time DESC, name DESC LIMIT 1
 				""", (it.item_code, it.warehouse))
-
-			if is_stock_item and flt(it.base_rate) < flt(last_valuation_rate):
-				throw_message(it.name, last_valuation_rate, "valuation rate")
+			if last_valuation_rate:
+				last_valuation_rate_in_sales_uom = last_valuation_rate[0][0] / (it.conversion_factor or 1)
+				if is_stock_item and flt(it.base_rate) < flt(last_valuation_rate_in_sales_uom):
+					throw_message(it.name, last_valuation_rate_in_sales_uom, "valuation rate")
 
 
 	def get_item_list(self):
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 5182c98..e422958 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -321,9 +321,13 @@
 	def sum_components(self, component_type, total_field):
 		joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
 			["date_of_joining", "relieving_date"])
+		
 		if not relieving_date:
 			relieving_date = getdate(self.end_date)
 
+		if not joining_date:
+			frappe.throw(_("Please set the Date Of Joining for employee {0}").format(frappe.bold(employee.employee)))
+
 		for d in self.get(component_type):
 			if ((cint(d.depends_on_lwp) == 1 and not self.salary_slip_based_on_timesheet) or\
 			getdate(self.start_date) < joining_date or getdate(self.end_date) > relieving_date):
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py
index da69bcc..dc1c04d 100644
--- a/erpnext/hr/doctype/salary_structure/salary_structure.py
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.py
@@ -33,6 +33,7 @@
 		for employee in self.get('employees'):
 			joining_date, relieving_date = frappe.db.get_value("Employee", employee.employee,
 				["date_of_joining", "relieving_date"])
+
 			if employee.from_date and joining_date and getdate(employee.from_date) < joining_date:
 				frappe.throw(_("From Date {0} for Employee {1} cannot be before employee's joining Date {2}")
 					    .format(employee.from_date, employee.employee, joining_date))
diff --git a/erpnext/portal/utils.py b/erpnext/portal/utils.py
index 7dffd03..8115c1f 100644
--- a/erpnext/portal/utils.py
+++ b/erpnext/portal/utils.py
@@ -4,14 +4,17 @@
 	'''Set customer, supplier, student based on email'''
 	if frappe.flags.setting_role or frappe.flags.in_migrate:
 		return
+
+	roles = frappe.get_roles(doc.name)
+
 	contact_name = frappe.get_value('Contact', dict(email_id=doc.email))
 	if contact_name:
 		contact = frappe.get_doc('Contact', contact_name)
 		for link in contact.links:
 			frappe.flags.setting_role = True
-			if link.link_doctype=='Customer':
+			if link.link_doctype=='Customer' and 'Customer' not in roles:
 				doc.add_roles('Customer')
-			elif link.link_doctype=='Supplier':
+			elif link.link_doctype=='Supplier' and 'Supplier' not in roles:
 				doc.add_roles('Supplier')
-	elif frappe.get_value('Student', dict(student_email_id=doc.email)):
+	elif frappe.get_value('Student', dict(student_email_id=doc.email)) and 'Student' not in roles:
 		doc.add_roles('Student')
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index cbedf80..6539530 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -500,6 +500,7 @@
 	},
 
 	get_exchange_rate: function(transaction_date, from_currency, to_currency, callback) {
+		if (!transaction_date || !from_currency || !to_currency) return;
 		return frappe.call({
 			method: "erpnext.setup.utils.get_exchange_rate",
 			args: {
@@ -563,14 +564,14 @@
 		}
 	},
 
-	conversion_factor: function(doc, cdt, cdn) {
+	conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) {
 		if(frappe.meta.get_docfield(cdt, "stock_qty", cdn)) {
 			var item = frappe.get_doc(cdt, cdn);
 			frappe.model.round_floats_in(item, ["qty", "conversion_factor"]);
 			item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item));
 			refresh_field("stock_qty", item.name, item.parentfield);
 			this.toggle_conversion_factor(item);
-			this.apply_price_list(item, true);
+			if(!dont_fetch_price_list_rate) this.apply_price_list(item, true);
 		}
 	},
 
@@ -581,7 +582,8 @@
 	},
 
 	qty: function(doc, cdt, cdn) {
-		this.conversion_factor(doc, cdt, cdn);
+		this.conversion_factor(doc, cdt, cdn, true);
+		this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true);
 	},
 
 	set_dynamic_labels: function() {
@@ -762,7 +764,6 @@
 			if(calculate_taxes_and_totals) me.calculate_taxes_and_totals();
 			return;
 		}
-
 		return this.frm.call({
 			method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.apply_pricing_rule",
 			args: {	args: args },
@@ -1117,4 +1118,4 @@
 
 		return method
 	},
-});
\ No newline at end of file
+});
diff --git a/erpnext/schools/doctype/student_group/student_group.js b/erpnext/schools/doctype/student_group/student_group.js
index c2c6912..ed94690 100644
--- a/erpnext/schools/doctype/student_group/student_group.js
+++ b/erpnext/schools/doctype/student_group/student_group.js
@@ -42,7 +42,7 @@
 	},
 
 	get_students: function(frm) {
-		if (frm.doc.group_based_on != "Activity") {
+		if (frm.doc.group_based_on == "Batch" || frm.doc.group_based_on == "Course") {
 			var student_list = [];
 			var max_roll_no = 0;
 			$.each(frm.doc.students, function(i,d) {
diff --git a/erpnext/selling/page/sales_analytics/sales_analytics.js b/erpnext/selling/page/sales_analytics/sales_analytics.js
index 73793d4..bb47f98 100644
--- a/erpnext/selling/page/sales_analytics/sales_analytics.js
+++ b/erpnext/selling/page/sales_analytics/sales_analytics.js
@@ -34,14 +34,16 @@
 				show: true,
 				item_key: "customer",
 				parent_field: "parent_customer_group",
-				formatter: function(item) { return item.customer_name || item.name; }
+				formatter: function(item) {
+					return item.customer_name? item.customer_name + " (" + item.name + ")" : item.name; 
+				}
 			},
 			"Customer": {
 				label: __("Customer"),
 				show: false,
 				item_key: "customer",
 				formatter: function(item) {
-					return item.customer_name || item.name;
+					return item.customer_name? item.customer_name + " (" + item.name + ")" : item.name;
 				}
 			},
 			"Item Group": {
@@ -67,7 +69,7 @@
 				item_key: "customer",
 				parent_field: "parent_territory",
 				formatter: function(item) {
-					return item.name;
+					return item.customer_name? item.customer_name + " (" + item.name + ")" : item.name;
 				}
 			}
 		}
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index c09255d..cc5e65d 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -282,7 +282,7 @@
 			if len(parts) == 1 or parts[1].lower() == old.lower():
 				frappe.rename_doc(dt, d[0], parts[0] + " - " + new)
 
-	for dt in ["Account", "Cost Center", "Warehouse"]:
+	for dt in ["Warehouse", "Account", "Cost Center"]:
 		_rename_record(dt)
 		frappe.db.commit()
 
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index a2a0115..1c730ff 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -117,18 +117,31 @@
 		if not self.installation_status: self.installation_status = 'Not Installed'
 
 	def validate_with_previous_doc(self):
-		for fn in (("Sales Order", "against_sales_order", "so_detail"),
-				("Sales Invoice", "against_sales_invoice", "si_detail")):
-			if filter(None, [getattr(d, fn[1], None) for d in self.get("items")]):
-				super(DeliveryNote, self).validate_with_previous_doc({
-					fn[0]: {
-						"ref_dn_field": fn[1],
-						"compare_fields": [["customer", "="], ["company", "="], ["project", "="],
-							["currency", "="]],
-					},
-				})
+		super(DeliveryNote, self).validate_with_previous_doc({
+			"Sales Order": {
+				"ref_dn_field": "against_sales_order",
+				"compare_fields": [["customer", "="], ["company", "="], ["project", "="], ["currency", "="]]
+			},
+			"Sales Order Item": {
+				"ref_dn_field": "so_detail",
+				"compare_fields": [["item_code", "="], ["uom", "="], ["conversion_factor", "="]],
+				"is_child_table": True,
+				"allow_duplicate_prev_row_id": True
+			},
+			"Sales Invoice": {
+				"ref_dn_field": "against_sales_invoice",
+				"compare_fields": [["customer", "="], ["company", "="], ["project", "="], ["currency", "="]]
+			},
+			"Sales Invoice Item": {
+				"ref_dn_field": "si_detail",
+				"compare_fields": [["item_code", "="], ["uom", "="], ["conversion_factor", "="]],
+				"is_child_table": True,
+				"allow_duplicate_prev_row_id": True
+			},
+		})
 
-		if cint(frappe.db.get_single_value('Selling Settings', 'maintain_same_sales_rate')) and not self.is_return:
+		if cint(frappe.db.get_single_value('Selling Settings', 'maintain_same_sales_rate')) \
+				and not self.is_return:
 			self.validate_rate_with_reference_doc([["Sales Order", "against_sales_order", "so_detail"],
 				["Sales Invoice", "against_sales_invoice", "si_detail"]])
 
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 4d0c3ac..6a9fd24 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -142,7 +142,7 @@
 
 	def make_route(self):
 		if not self.route:
-			return cstr(frappe.db.get_value('Item Group', self.item_group, 'route')) + '/' + self.scrub(self.item_name)
+			return cstr(frappe.db.get_value('Item Group', self.item_group, 'route')) + '/' + self.scrub(self.name)
 
 	def get_parents(self, context):
 		item_group, route = frappe.db.get_value('Item Group', self.item_group, ['name', 'route'])
diff --git a/erpnext/translations/ro.csv b/erpnext/translations/ro.csv
index cf444a3..3f8797b 100644
--- a/erpnext/translations/ro.csv
+++ b/erpnext/translations/ro.csv
@@ -36,7 +36,7 @@
 DocType: Delivery Note,Return Against Delivery Note,Reveni Împotriva livrare Nota
 DocType: Purchase Order,% Billed,% Facurat
 apps/erpnext/erpnext/controllers/sales_and_purchase_return.py +43,Exchange Rate must be same as {0} {1} ({2}),Rata de schimb trebuie să fie aceeași ca și {0} {1} ({2})
-DocType: Sales Invoice,Customer Name,Nume client
+DocType: Sales Invoice,Customer Name,Cumpărător
 DocType: Vehicle,Natural Gas,Gaz natural
 apps/erpnext/erpnext/setup/setup_wizard/setup_wizard.py +130,Bank account cannot be named as {0},Contul bancar nu poate fi numit ca {0}
 DocType: Account,Heads (or groups) against which Accounting Entries are made and balances are maintained.,Heads (sau grupuri) față de care înregistrările contabile sunt făcute și soldurile sunt menținute.
@@ -785,7 +785,7 @@
 
 #### Description of Columns
 
-1. Calculation Type: 
+1. Calculation Type:
     - This can be on **Net Total** (that is the sum of basic amount).
     - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.
     - **Actual** (as mentioned).
@@ -796,19 +796,19 @@
 6. Amount: Tax amount.
 7. Total: Cumulative total to this point.
 8. Enter Row: If based on ""Previous Row Total"" you can select the row number which will be taken as a base for this calculation (default is the previous row).
-9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.","Șablon de impozitare standard, care pot fi aplicate la toate tranzacțiile de vânzare. Acest model poate conține lista de capete fiscale și, de asemenea, mai multe capete de cheltuieli / venituri, cum ar fi ""de transport"", ""asigurare"", ""manipulare"" etc. 
+9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.","Șablon de impozitare standard, care pot fi aplicate la toate tranzacțiile de vânzare. Acest model poate conține lista de capete fiscale și, de asemenea, mai multe capete de cheltuieli / venituri, cum ar fi ""de transport"", ""asigurare"", ""manipulare"" etc.
 
- #### Notă 
+ #### Notă
 
  vă Rata de impozitare defini aici va fi cota de impozitare standard pentru toate Articole ** **. Dacă există articole ** **, care au preturi diferite, acestea trebuie să fie adăugate în ** Impozitul Postul ** masă în ** ** postul comandantului.
 
- #### Descrierea de coloane 
+ #### Descrierea de coloane
 
- 1. Calcul Tip: 
+ 1. Calcul Tip:
  - Acest lucru poate fi pe ** net total ** (care este suma cuantum de bază).
  - ** La rândul precedent Raport / Suma ** (pentru impozite sau taxe cumulative). Dacă selectați această opțiune, impozitul va fi aplicat ca procent din rândul anterior (în tabelul de impozitare) suma totală sau.
  - ** ** Real (după cum sa menționat).
- 2. Șeful cont: Registrul cont în care acest impozit va fi rezervat 
+ 2. Șeful cont: Registrul cont în care acest impozit va fi rezervat
  3. Cost Center: În cazul în care taxa / taxa este un venit (cum ar fi de transport maritim) sau cheltuieli trebuie să se rezervat împotriva unui centru de cost.
  4. Descriere: Descriere a taxei (care vor fi tipărite în facturi / citate).
  5. Notă: Rata de Profit Brut.
@@ -893,7 +893,7 @@
 DocType: Shopping Cart Settings,Enable Checkout,activaţi Checkout
 apps/erpnext/erpnext/config/learn.py +202,Purchase Order to Payment,Comandă de aprovizionare de plata
 apps/erpnext/erpnext/stock/page/stock_balance/stock_balance.js +48,Projected Qty,Proiectat Cantitate
-DocType: Sales Invoice,Payment Due Date,Data scadentă de plată
+DocType: Sales Invoice,Payment Due Date,Scadentă
 apps/erpnext/erpnext/stock/doctype/item/item.js +340,Item Variant {0} already exists with same attributes,Postul Varianta {0} există deja cu aceleași atribute
 apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py +95,'Opening',&quot;Deschiderea&quot;
 apps/erpnext/erpnext/setup/doctype/email_digest/templates/default.html +130,Open To Do,Deschideți To Do
@@ -1021,7 +1021,7 @@
 apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +120,Row {0}: Payment against Sales/Purchase Order should always be marked as advance,Rând {0}: Plata împotriva Vânzări / Ordinului de Procurare ar trebui să fie întotdeauna marcate ca avans
 apps/erpnext/erpnext/setup/setup_wizard/industry_type.py +16,Chemical,Chimic
 DocType: Salary Component Account,Default Bank / Cash account will be automatically updated in Salary Journal Entry when this mode is selected.,Default cont bancar / numerar vor fi actualizate automat în Jurnalul de intrare a salariului când este selectat acest mod.
-apps/erpnext/erpnext/schools/doctype/grading_structure/grading_structure.py +24,"The intervals for Grade Code {0} overlaps with the grade intervals for other grades. 
+apps/erpnext/erpnext/schools/doctype/grading_structure/grading_structure.py +24,"The intervals for Grade Code {0} overlaps with the grade intervals for other grades.
                     Please check intervals {0} and {1} and try again",Intervalele de cod Grad {0} se suprapune cu intervalele de grad pentru alte clase. Vă rugăm să verificați intervalele de {0} și {1} și încercați din nou
 DocType: BOM,Raw Material Cost(Company Currency),Brut Costul materialelor (companie Moneda)
 apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.py +715,All items have already been transferred for this Production Order.,Toate articolele acestei comenzi de producție au fost deja transferate.
@@ -2345,7 +2345,7 @@
 
 #### Description of Columns
 
-1. Calculation Type: 
+1. Calculation Type:
     - This can be on **Net Total** (that is the sum of basic amount).
     - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.
     - **Actual** (as mentioned).
@@ -2357,19 +2357,19 @@
 7. Total: Cumulative total to this point.
 8. Enter Row: If based on ""Previous Row Total"" you can select the row number which will be taken as a base for this calculation (default is the previous row).
 9. Consider Tax or Charge for: In this section you can specify if the tax / charge is only for valuation (not a part of total) or only for total (does not add value to the item) or for both.
-10. Add or Deduct: Whether you want to add or deduct the tax.","Șablon de impozitare standard care pot fi aplicate la toate tranzacțiile de cumpărare. Acest model poate conține lista de capete fiscale și, de asemenea, mai multe capete de cheltuieli, cum ar fi ""de transport"", ""asigurare"", ""manipulare"" etc. 
+10. Add or Deduct: Whether you want to add or deduct the tax.","Șablon de impozitare standard care pot fi aplicate la toate tranzacțiile de cumpărare. Acest model poate conține lista de capete fiscale și, de asemenea, mai multe capete de cheltuieli, cum ar fi ""de transport"", ""asigurare"", ""manipulare"" etc.
 
- #### Notă 
+ #### Notă
 
  Rata de impozitare pe care o definiți aici va fi rata de impozitare standard pentru toate Articole ** **. Dacă există articole ** **, care au preturi diferite, acestea trebuie să fie adăugate în ** Impozitul Postul ** masă în ** ** postul comandantului.
 
- #### Descrierea de coloane 
+ #### Descrierea de coloane
 
- 1. Calcul Tip: 
+ 1. Calcul Tip:
  - Acest lucru poate fi pe ** net total ** (care este suma cuantum de bază).
  - ** La rândul precedent Raport / Suma ** (pentru impozite sau taxe cumulative). Dacă selectați această opțiune, impozitul va fi aplicat ca procent din rândul anterior (în tabelul de impozitare) suma totală sau.
  - ** ** Real (după cum sa menționat).
- 2. Șeful cont: Registrul cont în care acest impozit va fi rezervat 
+ 2. Șeful cont: Registrul cont în care acest impozit va fi rezervat
  3. Cost Center: În cazul în care taxa / taxa este un venit (cum ar fi de transport maritim) sau cheltuieli trebuie să se rezervat împotriva unui centru de cost.
  4. Descriere: Descriere a taxei (care vor fi tipărite în facturi / citate).
  5. Notă: Rata de Profit Brut.
@@ -2579,7 +2579,7 @@
 1. Ways of addressing disputes, indemnity, liability, etc.
 1. Address and Contact of your Company.","Termeni și Condiții care pot fi adăugate la vânzările și achizițiile standard.
 
- Exemple: 
+ Exemple:
 
  1. Perioada de valabilitate a ofertei.
  1. Conditii de plata (in avans, pe credit, parte în avans etc.).
@@ -2588,7 +2588,7 @@
  1. Garantie dacă este cazul.
  1. Politica de Returnare.
  1. Condiții de transport maritim, dacă este cazul.
- 1. Modalitati de litigii de adresare, indemnizație, răspunderea, etc. 
+ 1. Modalitati de litigii de adresare, indemnizație, răspunderea, etc.
  1. Adresa și de contact ale companiei."
 DocType: Attendance,Leave Type,Tip Concediu
 DocType: Purchase Invoice,Supplier Invoice Details,Furnizor Detalii factură
@@ -3641,7 +3641,7 @@
 apps/erpnext/erpnext/setup/setup_wizard/industry_type.py +15,Brokerage,Brokeraj
 apps/erpnext/erpnext/hr/doctype/leave_application/leave_application.py +232,Attendance for employee {0} is already marked for this day,Prezență pentru angajat {0} este deja marcat pentru această zi
 DocType: Production Order Operation,"in Minutes
-Updated via 'Time Log'","în procesul-verbal 
+Updated via 'Time Log'","în procesul-verbal
  Actualizat prin ""Ora Log"""
 DocType: Customer,From Lead,Din Conducere
 apps/erpnext/erpnext/config/manufacturing.py +13,Orders released for production.,Comenzi lansat pentru producție.
@@ -3743,7 +3743,7 @@
 DocType: Stock Ledger Entry,Stock Ledger Entry,Stoc Ledger intrare
 apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py +87,Same item has been entered multiple times,Același articol a fost introdus de mai multe ori
 DocType: Department,Leave Block List,Lista Concedii Blocate
-DocType: Sales Invoice,Tax ID,ID impozit
+DocType: Sales Invoice,Tax ID,Cod inregistrare fiscala
 apps/erpnext/erpnext/stock/doctype/serial_no/serial_no.py +188,Item {0} is not setup for Serial Nos. Column must be blank,Articolul {0} nu este configurat pentru Numerotare Seriala. Coloana trebuie să fie vida
 DocType: Accounts Settings,Accounts Settings,Setări Conturi
 apps/erpnext/erpnext/schools/doctype/student_applicant/student_applicant.js +7,Approve,Aproba
@@ -3843,7 +3843,7 @@
 apps/erpnext/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py +34,Bank Statement balance as per General Ledger,Banca echilibru Declarație pe General Ledger
 DocType: Job Applicant,Applicant Name,Nume solicitant
 DocType: Authorization Rule,Customer / Item Name,Client / Denumire articol
-DocType: Product Bundle,"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. 
+DocType: Product Bundle,"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**.
 
 The package **Item** will have ""Is Stock Item"" as ""No"" and ""Is Sales Item"" as ""Yes"".
 
@@ -4195,7 +4195,7 @@
 apps/erpnext/erpnext/accounts/doctype/fiscal_year/fiscal_year.py +82,Year start date or end date is overlapping with {0}. To avoid please set company,Anul Data de începere sau de încheiere este suprapunerea cu {0}. Pentru a evita vă rugăm să setați companie
 apps/erpnext/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py +157,Start date should be less than end date for Item {0},Data de începere trebuie să fie mai mică decât data de sfârșit pentru postul {0}
 DocType: Item,"Example: ABCD.#####
-If series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.","Exemplu:. ABCD ##### 
+If series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.","Exemplu:. ABCD #####
  Dacă seria este setat și nu de serie nu este menționat în tranzacții, numărul de atunci automat de serie va fi creat pe baza acestei serii. Dacă întotdeauna doriți să se menționeze explicit Serial nr de acest articol. părăsi acest gol."
 DocType: Upload Attendance,Upload Attendance,Încărcați Spectatori
 apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.js +302,BOM and Manufacturing Quantity are required,BOM și cantitatea de producție sunt necesare