001 /**
002 * Copyright 2004-2013 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.hr.lm.leavepayout.web;
017
018 import java.sql.Date;
019 import java.util.ArrayList;
020 import java.util.List;
021 import java.util.Map;
022
023 import org.apache.commons.lang.time.DateUtils;
024 import org.apache.commons.lang3.StringUtils;
025 import org.apache.struts.action.ActionForm;
026 import org.apache.struts.action.ActionForward;
027 import org.apache.struts.action.ActionMapping;
028 import org.apache.struts.action.ActionRedirect;
029 import org.kuali.hr.lm.LMConstants;
030 import org.kuali.hr.lm.accrual.AccrualCategoryRule;
031 import org.kuali.hr.lm.leavepayout.LeavePayout;
032 import org.kuali.hr.lm.leavepayout.validation.LeavePayoutValidationUtils;
033 import org.kuali.hr.lm.leavepayout.web.LeavePayoutForm;
034 import org.kuali.hr.lm.leaveSummary.LeaveSummary;
035 import org.kuali.hr.lm.leaveSummary.LeaveSummaryRow;
036 import org.kuali.hr.lm.leaveblock.LeaveBlock;
037 import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument;
038 import org.kuali.hr.lm.workflow.LeaveCalendarDocumentHeader;
039 import org.kuali.hr.time.base.web.TkAction;
040 import org.kuali.hr.time.calendar.CalendarEntries;
041 import org.kuali.hr.time.service.base.TkServiceLocator;
042 import org.kuali.hr.time.timesheet.TimesheetDocument;
043 import org.kuali.hr.time.util.TKUtils;
044 import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
045 import org.kuali.rice.krad.util.GlobalVariables;
046 import org.kuali.rice.krad.util.ObjectUtils;
047
048 import javax.servlet.http.HttpServletRequest;
049 import javax.servlet.http.HttpServletResponse;
050
051 public class LeavePayoutAction extends TkAction {
052
053 public ActionForward leavePayoutOnLeaveApproval(ActionMapping mapping, ActionForm form,
054 HttpServletRequest request, HttpServletResponse response) throws Exception {
055
056 //if action was submit, execute the payout
057 LeavePayoutForm lpf = (LeavePayoutForm) form;
058 LeavePayout leavePayout = lpf.getLeavePayout();
059
060 boolean valid = LeavePayoutValidationUtils.validateTransfer(leavePayout);
061
062 //if payout amount has changed, and the resulting change produces forfeiture
063 //or changes the forfeiture amount, prompt for confirmation with the amount of
064 //forfeiture that the entered amount would produce.
065
066 if(valid) {
067
068 String accrualRuleId = leavePayout.getAccrualCategoryRule();
069
070 String documentId = leavePayout.getLeaveCalendarDocumentId();
071 TimesheetDocumentHeader tsdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(documentId);
072 LeaveCalendarDocumentHeader lcdh = TkServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(documentId);
073 CalendarEntries calendarEntry = null;
074 String strutsActionForward = "";
075 String methodToCall = "approveLeaveCalendar";
076 if(ObjectUtils.isNull(tsdh) && ObjectUtils.isNull(lcdh)) {
077 throw new RuntimeException("No document found");
078 }
079 else if(ObjectUtils.isNotNull(tsdh)) {
080 //Throws runtime exception, separate action forwards for timesheet/leave calendar payouts.
081 TimesheetDocument tsd = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId);
082 calendarEntry = tsd.getCalendarEntry();
083 strutsActionForward = "timesheetTransferSuccess";
084 methodToCall = "approveTimesheet";
085 }
086 else {
087 LeaveCalendarDocument lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(documentId);
088 calendarEntry = lcd.getCalendarEntry();
089 strutsActionForward = "leaveCalendarTransferSuccess";
090 methodToCall = "approveLeaveCalendar";
091 }
092
093 if(ObjectUtils.isNull(calendarEntry)) {
094 throw new RuntimeException("Could not retreive calendar entry for document " + documentId);
095 }
096
097 AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualRuleId);
098 Date effectiveDate = TKUtils.getCurrentDate();
099 if(TKUtils.getCurrentDate().after(calendarEntry.getEndPeriodDate()))
100 effectiveDate = new Date(DateUtils.addMinutes(calendarEntry.getEndPeriodDate(),-1).getTime());
101 // if submitting a delinquent calendar, use the calendar's end period date for the effective date.
102 // could adjust the end period date by subtracting a day so that the leave blocks appear on the month in question.
103
104 LeaveSummary ls = TkServiceLocator.getLeaveSummaryService().getLeaveSummary(leavePayout.getPrincipalId(), calendarEntry);
105 LeaveSummaryRow payoutRow = ls.getLeaveSummaryRowForAccrualCategory(accrualRule.getLmAccrualCategoryId());
106 LeavePayout defaultBT = TkServiceLocator.getLeavePayoutService().initializePayout(leavePayout.getPrincipalId(), accrualRuleId, payoutRow.getAccruedBalance(), effectiveDate);
107 if(leavePayout.getPayoutAmount().compareTo(defaultBT.getPayoutAmount()) != 0) {
108 //employee changed the payout amount, recalculate forfeiture.
109 //Note: payout form has been validated.
110 leavePayout = defaultBT.adjust(leavePayout.getPayoutAmount());
111 // showing the adjusted balance payout via the execution of another forward
112 // would cause a loop that would break only if the original payout amount was re-established in the form.
113 // javascript must be written if the forfeited amount is to be updated on the form object.
114 // an alternative to javascript would be to render a "re-calculate" button attached to a dedicated action forward method.
115 // must re-set leaveCalendarDocumentId, as leavePayout is now just an adjustment of the default initialized BT with no leave calendar doc id.
116 leavePayout.setLeaveCalendarDocumentId(documentId);
117 }
118
119 TkServiceLocator.getLeavePayoutService().submitToWorkflow(leavePayout);
120
121 if(ObjectUtils.isNotNull(documentId)) {
122 if(StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) ||
123 StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
124
125 ActionForward forward = new ActionForward(mapping.findForward(strutsActionForward));
126 forward.setPath(forward.getPath()+"?documentId="+documentId+"&action=R&methodToCall="+methodToCall);
127 return forward;
128 }
129 else
130 return mapping.findForward("closeLeavePayoutDoc");
131 }
132 else
133 return mapping.findForward("closeLeavePayoutDoc");
134 }
135 else //show user errors.
136 return mapping.findForward("basic");
137 }
138
139 public ActionForward cancel(ActionMapping mapping, ActionForm form,
140 HttpServletRequest request, HttpServletResponse response)
141 throws Exception {
142
143 LeavePayoutForm lpf = (LeavePayoutForm) form;
144 LeavePayout leavePayout = lpf.getLeavePayout();
145 String accrualCategoryRuleId = leavePayout.getAccrualCategoryRule();
146 AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualCategoryRuleId);
147 String actionFrequency = accrualRule.getMaxBalanceActionFrequency();
148
149 if(StringUtils.equals(actionFrequency,LMConstants.MAX_BAL_ACTION_FREQ.ON_DEMAND))
150 return mapping.findForward("closeLeavePayoutDoc");
151 else
152 if(StringUtils.equals(actionFrequency, LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) ||
153 StringUtils.equals(actionFrequency, LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
154
155 String documentId = leavePayout.getLeaveCalendarDocumentId();
156 TimesheetDocumentHeader tsdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(documentId);
157 LeaveCalendarDocumentHeader lcdh = TkServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(documentId);
158 String strutsActionForward = "";
159 if(ObjectUtils.isNull(tsdh) && ObjectUtils.isNull(lcdh)) {
160 strutsActionForward = "/";
161 }
162 else if(ObjectUtils.isNotNull(tsdh)) {
163 //Throws runtime exception, separate action forwards for timesheet/leave calendar transfers.
164 strutsActionForward = mapping.findForward("timesheetCancel").getPath() + "?documentId=" + leavePayout.getLeaveCalendarDocumentId();
165 }
166 else {
167 strutsActionForward = mapping.findForward("leaveCalendarCancel").getPath() + "?documentId=" + leavePayout.getLeaveCalendarDocumentId();
168 }
169
170 ActionRedirect redirect = new ActionRedirect();
171 redirect.setPath(strutsActionForward);
172 return redirect;
173
174 }
175 else
176 throw new RuntimeException("Action should only be reachable through triggers with frequency ON_DEMAND or LEAVE_APPROVE");
177 }
178
179 //Entry point for LeavePayout.do for accrual category rule triggered payouts with action frequency On Demand.
180 //May be better suited in the LeaveCalendarAction class.
181 public ActionForward leavePayoutOnDemand(ActionMapping mapping, ActionForm form,
182 HttpServletRequest request, HttpServletResponse response)
183 throws Exception {
184 GlobalVariables.getMessageMap().putWarning("document.payoutAmount","leavePayout.payoutAmount.adjust");
185
186 LeavePayoutForm lpf = (LeavePayoutForm) form;
187 //the leave calendar document that triggered this balance payout.
188 String documentId = request.getParameter("documentId");
189 String accrualRuleId = request.getParameter("accrualRuleId");
190 String timesheet = request.getParameter("timesheet");
191
192 boolean isTimesheet = false;
193 if(StringUtils.equals(timesheet, "true")) {
194 lpf.isTimesheet(true);
195 isTimesheet = true;
196 }
197 if(ObjectUtils.isNotNull(accrualRuleId)) {
198 AccrualCategoryRule aRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualRuleId);
199 if(ObjectUtils.isNotNull(aRule)) {
200 //should somewhat safegaurd against url fabrication.
201 if(!StringUtils.equals(aRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.ON_DEMAND))
202 throw new RuntimeException("attempted to execute on-demand balance payout for accrual category with action frequency " + aRule.getMaxBalanceActionFrequency());
203 else {
204 TimesheetDocument tsd = null;
205 LeaveCalendarDocument lcd = null;
206 String principalId = null;
207 CalendarEntries calendarEntry = null;
208
209 if(isTimesheet) {
210 tsd = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId);
211 principalId = tsd.getPrincipalId();
212 calendarEntry = tsd.getCalendarEntry();
213 }
214 else {
215 lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(documentId);
216 principalId = lcd.getPrincipalId();
217 calendarEntry = lcd.getCalendarEntry();
218 }
219 LeaveSummary ls = TkServiceLocator.getLeaveSummaryService().getLeaveSummary(principalId, calendarEntry);
220
221 Date effectiveDate = TKUtils.getCurrentDate();
222 if(TKUtils.getCurrentDate().after(calendarEntry.getEndPeriodDate()))
223 effectiveDate = new Date(DateUtils.addMinutes(calendarEntry.getEndPeriodDate(),-1).getTime());
224
225 LeaveSummaryRow payoutRow = ls.getLeaveSummaryRowForAccrualCategory(aRule.getLmAccrualCategoryId());
226 LeavePayout leavePayout = TkServiceLocator.getLeavePayoutService().initializePayout(principalId, accrualRuleId, payoutRow.getAccruedBalance(), effectiveDate);
227 leavePayout.setLeaveCalendarDocumentId(documentId);
228 if(ObjectUtils.isNotNull(leavePayout)) {
229 if(StringUtils.equals(aRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
230 // this particular combination of action / action frequency does not particularly make sense
231 // unless for some reason users still need to be prompted to submit the loss.
232 // For now, we treat as though it is a valid use-case.
233 //TkServiceLocator.getLeavePayoutService().submitToWorkflow(leavePayout);
234 // May need to update to save the business object to KPME's tables for record keeping.
235 leavePayout = TkServiceLocator.getLeavePayoutService().payout(leavePayout);
236 // May need to update to save the business object to KPME's tables for record keeping.
237 LeaveBlock forfeitedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(leavePayout.getForfeitedLeaveBlockId());
238 forfeitedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED);
239 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(forfeitedLeaveBlock, principalId);
240 return mapping.findForward("closeLeavePayoutDoc");
241 }
242 else {
243 ActionForward forward = mapping.findForward("basic");
244 lpf.setLeaveCalendarDocumentId(documentId);
245 lpf.setLeavePayout(leavePayout);
246 lpf.setPayoutAmount(leavePayout.getPayoutAmount());
247 return forward;
248 }
249 }
250 else
251 throw new RuntimeException("could not initialize a balance payout");
252
253 }
254 }
255 else
256 throw new RuntimeException("No rule for this accrual category could be found");
257 }
258 else
259 throw new RuntimeException("No accrual category rule id has been sent in the request.");
260 }
261
262 //Entry point for LeavePayout.do for accrual category rule triggered payouts with action frequency Leave Approve.
263 //TODO: Rename method to differentiate from ActionForward with same name in LeaveCalendarSubmit.
264 public ActionForward approveLeaveCalendar(ActionMapping mapping, ActionForm form,
265 HttpServletRequest request, HttpServletResponse response)
266 throws Exception {
267
268 GlobalVariables.getMessageMap().putWarning("document.newMaintainableObj.payoutAmount","leavePayout.payoutAmount.adjust");
269 LeavePayoutForm lpf = (LeavePayoutForm) form;
270
271 int categoryCounter = 0;
272 List<String> payoutableAccrualCategoryRules = new ArrayList<String>();
273 String accrualRuleId = request.getParameter("accrualCategory0");
274 while(ObjectUtils.isNotNull(accrualRuleId)) {
275 //TODO: Get rid of this loop
276 categoryCounter++;
277 payoutableAccrualCategoryRules.add(accrualRuleId);
278 accrualRuleId = request.getParameter("accrualCategory"+categoryCounter);
279 }
280
281 //Bad.... User must be prompted for each payout that needs to be made.
282 //For now, assuming not more than one accrual category is eligible for payout.
283 if(!payoutableAccrualCategoryRules.isEmpty()) {
284 //This is the leave calendar document that triggered this balance payout.
285 String leaveCalendarDocumentId = request.getParameter("documentId");
286 ActionForward forward = new ActionForward(mapping.findForward("basic"));
287 LeaveCalendarDocument lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(leaveCalendarDocumentId);
288 LeaveSummary leaveSummary = TkServiceLocator.getLeaveSummaryService().getLeaveSummary(lcd.getPrincipalId(), lcd.getCalendarEntry());
289
290 Date effectiveDate = TKUtils.getCurrentDate();
291 if(TKUtils.getCurrentDate().after(lcd.getCalendarEntry().getEndPeriodDate()))
292 effectiveDate = new Date(DateUtils.addMinutes(lcd.getCalendarEntry().getEndPeriodDate(),-1).getTime());
293
294 accrualRuleId = payoutableAccrualCategoryRules.get(0);
295 AccrualCategoryRule aRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualRuleId);
296 LeaveSummaryRow payoutRow = leaveSummary.getLeaveSummaryRowForAccrualCategory(aRule.getLmAccrualCategoryId());
297 LeavePayout leavePayout = TkServiceLocator.getLeavePayoutService().initializePayout(lcd.getPrincipalId(), accrualRuleId, payoutRow.getAccruedBalance(), effectiveDate);
298 leavePayout.setLeaveCalendarDocumentId(leaveCalendarDocumentId);
299
300 if(ObjectUtils.isNotNull(leavePayout)) {
301 AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualRuleId);
302 if(StringUtils.equals(accrualRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
303
304 //TkServiceLocator.getLeavePayoutService().submitToWorkflow(leavePayout);
305 leavePayout = TkServiceLocator.getLeavePayoutService().payout(leavePayout);
306 // May need to update to save the business object to KPME's tables for record keeping.
307 LeaveBlock forfeitedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(leavePayout.getForfeitedLeaveBlockId());
308 forfeitedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED);
309 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(forfeitedLeaveBlock, lcd.getPrincipalId());
310
311 ActionRedirect redirect = new ActionRedirect();
312 if(ObjectUtils.isNotNull(leaveCalendarDocumentId)) {
313 if(StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) ||
314 StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
315 ActionForward loseForward = new ActionForward(mapping.findForward("leaveCalendarTransferSuccess"));
316 loseForward.setPath(loseForward.getPath()+"?documentId="+leaveCalendarDocumentId+"&action=R&methodToCall=approveLeaveCalendar");
317 return loseForward;
318 }
319 //on demand handled in separate action forward.
320 }
321
322 } else {
323 lpf.setLeaveCalendarDocumentId(leaveCalendarDocumentId);
324 lpf.setLeavePayout(leavePayout);
325 lpf.setPayoutAmount(leavePayout.getPayoutAmount());
326 return forward;
327 }
328
329 }
330 throw new RuntimeException("could not initialize balance payout");
331
332 }
333 else
334 throw new RuntimeException("unable to fetch the accrual category that triggerred this payout");
335 }
336
337 public ActionForward approveTimesheet(ActionMapping mapping, ActionForm form,
338 HttpServletRequest request, HttpServletResponse response)
339 throws Exception {
340
341 GlobalVariables.getMessageMap().putWarning("document.newMaintainableObj.payoutAmount","leavePayout.payoutAmount.adjust");
342 LeavePayoutForm lpf = (LeavePayoutForm) form;
343
344 int categoryCounter = 0;
345 List<String> payoutableAccrualCategoryRules = new ArrayList<String>();
346 String accrualRuleId = request.getParameter("accrualCategory0");
347 while(ObjectUtils.isNotNull(accrualRuleId)) {
348 //TODO: Get rid of this loop
349 categoryCounter++;
350 payoutableAccrualCategoryRules.add(accrualRuleId);
351 accrualRuleId = request.getParameter("accrualCategory"+categoryCounter);
352 }
353
354 //Bad.... User must be prompted for each payout that needs to be made.
355 //For now, assuming not more than one accrual category is eligible for payout.
356 if(!payoutableAccrualCategoryRules.isEmpty()) {
357 //This is the leave calendar document that triggered this balance payout.
358 String timesheetDocumentId = request.getParameter("documentId");
359 ActionForward forward = new ActionForward(mapping.findForward("basic"));
360 TimesheetDocument tsd = TkServiceLocator.getTimesheetService().getTimesheetDocument(timesheetDocumentId);
361 LeaveSummary leaveSummary = TkServiceLocator.getLeaveSummaryService().getLeaveSummary(tsd.getPrincipalId(), tsd.getCalendarEntry());
362
363 Date effectiveDate = TKUtils.getCurrentDate();
364 if(TKUtils.getCurrentDate().after(tsd.getCalendarEntry().getEndPeriodDate()))
365 effectiveDate = new Date(DateUtils.addMinutes(tsd.getCalendarEntry().getEndPeriodDate(),-1).getTime());
366
367 accrualRuleId = payoutableAccrualCategoryRules.get(0);
368 AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualRuleId);
369 LeaveSummaryRow payoutRow = leaveSummary.getLeaveSummaryRowForAccrualCategory(accrualRule.getLmAccrualCategoryId());
370 LeavePayout leavePayout = TkServiceLocator.getLeavePayoutService().initializePayout(tsd.getPrincipalId(), accrualRuleId, payoutRow.getAccruedBalance(), effectiveDate);
371 leavePayout.setLeaveCalendarDocumentId(timesheetDocumentId);
372
373 if(ObjectUtils.isNotNull(leavePayout)) {
374 if(StringUtils.equals(accrualRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
375 // TODO: Redirect user to prompt stating excess leave will be forfeited and ask for confirmation.
376 // Do not submit the object to workflow for this max balance action.
377 leavePayout = TkServiceLocator.getLeavePayoutService().payout(leavePayout);
378 // May need to update to save the business object to KPME's tables for record keeping.
379 LeaveBlock forfeitedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(leavePayout.getForfeitedLeaveBlockId());
380 forfeitedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED);
381 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(forfeitedLeaveBlock, tsd.getPrincipalId());
382 ActionRedirect redirect = new ActionRedirect();
383 if(ObjectUtils.isNotNull(timesheetDocumentId)) {
384 if(StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) ||
385 StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
386 ActionForward loseForward = new ActionForward(mapping.findForward("timesheetTransferSuccess"));
387 loseForward.setPath(loseForward.getPath()+"?documentId="+timesheetDocumentId+"&action=R&methodToCall=approveTimesheet");
388 return loseForward;
389 }
390 //on demand handled in separate action forward.
391 }
392
393 } else {
394 lpf.setLeaveCalendarDocumentId(timesheetDocumentId);
395 lpf.setLeavePayout(leavePayout);
396 lpf.setPayoutAmount(leavePayout.getPayoutAmount());
397 return forward;
398 }
399
400 }
401 throw new RuntimeException("could not initialize balance payout");
402
403 }
404 else
405 throw new RuntimeException("unable to fetch the accrual category that triggerred this payout");
406 }
407
408 public ActionForward closeLeavePayoutDoc(ActionMapping mapping, ActionForm form,
409 HttpServletRequest request, HttpServletResponse response)
410 throws Exception {
411 return mapping.findForward("closeLeavePayoutDoc");
412 }
413 }