Merge branch 'hotfix'
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 03c30a1..ceb8ca2 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -2,7 +2,7 @@
 from __future__ import unicode_literals
 import frappe
 
-__version__ = '7.0.54'
+__version__ = '7.0.55'
 
 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 914c9be..d741a60 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -58,7 +58,7 @@
 		self.check_for_closed_status()
 		self.validate_with_previous_doc()
 		self.validate_uom_is_integer("uom", "qty")
-		self.set_expense_account()
+		self.set_expense_account(for_validate=True)
 		self.set_against_expense_account()
 		self.validate_write_off_account()
 		self.validate_multiple_billing("Purchase Receipt", "pr_detail", "amount", "items")
@@ -155,7 +155,7 @@
 
 		super(PurchaseInvoice, self).validate_warehouse()
 
-	def set_expense_account(self):
+	def set_expense_account(self, for_validate=False):
 		auto_accounting_for_stock = cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
 
 		if auto_accounting_for_stock:
@@ -181,7 +181,7 @@
 				else:
 					item.expense_account = stock_not_billed_account
 
-			elif not item.expense_account:
+			elif not item.expense_account and for_validate:
 				throw(_("Expense account is mandatory for item {0}").format(item.item_code or item.item_name))
 
 	def set_against_expense_account(self):
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index fa88481..668b377 100644
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -15,13 +15,11 @@
 	window.onbeforeunload = function () {
 		return wrapper.pos.beforeunload()
 	}
-	wrapper.pos.on_refresh_page()
 }
 
 
 erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
 	init: function(wrapper){
-		this.load = true;
 		this.page = wrapper.page;
 		this.wrapper = $(wrapper).find('.page-content');
 		this.set_indicator();
@@ -31,17 +29,6 @@
 		this.si_docs = this.get_doc_from_localstorage();
 	},
 
-	on_refresh_page: function() {
-		var me = this;
-		if(this.load){
-			this.load = false;
-		}else if(this.connection_status){
-			this.onload();
-		}else{
-			this.create_new();
-		}
-	},
-
 	beforeunload: function(e){
 		if(this.connection_status == false && frappe.get_route()[0] == "pos"){
 			e = e || window.event;
@@ -359,11 +346,14 @@
 	get_customers: function(key){
 		var me = this;
 		key = key.toLowerCase().trim()
+		var re = new RegExp('%', 'g');
+		var reg = new RegExp(key.replace(re, '\\w*\\s*[a-zA-Z0-9]*'))
+
 		if(key){
 			return $.grep(this.customers, function(data) {
-				if(data.name.toLowerCase().match(key)
-					|| data.customer_name.toLowerCase().match(key)
-					|| (data.customer_group && data.customer_group.toLowerCase().match(key))){
+				if(reg.test(data.name.toLowerCase())
+					|| reg.test(data.customer_name.toLowerCase())
+					|| (data.customer_group && reg.test(data.customer_group.toLowerCase()))){
 					return data
 				}
 			})
@@ -431,7 +421,9 @@
 			})
 		}
 
-		key = this.search.$input.val().toLowerCase();
+		key =  this.search.$input.val().toLowerCase();
+		var re = new RegExp('%', 'g');
+		var reg = new RegExp(key.replace(re, '\\w*\\s*[a-zA-Z0-9]*'))
 		search_status = true
 
 		if(key){
@@ -447,8 +439,8 @@
 					} else if(item.barcode == me.search.$input.val()) {
 						search_status = false;
 						return item.barcode == me.search.$input.val();
-					} else if((item.item_code.toLowerCase().match(key)) ||
-						(item.item_name.toLowerCase().match(key)) || (item.item_group.toLowerCase().match(key))) {
+					} else if(reg.test(item.item_code.toLowerCase()) || reg.test(item.description.toLowerCase()) ||
+					reg.test(item.item_name.toLowerCase()) || reg.test(item.item_group.toLowerCase()) ){
 						return true
 					}
 				}
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 8927da7..e245875 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -144,7 +144,7 @@
 				self.conversion_rate = get_exchange_rate(self.currency,
 					self.company_currency)
 
-	def set_missing_item_details(self):
+	def set_missing_item_details(self, for_validate=False):
 		"""set missing item values"""
 		from erpnext.stock.get_item_details import get_item_details
 
@@ -196,7 +196,7 @@
 								(1.0 - (flt(item.discount_percentage) / 100.0)), item.precision("rate"))
 
 			if self.doctype == "Purchase Invoice":
-				self.set_expense_account()
+				self.set_expense_account(for_validate)
 
 	def set_taxes(self):
 		if not self.meta.get_field("taxes"):
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 88acfb7..8bc081b 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -62,7 +62,7 @@
 		if getattr(self, "supplier", None):
 			self.update_if_missing(get_party_details(self.supplier, party_type="Supplier", ignore_permissions=self.flags.ignore_permissions))
 
-		self.set_missing_item_details()
+		self.set_missing_item_details(for_validate)
 
 	def set_supplier_from_item_default(self):
 		if self.meta.get_field("supplier") and not self.supplier:
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py
index 2bf3204..250d6e6 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/production_order.py
@@ -55,7 +55,8 @@
 				if not self.expected_delivery_date:
 					self.expected_delivery_date = so[0].delivery_date
 
-				self.project = so[0].project
+				if so[0].project:
+					self.project = so[0].project
 
 				self.validate_production_order_against_so()
 			else:
diff --git a/erpnext/patches/v7_0/remove_doctypes_and_reports.py b/erpnext/patches/v7_0/remove_doctypes_and_reports.py
index 3c45be4..03461de 100644
--- a/erpnext/patches/v7_0/remove_doctypes_and_reports.py
+++ b/erpnext/patches/v7_0/remove_doctypes_and_reports.py
@@ -13,7 +13,8 @@
 			'doctype': 'Custom Field',
 			'label': data.label,
 			'dt': 'Timesheet Detail',
-			'fieldname': data.fieldname
+			'fieldname': data.fieldname,
+			'fieldtype': data.fieldtype or "Data"
 		}).insert(ignore_permissions=True)
 
 	frappe.db.sql("""delete from `tabCustom Field` where dt = 'Time Log'""")
@@ -22,4 +23,4 @@
 
 	report = "Daily Time Log Summary"
 	if frappe.db.exists("Report", report):
-		frappe.delete_doc('Report', report)
\ No newline at end of file
+		frappe.delete_doc('Report', report)
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index a30a21b..cb23ff8 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -145,7 +145,7 @@
 
 	def validate_dates(self):
 		for data in self.time_logs:
-			if time_diff_in_hours(data.to_time, data.from_time) < 0:
+			if data.from_time and data.to_time and time_diff_in_hours(data.to_time, data.from_time) < 0:
 				frappe.throw(_("To date cannot be before from date"))
 
 	def validate_time_logs(self):
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 2149f6d..4e1288c 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -25,11 +25,11 @@
 			item.total_margin = item.price_list_rate + item.margin_rate_or_amount;
 		}
 
-		item.rate = flt(item.total_margin , 2);
+		item.rate = flt(item.total_margin , precision("rate", item));
 
 		if(item.discount_percentage){
 			discount_value = flt(item.total_margin) * flt(item.discount_percentage) / 100;
-			item.rate = flt((item.total_margin) - (discount_value), precision('rate'));
+			item.rate = flt((item.total_margin) - (discount_value), precision('rate', item));
 		}
 	},
 
diff --git a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.json b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.json
index 0612dc0..af28e20 100644
--- a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.json
+++ b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.json
@@ -1,5 +1,5 @@
 {
- "add_total_row": 0, 
+ "add_total_row": 1, 
  "apply_user_permissions": 1, 
  "creation": "2013-05-03 11:31:05", 
  "disabled": 0, 
@@ -7,7 +7,7 @@
  "doctype": "Report", 
  "idx": 1, 
  "is_standard": "Yes", 
- "modified": "2016-01-28 04:22:49.476068", 
+ "modified": "2016-10-05 12:26:15.736596", 
  "modified_by": "Administrator", 
  "module": "Selling", 
  "name": "Sales Person-wise Transaction Summary", 
diff --git a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py
index e9930f3..0c6914d 100644
--- a/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py
+++ b/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py
@@ -39,7 +39,7 @@
 		_("Customer") + ":Link/Customer:140", _("Territory") + ":Link/Territory:100", _("Posting Date") + ":Date:100",
 		_("Item Code") + ":Link/Item:120", _("Item Group") + ":Link/Item Group:120",
 		_("Brand") + ":Link/Brand:120", _("Qty") + ":Float:100", _("Amount") + ":Currency:120",
-		_("Sales Person") + ":Link/Sales Person:140", _("Contribution %") + ":Float:110",
+		_("Sales Person") + ":Link/Sales Person:140", _("Contribution %") + "::110",
 		_("Contribution Amount") + ":Currency:140"]
 
 def get_entries(filters):
diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.py b/erpnext/support/doctype/warranty_claim/warranty_claim.py
index b4427be..a3428a2 100644
--- a/erpnext/support/doctype/warranty_claim/warranty_claim.py
+++ b/erpnext/support/doctype/warranty_claim/warranty_claim.py
@@ -19,7 +19,7 @@
 		if session['user'] != 'Guest' and not self.customer:
 			frappe.throw(_("Customer is required"))
 
-		if self.status=="Closed" and \
+		if self.status=="Closed" and not self.resolution_date and \
 			frappe.db.get_value("Warranty Claim", self.name, "status")!="Closed":
 			self.resolution_date = now_datetime()