001 /** 002 * Copyright 2004-2013 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.lm.approval.web; 017 018 import java.sql.Date; 019 import java.text.SimpleDateFormat; 020 import java.util.ArrayList; 021 import java.util.Collections; 022 import java.util.Comparator; 023 import java.util.HashSet; 024 import java.util.List; 025 import java.util.Set; 026 027 import javax.servlet.http.HttpServletRequest; 028 import javax.servlet.http.HttpServletResponse; 029 030 import org.apache.commons.collections.CollectionUtils; 031 import org.apache.commons.lang.ObjectUtils; 032 import org.apache.commons.lang.StringUtils; 033 import org.apache.commons.lang.math.NumberUtils; 034 import org.apache.struts.action.ActionForm; 035 import org.apache.struts.action.ActionForward; 036 import org.apache.struts.action.ActionMapping; 037 import org.displaytag.tags.TableTagParameters; 038 import org.displaytag.util.ParamEncoder; 039 import org.hsqldb.lib.StringUtil; 040 import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument; 041 import org.kuali.hr.lm.workflow.LeaveCalendarDocumentHeader; 042 import org.kuali.hr.time.approval.web.ApprovalLeaveSummaryRow; 043 import org.kuali.hr.time.assignment.Assignment; 044 import org.kuali.hr.time.base.web.ApprovalAction; 045 import org.kuali.hr.time.base.web.ApprovalForm; 046 import org.kuali.hr.time.calendar.Calendar; 047 import org.kuali.hr.time.calendar.CalendarEntries; 048 import org.kuali.hr.time.detail.web.ActionFormUtils; 049 import org.kuali.hr.time.person.TKPerson; 050 import org.kuali.hr.time.service.base.TkServiceLocator; 051 import org.kuali.hr.time.util.TKContext; 052 import org.kuali.hr.time.util.TKUser; 053 import org.kuali.hr.time.util.TKUtils; 054 import org.kuali.hr.time.util.TkConstants; 055 import org.kuali.hr.time.workarea.WorkArea; 056 057 public class LeaveApprovalAction extends ApprovalAction{ 058 059 public ActionForward searchResult(ActionMapping mapping, ActionForm form, 060 HttpServletRequest request, HttpServletResponse response) 061 throws Exception { 062 LeaveApprovalActionForm laaf = (LeaveApprovalActionForm)form; 063 064 if (StringUtils.equals("documentId", laaf.getSearchField())) { 065 LeaveCalendarDocumentHeader lcd = TkServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(laaf.getSearchTerm()); 066 laaf.setSearchTerm(lcd != null ? lcd.getPrincipalId() : StringUtils.EMPTY); 067 } 068 069 laaf.setSearchField("principalId"); 070 List<String> principalIds = new ArrayList<String>(); 071 principalIds.add(laaf.getSearchTerm()); 072 List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds); 073 CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(laaf.getHrPyCalendarEntriesId()); 074 if (persons.isEmpty()) { 075 laaf.setLeaveApprovalRows(new ArrayList<ApprovalLeaveSummaryRow>()); 076 laaf.setResultSize(0); 077 } else { 078 this.setApprovalTables(laaf, principalIds, request, payCalendarEntries); 079 080 laaf.setPayCalendarEntries(payCalendarEntries); 081 laaf.setLeaveCalendarDates(TkServiceLocator.getLeaveSummaryService().getLeaveSummaryDates(payCalendarEntries)); 082 083 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignments(laaf.getSearchTerm(), payCalendarEntries.getEndPeriodDate()); 084 if(!assignments.isEmpty()){ 085 for(Long wa : laaf.getWorkAreaDescr().keySet()){ 086 for (Assignment assign : assignments) { 087 if (assign.getWorkArea().toString().equals(wa.toString())) { 088 laaf.setSelectedWorkArea(wa.toString()); 089 break; 090 } 091 } 092 } 093 } 094 } 095 096 return mapping.findForward("basic"); 097 } 098 099 public ActionForward approve(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 100 LeaveApprovalActionForm laaf = (LeaveApprovalActionForm) form; 101 102 List<ApprovalLeaveSummaryRow> lstLeaveRows = laaf.getLeaveApprovalRows(); 103 for (ApprovalLeaveSummaryRow ar : lstLeaveRows) { 104 if (ar.isApprovable() && StringUtils.equals(ar.getSelected(), "on")) { 105 String documentNumber = ar.getDocumentId(); 106 LeaveCalendarDocument lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(documentNumber); 107 TkServiceLocator.getLeaveCalendarService().approveLeaveCalendar(TKContext.getPrincipalId(), lcd); 108 } 109 } 110 111 return mapping.findForward("basic"); 112 } 113 114 public ActionForward selectNewDept(ActionMapping mapping, ActionForm form, 115 HttpServletRequest request, HttpServletResponse response) 116 throws Exception { 117 LeaveApprovalActionForm laaf = (LeaveApprovalActionForm)form; 118 laaf.setSearchField(null); 119 laaf.setSearchTerm(null); 120 121 CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(laaf.getHrPyCalendarEntriesId()); 122 laaf.setPayCalendarEntries(payCalendarEntries); 123 laaf.setLeaveCalendarDates(TkServiceLocator.getLeaveSummaryService().getLeaveSummaryDates(payCalendarEntries)); 124 125 laaf.getWorkAreaDescr().clear(); 126 laaf.setSelectedWorkArea(""); 127 List<WorkArea> workAreas = TkServiceLocator.getWorkAreaService().getWorkAreas(laaf.getSelectedDept(), new java.sql.Date(laaf.getPayBeginDate().getTime())); 128 for(WorkArea wa : workAreas){ 129 if (TKContext.getUser().getApproverWorkAreas().contains(wa.getWorkArea()) 130 || TKContext.getUser().getReviewerWorkAreas().contains(wa.getWorkArea())) { 131 laaf.getWorkAreaDescr().put(wa.getWorkArea(),wa.getDescription()+"("+wa.getWorkArea()+")"); 132 } 133 } 134 135 List<String> principalIds = this.getPrincipalIdsToPopulateTable(laaf); 136 this.setApprovalTables(laaf, principalIds, request, payCalendarEntries); 137 138 this.populateCalendarAndPayPeriodLists(request, laaf); 139 return mapping.findForward("basic"); 140 } 141 142 public ActionForward selectNewWorkArea(ActionMapping mapping, ActionForm form, 143 HttpServletRequest request, HttpServletResponse response) 144 throws Exception { 145 LeaveApprovalActionForm laaf = (LeaveApprovalActionForm)form; 146 laaf.setSearchField(null); 147 laaf.setSearchTerm(null); 148 149 CalendarEntries payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(laaf.getHrPyCalendarEntriesId()); 150 laaf.setLeaveCalendarDates(TkServiceLocator.getLeaveSummaryService().getLeaveSummaryDates(payCalendarEntries)); 151 152 List<String> idList = this.getPrincipalIdsToPopulateTable(laaf); 153 this.setApprovalTables(laaf, idList , request, payCalendarEntries); 154 155 return mapping.findForward("basic"); 156 } 157 158 private List<String> getPrincipalIdsToPopulateTable(LeaveApprovalActionForm laaf) { 159 List<String> workAreaList = new ArrayList<String>(); 160 if(StringUtil.isEmpty(laaf.getSelectedWorkArea())) { 161 for(Long aKey : laaf.getWorkAreaDescr().keySet()) { 162 workAreaList.add(aKey.toString()); 163 } 164 } else { 165 workAreaList.add(laaf.getSelectedWorkArea()); 166 } 167 java.sql.Date endDate = new java.sql.Date(laaf.getPayEndDate().getTime()); 168 java.sql.Date beginDate = new java.sql.Date(laaf.getPayBeginDate().getTime()); 169 170 List<String> idList = TkServiceLocator.getLeaveApprovalService() 171 .getLeavePrincipalIdsWithSearchCriteria(workAreaList, laaf.getSelectedPayCalendarGroup(), endDate, beginDate, endDate); 172 return idList; 173 } 174 175 private void setApprovalTables(LeaveApprovalActionForm laaf, List<String> principalIds, HttpServletRequest request, CalendarEntries payCalendarEntries) { 176 laaf.setLeaveCalendarDates(TkServiceLocator.getLeaveSummaryService().getLeaveSummaryDates(payCalendarEntries)); 177 178 if (principalIds.isEmpty()) { 179 laaf.setLeaveApprovalRows(new ArrayList<ApprovalLeaveSummaryRow>()); 180 laaf.setResultSize(0); 181 } else { 182 List<TKPerson> persons = TkServiceLocator.getPersonService().getPersonCollection(principalIds); 183 List<ApprovalLeaveSummaryRow> approvalRows = getApprovalLeaveRows(laaf, getSubListPrincipalIds(request, persons)); 184 185 final String sortField = request.getParameter("sortField"); 186 if (StringUtils.equals(sortField, "Name")) { 187 final boolean sortNameAscending = Boolean.parseBoolean(request.getParameter("sortNameAscending")); 188 Collections.sort(approvalRows, new Comparator<ApprovalLeaveSummaryRow>() { 189 @Override 190 public int compare(ApprovalLeaveSummaryRow row1, ApprovalLeaveSummaryRow row2) { 191 if (sortNameAscending) { 192 return ObjectUtils.compare(StringUtils.lowerCase(row1.getName()), StringUtils.lowerCase(row2.getName())); 193 } else { 194 return ObjectUtils.compare(StringUtils.lowerCase(row2.getName()), StringUtils.lowerCase(row1.getName())); 195 } 196 } 197 }); 198 } else if (StringUtils.equals(sortField, "DocumentID")) { 199 final boolean sortDocumentIdAscending = Boolean.parseBoolean(request.getParameter("sortDocumentIDAscending")); 200 Collections.sort(approvalRows, new Comparator<ApprovalLeaveSummaryRow>() { 201 @Override 202 public int compare(ApprovalLeaveSummaryRow row1, ApprovalLeaveSummaryRow row2) { 203 if (sortDocumentIdAscending) { 204 return ObjectUtils.compare(NumberUtils.toInt(row1.getDocumentId()), NumberUtils.toInt(row2.getDocumentId())); 205 } else { 206 return ObjectUtils.compare(NumberUtils.toInt(row2.getDocumentId()), NumberUtils.toInt(row1.getDocumentId())); 207 } 208 } 209 }); 210 } else if (StringUtils.equals(sortField, "Status")) { 211 final boolean sortStatusIdAscending = Boolean.parseBoolean(request.getParameter("sortStatusAscending")); 212 Collections.sort(approvalRows, new Comparator<ApprovalLeaveSummaryRow>() { 213 @Override 214 public int compare(ApprovalLeaveSummaryRow row1, ApprovalLeaveSummaryRow row2) { 215 if (sortStatusIdAscending) { 216 return ObjectUtils.compare(StringUtils.lowerCase(row1.getApprovalStatus()), StringUtils.lowerCase(row2.getApprovalStatus())); 217 } else { 218 return ObjectUtils.compare(StringUtils.lowerCase(row2.getApprovalStatus()), StringUtils.lowerCase(row1.getApprovalStatus())); 219 } 220 } 221 }); 222 } 223 224 laaf.setLeaveApprovalRows(approvalRows); 225 laaf.setResultSize(persons.size()); 226 } 227 } 228 229 @Override 230 public ActionForward loadApprovalTab(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) 231 throws Exception { 232 ActionForward fwd = mapping.findForward("basic"); 233 TKUser user = TKContext.getUser(); 234 LeaveApprovalActionForm laaf = (LeaveApprovalActionForm) form; 235 Date currentDate = null; 236 CalendarEntries payCalendarEntries = null; 237 Calendar currentPayCalendar = null; 238 String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE))); 239 240 241 //reset state 242 if(StringUtils.isBlank(laaf.getSelectedDept())){ 243 resetState(form, request); 244 } 245 246 // Set current pay calendar entries if present. Decide if the current date should be today or the end period date 247 if (laaf.getHrPyCalendarEntriesId() != null) { 248 if(payCalendarEntries == null){ 249 payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(laaf.getHrPyCalendarEntriesId()); 250 } 251 currentDate = payCalendarEntries.getEndPeriodDate(); 252 } else { 253 currentDate = TKUtils.getTimelessDate(null); 254 } 255 Set<Long> workAreas = TkServiceLocator.getTkRoleService().getWorkAreasForApprover(TKContext.getPrincipalId(), currentDate); 256 // should we use all three roles to find work areas??? 257 // List<String> roleNameList = Arrays.asList(TkConstants.ROLE_TK_APPROVER, TkConstants.ROLE_TK_APPROVER_DELEGATE, TkConstants.ROLE_TK_REVIEWER); 258 // Set<Long> workAreas = TkServiceLocator.getTkRoleService().getWorkAreasForRoleNames(TKContext.getPrincipalId(), roleNameList, currentDate); 259 260 List<String> principalIds = new ArrayList<String>(); 261 for (Long workArea : workAreas) { 262 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getActiveAssignmentsForWorkArea(workArea, currentDate); 263 for (Assignment a : assignments) { 264 principalIds.add(a.getPrincipalId()); 265 } 266 } 267 268 // Set calendar groups 269 List<String> calGroups = new ArrayList<String>(); 270 if (CollectionUtils.isNotEmpty(principalIds)) { 271 calGroups = TkServiceLocator.getLeaveApprovalService().getUniqueLeavePayGroupsForPrincipalIds(principalIds); 272 } 273 laaf.setPayCalendarGroups(calGroups); 274 275 if (StringUtils.isBlank(laaf.getSelectedPayCalendarGroup()) 276 && CollectionUtils.isNotEmpty(calGroups)) { 277 laaf.setSelectedPayCalendarGroup(calGroups.get(0)); 278 279 } 280 281 // Set current pay calendar entries if present. Decide if the current date should be today or the end period date 282 if (laaf.getHrPyCalendarEntriesId() != null) { 283 payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntries(laaf.getHrPyCalendarEntriesId()); 284 } else { 285 currentPayCalendar = TkServiceLocator.getCalendarService().getCalendarByGroup(laaf.getSelectedPayCalendarGroup()); 286 if (currentPayCalendar != null) { 287 payCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCurrentCalendarEntriesByCalendarId(currentPayCalendar.getHrCalendarId(), currentDate); 288 } 289 } 290 laaf.setPayCalendarEntries(payCalendarEntries); 291 292 293 if(laaf.getPayCalendarEntries() != null) { 294 populateCalendarAndPayPeriodLists(request, laaf); 295 } 296 setupDocumentOnFormContext(request,laaf,payCalendarEntries, page); 297 return fwd; 298 } 299 300 @Override 301 protected void setupDocumentOnFormContext(HttpServletRequest request,ApprovalForm form, CalendarEntries payCalendarEntries, String page) { 302 super.setupDocumentOnFormContext(request, form, payCalendarEntries, page); 303 LeaveApprovalActionForm laaf = (LeaveApprovalActionForm)form; 304 305 if (payCalendarEntries != null) { 306 laaf.setLeaveCalendarDates(TkServiceLocator.getLeaveSummaryService().getLeaveSummaryDates(payCalendarEntries)); 307 List<String> principalIds = this.getPrincipalIdsToPopulateTable(laaf); 308 this.setApprovalTables(laaf, principalIds, request, payCalendarEntries); 309 laaf.setOnCurrentPeriod(ActionFormUtils.getOnCurrentPeriodFlag(laaf.getPayCalendarEntries())); 310 } 311 } 312 313 public ActionForward selectNewPayCalendar(ActionMapping mapping, ActionForm form, 314 HttpServletRequest request, HttpServletResponse response) 315 throws Exception { 316 // resets the common fields for approval pages 317 super.resetMainFields(form); 318 LeaveApprovalActionForm laaf = (LeaveApprovalActionForm)form; 319 // KPME-909 320 laaf.setLeaveApprovalRows(new ArrayList<ApprovalLeaveSummaryRow>()); 321 322 return loadApprovalTab(mapping, form, request, response); 323 } 324 325 protected List<ApprovalLeaveSummaryRow> getApprovalLeaveRows(LeaveApprovalActionForm laaf, List<TKPerson> assignmentPrincipalIds) { 326 return TkServiceLocator.getLeaveApprovalService().getLeaveApprovalSummaryRows 327 (assignmentPrincipalIds, laaf.getPayCalendarEntries(), laaf.getLeaveCalendarDates()); 328 } 329 330 public void resetState(ActionForm form, HttpServletRequest request) { 331 LeaveApprovalActionForm laaf = (LeaveApprovalActionForm) form; 332 String page = request.getParameter((new ParamEncoder(TkConstants.APPROVAL_TABLE_ID).encodeParameterName(TableTagParameters.PARAMETER_PAGE))); 333 334 if (StringUtils.isBlank(page)) { 335 laaf.getDepartments().clear(); 336 laaf.getWorkAreaDescr().clear(); 337 laaf.setLeaveApprovalRows(new ArrayList<ApprovalLeaveSummaryRow>()); 338 laaf.setSelectedDept(null); 339 laaf.setSearchField(null); 340 laaf.setSearchTerm(null); 341 } 342 } 343 344 @Override 345 protected void populateCalendarAndPayPeriodLists(HttpServletRequest request, ApprovalForm taf) { 346 LeaveApprovalActionForm laaf = (LeaveApprovalActionForm) taf; 347 // set calendar year list 348 Set<String> yearSet = new HashSet<String>(); 349 SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); 350 // if selected calendar year is passed in 351 if(!StringUtils.isEmpty(request.getParameter("selectedCY"))) { 352 laaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString()); 353 } else { 354 laaf.setSelectedCalendarYear(sdf.format(laaf.getPayCalendarEntries().getBeginPeriodDate())); 355 } 356 357 List<CalendarEntries> pcListForYear = new ArrayList<CalendarEntries>(); 358 List<CalendarEntries> pceList = new ArrayList<CalendarEntries>(); 359 pceList.addAll(TkServiceLocator.getLeaveApprovalService() 360 .getAllLeavePayCalendarEntriesForApprover(TKContext.getPrincipalId(), TKUtils.getTimelessDate(null))); 361 362 for(CalendarEntries pce : pceList) { 363 yearSet.add(sdf.format(pce.getBeginPeriodDate())); 364 if(sdf.format(pce.getBeginPeriodDate()).equals(laaf.getSelectedCalendarYear())) { 365 pcListForYear.add(pce); 366 } 367 } 368 List<String> yearList = new ArrayList<String>(yearSet); 369 Collections.sort(yearList); 370 Collections.reverse(yearList); // newest on top 371 laaf.setCalendarYears(yearList); 372 373 // set pay period list contents 374 if(!StringUtils.isEmpty(request.getParameter("selectedPP"))) { 375 laaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString()); 376 } else { 377 laaf.setSelectedPayPeriod(laaf.getPayCalendarEntries().getHrCalendarEntriesId()); 378 laaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear)); 379 } 380 if(laaf.getPayPeriodsMap().isEmpty()) { 381 laaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(pcListForYear)); 382 } 383 } 384 385 }