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