001 /**
002 * Copyright 2004-2012 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.hr.time.roles;
017
018 import java.util.HashMap;
019 import java.util.HashSet;
020 import java.util.List;
021 import java.util.Map;
022 import java.util.Set;
023
024 import org.apache.commons.lang.StringUtils;
025 import org.kuali.hr.job.Job;
026 import org.kuali.hr.time.assignment.Assignment;
027 import org.kuali.hr.time.department.Department;
028 import org.kuali.hr.time.service.base.TkServiceLocator;
029 import org.kuali.hr.time.timesheet.TimesheetDocument;
030 import org.kuali.hr.time.util.TKContext;
031 import org.kuali.hr.time.util.TKUtils;
032 import org.kuali.hr.time.util.TkConstants;
033 import org.kuali.rice.krad.util.GlobalVariables;
034
035 /**
036 * TkUserRoles encapsulates the concept of roles for a single user and provides
037 * lookup methods for quick Role checking. This object will be stored in TkUser.
038 */
039 public class TkUserRoles implements UserRoles {
040 private boolean synchronousAssignments = false;
041 private TkRole globalViewOnly;
042 private TkRole systemAdmin;
043 private String principalId;
044
045 private Map<String, TkRole> orgAdminRolesDept = new HashMap<String, TkRole>();
046 private Map<String, TkRole> orgAdminRolesChart = new HashMap<String, TkRole>();
047 private Map<Long, TkRole> approverRoles = new HashMap<Long, TkRole>();
048 private Map<Long, TkRole> approverDelegateRoles = new HashMap<Long, TkRole>();
049 private Map<Long, TkRole> reviewerRoles = new HashMap<Long, TkRole>();
050
051 private Map<String, TkRole> deptViewOnlyRoles = new HashMap<String, TkRole>();
052 private Set<String> activeAssignmentIds = new HashSet<String>();
053
054 public static TkUserRoles getUserRoles(String principalId) {
055 List<TkRole> roles = TkServiceLocator.getTkRoleService().getRoles(principalId, TKUtils.getCurrentDate());
056 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignments(principalId, TKUtils.getCurrentDate());
057
058 return new TkUserRoles(principalId, roles, assignments);
059 }
060
061 /**
062 * Does not keep reference to the assignment objects. We just need the IDs,
063 * so in future refactoring, if we have a lighter weight call to obtain
064 * assignments, we could use that and modify this code.
065 *
066 * @param roles
067 * @param assignments
068 */
069 private TkUserRoles(String principalId, List<TkRole> roles, List<Assignment> assignments) {
070 this.principalId = principalId;
071 setRoles(roles);
072 setAssignments(assignments);
073 }
074
075 @Override
076 public boolean isLocationAdmin() {
077 return getOrgAdminCharts().size() > 0;
078 }
079
080 @Override
081 public boolean isDepartmentAdmin() {
082 return getOrgAdminDepartments().size() > 0;
083 }
084
085 public String getPrincipalId() {
086 return principalId;
087 }
088
089 public void setPrincipalId(String principalId) {
090 this.principalId = principalId;
091 }
092
093 @Override
094 public Set<Long> getApproverWorkAreas() {
095 Set<Long> workAreas = new HashSet<Long>();
096 workAreas.addAll(approverRoles.keySet());
097 workAreas.addAll(approverDelegateRoles.keySet());
098 return workAreas;
099 }
100
101 @Override
102 public Set<Long> getReviewerWorkAreas() {
103 return reviewerRoles.keySet();
104 }
105
106 @Override
107 public Set<String> getOrgAdminDepartments() {
108 return orgAdminRolesDept.keySet();
109 }
110
111 @Override
112 public Set<String> getOrgAdminCharts() {
113 return orgAdminRolesChart.keySet();
114 }
115
116 @Override
117 public Set<String> getDepartmentViewOnlyDepartments() {
118 return deptViewOnlyRoles.keySet();
119 }
120
121 /**
122 * Accessor method to obtain the Set of active Assignment ids for the
123 * current employee.
124 *
125 * @return a Set of active assignment IDs
126 */
127 @Override
128 public Set<String> getActiveAssignmentIds() {
129 return activeAssignmentIds;
130 }
131
132 @Override
133 public boolean isSystemAdmin() {
134 return systemAdmin != null;
135 }
136
137 @Override
138 public boolean isGlobalViewOnly() {
139 return globalViewOnly != null;
140 }
141
142 public boolean isDeptViewOnly() {
143 return deptViewOnlyRoles.size() > 0;
144 }
145
146 @Override
147 public boolean isSynchronous() {
148 return synchronousAssignments;
149 }
150
151 public boolean isReviewer() {
152 return TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId()).getReviewerWorkAreas().size() > 0;
153 }
154
155 public boolean isApprover() {
156 return TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId()).getApproverWorkAreas().size() > 0;
157 }
158
159 /**
160 * Place the TkRole objects in the provided List into their appropriate
161 * buckets for fast lookup.
162 *
163 * @param roles A List of TkRole objects for the current user.
164 */
165 public void setRoles(List<TkRole> roles) {
166 for (TkRole role : roles) {
167 if (role.getRoleName().equals(TkConstants.ROLE_TK_APPROVER)) {
168 approverRoles.put(role.getWorkArea(), role);
169 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_APPROVER_DELEGATE)) {
170 approverDelegateRoles.put(role.getWorkArea(), role);
171 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_LOCATION_ADMIN) ||
172 role.getRoleName().equals(TkConstants.ROLE_LV_DEPT_ADMIN)) {
173 if (!StringUtils.isEmpty(role.getChart())) {
174 orgAdminRolesChart.put(role.getChart(), role);
175 List<Department> ds = TkServiceLocator.getDepartmentService().getDepartments(role.getChart(), TKUtils.getCurrentDate());
176 for (Department d : ds) {
177 orgAdminRolesDept.put(d.getDept(), role);
178 }
179 }
180 } else if (StringUtils.equals(role.getRoleName(), TkConstants.ROLE_TK_LOCATION_VO)) {
181 if (!StringUtils.isEmpty(role.getChart())) {
182 List<Department> ds = TkServiceLocator.getDepartmentService().getDepartments(role.getChart(), TKUtils.getCurrentDate());
183 for (Department dept : ds) {
184 deptViewOnlyRoles.put(dept.getDept(), role);
185 }
186
187 }
188 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_SYS_ADMIN)) {
189 systemAdmin = role;
190 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_DEPT_VO)) {
191 deptViewOnlyRoles.put(role.getDepartment(), role);
192 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_DEPT_ADMIN)) {
193 orgAdminRolesDept.put(role.getDepartment(), role);
194 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_GLOBAL_VO)) {
195 globalViewOnly = role;
196 } else if (role.getRoleName().equals(TkConstants.ROLE_TK_REVIEWER)) {
197 reviewerRoles.put(role.getWorkArea(), role);
198 }
199 }
200 }
201
202 public void setAssignments(List<Assignment> assignments) {
203 for (Assignment a : assignments) {
204 activeAssignmentIds.add(a.getTkAssignmentId());
205 if (a.isSynchronous())
206 synchronousAssignments = true;
207 }
208 }
209
210 @Override
211 public boolean isActiveEmployee() {
212 return this.activeAssignmentIds.size() > 0;
213 }
214
215 @Override
216 public boolean isTimesheetApprover() {
217 return this.isSystemAdmin() || this.approverRoles.size() > 0 || this.approverDelegateRoles.size() > 0 || this.orgAdminRolesDept.size() > 0;
218 }
219
220 public boolean isTimesheetReviewer() {
221 return this.getReviewerWorkAreas().size() > 0;
222 }
223
224 @Override
225 public boolean isAnyApproverActive() {
226 return this.approverRoles.size() > 0 || this.approverDelegateRoles.size() > 0;
227 }
228
229
230 @Override
231 public boolean isApproverForTimesheet(TimesheetDocument doc) {
232 boolean approver = false;
233
234 if (this.isSystemAdmin()) {
235 return true;
236 }
237
238 List<Assignment> assignments = doc.getAssignments();
239 for (Assignment assignment : assignments) {
240 if (this.approverRoles.containsKey(assignment.getWorkArea()) || this.approverDelegateRoles.containsKey(assignment.getWorkArea())) {
241 return true;
242 }
243 }
244
245 return approver;
246 }
247
248 @Override
249 public boolean isApproverForTimesheet(String docId) {
250 boolean approver = false;
251
252 TimesheetDocument doc = TkServiceLocator.getTimesheetService().getTimesheetDocument(docId);
253 if (doc != null)
254 approver = isApproverForTimesheet(doc);
255
256 return approver;
257 }
258
259 @Override
260 public boolean isDocumentWritable(TimesheetDocument document) {
261 boolean writable = false;
262
263 // Quick escape.
264 if (document == null)
265 return writable;
266
267 // Sysadmin
268 writable = this.isSystemAdmin();
269 // Owner (and not enroute/final)
270 writable |= (StringUtils.equals(this.principalId, document.getPrincipalId())
271 && (StringUtils.equals(TkConstants.ROUTE_STATUS.INITIATED, document.getDocumentHeader().getDocumentStatus()) ||
272 StringUtils.equals(TkConstants.ROUTE_STATUS.SAVED, document.getDocumentHeader().getDocumentStatus()) ||
273 (StringUtils.equals(TkConstants.ROUTE_STATUS.ENROUTE, document.getDocumentHeader().getDocumentStatus()))));
274
275
276 if (!writable) {
277 // Departmental View Only? || Reviewer || Org Admin || Approver
278 // (document object iteration)
279 List<Assignment> assignments = document.getAssignments();
280 for (Assignment assignment : assignments) {
281 String dept = assignment.getDept();
282 Long wa = assignment.getWorkArea();
283 // Dept admins should not have write access
284 //writable |= this.orgAdminRolesDept.containsKey(dept);
285 writable |= this.approverRoles.containsKey(wa);
286 writable |= this.approverDelegateRoles.containsKey(wa);
287 writable |= this.reviewerRoles.containsKey(wa);
288 }
289 }
290
291 return writable;
292 }
293
294 @Override
295 public boolean isDocumentWritable(String documentId) {
296 return isDocumentWritable(TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId));
297 }
298
299 @Override
300 public boolean isDocumentReadable(String documentId) {
301 boolean readable = false;
302
303 if (documentId != null) {
304 return isDocumentReadable(TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId));
305 }
306
307 return readable;
308 }
309
310 @Override
311 public boolean isDocumentReadable(TimesheetDocument document) {
312 boolean readable = false;
313
314 // Quick escape.
315 if (document == null)
316 return readable;
317
318 // Sysadmin
319 readable = this.isSystemAdmin();
320 // Owner
321 readable |= StringUtils.equals(this.principalId, document.getPrincipalId());
322 // Global VO
323 readable |= this.isGlobalViewOnly();
324
325 if (!readable) {
326 // Departmental View Only? || Reviewer || Org Admin || Approver
327 // (document object iteration)
328 List<Assignment> assignments = document.getAssignments();
329 for (Assignment assignment : assignments) {
330 String dept = assignment.getDept();
331 Long wa = assignment.getWorkArea();
332
333 readable |= this.orgAdminRolesDept.containsKey(dept);
334 readable |= this.approverRoles.containsKey(wa);
335 readable |= this.approverDelegateRoles.containsKey(wa);
336 readable |= this.reviewerRoles.containsKey(wa);
337 readable |= this.deptViewOnlyRoles.containsKey(dept);
338 readable |= this.reviewerRoles.containsKey(wa);
339 }
340 }
341
342 return readable;
343 }
344
345 private boolean isLocationAdmin(TimesheetDocument doc) {
346 for (Assignment assign : doc.getAssignments()) {
347 String location = assign.getJob().getLocation();
348 return this.orgAdminRolesChart.containsKey(location);
349 }
350 return false;
351 }
352
353 private boolean isDepartmentAdmin(TimesheetDocument doc) {
354 for (Assignment assign : doc.getAssignments()) {
355 String dept = assign.getDept();
356 return this.orgAdminRolesDept.containsKey(dept);
357 }
358 return false;
359 }
360
361 @Override
362 public boolean canSubmitTimesheet(TimesheetDocument doc) {
363 if (StringUtils.equals(TKContext.getPrincipalId(), doc.getPrincipalId())) {
364 return true;
365 }
366
367 if (this.isApproverForTimesheet(doc)) {
368 return true;
369 }
370
371 //System admins can route the document as well as the employee
372 if (this.isSystemAdmin()) {
373 return true;
374 }
375 return false;
376 }
377
378 @Override
379 public boolean canSubmitTimesheet(String docId) {
380 TimesheetDocument doc = TkServiceLocator.getTimesheetService().getTimesheetDocument(docId);
381 return canSubmitTimesheet(doc);
382 }
383
384 @Override
385 public boolean isApproverForPerson(String principalId) {
386 List<Assignment> lstAssignment = TkServiceLocator.getAssignmentService().getAssignments(principalId, TKUtils.getCurrentDate());
387
388 for (Assignment assignment : lstAssignment) {
389 if (getUserRoles(GlobalVariables.getUserSession().getPrincipalId()).getApproverWorkAreas().contains(assignment.getWorkArea())) {
390 return true;
391 }
392 }
393
394 return false;
395
396 }
397
398 @Override
399 public boolean isDepartmentAdminForPerson(String principalId) {
400 UserRoles userRoles = getUserRoles(GlobalVariables.getUserSession().getPrincipalId());
401
402 // Department admin
403 // Department view only
404 if (userRoles.isDepartmentAdmin() || userRoles.isDeptViewOnly()) {
405 List<Job> jobs = TkServiceLocator.getJobService().getJobs(principalId,TKUtils.getCurrentDate());
406 for (Job job : jobs) {
407 if (getOrgAdminDepartments().contains(job.getDept())) {
408 return true;
409 }
410 }
411 }
412
413 return false;
414 }
415
416 @Override
417 public boolean isDeptViewOnlyForPerson(String principalId) {
418 return isDepartmentAdminForPerson(principalId);
419 }
420
421 @Override
422 public boolean isLocationAdminForPerson(String principalId) {
423 List<TkRole> roles = TkServiceLocator.getTkRoleService().getRoles(principalId, TKUtils.getCurrentDate());
424
425 if (roles.size() > 0) {
426 for (TkRole role : roles) {
427 if (this.getOrgAdminCharts().contains(role.getChart())) {
428 return true;
429 }
430 }
431 }
432
433 return false;
434 }
435
436 @Override
437 public boolean isTimesheetReviewerForPerson(String principalId) {
438 List<TkRole> roles = TkServiceLocator.getTkRoleService().getRoles(principalId, TKUtils.getCurrentDate());
439
440 if (roles.size() > 0) {
441 for (TkRole role : roles) {
442 if (this.getReviewerWorkAreas().contains(role.getWorkArea())) {
443 return true;
444 }
445 }
446 }
447
448 return false;
449 }
450 }