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.leavepayout.web;
17  
18  import java.math.BigDecimal;
19  import java.sql.Date;
20  import java.util.*;
21  
22  import org.apache.commons.lang.time.DateUtils;
23  import org.apache.commons.lang3.StringUtils;
24  import org.apache.struts.action.ActionForm;
25  import org.apache.struts.action.ActionForward;
26  import org.apache.struts.action.ActionMapping;
27  import org.apache.struts.action.ActionRedirect;
28  import org.joda.time.Interval;
29  import org.kuali.hr.lm.LMConstants;
30  import org.kuali.hr.lm.accrual.AccrualCategory;
31  import org.kuali.hr.lm.accrual.AccrualCategoryRule;
32  import org.kuali.hr.lm.leavepayout.LeavePayout;
33  import org.kuali.hr.lm.leavepayout.validation.LeavePayoutValidationUtils;
34  import org.kuali.hr.lm.leavepayout.web.LeavePayoutForm;
35  import org.kuali.hr.lm.leaveSummary.LeaveSummary;
36  import org.kuali.hr.lm.leaveSummary.LeaveSummaryRow;
37  import org.kuali.hr.lm.leaveblock.LeaveBlock;
38  import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument;
39  import org.kuali.hr.lm.workflow.LeaveCalendarDocumentHeader;
40  import org.kuali.hr.time.base.web.TkAction;
41  import org.kuali.hr.time.calendar.CalendarEntries;
42  import org.kuali.hr.time.service.base.TkServiceLocator;
43  import org.kuali.hr.time.timesheet.TimesheetDocument;
44  import org.kuali.hr.time.util.TKUtils;
45  import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
46  import org.kuali.rice.krad.service.KRADServiceLocator;
47  import org.kuali.rice.krad.util.GlobalVariables;
48  import org.kuali.rice.krad.util.ObjectUtils;
49  
50  import javax.servlet.http.HttpServletRequest;
51  import javax.servlet.http.HttpServletResponse;
52  
53  public class LeavePayoutAction extends TkAction {
54  
55  	public ActionForward leavePayoutOnLeaveApproval(ActionMapping mapping, ActionForm form,
56  			HttpServletRequest request, HttpServletResponse response) throws Exception {
57  
58  		//if action was submit, execute the payout
59  		LeavePayoutForm lpf = (LeavePayoutForm) form;
60  		LeavePayout leavePayout = lpf.getLeavePayout();
61  	
62  		boolean valid = LeavePayoutValidationUtils.validatePayout(leavePayout);
63  		
64  		//if payout amount has changed, and the resulting change produces forfeiture
65  		//or changes the forfeiture amount, prompt for confirmation with the amount of
66  		//forfeiture that the entered amount would produce.
67  
68  		if(valid) {
69  			
70  			String accrualRuleId = leavePayout.getAccrualCategoryRule();
71  			
72  			String documentId = leavePayout.getLeaveCalendarDocumentId();
73  			TimesheetDocumentHeader tsdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(documentId);
74  			LeaveCalendarDocumentHeader lcdh = TkServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(documentId);
75  			CalendarEntries calendarEntry = null;
76  			String strutsActionForward = "";
77  			String methodToCall = "approveLeaveCalendar";
78  			if(ObjectUtils.isNull(tsdh) && ObjectUtils.isNull(lcdh)) {
79  				throw new RuntimeException("No document found");
80  			}
81  			else if(ObjectUtils.isNotNull(tsdh)) {
82  				//Throws runtime exception, separate action forwards for timesheet/leave calendar payouts.
83  				TimesheetDocument tsd = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId);
84  				calendarEntry = tsd == null ? null : tsd.getCalendarEntry();
85  				strutsActionForward = "timesheetPayoutSuccess";
86  				methodToCall = "approveTimesheet";
87  			}
88  			else {
89  				LeaveCalendarDocument lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(documentId);
90  				calendarEntry = lcd == null ? null : lcd.getCalendarEntry();
91  				strutsActionForward = "leaveCalendarPayoutSuccess";
92  				methodToCall = "approveLeaveCalendar";
93  			}
94  			
95  			if(ObjectUtils.isNull(calendarEntry)) {
96  				throw new RuntimeException("Could not retreive calendar entry for document " + documentId);
97  			}
98  			
99  			AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualRuleId);
100 			AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getLmAccrualCategoryId());
101 			BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(leavePayout.getPrincipalId(), accrualCategory, leavePayout.getEffectiveDate());
102 
103 			LeavePayout defaultBT = TkServiceLocator.getLeavePayoutService().initializePayout(leavePayout.getPrincipalId(), accrualRuleId, accruedBalance, leavePayout.getEffectiveDate());
104 			if(leavePayout.getPayoutAmount().compareTo(defaultBT.getPayoutAmount()) != 0) {
105 				//employee changed the payout amount, recalculate forfeiture.
106 				//Note: payout form has been validated.
107 				leavePayout = defaultBT.adjust(leavePayout.getPayoutAmount());
108 				// showing the adjusted balance payout via the execution of another forward
109 				// would cause a loop that would break only if the original payout amount was re-established in the form.
110 				// javascript must be written if the forfeited amount is to be updated on the form object.
111 				// an alternative to javascript would be to render a "re-calculate" button attached to a dedicated action forward method.
112 				// must re-set leaveCalendarDocumentId, as leavePayout is now just an adjustment of the default initialized BT with no leave calendar doc id.
113 				leavePayout.setLeaveCalendarDocumentId(documentId);
114 			}
115 
116 			TkServiceLocator.getLeavePayoutService().submitToWorkflow(leavePayout);
117 			
118 			if(ObjectUtils.isNotNull(documentId)) {
119 				if(StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) ||
120 						StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
121 					
122 					ActionForward forward = new ActionForward(mapping.findForward(strutsActionForward));
123 					forward.setPath(forward.getPath()+"?documentId="+documentId+"&action=R&methodToCall="+methodToCall);
124 					return forward;
125 				}
126 				else
127 					return mapping.findForward("closeLeavePayoutDoc");
128 			}
129 			else
130 				return mapping.findForward("closeLeavePayoutDoc");
131 		}
132 		else //show user errors.
133 			return mapping.findForward("basic");
134 	}
135 	
136 	public ActionForward cancel(ActionMapping mapping, ActionForm form,
137 			HttpServletRequest request, HttpServletResponse response)
138 			throws Exception {
139 		
140 		LeavePayoutForm lpf = (LeavePayoutForm) form;
141 		LeavePayout leavePayout = lpf.getLeavePayout();
142 		String accrualCategoryRuleId = leavePayout.getAccrualCategoryRule();
143 		AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualCategoryRuleId);
144 		String actionFrequency = accrualRule.getMaxBalanceActionFrequency();
145 		
146 		if(StringUtils.equals(actionFrequency,LMConstants.MAX_BAL_ACTION_FREQ.ON_DEMAND))
147 			return mapping.findForward("closeLeavePayoutDoc");
148 		else 
149 			if(StringUtils.equals(actionFrequency, LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) ||
150 					StringUtils.equals(actionFrequency, LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
151 				
152 				String documentId = leavePayout.getLeaveCalendarDocumentId();
153 				TimesheetDocumentHeader tsdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(documentId);
154 				LeaveCalendarDocumentHeader lcdh = TkServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(documentId);
155 				String strutsActionForward = "";
156 				if(ObjectUtils.isNull(tsdh) && ObjectUtils.isNull(lcdh)) {
157 					strutsActionForward = "/";
158 				}
159 				else if(ObjectUtils.isNotNull(tsdh)) {
160 					//Throws runtime exception, separate action forwards for timesheet/leave calendar transfers.
161 					strutsActionForward = mapping.findForward("timesheetCancel").getPath() + "?documentId=" + leavePayout.getLeaveCalendarDocumentId();
162 				}
163 				else {
164 					strutsActionForward = mapping.findForward("leaveCalendarCancel").getPath() + "?documentId=" + leavePayout.getLeaveCalendarDocumentId();
165 				}
166 
167 				ActionRedirect redirect = new ActionRedirect();
168 				redirect.setPath(strutsActionForward);
169 				return redirect;
170 
171 			}
172 			else
173 				throw new RuntimeException("Action should only be reachable through triggers with frequency ON_DEMAND or LEAVE_APPROVE");
174 	}
175 	
176 	//Entry point for LeavePayout.do for accrual category rule triggered payouts with action frequency On Demand.
177 	//May be better suited in the LeaveCalendarAction class.
178 	public ActionForward leavePayoutOnDemand(ActionMapping mapping, ActionForm form,
179 			HttpServletRequest request, HttpServletResponse response)
180 			throws Exception {
181 		GlobalVariables.getMessageMap().putWarning("document.payoutAmount","leavePayout.payoutAmount.adjust");
182 
183 		LeavePayoutForm lpf = (LeavePayoutForm) form;
184 		//the leave calendar document that triggered this balance payout.
185 		String documentId = request.getParameter("documentId");
186 		String leaveBlockId = request.getParameter("accrualRuleId");
187 		String timesheet = request.getParameter("timesheet");
188 
189 		boolean isTimesheet = false;
190 		if(StringUtils.equals(timesheet, "true")) {
191 			lpf.isTimesheet(true);
192 			isTimesheet = true;
193 		}
194 		if(ObjectUtils.isNotNull(leaveBlockId)) {
195 			AccrualCategoryRule aRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(leaveBlockId);
196 			if(ObjectUtils.isNotNull(aRule)) {
197 				//should somewhat safegaurd against url fabrication.
198 				if(!StringUtils.equals(aRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.ON_DEMAND))
199 					throw new RuntimeException("attempted to execute on-demand balance payout for accrual category with action frequency " + aRule.getMaxBalanceActionFrequency());
200 				else {
201 					TimesheetDocument tsd = null;
202 					LeaveCalendarDocument lcd = null;
203 					String principalId = null;
204 					CalendarEntries calendarEntry = null;
205 
206 					if(isTimesheet) {
207 						tsd = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId);
208 						principalId = tsd == null ? null : tsd.getPrincipalId();
209 					}
210 					else {
211 						lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(documentId);
212 						principalId = lcd == null ? null : lcd.getPrincipalId();
213 					}
214 					
215 					AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(leaveBlockId);
216 					AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getLmAccrualCategoryId());
217 					BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(principalId, accrualCategory, TKUtils.getCurrentDate());
218 
219 					LeavePayout leavePayout = TkServiceLocator.getLeavePayoutService().initializePayout(principalId, leaveBlockId, accruedBalance, TKUtils.getCurrentDate());
220 					leavePayout.setLeaveCalendarDocumentId(documentId);
221 					if(ObjectUtils.isNotNull(leavePayout)) {
222 						if(StringUtils.equals(aRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) {	
223 							// this particular combination of action / action frequency does not particularly make sense
224 							// unless for some reason users still need to be prompted to submit the loss.
225 							// For now, we treat as though it is a valid use-case.
226 							//TkServiceLocator.getLeavePayoutService().submitToWorkflow(leavePayout);
227 							// May need to update to save the business object to KPME's tables for record keeping.
228 							leavePayout = TkServiceLocator.getLeavePayoutService().payout(leavePayout);
229 							// May need to update to save the business object to KPME's tables for record keeping.
230 							LeaveBlock forfeitedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(leavePayout.getForfeitedLeaveBlockId());
231 							forfeitedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED);
232 							TkServiceLocator.getLeaveBlockService().updateLeaveBlock(forfeitedLeaveBlock, principalId);
233 							return mapping.findForward("closeLeavePayoutDoc");
234 						}
235 						else {
236 							ActionForward forward = mapping.findForward("basic");
237 							lpf.setLeaveCalendarDocumentId(documentId);
238 							lpf.setLeavePayout(leavePayout);
239 							lpf.setPayoutAmount(leavePayout.getPayoutAmount());
240 							return forward;
241 						}
242 					}
243 					else
244 						throw new RuntimeException("could not initialize a balance payout");
245 
246 				}
247 			}
248 			else
249 				throw new RuntimeException("No rule for this accrual category could be found");
250 		}
251 		else
252 			throw new RuntimeException("No accrual category rule id has been sent in the request.");
253 	}
254 
255 	//Entry point for LeavePayout.do for accrual category rule triggered transfers with action frequency Leave Approve.
256 	//TODO: Rename method to differentiate from ActionForward with same name in LeaveCalendarSubmit.
257 	public ActionForward approveLeaveCalendar(ActionMapping mapping, ActionForm form,
258 			HttpServletRequest request, HttpServletResponse response)
259 					throws Exception {
260 		
261 		GlobalVariables.getMessageMap().putWarning("document.newMaintainableObj.transferAmount","leavePayout.transferAmount.adjust");
262 		LeavePayoutForm btf = (LeavePayoutForm) form;
263 
264 		List<LeaveBlock> eligiblePayouts = (List<LeaveBlock>) request.getSession().getAttribute("eligibilities");
265 		if(!eligiblePayouts.isEmpty()) {
266 			
267 			Collections.sort(eligiblePayouts, new Comparator() {
268 
269                 @Override
270                 public int compare(Object o1, Object o2) {
271                     LeaveBlock l1 = (LeaveBlock) o1;
272                     LeaveBlock l2 = (LeaveBlock) o2;
273                     return l1.getLeaveDate().compareTo(l2.getLeaveDate());
274                 }
275 
276             });
277 			
278 			//This is the leave calendar document that triggered this balance transfer.
279 
280 			String leaveCalendarDocumentId = request.getParameter("documentId");
281 			ActionForward forward = new ActionForward(mapping.findForward("basic"));
282 			LeaveCalendarDocument lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(leaveCalendarDocumentId);
283 			String principalId = lcd == null ? null : lcd.getPrincipalId();
284 			LeaveBlock leaveBlock = eligiblePayouts.get(0);
285 			Date effectiveDate = leaveBlock.getLeaveDate();
286 			String accrualCategoryRuleId = leaveBlock.getAccrualCategoryRuleId();
287 			if(!StringUtils.isBlank(accrualCategoryRuleId)) {
288 				AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualCategoryRuleId);
289 				AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getLmAccrualCategoryId());
290 				BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(principalId, accrualCategory, effectiveDate);
291 			
292 				LeavePayout leavePayout = TkServiceLocator.getLeavePayoutService().initializePayout(principalId, accrualCategoryRuleId, accruedBalance, effectiveDate);
293 				leavePayout.setLeaveCalendarDocumentId(leaveCalendarDocumentId);
294 	
295 				if(ObjectUtils.isNotNull(leavePayout)) {
296 	
297 				if(StringUtils.equals(accrualRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
298 					//payouts should never contain losses.
299 					//losses are treated as a special case of transfer
300 					//TkServiceLocator.getLeavePayoutService().submitToWorkflow(leavePayout);
301 					leavePayout = TkServiceLocator.getLeavePayoutService().payout(leavePayout);
302 					// May need to update to save the business object to KPME's tables for record keeping.
303 					LeaveBlock forfeitedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(leavePayout.getForfeitedLeaveBlockId());
304 					KRADServiceLocator.getBusinessObjectService().save(leavePayout);
305 					forfeitedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED);
306 					TkServiceLocator.getLeaveBlockService().updateLeaveBlock(forfeitedLeaveBlock, principalId);
307 					
308 					if(ObjectUtils.isNotNull(leaveCalendarDocumentId)) {
309 						if(StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) ||
310 								StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
311 							ActionForward loseForward = new ActionForward(mapping.findForward("leaveCalendarPayoutSuccess"));
312 							loseForward.setPath(loseForward.getPath()+"?documentId="+leaveCalendarDocumentId+"&action=R&methodToCall=approveLeaveCalendar");
313 							return loseForward;
314 						}
315 						//on demand handled in separate action forward.
316 					}
317 
318 				} else {
319 					btf.setLeaveCalendarDocumentId(leaveCalendarDocumentId);
320 					btf.setLeavePayout(leavePayout);
321 					btf.setPayoutAmount(leavePayout.getPayoutAmount());
322 					return forward;
323 				}
324 
325 			}
326 			throw new RuntimeException("could not initialize balance transfer");
327 
328 		}
329 		else
330 			throw new RuntimeException("unable to fetch the accrual category that triggerred this transfer");
331 		}
332 		else
333 			throw new RuntimeException("No infractions given");
334 	}
335 	
336 	public ActionForward approveTimesheet(ActionMapping mapping, ActionForm form,
337 			HttpServletRequest request, HttpServletResponse response)
338 					throws Exception {
339 		
340 		GlobalVariables.getMessageMap().putWarning("document.newMaintainableObj.transferAmount","leavePayout.transferAmount.adjust");
341 		LeavePayoutForm btf = (LeavePayoutForm) form;
342 
343 		List<LeaveBlock> eligiblePayouts = (List<LeaveBlock>) request.getSession().getAttribute("eligibilities");
344 		if(!eligiblePayouts.isEmpty()) {
345 			
346 			Collections.sort(eligiblePayouts, new Comparator() {
347 				
348 				@Override
349 				public int compare(Object o1, Object o2) {
350 					LeaveBlock l1 = (LeaveBlock) o1;
351 					LeaveBlock l2 = (LeaveBlock) o2;
352 					return l1.getLeaveDate().compareTo(l2.getLeaveDate());
353 				}
354 				
355 			});
356 			
357 			//This is the leave calendar document that triggered this balance transfer.
358 
359 			String timesheetDocumentId = request.getParameter("documentId");
360 			ActionForward forward = new ActionForward(mapping.findForward("basic"));
361 			TimesheetDocument tsd = TkServiceLocator.getTimesheetService().getTimesheetDocument(timesheetDocumentId);
362 			String principalId = tsd == null ? null : tsd.getPrincipalId();
363 
364 			LeaveBlock leaveBlock = eligiblePayouts.get(0);
365 			Date effectiveDate = leaveBlock.getLeaveDate();
366 			String accrualCategoryRuleId = leaveBlock.getAccrualCategoryRuleId();
367 			if(!StringUtils.isBlank(accrualCategoryRuleId)) {
368 				AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualCategoryRuleId);
369 				AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getLmAccrualCategoryId());
370 				BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(principalId, accrualCategory, effectiveDate);
371 
372 				LeavePayout leavePayout = TkServiceLocator.getLeavePayoutService().initializePayout(principalId, accrualCategoryRuleId, accruedBalance, effectiveDate);
373 				leavePayout.setLeaveCalendarDocumentId(timesheetDocumentId);
374 	
375 				if(ObjectUtils.isNotNull(leavePayout)) {
376 	
377 					if(StringUtils.equals(accrualRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
378 						// TODO: Redirect user to prompt stating excess leave will be forfeited and ask for confirmation.
379 						// Do not submit the object to workflow for this max balance action.
380 						leavePayout = TkServiceLocator.getLeavePayoutService().payout(leavePayout);
381 						KRADServiceLocator.getBusinessObjectService().save(leavePayout);
382 	
383 						// May need to update to save the business object to KPME's tables for record keeping.
384 						LeaveBlock forfeitedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(leavePayout.getForfeitedLeaveBlockId());
385 						forfeitedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED);
386 						TkServiceLocator.getLeaveBlockService().updateLeaveBlock(forfeitedLeaveBlock, principalId);
387 
388 						if(ObjectUtils.isNotNull(timesheetDocumentId)) {
389 							if(StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) ||
390 									StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
391 								ActionForward loseForward = new ActionForward(mapping.findForward("timesheetPayoutSuccess"));
392 								loseForward.setPath(loseForward.getPath()+"?documentId="+timesheetDocumentId+"&action=R&methodToCall=approveTimesheet");
393 								return loseForward;
394 							}
395 							//on demand handled in separate action forward.
396 						}
397 	
398 					} else {
399 						btf.setLeaveCalendarDocumentId(timesheetDocumentId);
400 						btf.setLeavePayout(leavePayout);
401 						btf.setPayoutAmount(leavePayout.getPayoutAmount());
402 						return forward;
403 					}
404 	
405 				}
406 				throw new RuntimeException("could not initialize balance transfer");
407 
408 		}
409 		else
410 			throw new RuntimeException("unable to fetch the accrual category that triggerred this transfer");
411 		}
412 		else
413 			throw new RuntimeException("no eligible transfers exist");
414 	}
415 	
416 	public ActionForward closeLeavePayoutDoc(ActionMapping mapping, ActionForm form,
417 			HttpServletRequest request, HttpServletResponse response)
418 			throws Exception {
419 		return mapping.findForward("closeLeavePayoutDoc");
420 	}
421 }