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