View Javadoc

1   /**
2    * Copyright 2004-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.hr.lm.leavecalendar.web;
17  
18  import org.apache.commons.collections.CollectionUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.apache.commons.lang.SystemUtils;
21  import org.apache.commons.lang.time.DateUtils;
22  import org.apache.log4j.Logger;
23  import org.apache.struts.action.ActionForm;
24  import org.apache.struts.action.ActionForward;
25  import org.apache.struts.action.ActionMapping;
26  import org.apache.struts.action.ActionRedirect;
27  import org.joda.time.DateTime;
28  import org.joda.time.Interval;
29  import org.joda.time.LocalDateTime;
30  import org.joda.time.format.DateTimeFormat;
31  import org.joda.time.format.DateTimeFormatter;
32  import org.kuali.hr.lm.LMConstants;
33  import org.kuali.hr.lm.accrual.AccrualCategory;
34  import org.kuali.hr.lm.accrual.AccrualCategoryRule;
35  import org.kuali.hr.lm.balancetransfer.BalanceTransfer;
36  import org.kuali.hr.lm.balancetransfer.validation.BalanceTransferValidationUtils;
37  import org.kuali.hr.lm.leaveSummary.LeaveSummary;
38  import org.kuali.hr.lm.leaveSummary.LeaveSummaryRow;
39  import org.kuali.hr.lm.leaveblock.LeaveBlock;
40  import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument;
41  import org.kuali.hr.lm.leavecalendar.validation.LeaveCalendarValidationUtil;
42  import org.kuali.hr.lm.util.LeaveBlockAggregate;
43  import org.kuali.hr.lm.workflow.LeaveCalendarDocumentHeader;
44  import org.kuali.hr.lm.workflow.LeaveRequestDocument;
45  import org.kuali.hr.time.assignment.Assignment;
46  import org.kuali.hr.time.base.web.TkAction;
47  import org.kuali.hr.time.calendar.Calendar;
48  import org.kuali.hr.time.calendar.CalendarEntries;
49  import org.kuali.hr.time.calendar.LeaveCalendar;
50  import org.kuali.hr.time.detail.web.ActionFormUtils;
51  import org.kuali.hr.time.earncode.EarnCode;
52  import org.kuali.hr.time.principal.PrincipalHRAttributes;
53  import org.kuali.hr.time.roles.TkUserRoles;
54  import org.kuali.hr.time.roles.UserRoles;
55  import org.kuali.hr.time.service.base.TkServiceLocator;
56  import org.kuali.hr.time.util.TKContext;
57  import org.kuali.hr.time.util.TKUser;
58  import org.kuali.hr.time.util.TKUtils;
59  import org.kuali.hr.time.util.TkConstants;
60  import org.kuali.rice.core.api.config.property.ConfigContext;
61  import org.kuali.rice.kew.api.KewApiServiceLocator;
62  import org.kuali.rice.kew.api.document.DocumentStatus;
63  import org.kuali.rice.kew.service.KEWServiceLocator;
64  import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
65  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
66  import org.kuali.rice.krad.exception.AuthorizationException;
67  import org.kuali.rice.krad.util.GlobalVariables;
68  import org.kuali.rice.krad.util.ObjectUtils;
69  import org.kuali.rice.krad.util.UrlFactory;
70  
71  import javax.servlet.http.HttpServletRequest;
72  import javax.servlet.http.HttpServletResponse;
73  import java.math.BigDecimal;
74  import java.sql.Date;
75  import java.sql.Timestamp;
76  import java.text.DateFormat;
77  import java.text.SimpleDateFormat;
78  import java.util.*;
79  import java.util.Map.Entry;
80  
81  public class LeaveCalendarAction extends TkAction {
82  
83  	private static final Logger LOG = Logger.getLogger(LeaveCalendarAction.class);
84  
85      @Override
86      protected void checkTKAuthorization(ActionForm form, String methodToCall) throws AuthorizationException {
87          UserRoles roles = TkUserRoles.getUserRoles(GlobalVariables.getUserSession().getPrincipalId());
88          LeaveCalendarDocument doc = TKContext.getCurrentLeaveCalendarDocument();
89  
90          if (doc != null && !roles.isDocumentReadable(doc)) {
91              throw new AuthorizationException(GlobalVariables.getUserSession().getPrincipalId(), "LeaveCalendarAction: docid: " + (doc == null ? "" : doc.getDocumentId()), "");
92          }
93      }
94      
95  	@Override
96  	public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
97  		LeaveCalendarForm lcf = (LeaveCalendarForm) form;
98  		String documentId = lcf.getDocumentId();
99  		
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 }