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    }