Task added to expense claim
all cost (expense claim and time log) against Task; task updates project cost.
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.json b/erpnext/hr/doctype/expense_claim/expense_claim.json
index ef3d617..7392138 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.json
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.json
@@ -192,6 +192,14 @@
    "precision": ""
   }, 
   {
+   "fieldname": "task", 
+   "fieldtype": "Link", 
+   "label": "Task", 
+   "options": "Task", 
+   "permlevel": 0, 
+   "precision": ""
+  }, 
+  {
    "fieldname": "email_id", 
    "fieldtype": "Data", 
    "hidden": 1, 
@@ -219,8 +227,8 @@
  ], 
  "icon": "icon-money", 
  "idx": 1, 
- "is_submittable": 1, 
- "modified": "2015-03-26 04:41:50.473196", 
+ "is_submittable": 1,
+ "modified": "2015-03-30 05:17:43.963137", 
  "modified_by": "Administrator", 
  "module": "HR", 
  "name": "Expense Claim", 
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py
index c86c3ef..886a55d 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.py
@@ -21,17 +21,18 @@
 		self.validate_sanctioned_amount()
 		self.validate_exp_details()
 		self.validate_expense_approver()
+		self.validate_task()
 		set_employee_name(self)
 
 	def on_submit(self):
 		if self.approval_status=="Draft":
 			frappe.throw(_("""Approval Status must be 'Approved' or 'Rejected'"""))
-		if self.project:
-			self.update_project()
+		if self.task:
+			self.update_task()
 			
 	def on_cancel(self):
 		if self.project:
-			self.update_project()
+			self.update_task()
 
 	def validate_exp_details(self):
 		if not self.get('expenses'):
@@ -42,10 +43,14 @@
 			frappe.throw(_("{0} ({1}) must have role 'Expense Approver'")\
 				.format(get_fullname(self.exp_approver), self.exp_approver), InvalidExpenseApproverError)
 	
-	def update_project(self):
+	def update_task(self):
 		expense_amount = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim` 
-			where project = %s and approval_status = "Approved" and docstatus=1""",self.project)
-		frappe.db.set_value("Project", self.project, "total_expense_claims", expense_amount)
+			where project = %s and task = %s and approval_status = "Approved" and docstatus=1""",(self.project, self.task))
+		frappe.db.set_value("Project", self.project, "total_expense_claim", expense_amount)
+
+	def validate_task(self):
+		if self.project and not self.task:
+			frappe.throw(_("Task is Mandatory if Time Log is against a project"))
 
 	def validate_sanctioned_amount(self):
 		if self.total_sanctioned_amount > self.total_claimed_amount:
diff --git a/erpnext/projects/doctype/project/project.json b/erpnext/projects/doctype/project/project.json
index f392bc8..90b4e65 100644
--- a/erpnext/projects/doctype/project/project.json
+++ b/erpnext/projects/doctype/project/project.json
@@ -206,9 +206,9 @@
    "read_only": 1
   }, 
   {
-   "fieldname": "total_expense_claims", 
+   "fieldname": "total_expense_claim", 
    "fieldtype": "Currency", 
-   "label": "Total Expense Claims", 
+   "label": "Total Expense Claim", 
    "permlevel": 0, 
    "precision": "", 
    "read_only": 1
@@ -278,7 +278,7 @@
  "icon": "icon-puzzle-piece", 
  "idx": 1, 
  "max_attachments": 4, 
- "modified": "2015-03-23 06:44:19.538443", 
+ "modified": "2015-03-30 08:42:33.940104", 
  "modified_by": "Administrator", 
  "module": "Projects", 
  "name": "Project", 
diff --git a/erpnext/projects/doctype/task/task.js b/erpnext/projects/doctype/task/task.js
index 51aabca..9756331 100644
--- a/erpnext/projects/doctype/task/task.js
+++ b/erpnext/projects/doctype/task/task.js
@@ -25,6 +25,19 @@
 		this.frm.doc.project && frappe.model.remove_from_locals("Project",
 			this.frm.doc.project);
 	},
+	
+	refresh: function(doc) {
+		if(!doc.__islocal) {
+			cur_frm.add_custom_button(__("Time Logs"), function() {
+				frappe.route_options = {"project": doc.project, "task": doc.name}
+				frappe.set_route("List", "Time Log");
+			}, "icon-list", true);
+			cur_frm.add_custom_button(__("Expense Claims"), function() {
+				frappe.route_options = {"project": doc.project, "task": doc.name}
+				frappe.set_route("List", "Expense Claim");
+			}, "icon-list", true);
+		}
+	}
 });
 
 
diff --git a/erpnext/projects/doctype/task/task.json b/erpnext/projects/doctype/task/task.json
index e547834..5cbef3c 100644
--- a/erpnext/projects/doctype/task/task.json
+++ b/erpnext/projects/doctype/task/task.json
@@ -7,16 +7,6 @@
  "document_type": "Master", 
  "fields": [
   {
-   "fieldname": "task_details", 
-   "fieldtype": "Section Break", 
-   "label": "", 
-   "oldfieldtype": "Section Break", 
-   "permlevel": 0, 
-   "print_width": "50%", 
-   "search_index": 0, 
-   "width": "50%"
-  }, 
-  {
    "fieldname": "subject", 
    "fieldtype": "Data", 
    "in_filter": 1, 
@@ -110,29 +100,28 @@
   {
    "fieldname": "time_and_budget", 
    "fieldtype": "Section Break", 
-   "label": "Time and Budget", 
+   "label": "", 
    "oldfieldtype": "Section Break", 
    "permlevel": 0
   }, 
   {
-   "fieldname": "expected", 
-   "fieldtype": "Column Break", 
-   "label": "Expected", 
-   "oldfieldtype": "Column Break", 
-   "permlevel": 0, 
-   "print_width": "50%", 
-   "width": "50%"
-  }, 
-  {
-   "fieldname": "exp_total_hrs", 
-   "fieldtype": "Data", 
-   "label": "Total Hours (Expected)", 
+   "default": "0", 
+   "description": "in Hours", 
+   "fieldname": "expected_time", 
+   "fieldtype": "Float", 
+   "label": "Expected Time", 
    "oldfieldname": "exp_total_hrs", 
    "oldfieldtype": "Data", 
    "permlevel": 0, 
    "reqd": 0
   }, 
   {
+   "fieldname": "column_break_12", 
+   "fieldtype": "Column Break", 
+   "permlevel": 0, 
+   "precision": ""
+  }, 
+  {
    "fieldname": "allocated_budget", 
    "fieldtype": "Currency", 
    "label": "Allocated Budget", 
@@ -143,8 +132,8 @@
   }, 
   {
    "fieldname": "actual", 
-   "fieldtype": "Column Break", 
-   "label": "Actual", 
+   "fieldtype": "Section Break", 
+   "label": "", 
    "oldfieldtype": "Column Break", 
    "permlevel": 0, 
    "print_width": "50%", 
@@ -156,7 +145,14 @@
    "label": "Actual Start Date", 
    "oldfieldname": "act_start_date", 
    "oldfieldtype": "Date", 
-   "permlevel": 0
+   "permlevel": 0, 
+   "read_only": 1
+  }, 
+  {
+   "fieldname": "column_break_15", 
+   "fieldtype": "Column Break", 
+   "permlevel": 0, 
+   "precision": ""
   }, 
   {
    "fieldname": "act_end_date", 
@@ -164,16 +160,50 @@
    "label": "Actual End Date", 
    "oldfieldname": "act_end_date", 
    "oldfieldtype": "Date", 
-   "permlevel": 0
+   "permlevel": 0, 
+   "read_only": 1
   }, 
   {
-   "fieldname": "actual_budget", 
+   "fieldname": "section_break_17", 
+   "fieldtype": "Section Break", 
+   "permlevel": 0, 
+   "precision": ""
+  }, 
+  {
+   "default": "0", 
+   "description": "in Hours", 
+   "fieldname": "actual_time", 
+   "fieldtype": "Float", 
+   "label": "Actual Time", 
+   "options": "", 
+   "permlevel": 0, 
+   "precision": "", 
+   "read_only": 1
+  }, 
+  {
+   "fieldname": "column_break_20", 
+   "fieldtype": "Column Break", 
+   "permlevel": 0, 
+   "precision": ""
+  }, 
+  {
+   "fieldname": "actual_cost", 
    "fieldtype": "Currency", 
-   "label": "Actual Budget", 
+   "label": "Actual Cost", 
    "oldfieldname": "actual_budget", 
    "oldfieldtype": "Currency", 
    "options": "Company:company:default_currency", 
-   "permlevel": 0
+   "permlevel": 0, 
+   "read_only": 1
+  }, 
+  {
+   "fieldname": "total_expense_claim", 
+   "fieldtype": "Currency", 
+   "label": "Total Expense Claim", 
+   "options": "Company:company:default_currency", 
+   "permlevel": 0, 
+   "precision": "", 
+   "read_only": 1
   }, 
   {
    "fieldname": "more_details", 
@@ -217,7 +247,7 @@
  "icon": "icon-check", 
  "idx": 1, 
  "max_attachments": 5, 
- "modified": "2015-02-20 05:09:27.295024", 
+ "modified": "2015-03-30 05:50:04.409614", 
  "modified_by": "Administrator", 
  "module": "Projects", 
  "name": "Task", 
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index acd0877..c921d02 100644
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe, json
 
-from frappe.utils import getdate, today
+from frappe.utils import getdate
 from frappe import _
 
 
@@ -26,27 +26,33 @@
 			return ret
 
 	def validate(self):
+		self.validate_dates()
+		
+	def validate_dates(self):
 		if self.exp_start_date and self.exp_end_date and getdate(self.exp_start_date) > getdate(self.exp_end_date):
 			frappe.throw(_("'Expected Start Date' can not be greater than 'Expected End Date'"))
 
 		if self.act_start_date and self.act_end_date and getdate(self.act_start_date) > getdate(self.act_end_date):
 			frappe.throw(_("'Actual Start Date' can not be greater than 'Actual End Date'"))
 
-		self.update_status()
-
-	def update_status(self):
-		status = frappe.db.get_value("Task", self.name, "status")
-		if self.status=="Working" and status !="Working" and not self.act_start_date:
-			self.act_start_date = today()
-
-		if self.status=="Closed" and status != "Closed" and not self.act_end_date:
-			self.act_end_date = today()
-
 	def on_update(self):
+		self.update_percentage()
+		self.update_project()
+			
+	def update_percentage(self):
 		"""update percent complete in project"""
 		if self.project and not self.flags.from_project:
 			project = frappe.get_doc("Project", self.project)
 			project.run_method("update_percent_complete")
+			
+	def update_project(self):
+		total_activity_cost = frappe.db.sql("""select sum(actual_cost) from `tabTask` 
+			where project = %s""",self.project)
+		frappe.db.set_value("Project", self.project, "total_activity_cost", total_activity_cost)
+		
+		total_expense_claim = frappe.db.sql("""select sum(total_expense_claim) from `tabTask` 
+			where project = %s""",self.project)
+		frappe.db.set_value("Project", self.project, "total_expense_claim", total_expense_claim)
 
 @frappe.whitelist()
 def get_events(start, end, filters=None):
diff --git a/erpnext/projects/doctype/time_log/time_log.json b/erpnext/projects/doctype/time_log/time_log.json
index 8b7c956..f52bcad 100644
--- a/erpnext/projects/doctype/time_log/time_log.json
+++ b/erpnext/projects/doctype/time_log/time_log.json
@@ -92,6 +92,25 @@
    "read_only": 1
   }, 
   {
+   "depends_on": "", 
+   "fieldname": "project", 
+   "fieldtype": "Link", 
+   "in_list_view": 1, 
+   "label": "Project", 
+   "options": "Project", 
+   "permlevel": 0, 
+   "read_only": 0
+  }, 
+  {
+   "depends_on": "", 
+   "fieldname": "task", 
+   "fieldtype": "Link", 
+   "label": "Task", 
+   "options": "Task", 
+   "permlevel": 0, 
+   "read_only": 0
+  }, 
+  {
    "depends_on": "eval:!doc.for_manufacturing", 
    "fieldname": "activity_type", 
    "fieldtype": "Link", 
@@ -103,15 +122,6 @@
    "reqd": 0
   }, 
   {
-   "depends_on": "eval:!doc.for_manufacturing", 
-   "fieldname": "task", 
-   "fieldtype": "Link", 
-   "label": "Task", 
-   "options": "Task", 
-   "permlevel": 0, 
-   "read_only": 0
-  }, 
-  {
    "depends_on": "eval:doc.for_manufacturing", 
    "fieldname": "section_break_11", 
    "fieldtype": "Section Break", 
@@ -189,22 +199,6 @@
    "read_only": 0
   }, 
   {
-   "fieldname": "section_break_9", 
-   "fieldtype": "Section Break", 
-   "permlevel": 0, 
-   "read_only": 0
-  }, 
-  {
-   "depends_on": "", 
-   "fieldname": "project", 
-   "fieldtype": "Link", 
-   "in_list_view": 1, 
-   "label": "Project", 
-   "options": "Project", 
-   "permlevel": 0, 
-   "read_only": 0
-  }, 
-  {
    "depends_on": "", 
    "fieldname": "section_break_24", 
    "fieldtype": "Section Break", 
diff --git a/erpnext/projects/doctype/time_log/time_log.py b/erpnext/projects/doctype/time_log/time_log.py
index de37912..09d0bec 100644
--- a/erpnext/projects/doctype/time_log/time_log.py
+++ b/erpnext/projects/doctype/time_log/time_log.py
@@ -24,15 +24,20 @@
 		self.check_workstation_timings()
 		self.validate_production_order()
 		self.validate_manufacturing()
+		self.validate_task()
 		self.validate_cost()
 
 	def on_submit(self):
-		self.update_production_order()
-		self.update_project()
+		if self.for_manufacturing:
+			self.update_production_order()
+		if self.task:
+			self.update_task()
 
 	def on_cancel(self):
-		self.update_production_order()
-		self.update_project()
+		if self.for_manufacturing:
+			self.update_production_order()
+		if self.task:
+			self.update_task()
 
 	def before_update_after_submit(self):
 		self.set_status()
@@ -128,7 +133,7 @@
 	def update_production_order(self):
 		"""Updates `start_date`, `end_date`, `status` for operation in Production Order."""
 
-		if self.for_manufacturing and self.production_order:
+		if self.production_order:
 			if not self.operation_id:
 				frappe.throw(_("Operation ID not set"))
 
@@ -217,10 +222,22 @@
 		else:
 			self.billing_amount = 0
 				
-	def update_project(self):
-		activity_cost = frappe.db.sql("""select sum(billing_cost) from `tabTime Log` 
-			where project = %s and docstatus=1""",self.project)
-		frappe.db.set_value("Project", self.project, "total_activity_cost", activity_cost)
+	def validate_task(self):
+		if self.project and not self.task:
+			frappe.throw(_("Task is Mandatory if Time Log is against a project"))
+	
+	def update_task(self):
+		tl = frappe.db.sql("""select min(from_time) as start_date, max(to_time) as end_date, sum(billing_amount) as cost, sum(hours) as time 
+			from `tabTime Log` where project = %s and task = %s and docstatus=1""",(self.project, self.task),as_dict=1)[0]
+			
+		task = frappe.get_doc("Task", self.task)
+		if task.status == "Open":
+			task.status = "Working"
+		task.actual_cost= tl.cost
+		task.actual_time= tl.time
+		task.act_start_date= tl.start_date
+		task.act_end_date= tl.end_date
+		task.save()
 
 @frappe.whitelist()
 def get_events(start, end, filters=None):