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