1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
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  		
59  		LeavePayoutForm lpf = (LeavePayoutForm) form;
60  		LeavePayout leavePayout = lpf.getLeavePayout();
61  	
62  		boolean valid = LeavePayoutValidationUtils.validatePayout(leavePayout);
63  		
64  		
65  		
66  		
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  				
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 				
106 				
107 				leavePayout = defaultBT.adjust(leavePayout.getPayoutAmount());
108 				
109 				
110 				
111 				
112 				
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 
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 					
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 	
177 	
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 		
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 				
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 							
224 							
225 							
226 							
227 							
228 							leavePayout = TkServiceLocator.getLeavePayoutService().payout(leavePayout);
229 							
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 	
256 	
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 			
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 					
299 					
300 					
301 					leavePayout = TkServiceLocator.getLeavePayoutService().payout(leavePayout);
302 					
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 						
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 			
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 						
379 						
380 						leavePayout = TkServiceLocator.getLeavePayoutService().payout(leavePayout);
381 						KRADServiceLocator.getBusinessObjectService().save(leavePayout);
382 	
383 						
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 							
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 }