Merge branch 'develop'
diff --git a/erpnext/__version__.py b/erpnext/__version__.py
index af58b16..c067798 100644
--- a/erpnext/__version__.py
+++ b/erpnext/__version__.py
@@ -1,2 +1,2 @@
 from __future__ import unicode_literals
-__version__ = '5.0.21'
+__version__ = '5.0.22'
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index 9ef011b..231c8ab 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -5,6 +5,13 @@
  "doctype": "DocType", 
  "fields": [
   {
+   "fieldname": "check_supplier_invoice_uniqueness", 
+   "fieldtype": "Check", 
+   "label": "Check Supplier Invoice Number Uniqueness", 
+   "permlevel": 0, 
+   "precision": ""
+  }, 
+  {
    "default": "1", 
    "description": "If enabled, the system will post accounting entries for inventory automatically.", 
    "fieldname": "auto_accounting_for_stock", 
@@ -43,7 +50,7 @@
  "icon": "icon-cog", 
  "idx": 1, 
  "issingle": 1, 
- "modified": "2015-02-05 05:11:34.163902", 
+ "modified": "2015-06-11 06:06:34.047890", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Accounts Settings", 
diff --git a/erpnext/accounts/doctype/c_form/c_form.py b/erpnext/accounts/doctype/c_form/c_form.py
index 9064754..c14990a 100644
--- a/erpnext/accounts/doctype/c_form/c_form.py
+++ b/erpnext/accounts/doctype/c_form/c_form.py
@@ -54,7 +54,7 @@
 			frappe.throw(_("Please enter atleast 1 invoice in the table"))
 
 	def set_total_invoiced_amount(self):
-		total = sum([flt(d.base_grand_total) for d in self.get('invoices')])
+		total = sum([flt(d.grand_total) for d in self.get('invoices')])
 		frappe.db.set(self, 'total_invoiced_amount', total)
 
 	def get_invoice_details(self, invoice_no):
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index c0ebf68..2516ded 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -39,6 +39,7 @@
 
 		self.po_required()
 		self.pr_required()
+		self.validate_supplier_invoice()
 		self.check_active_purchase_items()
 		self.check_conversion_rate()
 		self.validate_credit_to_acc()
@@ -385,6 +386,16 @@
 				project.update_purchase_costing()
 				project.save()
 				project_list.append(d.project_name)
+				
+	def validate_supplier_invoice(self):
+		if self.bill_date:
+			if self.bill_date > self.posting_date:
+				frappe.throw("Supplier Invoice Date cannot be greater than Posting Date")
+		if self.bill_no:
+			if cint(frappe.db.get_single_value("Accounts Settings", "check_supplier_invoice_uniqueness")):
+				pi = frappe.db.exists("Purchase Invoice", {"bill_no": self.bill_no, "fiscal_year": self.fiscal_year})
+				if pi:
+					frappe.throw("Supplier Invoice No exists in Purchase Invoice {0}".format(pi))
 
 @frappe.whitelist()
 def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 1684645..1f0b547 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -5,7 +5,7 @@
 app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
 app_icon = "icon-th"
 app_color = "#e74c3c"
-app_version = "5.0.21"
+app_version = "5.0.22"
 
 error_report_email = "support@erpnext.com"
 
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py
index 529c2a4..6de0d7b 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/production_order.py
@@ -309,10 +309,9 @@
 			self.actual_end_date = None
 
 	def validate_delivery_date(self):
-		if self.docstatus==1:
-			if self.planned_end_date and self.expected_delivery_date \
-				and getdate(self.expected_delivery_date) < getdate(self.planned_end_date):
-					frappe.msgprint(_("Production might not be able to finish by the Expected Delivery Date."))
+		if self.planned_start_date and self.expected_delivery_date \
+			and getdate(self.expected_delivery_date) < getdate(self.planned_start_date):
+				frappe.throw(_("Expected Delivery Date must be greater than Planned Start Date."))
 
 	def delete_time_logs(self):
 		for time_log in frappe.get_all("Time Log", ["name"], {"production_order": self.name}):
diff --git a/erpnext/projects/doctype/activity_cost/activity_cost.js b/erpnext/projects/doctype/activity_cost/activity_cost.js
new file mode 100644
index 0000000..ba10153
--- /dev/null
+++ b/erpnext/projects/doctype/activity_cost/activity_cost.js
@@ -0,0 +1 @@
+cur_frm.add_fetch('employee', 'employee_name', 'employee_name');
\ No newline at end of file
diff --git a/erpnext/projects/doctype/activity_cost/activity_cost.json b/erpnext/projects/doctype/activity_cost/activity_cost.json
index 7f7720a..bdc147e 100644
--- a/erpnext/projects/doctype/activity_cost/activity_cost.json
+++ b/erpnext/projects/doctype/activity_cost/activity_cost.json
@@ -2,7 +2,7 @@
  "allow_copy": 0, 
  "allow_import": 1, 
  "allow_rename": 1, 
- "autoname": "Activity Cost - .#", 
+ "autoname": "AC-.#####", 
  "creation": "2015-03-23 02:00:21.861546", 
  "custom": 0, 
  "docstatus": 0, 
@@ -31,11 +31,12 @@
   }, 
   {
    "fieldname": "employee_name", 
-   "fieldtype": "Read Only", 
+   "fieldtype": "Data", 
    "label": "Employee Name", 
-   "options": "employee.employee_name", 
+   "options": "", 
    "permlevel": 0, 
-   "precision": ""
+   "precision": "", 
+   "read_only": 1
   }, 
   {
    "fieldname": "column_break_2", 
@@ -135,7 +136,7 @@
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 0, 
- "modified": "2015-04-14 02:08:33.690406", 
+ "modified": "2015-06-11 06:50:47.999788", 
  "modified_by": "Administrator", 
  "module": "Projects", 
  "name": "Activity Cost", 
diff --git a/erpnext/projects/doctype/activity_cost/activity_cost.py b/erpnext/projects/doctype/activity_cost/activity_cost.py
index 121e650..8cd04f5 100644
--- a/erpnext/projects/doctype/activity_cost/activity_cost.py
+++ b/erpnext/projects/doctype/activity_cost/activity_cost.py
@@ -15,6 +15,8 @@
 		self.check_unique()
 		
 	def set_title(self):
+		if not self.employee_name:
+			self.employee_name = frappe.db.get_value("Employee", self.employee, "employee_name")
 		self.title = _("{0} for {1}").format(self.employee_name, self.activity_type)
 		
 	def check_unique(self):
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index 37a8b1b..05e4038 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -13,19 +13,25 @@
 	def get_feed(self):
 		return '{0}: {1}'.format(_(self.status), self.project_name)
 
-	def __setup__(self):
+	def onload(self):
 		"""Load project tasks for quick view"""
-		self.tasks = []
-		for task in frappe.get_all("Task", "*", {"project": self.name}, order_by="exp_start_date asc"):
-			self.append("tasks", {
-				"title": task.subject,
-				"status": task.status,
-				"start_date": task.exp_start_date,
-				"end_date": task.exp_end_date,
-				"description": task.description,
-				"task_id": task.name
-			})
-
+		if not self.get("tasks"):
+			for task in self.get_tasks():
+				self.append("tasks", {
+					"title": task.subject,
+					"status": task.status,
+					"start_date": task.exp_start_date,
+					"end_date": task.exp_end_date,
+					"description": task.description,
+					"task_id": task.name
+				})
+			
+	def __setup__(self):
+		self.onload()
+	
+	def get_tasks(self):
+		return frappe.get_all("Task", "*", {"project": self.name}, order_by="exp_start_date asc")
+		
 	def validate(self):
 		self.validate_dates()
 		self.sync_tasks()
diff --git a/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.js b/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.js
index e975e9f..6d00b82 100644
--- a/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.js
+++ b/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.js
@@ -8,6 +8,13 @@
 			"label": __("Days Since Last Order"),
 			"fieldtype": "Int",
 			"default": 60
+		},
+		{
+			"fieldname":"doctype",
+			"label": __("Doctype"),
+			"fieldtype": "Select",
+			"default": "Sales Order",
+			"options": "Sales Order\nSales Invoice"
 		}
 	]
 }
\ No newline at end of file
diff --git a/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.py b/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.py
index de4c655..86186aa 100644
--- a/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.py
+++ b/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.py
@@ -10,41 +10,51 @@
 	if not filters: filters ={}
 
 	days_since_last_order = filters.get("days_since_last_order")
+	doctype = filters.get("doctype")
+	
 	if cint(days_since_last_order) <= 0:
 		frappe.throw(_("'Days Since Last Order' must be greater than or equal to zero"))
 
 	columns = get_columns()
-	customers = get_so_details()
+	customers = get_sales_details(doctype)
 
 	data = []
 	for cust in customers:
 		if cint(cust[8]) >= cint(days_since_last_order):
-			cust.insert(7,get_last_so_amt(cust[0]))
+			cust.insert(7,get_last_sales_amt(cust[0], doctype))
 			data.append(cust)
 	return columns, data
 
-def get_so_details():
+def get_sales_details(doctype):
+	cond = """sum(so.base_net_total) as 'total_order_considered',
+			max(so.posting_date) as 'last_order_date',
+			DATEDIFF(CURDATE(), max(so.posting_date)) as 'days_since_last_order' """
+	if doctype == "Sales Order":
+		cond = """sum(if(so.status = "Stopped",
+				so.base_net_total * so.per_delivered/100,
+				so.base_net_total)) as 'total_order_considered',
+			max(so.transaction_date) as 'last_order_date',
+			DATEDIFF(CURDATE(), max(so.transaction_date)) as 'days_since_last_order'"""
+	
 	return frappe.db.sql("""select
 			cust.name,
 			cust.customer_name,
 			cust.territory,
 			cust.customer_group,
 			count(distinct(so.name)) as 'num_of_order',
-			sum(base_net_total) as 'total_order_value',
-			sum(if(so.status = "Stopped",
-				so.base_net_total * so.per_delivered/100,
-				so.base_net_total)) as 'total_order_considered',
-			max(so.transaction_date) as 'last_sales_order_date',
-			DATEDIFF(CURDATE(), max(so.transaction_date)) as 'days_since_last_order'
-		from `tabCustomer` cust, `tabSales Order` so
+			sum(base_net_total) as 'total_order_value', {0}
+		from `tabCustomer` cust, `tab{1}` so
 		where cust.name = so.customer and so.docstatus = 1
 		group by cust.name
-		order by 'days_since_last_order' desc """,as_list=1)
+		order by 'days_since_last_order' desc """.format(cond, doctype), as_list=1)
 
-def get_last_so_amt(customer):
-	res =  frappe.db.sql("""select base_net_total from `tabSales Order`
-		where customer = %s and docstatus = 1 order by transaction_date desc
-		limit 1""", customer)
+def get_last_sales_amt(customer, doctype):
+	cond = "posting_date"
+	if doctype =="Sales Order":
+		cond = "transaction_date"
+	res =  frappe.db.sql("""select base_net_total from `tab{0}`
+		where customer = %s and docstatus = 1 order by {1} desc
+		limit 1""".format(doctype, cond), customer)
 
 	return res and res[0][0] or 0
 
@@ -58,6 +68,6 @@
 		_("Total Order Value") + ":Currency:120",
 		_("Total Order Considered") + ":Currency:160",
 		_("Last Order Amount") + ":Currency:160",
-		_("Last Sales Order Date") + ":Date:160",
+		_("Last Order Date") + ":Date:160",
 		_("Days Since Last Order") + "::160"
 	]
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index da86432..d823e7e 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -185,9 +185,6 @@
 
 	def validate_production_order(self):
 		if self.purpose in ("Manufacture", "Material Transfer for Manufacture"):
-			if not self.bom_no:
-				frappe.throw(_("BOM No is mandatory"))
-				
 			# check if production order is entered
 			if not self.production_order:
 				frappe.throw(_("Production order number is mandatory for stock entry purpose manufacture"))
diff --git a/setup.py b/setup.py
index 9fe6e2f..2a8f024 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
 from setuptools import setup, find_packages
 
-version = "5.0.21"
+version = "5.0.22"
 
 with open("requirements.txt", "r") as f:
 	install_requires = f.readlines()