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