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 }