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.detail.web; 017 018 import java.math.BigDecimal; 019 import java.sql.Date; 020 import java.sql.Timestamp; 021 import java.text.SimpleDateFormat; 022 import java.util.ArrayList; 023 import java.util.Collection; 024 import java.util.Collections; 025 import java.util.HashSet; 026 import java.util.List; 027 import java.util.Map; 028 import java.util.Set; 029 030 import javax.servlet.http.HttpServletRequest; 031 import javax.servlet.http.HttpServletResponse; 032 033 import org.apache.commons.lang.StringUtils; 034 import org.apache.struts.action.ActionForm; 035 import org.apache.struts.action.ActionForward; 036 import org.apache.struts.action.ActionMapping; 037 import org.joda.time.DateTime; 038 import org.joda.time.Interval; 039 import org.kuali.hr.lm.LMConstants; 040 import org.kuali.hr.lm.leaveblock.LeaveBlock; 041 import org.kuali.hr.lm.leavecalendar.validation.LeaveCalendarValidationUtil; 042 import org.kuali.hr.lm.util.LeaveBlockAggregate; 043 import org.kuali.hr.time.assignment.Assignment; 044 import org.kuali.hr.time.calendar.Calendar; 045 import org.kuali.hr.time.calendar.CalendarEntries; 046 import org.kuali.hr.time.calendar.TkCalendar; 047 import org.kuali.hr.time.earncode.EarnCode; 048 import org.kuali.hr.time.roles.TkUserRoles; 049 import org.kuali.hr.time.roles.UserRoles; 050 import org.kuali.hr.time.service.base.TkServiceLocator; 051 import org.kuali.hr.time.timeblock.TimeBlock; 052 import org.kuali.hr.time.timeblock.TimeBlockHistory; 053 import org.kuali.hr.time.timesheet.TimesheetDocument; 054 import org.kuali.hr.time.timesheet.web.TimesheetAction; 055 import org.kuali.hr.time.timesheet.web.TimesheetActionForm; 056 import org.kuali.hr.time.timesummary.AssignmentRow; 057 import org.kuali.hr.time.timesummary.EarnCodeSection; 058 import org.kuali.hr.time.timesummary.EarnGroupSection; 059 import org.kuali.hr.time.timesummary.TimeSummary; 060 import org.kuali.hr.time.util.TKContext; 061 import org.kuali.hr.time.util.TKUser; 062 import org.kuali.hr.time.util.TKUtils; 063 import org.kuali.hr.time.util.TkConstants; 064 import org.kuali.hr.time.util.TkTimeBlockAggregate; 065 import org.kuali.hr.time.workflow.TimesheetDocumentHeader; 066 import org.kuali.rice.kew.service.KEWServiceLocator; 067 import org.kuali.rice.krad.exception.AuthorizationException; 068 import org.kuali.rice.krad.util.GlobalVariables; 069 070 public class TimeDetailAction extends TimesheetAction { 071 072 @Override 073 protected void checkTKAuthorization(ActionForm form, String methodToCall) throws AuthorizationException { 074 super.checkTKAuthorization(form, methodToCall); // Checks for read access first. 075 TKUser user = TKContext.getUser(); 076 UserRoles roles = TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId()); 077 TimesheetDocument doc = TKContext.getCurrentTimesheetDocument(); 078 079 // Check for write access to Timeblock. 080 if (StringUtils.equals(methodToCall, "addTimeBlock") || StringUtils.equals(methodToCall, "deleteTimeBlock") || StringUtils.equals(methodToCall, "updateTimeBlock")) { 081 if (!roles.isDocumentWritable(doc)) { 082 throw new AuthorizationException(roles.getPrincipalId(), "TimeDetailAction", ""); 083 } 084 } 085 } 086 087 @Override 088 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 089 ActionForward forward = super.execute(mapping, form, request, response); 090 if (forward.getRedirect()) { 091 return forward; 092 } 093 if (TKContext.getCurrentTimesheetDocument() == null) { 094 return forward; 095 } 096 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 097 tdaf.setAssignmentDescriptions(TkServiceLocator.getAssignmentService().getAssignmentDescriptions(TKContext.getCurrentTimesheetDocument(), false)); 098 099 // Handle User preference / timezone information (pushed up from TkCalendar to avoid duplication) 100 // Set calendar 101 CalendarEntries payCalendarEntry = tdaf.getPayCalendarDates(); 102 Calendar payCalendar = TkServiceLocator.getCalendarService().getCalendar(payCalendarEntry != null ? payCalendarEntry.getHrCalendarId() : null); 103 104 //List<TimeBlock> timeBlocks = TkServiceLocator.getTimeBlockService().getTimeBlocks(Long.parseLong(tdaf.getTimesheetDocument().getDocumentHeader().getTimesheetDocumentId())); 105 List<TimeBlock> timeBlocks = TKContext.getCurrentTimesheetDocument().getTimeBlocks(); 106 // get leave blocks 107 List<Assignment> timeAssignments = TKContext.getCurrentTimesheetDocument().getAssignments(); 108 List<String> tAssignmentKeys = new ArrayList<String>(); 109 for(Assignment assign : timeAssignments) { 110 tAssignmentKeys.add(assign.getAssignmentKey()); 111 } 112 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(TKContext.getCurrentTimesheetDocument().getPrincipalId(), 113 payCalendarEntry.getBeginPeriodDate(), payCalendarEntry.getEndPeriodDate(), tAssignmentKeys); 114 List<LeaveBlock> balanceTransferLeaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksWithType(TKContext.getCurrentTimesheetDocument().getPrincipalId(), 115 payCalendarEntry.getBeginPeriodDate(), payCalendarEntry.getEndPeriodDate(), LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER); 116 // List<String> warnings = tdaf.getWarnings(); 117 Map<String, Set<String>> allMessages = LeaveCalendarValidationUtil.getWarningMessagesForLeaveBlocks(balanceTransferLeaveBlocks); 118 Map<String, Set<String>> transactionalMessages = LeaveCalendarValidationUtil.validatePendingTransactions(TKContext.getTargetPrincipalId(), 119 payCalendarEntry.getBeginPeriodDate(), payCalendarEntry.getEndPeriodDate()); 120 121 List<String> infoMessages = tdaf.getInfoMessages(); 122 infoMessages.addAll(allMessages.get("infoMessages")); 123 infoMessages.addAll(transactionalMessages.get("infoMessages")); 124 125 List<String> warningMessages = tdaf.getWarningMessages(); 126 warningMessages.addAll(allMessages.get("warningMessages")); 127 warningMessages.addAll(transactionalMessages.get("warningMessages")); 128 129 List<String> actionMessages = tdaf.getActionMessages(); 130 actionMessages.addAll(allMessages.get("actionMessages")); 131 actionMessages.addAll(transactionalMessages.get("actionMessages")); 132 133 tdaf.setInfoMessages(infoMessages); 134 tdaf.setWarningMessages(warningMessages); 135 tdaf.setActionMessages(actionMessages); 136 137 this.assignStypeClassMapForTimeSummary(tdaf,timeBlocks, leaveBlocks); 138 139 List<Interval> intervals = TKUtils.getFullWeekDaySpanForCalendarEntry(payCalendarEntry); 140 LeaveBlockAggregate lbAggregate = new LeaveBlockAggregate(leaveBlocks, payCalendarEntry, intervals); 141 TkTimeBlockAggregate tbAggregate = new TkTimeBlockAggregate(timeBlocks, payCalendarEntry, payCalendar, true,intervals); 142 // use both time aggregate and leave aggregate to populate the calendar 143 TkCalendar cal = TkCalendar.getCalendar(tbAggregate, lbAggregate); 144 cal.assignAssignmentStyle(tdaf.getAssignStyleClassMap()); 145 tdaf.setTkCalendar(cal); 146 147 this.populateCalendarAndPayPeriodLists(request, tdaf); 148 149 tdaf.setTimeBlockString(ActionFormUtils.getTimeBlocksJson(tbAggregate.getFlattenedTimeBlockList())); 150 tdaf.setLeaveBlockString(ActionFormUtils.getLeaveBlocksJson(lbAggregate.getFlattenedLeaveBlockList())); 151 152 tdaf.setOvertimeEarnCodes(TkServiceLocator.getEarnCodeService().getOvertimeEarnCodesStrs(TKContext.getCurrentTimesheetDocument().getAsOfDate())); 153 154 if (StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())) { 155 tdaf.setWorkingOnItsOwn("true"); 156 } 157 158 tdaf.setDocEditable("false"); 159 if (TKContext.getUser().isSystemAdmin()) { 160 tdaf.setDocEditable("true"); 161 } else { 162 boolean docFinal = TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentStatus().equals(TkConstants.ROUTE_STATUS.FINAL); 163 if (!docFinal) { 164 if(StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId()) 165 || TKContext.getUser().isSystemAdmin() 166 || TKContext.getUser().isLocationAdmin() 167 || TKContext.getUser().isDepartmentAdmin() 168 || TKContext.getUser().isReviewer() 169 || TKContext.getUser().isApprover()) { 170 tdaf.setDocEditable("true"); 171 } 172 173 //if the timesheet has been approved by at least one of the approvers, the employee should not be able to edit it 174 if (StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId()) 175 && TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentStatus().equals(TkConstants.ROUTE_STATUS.ENROUTE)) { 176 Collection actions = KEWServiceLocator.getActionTakenService().findByDocIdAndAction(TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentId(), TkConstants.DOCUMENT_ACTIONS.APPROVE); 177 if(!actions.isEmpty()) { 178 tdaf.setDocEditable("false"); 179 } 180 } 181 } 182 } 183 184 return forward; 185 } 186 187 // use lists of time blocks and leave blocks to build the style class map and assign css class to associated summary rows 188 private void assignStypeClassMapForTimeSummary(TimeDetailActionForm tdaf, List<TimeBlock> timeBlocks, List<LeaveBlock> leaveBlocks) throws Exception { 189 TimeSummary ts = TkServiceLocator.getTimeSummaryService().getTimeSummary(TKContext.getCurrentTimesheetDocument()); 190 tdaf.setAssignStyleClassMap(ActionFormUtils.buildAssignmentStyleClassMap(timeBlocks, leaveBlocks)); 191 Map<String, String> aMap = tdaf.getAssignStyleClassMap(); 192 // set css classes for each assignment row 193 for (EarnGroupSection earnGroupSection : ts.getSections()) { 194 for (EarnCodeSection section : earnGroupSection.getEarnCodeSections()) { 195 for (AssignmentRow assignRow : section.getAssignmentsRows()) { 196 if (assignRow.getAssignmentKey() != null && aMap.containsKey(assignRow.getAssignmentKey())) { 197 assignRow.setCssClass(aMap.get(assignRow.getAssignmentKey())); 198 } else { 199 assignRow.setCssClass(""); 200 } 201 } 202 } 203 204 } 205 tdaf.setTimeSummary(ts); 206 ActionFormUtils.validateHourLimit(tdaf); 207 ActionFormUtils.addWarningTextFromEarnGroup(tdaf); 208 ActionFormUtils.addUnapprovedIPWarningFromClockLog(tdaf); 209 } 210 211 private void populateCalendarAndPayPeriodLists(HttpServletRequest request, TimeDetailActionForm tdaf) { 212 List<TimesheetDocumentHeader> documentHeaders = (List<TimesheetDocumentHeader>) TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeadersForPrincipalId(TKContext.getTargetPrincipalId()); 213 SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); 214 if(tdaf.getCalendarYears().isEmpty()) { 215 // get calendar year drop down list contents 216 Set<String> yearSet = new HashSet<String>(); 217 218 for(TimesheetDocumentHeader tdh : documentHeaders) { 219 yearSet.add(sdf.format(tdh.getBeginDate())); 220 } 221 List<String> yearList = new ArrayList<String>(yearSet); 222 Collections.sort(yearList); 223 Collections.reverse(yearList); // newest on top 224 tdaf.setCalendarYears(yearList); 225 } 226 // if selected calendar year is passed in 227 if(request.getParameter("selectedCY")!= null) { 228 tdaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString()); 229 } 230 // if there is no selected calendr year, use the year of current pay calendar entry 231 if(StringUtils.isEmpty(tdaf.getSelectedCalendarYear())) { 232 tdaf.setSelectedCalendarYear(sdf.format(tdaf.getPayCalendarDates().getBeginPeriodDate())); 233 } 234 if(tdaf.getPayPeriodsMap().isEmpty()) { 235 List<CalendarEntries> payPeriodList = new ArrayList<CalendarEntries>(); 236 for(TimesheetDocumentHeader tdh : documentHeaders) { 237 if(sdf.format(tdh.getBeginDate()).equals(tdaf.getSelectedCalendarYear())) { 238 CalendarEntries pe = TkServiceLocator.getCalendarEntriesService().getCalendarEntriesByBeginAndEndDate(tdh.getBeginDate(), tdh.getEndDate()); 239 payPeriodList.add(pe); 240 } 241 } 242 tdaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(payPeriodList)); 243 } 244 if(request.getParameter("selectedPP")!= null) { 245 tdaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString()); 246 } 247 if(StringUtils.isEmpty(tdaf.getSelectedPayPeriod())) { 248 tdaf.setSelectedPayPeriod(tdaf.getPayCalendarDates().getHrCalendarEntriesId()); 249 } 250 } 251 252 253 /** 254 * This method involves creating an object-copy of every TimeBlock on the 255 * time sheet for overtime re-calculation. 256 * 257 * @throws Exception 258 */ 259 public ActionForward deleteTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 260 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 261 //Grab timeblock to be deleted from form 262 List<TimeBlock> timeBlocks = tdaf.getTimesheetDocument().getTimeBlocks(); 263 TimeBlock deletedTimeBlock = null; 264 for (TimeBlock tb : timeBlocks) { 265 if (tb.getTkTimeBlockId().compareTo(tdaf.getTkTimeBlockId()) == 0) { 266 deletedTimeBlock = tb; 267 break; 268 } 269 } 270 if (deletedTimeBlock == null) { 271 return mapping.findForward("basic"); 272 } 273 //Remove from the list of timeblocks 274 List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(tdaf.getTimesheetDocument().getTimeBlocks().size()); 275 for (TimeBlock b : tdaf.getTimesheetDocument().getTimeBlocks()) { 276 referenceTimeBlocks.add(b.copy()); 277 } 278 279 // simple pointer, for clarity 280 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks(); 281 newTimeBlocks.remove(deletedTimeBlock); 282 283 //Delete timeblock 284 TkServiceLocator.getTimeBlockService().deleteTimeBlock(deletedTimeBlock); 285 // Add a row to the history table 286 TimeBlockHistory tbh = new TimeBlockHistory(deletedTimeBlock); 287 tbh.setActionHistory(TkConstants.ACTIONS.DELETE_TIME_BLOCK); 288 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh); 289 //reset time block 290 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks); 291 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId()); 292 TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks, TKContext.getPrincipalId()); 293 294 return mapping.findForward("basic"); 295 } 296 297 /** 298 * This method involves creating an object-copy of every TimeBlock on the 299 * time sheet for overtime re-calculation. 300 * Based on the form's timeBlockId or leaveBlockId, existing Time/Leave blocks will be deleted and new ones created 301 * 302 * @throws Exception 303 */ 304 public ActionForward addTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 305 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 306 307 if(StringUtils.isNotEmpty(tdaf.getTkTimeBlockId())) { 308 // the user is changing an existing time block, so need to delete this time block 309 this.removeOldTimeBlock(tdaf); 310 } else if(StringUtils.isNotEmpty(tdaf.getLmLeaveBlockId())) { 311 // the user is changing an existing leave block, so need to delete this leave block 312 this.removeOldLeaveBlock(tdaf.getLmLeaveBlockId()); 313 } 314 if(StringUtils.isNotEmpty(tdaf.getSelectedEarnCode())) { 315 EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument().getAsOfDate()); 316 if(ec != null && (ec.getLeavePlan() != null || ec.getEligibleForAccrual().equals("N"))) { // leave blocks changes 317 this.changeLeaveBlocks(tdaf); 318 } else { // time blocks changes 319 this.changeTimeBlocks(tdaf); 320 } 321 } 322 323 ActionFormUtils.validateHourLimit(tdaf); 324 ActionFormUtils.addWarningTextFromEarnGroup(tdaf); 325 326 return mapping.findForward("basic"); 327 } 328 329 private void removeOldTimeBlock(TimeDetailActionForm tdaf) { 330 if (tdaf.getTkTimeBlockId() != null) { 331 TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId()); 332 if (tb != null) { 333 TimeBlockHistory tbh = new TimeBlockHistory(tb); 334 TkServiceLocator.getTimeBlockService().deleteTimeBlock(tb); 335 336 // mark the original timeblock as deleted in the history table 337 tbh.setActionHistory(TkConstants.ACTIONS.DELETE_TIME_BLOCK); 338 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh); 339 340 // delete the timeblock from the memory 341 tdaf.getTimesheetDocument().getTimeBlocks().remove(tb); 342 } 343 } 344 } 345 346 private void removeOldLeaveBlock(String lbId) { 347 if (lbId != null) { 348 LeaveBlock lb = TkServiceLocator.getLeaveBlockService().getLeaveBlock(lbId); 349 if (lb != null) { 350 TkServiceLocator.getLeaveBlockService().deleteLeaveBlock(lbId, TKContext.getPrincipalId()); 351 } 352 } 353 } 354 355 // add/update leave blocks 356 private void changeLeaveBlocks(TimeDetailActionForm tdaf) { 357 DateTime beginDate = new DateTime(TKUtils.convertDateStringToTimestamp(tdaf.getStartDate())); 358 DateTime endDate = new DateTime(TKUtils.convertDateStringToTimestamp(tdaf.getEndDate())); 359 String selectedEarnCode = tdaf.getSelectedEarnCode(); 360 BigDecimal leaveAmount = tdaf.getLeaveAmount(); 361 362 String desc = ""; // there's no description field in time calendar pop window 363 String spanningWeeks = tdaf.getSpanningWeeks(); 364 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(tdaf.getTimesheetDocument(), tdaf.getSelectedAssignment()); 365 TkServiceLocator.getLeaveBlockService().addLeaveBlocks(beginDate, endDate, tdaf.getPayCalendarDates(), selectedEarnCode, leaveAmount, desc, assignment, 366 spanningWeeks, LMConstants.LEAVE_BLOCK_TYPE.TIME_CALENDAR, TKContext.getTargetPrincipalId()); 367 } 368 369 // add/update time blocks 370 private void changeTimeBlocks(TimeDetailActionForm tdaf) { 371 Timestamp overtimeBeginTimestamp = null; 372 Timestamp overtimeEndTimestamp = null; 373 boolean isClockLogCreated = false; 374 375 // This is for updating a timeblock or changing 376 // If tkTimeBlockId is not null and the new timeblock is valid, delete the existing timeblock and a new one will be created after submitting the form. 377 if (tdaf.getTkTimeBlockId() != null) { 378 TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId()); 379 if (tb != null) { 380 isClockLogCreated = tb.getClockLogCreated(); 381 if (StringUtils.isNotEmpty(tdaf.getOvertimePref())) { 382 overtimeBeginTimestamp = tb.getBeginTimestamp(); 383 overtimeEndTimestamp = tb.getEndTimestamp(); 384 } 385 } 386 // old time block is deleted from addTimeBlock method 387 // this.removeOldTimeBlock(tdaf); 388 } 389 390 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(tdaf.getTimesheetDocument(), tdaf.getSelectedAssignment()); 391 392 393 // Surgery point - Need to construct a Date/Time with Appropriate Timezone. 394 Timestamp startTime = TKUtils.convertDateStringToTimestamp(tdaf.getStartDate(), tdaf.getStartTime()); 395 Timestamp endTime = TKUtils.convertDateStringToTimestamp(tdaf.getEndDate(), tdaf.getEndTime()); 396 397 // We need a cloned reference set so we know whether or not to 398 // persist any potential changes without making hundreds of DB calls. 399 List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(tdaf.getTimesheetDocument().getTimeBlocks().size()); 400 for (TimeBlock tb : tdaf.getTimesheetDocument().getTimeBlocks()) { 401 referenceTimeBlocks.add(tb.copy()); 402 } 403 404 // This is just a reference, for code clarity, the above list is actually 405 // separate at the object level. 406 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks(); 407 DateTime startTemp = new DateTime(startTime); 408 DateTime endTemp = new DateTime(endTime); 409 // KPME-1446 add spanningweeks to the calls below 410 if (StringUtils.equals(tdaf.getAcrossDays(), "y") 411 && !(endTemp.getDayOfYear() - startTemp.getDayOfYear() <= 1 412 && endTemp.getHourOfDay() == 0)) { 413 List<TimeBlock> timeBlocksToAdd = TkServiceLocator.getTimeBlockService().buildTimeBlocksSpanDates(assignment, 414 tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument(), startTime, 415 endTime, tdaf.getHours(), tdaf.getAmount(), isClockLogCreated, Boolean.parseBoolean(tdaf.getLunchDeleted()), tdaf.getSpanningWeeks(), TKContext.getPrincipalId()); 416 for (TimeBlock tb : timeBlocksToAdd) { 417 if (!newTimeBlocks.contains(tb)) { 418 newTimeBlocks.add(tb); 419 } 420 } 421 } else { 422 List<TimeBlock> timeBlocksToAdd = TkServiceLocator.getTimeBlockService().buildTimeBlocks(assignment, 423 tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument(), startTime, 424 endTime, tdaf.getHours(), tdaf.getAmount(), isClockLogCreated, Boolean.parseBoolean(tdaf.getLunchDeleted()), TKContext.getPrincipalId()); 425 for (TimeBlock tb : timeBlocksToAdd) { 426 if (!newTimeBlocks.contains(tb)) { 427 newTimeBlocks.add(tb); 428 } 429 } 430 } 431 432 //reset time block 433 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks); 434 435 // apply overtime pref 436 // I changed start and end times comparison below. it used to be overtimeBeginTimestamp and overtimeEndTimestamp but 437 // for some reason, they're always null because, we have removed the time block before getting here. KPME-2162 438 for (TimeBlock tb : newTimeBlocks) { 439 if (tb.getBeginTimestamp().equals(startTime) && tb.getEndTimestamp().equals(endTime) && StringUtils.isNotEmpty(tdaf.getOvertimePref())) { 440 tb.setOvertimePref(tdaf.getOvertimePref()); 441 } 442 443 } 444 445 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId()); 446 TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks, TKContext.getPrincipalId()); 447 } 448 449 public ActionForward updateTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 450 451 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 452 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(tdaf.getTimesheetDocument(), tdaf.getSelectedAssignment()); 453 454 //Grab timeblock to be updated from form 455 List<TimeBlock> timeBlocks = tdaf.getTimesheetDocument().getTimeBlocks(); 456 TimeBlock updatedTimeBlock = null; 457 for (TimeBlock tb : timeBlocks) { 458 if (tb.getTkTimeBlockId().compareTo(tdaf.getTkTimeBlockId()) == 0) { 459 updatedTimeBlock = tb; 460 tb.setJobNumber(assignment.getJobNumber()); 461 tb.setWorkArea(assignment.getWorkArea()); 462 tb.setTask(assignment.getTask()); 463 break; 464 } 465 } 466 467 TkServiceLocator.getTimeBlockService().updateTimeBlock(updatedTimeBlock); 468 469 TimeBlockHistory tbh = new TimeBlockHistory(updatedTimeBlock); 470 tbh.setActionHistory(TkConstants.ACTIONS.UPDATE_TIME_BLOCK); 471 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh); 472 tdaf.setMethodToCall("addTimeBlock"); 473 return mapping.findForward("basic"); 474 } 475 476 477 public ActionForward actualTimeInquiry(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 478 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 479 return mapping.findForward("ati"); 480 } 481 482 public ActionForward deleteLunchDeduction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 483 484 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 485 String timeHourDetailId = tdaf.getTkTimeHourDetailId(); 486 TkServiceLocator.getTimeBlockService().deleteLunchDeduction(timeHourDetailId); 487 488 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks(); 489 490 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks); 491 492 // KPME-1340 493 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId()); 494 TkServiceLocator.getTimeBlockService().saveTimeBlocks(newTimeBlocks); 495 TKContext.getCurrentTimesheetDocument().setTimeBlocks(newTimeBlocks); 496 497 return mapping.findForward("basic"); 498 } 499 500 public ActionForward gotoCurrentPayPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 501 String viewPrincipal = TKUser.getCurrentTargetPerson().getPrincipalId(); 502 Date currentDate = TKUtils.getTimelessDate(null); 503 CalendarEntries pce = TkServiceLocator.getCalendarService().getCurrentCalendarDates(viewPrincipal, currentDate); 504 TimesheetDocument td = TkServiceLocator.getTimesheetService().openTimesheetDocument(viewPrincipal, pce); 505 setupDocumentOnFormContext((TimesheetActionForm)form, td); 506 return mapping.findForward("basic"); 507 } 508 509 //Triggered by changes of pay period drop down list, reload the whole page based on the selected pay period 510 public ActionForward changeCalendarYear(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 511 512 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 513 if(request.getParameter("selectedCY") != null) { 514 tdaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString()); 515 } 516 return mapping.findForward("basic"); 517 } 518 519 //Triggered by changes of pay period drop down list, reload the whole page based on the selected pay period 520 public ActionForward changePayPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 521 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 522 if(request.getParameter("selectedPP") != null) { 523 tdaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString()); 524 CalendarEntries pce = TkServiceLocator.getCalendarEntriesService() 525 .getCalendarEntries(request.getParameter("selectedPP").toString()); 526 if(pce != null) { 527 String viewPrincipal = TKUser.getCurrentTargetPerson().getPrincipalId(); 528 TimesheetDocument td = TkServiceLocator.getTimesheetService().openTimesheetDocument(viewPrincipal, pce); 529 setupDocumentOnFormContext((TimesheetActionForm)form, td); 530 } 531 } 532 return mapping.findForward("basic"); 533 } 534 535 public ActionForward deleteLeaveBlock(ActionMapping mapping,ActionForm form, HttpServletRequest request, 536 HttpServletResponse response) throws Exception { 537 TimeDetailActionForm tdaf = (TimeDetailActionForm) form; 538 String leaveBlockId = tdaf.getLmLeaveBlockId(); 539 540 LeaveBlock blockToDelete = TkServiceLocator.getLeaveBlockService().getLeaveBlock(leaveBlockId); 541 if (blockToDelete != null && TkServiceLocator.getPermissionsService().canDeleteLeaveBlock(blockToDelete)) { 542 TkServiceLocator.getLeaveBlockService().deleteLeaveBlock(leaveBlockId, TKContext.getPrincipalId()); 543 } 544 545 // if the leave block is NOT eligible for accrual, rerun accrual service for the leave calendar the leave block is on 546 EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(blockToDelete.getEarnCode(), blockToDelete.getLeaveDate()); 547 if(ec != null && ec.getEligibleForAccrual().equals("N")) { 548 CalendarEntries ce = TkServiceLocator.getCalendarService() 549 .getCurrentCalendarDatesForLeaveCalendar(blockToDelete.getPrincipalId(), blockToDelete.getLeaveDate()); 550 if(ce != null) { 551 TkServiceLocator.getLeaveAccrualService().runAccrual(blockToDelete.getPrincipalId(), ce.getBeginPeriodDate(), ce.getEndPeriodDate(), false); 552 } 553 } 554 555 return mapping.findForward("basic"); 556 } 557 558 }