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.lm.leavecalendar.web;
017
018 import org.apache.commons.collections.CollectionUtils;
019 import org.apache.commons.lang.StringUtils;
020 import org.apache.commons.lang.SystemUtils;
021 import org.apache.commons.lang.time.DateUtils;
022 import org.apache.log4j.Logger;
023 import org.apache.struts.action.ActionForm;
024 import org.apache.struts.action.ActionForward;
025 import org.apache.struts.action.ActionMapping;
026 import org.apache.struts.action.ActionRedirect;
027 import org.joda.time.DateTime;
028 import org.joda.time.Interval;
029 import org.joda.time.LocalDateTime;
030 import org.joda.time.format.DateTimeFormat;
031 import org.joda.time.format.DateTimeFormatter;
032 import org.kuali.hr.lm.LMConstants;
033 import org.kuali.hr.lm.accrual.AccrualCategory;
034 import org.kuali.hr.lm.accrual.AccrualCategoryRule;
035 import org.kuali.hr.lm.balancetransfer.BalanceTransfer;
036 import org.kuali.hr.lm.balancetransfer.validation.BalanceTransferValidationUtils;
037 import org.kuali.hr.lm.leaveSummary.LeaveSummary;
038 import org.kuali.hr.lm.leaveSummary.LeaveSummaryRow;
039 import org.kuali.hr.lm.leaveblock.LeaveBlock;
040 import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument;
041 import org.kuali.hr.lm.leavecalendar.validation.LeaveCalendarValidationUtil;
042 import org.kuali.hr.lm.util.LeaveBlockAggregate;
043 import org.kuali.hr.lm.workflow.LeaveCalendarDocumentHeader;
044 import org.kuali.hr.lm.workflow.LeaveRequestDocument;
045 import org.kuali.hr.time.assignment.Assignment;
046 import org.kuali.hr.time.base.web.TkAction;
047 import org.kuali.hr.time.calendar.Calendar;
048 import org.kuali.hr.time.calendar.CalendarEntries;
049 import org.kuali.hr.time.calendar.LeaveCalendar;
050 import org.kuali.hr.time.detail.web.ActionFormUtils;
051 import org.kuali.hr.time.earncode.EarnCode;
052 import org.kuali.hr.time.principal.PrincipalHRAttributes;
053 import org.kuali.hr.time.roles.TkUserRoles;
054 import org.kuali.hr.time.roles.UserRoles;
055 import org.kuali.hr.time.service.base.TkServiceLocator;
056 import org.kuali.hr.time.util.TKContext;
057 import org.kuali.hr.time.util.TKUser;
058 import org.kuali.hr.time.util.TKUtils;
059 import org.kuali.hr.time.util.TkConstants;
060 import org.kuali.rice.core.api.config.property.ConfigContext;
061 import org.kuali.rice.kew.api.KewApiServiceLocator;
062 import org.kuali.rice.kew.api.document.DocumentStatus;
063 import org.kuali.rice.kew.service.KEWServiceLocator;
064 import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
065 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
066 import org.kuali.rice.krad.exception.AuthorizationException;
067 import org.kuali.rice.krad.util.GlobalVariables;
068 import org.kuali.rice.krad.util.ObjectUtils;
069 import org.kuali.rice.krad.util.UrlFactory;
070
071 import javax.servlet.http.HttpServletRequest;
072 import javax.servlet.http.HttpServletResponse;
073 import java.math.BigDecimal;
074 import java.sql.Date;
075 import java.sql.Timestamp;
076 import java.text.DateFormat;
077 import java.text.SimpleDateFormat;
078 import java.util.*;
079 import java.util.Map.Entry;
080
081 public class LeaveCalendarAction extends TkAction {
082
083 private static final Logger LOG = Logger.getLogger(LeaveCalendarAction.class);
084
085 @Override
086 protected void checkTKAuthorization(ActionForm form, String methodToCall) throws AuthorizationException {
087 UserRoles roles = TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId());
088 LeaveCalendarDocument doc = TKContext.getCurrentLeaveCalendarDocument();
089
090 if (doc != null && !roles.isDocumentReadable(doc)) {
091 throw new AuthorizationException(GlobalVariables.getUserSession().getPrincipalId(), "LeaveCalendarAction: docid: " + (doc == null ? "" : doc.getDocumentId()), "");
092 }
093 }
094
095 @Override
096 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
097 LeaveCalendarForm lcf = (LeaveCalendarForm) form;
098 String documentId = lcf.getDocumentId();
099
100 if (StringUtils.equals(request.getParameter("command"), "displayDocSearchView")
101 || StringUtils.equals(request.getParameter("command"), "displayActionListView")
102 || StringUtils.equals(request.getParameter("command"), "displayDocSearchView")) {
103 documentId = (String) request.getParameter("docId");
104 }
105
106 LOG.debug("DOCID: " + documentId);
107
108 // if the reload was trigger by changing of the selectedPayPeriod, use the passed in parameter as the calendar entry id
109 String calendarEntryId = StringUtils.isNotBlank(request.getParameter("selectedPP")) ? request.getParameter("selectedPP") : lcf.getCalEntryId();
110
111 // Here - viewPrincipal will be the principal of the user we intend to
112 // view, be it target user, backdoor or otherwise.
113 String viewPrincipal = TKUser.getCurrentTargetPersonId();
114 CalendarEntries calendarEntry = null;
115
116 LeaveCalendarDocument lcd = null;
117 LeaveCalendarDocumentHeader lcdh = null;
118
119 // By handling the prev/next in the execute method, we are saving one
120 // fetch/construction of a LeaveCalendarDocument. If it were broken out into
121 // methods, we would first fetch the current document, and then fetch
122 // the next one instead of doing it in the single action.
123 if (StringUtils.isNotBlank(documentId)) {
124 lcd = TkServiceLocator.getLeaveCalendarService()
125 .getLeaveCalendarDocument(documentId);
126 if (lcd != null) {
127 calendarEntry = lcd.getCalendarEntry();
128 }
129 } else if (StringUtils.isNotBlank(calendarEntryId)) {
130 // do further procedure
131 calendarEntry = TkServiceLocator.getCalendarEntriesService()
132 .getCalendarEntries(calendarEntryId);
133 } else {
134 // Default to whatever is active for "today".
135 Date currentDate = TKUtils.getTimelessDate(null);
136 calendarEntry = TkServiceLocator.getCalendarService()
137 .getCurrentCalendarDatesForLeaveCalendar(viewPrincipal, currentDate);
138 }
139 lcf.setCalendarEntry(calendarEntry);
140 if(calendarEntry != null) {
141 lcf.setCalEntryId(calendarEntry.getHrCalendarEntriesId());
142 }
143 // check configuration setting for allowing accrual service to be ran from leave calendar
144 String runAccrualFlag = ConfigContext.getCurrentContextConfig().getProperty(LMConstants.RUN_ACCRUAL_FROM_CALENDAR);
145 if(StringUtils.equals(runAccrualFlag, "true")) {
146 // run accrual for future dates only, use planning month of leave plan for accrual period
147 // only run the accrual if the calendar entry contains future dates
148 if(calendarEntry != null && calendarEntry.getEndPeriodDate().after(TKUtils.getCurrentDate())) {
149 if(TkServiceLocator.getLeaveAccrualService().statusChangedSinceLastRun(viewPrincipal)) {
150 TkServiceLocator.getLeaveAccrualService().calculateFutureAccrualUsingPlanningMonth(viewPrincipal, calendarEntry.getBeginPeriodDate());
151 }
152 }
153 }
154
155 if(lcd == null) {
156 // use jobs to find out if this leave calendar should have a document created or not
157 boolean createFlag = TkServiceLocator.getLeaveCalendarService().shouldCreateLeaveDocument(viewPrincipal, calendarEntry);
158 if(createFlag) {
159 lcd = TkServiceLocator.getLeaveCalendarService().openLeaveCalendarDocument(viewPrincipal, calendarEntry);
160 } else {
161 if (calendarEntry != null) {
162 LeaveCalendarDocumentHeader header = TkServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(viewPrincipal, calendarEntry.getBeginPeriodDateTime(), calendarEntry.getEndPeriodDateTime());
163 if(header != null) {
164 lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(header.getDocumentId());
165 }
166 }
167 }
168 }
169 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByCalEntryForLeaveCalendar(viewPrincipal, calendarEntry);
170 List<String> assignmentKeys = new ArrayList<String>();
171 for(Assignment assign : assignments) {
172 assignmentKeys.add(assign.getAssignmentKey());
173 }
174 if (lcd != null) {
175 lcf.setDocumentId(lcd.getDocumentId());
176 lcf.setAssignmentDescriptions(TkServiceLocator.getAssignmentService().getAssignmentDescriptions(lcd));
177 lcdh = lcd.getDocumentHeader();
178 } else {
179 lcf.setAssignmentDescriptions(TkServiceLocator.getAssignmentService().getAssignmentDescriptionsForAssignments(assignments));
180 }
181 setupDocumentOnFormContext(lcf, lcd);
182 ActionForward forward = super.execute(mapping, form, request, response);
183 //no window exists if mapping->forward = closeBalanceTransferDoc.
184 if (forward.getRedirect()) {
185 return forward;
186 }
187
188 LeaveCalendar calendar = null;
189 if (calendarEntry != null) {
190 calendar = new LeaveCalendar(viewPrincipal, calendarEntry, assignmentKeys);
191 lcf.setLeaveCalendar(calendar);
192 }
193
194 this.populateCalendarAndPayPeriodLists(request, lcf);
195
196 // KPME-1447
197 List<LeaveBlock> leaveBlocks = new ArrayList<LeaveBlock>();
198 if (lcdh != null && lcdh.getPrincipalId() != null && lcdh.getBeginDate() != null && lcdh.getEndDate() != null) {
199 leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForLeaveCalendar(lcdh.getPrincipalId(), lcdh.getBeginDate(), lcdh.getEndDate(), assignmentKeys);
200 } else if(calendarEntry != null){
201 leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForLeaveCalendar(viewPrincipal, calendarEntry.getBeginPeriodDate(), calendarEntry.getEndPeriodDate(), assignmentKeys);
202 }
203
204 // leave summary
205 if (calendarEntry != null) {
206 //check to see if we are on a previous leave plan
207 PrincipalHRAttributes principalCal = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(viewPrincipal, calendarEntry.getEndPeriodDate());
208 if(principalCal != null) {
209
210 DateTime currentYearBeginDate = TkServiceLocator.getLeavePlanService().getFirstDayOfLeavePlan(principalCal.getLeavePlan(), TKUtils.getCurrentDate());
211 DateTime calEntryEndDate = new DateTime(calendarEntry.getEndPeriodDate());
212 if (calEntryEndDate.getMillis() > currentYearBeginDate.getMillis()) {
213 //current or future year
214 LeaveSummary ls = TkServiceLocator.getLeaveSummaryService().getLeaveSummary(viewPrincipal, calendarEntry);
215 lcf.setLeaveSummary(ls);
216 } else {
217 //current year roll over date has been passed, all previous calendars belong to the previous leave plan calendar year.
218 DateTime effDate = TkServiceLocator.getLeavePlanService().getRolloverDayOfLeavePlan(principalCal.getLeavePlan(), calEntryEndDate.toDate()).minus(1);
219 LeaveSummary ls = TkServiceLocator.getLeaveSummaryService().getLeaveSummaryAsOfDateWithoutFuture(viewPrincipal, new java.sql.Date(effDate.getMillis()));
220 //override title element (based on date passed in)
221 DateFormat formatter = new SimpleDateFormat("MMMM d");
222 DateFormat formatter2 = new SimpleDateFormat("MMMM d yyyy");
223 DateTime entryEndDate = new LocalDateTime(calendarEntry.getEndPeriodDate()).toDateTime();
224 if (entryEndDate.getHourOfDay() == 0) {
225 entryEndDate = entryEndDate.minusDays(1);
226 }
227 String aString = formatter.format(calendarEntry.getBeginPeriodDate()) + " - " + formatter2.format(entryEndDate.toDate());
228 ls.setPendingDatesString(aString);
229 DateTimeFormatter fmt = DateTimeFormat.forPattern("MMM d, yyyy");
230 ls.setNote("Values as of: " + fmt.print(effDate));
231 lcf.setLeaveSummary(ls);
232 }
233
234 }
235 }
236
237 // add warning messages based on earn codes of leave blocks
238 Map<String, Set<String>> allMessages = LeaveCalendarValidationUtil.getWarningMessagesForLeaveBlocks(leaveBlocks);
239
240 // add warning message for accrual categories that have exceeded max balance.
241
242 // Could set a flag on the transferable rows here so that LeaveCalendarSubmit.do knows
243 // which row(s) to transfer when user submits the calendar for approval.
244
245 if(ObjectUtils.isNotNull(calendarEntry)) {
246 PrincipalHRAttributes principalCalendar = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(viewPrincipal, calendarEntry.getEndPeriodDate());
247 List<BalanceTransfer> losses = new ArrayList<BalanceTransfer>();
248
249 Interval calendarInterval = new Interval(calendarEntry.getBeginPeriodDate().getTime(), calendarEntry.getEndPeriodDate().getTime());
250 Map<String,Set<LeaveBlock>> maxBalInfractions = new HashMap<String,Set<LeaveBlock>>();
251
252 Date effectiveDate = TKUtils.getCurrentDate();
253 if(!calendarInterval.contains(TKUtils.getCurrentDate().getTime()))
254 effectiveDate = calendarEntry.getEndPeriodDate();
255
256 if(ObjectUtils.isNotNull(principalCalendar)) {
257 maxBalInfractions = TkServiceLocator.getAccrualCategoryMaxBalanceService().getMaxBalanceViolations(calendarEntry, viewPrincipal);
258
259 LeaveSummary summary = lcf.getLeaveSummary();
260 for(Entry<String,Set<LeaveBlock>> entry : maxBalInfractions.entrySet()) {
261 for(LeaveBlock lb : entry.getValue()) {
262 AccrualCategory accrualCat = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(lb.getAccrualCategory(), lb.getLeaveDate());
263 AccrualCategoryRule aRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(lb.getAccrualCategoryRuleId());
264 if(StringUtils.equals(aRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
265 DateTime aDate = null;
266 if(StringUtils.equals(aRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
267 aDate = TkServiceLocator.getLeavePlanService().getRolloverDayOfLeavePlan(principalCalendar.getLeavePlan(), lb.getLeaveDate());
268 }
269 else {
270 Calendar cal = TkServiceLocator.getCalendarService().getCalendarByPrincipalIdAndDate(viewPrincipal, lb.getLeaveDate(), true);
271 CalendarEntries leaveEntry = TkServiceLocator.getCalendarEntriesService().getCurrentCalendarEntriesByCalendarId(cal.getHrCalendarId(), lb.getLeaveDate());
272 aDate = new DateTime(leaveEntry.getEndPeriodDate());
273 }
274 aDate = aDate.minusDays(1);
275 if(calendarInterval.contains(aDate.getMillis()) && aDate.toDate().compareTo(calendarEntry.getEndPeriodDate()) <= 0) {
276 //may want to calculate summary for all rows, displayable or not, and determine displayability via tags.
277 AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(aRule.getLmAccrualCategoryId());
278 BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(viewPrincipal, accrualCategory, lb.getLeaveDate());
279
280 BalanceTransfer loseTransfer = TkServiceLocator.getBalanceTransferService().initializeTransfer(viewPrincipal, lb.getAccrualCategoryRuleId(), accruedBalance, lb.getLeaveDate());
281 boolean valid = BalanceTransferValidationUtils.validateTransfer(loseTransfer);
282 if(valid)
283 losses.add(loseTransfer);
284 }
285 }
286 else if(StringUtils.equals(LMConstants.MAX_BAL_ACTION_FREQ.ON_DEMAND, aRule.getMaxBalanceActionFrequency())) {
287 if(calendarInterval.contains(lb.getLeaveDate().getTime())) {
288 // accrual categories within the leave plan that are hidden from the leave summary will not appear.
289 List<LeaveSummaryRow> summaryRows = summary.getLeaveSummaryRows();
290 List<LeaveSummaryRow> updatedSummaryRows = new ArrayList<LeaveSummaryRow>(summaryRows.size());
291 //AccrualCategoryRule currentRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRuleForDate(accrualCat, effectiveDate, principalCalendar.getServiceDate());
292 for(LeaveSummaryRow summaryRow : summaryRows) {
293 if(StringUtils.equals(summaryRow.getAccrualCategory(),accrualCat.getAccrualCategory())) {
294 if(StringUtils.equals(aRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.PAYOUT))
295 summaryRow.setPayoutable(true);
296 else
297 if(StringUtils.equals(aRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.TRANSFER))
298 summaryRow.setTransferable(true);
299
300 summaryRow.setInfractingLeaveBlockId(lb.getLmLeaveBlockId());
301 }
302 updatedSummaryRows.add(summaryRow);
303 }
304 summary.setLeaveSummaryRows(updatedSummaryRows);
305 }
306 }
307
308 if(calendarInterval.contains(lb.getLeaveDate().getTime())) {
309 // accrual categories within the leave plan that are hidden from the leave summary WILL appear.
310 String message = "You have exceeded the maximum balance limit for '" + accrualCat.getAccrualCategory() + "' as of " + lb.getLeaveDate() + ". "+
311 "Depending upon the accrual category rules, leave over this limit may be forfeited.";
312 // leave blocks are sorted in getMaxBalanceViolations() method, so we just take the one with the earliest leave date for an accrual category.
313 if(!StringUtils.contains(allMessages.get("warningMessages").toString(),"You have exceeded the maximum balance limit for '"+accrualCat.getAccrualCategory())) {
314 allMessages.get("warningMessages").add(message);
315 }
316 }
317 }
318 }
319 lcf.setLeaveSummary(summary);
320 }
321 lcf.setForfeitures(losses);
322
323 Map<String,Set<String>> transactions = LeaveCalendarValidationUtil.validatePendingTransactions(viewPrincipal, calendarEntry.getBeginPeriodDate(), calendarEntry.getEndPeriodDate());
324
325 allMessages.get("infoMessages").addAll(transactions.get("infoMessages"));
326 allMessages.get("warningMessages").addAll(transactions.get("warningMessages"));
327 allMessages.get("actionMessages").addAll(transactions.get("actionMessages"));
328 }
329
330
331
332
333 // add warning messages based on max carry over balances for each accrual category
334 if(calendarEntry != null) {
335 PrincipalHRAttributes principalCalendar = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(viewPrincipal, calendarEntry.getEndPeriodDate());
336 if (principalCalendar != null) {
337 List<AccrualCategory> accrualCategories = TkServiceLocator.getAccrualCategoryService().getActiveLeaveAccrualCategoriesForLeavePlan(principalCalendar.getLeavePlan(), new java.sql.Date(calendarEntry.getEndPeriodDate().getTime()));
338 for (AccrualCategory accrualCategory : accrualCategories) {
339 if (TkServiceLocator.getAccrualCategoryMaxCarryOverService().exceedsAccrualCategoryMaxCarryOver(accrualCategory.getAccrualCategory(), viewPrincipal, calendarEntry, calendarEntry.getEndPeriodDate())) {
340 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.";
341 if (!allMessages.get("warningMessages").contains(message)) {
342 allMessages.get("warningMessages").add(message);
343 }
344 }
345 }
346 }
347 }
348
349 List<String> warningMessages = new ArrayList<String>();
350 List<String> infoMessages = new ArrayList<String>();
351 List<String> actionMessages = new ArrayList<String>();
352
353 warningMessages.addAll(allMessages.get("warningMessages"));
354 infoMessages.addAll(allMessages.get("infoMessages"));
355 actionMessages.addAll(allMessages.get("actionMessages"));
356
357 lcf.setWarningMessages(warningMessages);
358 lcf.setInfoMessages(infoMessages);
359 lcf.setActionMessages(actionMessages);
360
361 // KPME-1690
362 // LeaveCalendar leaveCalender = new LeaveCalendar(viewPrincipal, calendarEntry);
363 if (calendarEntry != null) {
364 LeaveBlockAggregate aggregate = new LeaveBlockAggregate(leaveBlocks, calendarEntry, calendar);
365 lcf.setLeaveBlockString(LeaveActionFormUtils.getLeaveBlocksJson(aggregate.getFlattenedLeaveBlockList()));
366 }
367 //lcf.setLeaveBlockString(ActionFormUtils.getLeaveBlocksJson(aggregate.getFlattenedLeaveBlockList()));
368
369 // System.out.println("Leave block string : "+lcf.getLeaveBlockString());
370 return forward;
371 }
372
373 private void populateCalendarAndPayPeriodLists(HttpServletRequest request, LeaveCalendarForm lcf) {
374 String viewPrincipal = TKUser.getCurrentTargetPersonId();
375 SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
376 // find all the calendar entries up to the planning months of this employee
377 List<CalendarEntries> ceList = lcf.getCalendarEntry() == null ? new ArrayList<CalendarEntries>() : TkServiceLocator.getCalendarEntriesService()
378 .getAllCalendarEntriesForCalendarIdUpToPlanningMonths(lcf.getCalendarEntry().getHrCalendarId(), TKUser.getCurrentTargetPersonId());
379
380 if(lcf.getCalendarYears().isEmpty()) {
381 // get calendar year drop down list contents
382 Set<String> yearSet = new HashSet<String>();
383 for(CalendarEntries ce : ceList) {
384 yearSet.add(sdf.format(ce.getBeginPeriodDate()));
385 }
386 List<String> yearList = new ArrayList<String>(yearSet);
387 Collections.sort(yearList);
388 Collections.reverse(yearList); // newest on top
389 lcf.setCalendarYears(yearList);
390 }
391 // if selected calendar year is passed in
392 if(request.getParameter("selectedCY")!= null) {
393 lcf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
394 }
395 // if there is no selected calendr year, use the year of current pay calendar entry
396 if(StringUtils.isEmpty(lcf.getSelectedCalendarYear())
397 && lcf.getCalendarEntry() != null) {
398 lcf.setSelectedCalendarYear(sdf.format(lcf.getCalendarEntry().getBeginPeriodDate()));
399 }
400
401 if(lcf.getPayPeriodsMap().isEmpty()) {
402 List<CalendarEntries> yearCEList = ActionFormUtils.getAllCalendarEntriesForYear(ceList, lcf.getSelectedCalendarYear());
403 lcf.setPayPeriodsMap(ActionFormUtils.getPayPeriodsMap(yearCEList, viewPrincipal));
404 }
405
406 if(request.getParameter("selectedPP")!= null) {
407 lcf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
408 }
409 if(StringUtils.isEmpty(lcf.getSelectedPayPeriod())
410 && lcf.getCalendarEntry() != null) {
411 lcf.setSelectedPayPeriod(lcf.getCalendarEntry().getHrCalendarEntriesId());
412 }
413 }
414
415 public ActionForward addLeaveBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
416 LeaveCalendarForm lcf = (LeaveCalendarForm) form;
417 LeaveCalendarDocument lcd = lcf.getLeaveCalendarDocument();
418
419 String principalId = TKContext.getPrincipalId();
420 String targetPrincipalId = TKContext.getTargetPrincipalId();
421 CalendarEntries calendarEntry = lcf.getCalendarEntry();
422 String selectedAssignment = lcf.getSelectedAssignment();
423
424 DateTime beginDate = null;
425 DateTime endDate = null;
426
427 /** -- Jignasha : if earchcode type is 'T' then change the date and time with timezone.
428 // Surgery point - Need to construct a Date/Time with Appropriate Timezone.
429 * */
430 LOG.debug("Start time is "+lcf.getStartTime());
431 LOG.debug("Emnd time is "+lcf.getEndTime());
432 if(lcf.getStartTime() != null && lcf.getEndTime() != null) {
433 beginDate = new DateTime(TKUtils.convertDateStringToTimestampWithoutZone(lcf.getStartDate(), lcf.getStartTime()).getTime());
434 endDate = new DateTime(TKUtils.convertDateStringToTimestampWithoutZone(lcf.getEndDate(), lcf.getEndTime()).getTime());
435 } else {
436 beginDate = new DateTime(TKUtils.convertDateStringToTimestampNoTimezone(lcf.getStartDate()));
437 endDate = new DateTime(TKUtils.convertDateStringToTimestampNoTimezone(lcf.getEndDate()));
438 }
439 LOG.debug("Begin Date is>> "+beginDate);
440 LOG.debug("End Date is>> "+endDate);
441
442 /** Old Code
443 DateTime beginDate = new DateTime(TKUtils.convertDateStringToTimestampNoTimezone(lcf.getStartDate()));
444 DateTime endDate = new DateTime(TKUtils.convertDateStringToTimestampNoTimezone(lcf.getEndDate()));
445 */
446
447 String selectedEarnCode = lcf.getSelectedEarnCode();
448 BigDecimal hours = lcf.getLeaveAmount();
449 String desc = lcf.getDescription();
450 String spanningWeeks = lcf.getSpanningWeeks(); // KPME-1446
451
452 String documentId = lcd != null ? lcd.getDocumentId() : "";
453
454 Assignment assignment = null;
455 if(lcd != null) {
456 assignment = TkServiceLocator.getAssignmentService().getAssignment(lcd, selectedAssignment);
457 } else {
458 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByCalEntryForLeaveCalendar(targetPrincipalId, calendarEntry);
459 assignment = TkServiceLocator.getAssignmentService().getAssignment(assignments, selectedAssignment, calendarEntry.getBeginPeriodDate());
460 }
461
462 TkServiceLocator.getLeaveBlockService().addLeaveBlocks(beginDate, endDate, calendarEntry, selectedEarnCode, hours, desc, assignment, spanningWeeks,
463 LMConstants.LEAVE_BLOCK_TYPE.LEAVE_CALENDAR, targetPrincipalId);
464
465 generateLeaveCalendarChangedNotification(principalId, targetPrincipalId, documentId, calendarEntry.getHrCalendarEntriesId());
466
467 // after adding the leave block, set the fields of this form to null for future new leave blocks
468 lcf.setLeaveAmount(null);
469 lcf.setDescription(null);
470
471 // call accrual service if earn code is not eligible for accrual
472 if(calendarEntry != null) {
473 java.sql.Date sqlDate = new java.sql.Date(endDate.getMillis());
474 this.rerunAccrualForNotEligibleForAccrualChanges(selectedEarnCode, sqlDate, calendarEntry.getBeginPeriodDate(), calendarEntry.getEndPeriodDate());
475 }
476 // recalculate summary
477 if (calendarEntry != null) {
478 LeaveSummary ls = TkServiceLocator.getLeaveSummaryService().getLeaveSummary(targetPrincipalId, calendarEntry);
479 lcf.setLeaveSummary(ls);
480 }
481
482 return mapping.findForward("basic");
483 }
484
485
486 public ActionForward deleteLeaveBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
487 LeaveCalendarForm lcf = (LeaveCalendarForm) form;
488 LeaveCalendarDocument lcd = lcf.getLeaveCalendarDocument();
489
490 String principalId = TKContext.getPrincipalId();
491 String targetPrincipalId = TKContext.getTargetPrincipalId();
492 CalendarEntries calendarEntry = lcf.getCalendarEntry();
493 String leaveBlockId = lcf.getLeaveBlockId();
494
495 String documentId = lcd != null ? lcd.getDocumentId() : "";
496
497 LeaveBlock blockToDelete = TkServiceLocator.getLeaveBlockService().getLeaveBlock(leaveBlockId);
498 if (blockToDelete != null && TkServiceLocator.getPermissionsService().canDeleteLeaveBlock(blockToDelete)) {
499 //if leave block is a pending leave request, cancel the leave request document
500 if(blockToDelete.getRequestStatus().equals(LMConstants.REQUEST_STATUS.REQUESTED)) {
501 List<LeaveRequestDocument> lrdList = TkServiceLocator.getLeaveRequestDocumentService().getLeaveRequestDocumentsByLeaveBlockId(blockToDelete.getLmLeaveBlockId());
502 if(CollectionUtils.isNotEmpty(lrdList)) {
503 for(LeaveRequestDocument lrd : lrdList) {
504 DocumentStatus status = KewApiServiceLocator.getWorkflowDocumentService().getDocumentStatus(lrd.getDocumentNumber());
505 if(DocumentStatus.ENROUTE.getCode().equals(status.getCode())) {
506 // cancel the leave request document as the employee.
507 TkServiceLocator.getLeaveRequestDocumentService().recallAndCancelLeave(lrd.getDocumentNumber(), targetPrincipalId, "Leave block deleted by user " + principalId);
508 }
509 }
510 }
511 }
512
513 List<String> approverList = new ArrayList<String>();
514 //if leave block is an approved leave request, get list of approver's id
515 if(blockToDelete.getRequestStatus().equals(LMConstants.REQUEST_STATUS.APPROVED)) {
516 List<LeaveRequestDocument> lrdList = TkServiceLocator.getLeaveRequestDocumentService().getLeaveRequestDocumentsByLeaveBlockId(blockToDelete.getLmLeaveBlockId());
517 if(CollectionUtils.isNotEmpty(lrdList)) {
518 for(LeaveRequestDocument lrd : lrdList) {
519 DocumentStatus status = KewApiServiceLocator.getWorkflowDocumentService().getDocumentStatus(lrd.getDocumentNumber());
520 if(DocumentStatus.FINAL.getCode().equals(status.getCode())) {
521 // get approver's id for sending out email notification later
522 approverList = TkServiceLocator.getLeaveRequestDocumentService().getApproverIdList(lrd.getDocumentNumber());
523 }
524 }
525 }
526 }
527
528 TkServiceLocator.getLeaveBlockService().deleteLeaveBlock(leaveBlockId, principalId);
529 generateLeaveCalendarChangedNotification(principalId, targetPrincipalId, documentId, calendarEntry.getHrCalendarEntriesId());
530 if(CollectionUtils.isNotEmpty(approverList)) {
531 this.generateLeaveBlockDeletionNotification(approverList, targetPrincipalId, principalId, TKUtils.formatDate(blockToDelete.getLeaveDate()), blockToDelete.getLeaveAmount().toString());
532 }
533
534 // recalculate accruals
535 if(lcf.getCalendarEntry() != null) {
536 rerunAccrualForNotEligibleForAccrualChanges(blockToDelete.getEarnCode(), blockToDelete.getLeaveDate(), calendarEntry.getBeginPeriodDate(), calendarEntry.getEndPeriodDate());
537 }
538 }
539 // recalculate summary
540 if(lcf.getCalendarEntry() != null) {
541 LeaveSummary ls = TkServiceLocator.getLeaveSummaryService().getLeaveSummary(targetPrincipalId, calendarEntry);
542 lcf.setLeaveSummary(ls);
543 }
544 return mapping.findForward("basic");
545 }
546
547 /**
548 * Recalculate accrual when a leave block with not-eligible-for-accrual earn code is added or deleted
549 * calculate accrual only for the calendar entry period
550 * @param earnCode
551 * @param asOfDate
552 * @param startDate
553 * @param endDate
554 */
555 private void rerunAccrualForNotEligibleForAccrualChanges(String earnCode, Date asOfDate, Date startDate, Date endDate) {
556 EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(earnCode, asOfDate);
557 if(ec != null && ec.getEligibleForAccrual().equals("N")) {
558 if(startDate != null && endDate != null) {
559 // since we are only recalculating accrual for this pay period, we use "false" to not record the accrual run data
560 TkServiceLocator.getLeaveAccrualService().runAccrual(TKContext.getTargetPrincipalId(), startDate, endDate, false);
561 }
562 }
563 }
564
565 // KPME-1447
566 public ActionForward updateLeaveBlock(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
567 LeaveCalendarForm lcf = (LeaveCalendarForm) form;
568 LeaveCalendarDocument lcd = lcf.getLeaveCalendarDocument();
569
570 String principalId = TKContext.getPrincipalId();
571 String targetPrincipalId = TKContext.getTargetPrincipalId();
572 CalendarEntries calendarEntry = lcf.getCalendarEntry();
573 String selectedEarnCode = lcf.getSelectedEarnCode();
574 String leaveBlockId = lcf.getLeaveBlockId();
575
576 String documentId = lcd != null ? lcd.getDocumentId() : "";
577
578 LeaveBlock updatedLeaveBlock = null;
579 updatedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(leaveBlockId);
580 if (updatedLeaveBlock.isEditable()) {
581 if (StringUtils.isNotBlank(lcf.getDescription())) {
582 updatedLeaveBlock.setDescription(lcf.getDescription().trim());
583 }
584 if (!updatedLeaveBlock.getLeaveAmount().equals(lcf.getLeaveAmount())) {
585 updatedLeaveBlock.setLeaveAmount(lcf.getLeaveAmount());
586 }
587
588 DateTime beginDate = null;
589 DateTime endDate = null;
590
591 EarnCode earnCode = TkServiceLocator.getEarnCodeService().getEarnCode(selectedEarnCode, updatedLeaveBlock.getLeaveDate()); // selectedEarnCode = hrEarnCodeId
592 if(earnCode != null && earnCode.getRecordMethod().equalsIgnoreCase(TkConstants.EARN_CODE_TIME)) {
593 if(lcf.getStartTime() != null && lcf.getEndTime() != null) {
594 beginDate = new DateTime(TKUtils.convertDateStringToTimestampWithoutZone(lcf.getStartDate(), lcf.getStartTime()).getTime());
595 endDate = new DateTime(TKUtils.convertDateStringToTimestampWithoutZone(lcf.getEndDate(), lcf.getEndTime()).getTime());
596 } else {
597 beginDate = new DateTime(TKUtils.convertDateStringToTimestampNoTimezone(lcf.getStartDate()));
598 endDate = new DateTime(TKUtils.convertDateStringToTimestampNoTimezone(lcf.getEndDate()));
599 }
600 updatedLeaveBlock.setBeginTimestamp(new Timestamp(beginDate.getMillis()));
601 updatedLeaveBlock.setEndTimestamp(new Timestamp(endDate.getMillis()));
602 updatedLeaveBlock.setLeaveAmount(TKUtils.getHoursBetween(beginDate.getMillis(), endDate.getMillis()));
603 }
604
605 if (!updatedLeaveBlock.getEarnCode().equals(earnCode.getEarnCode())) {
606 updatedLeaveBlock.setEarnCode(earnCode.getEarnCode());
607 }
608
609 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(updatedLeaveBlock, principalId);
610 generateLeaveCalendarChangedNotification(principalId, targetPrincipalId, documentId, calendarEntry.getHrCalendarEntriesId());
611
612 lcf.setLeaveAmount(null);
613 lcf.setDescription(null);
614 lcf.setSelectedEarnCode(null);
615 // recalculate summary
616 if(lcf.getCalendarEntry() != null) {
617 LeaveSummary ls = TkServiceLocator.getLeaveSummaryService().getLeaveSummary(targetPrincipalId, calendarEntry);
618 lcf.setLeaveSummary(ls);
619 }
620 }
621 return mapping.findForward("basic");
622 }
623 protected void setupDocumentOnFormContext(LeaveCalendarForm leaveForm,
624 LeaveCalendarDocument lcd) {
625 CalendarEntries futureCalEntry = null;
626 String viewPrincipal = TKUser.getCurrentTargetPersonId();
627 CalendarEntries calEntry = leaveForm.getCalendarEntry();
628
629 Date startCalDate = null;
630
631 // some leave calendar may not have leaveCalendarDocument created based on the jobs status of this employee
632 if(lcd != null) {
633 if (lcd.getDocumentHeader() != null) {
634 TKContext.setCurrentLeaveCalendarDocumentId(lcd.getDocumentId());
635 leaveForm.setDocumentId(lcd.getDocumentId());
636 }
637 TKContext.setCurrentLeaveCalendarDocument(lcd);
638 TKContext.setCurrentLeaveCalendarDocumentId(lcd.getDocumentId());
639 leaveForm.setLeaveCalendarDocument(lcd);
640 leaveForm.setDocumentId(lcd.getDocumentId());
641 calEntry = lcd.getCalendarEntry();
642 }
643 // -- put condition if it is after current period
644 boolean isFutureDate = calEntry != null && TKUtils.getTimelessDate(null).compareTo(calEntry.getEndPeriodDateTime()) <= 0;
645
646 // fetch previous entry
647 if (calEntry != null) {
648 CalendarEntries calPreEntry = TkServiceLocator
649 .getCalendarEntriesService()
650 .getPreviousCalendarEntriesByCalendarId(
651 calEntry.getHrCalendarId(),
652 calEntry);
653 if (calPreEntry != null) {
654
655 // Check if service date of user is after the Calendar entry
656 Date asOfDate = new Date(DateUtils.addDays(calPreEntry.getEndPeriodDate(),-1).getTime());;
657 PrincipalHRAttributes principalHRAttributes = TkServiceLocator.getPrincipalHRAttributeService().getPrincipalCalendar(viewPrincipal, asOfDate);
658
659 if(principalHRAttributes != null) {
660 startCalDate = principalHRAttributes.getServiceDate();
661 if(startCalDate != null) {
662 if(!(calPreEntry.getBeginPeriodDate().compareTo(startCalDate) < 0)) {
663 leaveForm.setPrevCalEntryId(calPreEntry
664 .getHrCalendarEntriesId());
665 }
666 } else {
667 leaveForm.setPrevCalEntryId(calPreEntry
668 .getHrCalendarEntriesId());
669 }
670 }
671 }
672
673 int planningMonths = ActionFormUtils.getPlanningMonthsForEmployee(viewPrincipal);
674 if(planningMonths != 0) {
675 List<CalendarEntries> futureCalEntries = TkServiceLocator
676 .getCalendarEntriesService()
677 .getFutureCalendarEntries(
678 calEntry.getHrCalendarId(),
679 TKUtils.getTimelessDate(null),
680 planningMonths);
681
682 if (futureCalEntries != null && !futureCalEntries.isEmpty()) {
683 futureCalEntry = futureCalEntries.get(futureCalEntries
684 .size() - 1);
685
686 CalendarEntries calNextEntry = TkServiceLocator
687 .getCalendarEntriesService()
688 .getNextCalendarEntriesByCalendarId(
689 calEntry.getHrCalendarId(),
690 calEntry);
691
692 if (calNextEntry != null
693 && futureCalEntries != null
694 && calNextEntry
695 .getBeginPeriodDateTime()
696 .compareTo(
697 futureCalEntry
698 .getBeginPeriodDateTime()) <= 0) {
699 leaveForm.setNextCalEntryId(calNextEntry
700 .getHrCalendarEntriesId());
701 }
702 }
703 }
704 }
705 if(leaveForm.getViewLeaveTabsWithNEStatus()) {
706 if(isFutureDate) {
707 setDocEditable(leaveForm, lcd);
708 } else {
709 // retrieve current pay calendar date
710 Date currentDate = TKUtils.getTimelessDate(null);
711 CalendarEntries calendarEntry = TkServiceLocator.getCalendarService()
712 .getCurrentCalendarDatesForLeaveCalendar(viewPrincipal, currentDate);
713 if(calendarEntry != null) {
714 leaveForm.setCurrentPayCalStart(calendarEntry.getBeginLocalDateTime().toDateTime(TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback()));
715 leaveForm.setCurrentPayCalEnd(calendarEntry.getEndLocalDateTime().toDateTime(TkServiceLocator.getTimezoneService().getUserTimezoneWithFallback()));
716 }
717 }
718 } else {
719 setDocEditable(leaveForm, lcd);
720 }
721 leaveForm.setCalendarEntry(calEntry);
722 if(calEntry != null) {
723 leaveForm.setCalEntryId(calEntry.getHrCalendarEntriesId());
724 }
725 leaveForm.setOnCurrentPeriod(ActionFormUtils.getOnCurrentPeriodFlag(calEntry));
726
727 }
728
729 private void setDocEditable(LeaveCalendarForm leaveForm, LeaveCalendarDocument lcd) {
730 leaveForm.setDocEditable(false);
731 if(lcd == null) {
732 // working on own calendar
733 if(TKUser.getCurrentTargetPersonId().equals(GlobalVariables.getUserSession().getPrincipalId())) {
734 leaveForm.setDocEditable(true);
735 } else {
736 if(TKUser.isSystemAdmin()
737 || TKUser.isLocationAdmin()
738 || TKUser.isReviewer()
739 || TKUser.isApprover()) {
740 leaveForm.setDocEditable(true);
741 }
742 }
743 } else {
744 if (TKUser.isSystemAdmin() && !StringUtils.equals(lcd.getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())) {
745 leaveForm.setDocEditable(true);
746 } else {
747 String documentStatus = lcd.getDocumentHeader().getDocumentStatus();
748 boolean docFinal = DocumentStatus.FINAL.getCode().equals(documentStatus)
749 || DocumentStatus.CANCELED.getCode().equals(documentStatus)
750 || DocumentStatus.DISAPPROVED.getCode().equals(documentStatus);
751 if (!docFinal) {
752 if(StringUtils.equals(lcd.getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())
753 || TKUser.isSystemAdmin()
754 || TKUser.isLocationAdmin()
755 || TKUser.isReviewer()
756 || TKUser.isApprover()) {
757 leaveForm.setDocEditable(true);
758 }
759
760 //if the leave Calendar has been approved by at least one of the approvers, the employee should not be able to edit it
761 if (StringUtils.equals(lcd.getPrincipalId(), GlobalVariables.getUserSession().getPrincipalId())
762 && lcd.getDocumentHeader().getDocumentStatus().equals(TkConstants.ROUTE_STATUS.ENROUTE)) {
763 Collection actions = KEWServiceLocator.getActionTakenService().findByDocIdAndAction(lcd.getDocumentHeader().getDocumentId(), TkConstants.DOCUMENT_ACTIONS.APPROVE);
764 if(!actions.isEmpty()) {
765 leaveForm.setDocEditable(false);
766 }
767 }
768 }
769 }
770 }
771 }
772
773 public ActionForward gotoCurrentPayPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
774 LeaveCalendarForm lcf = (LeaveCalendarForm) form;
775 String viewPrincipal = TKUser.getCurrentTargetPersonId();
776 Date currentDate = TKUtils.getTimelessDate(null);
777 CalendarEntries calendarEntry = TkServiceLocator.getCalendarService().getCurrentCalendarDatesForLeaveCalendar(viewPrincipal, currentDate);
778 lcf.setCalendarEntry(calendarEntry);
779 if(calendarEntry != null) {
780 lcf.setCalEntryId(calendarEntry.getHrCalendarEntriesId());
781 }
782 lcf.setOnCurrentPeriod(ActionFormUtils.getOnCurrentPeriodFlag(calendarEntry));
783
784 LeaveCalendarDocument lcd = null;
785 // use jobs to find out if this leave calendar should have a document created or not
786 boolean createFlag = TkServiceLocator.getLeaveCalendarService().shouldCreateLeaveDocument(viewPrincipal, calendarEntry);
787 if(createFlag) {
788 lcd = TkServiceLocator.getLeaveCalendarService().openLeaveCalendarDocument(viewPrincipal, calendarEntry);
789 }
790 if (lcd != null) {
791 lcf.setAssignmentDescriptions(TkServiceLocator.getAssignmentService().getAssignmentDescriptions(lcd));
792 } else {
793 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByCalEntryForLeaveCalendar(viewPrincipal, calendarEntry);
794 lcf.setAssignmentDescriptions(TkServiceLocator.getAssignmentService().getAssignmentDescriptionsForAssignments(assignments));
795 }
796 setupDocumentOnFormContext(lcf, lcd);
797 return mapping.findForward("basic");
798 }
799
800 //Triggered by changes of pay period drop down list, reload the whole page based on the selected pay period
801 public ActionForward changeCalendarYear(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
802
803 LeaveCalendarForm lcf = (LeaveCalendarForm) form;
804 if(request.getParameter("selectedCY") != null) {
805 lcf.setSelectedCalendarYear(request.getParameter("selectedCY").toString());
806 }
807 return mapping.findForward("basic");
808 }
809
810 //Triggered by changes of pay period drop down list, reload the whole page based on the selected pay period
811 public ActionForward changePayPeriod(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
812 LeaveCalendarForm lcf = (LeaveCalendarForm) form;
813 if(request.getParameter("selectedPP") != null) {
814 lcf.setSelectedPayPeriod(request.getParameter("selectedPP").toString());
815 CalendarEntries ce = TkServiceLocator.getCalendarEntriesService()
816 .getCalendarEntries(request.getParameter("selectedPP").toString());
817 if(ce != null) {
818 String viewPrincipal = TKUser.getCurrentTargetPersonId();
819 lcf.setCalEntryId(ce.getHrCalendarEntriesId());
820 LeaveCalendarDocument lcd = null;
821 // use jobs to find out if this leave calendar should have a document created or not
822 boolean createFlag = TkServiceLocator.getLeaveCalendarService().shouldCreateLeaveDocument(viewPrincipal, ce);
823 if(createFlag) {
824 lcd = TkServiceLocator.getLeaveCalendarService().openLeaveCalendarDocument(viewPrincipal, ce);
825 }
826 if(lcd != null) {
827 lcf.setAssignmentDescriptions(TkServiceLocator.getAssignmentService().getAssignmentDescriptions(lcd));
828 } else {
829 List<Assignment> assignments = TkServiceLocator.getAssignmentService().getAssignmentsByCalEntryForLeaveCalendar(viewPrincipal, ce);
830 lcf.setAssignmentDescriptions(TkServiceLocator.getAssignmentService().getAssignmentDescriptionsForAssignments(assignments));
831 }
832 setupDocumentOnFormContext(lcf, lcd);
833 }
834 }
835 return mapping.findForward("basic");
836 }
837
838 private void generateLeaveCalendarChangedNotification(String principalId, String targetPrincipalId, String documentId, String hrCalendarEntryId) {
839 if (!StringUtils.equals(principalId, targetPrincipalId)) {
840 EntityNamePrincipalName person = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(principalId);
841 if (person != null && person.getDefaultName() != null) {
842 String subject = "Leave Calendar Modification Notice";
843 StringBuilder message = new StringBuilder();
844 message.append("Your Leave Calendar was changed by ");
845 message.append(person.getDefaultName().getCompositeNameUnmasked());
846 message.append(" on your behalf.");
847 message.append(SystemUtils.LINE_SEPARATOR);
848 message.append(getLeaveCalendarURL(documentId, hrCalendarEntryId));
849
850 TkServiceLocator.getKPMENotificationService().sendNotification(subject, message.toString(), targetPrincipalId);
851 }
852 }
853 }
854
855 private void generateLeaveBlockDeletionNotification(List<String> approverIdList, String employeeId, String userId, String dateString, String hrString) {
856 EntityNamePrincipalName employee = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(employeeId);
857 EntityNamePrincipalName user = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(userId);
858 if (employee != null
859 && user != null
860 && employee.getDefaultName() != null
861 && user.getDefaultName() != null) {
862 String subject = "Leave Request Deletion Notice";
863 StringBuilder message = new StringBuilder();
864 message.append("An Approved leave request of ").append(hrString).append(" hours on Date ").append(dateString);
865 message.append(" for ").append(employee.getDefaultName().getCompositeNameUnmasked()).append(" was deleted by ");
866 message.append(user.getDefaultName().getCompositeNameUnmasked());
867 for(String anId : approverIdList) {
868 TkServiceLocator.getKPMENotificationService().sendNotification(subject, message.toString(), anId);
869 }
870 }
871 }
872
873 @SuppressWarnings("deprecation")
874 private String getLeaveCalendarURL(String documentId, String hrCalendarEntryId) {
875 Properties params = new Properties();
876 params.put("documentId", documentId);
877 params.put("calEntryId", hrCalendarEntryId);
878 return UrlFactory.parameterizeUrl(getApplicationBaseUrl() + "/LeaveCalendar.do", params);
879 }
880
881 /**
882 * Handles the PAYOUT action of balance transfers issued from the leave calendar with frequency "on demand".
883 *
884 * This action should be triggered after the user submits to a prompt generated by clicking a "PAYOUT" button on the leave
885 * calendar. This button should only be displayed if, for the current pay period, a max balance has been reached
886 * and the max balance action frequency is set to "On-Demand". The prompt must allow the user to edit the transfer amount.
887 * It may or may not need to show the "to" and "from" accrual categories in the initial prompt, but could on a confirmation
888 * prompt - along with the transfer amount adjusted by the max balance conversion factor.
889 *
890 * Balance transfers with frequency of leave approval should be handled during the submission of the
891 * leave calendar document for approval and should be automated.
892 *
893 * @param mapping
894 * @param form
895 * @param request
896 * @param response
897 * @return
898 */
899 public ActionForward payoutOnDemandBalanceTransfer(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
900 /**
901 * TODO: create one new leave block, if applicable; the amount forfeited by this transfer action.
902 *
903 * The amount transfered, pending adjustment via the max balance conversion factor, will be put into a pay out earn code
904 * that can be redeemed/used by the employee at a later time.
905 */
906
907 return mapping.findForward("basic");
908 }
909
910 /**
911 * Leave Payout
912 *
913 * @param mapping
914 * @param form
915 * @param request
916 * @param response
917 * @return
918 */
919 public ActionForward leavePayout(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) {
920
921 return mapping.findForward("basic");
922 }
923
924 public ActionForward docHandler(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
925 ActionForward forward = mapping.findForward("basic");
926 String command = request.getParameter("command");
927
928 if (StringUtils.equals(command, "displayDocSearchView")
929 || StringUtils.equals(command, "displayActionListView")
930 || StringUtils.equals(command, "displaySuperUserView")) {
931 String docId = (String) request.getParameter("docId");
932 LeaveCalendarDocument leaveCalendarDocument = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(docId);
933 String timesheetPrincipalName = null;
934 if (leaveCalendarDocument != null) {
935 timesheetPrincipalName = KimApiServiceLocator.getPersonService().getPerson(leaveCalendarDocument.getPrincipalId()).getPrincipalName();
936 }
937
938 String principalId = TKUser.getCurrentTargetPersonId();
939 String principalName = KimApiServiceLocator.getPersonService().getPerson(principalId).getPrincipalName();
940
941 StringBuilder builder = new StringBuilder();
942 if (!StringUtils.equals(principalName, timesheetPrincipalName)) {
943 if (StringUtils.equals(command, "displayDocSearchView")
944 || StringUtils.equals(command, "displaySuperUserView")) {
945 builder.append("changeTargetPerson.do?methodToCall=changeTargetPerson");
946 builder.append("&documentId=");
947 builder.append(docId);
948 builder.append("&principalName=");
949 builder.append(timesheetPrincipalName);
950 builder.append("&targetUrl=LeaveCalendar.do");
951 builder.append("?documentId=").append(docId);
952 builder.append("&returnUrl=LeaveApproval.do");
953 } else {
954 builder.append("LeaveApproval.do");
955 builder.append("?documentId=").append(docId);
956 }
957 } else {
958 builder.append("LeaveCalendar.do");
959 builder.append("?documentId=" + docId);
960 }
961
962 forward = new ActionRedirect(builder.toString());
963 /*ActionRedirect fwd = new ActionRedirect(builder.toString());
964 if (StringUtils.isNotEmpty(docId)) {
965 fwd.addParameter("documentId", docId);
966 }*/
967 }
968
969 return forward;
970 }
971
972 }