Restrict Employee and Leave Approver to relevant Employee and Leave Application records
diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py
index 46f46da..6684951 100644
--- a/hr/doctype/employee/employee.py
+++ b/hr/doctype/employee/employee.py
@@ -7,13 +7,11 @@
 from webnotes.utils import getdate, validate_email_add, cstr, cint
 from webnotes.model.doc import make_autoname
 from webnotes import msgprint, _
+import webnotes.permissions
+from webnotes.defaults import get_restrictions
+from webnotes.model.controller import DocListController
 
-
-class DocType:
-	def __init__(self,doc,doclist=[]):
-		self.doc = doc
-		self.doclist = doclist
-		
+class DocType(DocListController):
 	def autoname(self):
 		naming_method = webnotes.conn.get_value("HR Settings", None, "emp_created_by")
 		if not naming_method:
@@ -39,33 +37,36 @@
 		
 	def on_update(self):
 		if self.doc.user_id:
+			self.restrict_user()
 			self.update_user_default()
 			self.update_profile()
+		
+		self.restrict_leave_approver()
 				
-	def update_user_default(self):
-		from webnotes.defaults import get_restrictions
-		if not "HR User" in webnotes.local.user.get_roles():
-			if not self.doc.user_id in get_restrictions().get("Employee", []):
-				webnotes.conn.set_default("Employee", self.doc.name, self.doc.user_id, "Restriction")
+	def restrict_user(self):
+		"""restrict to this employee for user"""
+		self.add_restriction_if_required("Employee", self.doc.user_id)
 
-		webnotes.conn.set_default("employee", self.doc.name, self.doc.user_id)
+	def update_user_default(self):
 		webnotes.conn.set_default("employee_name", self.doc.employee_name, self.doc.user_id)
 		webnotes.conn.set_default("company", self.doc.company, self.doc.user_id)
-		self.set_default_leave_approver()
 	
-	def set_default_leave_approver(self):
-		employee_leave_approvers = self.doclist.get({"parentfield": "employee_leave_approvers"})
-
-		if len(employee_leave_approvers):
-			webnotes.conn.set_default("leave_approver", employee_leave_approvers[0].leave_approver,
-				self.doc.user_id)
-		
-		elif self.doc.reports_to:
-			from webnotes.profile import Profile
-			reports_to_user = webnotes.conn.get_value("Employee", self.doc.reports_to, "user_id")
-			if "Leave Approver" in Profile(reports_to_user).get_roles():
-				webnotes.conn.set_default("leave_approver", reports_to_user, self.doc.user_id)
-
+	def restrict_leave_approver(self):
+		"""restrict to this employee for leave approver"""
+		employee_leave_approvers = [d.leave_approver for d in self.doclist.get({"parentfield": "employee_leave_approvers"})]
+		if self.doc.reports_to and self.doc.reports_to not in employee_leave_approvers:
+			employee_leave_approvers.append(webnotes.conn.get_value("Employee", self.doc.reports_to, "user_id"))
+			
+		for user in employee_leave_approvers:
+			self.add_restriction_if_required("Employee", user)
+			self.add_restriction_if_required("Leave Application", user)
+				
+	def add_restriction_if_required(self, doctype, user):
+		if webnotes.permissions.has_only_non_restrict_role(webnotes.get_doctype(doctype), user) \
+			and self.doc.name not in get_restrictions(user).get("Employee", []):
+			
+			webnotes.defaults.add_default("Employee", self.doc.name, user, "Restriction")
+	
 	def update_profile(self):
 		# add employee role if missing
 		if not "Employee" in webnotes.conn.sql_list("""select role from tabUserRole
diff --git a/hr/doctype/employee/employee.txt b/hr/doctype/employee/employee.txt
index 225b485..f8b08e0 100644
--- a/hr/doctype/employee/employee.txt
+++ b/hr/doctype/employee/employee.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-03-07 09:04:18", 
   "docstatus": 0, 
-  "modified": "2013-12-20 19:24:06", 
+  "modified": "2013-12-23 19:35:27", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -760,6 +760,7 @@
   "cancel": 1, 
   "create": 1, 
   "doctype": "DocPerm", 
+  "restrict": 0, 
   "role": "HR User", 
   "write": 1
  }, 
@@ -767,6 +768,7 @@
   "cancel": 1, 
   "create": 1, 
   "doctype": "DocPerm", 
+  "restrict": 1, 
   "role": "HR Manager", 
   "write": 1
  }
diff --git a/hr/doctype/leave_application/leave_application.txt b/hr/doctype/leave_application/leave_application.txt
index 10c0429..24de6a8 100644
--- a/hr/doctype/leave_application/leave_application.txt
+++ b/hr/doctype/leave_application/leave_application.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-02-20 11:18:11", 
   "docstatus": 0, 
-  "modified": "2013-12-20 19:24:12", 
+  "modified": "2013-12-23 19:53:41", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -256,6 +256,7 @@
   "permlevel": 0, 
   "print": 1, 
   "report": 1, 
+  "restrict": 1, 
   "role": "HR User", 
   "submit": 1, 
   "write": 1
diff --git a/patches/1312/p02_update_user_properties.py b/patches/1312/p02_update_user_properties.py
index 4ac1ab9..70c500f 100644
--- a/patches/1312/p02_update_user_properties.py
+++ b/patches/1312/p02_update_user_properties.py
@@ -3,51 +3,59 @@
 
 from __future__ import unicode_literals
 import webnotes
+import webnotes.permissions
+import webnotes.model.doctype
+import webnotes.defaults
 
 def execute():
+	webnotes.reload_doc("core", "doctype", "docperm")
 	update_user_properties()
 	update_user_match()
+	add_employee_restrictions_to_leave_approver()
 	update_permissions()
 	remove_duplicate_restrictions()
+	webnotes.defaults.clear_cache()
 	webnotes.clear_cache()
 
 def update_user_properties():
 	webnotes.reload_doc("core", "doctype", "docfield")
 	
-	for d in webnotes.conn.sql("""select parent, defkey, defvalue from tabDefaultValue 
+	for d in webnotes.conn.sql("""select parent, defkey, defvalue from tabDefaultValue
 		where parent not in ('__global', 'Control Panel')""", as_dict=True):
-		df = webnotes.conn.sql("""select options from tabDocField 
+		df = webnotes.conn.sql("""select options from tabDocField
 			where fieldname=%s and fieldtype='Link'""", d.defkey, as_dict=True)
 		
 		if df:
-			webnotes.conn.sql("""update tabDefaultValue 
-				set defkey=%s, parenttype='Restriction' 
-				where defkey=%s and 
+			webnotes.conn.sql("""update tabDefaultValue
+				set defkey=%s, parenttype='Restriction'
+				where defkey=%s and
 				parent not in ('__global', 'Control Panel')""", (df[0].options, d.defkey))
-				
+
 def update_user_match():
 	import webnotes.defaults
 	doctype_matches = {}
 	for doctype, match in webnotes.conn.sql("""select parent, `match` from `tabDocPerm`
-		where `match` like %s""", "%:user"):
+		where `match` like %s and ifnull(`match`, '')!="leave_approver:user" """, "%:user"):
 		doctype_matches.setdefault(doctype, []).append(match)
 	
 	for doctype, user_matches in doctype_matches.items():
-		# get permissions of this doctype
-		perms = webnotes.conn.sql("""select role, `match` from `tabDocPerm` 
-			where parent=%s and permlevel=0 and `read`=1""", doctype, as_dict=True)
+		meta = webnotes.get_doctype(doctype)
 		
 		# for each user with roles of this doctype, check if match condition applies
 		for profile in webnotes.conn.sql_list("""select name from `tabProfile`
 			where enabled=1 and user_type='System User'"""):
 			
-			roles = webnotes.get_roles(profile)
+			perms = webnotes.permissions.get_user_perms(meta, "read", profile)
+			# user does not have required roles
+			if not perms:
+				continue
 			
-			user_match = False
+			# assume match
+			user_match = True
 			for perm in perms:
-				if perm.role in roles and (perm.match and \
-					(perm.match.endswith(":user") or perm.match.endswith(":profile"))):
-					user_match = True
+				if not perm.match:
+					# aha! non match found
+					user_match = False
 					break
 			
 			if not user_match:
@@ -60,18 +68,35 @@
 					where `{field}`=%s""".format(doctype=doctype, field=match.split(":")[0]), profile):
 					
 					webnotes.defaults.add_default(doctype, name, profile, "Restriction")
+					
+def add_employee_restrictions_to_leave_approver():
+	from core.page.user_properties import user_properties
+	
+	# add restrict rights to HR User and HR Manager
+	webnotes.conn.sql("""update `tabDocPerm` set `restrict`=1 where parent in ('Employee', 'Leave Application')
+		and role in ('HR User', 'HR Manager') and permlevel=0 and `read`=1""")
+	webnotes.model.doctype.clear_cache()
+	
+	# add Employee restrictions (in on_update method)
+	for employee in webnotes.conn.sql_list("""select name from `tabEmployee`
+		where exists(select leave_approver from `tabEmployee Leave Approver`
+			where `tabEmployee Leave Approver`.parent=`tabEmployee`.name)
+		or ifnull(`reports_to`, '')!=''"""):
+		
+		webnotes.bean("Employee", employee).save()
 
 def update_permissions():
 	# clear match conditions other than owner
 	webnotes.conn.sql("""update tabDocPerm set `match`=''
 		where ifnull(`match`,'') not in ('', 'owner')""")
-		
+
 def remove_duplicate_restrictions():
 	# remove duplicate restrictions (if they exist)
-	for d in webnotes.conn.sql("""select parent, defkey, defvalue, 
-		count(*) as cnt from tabDefaultValue 
-		where parent not in ('__global', 'Control Panel') 
+	for d in webnotes.conn.sql("""select parent, defkey, defvalue,
+		count(*) as cnt from tabDefaultValue
+		where parent not in ('__global', 'Control Panel')
 		group by parent, defkey, defvalue""", as_dict=1):
 		if d.cnt > 1:
-			webnotes.conn.sql("""delete from tabDefaultValue where parent=%s, defkey=%s, 
-				defvalue=%s limit %s""", (d.parent, d.defkey, d.defvalue, d.cnt-1))
\ No newline at end of file
+			# order by parenttype so that restriction does not get removed!
+			webnotes.conn.sql("""delete from tabDefaultValue where parent=%s, defkey=%s,
+				defvalue=%s order by parenttype limit %s""", (d.parent, d.defkey, d.defvalue, d.cnt-1))