1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.hr.time.detail.web;
17
18 import java.math.BigDecimal;
19 import java.sql.Date;
20 import java.sql.Timestamp;
21 import java.text.SimpleDateFormat;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Map.Entry;
30 import java.util.Properties;
31 import java.util.Set;
32
33 import javax.servlet.http.HttpServletRequest;
34 import javax.servlet.http.HttpServletResponse;
35
36 import org.apache.commons.collections.MapUtils;
37 import org.apache.commons.lang.StringUtils;
38 import org.apache.commons.lang.SystemUtils;
39 import org.apache.struts.action.ActionForm;
40 import org.apache.struts.action.ActionForward;
41 import org.apache.struts.action.ActionMapping;
42 import org.joda.time.DateTime;
43 import org.joda.time.Interval;
44 import org.joda.time.LocalDateTime;
45 import org.kuali.hr.lm.LMConstants;
46 import org.kuali.hr.lm.accrual.AccrualCategory;
47 import org.kuali.hr.lm.accrual.AccrualCategoryRule;
48 import org.kuali.hr.lm.balancetransfer.BalanceTransfer;
49 import org.kuali.hr.lm.balancetransfer.validation.BalanceTransferValidationUtils;
50 import org.kuali.hr.lm.leaveblock.LeaveBlock;
51 import org.kuali.hr.lm.leavecalendar.validation.LeaveCalendarValidationUtil;
52 import org.kuali.hr.lm.util.LeaveBlockAggregate;
53 import org.kuali.hr.time.assignment.Assignment;
54 import org.kuali.hr.time.calendar.Calendar;
55 import org.kuali.hr.time.calendar.CalendarEntries;
56 import org.kuali.hr.time.calendar.TkCalendar;
57 import org.kuali.hr.time.earncode.EarnCode;
58 import org.kuali.hr.time.principal.PrincipalHRAttributes;
59 import org.kuali.hr.time.roles.TkUserRoles;
60 import org.kuali.hr.time.roles.UserRoles;
61 import org.kuali.hr.time.service.base.TkServiceLocator;
62 import org.kuali.hr.time.timeblock.TimeBlock;
63 import org.kuali.hr.time.timeblock.TimeBlockHistory;
64 import org.kuali.hr.time.timesheet.TimesheetDocument;
65 import org.kuali.hr.time.timesheet.web.TimesheetAction;
66 import org.kuali.hr.time.timesheet.web.TimesheetActionForm;
67 import org.kuali.hr.time.timesummary.AssignmentColumn;
68 import org.kuali.hr.time.timesummary.AssignmentRow;
69 import org.kuali.hr.time.timesummary.EarnCodeSection;
70 import org.kuali.hr.time.timesummary.EarnGroupSection;
71 import org.kuali.hr.time.timesummary.TimeSummary;
72 import org.kuali.hr.time.util.TKContext;
73 import org.kuali.hr.time.util.TKUser;
74 import org.kuali.hr.time.util.TKUtils;
75 import org.kuali.hr.time.util.TkConstants;
76 import org.kuali.hr.time.util.TkTimeBlockAggregate;
77 import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
78 import org.kuali.rice.kew.api.document.DocumentStatus;
79 import org.kuali.rice.kew.service.KEWServiceLocator;
80 import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
81 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
82 import org.kuali.rice.krad.exception.AuthorizationException;
83 import org.kuali.rice.krad.util.GlobalVariables;
84 import org.kuali.rice.krad.util.ObjectUtils;
85 import org.kuali.rice.krad.util.UrlFactory;
86
87 public class TimeDetailAction extends TimesheetAction {
88
89 @Override
90 protected void checkTKAuthorization(ActionForm form, String methodToCall) throws AuthorizationException {
91 super.checkTKAuthorization(form, methodToCall);
92 UserRoles roles = TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId());
93 TimesheetDocument doc = TKContext.getCurrentTimesheetDocument();
94
95
96 if (StringUtils.equals(methodToCall, "addTimeBlock") || StringUtils.equals(methodToCall, "deleteTimeBlock") || StringUtils.equals(methodToCall, "updateTimeBlock")) {
97 if (!roles.isDocumentWritable(doc)) {
98 throw new AuthorizationException(roles.getPrincipalId(), "TimeDetailAction", "");
99 }
100 }
101 }
102
103 @Override
104 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
105 ActionForward forward = super.execute(mapping, form, request, response);
106 if (forward.getRedirect()) {
107 return forward;
108 }
109 if (TKContext.getCurrentTimesheetDocument() == null) {
110 return forward;
111 }
112 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
113 tdaf.setAssignmentDescriptions(TkServiceLocator.getAssignmentService().getAssignmentDescriptions(TKContext.getCurrentTimesheetDocument(), false));
114
115
116
117 CalendarEntries payCalendarEntry = tdaf.getPayCalendarDates();
118 Calendar payCalendar = TkServiceLocator.getCalendarService().getCalendar(payCalendarEntry != null ? payCalendarEntry.getHrCalendarId() : null);
119
120
121 List<TimeBlock> timeBlocks = TKContext.getCurrentTimesheetDocument().getTimeBlocks();
122
123 List<Assignment> timeAssignments = TKContext.getCurrentTimesheetDocument().getAssignments();
124 List<String> tAssignmentKeys = new ArrayList<String>();
125 for(Assignment assign : timeAssignments) {
126 tAssignmentKeys.add(assign.getAssignmentKey());
127 }
128
129 Date endDate = payCalendarEntry.getEndPeriodDate();
130 LocalDateTime tempLocalDate = payCalendarEntry.getEndLocalDateTime();
131
132 if(tempLocalDate.getHourOfDay() == 0 && tempLocalDate.getMinuteOfHour() == 0 && tempLocalDate.getMillisOfSecond() == 0) {
133 endDate = new java.sql.Date(tempLocalDate.minusDays(1).toDate().getTime());
134 }
135
136 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(TKContext.getCurrentTimesheetDocument().getPrincipalId(),
137 payCalendarEntry.getBeginPeriodDate(), endDate, tAssignmentKeys);
138 List<LeaveBlock> balanceTransferLeaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksWithType(TKContext.getCurrentTimesheetDocument().getPrincipalId(),
139 payCalendarEntry.getBeginPeriodDate(), payCalendarEntry.getEndPeriodDate(), LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER);
140
141
142
143
144
145
146 Map<String, Set<String>> allMessages = LeaveCalendarValidationUtil.getWarningMessagesForLeaveBlocks(balanceTransferLeaveBlocks);
147 Map<String, Set<String>> transactionalMessages = LeaveCalendarValidationUtil.validatePendingTransactions(TKContext.getTargetPrincipalId(),
148 payCalendarEntry.getBeginPeriodDate(), payCalendarEntry.getEndPeriodDate());
149
150 List<String> warnings = new ArrayList<String>();
151
152
153
154
155 String viewPrincipal = TKContext.getTargetPrincipalId();
156 List<BalanceTransfer> losses = new ArrayList<BalanceTransfer>();
157 if (TkServiceLocator.getLeaveApprovalService().isActiveAssignmentFoundOnJobFlsaStatus(viewPrincipal, TkConstants.FLSA_STATUS_NON_EXEMPT, true)) {
158 PrincipalHRAttributes principalCalendar = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(viewPrincipal, payCalendarEntry.getEndPeriodDate());
159
160 Interval calendarInterval = new Interval(payCalendarEntry.getBeginPeriodDate().getTime(), payCalendarEntry.getEndPeriodDate().getTime());
161 Map<String,Set<LeaveBlock>> maxBalInfractions = new HashMap<String,Set<LeaveBlock>>();
162
163 if(ObjectUtils.isNotNull(principalCalendar)) {
164 maxBalInfractions = TkServiceLocator.getAccrualCategoryMaxBalanceService().getMaxBalanceViolations(payCalendarEntry, viewPrincipal);
165
166 for(Entry<String,Set<LeaveBlock>> entry : maxBalInfractions.entrySet()) {
167 for(LeaveBlock lb : entry.getValue()) {
168 if(calendarInterval.contains(lb.getLeaveDate().getTime())) {
169 AccrualCategory accrualCat = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(lb.getAccrualCategory(), lb.getLeaveDate());
170 AccrualCategoryRule aRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(lb.getAccrualCategoryRuleId());
171 if(StringUtils.equals(aRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
172 DateTime aDate = null;
173 if(StringUtils.equals(aRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
174 aDate = TkServiceLocator.getLeavePlanService().getRolloverDayOfLeavePlan(principalCalendar.getLeavePlan(), lb.getLeaveDate());
175 }
176 else {
177 Calendar cal = TkServiceLocator.getCalendarService().getCalendarByPrincipalIdAndDate(viewPrincipal, lb.getLeaveDate(), true);
178 CalendarEntries leaveEntry = TkServiceLocator.getCalendarEntriesService().getCurrentCalendarEntriesByCalendarId(cal.getHrCalendarId(), lb.getLeaveDate());
179 aDate = new DateTime(leaveEntry.getEndPeriodDate());
180 }
181 aDate = aDate.minusDays(1);
182 if(calendarInterval.contains(aDate.getMillis()) && aDate.toDate().compareTo(payCalendarEntry.getEndPeriodDate()) <= 0) {
183
184 AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(aRule.getLmAccrualCategoryId());
185 BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(viewPrincipal, accrualCategory, lb.getLeaveDate());
186
187 BalanceTransfer loseTransfer = TkServiceLocator.getBalanceTransferService().initializeTransfer(viewPrincipal, lb.getAccrualCategoryRuleId(), accruedBalance, lb.getLeaveDate());
188 boolean valid = BalanceTransferValidationUtils.validateTransfer(loseTransfer);
189 if(valid)
190 losses.add(loseTransfer);
191 }
192 }
193
194
195
196 String message = "You have exceeded the maximum balance limit for '" + accrualCat.getAccrualCategory() + "' as of " + lb.getLeaveDate() + ". "+
197 "Depending upon the accrual category rules, leave over this limit may be forfeited.";
198
199 if(!StringUtils.contains(allMessages.get("warningMessages").toString(),"You have exceeded the maximum balance limit for '"+accrualCat.getAccrualCategory())) {
200 allMessages.get("warningMessages").add(message);
201 }
202 }
203 }
204 }
205 }
206 tdaf.setForfeitures(losses);
207
208 if (principalCalendar != null) {
209 Calendar calendar = TkServiceLocator.getCalendarService().getCalendarByPrincipalIdAndDate(viewPrincipal, tdaf.getEndPeriodDateTime(), true);
210
211 if (calendar != null) {
212 List<CalendarEntries> leaveCalendarEntries = TkServiceLocator.getCalendarEntriesService().getCalendarEntriesEndingBetweenBeginAndEndDate(calendar.getHrCalendarId(), tdaf.getBeginPeriodDateTime(), tdaf.getEndPeriodDateTime());
213
214 List<AccrualCategory> accrualCategories = TkServiceLocator.getAccrualCategoryService().getActiveLeaveAccrualCategoriesForLeavePlan(principalCalendar.getLeavePlan(), new java.sql.Date(tdaf.getEndPeriodDateTime().getTime()));
215 for (AccrualCategory accrualCategory : accrualCategories) {
216 if (TkServiceLocator.getAccrualCategoryMaxCarryOverService().exceedsAccrualCategoryMaxCarryOver(accrualCategory.getAccrualCategory(), viewPrincipal, leaveCalendarEntries, tdaf.getEndPeriodDateTime())) {
217 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.";
218 if (!warnings.contains(message)) {
219 warnings.add(message);
220 }
221 }
222 }
223 }
224 }
225 }
226
227
228
229 allMessages.get("warningMessages").addAll(warnings);
230
231 List<String> infoMessages = tdaf.getInfoMessages();
232 infoMessages.addAll(allMessages.get("infoMessages"));
233 infoMessages.addAll(transactionalMessages.get("infoMessages"));
234
235 List<String> warningMessages = tdaf.getWarningMessages();
236 warningMessages.addAll(allMessages.get("warningMessages"));
237 warningMessages.addAll(transactionalMessages.get("warningMessages"));
238
239 List<String> actionMessages = tdaf.getActionMessages();
240 actionMessages.addAll(allMessages.get("actionMessages"));
241 actionMessages.addAll(transactionalMessages.get("actionMessages"));
242
243 tdaf.setInfoMessages(infoMessages);
244 tdaf.setWarningMessages(warningMessages);
245 tdaf.setActionMessages(actionMessages);
246
247 this.assignStypeClassMapForTimeSummary(tdaf,timeBlocks, leaveBlocks);
248
249 List<Interval> intervals = TKUtils.getFullWeekDaySpanForCalendarEntry(payCalendarEntry);
250 LeaveBlockAggregate lbAggregate = new LeaveBlockAggregate(leaveBlocks, payCalendarEntry, intervals);
251 TkTimeBlockAggregate tbAggregate = new TkTimeBlockAggregate(timeBlocks, payCalendarEntry, payCalendar, true,intervals);
252
253 TkCalendar cal = TkCalendar.getCalendar(tbAggregate, lbAggregate);
254 cal.assignAssignmentStyle(tdaf.getAssignStyleClassMap());
255 tdaf.setTkCalendar(cal);
256
257 this.populateCalendarAndPayPeriodLists(request, tdaf);
258
259 tdaf.setTimeBlockString(ActionFormUtils.getTimeBlocksJson(tbAggregate.getFlattenedTimeBlockList()));
260 tdaf.setLeaveBlockString(ActionFormUtils.getLeaveBlocksJson(lbAggregate.getFlattenedLeaveBlockList()));
261
262 tdaf.setOvertimeEarnCodes(TkServiceLocator.getEarnCodeService().getOvertimeEarnCodesStrs(TKContext.getCurrentTimesheetDocument().getAsOfDate()));
263
264 if (StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())) {
265 tdaf.setWorkingOnItsOwn("true");
266 }
267
268 tdaf.setDocEditable("false");
269 if (TKUser.isSystemAdmin()) {
270 tdaf.setDocEditable("true");
271 } else {
272 String documentStatus = TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentStatus();
273 boolean docFinal = DocumentStatus.FINAL.getCode().equals(documentStatus)
274 || DocumentStatus.CANCELED.getCode().equals(documentStatus)
275 || DocumentStatus.DISAPPROVED.getCode().equals(documentStatus);
276 if (!docFinal) {
277 if(StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())
278 || TKUser.isSystemAdmin()
279 || TKUser.isLocationAdmin()
280 || TKUser.isDepartmentAdmin()
281 || TKUser.isReviewer()
282 || TKUser.isApprover()) {
283 tdaf.setDocEditable("true");
284 }
285
286
287 if (StringUtils.equals(TKContext.getCurrentTimesheetDocument().getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())
288 && TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentStatus().equals(TkConstants.ROUTE_STATUS.ENROUTE)) {
289 Collection actions = KEWServiceLocator.getActionTakenService().findByDocIdAndAction(TKContext.getCurrentTimesheetDocument().getDocumentHeader().getDocumentId(), TkConstants.DOCUMENT_ACTIONS.APPROVE);
290 if(!actions.isEmpty()) {
291 tdaf.setDocEditable("false");
292 }
293 }
294 }
295 }
296
297 return forward;
298 }
299
300
301 private void assignStypeClassMapForTimeSummary(TimeDetailActionForm tdaf, List<TimeBlock> timeBlocks, List<LeaveBlock> leaveBlocks) throws Exception {
302 TimeSummary ts = TkServiceLocator.getTimeSummaryService().getTimeSummary(TKContext.getCurrentTimesheetDocument());
303 tdaf.setAssignStyleClassMap(ActionFormUtils.buildAssignmentStyleClassMap(timeBlocks, leaveBlocks));
304 Map<String, String> aMap = tdaf.getAssignStyleClassMap();
305
306 for (EarnGroupSection earnGroupSection : ts.getSections()) {
307 for (EarnCodeSection section : earnGroupSection.getEarnCodeSections()) {
308 for (AssignmentRow assignRow : section.getAssignmentsRows()) {
309 String assignmentCssStyle = MapUtils.getString(aMap, assignRow.getAssignmentKey());
310 assignRow.setCssClass(assignmentCssStyle);
311 for (AssignmentColumn assignmentColumn : assignRow.getAssignmentColumns()) {
312 assignmentColumn.setCssClass(assignmentCssStyle);
313 }
314 }
315 }
316
317 }
318 tdaf.setTimeSummary(ts);
319
320 ActionFormUtils.addWarningTextFromEarnGroup(tdaf);
321 ActionFormUtils.addUnapprovedIPWarningFromClockLog(tdaf);
322 }
323
324 private void populateCalendarAndPayPeriodLists(HttpServletRequest request, TimeDetailActionForm tdaf) {
325 String viewPrincipal = TKContext.getTargetPrincipalId();
326 List<TimesheetDocumentHeader> documentHeaders = (List<TimesheetDocumentHeader>) TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeadersForPrincipalId(TKContext.getTargetPrincipalId());
327 SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
328 if(tdaf.getCalendarYears().isEmpty()) {
329
330 Set<String> yearSet = new HashSet<String>();
331
332 for(TimesheetDocumentHeader tdh : documentHeaders) {
333 yearSet.add(sdf.format(tdh.getBeginDate()));
334 }
335 List<String> yearList = new ArrayList<String>(yearSet);
336 Collections.sort(yearList);
337 Collections.reverse(yearList);
338 tdaf.setCalendarYears(yearList);
339 }
340
341 if(request.getParameter("selectedCY")!= null) {
342 tdaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
343 }
344
345 if(StringUtils.isEmpty(tdaf.getSelectedCalendarYear())) {
346 tdaf.setSelectedCalendarYear(sdf.format(tdaf.getPayCalendarDates().getBeginPeriodDate()));
347 }
348 if(tdaf.getPayPeriodsMap().isEmpty()) {
349 List<CalendarEntries> payPeriodList = new ArrayList<CalendarEntries>();
350 for(TimesheetDocumentHeader tdh : documentHeaders) {
351 if(sdf.format(tdh.getBeginDate()).equals(tdaf.getSelectedCalendarYear())) {
352 CalendarEntries pe = TkServiceLocator.getCalendarService().getCalendarDatesByPayEndDate(tdh.getPrincipalId(), tdh.getEndDate(), TkConstants.PAY_CALENDAR_TYPE);
353
354 payPeriodList.add(pe);
355 }
356 }
357 tdaf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(payPeriodList, viewPrincipal));
358 }
359 if(request.getParameter("selectedPP")!= null) {
360 tdaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
361 }
362 if(StringUtils.isEmpty(tdaf.getSelectedPayPeriod())) {
363 tdaf.setSelectedPayPeriod(tdaf.getPayCalendarDates().getHrCalendarEntriesId());
364 }
365 }
366
367
368
369
370
371
372
373
374 public ActionForward deleteTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
375 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
376
377 String principalId = TKContext.getPrincipalId();
378 String targetPrincipalId = TKContext.getTargetPrincipalId();
379 String documentId = tdaf.getDocumentId();
380
381
382 List<TimeBlock> timeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
383 TimeBlock deletedTimeBlock = null;
384 for (TimeBlock tb : timeBlocks) {
385 if (tb.getTkTimeBlockId().compareTo(tdaf.getTkTimeBlockId()) == 0) {
386 deletedTimeBlock = tb;
387 break;
388 }
389 }
390 if (deletedTimeBlock == null) {
391 return mapping.findForward("basic");
392 }
393
394 List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(tdaf.getTimesheetDocument().getTimeBlocks().size());
395 for (TimeBlock b : tdaf.getTimesheetDocument().getTimeBlocks()) {
396 referenceTimeBlocks.add(b.copy());
397 }
398
399
400 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
401 newTimeBlocks.remove(deletedTimeBlock);
402
403
404 TkServiceLocator.getTimeBlockService().deleteTimeBlock(deletedTimeBlock);
405
406 TimeBlockHistory tbh = new TimeBlockHistory(deletedTimeBlock);
407 tbh.setActionHistory(TkConstants.ACTIONS.DELETE_TIME_BLOCK);
408 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh);
409
410 List<Assignment> assignments = tdaf.getTimesheetDocument().getAssignments();
411 List<String> assignmentKeys = new ArrayList<String>();
412 for (Assignment assignment : assignments) {
413 assignmentKeys.add(assignment.getAssignmentKey());
414 }
415 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(principalId, tdaf.getTimesheetDocument().getAsOfDate(), tdaf.getTimesheetDocument().getDocEndDate(), assignmentKeys);
416
417
418 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks, tdaf.getTimesheetDocument().getAsOfDate());
419 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, leaveBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId());
420 TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks, TKContext.getPrincipalId());
421
422 generateTimesheetChangedNotification(principalId, targetPrincipalId, documentId);
423
424 return mapping.findForward("basic");
425 }
426
427
428
429
430
431
432
433
434 public ActionForward addTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
435 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
436
437 String principalId = TKContext.getPrincipalId();
438 String targetPrincipalId = TKContext.getTargetPrincipalId();
439 String documentId = tdaf.getDocumentId();
440
441 if(StringUtils.isNotEmpty(tdaf.getTkTimeBlockId())) {
442
443 this.removeOldTimeBlock(tdaf);
444 } else if(StringUtils.isNotEmpty(tdaf.getLmLeaveBlockId())) {
445
446 this.removeOldLeaveBlock(tdaf.getLmLeaveBlockId());
447 }
448 if(StringUtils.isNotEmpty(tdaf.getSelectedEarnCode())) {
449 EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument().getAsOfDate());
450 if(ec != null && (ec.getLeavePlan() != null || ec.getEligibleForAccrual().equals("N"))) {
451 this.changeLeaveBlocks(tdaf);
452 } else {
453 this.changeTimeBlocks(tdaf);
454 }
455 }
456
457
458 ActionFormUtils.addWarningTextFromEarnGroup(tdaf);
459
460 generateTimesheetChangedNotification(principalId, targetPrincipalId, documentId);
461
462 return mapping.findForward("basic");
463 }
464
465 private void removeOldTimeBlock(TimeDetailActionForm tdaf) {
466 if (tdaf.getTkTimeBlockId() != null) {
467 TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId());
468 if (tb != null) {
469 TimeBlockHistory tbh = new TimeBlockHistory(tb);
470 TkServiceLocator.getTimeBlockService().deleteTimeBlock(tb);
471
472
473 tbh.setActionHistory(TkConstants.ACTIONS.DELETE_TIME_BLOCK);
474 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh);
475
476
477 tdaf.getTimesheetDocument().getTimeBlocks().remove(tb);
478 }
479 }
480 }
481
482 private void removeOldLeaveBlock(String lbId) {
483 if (lbId != null) {
484 LeaveBlock lb = TkServiceLocator.getLeaveBlockService().getLeaveBlock(lbId);
485 if (lb != null) {
486 TkServiceLocator.getLeaveBlockService().deleteLeaveBlock(lbId, TKContext.getPrincipalId());
487 }
488 }
489 }
490
491
492 private void changeLeaveBlocks(TimeDetailActionForm tdaf) {
493 DateTime beginDate = null;
494 DateTime endDate = null;
495
496 if(tdaf.getStartTime() != null && tdaf.getEndTime() != null) {
497 beginDate = new DateTime(TKUtils.convertDateStringToTimestamp(tdaf.getStartDate(), tdaf.getStartTime()));
498 endDate = new DateTime(TKUtils.convertDateStringToTimestamp(tdaf.getEndDate(), tdaf.getEndTime()));
499 } else {
500 beginDate = new DateTime(TKUtils.convertDateStringToTimestamp(tdaf.getStartDate()));
501 endDate = new DateTime(TKUtils.convertDateStringToTimestamp(tdaf.getEndDate()));
502 }
503
504 String selectedEarnCode = tdaf.getSelectedEarnCode();
505 BigDecimal leaveAmount = tdaf.getLeaveAmount();
506
507 String desc = "";
508 String spanningWeeks = tdaf.getSpanningWeeks();
509 Assignment currentAssignment = TkServiceLocator.getAssignmentService().getAssignment(tdaf.getTimesheetDocument(), tdaf.getSelectedAssignment());
510 TkServiceLocator.getLeaveBlockService().addLeaveBlocks(beginDate, endDate, tdaf.getPayCalendarDates(), selectedEarnCode, leaveAmount, desc, currentAssignment,
511 spanningWeeks, LMConstants.LEAVE_BLOCK_TYPE.TIME_CALENDAR, TKContext.getTargetPrincipalId());
512
513 List<Assignment> assignments = tdaf.getTimesheetDocument().getAssignments();
514 List<String> assignmentKeys = new ArrayList<String>();
515 for (Assignment assignment : assignments) {
516 assignmentKeys.add(assignment.getAssignmentKey());
517 }
518 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(TKContext.getTargetPrincipalId(), tdaf.getTimesheetDocument().getAsOfDate(), tdaf.getTimesheetDocument().getDocEndDate(), assignmentKeys);
519
520
521 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
522 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, leaveBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId());
523 TkServiceLocator.getTimeBlockService().saveTimeBlocks(newTimeBlocks, newTimeBlocks, TKContext.getPrincipalId());
524 }
525
526
527 private void changeTimeBlocks(TimeDetailActionForm tdaf) {
528 Timestamp overtimeBeginTimestamp = null;
529 Timestamp overtimeEndTimestamp = null;
530 boolean isClockLogCreated = false;
531
532
533
534 if (tdaf.getTkTimeBlockId() != null) {
535 TimeBlock tb = TkServiceLocator.getTimeBlockService().getTimeBlock(tdaf.getTkTimeBlockId());
536 if (tb != null) {
537 isClockLogCreated = tb.getClockLogCreated();
538 if (StringUtils.isNotEmpty(tdaf.getOvertimePref())) {
539
540 overtimeBeginTimestamp = tb.getBeginTimestamp();
541 overtimeEndTimestamp = tb.getEndTimestamp();
542 }
543 }
544
545
546 }
547
548 Assignment currentAssignment = TkServiceLocator.getAssignmentService().getAssignment(tdaf.getTimesheetDocument(), tdaf.getSelectedAssignment());
549
550
551
552 Timestamp startTime = TKUtils.convertDateStringToTimestamp(tdaf.getStartDate(), tdaf.getStartTime());
553 Timestamp endTime = TKUtils.convertDateStringToTimestamp(tdaf.getEndDate(), tdaf.getEndTime());
554
555
556
557 List<TimeBlock> referenceTimeBlocks = new ArrayList<TimeBlock>(tdaf.getTimesheetDocument().getTimeBlocks().size());
558 for (TimeBlock tb : tdaf.getTimesheetDocument().getTimeBlocks()) {
559 referenceTimeBlocks.add(tb.copy());
560 }
561
562
563
564 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
565 DateTime startTemp = new DateTime(startTime);
566 DateTime endTemp = new DateTime(endTime);
567
568 if (StringUtils.equals(tdaf.getAcrossDays(), "y")
569 && !(endTemp.getDayOfYear() - startTemp.getDayOfYear() <= 1
570 && endTemp.getHourOfDay() == 0)) {
571 List<TimeBlock> timeBlocksToAdd = TkServiceLocator.getTimeBlockService().buildTimeBlocksSpanDates(currentAssignment,
572 tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument(), startTime,
573 endTime, tdaf.getHours(), tdaf.getAmount(), isClockLogCreated, Boolean.parseBoolean(tdaf.getLunchDeleted()), tdaf.getSpanningWeeks(), TKContext.getPrincipalId());
574 for (TimeBlock tb : timeBlocksToAdd) {
575 if (!newTimeBlocks.contains(tb)) {
576 newTimeBlocks.add(tb);
577 }
578 }
579 } else {
580 List<TimeBlock> timeBlocksToAdd = TkServiceLocator.getTimeBlockService().buildTimeBlocks(currentAssignment,
581 tdaf.getSelectedEarnCode(), tdaf.getTimesheetDocument(), startTime,
582 endTime, tdaf.getHours(), tdaf.getAmount(), isClockLogCreated, Boolean.parseBoolean(tdaf.getLunchDeleted()), TKContext.getPrincipalId());
583 for (TimeBlock tb : timeBlocksToAdd) {
584 if (!newTimeBlocks.contains(tb)) {
585 newTimeBlocks.add(tb);
586 }
587 }
588 }
589
590
591 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks, tdaf.getTimesheetDocument().getAsOfDate());
592
593
594
595
596 for (TimeBlock tb : newTimeBlocks) {
597 if (tb.getBeginTimestamp().equals(startTime) && tb.getEndTimestamp().equals(endTime) && StringUtils.isNotEmpty(tdaf.getOvertimePref())) {
598 tb.setOvertimePref(tdaf.getOvertimePref());
599 }
600
601 }
602
603 List<Assignment> assignments = tdaf.getTimesheetDocument().getAssignments();
604 List<String> assignmentKeys = new ArrayList<String>();
605 for (Assignment assignment : assignments) {
606 assignmentKeys.add(assignment.getAssignmentKey());
607 }
608 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(TKContext.getTargetPrincipalId(), tdaf.getTimesheetDocument().getAsOfDate(), tdaf.getTimesheetDocument().getDocEndDate(), assignmentKeys);
609
610 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, leaveBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId());
611 TkServiceLocator.getTimeBlockService().saveTimeBlocks(referenceTimeBlocks, newTimeBlocks, TKContext.getPrincipalId());
612 }
613
614 public ActionForward updateTimeBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
615
616 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
617 Assignment assignment = TkServiceLocator.getAssignmentService().getAssignment(tdaf.getTimesheetDocument(), tdaf.getSelectedAssignment());
618
619
620 List<TimeBlock> timeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
621 TimeBlock updatedTimeBlock = null;
622 for (TimeBlock tb : timeBlocks) {
623 if (tb.getTkTimeBlockId().compareTo(tdaf.getTkTimeBlockId()) == 0) {
624 updatedTimeBlock = tb;
625 tb.setJobNumber(assignment.getJobNumber());
626 tb.setWorkArea(assignment.getWorkArea());
627 tb.setTask(assignment.getTask());
628 break;
629 }
630 }
631
632 Set<String> earnCodes = new HashSet<String>();
633 if (updatedTimeBlock != null) {
634 List<EarnCode> validEarnCodes = TkServiceLocator.getEarnCodeService().getEarnCodesForTime(assignment, updatedTimeBlock.getBeginDate(), true);
635 for (EarnCode e : validEarnCodes) {
636 earnCodes.add(e.getEarnCode());
637 }
638 }
639
640 if (updatedTimeBlock != null
641 && earnCodes.contains(updatedTimeBlock.getEarnCode())) {
642 TkServiceLocator.getTimeBlockService().updateTimeBlock(updatedTimeBlock);
643
644 TimeBlockHistory tbh = new TimeBlockHistory(updatedTimeBlock);
645 tbh.setActionHistory(TkConstants.ACTIONS.UPDATE_TIME_BLOCK);
646 TkServiceLocator.getTimeBlockHistoryService().saveTimeBlockHistory(tbh);
647 }
648 tdaf.setMethodToCall("addTimeBlock");
649 return mapping.findForward("basic");
650 }
651
652
653 public ActionForward actualTimeInquiry(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
654 return mapping.findForward("ati");
655 }
656
657 public ActionForward deleteLunchDeduction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
658
659 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
660 String timeHourDetailId = tdaf.getTkTimeHourDetailId();
661 TkServiceLocator.getTimeBlockService().deleteLunchDeduction(timeHourDetailId);
662
663 List<TimeBlock> newTimeBlocks = tdaf.getTimesheetDocument().getTimeBlocks();
664
665 List<Assignment> assignments = tdaf.getTimesheetDocument().getAssignments();
666 List<String> assignmentKeys = new ArrayList<String>();
667 for (Assignment assignment : assignments) {
668 assignmentKeys.add(assignment.getAssignmentKey());
669 }
670 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForTimeCalendar(TKContext.getTargetPrincipalId(), tdaf.getTimesheetDocument().getAsOfDate(), tdaf.getTimesheetDocument().getDocEndDate(), assignmentKeys);
671
672 TkServiceLocator.getTimesheetService().resetTimeBlock(newTimeBlocks, tdaf.getTimesheetDocument().getAsOfDate());
673
674
675 TkServiceLocator.getTkRuleControllerService().applyRules(TkConstants.ACTIONS.ADD_TIME_BLOCK, newTimeBlocks, leaveBlocks, tdaf.getPayCalendarDates(), tdaf.getTimesheetDocument(), TKContext.getPrincipalId());
676 TkServiceLocator.getTimeBlockService().saveTimeBlocks(newTimeBlocks);
677 TKContext.getCurrentTimesheetDocument().setTimeBlocks(newTimeBlocks);
678
679 return mapping.findForward("basic");
680 }
681
682 public ActionForward gotoCurrentPayPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
683 String viewPrincipal = TKUser.getCurrentTargetPersonId();
684 Date currentDate = TKUtils.getTimelessDate(null);
685 CalendarEntries pce = TkServiceLocator.getCalendarService().getCurrentCalendarDates(viewPrincipal, currentDate);
686 TimesheetDocument td = TkServiceLocator.getTimesheetService().openTimesheetDocument(viewPrincipal, pce);
687 setupDocumentOnFormContext((TimesheetActionForm)form, td);
688 return mapping.findForward("basic");
689 }
690
691
692 public ActionForward changeCalendarYear(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
693
694 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
695 if(request.getParameter("selectedCY") != null) {
696 tdaf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
697 }
698 return mapping.findForward("basic");
699 }
700
701
702 public ActionForward changePayPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
703 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
704 if(request.getParameter("selectedPP") != null) {
705 tdaf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
706 CalendarEntries pce = TkServiceLocator.getCalendarEntriesService()
707 .getCalendarEntries(request.getParameter("selectedPP").toString());
708 if(pce != null) {
709 String viewPrincipal = TKUser.getCurrentTargetPersonId();
710 TimesheetDocument td = TkServiceLocator.getTimesheetService().openTimesheetDocument(viewPrincipal, pce);
711 setupDocumentOnFormContext((TimesheetActionForm)form, td);
712 }
713 }
714 return mapping.findForward("basic");
715 }
716
717 public ActionForward deleteLeaveBlock(ActionMapping mapping,ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
718 TimeDetailActionForm tdaf = (TimeDetailActionForm) form;
719
720 String principalId = TKContext.getPrincipalId();
721 String targetPrincipalId = TKContext.getTargetPrincipalId();
722 String documentId = tdaf.getDocumentId();
723 String leaveBlockId = tdaf.getLmLeaveBlockId();
724
725 LeaveBlock blockToDelete = TkServiceLocator.getLeaveBlockService().getLeaveBlock(leaveBlockId);
726 if (blockToDelete != null && TkServiceLocator.getPermissionsService().canDeleteLeaveBlock(blockToDelete)) {
727 TkServiceLocator.getLeaveBlockService().deleteLeaveBlock(leaveBlockId, TKContext.getPrincipalId());
728
729 generateTimesheetChangedNotification(principalId, targetPrincipalId, documentId);
730 }
731
732
733 EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(blockToDelete.getEarnCode(), blockToDelete.getLeaveDate());
734 if(ec != null && ec.getEligibleForAccrual().equals("N")) {
735 CalendarEntries ce = TkServiceLocator.getCalendarService()
736 .getCurrentCalendarDatesForLeaveCalendar(blockToDelete.getPrincipalId(), blockToDelete.getLeaveDate());
737 if(ce != null) {
738 TkServiceLocator.getLeaveAccrualService().runAccrual(blockToDelete.getPrincipalId(), ce.getBeginPeriodDate(), ce.getEndPeriodDate(), false);
739 }
740 }
741
742 return mapping.findForward("basic");
743 }
744
745 private void generateTimesheetChangedNotification(String principalId, String targetPrincipalId, String documentId) {
746 if (!StringUtils.equals(principalId, targetPrincipalId)) {
747 EntityNamePrincipalName person = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(principalId);
748 if (person != null && person.getDefaultName() != null) {
749 String subject = "Timesheet Modification Notice";
750 StringBuilder message = new StringBuilder();
751 message.append("Your Timesheet was changed by ");
752 message.append(person.getDefaultName().getCompositeNameUnmasked());
753 message.append(" on your behalf.");
754 message.append(SystemUtils.LINE_SEPARATOR);
755 message.append(getTimesheetURL(documentId));
756
757 TkServiceLocator.getKPMENotificationService().sendNotification(subject, message.toString(), targetPrincipalId);
758 }
759 }
760 }
761
762 @SuppressWarnings("deprecation")
763 private String getTimesheetURL(String documentId) {
764 Properties params = new Properties();
765 params.put("documentId", documentId);
766 return UrlFactory.parameterizeUrl(getApplicationBaseUrl() + "/TimeDetail.do", params);
767 }
768
769 }