Merge branch 'master' of github.com:webnotes/erpnext
diff --git a/accounts/page/accounts_home/accounts_home.html b/accounts/page/accounts_home/accounts_home.html
index 498f811..498b214 100644
--- a/accounts/page/accounts_home/accounts_home.html
+++ b/accounts/page/accounts_home/accounts_home.html
@@ -18,7 +18,11 @@
 			<br>
 			<h5><a href="#Accounts Browser/Cost Center">Chart of Cost Centers</a></h5>
 			<p class="help">Structure cost centers</p>
-			<br>
+		</div>
+		<div style="clear: both"></div>
+		<hr>
+		<h4>Reports</h4>
+		<div style="width: 48%; float: left;">
 			<h5><a href="#general-ledger" 
 				data-role="Analytics, Accounts Manager, Accounts User">
 					General Ledger</a>
@@ -29,16 +33,16 @@
 				data-role="Analytics, Accounts Manager, Accounts User">Trial Balance</a>
 			</h5>
 			<p class="help">Tree view of all Account balances</p>
-			<br>
+		</div>
+		<div style="width: 48%; float: right;">
 			<h5><a href="#financial-analytics" 
 				data-role="Analytics, Accounts Manager, Accounts User">
 					Financial Analytics</a>
 			</h5>
 			<p class="help">Visual representation of financial trends</p>
 		</div>
-		<div style="clear: both"></div>
+		<div style="clear: both;"></div>
 		<hr>
-		<h3>Reports</h3>
 		<div class="reports-list"></div>
 	</div>
 	<div class="layout-side-section">
diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py
index 85a11ed..f589b67 100644
--- a/buying/doctype/purchase_order/purchase_order.py
+++ b/buying/doctype/purchase_order/purchase_order.py
@@ -128,9 +128,14 @@
 	# Validate
 	def validate(self):
 		self.validate_fiscal_year()
-		# Step 1:=> set status as "Draft"
-		webnotes.conn.set(self.doc, 'status', 'Draft')
-		
+
+		if not self.doc.status:
+			self.doc.status = "Draft"
+
+		import utilities
+		utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped", 
+			"Cancelled"])
+
 		# Step 2:=> get Purchase Common Obj
 		pc_obj = get_obj(dt='Purchase Common')
 		
diff --git a/buying/doctype/purchase_request/purchase_request.py b/buying/doctype/purchase_request/purchase_request.py
index 3f7f932..0a7ae19 100644
--- a/buying/doctype/purchase_request/purchase_request.py
+++ b/buying/doctype/purchase_request/purchase_request.py
@@ -141,8 +141,12 @@
 		self.validate_schedule_date()
 		self.validate_fiscal_year()
 		
-		# set status as "Draft"
-		webnotes.conn.set(self.doc, 'status', 'Draft')
+		if not self.doc.status:
+			self.doc.status = "Draft"
+
+		import utilities
+		utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped", 
+			"Cancelled"])
 
 		# Get Purchase Common Obj
 		pc_obj = get_obj(dt='Purchase Common')
diff --git a/buying/doctype/supplier_quotation/supplier_quotation.py b/buying/doctype/supplier_quotation/supplier_quotation.py
index cac4bab..9e62e13 100644
--- a/buying/doctype/supplier_quotation/supplier_quotation.py
+++ b/buying/doctype/supplier_quotation/supplier_quotation.py
@@ -30,10 +30,16 @@
 		self.doc.name = make_autoname(self.doc.naming_series + ".#####")
 		
 	def validate(self):
+		if not self.doc.status:
+			self.doc.status = "Draft"
+
+		import utilities
+		utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped", 
+			"Cancelled"])
+		
 		self.validate_fiscal_year()
 		self.validate_common()
 		self.set_in_words()
-		self.doc.status = "Draft"
 
 	def on_submit(self):
 		purchase_controller = webnotes.get_obj("Purchase Common")
diff --git a/buying/page/buying_home/buying_home.html b/buying/page/buying_home/buying_home.html
index 68544fb..785abd5 100644
--- a/buying/page/buying_home/buying_home.html
+++ b/buying/page/buying_home/buying_home.html
@@ -23,15 +23,20 @@
 			<br>
 			<h5><a href="#List/Address">Address</a></h5>
 			<p class="help">Address Master</p>
-			<br>
+		</div>
+		<div style="clear: both"></div>
+		<hr>
+		<h4>Reports</h4>
+		<div style="width: 48%; float: left;">
 			<h5><a href="#purchase-analytics" data-role="Analytics, Purchase Manager">
 					Purchase Analytics</a>
 			</h5>
 			<p class="help">Purchase trends based on Purchase Invoice</p>
 		</div>
-		<div style="clear: both"></div>
+		<div style="width: 48%; float: right;">
+		</div>
+		<div style="clear: both;"></div>
 		<hr>
-		<h3>Reports</h3>
 		<div class="reports-list"></div>
 	</div>
 	<div class="layout-side-section">
diff --git a/home/page/latest_updates/latest_updates.js b/home/page/latest_updates/latest_updates.js
index b9296f2..304947e 100644
--- a/home/page/latest_updates/latest_updates.js
+++ b/home/page/latest_updates/latest_updates.js
@@ -1,7 +1,9 @@
 erpnext.updates = [
 	["28th December 2012", [
 		"Workflow: Added System for Multi-level approval before Submission. \
-			<br>See video at <a href='https://www.youtube.com/watch?v=zuGv59_wJKw' target='_blank'>https://www.youtube.com/watch?v=zuGv59_wJKw</a>.",
+			<br>See video at <a href='https://www.youtube.com/watch?v=zuGv59_wJKw' \
+			target='_blank'>https://www.youtube.com/watch?v=zuGv59_wJKw</a>.",
+		"Stock Level Report: New report to see available and estimated qty of stock",
 	]],
 	["27th December 2012", [
 		"Website: Added auto-generated Contact Us and About Us Pages",
diff --git a/hr/doctype/appraisal/appraisal.py b/hr/doctype/appraisal/appraisal.py
index b4b0e4e..82fb77b 100644
--- a/hr/doctype/appraisal/appraisal.py
+++ b/hr/doctype/appraisal/appraisal.py
@@ -57,6 +57,7 @@
 	def validate(self):
 		if not self.doc.status:
 			self.doc.status = "Draft"
+
 		self.validate_dates()
 		self.validate_existing_appraisal()
 		self.calculate_total()
diff --git a/hr/doctype/attendance/attendance.py b/hr/doctype/attendance/attendance.py
index d3daeb1..d1ebc97 100644
--- a/hr/doctype/attendance/attendance.py
+++ b/hr/doctype/attendance/attendance.py
@@ -8,11 +8,11 @@
 # 
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
 # 
 # You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
 
 from __future__ import unicode_literals
 import webnotes
@@ -28,79 +28,81 @@
 
 
 class DocType:
-  def __init__(self, doc, doclist=[]):
-    self.doc = doc
-    self.doclist = doclist
-    
-  #autoname function
-  def autoname(self):
-    self.doc.name = make_autoname(self.doc.naming_series+'.#####')
-  
-  #get employee name based on employee id selected 
-  def get_emp_name(self):
-    emp_nm = sql("select employee_name from `tabEmployee` where name=%s", self.doc.employee)
+	def __init__(self, doc, doclist=[]):
+		self.doc = doc
+		self.doclist = doclist
+		
+	#autoname function
+	def autoname(self):
+		self.doc.name = make_autoname(self.doc.naming_series+'.#####')
+	
+	#get employee name based on employee id selected 
+	def get_emp_name(self):
+		emp_nm = sql("select employee_name from `tabEmployee` where name=%s", self.doc.employee)
 
-    #this is done because sometimes user entered wrong employee name while uploading employee attendance
-    webnotes.conn.set(self.doc, 'employee_name', emp_nm and emp_nm[0][0] or '')
+		#this is done because sometimes user entered wrong employee name while uploading employee attendance
+		webnotes.conn.set(self.doc, 'employee_name', emp_nm and emp_nm[0][0] or '')
 
-    ret = { 'employee_name' : emp_nm and emp_nm[0][0] or ''}
-    return ret
-  
-  #validation for duplicate record
-  def validate_duplicate_record(self):   
-    res = sql("select name from `tabAttendance` where employee = '%s' and att_date = '%s' and not name = '%s' and docstatus = 1"%(self.doc.employee,self.doc.att_date, self.doc.name))
-    if res:
-      msgprint("Employee's attendance already marked.")
-      raise Exception
-      
-  
-  #check for already record present in leave transaction for same date
-  def check_leave_record(self):
-    if self.doc.status == 'Present':
-      chk = sql("select name from `tabLeave Application` where employee=%s and (from_date <= %s and to_date >= %s) and docstatus!=2", (self.doc.employee, self.doc.att_date, self.doc.att_date))
-      if chk:
-        msgprint("Leave Application created for employee "+self.doc.employee+" whom you are trying to mark as 'Present' ")
-        raise Exception
-  
-         
-  def validate_fiscal_year(self):
-    fy=sql("select year_start_date from `tabFiscal Year` where name='%s'"% self.doc.fiscal_year)
-    ysd=fy and fy[0][0] or ""
-    yed=add_days(str(ysd),365)
-    if str(self.doc.att_date) < str(ysd) or str(self.doc.att_date) > str(yed):
-      msgprint("'%s' Not Within The Fiscal Year selected"%(self.doc.att_date))
-      raise Exception
-  
-  def validate_att_date(self):
-    import datetime
-    if getdate(self.doc.att_date)>getdate(datetime.datetime.now().date().strftime('%Y-%m-%d')):
-      msgprint("Attendance can not be marked for future dates")
-      raise Exception
+		ret = { 'employee_name' : emp_nm and emp_nm[0][0] or ''}
+		return ret
+	
+	#validation for duplicate record
+	def validate_duplicate_record(self):	 
+		res = sql("select name from `tabAttendance` where employee = '%s' and att_date = '%s' and not name = '%s' and docstatus = 1"%(self.doc.employee,self.doc.att_date, self.doc.name))
+		if res:
+			msgprint("Employee's attendance already marked.")
+			raise Exception
+			
+	
+	#check for already record present in leave transaction for same date
+	def check_leave_record(self):
+		if self.doc.status == 'Present':
+			chk = sql("select name from `tabLeave Application` where employee=%s and (from_date <= %s and to_date >= %s) and docstatus!=2", (self.doc.employee, self.doc.att_date, self.doc.att_date))
+			if chk:
+				msgprint("Leave Application created for employee "+self.doc.employee+" whom you are trying to mark as 'Present' ")
+				raise Exception
+	
+				 
+	def validate_fiscal_year(self):
+		fy=sql("select year_start_date from `tabFiscal Year` where name='%s'" % \
+			self.doc.fiscal_year)
+		ysd=fy and fy[0][0] or ""
+		yed=add_days(str(ysd),365)
+		if str(self.doc.att_date) < str(ysd) or str(self.doc.att_date) > str(yed):
+			msgprint("'%s' Not Within The Fiscal Year selected"%(self.doc.att_date))
+			raise Exception
+	
+	def validate_att_date(self):
+		import datetime
+		if getdate(self.doc.att_date)>getdate(datetime.datetime.now().date().strftime('%Y-%m-%d')):
+			msgprint("Attendance can not be marked for future dates")
+			raise Exception
 
-  # Validate employee
-  #-------------------
-  def validate_employee(self):
-    emp = sql("select name, status from `tabEmployee` where name = '%s'" % self.doc.employee)
-    if not emp:
-      msgprint("Employee: %s does not exists in the system" % self.doc.employee, raise_exception=1)
-    elif emp[0][1] != 'Active':
-      msgprint("Employee: %s is not Active" % self.doc.employee, raise_exception=1)
-      
-  # validate...
-  def validate(self):
-    self.validate_fiscal_year()
-    self.validate_att_date()
-    self.validate_duplicate_record()
-    #self.validate_status()
-    self.check_leave_record()
-    
-  def on_update(self):
-    #self.validate()
-    
-    #this is done because sometimes user entered wrong employee name while uploading employee attendance
-    x=self.get_emp_name()
+	# Validate employee
+	#-------------------
+	def validate_employee(self):
+		emp = sql("select name, status from `tabEmployee` where name = '%s'" % self.doc.employee)
+		if not emp:
+			msgprint("Employee: %s does not exists in the system" % self.doc.employee, raise_exception=1)
+		elif emp[0][1] != 'Active':
+			msgprint("Employee: %s is not Active" % self.doc.employee, raise_exception=1)
+			
+	def validate(self):
+		import utilities
+		utilities.validate_status(self.doc.status, ["Present", "Absent", "Half Day"])
 
-  def on_submit(self):
-    #this is done because while uploading attendance chnage docstatus to 1 i.e. submit
-    webnotes.conn.set(self.doc,'docstatus',1)
-    pass
+		self.validate_fiscal_year()
+		self.validate_att_date()
+		self.validate_duplicate_record()
+		self.check_leave_record()
+		
+	def on_update(self):
+		#self.validate()
+		
+		#this is done because sometimes user entered wrong employee name while uploading employee attendance
+		x=self.get_emp_name()
+
+	def on_submit(self):
+		#this is done because while uploading attendance chnage docstatus to 1 i.e. submit
+		webnotes.conn.set(self.doc,'docstatus',1)
+		pass
diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py
index c0f7be3..ab3f842 100644
--- a/hr/doctype/employee/employee.py
+++ b/hr/doctype/employee/employee.py
@@ -19,7 +19,7 @@
 
 from webnotes.utils import getdate, validate_email_add
 from webnotes.model.doc import make_autoname
-from webnotes import msgprint
+from webnotes import msgprint, _
 
 sql = webnotes.conn.sql
 
@@ -39,6 +39,16 @@
 				self.doc.name = make_autoname(self.doc.employee_number)
 
 		self.doc.employee = self.doc.name
+
+	def validate(self):
+		import utilities
+		utilities.validate_status(self.doc.status, ["Active", "Left"])
+
+		self.doc.employee = self.doc.name
+		self.validate_date()
+		self.validate_email()
+		self.validate_name()
+		self.validate_status()
 				
 	def get_retirement_date(self):		
 		import datetime
@@ -52,13 +62,6 @@
 		ret_sal_struct=sql("select name from `tabSalary Structure` where employee='%s' and is_active = 'Yes' and docstatus!= 2"%nm)
 		return ret_sal_struct and ret_sal_struct[0][0] or ''
 
-	def validate(self):
-		self.doc.employee = self.doc.name
-		self.validate_date()
-		self.validate_email()
-		self.validate_name()
-		self.validate_status()
-	
 	def on_update(self):
 		self.update_user_default()
 	
diff --git a/hr/doctype/expense_claim/expense_claim.py b/hr/doctype/expense_claim/expense_claim.py
index b3a132e..2ba53aa 100644
--- a/hr/doctype/expense_claim/expense_claim.py
+++ b/hr/doctype/expense_claim/expense_claim.py
@@ -33,9 +33,8 @@
 		# if self.doc.exp_approver == self.doc.owner:
 		# 	webnotes.msgprint("""Self Approval is not allowed.""", raise_exception=1)
 
-		if self.doc.status not in ("Draft", "Approved", "Rejected"):
-			webnotes.msgprint("Status must be one of 'Draft', 'Approved' or 'Rejected'", 
-				raise_exception=True)
+		import utilities
+		utilities.validate_status(self.doc.status, ["Draft", "Approved", "Rejected"])
 
 		self.validate_fiscal_year()
 		self.validate_exp_details()
diff --git a/hr/doctype/leave_application/leave_application.py b/hr/doctype/leave_application/leave_application.py
index e61f7b5..ebefc0e 100755
--- a/hr/doctype/leave_application/leave_application.py
+++ b/hr/doctype/leave_application/leave_application.py
@@ -33,9 +33,8 @@
 	def validate(self):
 		# if self.doc.leave_approver == self.doc.owner:
 		# 	webnotes.msgprint("""Self Approval is not allowed.""", raise_exception=1)
-		if self.doc.status not in ("Open", "Approved", "Rejected"):
-			webnotes.msgprint("Status must be one of 'Open', 'Approved' or 'Rejected'", 
-				raise_exception=True)
+		import utilities
+		utilities.validate_status(self.doc.status, ["Open", "Approved", "Rejected"])
 
 		self.validate_to_date()
 		self.validate_balance_leaves()
diff --git a/hr/doctype/salary_structure/salary_structure.py b/hr/doctype/salary_structure/salary_structure.py
index f310b7b..9c5ad24 100644
--- a/hr/doctype/salary_structure/salary_structure.py
+++ b/hr/doctype/salary_structure/salary_structure.py
@@ -8,11 +8,11 @@
 # 
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
 # GNU General Public License for more details.
 # 
 # You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# along with this program.	If not, see <http://www.gnu.org/licenses/>.
 
 from __future__ import unicode_literals
 import webnotes
@@ -28,87 +28,86 @@
 
 
 class DocType:
-  #init function
-  def __init__(self,doc,doclist=[]):
-    self.doc = doc
-    self.doclist = doclist
+	#init function
+	def __init__(self,doc,doclist=[]):
+		self.doc = doc
+		self.doclist = doclist
  
-  #autoname function
-  #---------------------------------------------------------
-  def autoname(self):
-    self.doc.name = make_autoname(self.doc.employee + '/.SST' + '/.#####')
-  
-  #get employee details
-  #---------------------------------------------------------
-  def get_employee_details(self):
-    ret = {}
-    det = sql("select employee_name, branch, designation, department, grade from `tabEmployee` where name = '%s'" %self.doc.employee)
-    if det:
-      ret = {
-        'employee_name'  : cstr(det[0][0]),
-        'branch'         : cstr(det[0][1]),
-        'designation'    : cstr(det[0][2]),
-        'department'     : cstr(det[0][3]),
-        'grade'          : cstr(det[0][4]),
-        'backup_employee': cstr(self.doc.employee)
-      }
-    return ret
-    
+	#autoname function
+	#---------------------------------------------------------
+	def autoname(self):
+		self.doc.name = make_autoname(self.doc.employee + '/.SST' + '/.#####')
+	
+	#get employee details
+	#---------------------------------------------------------
+	def get_employee_details(self):
+		ret = {}
+		det = sql("select employee_name, branch, designation, department, grade from `tabEmployee` where name = '%s'" %self.doc.employee)
+		if det:
+			ret = {
+				'employee_name': cstr(det[0][0]),
+				'branch': cstr(det[0][1]),
+				'designation': cstr(det[0][2]),
+				'department': cstr(det[0][3]),
+				'grade': cstr(det[0][4]),
+				'backup_employee': cstr(self.doc.employee)
+			}
+		return ret
+		
 
-  # Set Salary structure field values
-  #---------------------------------------------------------
-  def get_ss_values(self,employee):
-    basic_info = sql("select bank_name, bank_ac_no, esic_card_no, pf_number from `tabEmployee` where name ='%s'" % employee)
-    ret = {'bank_name'   : basic_info and basic_info[0][0] or '',
-            'bank_ac_no'  : basic_info and basic_info[0][1] or '',
-            'esic_no'     : basic_info and basic_info[0][2] or '',
-            'pf_no'       : basic_info and basic_info[0][3] or ''}
-    return ret
-   
-  # Make earning and deduction table    
-  #---------------------------------------------------------
-  def make_table(self, doct_name, tab_fname, tab_name):
-    list1 = sql("select name from `tab%s` where docstatus != 2" % doct_name)
-    for li in list1:
-      child = addchild(self.doc, tab_fname, tab_name, self.doclist)
-      if(tab_fname == 'earning_details'):
-        child.e_type = cstr(li[0])
-        child.modified_value = 0
-      elif(tab_fname == 'deduction_details'):
-        child.d_type = cstr(li[0])
-        child.d_modified_amt = 0
-    
-  # add earning & deduction types to table 
-  #---------------------------------------------------------   
-  def make_earn_ded_table(self):           
-    #Earning List
-    self.make_table('Earning Type','earning_details','Salary Structure Earning')
-    
-    #Deduction List
-    self.make_table('Deduction Type','deduction_details', 'Salary Structure Deduction')
-    
+	# Set Salary structure field values
+	#---------------------------------------------------------
+	def get_ss_values(self,employee):
+		basic_info = sql("select bank_name, bank_ac_no, esic_card_no, pf_number from `tabEmployee` where name ='%s'" % employee)
+		ret = {'bank_name': basic_info and basic_info[0][0] or '',
+			'bank_ac_no': basic_info and basic_info[0][1] or '',
+			'esic_no': basic_info and basic_info[0][2] or '',
+			'pf_no': basic_info and basic_info[0][3] or ''}
+		return ret
+	 
+	# Make earning and deduction table		
+	#---------------------------------------------------------
+	def make_table(self, doct_name, tab_fname, tab_name):
+		list1 = sql("select name from `tab%s` where docstatus != 2" % doct_name)
+		for li in list1:
+			child = addchild(self.doc, tab_fname, tab_name, self.doclist)
+			if(tab_fname == 'earning_details'):
+				child.e_type = cstr(li[0])
+				child.modified_value = 0
+			elif(tab_fname == 'deduction_details'):
+				child.d_type = cstr(li[0])
+				child.d_modified_amt = 0
+		
+	# add earning & deduction types to table 
+	#---------------------------------------------------------	 
+	def make_earn_ded_table(self):					 
+		#Earning List
+		self.make_table('Earning Type','earning_details','Salary Structure Earning')
+		
+		#Deduction List
+		self.make_table('Deduction Type','deduction_details', 
+			'Salary Structure Deduction')
+		
 
-  # Check if another active ss exists
-  #---------------------------------------------------------
-  def check_existing(self):
-    ret = sql("select name from `tabSalary Structure` where is_active = 'Yes' and employee = '%s' and name!='%s'" %(self.doc.employee,self.doc.name))
-    if ret and self.doc.is_active=='Yes':
-      msgprint("Another Salary Structure '%s' is active for employee '%s'. Please make its status 'Inactive' to proceed."%(cstr(ret), self.doc.employee))
-      raise Exception
+	# Check if another active ss exists
+	#---------------------------------------------------------
+	def check_existing(self):
+		ret = sql("select name from `tabSalary Structure` where is_active = 'Yes' and employee = '%s' and name!='%s'" %(self.doc.employee,self.doc.name))
+		if ret and self.doc.is_active=='Yes':
+			msgprint("Another Salary Structure '%s' is active for employee '%s'. Please make its status 'Inactive' to proceed."%(cstr(ret), self.doc.employee))
+			raise Exception
 
-  # Validate net pay
-  #---------------------------------------------------------
-  def validate_net_pay(self):
-    if flt(self.doc.net_pay) < 0:
-      msgprint("Net pay can not be negative")
-      raise Exception
-    elif flt(self.doc.net_pay) > flt(self.doc.ctc):
-      msgprint("Net pay can not be greater than CTC")
-      raise Exception      
+	# Validate net pay
+	#---------------------------------------------------------
+	def validate_net_pay(self):
+		if flt(self.doc.net_pay) < 0:
+			msgprint("Net pay can not be negative")
+			raise Exception
+		elif flt(self.doc.net_pay) > flt(self.doc.ctc):
+			msgprint("Net pay can not be greater than CTC")
+			raise Exception			
 
-  # Validate
-  #---------------------------------------------------------
-  def validate(self):   
-    self.check_existing()
-    self.validate_net_pay()
+	def validate(self):	 
+		self.check_existing()
+		self.validate_net_pay()
 
diff --git a/hr/page/hr_home/hr_home.html b/hr/page/hr_home/hr_home.html
index b7c91bb..9d6875a 100644
--- a/hr/page/hr_home/hr_home.html
+++ b/hr/page/hr_home/hr_home.html
@@ -23,7 +23,7 @@
 		</div>
 		<div style="clear: both"></div>
 		<hr>
-		<h3>Reports</h3>
+		<h4>Reports</h4>
 		<div class="reports-list"></div>
 	</div>
 	<div class="layout-side-section">
diff --git a/manufacturing/doctype/production_order/production_order.py b/manufacturing/doctype/production_order/production_order.py
index 3ba368e..9a09494 100644
--- a/manufacturing/doctype/production_order/production_order.py
+++ b/manufacturing/doctype/production_order/production_order.py
@@ -34,6 +34,10 @@
 		self.doclist = doclist
 
 	def validate(self):
+		import utilities
+		utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped", 
+			"In Process", "Completed", "Cancelled"])
+
 		if self.doc.production_item :
 			item_detail = sql("select name from `tabItem` where name = '%s' and docstatus != 2"
 			 	% self.doc.production_item, as_dict = 1)
diff --git a/manufacturing/page/manufacturing_home/manufacturing_home.html b/manufacturing/page/manufacturing_home/manufacturing_home.html
index 201eaeb..737a7c1 100644
--- a/manufacturing/page/manufacturing_home/manufacturing_home.html
+++ b/manufacturing/page/manufacturing_home/manufacturing_home.html
@@ -17,7 +17,7 @@
 		</div>
 		<div style="clear: both"></div>
 		<hr>
-		<h3>Reports</h3>
+		<h4>Reports</h4>
 		<div class="reports-list"></div>
 	</div>
 	<div class="layout-side-section">
diff --git a/projects/page/projects_home/projects_home.html b/projects/page/projects_home/projects_home.html
index 5cd48a0..cb4f1f8 100644
--- a/projects/page/projects_home/projects_home.html
+++ b/projects/page/projects_home/projects_home.html
@@ -17,7 +17,7 @@
 		</div>
 		<div style="clear: both"></div>
 		<hr>
-		<h3>Reports</h3>
+		<h4>Reports</h4>
 		<div class="reports-list"></div>
 	</div>
 	<div class="layout-side-section">
diff --git a/public/js/stock_analytics.js b/public/js/stock_analytics.js
index 35b3f56..53641ce 100644
--- a/public/js/stock_analytics.js
+++ b/public/js/stock_analytics.js
@@ -70,7 +70,7 @@
 		{fieldtype:"Select", label: "Brand", link:"Brand", 
 			default_value: "Select Brand...", filter: function(val, item, opts) {
 				return val == opts.default_value || item.brand == val || item._show;
-			}},
+			}, link_formatter: {filter_input: "brand"}},
 		{fieldtype:"Select", label: "Warehouse", link:"Warehouse", 
 			default_value: "Select Warehouse..."},
 		{fieldtype:"Date", label: "From Date"},
diff --git a/selling/doctype/installation_note/installation_note.py b/selling/doctype/installation_note/installation_note.py
index 1b8590b..5a997fd 100644
--- a/selling/doctype/installation_note/installation_note.py
+++ b/selling/doctype/installation_note/installation_note.py
@@ -8,11 +8,11 @@
 # 
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
 # GNU General Public License for more details.
 # 
 # You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+# along with this program.	If not, see <http://www.gnu.org/licenses/>.
 
 from __future__ import unicode_literals
 import webnotes
@@ -30,178 +30,176 @@
 from utilities.transaction_base import TransactionBase
 
 class DocType(TransactionBase):
-  def __init__(self, doc, doclist=[]):
-    self.doc = doc
-    self.doclist = doclist
-    self.tname = 'Installation Note Item'
-    self.fname = 'installed_item_details'
+	def __init__(self, doc, doclist=[]):
+		self.doc = doc
+		self.doclist = doclist
+		self.tname = 'Installation Note Item'
+		self.fname = 'installed_item_details'
 
-  # Autoname
-  # ---------
-  def autoname(self):
-    self.doc.name = make_autoname(self.doc.naming_series+'.#####')
+	def autoname(self):
+		self.doc.name = make_autoname(self.doc.naming_series+'.#####')
+
+	def validate(self):
+		self.validate_fiscal_year()
+		self.validate_installation_date()
+		self.check_item_table()
+		sales_com_obj = get_obj(dt = 'Sales Common')
+		sales_com_obj.check_active_sales_items(self)
+		sales_com_obj.get_prevdoc_date(self)
+		self.validate_mandatory()
+		self.validate_reference_value()
  
-  
-  #fetch delivery note details
-  #====================================
-  def pull_delivery_note_details(self):
-    self.validate_prev_docname()
-    self.doclist = get_obj('DocType Mapper', 'Delivery Note-Installation Note').dt_map('Delivery Note', 'Installation Note', self.doc.delivery_note_no, self.doc, self.doclist, "[['Delivery Note', 'Installation Note'],['Delivery Note Item', 'Installation Note Item']]")
-  
-  # Validates that Delivery Note is not pulled twice 
-  #============================================
-  def validate_prev_docname(self):
-    for d in getlist(self.doclist, 'installed_item_details'): 
-      if self.doc.delivery_note_no == d.prevdoc_docname:
-        msgprint(cstr(self.doc.delivery_note_no) + " delivery note details have already been pulled. ")
-        raise Exception, "Validation Error. "
-  
-  #Fiscal Year Validation
-  #================================
-  def validate_fiscal_year(self):
-    get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.inst_date,'Installation Date')
-  
-  #  Validate Mandatory 
-  #===============================
-  def validate_mandatory(self):
-    # Amendment Date
-    if self.doc.amended_from and not self.doc.amendment_date:
-      msgprint("Please Enter Amendment Date")
-      raise Exception, "Validation Error. "
-  
-  # Validate values with reference document
-  #----------------------------------------
-  def validate_reference_value(self):
-    get_obj('DocType Mapper', 'Delivery Note-Installation Note', with_children = 1).validate_reference_value(self, self.doc.name)
-  
-  #check if serial no added
-  #-----------------------------
-  def is_serial_no_added(self,item_code,serial_no):
-    ar_required = sql("select has_serial_no from tabItem where name = '%s'" % item_code)
-    ar_required = ar_required and ar_required[0][0] or ''
-    if ar_required == 'Yes' and not serial_no:
-      msgprint("Serial No is mandatory for item: "+ item_code)
-      raise Exception
-    elif ar_required != 'Yes' and cstr(serial_no).strip():
-      msgprint("If serial no required, please select 'Yes' in 'Has Serial No' in Item :"+item_code)
-      raise Exception
-  
-  #check if serial no exist in system
-  #-------------------------------------
-  def is_serial_no_exist(self, item_code, serial_no):
-    for x in serial_no:
-      chk = sql("select name from `tabSerial No` where name =%s", x)
-      if not chk:
-        msgprint("Serial No "+x+" does not exist in the system")
-        raise Exception
-  
-  #check if serial no already installed
-  #------------------------------------------
-  def is_serial_no_installed(self,cur_s_no,item_code):
-    for x in cur_s_no:
-      status = sql("select status from `tabSerial No` where name = %s", x)
-      status = status and status[0][0] or ''
-      
-      if status == 'Installed':
-        msgprint("Item "+item_code+" with serial no. "+x+" already installed")
-        raise Exception, "Validation Error."
-  
-  #get list of serial no from previous_doc
-  #----------------------------------------------
-  def get_prevdoc_serial_no(self, prevdoc_detail_docname, prevdoc_docname):
-    from stock.doctype.stock_ledger.stock_ledger import get_sr_no_list
 	
-    res = sql("select serial_no from `tabDelivery Note Item` where name = '%s' and parent ='%s'" % (prevdoc_detail_docname, prevdoc_docname))
-    return get_sr_no_list(res[0][0])
-    
-  #check if all serial nos from current record exist in resp delivery note
-  #---------------------------------------------------------------------------------
-  def is_serial_no_match(self, cur_s_no, prevdoc_s_no, prevdoc_docname):
-    for x in cur_s_no:
-      if not(x in prevdoc_s_no):
-        msgprint("Serial No. "+x+" not present in the Delivery Note "+prevdoc_docname, raise_exception = 1)
-        raise Exception, "Validation Error."
-  
-  #validate serial number
-  #----------------------------------------
-  def validate_serial_no(self):
-    cur_s_no, prevdoc_s_no, sr_list = [], [], []
-    from stock.doctype.stock_ledger.stock_ledger import get_sr_no_list
-    
-    for d in getlist(self.doclist, 'installed_item_details'):
-      self.is_serial_no_added(d.item_code, d.serial_no)
-      
-      if d.serial_no:
+	#fetch delivery note details
+	#====================================
+	def pull_delivery_note_details(self):
+		self.validate_prev_docname()
+		self.doclist = get_obj('DocType Mapper', 'Delivery Note-Installation Note').dt_map('Delivery Note', 'Installation Note', self.doc.delivery_note_no, self.doc, self.doclist, "[['Delivery Note', 'Installation Note'],['Delivery Note Item', 'Installation Note Item']]")
+	
+	# Validates that Delivery Note is not pulled twice 
+	#============================================
+	def validate_prev_docname(self):
+		for d in getlist(self.doclist, 'installed_item_details'): 
+			if self.doc.delivery_note_no == d.prevdoc_docname:
+				msgprint(cstr(self.doc.delivery_note_no) + " delivery note details have already been pulled. ")
+				raise Exception, "Validation Error. "
+	
+	#Fiscal Year Validation
+	#================================
+	def validate_fiscal_year(self):
+		get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.inst_date,'Installation Date')
+	
+	#	Validate Mandatory 
+	#===============================
+	def validate_mandatory(self):
+		# Amendment Date
+		if self.doc.amended_from and not self.doc.amendment_date:
+			msgprint("Please Enter Amendment Date")
+			raise Exception, "Validation Error. "
+	
+	# Validate values with reference document
+	#----------------------------------------
+	def validate_reference_value(self):
+		get_obj('DocType Mapper', 'Delivery Note-Installation Note', with_children = 1).validate_reference_value(self, self.doc.name)
+	
+	#check if serial no added
+	#-----------------------------
+	def is_serial_no_added(self,item_code,serial_no):
+		ar_required = sql("select has_serial_no from tabItem where name = '%s'" % item_code)
+		ar_required = ar_required and ar_required[0][0] or ''
+		if ar_required == 'Yes' and not serial_no:
+			msgprint("Serial No is mandatory for item: "+ item_code)
+			raise Exception
+		elif ar_required != 'Yes' and cstr(serial_no).strip():
+			msgprint("If serial no required, please select 'Yes' in 'Has Serial No' in Item :"+item_code)
+			raise Exception
+	
+	#check if serial no exist in system
+	#-------------------------------------
+	def is_serial_no_exist(self, item_code, serial_no):
+		for x in serial_no:
+			chk = sql("select name from `tabSerial No` where name =%s", x)
+			if not chk:
+				msgprint("Serial No "+x+" does not exist in the system")
+				raise Exception
+	
+	#check if serial no already installed
+	#------------------------------------------
+	def is_serial_no_installed(self,cur_s_no,item_code):
+		for x in cur_s_no:
+			status = sql("select status from `tabSerial No` where name = %s", x)
+			status = status and status[0][0] or ''
+			
+			if status == 'Installed':
+				msgprint("Item "+item_code+" with serial no. "+x+" already installed")
+				raise Exception, "Validation Error."
+	
+	#get list of serial no from previous_doc
+	#----------------------------------------------
+	def get_prevdoc_serial_no(self, prevdoc_detail_docname, prevdoc_docname):
+		from stock.doctype.stock_ledger.stock_ledger import get_sr_no_list
+	
+		res = sql("select serial_no from `tabDelivery Note Item` where name = '%s' and parent ='%s'" % (prevdoc_detail_docname, prevdoc_docname))
+		return get_sr_no_list(res[0][0])
+		
+	#check if all serial nos from current record exist in resp delivery note
+	#---------------------------------------------------------------------------------
+	def is_serial_no_match(self, cur_s_no, prevdoc_s_no, prevdoc_docname):
+		for x in cur_s_no:
+			if not(x in prevdoc_s_no):
+				msgprint("Serial No. "+x+" not present in the Delivery Note "+prevdoc_docname, raise_exception = 1)
+				raise Exception, "Validation Error."
+	
+	#validate serial number
+	#----------------------------------------
+	def validate_serial_no(self):
+		cur_s_no, prevdoc_s_no, sr_list = [], [], []
+		from stock.doctype.stock_ledger.stock_ledger import get_sr_no_list
+		
+		for d in getlist(self.doclist, 'installed_item_details'):
+			self.is_serial_no_added(d.item_code, d.serial_no)
+			
+			if d.serial_no:
 
-        sr_list = get_sr_no_list(d.serial_no, d.qty, d.item_code)
-        self.is_serial_no_exist(d.item_code, sr_list)
-        
-        prevdoc_s_no = self.get_prevdoc_serial_no(d.prevdoc_detail_docname, d.prevdoc_docname)
-        if prevdoc_s_no:
-          self.is_serial_no_match(sr_list, prevdoc_s_no, d.prevdoc_docname)
-        
-        self.is_serial_no_installed(sr_list, d.item_code)
-    return sr_list
-  
-  #validate installation date
-  #-------------------------------
-  def validate_installation_date(self):
-    for d in getlist(self.doclist, 'installed_item_details'):
-      if d.prevdoc_docname:
-        d_date = sql("select posting_date from `tabDelivery Note` where name=%s", d.prevdoc_docname)
-        d_date = d_date and d_date[0][0] or ''
-        
-        if d_date > getdate(self.doc.inst_date):
-          msgprint("Installation Date can not be before Delivery Date "+cstr(d_date)+" for item "+d.item_code)
-          raise Exception
-  
-  def validate(self):
-    self.validate_fiscal_year()
-    self.validate_installation_date()
-    self.check_item_table()
-    sales_com_obj = get_obj(dt = 'Sales Common')
-    sales_com_obj.check_active_sales_items(self)
-    sales_com_obj.get_prevdoc_date(self)
-    self.validate_mandatory()
-    self.validate_reference_value()
-  
-  def check_item_table(self):
-    if not(getlist(self.doclist, 'installed_item_details')):
-      msgprint("Please fetch items from Delivery Note selected")
-      raise Exception
-  
-  def on_update(self):
-    webnotes.conn.set(self.doc, 'status', 'Draft')
-  
-  def on_submit(self):
-    valid_lst = []
-    valid_lst = self.validate_serial_no()
-    
-    get_obj("Sales Common").update_prevdoc_detail(1,self)
-    
-    for x in valid_lst:
-      wp = sql("select warranty_period from `tabSerial No` where name = '%s'"% x)
-      wp = wp and wp[0][0] or 0
-      if wp:
-        sql("update `tabSerial No` set maintenance_status = 'Under Warranty' where name = '%s'" % x)
-      
-      sql("update `tabSerial No` set status = 'Installed' where name = '%s'" % x)
-    
-    webnotes.conn.set(self.doc, 'status', 'Submitted')
+				sr_list = get_sr_no_list(d.serial_no, d.qty, d.item_code)
+				self.is_serial_no_exist(d.item_code, sr_list)
+				
+				prevdoc_s_no = self.get_prevdoc_serial_no(d.prevdoc_detail_docname, d.prevdoc_docname)
+				if prevdoc_s_no:
+					self.is_serial_no_match(sr_list, prevdoc_s_no, d.prevdoc_docname)
+				
+				self.is_serial_no_installed(sr_list, d.item_code)
+		return sr_list
+	
+	#validate installation date
+	#-------------------------------
+	def validate_installation_date(self):
+		for d in getlist(self.doclist, 'installed_item_details'):
+			if d.prevdoc_docname:
+				d_date = sql("select posting_date from `tabDelivery Note` where name=%s", d.prevdoc_docname)
+				d_date = d_date and d_date[0][0] or ''
+				
+				if d_date > getdate(self.doc.inst_date):
+					msgprint("Installation Date can not be before Delivery Date "+cstr(d_date)+" for item "+d.item_code)
+					raise Exception
+	
+	def check_item_table(self):
+		if not(getlist(self.doclist, 'installed_item_details')):
+			msgprint("Please fetch items from Delivery Note selected")
+			raise Exception
+	
+	def on_update(self):
+		webnotes.conn.set(self.doc, 'status', 'Draft')
+	
+	def on_submit(self):
+		valid_lst = []
+		valid_lst = self.validate_serial_no()
+		
+		get_obj("Sales Common").update_prevdoc_detail(1,self)
+		
+		for x in valid_lst:
+			wp = sql("select warranty_period from `tabSerial No` where name = '%s'"% x)
+			wp = wp and wp[0][0] or 0
+			if wp:
+				sql("update `tabSerial No` set maintenance_status = 'Under Warranty' where name = '%s'" % x)
+			
+			sql("update `tabSerial No` set status = 'Installed' where name = '%s'" % x)
+		
+		webnotes.conn.set(self.doc, 'status', 'Submitted')
 
-  
-  def on_cancel(self):
-    cur_s_no = []
-    sales_com_obj = get_obj(dt = 'Sales Common')
-    sales_com_obj.update_prevdoc_detail(0,self)
-    
-    for d in getlist(self.doclist, 'installed_item_details'):
-      if d.serial_no:
-        #get current list of serial no
-        cur_serial_no = d.serial_no.replace(' ', '')
-        cur_s_no = cur_serial_no.split(',')
-    
-    for x in cur_s_no:
-      sql("update `tabSerial No` set status = 'Delivered' where name = '%s'" % x)
-      
-    webnotes.conn.set(self.doc, 'status', 'Cancelled')
+	
+	def on_cancel(self):
+		cur_s_no = []
+		sales_com_obj = get_obj(dt = 'Sales Common')
+		sales_com_obj.update_prevdoc_detail(0,self)
+		
+		for d in getlist(self.doclist, 'installed_item_details'):
+			if d.serial_no:
+				#get current list of serial no
+				cur_serial_no = d.serial_no.replace(' ', '')
+				cur_s_no = cur_serial_no.split(',')
+		
+		for x in cur_s_no:
+			sql("update `tabSerial No` set status = 'Delivered' where name = '%s'" % x)
+			
+		webnotes.conn.set(self.doc, 'status', 'Cancelled')
diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py
index 3b452f1..ed09ab0 100644
--- a/selling/doctype/quotation/quotation.py
+++ b/selling/doctype/quotation/quotation.py
@@ -179,6 +179,10 @@
 	# Validate
 	# --------
 	def validate(self):
+		import utilities
+		utilities.validate_status(self.doc.status, ["Draft", "Submitted", 
+			"Order Confirmed", "Order Lost", "Cancelled"])
+
 		self.validate_fiscal_year()
 		self.validate_mandatory()
 		self.set_last_contact_date()
diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py
index e0ac2ff..3e7b03d 100644
--- a/selling/doctype/sales_order/sales_order.py
+++ b/selling/doctype/sales_order/sales_order.py
@@ -226,8 +226,13 @@
 		self.doc.in_words = sales_com_obj.get_total_in_words(dcc, self.doc.rounded_total)
 		self.doc.in_words_export = sales_com_obj.get_total_in_words(self.doc.currency, self.doc.rounded_total_export)
 		
-		# set SO status
-		self.doc.status='Draft'
+		if not self.doc.status:
+			self.doc.status = "Draft"
+
+		import utilities
+		utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped", 
+			"Cancelled"])
+
 		if not self.doc.billing_status: self.doc.billing_status = 'Not Billed'
 		if not self.doc.delivery_status: self.doc.delivery_status = 'Not Delivered'
 		
diff --git a/selling/page/selling_home/selling_home.html b/selling/page/selling_home/selling_home.html
index 3009ceb..e483b50 100644
--- a/selling/page/selling_home/selling_home.html
+++ b/selling/page/selling_home/selling_home.html
@@ -29,15 +29,20 @@
 			<br>
 			<h5><a href="#List/Address">Address</a></h5>
 			<p class="help">Address Master</p>
-			<br>
+		</div>
+		<div style="clear: both"></div>
+		<hr>
+		<h4>Reports</h4>
+		<div style="width: 48%; float: left;">
 			<h5><a href="#sales-analytics" data-role="Analytics, Sales Manager,
 					Maintenance Manager">Sales Analytics</a>
 			</h5>
 			<p class="help">Sales trends based on Sales Invoice</p>
 		</div>
-		<div style="clear: both"></div>
+		<div style="width: 48%; float: right;">
+		</div>
+		<div style="clear: both;"></div>
 		<hr>
-		<h3>Reports</h3>
 		<div class="reports-list"></div>
 	</div>
 	<div class="layout-side-section">
diff --git a/startup/report_data_map.py b/startup/report_data_map.py
index b07ded5..6a7ba42 100644
--- a/startup/report_data_map.py
+++ b/startup/report_data_map.py
@@ -93,13 +93,57 @@
 			"item_code": ["Item", "name"],
 			"warehouse": ["Warehouse", "name"]
 		},
-		"force_index": "posting_sort_index"		
+		"force_index": "posting_sort_index"
 	},
 	"Stock Entry": {
 		"columns": ["name", "purpose"],
 		"conditions": ["docstatus=1"],
 		"order_by": "posting_date, posting_time, name",
 	},
+	"Production Order": {
+		"columns": ["production_item as item_code", 
+			"(ifnull(qty, 0) - ifnull(produced_qty, 0)) as qty", 
+			"fg_warehouse as warehouse"],
+		"conditions": ["docstatus=1", "status != 'Stopped'", "ifnull(fg_warehouse, '')!=''",
+			"ifnull(qty, 0) > ifnull(produced_qty, 0)"],
+		"links": {
+			"item_code": ["Item", "name"],
+			"warehouse": ["Warehouse", "name"]
+		},
+	},
+	"Purchase Request Item": {
+		"columns": ["item_code", "warehouse", 
+			"(ifnull(qty, 0) - ifnull(ordered_qty, 0)) as qty"],
+		"from": "`tabPurchase Request Item` item, `tabPurchase Request` main",
+		"conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'", 
+			"ifnull(warehouse, '')!=''", "ifnull(qty, 0) > ifnull(ordered_qty, 0)"],
+		"links": {
+			"item_code": ["Item", "name"],
+			"warehouse": ["Warehouse", "name"]
+		},
+	},
+	"Purchase Order Item": {
+		"columns": ["item_code", "warehouse", 
+			"(ifnull(qty, 0) - ifnull(received_qty, 0)) as qty"],
+		"from": "`tabPurchase Order Item` item, `tabPurchase Order` main",
+		"conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'", 
+			"ifnull(warehouse, '')!=''", "ifnull(qty, 0) > ifnull(received_qty, 0)"],
+		"links": {
+			"item_code": ["Item", "name"],
+			"warehouse": ["Warehouse", "name"]
+		},
+	},
+	"Sales Order Item": {
+		"columns": ["item_code", "(ifnull(qty, 0) - ifnull(delivered_qty, 0)) as qty", 
+			"reserved_warehouse as warehouse"],
+		"from": "`tabSales Order Item` item, `tabSales Order` main",
+		"conditions": ["item.parent = main.name", "main.docstatus=1", "main.status != 'Stopped'", 
+			"ifnull(reserved_warehouse, '')!=''", "ifnull(qty, 0) > ifnull(delivered_qty, 0)"],
+		"links": {
+			"item_code": ["Item", "name"],
+			"warehouse": ["Warehouse", "name"]
+		},
+	},
 
 	# Sales
 	"Customer": {
diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py
index af4d91e..411ce5c 100644
--- a/stock/doctype/delivery_note/delivery_note.py
+++ b/stock/doctype/delivery_note/delivery_note.py
@@ -131,6 +131,9 @@
 
 
 	def validate(self):
+		import utilities
+		utilities.validate_status(self.doc.status, ["Draft", "submitted", "Cancelled"])
+
 		self.so_required()
 		self.validate_fiscal_year()
 		self.validate_proj_cust()
diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py
index 5e60753..8c2ad01 100644
--- a/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -148,7 +148,13 @@
 	def validate(self):
 		self.po_required()
 		self.validate_fiscal_year()
-		webnotes.conn.set(self.doc, 'status', 'Draft')			 # set status as "Draft"
+
+		if not self.doc.status:
+			self.doc.status = "Draft"
+
+		import utilities
+		utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Cancelled"])
+
 		self.validate_accepted_rejected_qty()
 		self.validate_inspection()						 # Validate Inspection
 		get_obj('Stock Ledger').validate_serial_no(self, 'purchase_receipt_details')
diff --git a/stock/doctype/serial_no/serial_no.py b/stock/doctype/serial_no/serial_no.py
index b6f60f5..190b92b 100644
--- a/stock/doctype/serial_no/serial_no.py
+++ b/stock/doctype/serial_no/serial_no.py
@@ -65,6 +65,10 @@
 	# validate
 	# ---------
 	def validate(self):
+		# import utilities
+		# utilities.validate_status(self.doc.status, ["In Store", "Delivered", 
+		# 	"Not in Use", "Purchase Returned"])
+
 		self.validate_warranty_status()
 		self.validate_amc_status()
 		self.validate_warehouse()
diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py
index 2e26a1a..1844032 100644
--- a/stock/doctype/stock_entry/stock_entry.py
+++ b/stock/doctype/stock_entry/stock_entry.py
@@ -17,7 +17,7 @@
 from __future__ import unicode_literals
 import webnotes
 
-from webnotes.utils import cstr, cint, flt, getdate, now
+from webnotes.utils import cstr, cint, flt, getdate, now, comma_or
 from webnotes.model import db_exists, delete_doc
 from webnotes.model.doc import Document, addchild
 from webnotes.model.wrapper import getlist, copy_doclist
@@ -35,6 +35,8 @@
 		self.fname = 'mtn_details' 
 		
 	def validate(self):
+		self.validate_purpose()
+
 		self.validate_serial_nos()
 		pro_obj = self.doc.production_order and \
 			get_obj('Production Order', self.doc.production_order) or None
@@ -57,6 +59,13 @@
 		self.update_stock_ledger(1)
 		# update Production Order
 		self.update_production_order(0)
+
+	def validate_purpose(self):
+		valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer", 
+			"Manufacture/Repack", "Subcontract", "Sales Return", "Purchase Return"]
+		if self.doc.purpose not in valid_purposes:
+			msgprint(_("Purpose must be one of ") + comma_or(valid_purposes),
+				raise_exception=True)
 					
 	def validate_serial_nos(self):
 		sl_obj = get_obj("Stock Ledger")
diff --git a/stock/page/stock_ageing/stock_ageing.js b/stock/page/stock_ageing/stock_ageing.js
index 7809ab9..ea495ce 100644
--- a/stock/page/stock_ageing/stock_ageing.js
+++ b/stock/page/stock_ageing/stock_ageing.js
@@ -63,7 +63,7 @@
 		{fieldtype:"Select", label: "Brand", link:"Brand", 
 			default_value: "Select Brand...", filter: function(val, item, opts) {
 				return val == opts.default_value || item.brand == val;
-			}},
+			}, link_formatter: {filter_input: "brand"}},
 		{fieldtype:"Select", label: "Plot By", 
 			options: ["Average Age", "Earliest", "Latest"]},
 		{fieldtype:"Date", label: "To Date"},
diff --git a/stock/page/stock_balance/stock_balance.js b/stock/page/stock_balance/stock_balance.js
index 3033470..485909c 100644
--- a/stock/page/stock_balance/stock_balance.js
+++ b/stock/page/stock_balance/stock_balance.js
@@ -63,7 +63,7 @@
 		{fieldtype:"Select", label: "Brand", link:"Brand", 
 			default_value: "Select Brand...", filter: function(val, item, opts) {
 				return val == opts.default_value || item.brand == val || item._show;
-			}},
+			}, link_formatter: {filter_input: "brand"}},
 		{fieldtype:"Select", label: "Warehouse", link:"Warehouse", 
 			default_value: "Select Warehouse..."},
 		{fieldtype:"Date", label: "From Date"},
diff --git a/stock/page/stock_home/stock_home.html b/stock/page/stock_home/stock_home.html
index 7e43e99..d4dfd4c 100644
--- a/stock/page/stock_home/stock_home.html
+++ b/stock/page/stock_home/stock_home.html
@@ -23,7 +23,11 @@
 			<br>
 			<h5><a href="#List/Warehouse">Warehouse</a></h5>
 			<p class="help">Warehouse is where items are stored</p>
-			<br>
+		</div>
+		<div style="clear: both"></div>
+		<hr>
+		<h4>Reports</h4>
+		<div style="width: 48%; float: left;">
 			<h5><a href="#stock-ledger" data-role="Analytics, Material Manager,
 					Material User">Stock Ledger</a>
 			</h5>
@@ -34,6 +38,12 @@
 			</h5>
 			<p class="help">Inflow, outflow and balance of stock</p>
 			<br>
+			<h5><a href="#stock-level" data-role="Analytics, Material Manager">
+					Stock Level</a>
+			</h5>
+			<p class="help">Available and estimated qty of stock, as of now</p>
+		</div>
+		<div style="width: 48%; float: right;">
 			<h5><a href="#stock-analytics" data-role="Analytics, Material Manager">
 					Stock Analytics</a>
 			</h5>
@@ -44,9 +54,8 @@
 			</h5>
 			<p class="help">Analysis of slow moving stock</p>
 		</div>
-		<div style="clear: both"></div>
+		<div style="clear: both;"></div>
 		<hr>
-		<h3>Reports</h3>
 		<div class="reports-list"></div>
 	</div>
 	<div class="layout-side-section">
diff --git a/stock/page/stock_ledger/stock_ledger.js b/stock/page/stock_ledger/stock_ledger.js
index e0cfd02..97d6417 100644
--- a/stock/page/stock_ledger/stock_ledger.js
+++ b/stock/page/stock_ledger/stock_ledger.js
@@ -86,7 +86,7 @@
 		{fieldtype:"Select", label: "Brand", link:"Brand", 
 			default_value: "Select Brand...", filter: function(val, item, opts) {
 				return val == opts.default_value || item.brand == val || item._show;
-			}},
+			}, link_formatter: {filter_input: "brand"}},
 		{fieldtype:"Data", label: "Voucher No",
 			filter: function(val, item, opts) {
 				if(!val) return true;
diff --git a/stock/page/stock_level/__init__.py b/stock/page/stock_level/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/stock/page/stock_level/__init__.py
diff --git a/stock/page/stock_level/stock_level.js b/stock/page/stock_level/stock_level.js
new file mode 100644
index 0000000..87fce6a
--- /dev/null
+++ b/stock/page/stock_level/stock_level.js
@@ -0,0 +1,225 @@
+// ERPNext - web based ERP (http://erpnext.com)
+// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
+// 
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+wn.pages['stock-level'].onload = function(wrapper) { 
+	wn.ui.make_app_page({
+		parent: wrapper,
+		title: 'Stock Level',
+		single_column: true
+	});
+	
+	new erpnext.StockLevel(wrapper);
+
+	wrapper.appframe.add_home_breadcrumb()
+	wrapper.appframe.add_module_breadcrumb("Stock")
+	wrapper.appframe.add_breadcrumb("icon-bar-chart");
+}
+
+wn.require("app/js/stock_grid_report.js");
+
+erpnext.StockLevel = erpnext.StockGridReport.extend({
+	init: function(wrapper) {
+		var me = this;
+		
+		this._super({
+			title: "Stock Level",
+			page: wrapper,
+			parent: $(wrapper).find('.layout-main'),
+			appframe: wrapper.appframe,
+			doctypes: ["Item", "Warehouse", "Stock Ledger Entry", "Production Order", 
+				"Purchase Request Item", "Purchase Order Item", "Sales Order Item", "Brand"],
+		});
+		
+		this.wrapper.bind("make", function() {
+			wn.utils.set_footnote(me, me.wrapper.get(0),
+				"<ul> \
+					<li style='font-weight: bold;'> \
+						Projected Qty = Actual Qty + Planned Qty + Requested Qty \
+						+ Ordered Qty - Reserved Qty </li> \
+					<ul> \
+						<li>Actual Qty: Quantity available in the warehouse. </li> \
+						<li>Planned Qty: Quantity, for which, Production Order has been raised, \
+							but is pending to be manufactured. </li> \
+						<li>Requested Qty: Quantity requested for purchase, but not ordered. </li> \
+						<li>Ordered Qty: Quantity ordered for purchase, but not received.</li> \
+						<li>Reserved Qty: Quantity ordered for sale, but not delivered. </li> \
+					</ul> \
+				</ul>");
+		});
+	},
+	
+	setup_columns: function() {
+		this.columns = [
+			{id: "item_code", name: "Item Code", field: "item_code", width: 160, 	
+				link_formatter: {
+					filter_input: "item_code",
+					open_btn: true,
+					doctype: '"Item"',
+				}},
+			{id: "warehouse", name: "Warehouse", field: "warehouse", width: 100,
+				link_formatter: {filter_input: "warehouse"}},
+			{id: "actual_qty", name: "Actual Qty", 
+				field: "actual_qty", width: 80, formatter: this.currency_formatter},
+			{id: "planned_qty", name: "Planned Qty", 
+				field: "planned_qty", width: 80, formatter: this.currency_formatter},
+			{id: "requested_qty", name: "Requested Qty", 
+				field: "requested_qty", width: 80, formatter: this.currency_formatter},
+			{id: "ordered_qty", name: "Ordered Qty", 
+				field: "ordered_qty", width: 80, formatter: this.currency_formatter},
+			{id: "reserved_qty", name: "Reserved Qty", 
+				field: "reserved_qty", width: 80, formatter: this.currency_formatter},
+			{id: "projected_qty", name: "Projected Qty", 
+				field: "projected_qty", width: 80, formatter: this.currency_formatter},
+			{id: "uom", name: "UOM", field: "uom", width: 60},
+			{id: "item_name", name: "Item Name", field: "item_name", width: 100,
+				formatter: this.text_formatter},
+			{id: "brand", name: "Brand", field: "brand", width: 100,
+				link_formatter: {filter_input: "brand"}},
+		];
+	},
+	
+	filters: [
+		{fieldtype:"Select", label: "Item Code", link:"Item", default_value: "Select Item...",
+			filter: function(val, item, opts) {
+				return item.item_code == val || val == opts.default_value;
+			}},
+			
+		{fieldtype:"Select", label: "Warehouse", link:"Warehouse", 
+			default_value: "Select Warehouse...", filter: function(val, item, opts) {
+				return item.warehouse == val || val == opts.default_value;
+			}},
+		
+		{fieldtype:"Select", label: "Brand", link:"Brand", 
+			default_value: "Select Brand...", filter: function(val, item, opts) {
+				return val == opts.default_value || item.brand == val;
+			}},
+		{fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"},
+		{fieldtype:"Button", label: "Reset Filters"}
+	],
+	
+	setup_filters: function() {
+		var me = this;
+		this._super();
+		
+		this.wrapper.bind("apply_filters_from_route", function() { me.toggle_enable_brand(); });
+		this.filter_inputs.item_code.change(function() { me.toggle_enable_brand(); });
+		
+		this.trigger_refresh_on_change(["item_code", "warehouse", "brand"]);
+	},
+	
+	toggle_enable_brand: function() {
+		if(this.filter_inputs.item_code.val() ==
+				this.filter_inputs.item_code.get(0).opts.default_value) {
+			this.filter_inputs.brand.removeAttr("disabled");
+		} else {
+			this.filter_inputs.brand
+				.val(this.filter_inputs.brand.get(0).opts.default_value)
+				.attr("disabled", "disabled");
+		}
+	},
+	
+	init_filter_values: function() {
+		this._super();
+		this.filter_inputs.warehouse.get(0).selectedIndex = 0;
+	},
+	
+	prepare_data: function() {
+		var me = this;
+
+		if(!this._data) {
+			this._data = [];
+			this.item_warehouse_map = [];
+			this.item_by_name = this.make_name_map(wn.report_dump.data["Item"]);
+			var sorted_item_list = Object.keys(this.item_by_name).sort();
+			$.each(sorted_item_list, function(i, item_code) {
+				var item = me.item_by_name[item_code];
+				$.each(wn.report_dump.data["Warehouse"], function(i, warehouse) {
+					// a list of item warehouse combination objects
+					var row = {
+						item_code: item_code,
+						warehouse: warehouse.name,
+						brand: item.brand,
+						item_name: item.item_name || item.name,
+						uom: item.stock_uom,
+						id: item_code + ":" + warehouse.name,
+					}
+					me.reset_item_values(row);
+					me._data.push(row);
+					me.item_warehouse_map[row.id] = row;
+				});
+			});
+			this.calculate_quantities();
+			
+			// filter out rows with zero values
+			this._data = $.map(this._data, function(d) {
+				return me.apply_zero_filter(null, d, null, me) ? d : null;
+			});
+		}
+		
+		this.data = [].concat(this._data);
+		this.data = $.map(this.data, function(d) {
+			return me.apply_filters(d) ? d : null;
+		});
+
+		this.calculate_total();
+	},
+	
+	calculate_quantities: function() {
+		var me = this;
+		$.each([
+			["Stock Ledger Entry", "actual_qty"], 
+			["Production Order", "planned_qty"], 
+			["Purchase Request Item", "requested_qty"],
+			["Purchase Order Item", "ordered_qty"],
+			["Sales Order Item", "reserved_qty"]], 
+			function(i, v) {
+				$.each(wn.report_dump.data[v[0]], function(i, item) {
+					var row = me.item_warehouse_map[item.item_code + ":" + item.warehouse];
+					row[v[1]] += flt(item.qty);
+				});
+			}
+		);
+		
+		$.each(this._data, function(i, row) {
+			row.projected_qty = row.actual_qty + row.planned_qty + row.requested_qty
+				+ row.ordered_qty - row.reserved_qty;
+		});
+	},
+	
+	calculate_total: function() {
+		var me = this;
+		// show total if a specific item is selected and warehouse is not filtered
+		if(this.is_default("warehouse") && !this.is_default("item_code")) {
+			var total = {
+				id: "_total",
+				item_code: "Total",
+				_style: "font-weight: bold",
+				_show: true
+			};
+			this.reset_item_values(total);
+			
+			$.each(this.data, function(i, row) {
+				$.each(me.columns, function(i, col) {
+					if (col.formatter==me.currency_formatter) {
+						total[col.id] += row[col.id];
+					}
+				});
+			});
+			
+			this.data = this.data.concat([total]);
+		}
+	}
+})
diff --git a/stock/page/stock_level/stock_level.txt b/stock/page/stock_level/stock_level.txt
new file mode 100644
index 0000000..6bf5c41
--- /dev/null
+++ b/stock/page/stock_level/stock_level.txt
@@ -0,0 +1,21 @@
+[
+ {
+  "owner": "Administrator", 
+  "docstatus": 0, 
+  "creation": "2012-12-28 11:02:23", 
+  "modified_by": "Administrator", 
+  "modified": "2012-12-28 11:02:23"
+ }, 
+ {
+  "name": "__common__", 
+  "title": "Stock Level", 
+  "doctype": "Page", 
+  "module": "Stock", 
+  "standard": "Yes", 
+  "page_name": "stock-level"
+ }, 
+ {
+  "name": "stock-level", 
+  "doctype": "Page"
+ }
+]
\ No newline at end of file
diff --git a/support/doctype/customer_issue/customer_issue.py b/support/doctype/customer_issue/customer_issue.py
index 44ae891..0a08d82 100644
--- a/support/doctype/customer_issue/customer_issue.py
+++ b/support/doctype/customer_issue/customer_issue.py
@@ -41,9 +41,8 @@
 	
 	def validate(self):
 		if session['user'] != 'Guest' and not self.doc.customer:
-			msgprint("Please select Customer from whom issue is raised")
-			raise Exception
-
+			msgprint("Please select Customer from whom issue is raised",
+				raise_exception=True)
 	
 	def on_cancel(self):
 		lst = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t2.prevdoc_docname = '%s' and	t1.docstatus!=2"%(self.doc.name))
diff --git a/support/page/support_home/support_home.html b/support/page/support_home/support_home.html
index 8975bae..ed01fa0 100644
--- a/support/page/support_home/support_home.html
+++ b/support/page/support_home/support_home.html
@@ -26,7 +26,7 @@
 		</div>
 		<div style="clear: both"></div>
 		<hr>
-		<h3>Reports</h3>
+		<h4>Reports</h4>
 		<div class="reports-list"></div>
 	</div>
 	<div class="layout-side-section">
diff --git a/utilities/__init__.py b/utilities/__init__.py
index 486568d..7c44ec3 100644
--- a/utilities/__init__.py
+++ b/utilities/__init__.py
@@ -16,7 +16,8 @@
 
 from __future__ import unicode_literals
 import webnotes
-from webnotes.utils import cint
+from webnotes import _, msgprint
+from webnotes.utils import cint, comma_or
 
 @webnotes.whitelist()
 def get_sc_list(arg=None):
@@ -52,4 +53,8 @@
 			and ifnull(tabReport.disabled,0) != 1
 			order by tabReport.name 
 			limit %s, %s""" % \
-		("%s", cint(limit_start), cint(limit_page_length)), (module,), as_dict=True)
\ No newline at end of file
+		("%s", cint(limit_start), cint(limit_page_length)), (module,), as_dict=True)
+
+def validate_status(status, options):
+	if status not in options:
+		msgprint(_("Status must be one of ") + comma_or(options), raise_exception=True)
diff --git a/website/helpers/product.py b/website/helpers/product.py
index 1e8257a..623ceee 100644
--- a/website/helpers/product.py
+++ b/website/helpers/product.py
@@ -102,4 +102,5 @@
 		
 def invalidate_cache_for(item_group):
 	for i in get_parent_item_groups(item_group):
-		delete_page_cache(i.page_name)
\ No newline at end of file
+		if i.page_name:
+			delete_page_cache(i.page_name)
\ No newline at end of file
diff --git a/website/utils.py b/website/utils.py
index ec33103..674d752 100644
--- a/website/utils.py
+++ b/website/utils.py
@@ -263,7 +263,8 @@
 		webnotes.cache().delete_keys("page:")
 	
 def delete_page_cache(page_name):
-	webnotes.cache().delete_value("page:" + page_name)
+	if page_name:
+		webnotes.cache().delete_value("page:" + page_name)
 	
 def url_for_website(url):
 	if url and not url.lower().startswith("http"):