[crm] Updated status and workflow for Lead > Opportunity > Quotation > Sales Order
diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py
index f1117ed..2816524 100644
--- a/controllers/selling_controller.py
+++ b/controllers/selling_controller.py
@@ -14,7 +14,10 @@
 	def onload_post_render(self):
 		# contact, address, item details and pos details (if applicable)
 		self.set_missing_values()
-		
+	
+	def get_sender(self, comm):
+		return webnotes.conn.get_value('Sales Email Settings', None, 'email_id')
+	
 	def set_missing_values(self, for_validate=False):
 		super(SellingController, self).set_missing_values(for_validate)
 		
diff --git a/controllers/status_updater.py b/controllers/status_updater.py
index 070f200..07b812a 100644
--- a/controllers/status_updater.py
+++ b/controllers/status_updater.py
@@ -8,6 +8,51 @@
 
 from webnotes.model.controller import DocListController
 
+status_map = {
+	"Contact": [
+		["Replied", "communication_sent"],
+		["Open", "communication_received"]
+	],
+	"Job Applicant": [
+		["Replied", "communication_sent"],
+		["Open", "communication_received"]
+	],
+	"Lead": [
+		["Replied", "communication_sent"],
+		["Converted", "has_customer"],
+		["Opportunity", "has_opportunity"],
+		["Open", "communication_received"],
+	],
+	"Opportunity": [
+		["Draft", None],
+		["Submitted", "eval:self.doc.docstatus==1"],
+		["Lost", "eval:self.doc.status=='Lost'"],
+		["Quotation", "has_quotation"],
+		["Replied", "communication_sent"],
+		["Cancelled", "eval:self.doc.docstatus==2"],
+		["Open", "communication_received"],
+	],
+	"Quotation": [
+		["Draft", None],
+		["Submitted", "eval:self.doc.docstatus==1"],
+		["Lost", "eval:self.doc.status=='Lost'"],
+		["Ordered", "has_sales_order"],
+		["Replied", "communication_sent"],
+		["Cancelled", "eval:self.doc.docstatus==2"],
+		["Open", "communication_received"],
+	],
+	"Sales Order": [
+		["Draft", None],
+		["Submitted", "eval:self.doc.docstatus==1"],
+		["Stopped", "eval:self.doc.status=='Stopped'"],
+		["Cancelled", "eval:self.doc.docstatus==2"],
+	],
+	"Support Ticket": [
+		["Replied", "communication_sent"],
+		["Open", "communication_received"]
+	],
+}
+
 class StatusUpdater(DocListController):
 	"""
 		Updates the status of the calling records
@@ -20,6 +65,39 @@
 		self.update_qty()
 		self.validate_qty()
 	
+	def set_status(self, update=False):
+		if self.doc.get("__islocal"):
+			return
+			
+		if self.doc.doctype in status_map.keys():
+			for s in status_map[self.doc.doctype].reverse():
+				if not s[1]:
+					self.doc.status = s[0]
+					break
+				elif s[1].startwith("eval:"):
+					if eval(s[1][5:]):
+						self.doc.status = s[0]
+						break
+				elif getattr(self, s[1])():
+					self.doc.status = s[0]
+					break
+		
+			if update:
+				webnotes.conn.set_value(self.doc.doctype, self.doc.name, "status", self.doc.status)
+	
+	def on_communication(self):
+		self.set_status(update=True)
+	
+	def communication_received(self):
+		last_comm = self.doclist.get({"doctype":"Communication"})[-1]
+		if last_comm:
+			return last_comm.sent_or_received == "Received"
+
+	def communication_sent(self):
+		last_comm = self.doclist.get({"doctype":"Communication"})[-1]
+		if last_comm:
+			return last_comm.sent_or_received == "Sent"
+			
 	def validate_qty(self):
 		"""
 			Validates qty at row level
diff --git a/hr/doctype/job_applicant/job_applicant.py b/hr/doctype/job_applicant/job_applicant.py
index 9bf1b96..0ab4ba8 100644
--- a/hr/doctype/job_applicant/job_applicant.py
+++ b/hr/doctype/job_applicant/job_applicant.py
@@ -11,14 +11,9 @@
 class DocType(TransactionBase):
 	def __init__(self, d, dl):
 		self.doc, self.doclist = d, dl
-		
+	
 	def get_sender(self, comm):
-		return webnotes.conn.get_value('Jobs Email Settings',None,'email_id')
-		
-	def on_communication(self, comm):
-		if webnotes.conn.get_value("Profile", extract_email_id(comm.sender), "user_type")=="System User":
-			status = "Replied"
-		else:
-			status = "Open"
-			
-		webnotes.conn.set(self.doc, 'status', status)
\ No newline at end of file
+		return webnotes.conn.get_value('Jobs Email Settings',None,'email_id')	
+	
+	def validate(self):
+		self.set_status()	
\ No newline at end of file
diff --git a/patches/october_2013/p02_set_communication_status.py b/patches/october_2013/p02_set_communication_status.py
new file mode 100644
index 0000000..8360fe6
--- /dev/null
+++ b/patches/october_2013/p02_set_communication_status.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import webnotes
+
+def execute():
+	webnotes.conn.sql("""update tabCommunication 
+		set sent_or_received= if(ifnull(recipients, '')='', "Received", "Sent")""")
\ No newline at end of file
diff --git a/patches/october_2013/p03_crm_update_status.py b/patches/october_2013/p03_crm_update_status.py
new file mode 100644
index 0000000..e5b434c
--- /dev/null
+++ b/patches/october_2013/p03_crm_update_status.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import webnotes
+
+# reason field
+
+def execute():
+	change_map = {
+		"Lead": [
+			["Lead Lost", "Lead"],
+			["Not interested", "Do Not Contact"],
+			["Opportunity Made", "Opportunity"],
+			["Contacted", "Replied"],
+			["Attempted to Contact", "Replied"],
+			["Contact in Future", "Interested"],
+		],
+		"Opportunity": [
+			["Quotation Sent", "Quotation"],
+			["Order Confirmed", "Quotation"],
+			["Opportunity Lost", "Lost"],
+		],
+		"Quotation": [
+			["Order Confirmed", "Ordered"],
+			["Order Lost", "Lost"]
+		],
+		"Support Ticket": [
+			["Waiting for Customer", "Replied"],
+			["To Reply", "Open"],
+		]
+	}	
\ No newline at end of file
diff --git a/patches/patch_list.py b/patches/patch_list.py
index e19afda..1596a28 100644
--- a/patches/patch_list.py
+++ b/patches/patch_list.py
@@ -221,4 +221,6 @@
 	"patches.september_2013.p05_fix_customer_in_pos",
 	"patches.october_2013.fix_is_cancelled_in_sle",
 	"patches.october_2013.p01_update_delivery_note_prevdocs",
+	"patches.october_2013.p02_set_communication_status",
+	"patches.october_2013.p03_crm_update_status",
 ]
\ No newline at end of file
diff --git a/selling/doctype/lead/lead.py b/selling/doctype/lead/lead.py
index 7a37446..b42a380 100644
--- a/selling/doctype/lead/lead.py
+++ b/selling/doctype/lead/lead.py
@@ -26,24 +26,9 @@
 		customer = webnotes.conn.get_value("Customer", {"lead_name": self.doc.name})
 		if customer:
 			self.doc.fields["__is_customer"] = customer
-
-	def on_communication(self, comm):
-		if comm.sender == self.get_sender(comm) or \
-			webnotes.conn.get_value("Profile", extract_email_id(comm.sender), "user_type")=="System User":
-				status = "Replied"
-		else:
-			status = "Open"
-			
-		webnotes.conn.set(self.doc, 'status', status)
-
-	def check_status(self):
-		chk = webnotes.conn.sql("select status from `tabLead` where name=%s", self.doc.name)
-		chk = chk and chk[0][0] or ''
-		return cstr(chk)
 	
 	def validate(self):
-		if self.doc.status == 'Lead Lost' and not self.doc.order_lost_reason:
-			webnotes.throw("Please Enter Lost Reason under More Info section")
+		self.set_status()
 		
 		if self.doc.source == 'Campaign' and not self.doc.campaign_name and session['user'] != 'Guest':
 			webnotes.throw("Please specify campaign name")
@@ -75,14 +60,18 @@
 				webnotes.msgprint(_("""Email Id must be unique, already exists for: """) + \
 					", ".join(items), raise_exception=True)
 
-	def get_sender(self, comm):
-		return webnotes.conn.get_value('Sales Email Settings',None,'email_id')
-
 	def on_trash(self):
 		webnotes.conn.sql("""update `tabSupport Ticket` set lead='' where lead=%s""",
 			self.doc.name)
 		
 		self.delete_events()
+		
+	def has_customer(self):
+		return webnotes.conn.get_value("Customer", {"lead_name": self.doc.name})
+		
+	def has_opportunity(self):
+		return webnotes.conn.get_value("Opportunity", {"lead": self.doc.name, "docstatus": 1,
+			"status": ["!=", "Lost"]})
 
 @webnotes.whitelist()
 def make_customer(source_name, target_doclist=None):
diff --git a/selling/doctype/lead/lead.txt b/selling/doctype/lead/lead.txt
index 6044f79..4f481b0 100644
--- a/selling/doctype/lead/lead.txt
+++ b/selling/doctype/lead/lead.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-04-10 11:45:37", 
   "docstatus": 0, 
-  "modified": "2013-10-02 14:24:30", 
+  "modified": "2013-10-03 17:24:33", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -102,7 +102,7 @@
   "fieldtype": "Column Break"
  }, 
  {
-  "default": "Open", 
+  "default": "Lead", 
   "doctype": "DocField", 
   "fieldname": "status", 
   "fieldtype": "Select", 
@@ -112,7 +112,7 @@
   "no_copy": 1, 
   "oldfieldname": "status", 
   "oldfieldtype": "Select", 
-  "options": "\nOpen\nReplied\nAttempted to Contact\nContact in Future\nContacted\nOpportunity Made\nInterested\nNot interested\nLead Lost\nConverted\nPassive", 
+  "options": "Lead\nOpen\nReplied\nOpportunity\nInterested\nConverted\nDo Not Contact", 
   "reqd": 1, 
   "search_index": 1
  }, 
@@ -336,18 +336,6 @@
  }, 
  {
   "allow_on_submit": 0, 
-  "depends_on": "eval:doc.status == 'Lead Lost'", 
-  "doctype": "DocField", 
-  "fieldname": "order_lost_reason", 
-  "fieldtype": "Link", 
-  "hidden": 0, 
-  "label": "Lost Reason", 
-  "oldfieldname": "order_lost_reason", 
-  "oldfieldtype": "Link", 
-  "options": "Quotation Lost Reason"
- }, 
- {
-  "allow_on_submit": 0, 
   "description": "Your sales person who will contact the lead in future", 
   "doctype": "DocField", 
   "fieldname": "contact_by", 
diff --git a/selling/doctype/opportunity/opportunity.js b/selling/doctype/opportunity/opportunity.js
index 25f28bf..d2b866c 100644
--- a/selling/doctype/opportunity/opportunity.js
+++ b/selling/doctype/opportunity/opportunity.js
@@ -101,20 +101,13 @@
 
 cur_frm.cscript.refresh = function(doc, cdt, cdn){
 	erpnext.hide_naming_series();
-
-	cur_frm.dashboard.reset(doc);
-	if(!doc.__islocal) {
-		if(doc.status=="Converted" || doc.status=="Order Confirmed") {
-			cur_frm.dashboard.set_headline_alert(wn._(doc.status), "alert-success", "icon-ok-sign");
-		} else if(doc.status=="Opportunity Lost") {
-			cur_frm.dashboard.set_headline_alert(wn._(doc.status), "alert-danger", "icon-exclamation-sign");
-		}
-	}
 	
 	cur_frm.clear_custom_buttons();
-	if(doc.docstatus === 1 && doc.status!=="Opportunity Lost") {
+	if(doc.docstatus === 1 && doc.status!=="Lost") {
 		cur_frm.add_custom_button('Create Quotation', cur_frm.cscript.create_quotation);
-		cur_frm.add_custom_button('Opportunity Lost', cur_frm.cscript['Declare Opportunity Lost']);
+		if(doc.status!=="Quotation") {
+			cur_frm.add_custom_button('Opportunity Lost', cur_frm.cscript['Declare Opportunity Lost']);
+		}
 		cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms);
 	}
 	
diff --git a/selling/doctype/opportunity/opportunity.py b/selling/doctype/opportunity/opportunity.py
index e0be5fa..e63ce6b 100644
--- a/selling/doctype/opportunity/opportunity.py
+++ b/selling/doctype/opportunity/opportunity.py
@@ -6,7 +6,7 @@
 
 from webnotes.utils import cstr, getdate, cint
 from webnotes.model.bean import getlist
-from webnotes import msgprint
+from webnotes import msgprint, _
 
 	
 from utilities.transaction_base import TransactionBase
@@ -67,7 +67,8 @@
 			'email_id' : contact and contact[0]['email_id'] or ''
 		}
 		return ret
-		
+			
+	
 	def on_update(self):
 		# Add to calendar
 		if self.doc.contact_date and self.doc.contact_date_ref != self.doc.contact_date:
@@ -120,6 +121,7 @@
 			msgprint("Customer is mandatory if 'Opportunity From' is selected as Customer", raise_exception=1)
 
 	def validate(self):
+		self.set_status()
 		self.set_last_contact_date()
 		self.validate_item_details()
 		self.validate_uom_is_integer("uom", "qty")
@@ -127,42 +129,29 @@
 		
 		from accounts.utils import validate_fiscal_year
 		validate_fiscal_year(self.doc.transaction_date, self.doc.fiscal_year, "Opportunity Date")
-		self.doc.status = "Draft"
 
 	def on_submit(self):
-		webnotes.conn.set(self.doc, 'status', 'Submitted')
-		if self.doc.lead and webnotes.conn.get_value("Lead", self.doc.lead, "status")!="Converted":
-			webnotes.conn.set_value("Lead", self.doc.lead, "status", "Opportunity Made")
+		if self.doc.lead:
+			webnotes.bean("Lead", self.doc.lead).get_controller().set_status(update=True)
 	
 	def on_cancel(self):
-		chk = webnotes.conn.sql("select t1.name from `tabQuotation` t1, `tabQuotation Item` t2 where t2.parent = t1.name and t1.docstatus=1 and (t1.status!='Order Lost' and t1.status!='Cancelled') and t2.prevdoc_docname = %s",self.doc.name)
-		if chk:
-			msgprint("Quotation No. "+cstr(chk[0][0])+" is submitted against this Opportunity. Thus can not be cancelled.")
-			raise Exception
-		else:
-			webnotes.conn.set(self.doc, 'status', 'Cancelled')
-			if self.doc.lead and webnotes.conn.get_value("Lead", self.doc.lead,
-				"status")!="Converted":
-					if webnotes.conn.get_value("Communication", {"parent": self.doc.lead}):
-						status = "Contacted"
-					else:
-						status = "Open"
-					
-					webnotes.conn.set_value("Lead", self.doc.lead, "status", status)
+		if self.has_quotation():
+			webnotes.throw(_("Cannot Cancel Opportunity as Quotation Exists"))
+		self.set_status(update=True)
 		
 	def declare_enquiry_lost(self,arg):
-		chk = webnotes.conn.sql("select t1.name from `tabQuotation` t1, `tabQuotation Item` t2 where t2.parent = t1.name and t1.docstatus=1 and (t1.status!='Order Lost' and t1.status!='Cancelled') and t2.prevdoc_docname = %s",self.doc.name)
-		if chk:
-			msgprint("Quotation No. "+cstr(chk[0][0])+" is submitted against this Opportunity. Thus 'Opportunity Lost' can not be declared against it.")
-			raise Exception
-		else:
-			webnotes.conn.set(self.doc, 'status', 'Opportunity Lost')
+		if not self.has_quotation():
+			webnotes.conn.set(self.doc, 'status', 'Lost')
 			webnotes.conn.set(self.doc, 'order_lost_reason', arg)
-			return 'true'
+		else:
+			webnotes.throw(_("Cannot declare as lost, because Quotation has been made."))
 
 	def on_trash(self):
 		self.delete_events()
 		
+	def has_quotation(self):
+		return webnotes.conn.get_value("Quotation Item", {"prevdoc_docname": self.doc.name, "docstatus": 1})
+		
 @webnotes.whitelist()
 def make_quotation(source_name, target_doclist=None):
 	from webnotes.model.mapper import get_mapped_doclist
diff --git a/selling/doctype/opportunity/opportunity.txt b/selling/doctype/opportunity/opportunity.txt
index 21eae5f..02caea0 100644
--- a/selling/doctype/opportunity/opportunity.txt
+++ b/selling/doctype/opportunity/opportunity.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-03-07 18:50:30", 
   "docstatus": 0, 
-  "modified": "2013-10-02 14:24:30", 
+  "modified": "2013-10-03 16:30:58", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -126,7 +126,7 @@
   "no_copy": 1, 
   "oldfieldname": "status", 
   "oldfieldtype": "Select", 
-  "options": "\nDraft\nSubmitted\nQuotation Sent\nOrder Confirmed\nOpportunity Lost\nCancelled", 
+  "options": "Draft\nSubmitted\nQuotation\nLost\nCancelled\nReplied\nOpen", 
   "read_only": 1, 
   "reqd": 1
  }, 
@@ -351,18 +351,6 @@
   "read_only": 0
  }, 
  {
-  "depends_on": "eval:!doc.__islocal", 
-  "doctype": "DocField", 
-  "fieldname": "order_lost_reason", 
-  "fieldtype": "Small Text", 
-  "label": "Quotation Lost Reason", 
-  "no_copy": 1, 
-  "oldfieldname": "order_lost_reason", 
-  "oldfieldtype": "Small Text", 
-  "read_only": 1, 
-  "report_hide": 0
- }, 
- {
   "doctype": "DocField", 
   "fieldname": "company", 
   "fieldtype": "Link", 
@@ -377,6 +365,15 @@
   "search_index": 1
  }, 
  {
+  "depends_on": "eval:!doc.__islocal", 
+  "doctype": "DocField", 
+  "fieldname": "order_lost_reason", 
+  "fieldtype": "Text", 
+  "label": "Lost Reason", 
+  "no_copy": 1, 
+  "read_only": 1
+ }, 
+ {
   "doctype": "DocField", 
   "fieldname": "column_break2", 
   "fieldtype": "Column Break", 
diff --git a/selling/doctype/quotation/quotation.js b/selling/doctype/quotation/quotation.js
index e20308f..05feed0 100644
--- a/selling/doctype/quotation/quotation.js
+++ b/selling/doctype/quotation/quotation.js
@@ -24,19 +24,10 @@
 	},
 	refresh: function(doc, dt, dn) {
 		this._super(doc, dt, dn);
-
-		cur_frm.dashboard.reset(doc);
-		if(!doc.__islocal) {
-			if(doc.status=="Converted" || doc.status=="Order Confirmed") {
-				cur_frm.dashboard.set_headline_alert(wn._(doc.status), "alert-success", "icon-ok-sign");
-			} else if(doc.status==="Order Lost") {
-				cur_frm.dashboard.set_headline_alert(wn._(doc.status), "alert-danger", "icon-exclamation-sign");
-			}
-		}
 		
-		if(doc.docstatus == 1 && doc.status!=='Order Lost') {
+		if(doc.docstatus == 1 && doc.status!=='Lost') {
 			cur_frm.add_custom_button('Make Sales Order', cur_frm.cscript['Make Sales Order']);
-			if(doc.status!=="Order Confirmed") {
+			if(doc.status!=="Ordered") {
 				cur_frm.add_custom_button('Set as Lost', cur_frm.cscript['Declare Order Lost']);
 			}
 			cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms);
diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py
index 8a3bef1..697f805 100644
--- a/selling/doctype/quotation/quotation.py
+++ b/selling/doctype/quotation/quotation.py
@@ -47,6 +47,11 @@
 						if not doc.fields.get(r):
 							doc.fields[r] = res[r]
 
+
+	def has_sales_order(self):
+		return webnotes.conn.get_value("Sales Order Item", {"prevdoc_docname": self.doc.name, "docstatus": 1})
+				
+		
 	# Re-calculates Basic Rate & amount based on Price List Selected
 	# --------------------------------------------------------------
 	def get_adj_percent(self, arg=''):
@@ -108,13 +113,7 @@
 	def validate(self):
 		super(DocType, self).validate()
 		
-		import utilities
-		if not self.doc.status:
-			self.doc.status = "Draft"
-		else:
-			utilities.validate_status(self.doc.status, ["Draft", "Submitted", 
-				"Order Confirmed", "Order Lost", "Cancelled"])
-
+		self.set_status()
 		self.set_last_contact_date()
 		self.validate_order_type()
 		self.validate_for_items()
@@ -125,42 +124,22 @@
 		sales_com_obj.check_active_sales_items(self)
 		sales_com_obj.validate_max_discount(self,'quotation_details')
 		sales_com_obj.check_conversion_rate(self)
-		
-
-	def on_update(self):
-		# Set Quotation Status
-		webnotes.conn.set(self.doc, 'status', 'Draft')
-	
+			
 	#update enquiry
 	#------------------
-	def update_enquiry(self, flag):
-		prevdoc=''
-		for d in getlist(self.doclist, 'quotation_details'):
-			if d.prevdoc_docname:
-				prevdoc = d.prevdoc_docname
-		
-		if prevdoc:
-			if flag == 'submit': #on submit
-				webnotes.conn.sql("update `tabOpportunity` set status = 'Quotation Sent' where name = %s", prevdoc)
-			elif flag == 'cancel': #on cancel
-				webnotes.conn.sql("update `tabOpportunity` set status = 'Open' where name = %s", prevdoc)
-			elif flag == 'order lost': #order lost
-				webnotes.conn.sql("update `tabOpportunity` set status = 'Opportunity Lost' where name=%s", prevdoc)
-			elif flag == 'order confirm': #order confirm
-				webnotes.conn.sql("update `tabOpportunity` set status='Order Confirmed' where name=%s", prevdoc)
+	def update_opportunity(self):
+		for opportunity in self.doclist.get_distinct_values("prevdoc_docname"):
+			webnotes.bean("Opportunity", opportunity).get_controller().set_status(update=True)
 	
 	# declare as order lost
 	#-------------------------
 	def declare_order_lost(self, arg):
-		chk = webnotes.conn.sql("select t1.name from `tabSales Order` t1, `tabSales Order Item` t2 where t2.parent = t1.name and t1.docstatus=1 and t2.prevdoc_docname = %s",self.doc.name)
-		if chk:
-			msgprint("Sales Order No. "+cstr(chk[0][0])+" is submitted against this Quotation. Thus 'Order Lost' can not be declared against it.")
-			raise Exception
-		else:
-			webnotes.conn.set(self.doc, 'status', 'Order Lost')
+		if not self.has_sales_order():
+			webnotes.conn.set(self.doc, 'status', 'Lost')
 			webnotes.conn.set(self.doc, 'order_lost_reason', arg)
-			self.update_enquiry('order lost')
-			return 'true'
+			self.update_opportunity()
+		else:
+			webnotes.throw(_("Cannot set as Lost as Sales Order is made."))
 	
 	#check if value entered in item table
 	#--------------------------------------
@@ -176,21 +155,17 @@
 		
 		# Check for Approving Authority
 		get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.grand_total, self)
-
-		# Set Quotation Status
-		webnotes.conn.set(self.doc, 'status', 'Submitted')
-		
+			
 		#update enquiry status
-		self.update_enquiry('submit')
+		self.update_opportunity()
 		
 		
 # ON CANCEL
 # ==========================================================================
 	def on_cancel(self):
 		#update enquiry status
-		self.update_enquiry('cancel')
-		
-		webnotes.conn.set(self.doc,'status','Cancelled')
+		self.set_status()
+		self.update_opportunity()
 			
 # Print other charges
 # ===========================================================================
@@ -202,6 +177,7 @@
 			lst1.append(d.total)
 			print_lst.append(lst1)
 		return print_lst
+		
 	
 @webnotes.whitelist()
 def make_sales_order(source_name, target_doclist=None):
diff --git a/selling/doctype/quotation/quotation.txt b/selling/doctype/quotation/quotation.txt
index 200627f..8a8b24b 100644
--- a/selling/doctype/quotation/quotation.txt
+++ b/selling/doctype/quotation/quotation.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-05-24 19:29:08", 
   "docstatus": 0, 
-  "modified": "2013-10-02 14:24:35", 
+  "modified": "2013-10-03 16:31:55", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -734,7 +734,7 @@
   "no_copy": 1, 
   "oldfieldname": "status", 
   "oldfieldtype": "Select", 
-  "options": "\nDraft\nSubmitted\nOrder Confirmed\nOrder Lost\nCancelled", 
+  "options": "Draft\nSubmitted\nOrdered\nLost\nCancelled", 
   "print_hide": 1, 
   "read_only": 1, 
   "reqd": 1, 
diff --git a/selling/doctype/sales_order/sales_order.js b/selling/doctype/sales_order/sales_order.js
index 0c26179..bf23b9c 100644
--- a/selling/doctype/sales_order/sales_order.js
+++ b/selling/doctype/sales_order/sales_order.js
@@ -66,7 +66,7 @@
 						source_doctype: "Quotation",
 						get_query_filters: {
 							docstatus: 1,
-							status: ["!=", "Order Lost"],
+							status: ["!=", "Lost"],
 							order_type: cur_frm.doc.order_type,
 							customer: cur_frm.doc.customer || undefined,
 							company: cur_frm.doc.company
diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py
index 8fc728f..d3ac7ad 100644
--- a/selling/doctype/sales_order/sales_order.py
+++ b/selling/doctype/sales_order/sales_order.py
@@ -165,36 +165,20 @@
 		})
 
 		
-	def check_prev_docstatus(self):
-		for d in getlist(self.doclist, 'sales_order_details'):
-			cancel_quo = webnotes.conn.sql("select name from `tabQuotation` where docstatus = 2 and name = '%s'" % d.prevdoc_docname)
-			if cancel_quo:
-				msgprint("Quotation :" + cstr(cancel_quo[0][0]) + " is already cancelled !")
-				raise Exception , "Validation Error. "
-	
 	def update_enquiry_status(self, prevdoc, flag):
 		enq = webnotes.conn.sql("select t2.prevdoc_docname from `tabQuotation` t1, `tabQuotation Item` t2 where t2.parent = t1.name and t1.name=%s", prevdoc)
 		if enq:
 			webnotes.conn.sql("update `tabOpportunity` set status = %s where name=%s",(flag,enq[0][0]))
 
-	def update_prevdoc_status(self, flag):
-		for d in getlist(self.doclist, 'sales_order_details'):
-			if d.prevdoc_docname:
-				if flag=='submit':
-					webnotes.conn.sql("update `tabQuotation` set status = 'Order Confirmed' where name=%s",d.prevdoc_docname)
-					
-					#update enquiry
-					self.update_enquiry_status(d.prevdoc_docname, 'Order Confirmed')
-				elif flag == 'cancel':
-					chk = webnotes.conn.sql("select t1.name from `tabSales Order` t1, `tabSales Order Item` t2 where t2.parent = t1.name and t2.prevdoc_docname=%s and t1.name!=%s and t1.docstatus=1", (d.prevdoc_docname,self.doc.name))
-					if not chk:
-						webnotes.conn.sql("update `tabQuotation` set status = 'Submitted' where name=%s",d.prevdoc_docname)
-						
-						#update enquiry
-						self.update_enquiry_status(d.prevdoc_docname, 'Quotation Sent')
+	def update_prevdoc_status(self, flag):				
+		for quotation in self.doclist.get_distinct_values("prevdoc_docname"):
+			bean = webnotes.bean("Quotation", quotation)
+			if bean.doc.docstatus==2:
+				webnotes.throw(d.prevdoc_docname + ": " + webnotes._("Quotation is cancelled."))
+				
+			bean.get_controller().set_status(update=True)
 
 	def on_submit(self):
-		self.check_prev_docstatus()		
 		self.update_stock_ledger(update_stock = 1)
 
 		get_obj('Sales Common').check_credit(self,self.doc.grand_total)
diff --git a/support/doctype/support_ticket/get_support_mails.py b/support/doctype/support_ticket/get_support_mails.py
index 4dcb59e..4b61352 100644
--- a/support/doctype/support_ticket/get_support_mails.py
+++ b/support/doctype/support_ticket/get_support_mails.py
@@ -54,7 +54,7 @@
 		
 	def auto_close_tickets(self):
 		webnotes.conn.sql("""update `tabSupport Ticket` set status = 'Closed' 
-			where status = 'Waiting for Customer' 
+			where status = 'Replied' 
 			and date_sub(curdate(),interval 15 Day) > modified""")
 
 def get_support_mails():
diff --git a/support/doctype/support_ticket/support_ticket.py b/support/doctype/support_ticket/support_ticket.py
index bf2a9fb..eb68ff3 100644
--- a/support/doctype/support_ticket/support_ticket.py
+++ b/support/doctype/support_ticket/support_ticket.py
@@ -14,7 +14,7 @@
 	
 	def get_sender(self, comm):
 		return webnotes.conn.get_value('Email Settings',None,'support_email')
-	
+
 	def get_subject(self, comm):
 		return '[' + self.doc.name + '] ' + (comm.subject or 'No Subject Specified')
 	
@@ -35,16 +35,7 @@
 		if self.doc.status == "Closed":
 			from webnotes.widgets.form.assign_to import clear
 			clear(self.doc.doctype, self.doc.name)
-		
-	def on_communication(self, comm):
-		if comm.sender == self.get_sender(comm) or \
-			webnotes.conn.get_value("Profile", extract_email_id(comm.sender), "user_type")=="System User":
-				self.doc.status = "Waiting for Customer"
-		else:
-			self.doc.status = "Open"
-		self.update_status()
-		self.doc.save()
-		
+				
 	def set_lead_contact(self, email_id):
 		import email.utils
 		email_id = email.utils.parseaddr(email_id)
diff --git a/support/doctype/support_ticket/support_ticket.txt b/support/doctype/support_ticket/support_ticket.txt
index 9f385b2..76d9dcf 100644
--- a/support/doctype/support_ticket/support_ticket.txt
+++ b/support/doctype/support_ticket/support_ticket.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-02-01 10:36:25", 
   "docstatus": 0, 
-  "modified": "2013-09-10 10:54:02", 
+  "modified": "2013-10-03 16:45:41", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -71,7 +71,7 @@
   "no_copy": 1, 
   "oldfieldname": "status", 
   "oldfieldtype": "Select", 
-  "options": "\nOpen\nTo Reply\nWaiting for Customer\nHold\nClosed", 
+  "options": "Open\nReplied\nHold\nClosed", 
   "read_only": 0, 
   "reqd": 0, 
   "search_index": 1
diff --git a/utilities/doctype/contact/contact.py b/utilities/doctype/contact/contact.py
index 58437f1..db233fb 100644
--- a/utilities/doctype/contact/contact.py
+++ b/utilities/doctype/contact/contact.py
@@ -12,14 +12,6 @@
 		self.doc = doc
 		self.doclist = doclist
 
-	def on_communication(self, comm):
-		if webnotes.conn.get_value("Profile", extract_email_id(comm.sender), "user_type")=="System User":
-			status = "Replied"
-		else:
-			status = "Open"
-			
-		webnotes.conn.set(self.doc, 'status', status)
-
 	def autoname(self):
 		# concat first and last name
 		self.doc.name = " ".join(filter(None, 
@@ -32,6 +24,7 @@
 				break
 		
 	def validate(self):
+		self.set_status()
 		self.validate_primary_contact()
 
 	def validate_primary_contact(self):
diff --git a/utilities/doctype/contact/contact.txt b/utilities/doctype/contact/contact.txt
index 92dcf2e..db23410 100644
--- a/utilities/doctype/contact/contact.txt
+++ b/utilities/doctype/contact/contact.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-01-10 16:34:32", 
   "docstatus": 0, 
-  "modified": "2013-09-10 10:50:27", 
+  "modified": "2013-10-03 16:44:08", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -70,11 +70,12 @@
   "fieldtype": "Column Break"
  }, 
  {
+  "default": "Passive", 
   "doctype": "DocField", 
   "fieldname": "status", 
   "fieldtype": "Select", 
   "label": "Status", 
-  "options": "\nOpen\nReplied"
+  "options": "Passive\nOpen\nReplied"
  }, 
  {
   "doctype": "DocField",