[event] [lead, opportunity, project] [fix] create events
diff --git a/patches/june_2013/p04_fix_event_for_lead_oppty_project.py b/patches/june_2013/p04_fix_event_for_lead_oppty_project.py
new file mode 100644
index 0000000..a6449c5
--- /dev/null
+++ b/patches/june_2013/p04_fix_event_for_lead_oppty_project.py
@@ -0,0 +1,21 @@
+import webnotes
+
+def execute():
+	# delete orphaned Event User
+	webnotes.conn.sql("""delete from `tabEvent User`
+		where not exists(select name from `tabEvent` where `tabEvent`.name = `tabEvent User`.parent)""")
+		
+	for dt in ["Lead", "Opportunity", "Project"]:
+		for ref_name in webnotes.conn.sql_list("""select ref_name 
+			from `tabEvent` where ref_type=%s and ifnull(starts_on, '')='' """, dt):
+				if webnotes.conn.exists(dt, ref_name):
+					controller = webnotes.get_obj(dt, ref_name)
+					if dt == "Project":
+						controller.add_calendar_event()
+					else:
+						controller.delete_events()
+						controller._add_calendar_event()
+				else:
+					# remove events where ref doc doesn't exist
+					webnotes.delete_doc("Event", webnotes.conn.sql_list("""select name from `tabEvent` 
+						where ref_type=%s and ref_name=%s""", (dt, ref_name)))
\ No newline at end of file
diff --git a/patches/patch_list.py b/patches/patch_list.py
index d8b84da..6b88955 100644
--- a/patches/patch_list.py
+++ b/patches/patch_list.py
@@ -254,4 +254,5 @@
 	"patches.may_2013.p05_update_cancelled_gl_entries",
 	"patches.june_2013.p01_update_bom_exploded_items",
 	"execute:webnotes.delete_doc('DocType', 'System Console')",
+	"patches.june_2013.p04_fix_event_for_lead_oppty_project",
 ]
\ No newline at end of file
diff --git a/projects/doctype/project/project.py b/projects/doctype/project/project.py
index 1de551c..b519224 100644
--- a/projects/doctype/project/project.py
+++ b/projects/doctype/project/project.py
@@ -18,24 +18,17 @@
 import webnotes
 
 from webnotes.utils import flt, getdate
-from webnotes.model import db_exists
-from webnotes.model.doc import Document
-from webnotes.model.bean import copy_doclist
 from webnotes import msgprint
 
-sql = webnotes.conn.sql
-	
-
-
 class DocType:
-	def __init__(self, doc, doclist=[]):
+	def __init__(self, doc, doclist=None):
 		self.doc = doc
 		self.doclist = doclist
 	
 	# Get Customer Details along with its primary contact details
 	# ==============================================================
 	def get_customer_details(self):
-		details =sql("select address, territory, customer_group,customer_name from `tabCustomer` where name=%s and docstatus!=2",(self.doc.customer),as_dict=1)
+		details =webnotes.conn.sql("select address, territory, customer_group,customer_name from `tabCustomer` where name=%s and docstatus!=2",(self.doc.customer),as_dict=1)
 		if details:
 			ret = {
 				'customer_address'	:	details and details[0]['address'] or '',
@@ -44,7 +37,7 @@
 	'customer_name'		 :	details and details[0]['customer_name'] or ''
 			}
 			#get primary contact details(this is done separately coz. , if join query used & no primary contact thn it would not be able to fetch customer details)
-			contact_det = sql("select contact_name, phone, email_id from `tabContact` where customer_name='%s' and is_customer=1 and is_primary_contact=1 and docstatus!=2" %(self.doc.customer), as_dict = 1)
+			contact_det = webnotes.conn.sql("select contact_name, phone, email_id from `tabContact` where customer_name='%s' and is_customer=1 and is_primary_contact=1 and docstatus!=2" %(self.doc.customer), as_dict = 1)
 			ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or ''
 			ret['contact_no'] = contact_det and contact_det[0]['phone'] or ''
 			ret['email_id'] = contact_det and contact_det[0]['email_id'] or ''		
@@ -52,21 +45,7 @@
 		else:
 			msgprint("Customer : %s does not exist in system." % (self.doc.customer))
 			raise Exception	
-	
-	# Get customer's contact person details
-	# ==============================================================
-	def get_contact_details(self):
-		contact = sql("select contact_no, email_id from `tabContact` where contact_name = '%s' and customer_name = '%s' and docstatus != 2" %(self.doc,contact_person,self.doc.customer), as_dict=1)
-		if contact:
-			ret = {
-				'contact_no' : contact and contact[0]['contact_no'] or '',
-				'email_id' : contact and contact[0]['email_id'] or ''
-			}
-			return ret
-		else:
-			msgprint("Contact Person : %s does not exist in the system." % (self.doc,contact_person))
-			raise Exception
-	
+		
 	#calculate gross profit
 	#=============================================
 	def get_gross_profit(self):
@@ -86,20 +65,29 @@
 				raise Exception
 				
 	def on_update(self):
-		# update milestones
-		webnotes.conn.sql("""delete from tabEvent where ref_type='Project' and ref_name=%s""",
-			self.doc.name)
-		for d in self.doclist:
-			if d.doctype=='Project Milestone' and d.docstatus!=2:
-				self.add_calendar_event(d.milestone, d.milestone_date)
+		self.add_calendar_event()
 
-	def add_calendar_event(self, milestone, date):
-		""" Add calendar event for task in calendar of Allocated person"""
-		event = Document('Event')
-		event.description = milestone + ' for ' + self.doc.name
-		event.event_date = date
-		event.event_hour =  '10:00'
-		event.event_type = 'Public'
-		event.ref_type = 'Project'
-		event.ref_name = self.doc.name
-		event.save(1)
+	def add_calendar_event(self):
+		# delete any earlier event for this project
+		self.delete_events()
+		
+		# add events
+		for milestone in self.doclist.get({"parentfield": "project_milestones"}):
+			description = milestone.milestone + " for " + self.doc.name
+			webnotes.bean({
+				"doctype": "Event",
+				"owner": self.doc.owner,
+				"subject": description,
+				"description": description,
+				"starts_on": milestone.milestone_date + " 10:00:00",
+				"event_type": "Private",
+				"ref_type": self.doc.doctype,
+				"ref_name": self.doc.name
+			}).insert()
+	
+	def on_trash(self):
+		self.delete_events()
+			
+	def delete_events(self):
+		webnotes.delete_doc("Event", webnotes.conn.sql_list("""select name from `tabEvent` 
+			where ref_type=%s and ref_name=%s""", (self.doc.doctype, self.doc.name)))
\ No newline at end of file
diff --git a/selling/doctype/lead/lead.py b/selling/doctype/lead/lead.py
index d80f843..0e27261 100644
--- a/selling/doctype/lead/lead.py
+++ b/selling/doctype/lead/lead.py
@@ -29,6 +29,13 @@
 		self.doc = doc
 		self.doclist = doclist
 
+		self._prev = webnotes._dict({
+			"contact_date": webnotes.conn.get_value("Lead", self.doc.name, "contact_date") if \
+				(not cint(self.doc.fields.get("__islocal"))) else None,
+			"contact_by": webnotes.conn.get_value("Lead", self.doc.name, "contact_by") if \
+				(not cint(self.doc.fields.get("__islocal"))) else None,
+		})
+
 	def onload(self):
 		self.add_communication_list()
 
@@ -53,19 +60,19 @@
 			if not validate_email_add(self.doc.email_id):
 				msgprint('Please enter valid email id.')
 				raise Exception
-		
-		self._prev = webnotes._dict({
-			"contact_date": webnotes.conn.get_value("Lead", self.doc.name, "contact_date") if \
-				(not cint(self.doc.fields.get("__islocal"))) else None,
-			"contact_by": webnotes.conn.get_value("Lead", self.doc.name, "contact_by") if \
-				(not cint(self.doc.fields.get("__islocal"))) else None,
-		})
 				
-	
 	def on_update(self):
-		self.add_calendar_event()
-			
 		self.check_email_id_is_unique()
+		self.add_calendar_event()
+		
+	def add_calendar_event(self, opts=None):
+		super(DocType, self).add_calendar_event({
+			"owner": self.doc.lead_owner,
+			"subject": ('Contact ' + cstr(self.doc.lead_name)),
+			"description": ('Contact ' + cstr(self.doc.lead_name)) + \
+				(self.doc.contact_by and ('. By : ' + cstr(self.doc.contact_by)) or '') + \
+				(self.doc.remark and ('.To Discuss : ' + cstr(self.doc.remark)) or '')
+		})
 
 	def check_email_id_is_unique(self):
 		if self.doc.email_id:
@@ -76,35 +83,6 @@
 				items = [e[0] for e in email_list if e[0]!=self.doc.name]
 				webnotes.msgprint(_("""Email Id must be unique, already exists for: """) + \
 					", ".join(items), raise_exception=True)
-		
-	def add_calendar_event(self):
-		if self.doc.contact_by != cstr(self._prev.contact_by) or \
-				self.doc.contact_date != cstr(self._prev.contact_date):
-			# delete any earlier event by this lead
-			for name in webnotes.conn.sql_list("""select name from `tabEvent` 
-				where ref_type="Lead" and ref_name=%s""", self.doc.name):
-					webnotes.delete_doc("Event", name)
-			
-			if self.doc.contact_date:	
-				webnotes.bean([
-					{
-						"doctype": "Event",
-						"owner": self.doc.lead_owner or self.doc.owner,
-						"subject": ('Contact ' + cstr(self.doc.lead_name)),
-						"description": ('Contact ' + cstr(self.doc.lead_name)) + \
-							(self.doc.contact_by and ('. By : ' + cstr(self.doc.contact_by)) or '') + \
-							(self.doc.remark and ('.To Discuss : ' + cstr(self.doc.remark)) or ''),
-						"starts_on": self.doc.contact_date + " 10:00:00",
-						"event_type": "Private",
-						"ref_type": "Lead",
-						"ref_name": self.doc.name
-					},
-					{
-						"doctype": "Event User",
-						"parentfield": "event_individuals",
-						"person": self.doc.contact_by
-					}
-				]).insert()
 
 	def get_sender(self, comm):
 		return webnotes.conn.get_value('Sales Email Settings',None,'email_id')
@@ -113,3 +91,5 @@
 		webnotes.conn.sql("""update tabCommunication set lead=null where lead=%s""", self.doc.name)
 		webnotes.conn.sql("""update `tabSupport Ticket` set lead='' where lead=%s""",
 			self.doc.name)
+		
+		self.delete_events()
\ No newline at end of file
diff --git a/selling/doctype/opportunity/opportunity.py b/selling/doctype/opportunity/opportunity.py
index 75a7cd2..0540ac9 100644
--- a/selling/doctype/opportunity/opportunity.py
+++ b/selling/doctype/opportunity/opportunity.py
@@ -17,9 +17,7 @@
 from __future__ import unicode_literals
 import webnotes
 
-from webnotes.utils import add_days, cstr, getdate
-from webnotes.model import db_exists
-from webnotes.model.doc import Document, addchild
+from webnotes.utils import add_days, cstr, getdate, cint
 from webnotes.model.bean import getlist
 from webnotes import msgprint
 
@@ -34,6 +32,13 @@
 		self.fname = 'enq_details'
 		self.tname = 'Opportunity Item'
 
+		self._prev = webnotes._dict({
+			"contact_date": webnotes.conn.get_value("Opportunity", self.doc.name, "contact_date") if \
+				(not cint(self.doc.fields.get("__islocal"))) else None,
+			"contact_by": webnotes.conn.get_value("Opportunity", self.doc.name, "contact_by") if \
+				(not cint(self.doc.fields.get("__islocal"))) else None,
+		})
+
 	def onload(self):
 		self.add_communication_list()
 		
@@ -84,48 +89,34 @@
 	def on_update(self):
 		# Add to calendar
 		if self.doc.contact_date and self.doc.contact_date_ref != self.doc.contact_date:
-			if self.doc.contact_by:
-				self.add_calendar_event()
 			webnotes.conn.set(self.doc, 'contact_date_ref',self.doc.contact_date)
-		webnotes.conn.set(self.doc, 'status', 'Draft')
 
-	def add_calendar_event(self):
-		desc=''
-		user_lst =[]
+		self.add_calendar_event()
+
+	def add_calendar_event(self, opts=None):
+		if not opts:
+			opts = webnotes._dict()
+		
+		opts.description = ""
+		
 		if self.doc.customer:
 			if self.doc.contact_person:
-				desc = 'Contact '+cstr(self.doc.contact_person)
+				opts.description = 'Contact '+cstr(self.doc.contact_person)
 			else:
-				desc = 'Contact customer '+cstr(self.doc.customer)
+				opts.description = 'Contact customer '+cstr(self.doc.customer)
 		elif self.doc.lead:
 			if self.doc.contact_display:
-				desc = 'Contact '+cstr(self.doc.contact_display)
+				opts.description = 'Contact '+cstr(self.doc.contact_display)
 			else:
-				desc = 'Contact lead '+cstr(self.doc.lead)
-		desc = desc+ '. By : ' + cstr(self.doc.contact_by)
+				opts.description = 'Contact lead '+cstr(self.doc.lead)
+				
+		opts.subject = opts.description
+		opts.description += '. By : ' + cstr(self.doc.contact_by)
 		
 		if self.doc.to_discuss:
-			desc = desc+' To Discuss : ' + cstr(self.doc.to_discuss)
+			opts.description += ' To Discuss : ' + cstr(self.doc.to_discuss)
 		
-		ev = Document('Event')
-		ev.description = desc
-		ev.event_date = self.doc.contact_date
-		ev.event_hour = '10:00'
-		ev.event_type = 'Private'
-		ev.ref_type = 'Opportunity'
-		ev.ref_name = self.doc.name
-		ev.save(1)
-		
-		user_lst.append(self.doc.owner)
-		
-		chk = sql("select t1.name from `tabProfile` t1, `tabSales Person` t2 where t2.email_id = t1.name and t2.name=%s",self.doc.contact_by)
-		if chk:
-			user_lst.append(chk[0][0])
-		
-		for d in user_lst:
-			ch = addchild(ev, 'event_individuals', 'Event User')
-			ch.person = d
-			ch.save(1)
+		super(DocType, self).add_calendar_event(opts)
 
 	def set_last_contact_date(self):
 		if self.doc.contact_date_ref and self.doc.contact_date_ref != self.doc.contact_date:
@@ -159,6 +150,9 @@
 		self.set_last_contact_date()
 		self.validate_item_details()
 		self.validate_lead_cust()
+		
+		if not self.doc.status:
+			self.doc.status = "Draft"
 
 	def on_submit(self):
 		webnotes.conn.set(self.doc, 'status', 'Submitted')
@@ -180,3 +174,6 @@
 			webnotes.conn.set(self.doc, 'status', 'Opportunity Lost')
 			webnotes.conn.set(self.doc, 'order_lost_reason', arg)
 			return 'true'
+
+	def on_trash(self):
+		self.delete_events()
\ No newline at end of file
diff --git a/support/doctype/maintenance_schedule/maintenance_schedule.py b/support/doctype/maintenance_schedule/maintenance_schedule.py
index 60962b1..06c5a47 100644
--- a/support/doctype/maintenance_schedule/maintenance_schedule.py
+++ b/support/doctype/maintenance_schedule/maintenance_schedule.py
@@ -18,7 +18,7 @@
 import webnotes
 
 from webnotes.utils import add_days, cstr, getdate
-from webnotes.model.doc import Document, addchild
+from webnotes.model.doc import addchild
 from webnotes.model.bean import getlist
 from webnotes.model.code import get_obj
 from webnotes import msgprint
@@ -100,23 +100,21 @@
 
 			for key in scheduled_date:
 				if email_map[d.incharge_name]:
-					self.add_calender_event(key["scheduled_date"],email_map[d.incharge_name],d.item_code)		 
+					description = "Reference: %s, Item Code: %s and Customer: %s" % \
+						(self.doc.name, d.item_code, self.doc.customer)
+					webnotes.bean({
+						"doctype": "Event",
+						"owner": email_map[d.incharge_name] or self.doc.owner,
+						"subject": description,
+						"description": description,
+						"starts_on": key["scheduled_date"] + " 10:00:00",
+						"event_type": "Private",
+						"ref_type": self.doc.doctype,
+						"ref_name": self.doc.name
+					}).insert()
+
 		webnotes.conn.set(self.doc, 'status', 'Submitted')		
 		
-
-	def add_calender_event(self,scheduled_date,incharge_email,item_code):
-		""" Add calendar event for Maintenece Schedule in calendar of Allocated person"""
-		event = Document('Event')
-		event.owner = incharge_email
-		event.description = "Reference:%s, Item Code:%s and Customer: %s" %(self.doc.name, item_code, self.doc.customer)
-		event.event_date = scheduled_date
-		event.event_hour =	'10:00'
-		event.event_type = 'Private'
-		event.ref_type = 'Maintenance Schedule'
-		event.ref_name = self.doc.name
-		event.save(1)
-
-
 	#get schedule dates
 	#----------------------
 	def create_schedule_list(self, start_date, end_date, no_of_visit):
@@ -329,8 +327,13 @@
 			if d.serial_no:
 				self.update_amc_date(d.serial_no, '')
 		webnotes.conn.set(self.doc, 'status', 'Cancelled')
-		sql("delete from `tabEvent` where ref_type='Maintenance Schedule' and ref_name='%s' " %(self.doc.name))
+		self.delete_events()
+		
 	def on_trash(self):
-		sql("delete from `tabEvent` where ref_type='Maintenance Schedule' and ref_name='%s' " %(self.doc.name))
+		self.delete_events()
+		
+	def delete_events(self):
+		webnotes.delete_doc("Event", webnotes.conn.sql_list("""select name from `tabEvent` 
+			where ref_type=%s and ref_name=%s""", (self.doc.doctype, self.doc.name)))
 		
 
diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py
index 5d7d1a8..4c70eba 100644
--- a/utilities/transaction_base.py
+++ b/utilities/transaction_base.py
@@ -268,4 +268,38 @@
 	def validate_posting_time(self):
 		if not self.doc.posting_time:
 			self.doc.posting_time = now_datetime().strftime('%H:%M:%S')
-	
\ No newline at end of file
+			
+	def add_calendar_event(self, opts):
+		if self.doc.contact_by != cstr(self._prev.contact_by) or \
+				self.doc.contact_date != cstr(self._prev.contact_date):
+			
+			self.delete_events()
+			self._add_calendar_event(opts)
+			
+	def delete_events(self):
+		webnotes.delete_doc("Event", webnotes.conn.sql_list("""select name from `tabEvent` 
+			where ref_type=%s and ref_name=%s""", (self.doc.doctype, self.doc.name)))
+			
+	def _add_calendar_event(self, opts):
+		opts = webnotes._dict(opts)
+		
+		if self.doc.contact_date:
+			event_doclist = [{
+				"doctype": "Event",
+				"owner": opts.owner or self.doc.owner,
+				"subject": opts.subject,
+				"description": opts.description,
+				"starts_on": self.doc.contact_date + " 10:00:00",
+				"event_type": "Private",
+				"ref_type": self.doc.doctype,
+				"ref_name": self.doc.name
+			}]
+			
+			if webnotes.conn.exists("Profile", self.doc.contact_by):
+				event_doclist.append({
+					"doctype": "Event User",
+					"parentfield": "event_individuals",
+					"person": self.doc.contact_by
+				})
+			
+			webnotes.bean(event_doclist).insert()