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