Java tutorial
/** * Copyright 2004-2014 The Kuali Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ecl2.php * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kuali.kpme.tklm.time.detail.web; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.SystemUtils; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionRedirect; import org.joda.time.DateTime; import org.joda.time.Interval; import org.joda.time.LocalDate; import org.kuali.kpme.core.api.accrualcategory.AccrualCategory; import org.kuali.kpme.core.api.accrualcategory.AccrualCategoryContract; import org.kuali.kpme.core.api.accrualcategory.rule.AccrualCategoryRuleContract; import org.kuali.kpme.core.api.assignment.Assignment; import org.kuali.kpme.core.api.assignment.AssignmentDescriptionKey; import org.kuali.kpme.core.api.calendar.Calendar; import org.kuali.kpme.core.api.calendar.entry.CalendarEntry; import org.kuali.kpme.core.api.earncode.EarnCode; import org.kuali.kpme.core.api.earncode.EarnCodeContract; import org.kuali.kpme.core.api.principal.PrincipalHRAttributes; import org.kuali.kpme.core.service.HrServiceLocator; import org.kuali.kpme.core.util.HrConstants; import org.kuali.kpme.core.util.HrContext; import org.kuali.kpme.core.util.TKUtils; import org.kuali.kpme.tklm.api.common.TkConstants; import org.kuali.kpme.tklm.api.leave.block.LeaveBlock; import org.kuali.kpme.tklm.api.leave.block.LeaveBlockContract; import org.kuali.kpme.tklm.api.leave.summary.LeaveSummaryContract; import org.kuali.kpme.tklm.api.leave.summary.LeaveSummaryRowContract; import org.kuali.kpme.tklm.api.time.timeblock.TimeBlock; import org.kuali.kpme.tklm.api.time.timeblock.TimeBlockContract; import org.kuali.kpme.tklm.api.time.timehourdetail.TimeHourDetail; import org.kuali.kpme.tklm.common.LMConstants; import org.kuali.kpme.tklm.leave.block.LeaveBlockAggregate; import org.kuali.kpme.tklm.leave.calendar.validation.LeaveCalendarValidationUtil; import org.kuali.kpme.tklm.leave.service.LmServiceLocator; import org.kuali.kpme.tklm.leave.transfer.BalanceTransfer; import org.kuali.kpme.tklm.leave.transfer.validation.BalanceTransferValidationUtils; import org.kuali.kpme.tklm.time.calendar.TkCalendar; import org.kuali.kpme.tklm.time.detail.validation.TimeDetailValidationUtil; import org.kuali.kpme.tklm.time.service.TkServiceLocator; import org.kuali.kpme.tklm.time.timeblock.TimeBlockBo; import org.kuali.kpme.tklm.time.timeblock.TimeBlockHistory; import org.kuali.kpme.tklm.time.timesheet.TimesheetDocument; import org.kuali.kpme.tklm.time.timesheet.TimesheetUtils; import org.kuali.kpme.tklm.time.timesheet.web.TimesheetAction; import org.kuali.kpme.tklm.time.timesummary.*; import org.kuali.kpme.tklm.time.util.TkContext; import org.kuali.kpme.tklm.time.util.TkTimeBlockAggregate; import org.kuali.rice.core.api.config.property.ConfigContext; import org.kuali.rice.core.api.mo.ModelObjectUtils; import org.kuali.rice.kew.api.KewApiServiceLocator; import org.kuali.rice.kew.api.action.ActionTaken; import org.kuali.rice.kew.api.action.ActionType; import org.kuali.rice.kew.api.document.DocumentStatus; import org.kuali.rice.kew.service.KEWServiceLocator; import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName; import org.kuali.rice.kim.api.services.KimApiServiceLocator; import org.kuali.rice.krad.exception.AuthorizationException; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.UrlFactory; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.util.*; import java.util.Map.Entry; public class TimeDetailAction extends TimesheetAction { @Override protected void checkTKAuthorization(ActionForm form, String methodToCall) throws AuthorizationException { super.checkTKAuthorization(form, methodToCall); TimeDetailActionForm timeDetailActionForm = (TimeDetailActionForm) form; String principalId = GlobalVariables.getUserSession().getPrincipalId(); TimesheetDocument timesheetDocument = TkServiceLocator.getTimesheetService() .getTimesheetDocument(timeDetailActionForm.getDocumentId()); if (StringUtils.equals(methodToCall, "addTimeBlock") || StringUtils.equals(methodToCall, "deleteTimeBlock") || StringUtils.equals(methodToCall, "updateTimeBlock")) { if (!HrServiceLocator.getHRPermissionService().canEditCalendarDocument(principalId, timesheetDocument)) { throw new AuthorizationException(principalId, "TimeDetailAction", ""); } } } @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { ActionForward forward = super.execute(mapping, form, request, response); TimeDetailActionForm timeDetailActionForm = (TimeDetailActionForm) form; CalendarEntry calendarEntry = timeDetailActionForm.getCalendarEntry(); TimesheetDocument timesheetDocument = timeDetailActionForm.getTimesheetDocument(); if (calendarEntry != null && timesheetDocument != null) { List<String> assignmentKeys = new ArrayList<String>(); for (Assignment assignment : timesheetDocument.getAllAssignments()) { assignmentKeys.add(assignment.getAssignmentKey()); } //timeDetailActionForm.setAssignmentDescriptions(timeDetailActionForm.getTimesheetDocument().getAssignmentDescriptions(false)); timeDetailActionForm.setDocEditable("false"); if (HrContext.isSystemAdmin()) { timeDetailActionForm.setDocEditable("true"); } else { DocumentStatus documentStatus = KewApiServiceLocator.getWorkflowDocumentService() .getDocumentStatus(timeDetailActionForm.getDocumentId()); if (!DocumentStatus.FINAL.equals(documentStatus) && !DocumentStatus.CANCELED.equals(documentStatus) && !DocumentStatus.DISAPPROVED.equals(documentStatus)) { if (StringUtils.equals(timesheetDocument.getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId()) || HrContext.isSystemAdmin() || TkContext.isLocationAdmin() || HrContext.isReviewer() || HrContext.isAnyApprover() || HrContext.isAnyPayrollProcessor()) { timeDetailActionForm.setDocEditable("true"); } //if the timesheet has been approved by at least one of the approvers, the employee should not be able to edit it if (StringUtils.equals(timesheetDocument.getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId()) && timesheetDocument.getDocumentHeader().getDocumentStatus() .equals(HrConstants.ROUTE_STATUS.ENROUTE)) { List<ActionTaken> actionsTaken = KewApiServiceLocator.getWorkflowDocumentService() .getAllActionsTaken(timesheetDocument.getDocumentId()); for (ActionTaken at : actionsTaken) { if (ActionType.APPROVE.equals(at.getActionTaken())) { timeDetailActionForm.setDocEditable("false"); break; } } } } else if (DocumentStatus.FINAL.equals(documentStatus)) { if (HrContext.isSystemAdmin()) { timeDetailActionForm.setNotesEditable(Boolean.TRUE); } else { timeDetailActionForm.setNotesEditable(Boolean.FALSE); } } } List<TimeBlock> timeBlocks = TkServiceLocator.getTimesheetService() .getTimesheetDocument(timeDetailActionForm.getDocumentId()).getTimeBlocks(); List<LeaveBlock> leaveBlocks = LmServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar( timesheetDocument.getPrincipalId(), calendarEntry.getBeginPeriodFullDateTime().toLocalDate(), calendarEntry.getEndPeriodFullDateTime().toLocalDate(), assignmentKeys); timeDetailActionForm.getTimesheetDocument().setTimeBlocks(timeBlocks); assignStyleClassMapForTimeSummary(timeDetailActionForm, timeBlocks, leaveBlocks); Calendar payCalendar = HrServiceLocator.getCalendarService() .getCalendar(calendarEntry != null ? calendarEntry.getHrCalendarId() : null); List<Interval> intervals = TKUtils.getFullWeekDaySpanForCalendarEntry(calendarEntry); LeaveBlockAggregate lbAggregate = new LeaveBlockAggregate(leaveBlocks, calendarEntry, intervals); TkTimeBlockAggregate tbAggregate = new TkTimeBlockAggregate(timeBlocks, calendarEntry, payCalendar, true, intervals); // use both time aggregate and leave aggregate to populate the calendar TkCalendar cal = TkCalendar.getCalendar(tbAggregate, lbAggregate); cal.assignAssignmentStyle(timeDetailActionForm.getAssignStyleClassMap()); timeDetailActionForm.setTkCalendar(cal); timeDetailActionForm .setTimeBlockString(ActionFormUtils.getTimeBlocksJson(tbAggregate.getFlattenedTimeBlockList())); timeDetailActionForm.setLeaveBlockString( ActionFormUtils.getLeaveBlocksJson(lbAggregate.getFlattenedLeaveBlockList())); timeDetailActionForm.setOvertimeEarnCodes(HrServiceLocator.getEarnCodeService() .getOvertimeEarnCodesStrs(timesheetDocument.getAsOfDate())); if (StringUtils.equals(timesheetDocument.getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())) { timeDetailActionForm.setWorkingOnItsOwn("true"); } setMessages(timeDetailActionForm); } return forward; } // use lists of time blocks and leave blocks to build the style class map and assign css class to associated summary rows private void assignStyleClassMapForTimeSummary(TimeDetailActionForm tdaf, List<? extends TimeBlockContract> timeBlocks, List<? extends LeaveBlockContract> leaveBlocks) throws Exception { TimesheetDocument td = tdaf.getTimesheetDocument(); TimeSummary ts = (TimeSummary) TkServiceLocator.getTimeSummaryService().getTimeSummary(td.getPrincipalId(), td.getTimeBlocks(), td.getCalendarEntry(), td.getAssignmentMap()); tdaf.setAssignStyleClassMap(ActionFormUtils.buildAssignmentStyleClassMap(timeBlocks, leaveBlocks)); Map<String, String> aMap = tdaf.getAssignStyleClassMap(); // set css classes for each assignment row for (EarnGroupSection earnGroupSection : ts.getSections()) { for (EarnCodeSection section : earnGroupSection.getEarnCodeSections()) { for (AssignmentRow assignRow : section.getAssignmentsRows()) { String assignmentCssStyle = MapUtils.getString(aMap, assignRow.getAssignmentKey()); assignRow.setCssClass(assignmentCssStyle); for (AssignmentColumn assignmentColumn : assignRow.getAssignmentColumns().values()) { assignmentColumn.setCssClass(assignmentCssStyle); } } } } tdaf.setTimeSummary(ts); //ActionFormUtils.validateHourLimit(tdaf); ActionFormUtils.addWarningTextFromEarnGroup(tdaf); ActionFormUtils.addUnapprovedIPWarningFromClockLog(tdaf); } protected void setMessages(TimeDetailActionForm timeDetailActionForm) { String principalId = HrContext.getTargetPrincipalId(); TimesheetDocument timesheetDocument = timeDetailActionForm.getTimesheetDocument(); CalendarEntry calendarEntry = timeDetailActionForm.getCalendarEntry(); List<LeaveBlock> balanceTransferLeaveBlocks = LmServiceLocator.getLeaveBlockService() .getLeaveBlocksWithType(timesheetDocument.getPrincipalId(), calendarEntry.getBeginPeriodFullDateTime().toLocalDate(), calendarEntry.getEndPeriodFullDateTime().toLocalDate(), LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER); Map<String, Set<String>> allMessages = LeaveCalendarValidationUtil.getWarningMessagesForLeaveBlocks( balanceTransferLeaveBlocks, calendarEntry.getBeginPeriodFullDateTime(), calendarEntry.getEndPeriodFullDateTime()); // add warning messages based on max carry over balances for each accrual category for non-exempt leave users List<BalanceTransfer> losses = new ArrayList<BalanceTransfer>(); if (LmServiceLocator.getLeaveApprovalService().isActiveAssignmentFoundOnJobFlsaStatus(principalId, HrConstants.FLSA_STATUS_NON_EXEMPT, true)) { PrincipalHRAttributes principalCalendar = HrServiceLocator.getPrincipalHRAttributeService() .getPrincipalCalendar(principalId, calendarEntry.getEndPeriodFullDateTime().toLocalDate()); Interval calendarInterval = new Interval(calendarEntry.getBeginPeriodFullDateTime(), calendarEntry.getEndPeriodFullDateTime()); Map<String, Set<LeaveBlock>> maxBalInfractions = new HashMap<String, Set<LeaveBlock>>(); if (principalCalendar != null) { maxBalInfractions = LmServiceLocator.getAccrualCategoryMaxBalanceService() .getMaxBalanceViolations(calendarEntry, principalId); for (Entry<String, Set<LeaveBlock>> entry : maxBalInfractions.entrySet()) { for (LeaveBlockContract lb : entry.getValue()) { if (calendarInterval.contains(lb.getLeaveDateTime())) { AccrualCategoryContract accrualCat = lb.getAccrualCategoryObj(); AccrualCategoryRuleContract aRule = lb.getAccrualCategoryRule(); if (StringUtils.equals(aRule.getActionAtMaxBalance(), HrConstants.ACTION_AT_MAX_BALANCE.LOSE)) { DateTime aDate = null; if (StringUtils.equals(aRule.getMaxBalanceActionFrequency(), HrConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) { aDate = HrServiceLocator.getLeavePlanService().getRolloverDayOfLeavePlan( principalCalendar.getLeavePlan(), lb.getLeaveLocalDate()); } else { Calendar cal = HrServiceLocator.getCalendarService() .getCalendarByPrincipalIdAndDate(principalId, lb.getLeaveLocalDate(), true); CalendarEntry leaveEntry = HrServiceLocator.getCalendarEntryService() .getCurrentCalendarEntryByCalendarId(cal.getHrCalendarId(), new DateTime(lb.getLeaveDateTime())); aDate = leaveEntry.getEndPeriodFullDateTime(); } aDate = aDate.minusDays(1); if (calendarInterval.contains(aDate.getMillis()) && aDate.compareTo(calendarEntry.getEndPeriodFullDateTime()) <= 0) { //may want to calculate summary for all rows, displayable or not, and determine displayability via tags. AccrualCategory accrualCategory = HrServiceLocator.getAccrualCategoryService() .getAccrualCategory(aRule.getLmAccrualCategoryId()); BigDecimal accruedBalance = LmServiceLocator.getAccrualService() .getAccruedBalanceForPrincipal(principalId, accrualCategory, lb.getLeaveLocalDate()); // BigDecimal leaveBalance = LmServiceLocator.getLeaveSummaryService().getLeaveBalanceForAccrCatUpToDate(principalId, startDate, endDate, accrualCategory, usageEndDate) BalanceTransfer loseTransfer = LmServiceLocator.getBalanceTransferService() .initializeTransfer(principalId, aRule.getLmAccrualCategoryRuleId(), accruedBalance, lb.getLeaveLocalDate()); boolean valid = BalanceTransferValidationUtils.validateTransfer(loseTransfer); if (valid) { //validation occurs again before the "transfer" action occurs that submits the forfeiture. losses.add(loseTransfer); } } } // accrual categories within the leave plan that are hidden from the leave summary WILL appear. String message = "You have exceeded the maximum balance limit for '" + accrualCat.getAccrualCategory() + "' as of " + lb.getLeaveLocalDate() + ". " + "Depending upon the accrual category rules, leave over this limit may be forfeited."; // leave blocks are sorted in getMaxBalanceViolations() method, so we just take the one with the earliest leave date for an accrual category. if (!StringUtils.contains(allMessages.get("warningMessages").toString(), "You have exceeded the maximum balance limit for '" + accrualCat.getAccrualCategory())) { allMessages.get("warningMessages").add(message); } } } } } timeDetailActionForm.setForfeitures(losses); Map<String, Set<String>> transactionalMessages = LeaveCalendarValidationUtil .validatePendingTransactions(HrContext.getTargetPrincipalId(), calendarEntry.getBeginPeriodFullDateTime().toLocalDate(), calendarEntry.getEndPeriodFullDateTime().toLocalDate()); allMessages.get("infoMessages").addAll(transactionalMessages.get("infoMessages")); allMessages.get("warningMessages").addAll(transactionalMessages.get("warningMessages")); allMessages.get("actionMessages").addAll(transactionalMessages.get("actionMessages")); LeaveSummaryContract leaveSummary = null; try { leaveSummary = LmServiceLocator.getLeaveSummaryService().getLeaveSummary(principalId, calendarEntry); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } if (principalCalendar != null) { Calendar calendar = HrServiceLocator.getCalendarService().getCalendarByPrincipalIdAndDate( principalId, calendarEntry.getEndPeriodFullDateTime().toLocalDate(), true); if (calendar != null) { List<CalendarEntry> leaveCalendarEntries = HrServiceLocator.getCalendarEntryService() .getCalendarEntriesEndingBetweenBeginAndEndDate(calendar.getHrCalendarId(), calendarEntry.getBeginPeriodFullDateTime(), calendarEntry.getEndPeriodFullDateTime()); List<AccrualCategory> accrualCategories = HrServiceLocator.getAccrualCategoryService() .getActiveLeaveAccrualCategoriesForLeavePlan(principalCalendar.getLeavePlan(), calendarEntry.getEndPeriodFullDateTime().toLocalDate()); for (AccrualCategory accrualCategory : accrualCategories) { if (LmServiceLocator.getAccrualCategoryMaxCarryOverService() .exceedsAccrualCategoryMaxCarryOver(accrualCategory.getAccrualCategory(), principalId, leaveCalendarEntries, calendarEntry.getEndPeriodFullDateTime().toLocalDate())) { String message = "Your pending leave balance is greater than the annual max carry over for accrual category '" + accrualCategory.getAccrualCategory() + "' and upon approval, the excess balance will be lost."; if (!allMessages.get("warningMessages").contains(message)) { allMessages.get("warningMessages").add(message); } } } // check for the negative Accrual balance for the category. if (leaveSummary != null && leaveSummary.getLeaveSummaryRows().size() > 0) { for (LeaveSummaryRowContract summaryRow : leaveSummary.getLeaveSummaryRows()) { if (summaryRow.getLeaveBalance() != null && summaryRow.getLeaveBalance().compareTo(BigDecimal.ZERO) < 0) { String message = "Negative available balance found for the accrual category '" + summaryRow.getAccrualCategory() + "'."; allMessages.get("warningMessages").add(message); } } } } } } List<String> infoMessages = timeDetailActionForm.getInfoMessages(); infoMessages.addAll(allMessages.get("infoMessages")); List<String> warningMessages = timeDetailActionForm.getWarningMessages(); warningMessages.addAll(allMessages.get("warningMessages")); List<String> actionMessages = timeDetailActionForm.getActionMessages(); actionMessages.addAll(allMessages.get("actionMessages")); timeDetailActionForm.setInfoMessages(infoMessages); timeDetailActionForm.setWarningMessages(warningMessages); timeDetailActionForm.setActionMessages(actionMessages); } /** * This method involves creating an object-copy of every TimeBlock on the * time sheet for overtime re-calculation. * * @throws Exception */ public ActionForward deleteTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TimeDetailActionForm tdaf = (TimeDetailActionForm) form; String principalId = HrContext.getPrincipalId(); String targetPrincipalId = HrContext.getTargetPrincipalId(); String documentId = tdaf.getDocumentId(); //Grab timeblock to be deleted from form List<TimeBlock> timeBlocks = tdaf.getTimesheetDocument().getTimeBlocks(); TimeBlock deletedTimeBlock = null; for (TimeBlock tb : timeBlocks) { if (tb.getTkTimeBlockId().compareTo(tdaf.getTkTimeBlockId()) == 0) { deletedTimeBlock = tb; break; } } if (deletedTimeBlock == null) { return mapping.findForward("basic"); } List<TimeBlock> newTimeBlocks = TimesheetUtils .getTimesheetTimeblocksForProcessing(tdaf.getTimesheetDocument(), true); List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(newTimeBlocks); newTimeBlocks.remove(deletedTimeBlock); //Delete timeblock TkServiceLocator.getTimeBlockService().deleteTimeBlock(deletedTimeBlock); // Add a row to the history table TimeBlockHistory tbh = new TimeBlockHistory(TimeBlockBo.from(deletedTimeBlock)); tbh.setActionHistory(TkConstants.ACTIONS.DELETE_TIME_BLOCK); tbh.setPrincipalIdModified(principalId); tbh.setTimestampModified(TKUtils.getCurrentTimestamp()); TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh); List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(tdaf.getTimesheetDocument()); //reset time block TimesheetUtils.processTimeBlocksWithRuleChange(newTimeBlocks, referenceTimeBlocks, leaveBlocks, tdaf.getTimesheetDocument().getCalendarEntry(), tdaf.getTimesheetDocument(), HrContext.getPrincipalId()); generateTimesheetChangedNotification(principalId, targetPrincipalId, documentId); return mapping.findForward("basic"); } /** * This method involves creating an object-copy of every TimeBlock on the * time sheet for overtime re-calculation. * Based on the form's timeBlockId or leaveBlockId, existing Time/Leave blocks will be deleted and new ones created * * @throws Exception */ public ActionForward addTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TimeDetailActionForm tdaf = (TimeDetailActionForm) form; //if(this.isTokenValid(request,true)) { if (StringUtils.isNotEmpty(tdaf.getLmLeaveBlockId())) { List<String> errors = TimeDetailValidationUtil.validateLeaveEntry(tdaf); if (errors.isEmpty()) { //KPME-2832: validate leave entry prior to save. //This duplicates validation done on submissions that went through TimeDetailWSAction, i.e. typical time calendar transactions. this.updateLeaveBlock(tdaf); } else { tdaf.setErrorMessages(errors); } return mapping.findForward("basic"); } if (StringUtils.isNotEmpty(tdaf.getSelectedEarnCode())) { EarnCode ec = HrServiceLocator.getEarnCodeService().getEarnCode(tdaf.getSelectedEarnCode(), TKUtils.formatDateTimeStringNoTimezone(tdaf.getEndDate()).toLocalDate()); if (ec != null && (StringUtils.isNotEmpty(ec.getLeavePlan()) || (ec.getEligibleForAccrual().equals("N") && ec.getAccrualBalanceAction().equals("U")))) { //leave blocks changes List<String> errors = TimeDetailValidationUtil.validateLeaveEntry(tdaf); if (errors.isEmpty()) { //KPME-2832: validate leave entry prior to save. //This duplicates validation done on submissions that went through TimeDetailWSAction, i.e. typical time calendar transactions. this.changeLeaveBlocks(tdaf); } else { tdaf.setErrorMessages(errors); } } else { // time blocks changes List<String> errors = TimeDetailValidationUtil.validateTimeEntryDetails(tdaf); if (errors.isEmpty()) { //KPME-2832: validate leave entry prior to save. //This duplicates validation done on submissions that went through TimeDetailWSAction, i.e. typical time calendar transactions. this.changeTimeBlocks(tdaf, ec); } else { tdaf.setErrorMessages(errors); } } } // ActionFormUtils.validateHourLimit(tdaf); // Removing the redirect and returning the basic action mapping forward results in // duplicate time detail entry forms being submitted on browser refresh or back actions. ActionFormUtils.addWarningTextFromEarnGroup(tdaf); ActionRedirect redirect = new ActionRedirect(); redirect.setPath("/TimeDetail.do"); redirect.addParameter("documentId", tdaf.getDocumentId()); return redirect; } private void removeOldTimeBlock(TimeDetailActionForm tdaf) { if (tdaf.getTkTimeBlockId() != null) { TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId()); if (tb != null) { TimeBlockHistory tbh = new TimeBlockHistory(TimeBlockBo.from(tb)); TkServiceLocator.getTimeBlockService().deleteTimeBlock(tb); // mark the original timeblock as deleted in the history table tbh.setActionHistory(TkConstants.ACTIONS.DELETE_TIME_BLOCK); TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh); // delete the timeblock from the memory tdaf.getTimesheetDocument().getTimeBlocks().remove(tb); } } } private void removeOldLeaveBlock(String lbId) { if (lbId != null) { LeaveBlock lb = LmServiceLocator.getLeaveBlockService().getLeaveBlock(lbId); if (lb != null) { LmServiceLocator.getLeaveBlockService().deleteLeaveBlock(lbId, HrContext.getPrincipalId()); } } } /** * * Callers must first run Time Entry validations on tdaf. * * @param tdaf */ // add/update leave blocks private void changeLeaveBlocks(TimeDetailActionForm tdaf) { DateTime beginDate = null; DateTime endDate = null; if (tdaf.getStartTime() != null && tdaf.getEndTime() != null) { beginDate = TKUtils.convertDateStringToDateTime(tdaf.getStartDate(), tdaf.getStartTime()); endDate = TKUtils.convertDateStringToDateTime(tdaf.getEndDate(), tdaf.getEndTime()); } else { // should not apply time zone to dates when user's changing an hour entry beginDate = TKUtils.formatDateTimeStringNoTimezone(tdaf.getStartDate()); endDate = TKUtils.formatDateTimeStringNoTimezone(tdaf.getEndDate()); } String selectedEarnCode = tdaf.getSelectedEarnCode(); BigDecimal leaveAmount = tdaf.getLeaveAmount(); String desc = ""; // there's no description field in time calendar pop window String spanningWeeks = "Y";// tdaf.getSpanningWeeks(); Assignment currentAssignment = tdaf.getTimesheetDocument() .getAssignment(AssignmentDescriptionKey.get(tdaf.getSelectedAssignment()), beginDate.toLocalDate()); LmServiceLocator.getLeaveBlockService().addLeaveBlocks(beginDate, endDate, tdaf.getCalendarEntry(), selectedEarnCode, leaveAmount, desc, currentAssignment, spanningWeeks, LMConstants.LEAVE_BLOCK_TYPE.TIME_CALENDAR, HrContext.getTargetPrincipalId()); List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(tdaf.getTimesheetDocument()); // A bad hack to apply rules to all timeblocks on timesheet List<TimeBlock> newTimeBlocks = TimesheetUtils .getTimesheetTimeblocksForProcessing(tdaf.getTimesheetDocument(), true); List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(newTimeBlocks); // if we are changing an existing time block, we need to remove the time block if (StringUtils.isNotBlank(tdaf.getTkTimeBlockId())) { TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId()); if (tb != null) { TkServiceLocator.getTimeBlockService().deleteTimeBlock(tb); newTimeBlocks.remove(tb); // removed the timeblock that should be deleted from list } } TimesheetUtils.processTimeBlocksWithRuleChange(newTimeBlocks, referenceTimeBlocks, leaveBlocks, tdaf.getTimesheetDocument().getCalendarEntry(), tdaf.getTimesheetDocument(), HrContext.getPrincipalId()); generateTimesheetChangedNotification(HrContext.getPrincipalId(), HrContext.getTargetPrincipalId(), tdaf.getDocumentId()); } /** * * Callers must first run Time Entry validations on tdaf. * * @param tdaf */ // add/update time blocks private void changeTimeBlocks(TimeDetailActionForm tdaf, EarnCodeContract ec) { boolean isClockLogCreated = false; String clockLogBeginId = null; String clockLogEndId = null; tdaf.getDocumentId(); // This is for updating a timeblock or changing // 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. if (tdaf.getTkTimeBlockId() != null) { TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId()); if (tb != null) { isClockLogCreated = tb.isClockLogCreated(); clockLogBeginId = tb.getClockLogBeginId(); clockLogEndId = tb.getClockLogEndId(); } } // Surgery point - Need to construct a Date/Time with Appropriate Timezone. DateTime startTime; DateTime endTime; if (tdaf.getStartTime() != null && tdaf.getEndTime() != null) { startTime = TKUtils.convertDateStringToDateTime(tdaf.getStartDate(), tdaf.getStartTime()); endTime = TKUtils.convertDateStringToDateTime(tdaf.getEndDate(), tdaf.getEndTime()); String gpRuleConfig = ConfigContext.getCurrentContextConfig() .getProperty(TkConstants.KPME_GRACE_PERIOD_RULE_CONFIG); if (gpRuleConfig != null && StringUtils.equals(gpRuleConfig, TkConstants.GRACE_PERIOD_RULE_CONFIG.TIME_ENTRY)) { if (ec != null && StringUtils.equals(ec.getRecordMethod(), HrConstants.RECORD_METHOD.TIME)) { if (HrContext.isAnyAdmin() || HrContext.isAnyApprover() || HrContext.isAnyPayrollProcessor() || HrContext.isReviewer()) { startTime = TkServiceLocator.getGracePeriodService().processGracePeriodRule(startTime, LocalDate.fromDateFields(tdaf.getBeginCalendarEntryDate())); endTime = TkServiceLocator.getGracePeriodService().processGracePeriodRule(endTime, LocalDate.fromDateFields(tdaf.getBeginCalendarEntryDate())); } } } else if (gpRuleConfig != null && StringUtils.equals(gpRuleConfig, TkConstants.GRACE_PERIOD_RULE_CONFIG.REG_ENTRY)) { Assignment currentAssignment = tdaf.getTimesheetDocument().getAssignment( AssignmentDescriptionKey.get(tdaf.getSelectedAssignment()), startTime.toLocalDate()); if (currentAssignment != null) { if (tdaf.getSelectedEarnCode() .equals(currentAssignment.getJob().getPayTypeObj().getRegEarnCode())) { startTime = TkServiceLocator.getGracePeriodService().processGracePeriodRule(startTime, LocalDate.fromDateFields(tdaf.getBeginCalendarEntryDate())); endTime = TkServiceLocator.getGracePeriodService().processGracePeriodRule(endTime, LocalDate.fromDateFields(tdaf.getBeginCalendarEntryDate())); } } } } else { // should not apply time zone to dates when user's changing an hour entry startTime = TKUtils.formatDateTimeStringNoTimezone(tdaf.getStartDate()); endTime = TKUtils.formatDateTimeStringNoTimezone(tdaf.getEndDate()); } Assignment currentAssignment = tdaf.getTimesheetDocument() .getAssignment(AssignmentDescriptionKey.get(tdaf.getSelectedAssignment()), startTime.toLocalDate()); // This is just a reference, for code clarity, the below list is actually // separate at the object level. List<TimeBlock> initialBlocks = TimesheetUtils .getTimesheetTimeblocksForProcessing(tdaf.getTimesheetDocument(), true); List<TimeBlock.Builder> newTimeBlocks = ModelObjectUtils.transform(initialBlocks, toTimeBlockBuilder); // We need a cloned reference set so we know whether or not to // persist any potential changes without making hundreds of DB calls. List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(initialBlocks); List<TimeBlock.Builder> timeBlocksToAdd = null; // KPME-1446 add spanningweeks to the calls below if (StringUtils.equals(tdaf.getAcrossDays(), "y") && !(endTime.getDayOfYear() - startTime.getDayOfYear() <= 1 && endTime.getHourOfDay() == 0)) { timeBlocksToAdd = ModelObjectUtils.transform(TkServiceLocator.getTimeBlockService() .buildTimeBlocksSpanDates(tdaf.getTimesheetDocument().getPrincipalId(), tdaf.getTimesheetDocument().getCalendarEntry(), currentAssignment, tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument().getDocumentId(), startTime, endTime, tdaf.getHours(), tdaf.getAmount(), isClockLogCreated, Boolean.parseBoolean(tdaf.getLunchDeleted()), HrContext.getPrincipalId(), clockLogBeginId, clockLogEndId), toTimeBlockBuilder); } else { TimesheetDocument tempTd = tdaf.getTimesheetDocument(); timeBlocksToAdd = ModelObjectUtils.transform(TkServiceLocator.getTimeBlockService().buildTimeBlocks( tempTd.getPrincipalId(), tempTd.getCalendarEntry(), currentAssignment, tdaf.getSelectedEarnCode(), tdaf.getDocumentId(), startTime, endTime, tdaf.getHours(), tdaf.getAmount(), isClockLogCreated, Boolean.parseBoolean(tdaf.getLunchDeleted()), HrContext.getPrincipalId(), clockLogBeginId, clockLogEndId), toTimeBlockBuilder); } //TimeBlock.Builder existingTimeBlock = null; TimeBlock.Builder timeBlockToUpdate = null; if (tdaf.getTkTimeBlockId() != null && CollectionUtils.isNotEmpty(timeBlocksToAdd)) { timeBlockToUpdate = timeBlocksToAdd.get(0); TkServiceLocator.getTimeHourDetailService().removeTimeHourDetails(tdaf.getTkTimeBlockId()); timeBlockToUpdate.setTkTimeBlockId(tdaf.getTkTimeBlockId()); } List<TimeBlock.Builder> finalNewTimeBlocks = new ArrayList<TimeBlock.Builder>(); for (TimeBlock.Builder tb : newTimeBlocks) { if (!ObjectUtils.equals(tb.getTkTimeBlockId(), tdaf.getTkTimeBlockId())) { finalNewTimeBlocks.add(TimeBlock.Builder.create(tb)); } else { //existingTimeBlock = tb; //existingTimeBlock.setTkTimeBlockId(timeBlockToUpdate.getTkTimeBlockId()); TimeBlock.Builder existingBlock = TimeBlock.Builder.create(timeBlockToUpdate); existingBlock.setVersionNumber(tb.getVersionNumber()); existingBlock.setObjectId(tb.getObjectId()); existingBlock.setOvertimePref(null); //existingBlock.setTkTimeBlockId(tb.getTkTimeBlockId()); finalNewTimeBlocks.add(existingBlock); } } for (TimeBlock.Builder tb : timeBlocksToAdd) { if (tdaf.getTkTimeBlockId() != null) { if (!StringUtils.equals(tb.getTkTimeBlockId(), tdaf.getTkTimeBlockId())) { finalNewTimeBlocks.add(TimeBlock.Builder.create(tb)); } } else { finalNewTimeBlocks.add(TimeBlock.Builder.create(tb)); } } //reset time block List<TimeBlock> tbs = TkServiceLocator.getTimesheetService().resetTimeBlock( ModelObjectUtils.<TimeBlock>buildImmutableCopy(finalNewTimeBlocks), tdaf.getTimesheetDocument().getAsOfDate()); finalNewTimeBlocks = ModelObjectUtils.transform(tbs, toTimeBlockBuilder); // apply overtime pref // I changed start and end times comparison below. it used to be overtimeBeginTimestamp and overtimeEndTimestamp but // for some reason, they're always null because, we have removed the time block before getting here. KPME-2162 if (StringUtils.isNotEmpty(tdaf.getOvertimePref())) { for (TimeBlock.Builder tb : finalNewTimeBlocks) { if ((StringUtils.isNotEmpty(tdaf.getTkTimeBlockId()) && tdaf.getTkTimeBlockId().equals(tb.getTkTimeBlockId())) || (tb.getBeginDateTime().compareTo(startTime) == 0 && tb.getEndDateTime().compareTo(endTime) == 0)) { tb.setOvertimePref(tdaf.getOvertimePref()); } } } tbs = ModelObjectUtils.<TimeBlock>buildImmutableCopy(finalNewTimeBlocks); List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(tdaf.getTimesheetDocument()); TimesheetUtils.processTimeBlocksWithRuleChange(tbs, referenceTimeBlocks, leaveBlocks, tdaf.getTimesheetDocument().getCalendarEntry(), tdaf.getTimesheetDocument(), HrContext.getPrincipalId()); //tbs = TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, tbs, leaveBlocks, tdaf.getCalendarEntry(), tdaf.getTimesheetDocument(), HrContext.getPrincipalId()); //tbs = TkServiceLocator.getTimeBlockService().saveOrUpdateTimeBlocks(referenceTimeBlocks, tbs, HrContext.getPrincipalId()); generateTimesheetChangedNotification(HrContext.getPrincipalId(), HrContext.getTargetPrincipalId(), tdaf.getDocumentId()); tdaf.getTimesheetDocument().setTimeBlocks(tbs); } /** * * Callers must first run Time Entry validations on tdaf. * * @param tdaf */ // KPME-2386 private void updateLeaveBlock(TimeDetailActionForm tdaf) throws Exception { String principalId = HrContext.getPrincipalId(); String targetPrincipalId = HrContext.getTargetPrincipalId(); String selectedEarnCode = tdaf.getSelectedEarnCode(); String leaveBlockId = tdaf.getLmLeaveBlockId(); LeaveBlock updatedLeaveBlock = null; updatedLeaveBlock = LmServiceLocator.getLeaveBlockService().getLeaveBlock(leaveBlockId); // KPME-3070: Code for creating new time block and deleting existing leave block starts here EarnCodeContract ec = HrServiceLocator.getEarnCodeService().getEarnCode(tdaf.getSelectedEarnCode(), TKUtils.formatDateTimeStringNoTimezone(tdaf.getEndDate()).toLocalDate()); if (ec == null || StringUtils.isEmpty(ec.getLeavePlan())) { // delete leave block code will come here LmServiceLocator.getLeaveBlockService().deleteLeaveBlock(leaveBlockId, HrContext.getPrincipalId()); // time blocks changes List<String> errors = TimeDetailValidationUtil.validateTimeEntryDetails(tdaf); if (errors.isEmpty()) { // validate leave entry prior to save. this.changeTimeBlocks(tdaf, ec); } else { tdaf.setErrorMessages(errors); } ActionFormUtils.addWarningTextFromEarnGroup(tdaf); ActionRedirect redirect = new ActionRedirect(); redirect.setPath("/TimeDetail.do"); redirect.addParameter("documentId", tdaf.getDocumentId()); return; } // Code for creating new time block ends here if (LmServiceLocator.getLMPermissionService().canEditLeaveBlock(HrContext.getPrincipalId(), updatedLeaveBlock)) { LeaveBlock.Builder builder = LeaveBlock.Builder.create(updatedLeaveBlock); DateTime beginDate = null; DateTime endDate = null; beginDate = TKUtils.formatDateTimeStringNoTimezone(tdaf.getStartDate()); endDate = TKUtils.formatDateTimeStringNoTimezone(tdaf.getEndDate()); builder.setLeaveDateTime(beginDate); EarnCode earnCode = HrServiceLocator.getEarnCodeService().getEarnCode(selectedEarnCode, updatedLeaveBlock.getLeaveLocalDate()); // selectedEarnCode = hrEarnCodeId if (earnCode != null && earnCode.getRecordMethod().equalsIgnoreCase(HrConstants.EARN_CODE_TIME)) { if (tdaf.getStartTime() != null && tdaf.getEndTime() != null) { beginDate = TKUtils.convertDateStringToDateTimeWithoutZone(tdaf.getStartDate(), tdaf.getStartTime()); endDate = TKUtils.convertDateStringToDateTimeWithoutZone(tdaf.getEndDate(), tdaf.getEndTime()); } else { beginDate = TKUtils.formatDateTimeStringNoTimezone(tdaf.getStartDate()); endDate = TKUtils.formatDateTimeStringNoTimezone(tdaf.getEndDate()); } builder.setBeginDateTime(beginDate); builder.setEndDateTime(endDate); builder.setLeaveAmount(TKUtils.getHoursBetween(beginDate.getMillis(), endDate.getMillis())); } if (!updatedLeaveBlock.getLeaveAmount().equals(tdaf.getLeaveAmount())) { builder.setLeaveAmount(tdaf.getLeaveAmount()); Assignment assignment = tdaf.getTimesheetDocument().getAssignment( AssignmentDescriptionKey.get(tdaf.getSelectedAssignment()), beginDate.toLocalDate()); builder.setAssignmentKey(tdaf.getSelectedAssignment()); builder.setJobNumber(assignment.getJobNumber()); builder.setWorkArea(assignment.getWorkArea()); builder.setTask(assignment.getTask()); } if (earnCode != null && !StringUtils.equals(updatedLeaveBlock.getEarnCode(), earnCode.getEarnCode())) { builder.setEarnCode(earnCode.getEarnCode()); } LmServiceLocator.getLeaveBlockService().updateLeaveBlock(builder.build(), principalId); } List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(tdaf.getTimesheetDocument()); // A bad hack to apply rules to all timeblocks on timesheet List<TimeBlock> newTimeBlocks = TimesheetUtils .getTimesheetTimeblocksForProcessing(tdaf.getTimesheetDocument(), true); List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(newTimeBlocks); TimesheetUtils.processTimeBlocksWithRuleChange(newTimeBlocks, referenceTimeBlocks, leaveBlocks, tdaf.getTimesheetDocument().getCalendarEntry(), tdaf.getTimesheetDocument(), HrContext.getPrincipalId()); generateTimesheetChangedNotification(principalId, targetPrincipalId, tdaf.getDocumentId()); } //No time blocks should be saved directly in this action forward without first validating the entry. public ActionForward updateTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TimeDetailActionForm tdaf = (TimeDetailActionForm) form; //Grab timeblock to be updated from form List<TimeBlock> timeBlocks = TimesheetUtils.getTimesheetTimeblocksForProcessing(tdaf.getTimesheetDocument(), true); // We need a cloned reference set so we know whether or not to // persist any potential changes without making hundreds of DB calls. List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(timeBlocks); List<TimeBlock.Builder> timeBlockBuilders = new ArrayList<TimeBlock.Builder>(); TimeBlock.Builder updatedTimeBlock = null; List<TimeHourDetail.Builder> oldDetailList = new ArrayList<TimeHourDetail.Builder>(); String oldAssignmenString = ""; AssignmentDescriptionKey assignmentKey = AssignmentDescriptionKey.get(tdaf.getSelectedAssignment()); for (TimeBlock tb : timeBlocks) { if (tb.getTkTimeBlockId().compareTo(tdaf.getTkTimeBlockId()) == 0) { updatedTimeBlock = TimeBlock.Builder.create(tb); oldDetailList = updatedTimeBlock.getTimeHourDetails(); oldAssignmenString = updatedTimeBlock.getAssignmentKey(); updatedTimeBlock.setJobNumber(assignmentKey.getJobNumber()); updatedTimeBlock.setGroupKeyCode(assignmentKey.getGroupKeyCode()); updatedTimeBlock.setWorkArea(assignmentKey.getWorkArea()); updatedTimeBlock.setTask(assignmentKey.getTask()); timeBlockBuilders.add(updatedTimeBlock); } else { timeBlockBuilders.add(TimeBlock.Builder.create(tb)); } } AssignmentDescriptionKey assignKey = AssignmentDescriptionKey.get(oldAssignmenString); Assignment oldAssignment = HrServiceLocator.getAssignmentService().getAssignment( updatedTimeBlock.getPrincipalId(), assignKey, updatedTimeBlock.getBeginDateTime().toLocalDate()); String oldRegEarnCode = oldAssignment.getJob().getPayTypeObj().getRegEarnCode(); List<TimeHourDetail.Builder> tempList = new ArrayList<TimeHourDetail.Builder>(); tempList.addAll(oldDetailList); for (TimeHourDetail.Builder thd : tempList) { // remove rule created details from old time block if (!thd.getEarnCode().equals(oldRegEarnCode)) { oldDetailList.remove(thd); } } Set<String> earnCodes = new HashSet<String>(); if (updatedTimeBlock != null) { Assignment assignment = tdaf.getTimesheetDocument().getAssignment( AssignmentDescriptionKey.get(updatedTimeBlock.getAssignmentKey()), updatedTimeBlock.getBeginDateTime().toLocalDate()); List<EarnCode> validEarnCodes = TkServiceLocator.getTimesheetService().getEarnCodesForTime(assignment, updatedTimeBlock.getBeginDateTime().toLocalDate(), true); for (EarnCode e : validEarnCodes) { earnCodes.add(e.getEarnCode()); } } if (updatedTimeBlock != null && earnCodes.contains(updatedTimeBlock.getEarnCode())) { List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(tdaf.getTimesheetDocument()); TimesheetUtils.processTimeBlocksWithRuleChange( ModelObjectUtils.<TimeBlock>buildImmutableCopy(timeBlockBuilders), referenceTimeBlocks, leaveBlocks, tdaf.getTimesheetDocument().getCalendarEntry(), tdaf.getTimesheetDocument(), HrContext.getPrincipalId()); generateTimesheetChangedNotification(HrContext.getPrincipalId(), HrContext.getTargetPrincipalId(), tdaf.getDocumentId()); } //addTimeBlock handles validation and creation of object. Do not save time blocks directly in this method without validating the entry! tdaf.setMethodToCall("addTimeBlock"); return mapping.findForward("basic"); } public ActionForward actualTimeInquiry(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { return mapping.findForward("ati"); } public ActionForward deleteLunchDeduction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TimeDetailActionForm tdaf = (TimeDetailActionForm) form; String timeHourDetailId = tdaf.getTkTimeHourDetailId(); List<TimeBlock> existingBlocks = TimesheetUtils .getTimesheetTimeblocksForProcessing(tdaf.getTimesheetDocument(), true); List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(existingBlocks); List<TimeBlock.Builder> newTimeBlocks = ModelObjectUtils.transform(existingBlocks, toTimeBlockBuilder); TimeHourDetail thd = TkServiceLocator.getTimeHourDetailService().getTimeHourDetail(timeHourDetailId); for (TimeBlock.Builder tb : newTimeBlocks) { if (tb.getTkTimeBlockId().equals(thd.getTkTimeBlockId())) { // mark the lunch deleted as Y tb.setLunchDeleted(true); } } // remove the related time hour detail row with the lunch deduction //TkServiceLocator.getTimeHourDetailService().removeTimeHourDetail(thd.getTkTimeHourDetailId()); List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(tdaf.getTimesheetDocument()); List<TimeBlock> tbs = ModelObjectUtils.<TimeBlock>buildImmutableCopy(newTimeBlocks); TimesheetUtils.processTimeBlocksWithRuleChange(tbs, referenceTimeBlocks, leaveBlocks, tdaf.getTimesheetDocument().getCalendarEntry(), tdaf.getTimesheetDocument(), HrContext.getPrincipalId()); //tbs = TkServiceLocator.getTimesheetService().resetTimeBlock(tbs, tdaf.getTimesheetDocument().getAsOfDate()); // KPME-1340 //tbs = TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, tbs, leaveBlocks, tdaf.getCalendarEntry(), tdaf.getTimesheetDocument(), HrContext.getPrincipalId()); //tbs = TkServiceLocator.getTimeBlockService().saveTimeBlocks(tbs); //tdaf.getTimesheetDocument().setTimeBlocks(tbs); return mapping.findForward("basic"); } public ActionForward deleteLeaveBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { TimeDetailActionForm tdaf = (TimeDetailActionForm) form; String principalId = HrContext.getPrincipalId(); String targetPrincipalId = HrContext.getTargetPrincipalId(); String documentId = tdaf.getDocumentId(); String leaveBlockId = tdaf.getLmLeaveBlockId(); LeaveBlock blockToDelete = LmServiceLocator.getLeaveBlockService().getLeaveBlock(leaveBlockId); if (blockToDelete != null && LmServiceLocator.getLMPermissionService() .canDeleteLeaveBlock(HrContext.getPrincipalId(), blockToDelete)) { LmServiceLocator.getLeaveBlockService().deleteLeaveBlock(leaveBlockId, HrContext.getPrincipalId()); // A bad hack to apply rules to all timeblocks on timesheet List<TimeBlock> newTimeBlocks = TimesheetUtils .getTimesheetTimeblocksForProcessing(tdaf.getTimesheetDocument(), true); // We need a cloned reference set so we know whether or not to // persist any potential changes without making hundreds of DB calls. List<TimeBlock> referenceTimeBlocks = TimesheetUtils.getReferenceTimeBlocks(newTimeBlocks); List<LeaveBlock> leaveBlocks = TimesheetUtils.getLeaveBlocksForTimesheet(tdaf.getTimesheetDocument()); //reset time block TimesheetUtils.processTimeBlocksWithRuleChange(newTimeBlocks, referenceTimeBlocks, leaveBlocks, tdaf.getTimesheetDocument().getCalendarEntry(), tdaf.getTimesheetDocument(), HrContext.getPrincipalId()); generateTimesheetChangedNotification(principalId, targetPrincipalId, documentId); } // if the leave block is NOT eligible for accrual, rerun accrual service for the leave calendar the leave block is on EarnCodeContract ec = HrServiceLocator.getEarnCodeService().getEarnCode(blockToDelete.getEarnCode(), blockToDelete.getLeaveLocalDate()); if (ec != null && ec.getEligibleForAccrual().equals("N")) { CalendarEntry ce = HrServiceLocator.getCalendarEntryService().getCurrentCalendarDatesForLeaveCalendar( blockToDelete.getPrincipalId(), blockToDelete.getLeaveDateTime()); if (ce != null) { LmServiceLocator.getLeaveAccrualService().runAccrual(blockToDelete.getPrincipalId(), ce.getBeginPeriodFullDateTime().toDateTime(), ce.getEndPeriodFullDateTime().toDateTime(), false); } } return mapping.findForward("basic"); } private void generateTimesheetChangedNotification(String principalId, String targetPrincipalId, String documentId) { if (!StringUtils.equals(principalId, targetPrincipalId)) { EntityNamePrincipalName person = KimApiServiceLocator.getIdentityService() .getDefaultNamesForPrincipalId(principalId); if (person != null && person.getDefaultName() != null) { String subject = "Timesheet Modification Notice"; StringBuilder message = new StringBuilder(); message.append("Your Timesheet was changed by "); message.append(person.getDefaultName().getCompositeNameUnmasked()); message.append(" on your behalf."); message.append(SystemUtils.LINE_SEPARATOR); message.append(getTimesheetURL(documentId)); HrServiceLocator.getKPMENotificationService().sendNotification(subject, message.toString(), targetPrincipalId); } } } @SuppressWarnings("deprecation") private String getTimesheetURL(String documentId) { Properties params = new Properties(); params.put("documentId", documentId); return UrlFactory.parameterizeUrl(getApplicationBaseUrl() + "/TimeDetail.do", params); } @Override protected String generateToken(HttpServletRequest request) { return super.generateToken(request); } @Override protected boolean isTokenValid(HttpServletRequest request, boolean reset) { return super.isTokenValid(request, reset); } @Override protected void resetToken(HttpServletRequest request) { super.resetToken(request); } @Override protected void saveToken(HttpServletRequest request) { super.saveToken(request); } }