completed Time Log / Time Log Batch
diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py
index 9973398..7068c72 100644
--- a/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/accounts/doctype/sales_invoice/sales_invoice.py
@@ -75,6 +75,7 @@
 		self.set_aging_date()
 		self.set_against_income_account()
 		self.validate_c_form()
+		self.validate_time_logs_are_submitted()
 		self.validate_recurring_invoice()
 		
 	def on_submit(self):
@@ -104,7 +105,7 @@
 			self.update_against_document_in_jv()
 
 		self.update_c_form()
-		
+		self.update_time_log_batch(self.doc.name)
 		self.convert_to_recurring()
 
 
@@ -122,12 +123,28 @@
 		self.check_next_docstatus()
 		sales_com_obj.update_prevdoc_detail(0, self)
 
+		self.update_time_log_batch(None)
 		self.make_gl_entries(is_cancel=1)
 
 	def on_update_after_submit(self):
 		self.validate_recurring_invoice()
 		self.convert_to_recurring()
 
+	def update_time_log_batch(self, sales_invoice):
+		for d in self.doclist.get({"doctype":"Sales Invoice Item"}):
+			if d.time_log_batch:
+				tlb = webnotes.bean("Time Log Batch", d.time_log_batch)
+				tlb.doc.sales_invoice = sales_invoice
+				tlb.update_after_submit()
+
+	def validate_time_logs_are_submitted(self):
+		for d in self.doclist.get({"doctype":"Sales Invoice Item"}):
+			if d.time_log_batch:
+				status = webnotes.conn.get_value("Time Log Batch", d.time_log_batch, "status")
+				if status!="Submitted":
+					webnotes.msgprint(_("Time Log Batch status must be 'Submitted'") + ":" + d.time_log_batch,
+						raise_exception=True)
+
 	def set_pos_fields(self):
 		"""Set retail related fields from pos settings"""
 		pos = webnotes.conn.sql("select * from `tabPOS Setting` where ifnull(user,'') = '%s' and company = '%s'" % (session['user'], self.doc.company), as_dict=1)
diff --git a/accounts/doctype/sales_invoice/sales_invoice_map.js b/accounts/doctype/sales_invoice/sales_invoice_map.js
new file mode 100644
index 0000000..dec4c6f
--- /dev/null
+++ b/accounts/doctype/sales_invoice/sales_invoice_map.js
@@ -0,0 +1,16 @@
+wn.model.map_info["Sales Invoice"] = {
+	"Time Log Batch": {
+		table_map: {
+			"Sales Invoice Item": "Time Log Batch",
+		},
+		field_map: {
+			"Sales Invoice Item": {
+				"basic_rate": "rate",
+				"time_log_batch": "name",
+				"qty": "total_hours",
+				"stock_uom": "=Hour",
+				"description": "=via Time Logs"
+			}
+		},
+	}
+}
\ No newline at end of file
diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py
index 6dcb713..9059978 100644
--- a/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -28,6 +28,31 @@
 		jv.cancel()
 		self.assertEquals(webnotes.conn.get_value("Sales Invoice", w.doc.name, "outstanding_amount"),
 			561.8)
+			
+	def test_time_log_batch(self):
+		tlb = webnotes.bean("Time Log Batch", "_T-Time Log Batch-00001")
+		tlb.submit()
+		
+		w = webnotes.bean(webnotes.copy_doclist(test_records[0]))
+		w.doclist[1].time_log_batch = "_T-Time Log Batch-00001"
+		w.insert()
+		w.submit()
+		
+		self.assertEquals(webnotes.conn.get_value("Time Log Batch", "_T-Time Log Batch-00001", "status"), 
+			"Billed")
+
+		self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), 
+			"Billed")
+
+		w.cancel()
+
+		self.assertEquals(webnotes.conn.get_value("Time Log Batch", "_T-Time Log Batch-00001", "status"), 
+			"Submitted")
+
+		self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), 
+			"Batched for Billing")
+			
+		
 		
 test_dependencies = ["Journal Voucher"]
 
diff --git a/accounts/doctype/sales_invoice_item/sales_invoice_item.txt b/accounts/doctype/sales_invoice_item/sales_invoice_item.txt
index 88c5aa8..ae1afe9 100644
--- a/accounts/doctype/sales_invoice_item/sales_invoice_item.txt
+++ b/accounts/doctype/sales_invoice_item/sales_invoice_item.txt
@@ -1,8 +1,8 @@
 [
  {
-  "creation": "2013-01-10 16:34:09", 
+  "creation": "2013-01-29 19:25:49", 
   "docstatus": 0, 
-  "modified": "2013-01-29 16:27:51", 
+  "modified": "2013-03-01 13:41:51", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -322,6 +322,13 @@
  }, 
  {
   "doctype": "DocField", 
+  "fieldname": "time_log_batch", 
+  "fieldtype": "Link", 
+  "label": "Time Log Batch", 
+  "options": "Time Log Batch"
+ }, 
+ {
+  "doctype": "DocField", 
   "fieldname": "item_tax_rate", 
   "fieldtype": "Small Text", 
   "hidden": 1, 
diff --git a/hr/doctype/leave_application/leave_application.py b/hr/doctype/leave_application/leave_application.py
index 313f27f..e8cc446 100755
--- a/hr/doctype/leave_application/leave_application.py
+++ b/hr/doctype/leave_application/leave_application.py
@@ -22,6 +22,7 @@
 from webnotes import msgprint
 
 class LeaveDayBlockedError(Exception): pass
+class OverlapError(Exception): pass
 	
 from webnotes.model.controller import DocListController
 class DocType(DocListController):
@@ -129,17 +130,22 @@
 						(self.doc.leave_type,), raise_exception=1)
 
 	def validate_leave_overlap(self):
+		if not self.doc.name:
+			self.doc.name = "New Leave Application"
+			
 		for d in webnotes.conn.sql("""select name, leave_type, posting_date, 
 			from_date, to_date 
 			from `tabLeave Application` 
 			where 
-			(from_date <= %(to_date)s and to_date >= %(from_date)s)
-			and employee = %(employee)s
+			employee = %(employee)s
 			and docstatus < 2
 			and status in ("Open", "Approved")
+			and (from_date between %(from_date)s and %(to_date)s 
+				or to_date between %(from_date)s and %(to_date)s
+				or %(from_date)s between from_date and to_date)
 			and name != %(name)s""", self.doc.fields, as_dict = 1):
  
-			msgprint("Employee : %s has already applied for %s between %s and %s on %s. Please refer Leave Application : <a href=\"#Form/Leave Application/%s\">%s</a>" % (self.doc.employee, cstr(d['leave_type']), formatdate(d['from_date']), formatdate(d['to_date']), formatdate(d['posting_date']), d['name'], d['name']), raise_exception = 1)
+			msgprint("Employee : %s has already applied for %s between %s and %s on %s. Please refer Leave Application : <a href=\"#Form/Leave Application/%s\">%s</a>" % (self.doc.employee, cstr(d['leave_type']), formatdate(d['from_date']), formatdate(d['to_date']), formatdate(d['posting_date']), d['name'], d['name']), raise_exception = OverlapError)
 
 	def validate_max_days(self):
 		max_days = webnotes.conn.sql("select max_days_allowed from `tabLeave Type` where name = '%s'" %(self.doc.leave_type))
diff --git a/hr/doctype/leave_application/test_leave_application.py b/hr/doctype/leave_application/test_leave_application.py
index dc1b463..bc4a38c 100644
--- a/hr/doctype/leave_application/test_leave_application.py
+++ b/hr/doctype/leave_application/test_leave_application.py
@@ -1,7 +1,7 @@
 import webnotes
 import unittest
 
-from hr.doctype.leave_application.leave_application import LeaveDayBlockedError
+from hr.doctype.leave_application.leave_application import LeaveDayBlockedError, OverlapError
 
 class TestLeaveApplication(unittest.TestCase):
 	def get_application(self, doclist):
@@ -23,13 +23,22 @@
 		
 		from webnotes.profile import add_role
 		add_role("test1@example.com", "HR User")
+
+		# clear other applications
+		webnotes.conn.sql("delete from `tabLeave Application`")
 		
 		application = self.get_application(test_records[1])
 		self.assertTrue(application.insert())
+
+	def test_overlap(self):
+		application = self.get_application(test_records[1])
+		self.assertRaises(OverlapError, application.insert)
 		
 	def test_global_block_list(self):
+		
 		application = self.get_application(test_records[3])
 		application.doc.leave_approver = "test@example.com"
+		
 		webnotes.conn.set_value("Leave Block List", "_Test Leave Block List", 
 			"applies_to_all_departments", 1)
 		webnotes.conn.set_value("Employee", "_T-Employee-0002", "department", 
diff --git a/patches/patch_list.py b/patches/patch_list.py
index 1160809..42fc554 100644
--- a/patches/patch_list.py
+++ b/patches/patch_list.py
@@ -200,4 +200,5 @@
 	'execute:webnotes.reload_doc("accounts", "Print Format", "Sales Invoice Modern") # 2013-02-26',
 	'execute:webnotes.reload_doc("accounts", "Print Format", "Sales Invoice Spartan") # 2013-02-26',
 	"execute:(not webnotes.conn.exists('Role', 'Projects Manager')) and webnotes.doc({'doctype':'Role', 'role_name':'Projects Manager'}).insert()",
+	"execute:(not webnotes.conn.exists('UOM', 'Hour')) and webnotes.doc({'uom_name': 'Unit', 'doctype': 'UOM', 'name': 'Hour'}).insert()",
 ]
\ No newline at end of file
diff --git a/projects/doctype/activity_type/test_activity_type.py b/projects/doctype/activity_type/test_activity_type.py
new file mode 100644
index 0000000..77ef7b3
--- /dev/null
+++ b/projects/doctype/activity_type/test_activity_type.py
@@ -0,0 +1,5 @@
+test_records = [
+	[{"activity_type":"_Test Activity Type"}],
+	[{"activity_type":"_Test Activity Type 1"}],
+	[{"activity_type":"_Test Activity Type 2"}]
+]
\ No newline at end of file
diff --git a/projects/doctype/project/test_project.py b/projects/doctype/project/test_project.py
new file mode 100644
index 0000000..bd7460d
--- /dev/null
+++ b/projects/doctype/project/test_project.py
@@ -0,0 +1,8 @@
+test_records = [[{
+	"project_name": "_Test Project",
+	"status": "Open"
+}],
+[{
+	"project_name": "_Test Project 1",
+	"status": "Open"
+}]]
\ No newline at end of file
diff --git a/projects/doctype/task/test_task.py b/projects/doctype/task/test_task.py
new file mode 100644
index 0000000..2e95806
--- /dev/null
+++ b/projects/doctype/task/test_task.py
@@ -0,0 +1,7 @@
+test_records = [
+	[{"subject": "_Test Task", "project":"_Test Project", "status":"Open"}],
+	[{"subject": "_Test Task 1", "status":"Open"}],
+	[{"subject": "_Test Task 2", "status":"Open"}]
+]
+
+test_ignore = ["Customer"]
\ No newline at end of file
diff --git a/projects/doctype/time_log/test_time_log.py b/projects/doctype/time_log/test_time_log.py
new file mode 100644
index 0000000..1168c01
--- /dev/null
+++ b/projects/doctype/time_log/test_time_log.py
@@ -0,0 +1,19 @@
+import webnotes
+import unittest
+
+from projects.doctype.time_log.time_log import OverlapError
+
+class TestTimeLog(unittest.TestCase):
+	def test_duplication(self):		
+		ts = webnotes.bean(webnotes.copy_doclist(test_records[0]))
+		self.assertRaises(OverlapError, ts.insert)
+
+test_records = [[{
+	"from_time": "2013-01-01 10:00:00",
+	"to_time": "2013-01-01 11:00:00",
+	"activity_type": "_Test Activity Type",
+	"note": "_Test Note",
+	"docstatus": 1
+}]]
+
+test_ignore = ["Sales Invoice", "Time Log Batch"]
\ No newline at end of file
diff --git a/projects/doctype/time_log/time_log.js b/projects/doctype/time_log/time_log.js
new file mode 100644
index 0000000..a602332
--- /dev/null
+++ b/projects/doctype/time_log/time_log.js
@@ -0,0 +1,5 @@
+$.extend(cur_frm.cscript, {
+	refresh: function(doc) {
+		
+	}
+});
\ No newline at end of file
diff --git a/projects/doctype/time_log/time_log.py b/projects/doctype/time_log/time_log.py
index a605998..34969a9 100644
--- a/projects/doctype/time_log/time_log.py
+++ b/projects/doctype/time_log/time_log.py
@@ -6,6 +6,8 @@
 
 from webnotes.widgets.reportview import build_match_conditions
 
+class OverlapError(webnotes.ValidationError): pass
+
 class DocType:
 	def __init__(self, d, dl):
 		self.doc, self.doclist = d, dl
@@ -13,28 +15,46 @@
 	def validate(self):
 		self.set_status()
 		self.validate_overlap()
+		self.calculate_total_hours()
+		
+	def calculate_total_hours(self):
+		from webnotes.utils import time_diff_in_hours
+		self.doc.hours = time_diff_in_hours(self.doc.to_time, self.doc.from_time)
 
 	def set_status(self):
-		if self.doc.docstatus==0:
-			self.doc.status = "Draft"
-		elif self.doc.docstatus==1:
-			self.doc.status = "Submitted"
-		elif self.doc.docstatus==2:
-			self.doc.status = "Cancelled"
+		self.doc.status = {
+			"0": "Draft",
+			"1": "Submitted",
+			"2": "Cancelled"
+		}[str(self.doc.docstatus or 0)]
+		
+		if self.doc.time_log_batch:
+			self.doc.status="Batched for Billing"
 			
-		# billed will be set directly
-				
-	def validate_overlap(self):
+		if self.doc.sales_invoice:
+			self.doc.status="Billed"
+			
+	def validate_overlap(self):		
 		existing = webnotes.conn.sql_list("""select name from `tabTime Log` where owner=%s and
-			((from_time between %s and %s) or (to_time between %s and %s)) and name!=%s""", 
+			(
+				(from_time between %s and %s) or 
+				(to_time between %s and %s) or 
+				(%s between from_time and to_time)) 
+			and name!=%s
+			and docstatus < 2""", 
 			(self.doc.owner, self.doc.from_time, self.doc.to_time, self.doc.from_time, 
-				self.doc.to_time, self.doc.name))
+				self.doc.to_time, self.doc.from_time, self.doc.name or "No Name"))
 
 		if existing:
 			webnotes.msgprint(_("This Time Log conflicts with") + ":" + ', '.join(existing),
-				raise_exception=True)
+				raise_exception=OverlapError)
+	
+	def before_cancel(self):
+		self.set_status()
+	
+	def before_update_after_submit(self):
+		self.set_status()
 				
-		
 @webnotes.whitelist()
 def get_events(start, end):
 	match = build_match_conditions("Time Log")
diff --git a/projects/doctype/time_log/time_log.txt b/projects/doctype/time_log/time_log.txt
index a6ad667..0e52464 100644
--- a/projects/doctype/time_log/time_log.txt
+++ b/projects/doctype/time_log/time_log.txt
@@ -2,13 +2,13 @@
  {
   "creation": "2013-02-26 14:58:28", 
   "docstatus": 0, 
-  "modified": "2013-02-28 18:41:40", 
+  "modified": "2013-03-01 17:48:09", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
  {
   "allow_attach": 1, 
-  "autoname": "TL-.######", 
+  "autoname": "naming_series:", 
   "description": "Log of Activities performed by users against Tasks that can be used for tracking time, billing.", 
   "doctype": "DocType", 
   "document_type": "Master", 
@@ -40,14 +40,12 @@
  }, 
  {
   "doctype": "DocField", 
-  "fieldname": "status", 
+  "fieldname": "naming_series", 
   "fieldtype": "Select", 
-  "in_list_view": 1, 
-  "label": "Status", 
-  "options": "Draft\nSubmitted\nBatched for Billing\nBilled\nCancelled", 
+  "label": "Naming Series", 
+  "options": "TL-", 
   "permlevel": 0, 
-  "read_only": 1, 
-  "reqd": 0
+  "reqd": 1
  }, 
  {
   "doctype": "DocField", 
@@ -69,12 +67,31 @@
  }, 
  {
   "doctype": "DocField", 
+  "fieldname": "hours", 
+  "fieldtype": "Float", 
+  "label": "Hours", 
+  "permlevel": 0, 
+  "read_only": 1
+ }, 
+ {
+  "doctype": "DocField", 
   "fieldname": "column_break_3", 
   "fieldtype": "Column Break", 
   "permlevel": 0
  }, 
  {
   "doctype": "DocField", 
+  "fieldname": "status", 
+  "fieldtype": "Select", 
+  "in_list_view": 1, 
+  "label": "Status", 
+  "options": "Draft\nSubmitted\nBatched for Billing\nBilled\nCancelled", 
+  "permlevel": 0, 
+  "read_only": 1, 
+  "reqd": 0
+ }, 
+ {
+  "doctype": "DocField", 
   "fieldname": "activity_type", 
   "fieldtype": "Link", 
   "in_list_view": 1, 
@@ -128,6 +145,26 @@
   "permlevel": 0
  }, 
  {
+  "description": "Will be updated when batched.", 
+  "doctype": "DocField", 
+  "fieldname": "time_log_batch", 
+  "fieldtype": "Link", 
+  "label": "Time Log Batch", 
+  "options": "Time Log Batch", 
+  "permlevel": 0, 
+  "read_only": 1
+ }, 
+ {
+  "description": "Will be updated when billed.", 
+  "doctype": "DocField", 
+  "fieldname": "sales_invoice", 
+  "fieldtype": "Link", 
+  "label": "Sales Invoice", 
+  "options": "Sales Invoice", 
+  "permlevel": 0, 
+  "read_only": 1
+ }, 
+ {
   "doctype": "DocField", 
   "fieldname": "file_list", 
   "fieldtype": "Text", 
@@ -143,7 +180,7 @@
   "fieldtype": "Link", 
   "label": "Amended From", 
   "no_copy": 1, 
-  "options": "Sales Invoice", 
+  "options": "Time Log", 
   "permlevel": 1, 
   "print_hide": 1
  }, 
diff --git a/projects/doctype/time_log/time_log_list.js b/projects/doctype/time_log/time_log_list.js
index 13d35c1..85c9b2a 100644
--- a/projects/doctype/time_log/time_log_list.js
+++ b/projects/doctype/time_log/time_log_list.js
@@ -1,5 +1,6 @@
 // render
 wn.listview_settings['Time Log'] = {
+	add_fields: ["`tabTime Log`.`status`", "`tabTime Log`.`billable`", "`tabTime Log`.`activity_type`"],
 	selectable: true,
 	onload: function(me) {
 		me.appframe.add_button(wn._("Make Time Log Batch"), function() {
@@ -16,12 +17,28 @@
 					msgprint(wn._("Time Log is not billable") + ": " + d.name);
 					return;
 				}
-				if(d.sales_invoice) {
-					msgprint(wn._("Time Log has been Invoiced") + ": " + d.name);
+				if(d.status!="Submitted") {
+					msgprint(wn._("Time Log Status must be Submitted."));
 				}
 			}
 			
-			//
+			// make batch
+			wn.model.with_doctype("Time Log Batch", function() {
+				var tlb = wn.model.get_new_doc("Time Log Batch");
+				$.each(selected, function(i, d) {
+					var detail = wn.model.get_new_doc("Time Log Batch Detail");
+					$.extend(detail, {
+						"parenttype": "Time Log Batch",
+						"parentfield": "time_log_batch_details",
+						"parent": tlb.name,
+						"time_log": d.name,
+						"activity_type": d.activity_type,
+						"created_by": d.owner,
+						"idx": i+1
+					});
+				})
+				wn.set_route("Form", "Time Log Batch", tlb.name);
+			})
 			
 		}, "icon-file-alt");
 	}
diff --git a/projects/doctype/time_log_batch/test_time_log_batch.py b/projects/doctype/time_log_batch/test_time_log_batch.py
new file mode 100644
index 0000000..54195c2
--- /dev/null
+++ b/projects/doctype/time_log_batch/test_time_log_batch.py
@@ -0,0 +1,20 @@
+import webnotes, unittest
+
+class TimeLogBatchTest(unittest.TestCase):
+	def test_time_log_status(self):
+		self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Submitted")
+		tlb = webnotes.bean("Time Log Batch", "_T-Time Log Batch-00001")
+		tlb.submit()
+		self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Batched for Billing")
+		tlb.cancel()
+		self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Submitted")
+
+test_records = [[
+	{"rate": "500"},
+	{
+		"doctype": "Time Log Batch Detail",
+		"parenttype": "Time Log Batch",
+		"parentfield": "time_log_batch_details",
+		"time_log": "_T-Time Log-00001",
+	}
+]]
\ No newline at end of file
diff --git a/projects/doctype/time_log_batch/time_log_batch.js b/projects/doctype/time_log_batch/time_log_batch.js
index bd47c0b..6e5165b 100644
--- a/projects/doctype/time_log_batch/time_log_batch.js
+++ b/projects/doctype/time_log_batch/time_log_batch.js
@@ -1,5 +1,6 @@
 cur_frm.add_fetch("time_log", "activity_type", "activity_type");
 cur_frm.add_fetch("time_log", "owner", "created_by");
+cur_frm.add_fetch("time_log", "hours", "hours");
 
 cur_frm.set_query("time_log", "time_log_batch_details", function(doc) {
 	return {
@@ -12,7 +13,24 @@
 });
 
 $.extend(cur_frm.cscript, {
-	refresh: function() {
+	refresh: function(doc) {
+		cur_frm.set_intro({
+			"Draft": wn._("Select Time Logs and Submit to create a new Sales Invoice."),
+			"Submitted": wn._("Click on 'Make Sales Invoice' button to create a new Sales Invoice."),
+			"Billed": wn._("This Time Log Batch has been billed."),
+			"Cancelled": wn._("This Time Log Batch has been cancelled.")
+		}[doc.status]);
 		
+		if(doc.status=="Submitted") {
+			cur_frm.add_custom_button("Make Sales Invoice", function() { cur_frm.cscript.make_invoice() }, 
+				"icon-file-alt");
+		}
+	},
+	make_invoice: function() {
+		var doc = cur_frm.doc;
+		wn.model.map({
+			source: wn.model.get_doclist(doc.doctype, doc.name),
+			target: "Sales Invoice"
+		});
 	}
-})
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/projects/doctype/time_log_batch/time_log_batch.py b/projects/doctype/time_log_batch/time_log_batch.py
index fe4e9a3..6ec0e5b 100644
--- a/projects/doctype/time_log_batch/time_log_batch.py
+++ b/projects/doctype/time_log_batch/time_log_batch.py
@@ -2,10 +2,59 @@
 
 from __future__ import unicode_literals
 import webnotes
+from webnotes import _
 
 class DocType:
 	def __init__(self, d, dl):
 		self.doc, self.doclist = d, dl
+
+	def validate(self):
+		self.set_status()
+		self.doc.total_hours = 0.0
+		for d in self.doclist.get({"doctype":"Time Log Batch Detail"}):
+			tl = webnotes.doc("Time Log", d.time_log)
+			self.update_time_log_values(d, tl)
+			self.validate_time_log_is_submitted(tl)
+			self.doc.total_hours += float(tl.hours or 0.0)
+
+	def update_time_log_values(self, d, tl):
+		d.fields.update({
+			"hours": tl.hours,
+			"activity_type": tl.activity_type,
+			"created_by": tl.owner
+		})
+
+	def validate_time_log_is_submitted(self, tl):
+		if tl.status != "Submitted":
+			webnotes.msgprint(_("Time Log must have status 'Submitted'") + \
+				" :" + tl.name + " (" + _(tl.status) + ")", raise_exception=True)
+	
+	def set_status(self):
+		self.doc.status = {
+			"0": "Draft",
+			"1": "Submitted",
+			"2": "Cancelled"
+		}[str(self.doc.docstatus or 0)]
 		
+		if self.doc.sales_invoice:
+			self.doc.status = "Billed"
+	
 	def on_submit(self):
-		# update time logs as batched
\ No newline at end of file
+		self.update_status(self.doc.name)
+
+	def before_cancel(self):
+		self.update_status(None)
+
+	def before_update_after_submit(self):
+		self.update_status(self.doc.name)
+
+	def update_status(self, time_log_batch):
+		self.set_status()
+		for d in self.doclist.get({"doctype":"Time Log Batch Detail"}):
+			tl = webnotes.bean("Time Log", d.time_log)
+			tl.doc.time_log_batch = time_log_batch
+			tl.doc.sales_invoice = self.doc.sales_invoice
+			tl.update_after_submit()
+		
+
+		
\ No newline at end of file
diff --git a/projects/doctype/time_log_batch/time_log_batch.txt b/projects/doctype/time_log_batch/time_log_batch.txt
index b217f23..7fe1827 100644
--- a/projects/doctype/time_log_batch/time_log_batch.txt
+++ b/projects/doctype/time_log_batch/time_log_batch.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-02-28 17:57:33", 
   "docstatus": 0, 
-  "modified": "2013-02-28 18:36:28", 
+  "modified": "2013-03-01 17:54:57", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -24,6 +24,7 @@
   "permlevel": 0
  }, 
  {
+  "amend": 1, 
   "cancel": 1, 
   "create": 1, 
   "doctype": "DocPerm", 
@@ -59,17 +60,49 @@
  }, 
  {
   "doctype": "DocField", 
+  "fieldname": "column_break_3", 
+  "fieldtype": "Column Break"
+ }, 
+ {
+  "default": "Draft", 
+  "doctype": "DocField", 
+  "fieldname": "status", 
+  "fieldtype": "Select", 
+  "in_list_view": 1, 
+  "label": "Status", 
+  "options": "Draft\nSubmitted\nBilled\nCancelled", 
+  "read_only": 1
+ }, 
+ {
+  "description": "Will be updated after Sales Invoice is Submitted.", 
+  "doctype": "DocField", 
+  "fieldname": "sales_invoice", 
+  "fieldtype": "Link", 
+  "in_list_view": 1, 
+  "label": "Sales Invoice", 
+  "options": "Sales Invoice", 
+  "read_only": 1
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "section_break_5", 
+  "fieldtype": "Section Break"
+ }, 
+ {
+  "doctype": "DocField", 
   "fieldname": "time_log_batch_details", 
   "fieldtype": "Table", 
   "label": "Time Log Batch Details", 
-  "options": "Time Log Batch Detail"
+  "options": "Time Log Batch Detail", 
+  "reqd": 1
  }, 
  {
   "description": "In Hours", 
   "doctype": "DocField", 
-  "fieldname": "total_time", 
+  "fieldname": "total_hours", 
   "fieldtype": "Float", 
-  "label": "Total Time", 
+  "in_list_view": 1, 
+  "label": "Total Hours", 
   "read_only": 1
  }, 
  {
diff --git a/projects/doctype/time_log_batch_detail/time_log_batch_detail.txt b/projects/doctype/time_log_batch_detail/time_log_batch_detail.txt
index 0f7d23f..d1e1eae 100644
--- a/projects/doctype/time_log_batch_detail/time_log_batch_detail.txt
+++ b/projects/doctype/time_log_batch_detail/time_log_batch_detail.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-02-28 17:56:12", 
   "docstatus": 0, 
-  "modified": "2013-02-28 17:56:12", 
+  "modified": "2013-03-01 15:20:17", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -47,5 +47,11 @@
   "fieldtype": "Data", 
   "label": "Activity Type", 
   "read_only": 1
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "hours", 
+  "fieldtype": "Float", 
+  "label": "Hours"
  }
 ]
\ No newline at end of file
diff --git a/projects/page/projects_home/projects_home.js b/projects/page/projects_home/projects_home.js
index 36e3c0b..d9476e9 100644
--- a/projects/page/projects_home/projects_home.js
+++ b/projects/page/projects_home/projects_home.js
@@ -56,7 +56,18 @@
 			},
 		]
 	},
-]
+	{
+		title: wn._("Reports"),
+		right: true,
+		icon: "icon-list",
+		items: [
+			{
+				"label":wn._("Time Log Summary"),
+				route: "Report2/Time Log/Time Log Summary",
+				doctype: "Time Log"
+			},
+		]
+	}]
 
 pscript['onload_projects-home'] = function(wrapper) {
 	wn.views.moduleview.make(wrapper, "Projects");
diff --git a/projects/report/__init__.py b/projects/report/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/projects/report/__init__.py
diff --git a/projects/report/time_log_summary/__init__.py b/projects/report/time_log_summary/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/projects/report/time_log_summary/__init__.py
diff --git a/projects/report/time_log_summary/time_log_summary.txt b/projects/report/time_log_summary/time_log_summary.txt
new file mode 100644
index 0000000..3925a2d
--- /dev/null
+++ b/projects/report/time_log_summary/time_log_summary.txt
@@ -0,0 +1,22 @@
+[
+ {
+  "creation": "2013-03-01 17:36:35", 
+  "docstatus": 0, 
+  "modified": "2013-03-01 18:17:13", 
+  "modified_by": "Administrator", 
+  "owner": "Administrator"
+ }, 
+ {
+  "doctype": "Report", 
+  "is_standard": "Yes", 
+  "json": "{\"filters\":[],\"columns\":[[\"name\",\"Time Log\"],[\"status\",\"Time Log\"],[\"from_time\",\"Time Log\"],[\"hours\",\"Time Log\"],[\"activity_type\",\"Time Log\"],[\"owner\",\"Time Log\"],[\"billable\",\"Time Log\"],[\"time_log_batch\",\"Time Log\"],[\"sales_invoice\",\"Time Log\"]],\"sort_by\":\"Time Log.name\",\"sort_order\":\"desc\",\"sort_by_next\":\"\",\"sort_order_next\":\"desc\"}", 
+  "name": "__common__", 
+  "ref_doctype": "Time Log", 
+  "report_name": "Time Log Summary", 
+  "report_type": "Report Builder"
+ }, 
+ {
+  "doctype": "Report", 
+  "name": "Time Log Summary"
+ }
+]
\ No newline at end of file
diff --git a/startup/install.py b/startup/install.py
index 5ddbf09..f584769 100644
--- a/startup/install.py
+++ b/startup/install.py
@@ -162,6 +162,7 @@
 		
 		# UOM
 		{'uom_name': 'Unit', 'doctype': 'UOM', 'name': 'Unit'}, 
+		{'uom_name': 'Unit', 'doctype': 'UOM', 'name': 'Hour'}, 
 		{'uom_name': 'Box', 'doctype': 'UOM', 'name': 'Box'}, 
 		{'uom_name': 'Ft', 'doctype': 'UOM', 'name': 'Ft'}, 
 		{'uom_name': 'Kg', 'doctype': 'UOM', 'name': 'Kg'}, 
diff --git a/startup/observers.py b/startup/observers.py
index 0e17c9d..89980e4 100644
--- a/startup/observers.py
+++ b/startup/observers.py
@@ -19,5 +19,4 @@
 	"*:on_submit": "home.update_feed",
 	"Stock Entry:on_submit": "stock.doctype.material_request.material_request.update_completed_qty",
 	"Stock Entry:on_cancel": "stock.doctype.material_request.material_request.update_completed_qty",
-#	"*:on_update": "webnotes.widgets.moduleview.update_count"
 }
\ No newline at end of file
diff --git a/startup/open_count.py b/startup/open_count.py
index 7d8dcf8..916ecbd 100644
--- a/startup/open_count.py
+++ b/startup/open_count.py
@@ -27,4 +27,6 @@
 	"Production Order": {"docstatus":0},
 	"BOM": {"docstatus":0},
 	"Timesheet": {"docstatus":0},
+	"Time Log": {"status":"Draft"},
+	"Time Log Batch": {"status":"Draft"},
 }
\ No newline at end of file