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    }