View Javadoc
1   /**
2    * Copyright 2004-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.kpme.tklm.time.service.permission;
17  
18  import java.util.HashMap;
19  import java.util.List;
20  import java.util.Map;
21  
22  import org.apache.commons.collections.CollectionUtils;
23  import org.apache.commons.lang.StringUtils;
24  import org.joda.time.DateTime;
25  import org.joda.time.LocalDate;
26  import org.kuali.kpme.core.KPMENamespace;
27  import org.kuali.kpme.core.assignment.Assignment;
28  import org.kuali.kpme.core.block.CalendarBlockPermissions;
29  import org.kuali.kpme.core.department.Department;
30  import org.kuali.kpme.core.earncode.security.EarnCodeSecurity;
31  import org.kuali.kpme.core.job.Job;
32  import org.kuali.kpme.core.paytype.PayType;
33  import org.kuali.kpme.core.role.KPMERole;
34  import org.kuali.kpme.core.service.HrServiceLocator;
35  import org.kuali.kpme.core.service.permission.HrPermissionServiceBase;
36  import org.kuali.kpme.core.util.HrContext;
37  import org.kuali.kpme.core.workarea.WorkArea;
38  import org.kuali.kpme.tklm.time.rules.timecollection.TimeCollectionRule;
39  import org.kuali.kpme.tklm.time.service.TkServiceLocator;
40  import org.kuali.kpme.tklm.time.timeblock.TimeBlock;
41  import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument;
42  import org.kuali.kpme.tklm.time.timesheet.service.TimesheetService;
43  import org.kuali.kpme.tklm.time.util.TkContext;
44  import org.kuali.rice.kew.api.KewApiServiceLocator;
45  import org.kuali.rice.kew.api.document.DocumentStatus;
46  
47  public class TKPermissionServiceImpl extends HrPermissionServiceBase implements TKPermissionService {
48  	
49  	private TimesheetService timesheetService;
50  
51  	@Override
52  	public boolean isAuthorized(String principalId, String permissionName, DateTime asOfDate) {
53  		Map<String, String> qualification = new HashMap<String, String>();
54  		
55  		return isAuthorized(principalId, permissionName, qualification, asOfDate);
56  	}
57  
58  	@Override
59  	public boolean isAuthorized(String principalId, String permissionName, Map<String, String> qualification, DateTime asOfDate) {
60  		return getPermissionService().isAuthorized(principalId, KPMENamespace.KPME_TK.getNamespaceCode(), permissionName, qualification);
61  	}
62      
63      @Override
64  	public boolean isAuthorizedByTemplate(String principalId, String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails, DateTime asOfDate) {
65  		Map<String, String> qualification = new HashMap<String, String>();
66  		
67  		return isAuthorizedByTemplate(principalId, namespaceCode, permissionTemplateName, permissionDetails, qualification, asOfDate);
68  	}
69  	
70      @Override
71  	public boolean isAuthorizedByTemplate(String principalId, String namespaceCode, String permissionTemplateName, Map<String, String> permissionDetails, Map<String, String> qualification, DateTime asOfDate) {
72  		return getPermissionService().isAuthorizedByTemplate(principalId, namespaceCode, permissionTemplateName, permissionDetails, qualification);
73  	}
74  
75      private boolean updateCanEditTimeblockPerm(String principalId, CalendarBlockPermissions perms, boolean canEdit) {
76          perms.putCanEdit(principalId, canEdit);
77          HrServiceLocator.getHRPermissionService().updateTimeBlockPermissions(perms);
78          return canEdit;
79      }
80  
81      private boolean updateCanEditAllFieldsTimeblockPerm(String principalId, CalendarBlockPermissions perms, boolean canEditAll) {
82          perms.putCanEditAllFields(principalId, canEditAll);
83          HrServiceLocator.getHRPermissionService().updateTimeBlockPermissions(perms);
84          return canEditAll;
85      }
86  
87      private boolean updateCanDeleteTimeblockPerm(String principalId, CalendarBlockPermissions perms, boolean canDelete) {
88          perms.putCanDelete(principalId, canDelete);
89          HrServiceLocator.getHRPermissionService().updateTimeBlockPermissions(perms);
90          return canDelete;
91      }
92  
93      private boolean updateCanEditOvtPerm(String principalId, CalendarBlockPermissions perms, boolean canEditOvt) {
94          perms.putCanEditOvertimeEarnCode(principalId, canEditOvt);
95          HrServiceLocator.getHRPermissionService().updateTimeBlockPermissions(perms);
96          return canEditOvt;
97      }
98  
99      @Override
100     public boolean canEditTimeBlock(String principalId, TimeBlock timeBlock) {
101         if (principalId != null) {
102             //check cache!
103             CalendarBlockPermissions perms = HrServiceLocator.getHRPermissionService().getTimeBlockPermissions(timeBlock.getTkTimeBlockId());
104             Boolean canEdit = perms.isPrincipalCanEdit(principalId);
105 
106             if (canEdit != null) {
107                 return canEdit;
108             }
109             if(userHasRolesToEditTimeBlock(principalId, timeBlock)) {
110             	return updateCanEditTimeblockPerm(principalId, perms, true);
111             } else {
112             	return updateCanEditTimeblockPerm(principalId, perms, false);
113             }
114         }
115         return false;
116     }
117     
118     @Override
119     public boolean userHasRolesToEditTimeBlock(String principalId, TimeBlock aTimeBlock) {
120     	// system admin, TimeSysAdmin and time location admin have full permissions when they are not working on their own timesheet, no need to check earnCodeSecurity in this case
121     	if(this.userHasTimeSysLocationAdminRoles(principalId,aTimeBlock) && !StringUtils.equals(TkContext.getTargetPrincipalId(), principalId)) {
122     		return true;
123         }
124     	
125     	// timesheet is cancelled/disapproved, then no edit permissions for roles other than sys/location admins
126     	if (StringUtils.isNotBlank(aTimeBlock.getDocumentId())) {
127         	DocumentStatus documentStatus = KewApiServiceLocator.getWorkflowDocumentService().getDocumentStatus(aTimeBlock.getDocumentId());
128         	if (DocumentStatus.CANCELED.equals(documentStatus) || DocumentStatus.DISAPPROVED.equals(documentStatus)) {
129         		return false;
130         	}
131         }    	
132     	
133     	Job job = HrServiceLocator.getJobService().getJob(
134                  HrContext.getTargetPrincipalId(), aTimeBlock.getJobNumber(),
135                  aTimeBlock.getEndDateTime().toLocalDate());
136     	
137         PayType payType = HrServiceLocator.getPayTypeService().getPayType(
138                 job.getHrPayType(), aTimeBlock.getEndDateTime().toLocalDate()); 
139         
140         DateTime asOfDate = LocalDate.now().toDateTimeAtStartOfDay();
141         boolean isReviewerOrApprover = HrServiceLocator.getKPMERoleService().principalHasRoleInWorkArea(principalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.REVIEWER.getRoleName(), aTimeBlock.getWorkArea(), asOfDate)
142 						  		    	|| HrServiceLocator.getKPMERoleService().principalHasRoleInWorkArea(principalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.APPROVER.getRoleName(), aTimeBlock.getWorkArea(), asOfDate)
143 						  		    	|| HrServiceLocator.getKPMERoleService().principalHasRoleInWorkArea(principalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.APPROVER_DELEGATE.getRoleName(), aTimeBlock.getWorkArea(), asOfDate);
144         boolean isPayrollProcessor = HrServiceLocator.getKPMERoleService().principalHasRoleInDepartment(principalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.PAYROLL_PROCESSOR.getRoleName(), job.getDept(), asOfDate)
145 		    							|| HrServiceLocator.getKPMERoleService().principalHasRoleInDepartment(principalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.PAYROLL_PROCESSOR_DELEGATE.getRoleName(), job.getDept(), asOfDate);
146         
147         // when the earn code is regular earn code, don't use earn code security to determine the permissions
148         if (payType != null && StringUtils.equals(payType.getRegEarnCode(), aTimeBlock.getEarnCode())) {
149         	if (aTimeBlock.getPrincipalId().equals(principalId)) {
150         		 TimeCollectionRule tcr = TkServiceLocator.getTimeCollectionRuleService().getTimeCollectionRule(job.getDept(),aTimeBlock.getWorkArea(), payType.getPayType(), aTimeBlock.getBeginDateTime().toLocalDate());
151         		 if (tcr == null || tcr.isClockUserFl()) {
152                      //if there is only 1 assignment here, it isn't editable.
153                      TimesheetDocument td = TkServiceLocator.getTimesheetService().getTimesheetDocument(aTimeBlock.getDocumentId());
154                      Map<String, String> assignments = td.getAssignmentDescriptions(true);
155                      if (assignments.size() <= 1) {
156                          return false;
157                      } else {
158                     	 return true;
159                      }
160                  } else {
161                 	 return true;
162                  }
163         	} else {
164         		// approver, reviewer and payroll processor should have edit access to regular earn code
165 	        	  if(isReviewerOrApprover || isPayrollProcessor) {
166 	        		  return true;
167 	        	  } else {
168 	        		  return false;
169 	        	  }
170         	}
171         		  
172         }
173 
174     	// use earnCodeSecurity employee/approver/payrollProcessor flags to determine if the user has edit permission to the earn code 
175     	List<EarnCodeSecurity> earnCodeSecurityList = HrServiceLocator
176                   .getEarnCodeSecurityService().getEarnCodeSecurities(
177                           job.getDept(), job.getHrSalGroup(),
178                           job.getLocation(), aTimeBlock.getEndDateTime().toLocalDate());
179     	// no earn code security found, then no edit permissions for roles other than sys/location admins
180     	if(CollectionUtils.isEmpty(earnCodeSecurityList))
181     		return false; 
182     	
183     	// user working on his/her own timesheet
184         if (StringUtils.equals(TkContext.getTargetPrincipalId(), principalId)) {    	
185         	boolean employeeSecurityFlag = false;
186         	for(EarnCodeSecurity ecs : earnCodeSecurityList ) {
187         		if(ecs.isEmployee() && StringUtils.equals(ecs.getEarnCode(), aTimeBlock.getEarnCode())) {
188         			employeeSecurityFlag = true;
189         			break;
190         		}
191         	}        	
192         	if(employeeSecurityFlag) {	// found earn code security with employee flag
193         		// regular earn codes
194 		    	if (StringUtils.equals(payType.getRegEarnCode(), aTimeBlock.getEarnCode())) {		             
195 		            boolean moreThanOneClockAssignment = this.userHasMoreThanOneClockAssignment(principalId, aTimeBlock.getBeginDateTime().toLocalDate());
196 		            //If you are a clock user and you have only one Clock assignment you should not be allowed to change the time block
197 		            if(!moreThanOneClockAssignment){
198 		             	TimeCollectionRule tcr = TkServiceLocator.getTimeCollectionRuleService().getTimeCollectionRule(job.getDept(),aTimeBlock.getWorkArea(),job.getHrPayType(), aTimeBlock.getBeginDateTime().toLocalDate());
199 		                 return  (tcr != null && !tcr.isClockUserFl());
200 		            } else {
201 		                return true;
202 		            }
203 		        } else {
204 		        	return true;
205 		        }
206         	}        	
207         } else {        // user not working on his/her own timesheet	
208 		    // Reviewer/Approver/Approver Delegate
209 		    if(isReviewerOrApprover) {
210 		    	for(EarnCodeSecurity ecs : earnCodeSecurityList ) {
211 	        		if(ecs.isApprover() && StringUtils.equals(ecs.getEarnCode(),aTimeBlock.getEarnCode()))
212 	        			return true;
213 	        	}
214 	        }
215 		    
216 		    // Payroll Processor / Payroll Processor Delegate
217 		    if(isPayrollProcessor) {
218 		    	for(EarnCodeSecurity ecs : earnCodeSecurityList ) {
219 	        		if(ecs.isPayrollProcessor() && StringUtils.equals(ecs.getEarnCode(),aTimeBlock.getEarnCode()))
220 	        			return true;
221 	        	}
222 	        }
223         }
224         
225 	    // no eligible roles found
226 	    return false;
227     }
228     
229     private boolean userHasMoreThanOneClockAssignment(String principalId, LocalDate aLocalDate) {
230     	 List<Assignment> assignments = HrServiceLocator.getAssignmentService().getAssignments(principalId, aLocalDate);
231          int clockAssignNumber = 0;
232          for(Assignment anAssign : assignments) {
233         	 Job aJob = HrServiceLocator.getJobService().getJob(HrContext.getTargetPrincipalId(), anAssign.getJobNumber(), aLocalDate);
234         	 TimeCollectionRule tcr = TkServiceLocator.getTimeCollectionRuleService().getTimeCollectionRule(anAssign.getDept(), anAssign.getWorkArea(),aJob.getHrPayType(), aLocalDate);
235         	 if(tcr != null && tcr.isClockUserFl())
236         		 clockAssignNumber ++;
237          }
238          return clockAssignNumber > 1;
239     }
240 
241     @Override
242 	public boolean userHasTimeSysLocationAdminRoles(String principalId,TimeBlock aTimeBlock) {
243 		DateTime asOfDate = LocalDate.now().toDateTimeAtStartOfDay();
244 		// system admin or TimeSysAdmin has full permissions when they are not working on their own timesheet, no need to check earnCodeSecurity in this case
245 		if(HrServiceLocator.getKPMEGroupService().isMemberOfSystemAdministratorGroup(principalId, asOfDate )
246 				|| HrServiceLocator.getKPMERoleService().principalHasRole(principalId, KPMENamespace.KPME_TK.getNamespaceCode(), KPMERole.TIME_SYSTEM_ADMINISTRATOR.getRoleName(), asOfDate)) {
247 			return true;
248 		}		    
249 		// use job to find the department, then use the location from Department to get the location roles 
250 		Job aJob = HrServiceLocator.getJobService().getJob(aTimeBlock.getPrincipalId(), aTimeBlock.getJobNumber(), aTimeBlock.getEndDateTime().toLocalDate());
251 		if(aJob != null) {
252 			Department aDept = HrServiceLocator.getDepartmentService().getDepartmentWithoutRoles(aJob.getDept(), aJob.getEffectiveLocalDate());
253 			if(aDept != null) {
254 				// TimeLocationAdmin
255 			    if(HrServiceLocator.getKPMERoleService().principalHasRoleInLocation(principalId, KPMENamespace.KPME_TK.getNamespaceCode(), KPMERole.TIME_LOCATION_ADMINISTRATOR.getRoleName(), aDept.getLocation(), asOfDate))
256 			    	return true;
257 			}
258 		}
259 		return false;
260 	} 
261     
262     @Override
263     public boolean canEditTimeBlockAllFields(String principalId, TimeBlock timeBlock) {
264         if (principalId != null) {
265             CalendarBlockPermissions perms = HrServiceLocator.getHRPermissionService().getTimeBlockPermissions(timeBlock.getTkTimeBlockId());
266             Boolean canEditAll = perms.isPrincipalCanEditAllFields(principalId);
267 
268             if (canEditAll != null) {
269                 return canEditAll;
270             }
271 
272             // if the user does not have permission to edit the time block at all, no need to check any further
273             // this cover the case when the user only have one clock assignment, so the regular earn code Clocked time block is not editable
274             if(!this.canEditTimeBlock(principalId, timeBlock)) {
275             	return updateCanEditAllFieldsTimeblockPerm(principalId, perms, false);
276             } else {
277             	// user is working on his/her own timesheet and has more than one clock assignment,
278             	// user should only be able to edit assignment list field if the earn code is a regular one
279 	          if(principalId.equals(HrContext.getTargetPrincipalId())) {       	
280 	        	  Job job = HrServiceLocator.getJobService().getJob(
281 		        		  HrContext.getTargetPrincipalId(), timeBlock.getJobNumber(),
282 		        		  timeBlock.getEndDateTime().toLocalDate());
283 		          PayType payType = job.getPayTypeObj();		          
284 		          TimeCollectionRule tcr = TkServiceLocator.getTimeCollectionRuleService().
285 		        		  getTimeCollectionRule(job.getDept(), timeBlock.getWorkArea(),job.getHrPayType(),timeBlock.getBeginDateTime().toLocalDate());
286 		          
287 	              if (tcr != null && tcr.isClockUserFl() && StringUtils.equals(payType.getRegEarnCode(), timeBlock.getEarnCode())) {
288 	                  return updateCanEditAllFieldsTimeblockPerm(principalId, perms, false);
289 	              } else {
290 	            	  return updateCanEditAllFieldsTimeblockPerm(principalId, perms, true); 
291 	              }
292 	        	  
293 	            } else {
294 	            	return updateCanEditAllFieldsTimeblockPerm(principalId, perms, true);
295 	            }
296             }
297         }
298 
299         return false;
300     }
301 
302     @Override
303     public boolean canDeleteTimeBlock(String principalId, TimeBlock timeBlock) {
304         if (principalId != null) {
305             CalendarBlockPermissions perms = HrServiceLocator.getHRPermissionService().getTimeBlockPermissions(timeBlock.getTkTimeBlockId());
306             Boolean canDelete = perms.isPrincipalCanDelete(principalId);
307 
308             if (canDelete != null) {
309                 return canDelete;
310             }
311        
312             // if user cannot edit time block, they cannot delete it either
313             if(!this.canEditTimeBlock(principalId, timeBlock)) {
314             	return updateCanDeleteTimeblockPerm(principalId, perms, false);
315             } else {
316             	 Job job = HrServiceLocator.getJobService().getJob(
317                          HrContext.getTargetPrincipalId(), timeBlock.getJobNumber(),
318                          timeBlock.getEndDateTime().toLocalDate());
319                  PayType payType = HrServiceLocator.getPayTypeService().getPayType(
320                          job.getHrPayType(), timeBlock.getEndDateTime().toLocalDate());
321             	  if (principalId.equals(HrContext.getTargetPrincipalId())) {
322             		  // if the user is working on his/her own timesheet and the time block is clock generated, user should not be able to delete the time block
323             		  if(timeBlock.getClockLogCreated()) {
324       	                return updateCanDeleteTimeblockPerm(principalId, perms, false);
325       				  }
326             		  //if on a regular earncode and the user is a clock user and this is the users timesheet, do not allow to be deleted
327             		  if(StringUtils.equals(payType.getRegEarnCode(), timeBlock.getEarnCode())) {
328       	            	TimeCollectionRule tcr = TkServiceLocator.getTimeCollectionRuleService().getTimeCollectionRule(job.getDept(),timeBlock.getWorkArea(),payType.getPayType(),timeBlock.getEndDateTime().toLocalDate());
329       	            	
330       	            	if (tcr == null || tcr.isClockUserFl()) {
331       	            		if (StringUtils.equals(principalId,HrContext.getTargetPrincipalId())) {
332       	                        return updateCanDeleteTimeblockPerm(principalId, perms, false);
333       		                }  else {
334       	                        return updateCanDeleteTimeblockPerm(principalId, perms, true);
335       		                }
336       	                }
337       	              }
338             		  return updateCanDeleteTimeblockPerm(principalId, perms, true);
339             	  } else {
340             		  // user not working on his/her own timesheet and have permission to edit, so user should be able to delete the time block
341             		  return updateCanDeleteTimeblockPerm(principalId, perms, true); 
342             	  }
343             }
344         }
345         return false;
346     }
347     
348     @Override
349     public boolean canEditOvertimeEarnCode(String principalId, TimeBlock timeBlock) {
350         if (principalId != null) {
351             CalendarBlockPermissions perms = HrServiceLocator.getHRPermissionService().getTimeBlockPermissions(timeBlock.getTkTimeBlockId());
352             Boolean canEdit = perms.isPrincipalCanEditOvertimeEarnCode(principalId);
353             if (canEdit != null) {
354                 return canEdit;
355             }
356             
357             boolean workingOnOwnTimesheet = principalId.equals(timeBlock.getPrincipalId());
358             // sys admin/Time sys admin/Time Location admins should have access to overtime earn code if they are not working on their own time sheet
359             if(this.userHasTimeSysLocationAdminRoles(principalId, timeBlock) && !workingOnOwnTimesheet)
360             	return updateCanEditOvtPerm(principalId, perms, true);
361             
362             Long workArea = timeBlock.getWorkArea();
363             WorkArea workAreaObj = HrServiceLocator.getWorkAreaService().getWorkAreaWithoutRoles(workArea, timeBlock.getEndDateTime().toLocalDate());
364             String department = workAreaObj.getDept();
365             DateTime tbDateTime = timeBlock.getBeginDateTime();	// datetime used to retrieve user roles
366             
367             if(workingOnOwnTimesheet) {
368             	// when user is working on his/her own timesheet, the user can only edit overtime if overtime edit role is "employee"
369             	if (StringUtils.equals(workAreaObj.getOvertimeEditRole(), "Employee"))
370             		return updateCanEditOvtPerm(principalId, perms, true);
371             	else 
372             		return updateCanEditOvtPerm(principalId, perms, false);
373             } else {	// user is not working on his/her own timesheet
374 	            // when workarea's overtime edit role is employee, approver/approver delegate/payroll processor/payroll processor delegate should all have edit permission
375 	            if (StringUtils.equals(workAreaObj.getOvertimeEditRole(), "Employee")) {
376             		boolean toReturn = this.isApproverForWorkArea(principalId, workArea, tbDateTime)
377             							|| this.isPayrollProcessorForDepartment(principalId, department, tbDateTime);
378             		return updateCanEditOvtPerm(principalId, perms, toReturn);
379 	            } else if (StringUtils.equals(workAreaObj.getOvertimeEditRole(), KPMERole.APPROVER.getRoleName())) {
380 	            	// when overtime edit role is approver, only approver/approver delegate/payroll processor/payroll processor delegate have edit permission
381 	                boolean toReturn = this.isApproverForWorkArea(principalId, workArea, tbDateTime)
382 	                        			|| this.isPayrollProcessorForDepartment(principalId, department, tbDateTime);
383 	                return updateCanEditOvtPerm(principalId, perms, toReturn);
384 	            } else if(StringUtils.equals(workAreaObj.getOvertimeEditRole(), KPMERole.PAYROLL_PROCESSOR.getRoleName())) {
385 	            	// when overtime edit role is Payroll processor, only payroll processor/payroll processor delegate have edit permission
386 	                boolean toReturn = isPayrollProcessorForDepartment(principalId, department, tbDateTime);
387 	                return updateCanEditOvtPerm(principalId, perms, toReturn);
388 	            } else if(StringUtils.equals(workAreaObj.getOvertimeEditRole(), KPMERole.TIME_DEPARTMENT_ADMINISTRATOR.getRoleName())) {
389 	            	// when overtime edit role is Time Dept Admin, only Time Dept Admin has edit permission
390 	                boolean toReturn = HrServiceLocator.getKPMERoleService()
391 	                		.principalHasRoleInDepartment(principalId, KPMENamespace.KPME_TK.getNamespaceCode(), KPMERole.TIME_DEPARTMENT_ADMINISTRATOR.getRoleName(), department, tbDateTime);
392 	                return updateCanEditOvtPerm(principalId, perms, toReturn);
393 	            }
394             }
395         }
396         return false;
397     }
398     
399     @Override
400     public boolean isPayrollProcessorForDepartment(String principalId, String dept, DateTime asOfDate) {
401     	return HrServiceLocator.getKPMERoleService().principalHasRoleInDepartment(principalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.PAYROLL_PROCESSOR.getRoleName(), dept, asOfDate)
402     			|| HrServiceLocator.getKPMERoleService().principalHasRoleInDepartment(principalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.PAYROLL_PROCESSOR_DELEGATE.getRoleName(), dept, asOfDate);
403     }
404     
405     @Override
406     public boolean isApproverForWorkArea(String principalId, Long workArea, DateTime asOfDate) {
407     	return HrServiceLocator.getKPMERoleService().principalHasRoleInWorkArea(principalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.APPROVER_DELEGATE.getRoleName(), workArea, asOfDate)
408     			|| HrServiceLocator.getKPMERoleService().principalHasRoleInWorkArea(principalId, KPMENamespace.KPME_HR.getNamespaceCode(), KPMERole.APPROVER.getRoleName(), workArea, asOfDate);
409     }
410 
411 
412 	public TimesheetService getTimesheetService() {
413 		return timesheetService;
414 	}
415 
416 	public void setTimesheetService(TimesheetService timesheetService) {
417 		this.timesheetService = timesheetService;
418 	}
419 }