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 }