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.balancetransfer.web;
017
018 import java.math.BigDecimal;
019 import java.sql.Date;
020 import java.util.*;
021 import java.util.Map.Entry;
022
023 import javax.servlet.http.HttpServletRequest;
024 import javax.servlet.http.HttpServletResponse;
025
026 import org.apache.commons.collections.CollectionUtils;
027 import org.apache.commons.lang.time.DateUtils;
028 import org.apache.commons.lang3.StringUtils;
029 import org.apache.struts.action.ActionForm;
030 import org.apache.struts.action.ActionForward;
031 import org.apache.struts.action.ActionMapping;
032 import org.apache.struts.action.ActionRedirect;
033 import org.kuali.hr.lm.LMConstants;
034 import org.kuali.hr.lm.accrual.AccrualCategory;
035 import org.kuali.hr.lm.accrual.AccrualCategoryRule;
036 import org.kuali.hr.lm.balancetransfer.BalanceTransfer;
037 import org.kuali.hr.lm.balancetransfer.validation.BalanceTransferValidationUtils;
038 import org.kuali.hr.lm.leaveSummary.LeaveSummary;
039 import org.kuali.hr.lm.leaveSummary.LeaveSummaryRow;
040 import org.kuali.hr.lm.leaveblock.LeaveBlock;
041 import org.kuali.hr.lm.leavecalendar.LeaveCalendarDocument;
042 import org.kuali.hr.lm.timeoff.SystemScheduledTimeOff;
043 import org.kuali.hr.lm.workflow.LeaveCalendarDocumentHeader;
044 import org.kuali.hr.time.base.web.TkAction;
045 import org.kuali.hr.time.calendar.Calendar;
046 import org.kuali.hr.time.calendar.CalendarEntries;
047 import org.kuali.hr.time.earncode.EarnCode;
048 import org.kuali.hr.time.service.base.TkServiceLocator;
049 import org.kuali.hr.time.timesheet.TimesheetDocument;
050 import org.kuali.hr.time.util.TKUtils;
051 import org.kuali.hr.time.workflow.TimesheetDocumentHeader;
052 import org.kuali.rice.krad.service.KRADServiceLocator;
053 import org.kuali.rice.krad.util.GlobalVariables;
054 import org.kuali.rice.krad.util.ObjectUtils;
055
056 public class BalanceTransferAction extends TkAction {
057
058 public ActionForward balanceTransferOnLeaveApproval(ActionMapping mapping, ActionForm form,
059 HttpServletRequest request, HttpServletResponse response) throws Exception {
060
061 //if action was submit, execute the transfer
062 BalanceTransferForm btf = (BalanceTransferForm) form;
063 BalanceTransfer balanceTransfer = btf.getBalanceTransfer();
064
065 boolean valid = BalanceTransferValidationUtils.validateTransfer(balanceTransfer);
066
067 //if transfer amount has changed, and the resulting change produces forfeiture
068 //or changes the forfeiture amount, prompt for confirmation with the amount of
069 //forfeiture that the entered amount would produce.
070
071 if(valid) {
072
073 String accrualRuleId = balanceTransfer.getAccrualCategoryRule();
074
075 String documentId = balanceTransfer.getLeaveCalendarDocumentId();
076 TimesheetDocumentHeader tsdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(documentId);
077 LeaveCalendarDocumentHeader lcdh = TkServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(documentId);
078 CalendarEntries calendarEntry = null;
079 String strutsActionForward = "";
080 String methodToCall = "approveLeaveCalendar";
081 if(ObjectUtils.isNull(tsdh) && ObjectUtils.isNull(lcdh)) {
082 throw new RuntimeException("No document found");
083 }
084 else if(ObjectUtils.isNotNull(tsdh)) {
085 //Throws runtime exception, separate action forwards for timesheet/leave calendar transfers.
086 TimesheetDocument tsd = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId);
087 calendarEntry = tsd != null ? tsd.getCalendarEntry() : null;
088 strutsActionForward = "timesheetTransferSuccess";
089 methodToCall = "approveTimesheet";
090 }
091 else {
092 LeaveCalendarDocument lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(documentId);
093 calendarEntry = lcd != null ? lcd.getCalendarEntry() : null;
094 strutsActionForward = "leaveCalendarTransferSuccess";
095 methodToCall = "approveLeaveCalendar";
096 }
097
098 if(ObjectUtils.isNull(calendarEntry)) {
099 throw new RuntimeException("Could not retreive calendar entry for document " + documentId);
100 }
101
102 AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualRuleId);
103
104 AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getLmAccrualCategoryId());
105 BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(balanceTransfer.getPrincipalId(), accrualCategory, balanceTransfer.getEffectiveDate());
106
107 BalanceTransfer defaultBT = TkServiceLocator.getBalanceTransferService().initializeTransfer(balanceTransfer.getPrincipalId(), accrualRuleId, accruedBalance, balanceTransfer.getEffectiveDate());
108 if(balanceTransfer.getTransferAmount().compareTo(defaultBT.getTransferAmount()) != 0) {
109 //employee changed the transfer amount, recalculate forfeiture.
110 //Note: transfer form has been validated.
111 balanceTransfer = defaultBT.adjust(balanceTransfer.getTransferAmount());
112 // showing the adjusted balance transfer via the execution of another forward
113 // would cause a loop that would break only if the original transfer amount was re-established in the form.
114 // javascript must be written if the forfeited amount is to be updated on the form object.
115 // an alternative to javascript would be to render a "re-calculate" button attached to a dedicated action forward method.
116 // must re-set leaveCalendarDocumentId, as balanceTransfer is now just an adjustment of the default initialized BT with no leave calendar doc id.
117 balanceTransfer.setLeaveCalendarDocumentId(documentId);
118 }
119
120 TkServiceLocator.getBalanceTransferService().submitToWorkflow(balanceTransfer);
121
122 if(ObjectUtils.isNotNull(documentId)) {
123 if(StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) ||
124 StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
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("closeBalanceTransferDoc");
131 }
132 else
133 return mapping.findForward("closeBalanceTransferDoc");
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 BalanceTransferForm btf = (BalanceTransferForm) form;
144 BalanceTransfer bt = btf.getBalanceTransfer();
145
146 if(btf.isSstoTransfer()) {
147 return mapping.findForward("closeBalanceTransferDoc");
148 }
149
150 String accrualCategoryRuleId = bt.getAccrualCategoryRule();
151 AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualCategoryRuleId);
152 String actionFrequency = accrualRule.getMaxBalanceActionFrequency();
153
154 if(StringUtils.equals(actionFrequency,LMConstants.MAX_BAL_ACTION_FREQ.ON_DEMAND))
155 return mapping.findForward("closeBalanceTransferDoc");
156 else
157 if(StringUtils.equals(actionFrequency, LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) ||
158 StringUtils.equals(actionFrequency, LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
159 String documentId = bt.getLeaveCalendarDocumentId();
160 TimesheetDocumentHeader tsdh = TkServiceLocator.getTimesheetDocumentHeaderService().getDocumentHeader(documentId);
161 LeaveCalendarDocumentHeader lcdh = TkServiceLocator.getLeaveCalendarDocumentHeaderService().getDocumentHeader(documentId);
162 String strutsActionForward = "";
163 if(ObjectUtils.isNull(tsdh) && ObjectUtils.isNull(lcdh)) {
164 strutsActionForward = "/";
165 }
166 else if(ObjectUtils.isNotNull(tsdh)) {
167 //Throws runtime exception, separate action forwards for timesheet/leave calendar transfers.
168 strutsActionForward = mapping.findForward("timesheetCancel").getPath() + "?documentId=" + bt.getLeaveCalendarDocumentId();
169 }
170 else {
171 strutsActionForward = mapping.findForward("leaveCalendarCancel").getPath() + "?documentId=" + bt.getLeaveCalendarDocumentId();
172 }
173
174 ActionRedirect redirect = new ActionRedirect();
175 redirect.setPath(strutsActionForward);
176 return redirect;
177 }
178 else
179 throw new RuntimeException("Action should only be reachable through triggers with frequency ON_DEMAND or LEAVE_APPROVE");
180 }
181
182 //Entry point for BalanceTransfer.do for accrual category rule triggered transfers with action frequency On Demand.
183 //May be better suited in the LeaveCalendarAction class.
184 public ActionForward balanceTransferOnDemand(ActionMapping mapping, ActionForm form,
185 HttpServletRequest request, HttpServletResponse response)
186 throws Exception {
187 GlobalVariables.getMessageMap().putWarning("document.transferAmount","balanceTransfer.transferAmount.adjust");
188
189 BalanceTransferForm btf = (BalanceTransferForm) form;
190 //the leave calendar document that triggered this balance transfer.
191 String documentId = request.getParameter("documentId");
192 String accrualRuleId = request.getParameter("accrualRuleId");
193 String timesheet = request.getParameter("timesheet");
194 boolean isTimesheet = false;
195 if(StringUtils.equals(timesheet, "true")) {
196 btf.isTimesheet(true);
197 isTimesheet = true;
198 }
199 if(ObjectUtils.isNotNull(accrualRuleId)) {
200 //LeaveBlock lb = TkServiceLocator.getLeaveBlockService().getLeaveBlock(leaveBlockId);
201 AccrualCategoryRule aRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualRuleId);
202 if(ObjectUtils.isNotNull(aRule)) {
203 //should somewhat safegaurd against url fabrication.
204 if(!StringUtils.equals(aRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.ON_DEMAND))
205 throw new RuntimeException("attempted to execute on-demand balance transfer for accrual category with action frequency " + aRule.getMaxBalanceActionFrequency());
206 else {
207 String principalId = null;
208
209 if(isTimesheet) {
210 TimesheetDocument tsd = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId);
211 principalId = tsd == null ? null : tsd.getPrincipalId();
212 }
213 else {
214 LeaveCalendarDocument lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(documentId);
215 principalId = lcd == null ? null : lcd.getPrincipalId();
216 }
217
218 AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualRuleId);
219 AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getLmAccrualCategoryId());
220 BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(principalId, accrualCategory, TKUtils.getCurrentDate());
221
222 BalanceTransfer balanceTransfer = TkServiceLocator.getBalanceTransferService().initializeTransfer(principalId, aRule.getLmAccrualCategoryRuleId(), accruedBalance, TKUtils.getCurrentDate());
223 balanceTransfer.setLeaveCalendarDocumentId(documentId);
224 if(ObjectUtils.isNotNull(balanceTransfer)) {
225 if(StringUtils.equals(aRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
226 // this particular combination of action / action frequency does not particularly make sense
227 // unless for some reason users still need to be prompted to submit the loss.
228 // For now, we treat as though it is a valid use-case.
229 //TkServiceLocator.getBalanceTransferService().submitToWorkflow(balanceTransfer);
230 // May need to update to save the business object to KPME's tables for record keeping.
231 balanceTransfer = TkServiceLocator.getBalanceTransferService().transfer(balanceTransfer);
232 // May need to update to save the business object to KPME's tables for record keeping.
233 LeaveBlock forfeitedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(balanceTransfer.getForfeitedLeaveBlockId());
234 forfeitedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED);
235 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(forfeitedLeaveBlock, principalId);
236 return mapping.findForward("closeBalanceTransferDoc");
237 }
238 else {
239 ActionForward forward = mapping.findForward("basic");
240 btf.setLeaveCalendarDocumentId(documentId);
241 btf.setBalanceTransfer(balanceTransfer);
242 btf.setTransferAmount(balanceTransfer.getTransferAmount());
243 return forward;
244 }
245 }
246 else
247 throw new RuntimeException("could not initialize a balance transfer");
248
249 }
250 }
251 else
252 throw new RuntimeException("No rule for this accrual category could be found");
253 }
254 else
255 throw new RuntimeException("No accrual category rule id has been sent in the request.");
256 }
257
258 //Entry point for BalanceTransfer.do for accrual category rule triggered transfers with action frequency Leave Approve.
259 //TODO: Rename method to differentiate from ActionForward with same name in LeaveCalendarSubmit.
260 public ActionForward approveLeaveCalendar(ActionMapping mapping, ActionForm form,
261 HttpServletRequest request, HttpServletResponse response)
262 throws Exception {
263
264 GlobalVariables.getMessageMap().putWarning("document.newMaintainableObj.transferAmount","balanceTransfer.transferAmount.adjust");
265 BalanceTransferForm btf = (BalanceTransferForm) form;
266
267 List<LeaveBlock> eligibleTransfers = (List<LeaveBlock>) request.getSession().getAttribute("eligibilities");
268 if(!eligibleTransfers.isEmpty()) {
269
270 Collections.sort(eligibleTransfers, new Comparator() {
271
272 @Override
273 public int compare(Object o1, Object o2) {
274 LeaveBlock l1 = (LeaveBlock) o1;
275 LeaveBlock l2 = (LeaveBlock) o2;
276 return l1.getLeaveDate().compareTo(l2.getLeaveDate());
277 }
278
279 });
280
281 //This is the leave calendar document that triggered this balance transfer.
282
283 String leaveCalendarDocumentId = request.getParameter("documentId");
284 ActionForward forward = new ActionForward(mapping.findForward("basic"));
285 LeaveCalendarDocument lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(leaveCalendarDocumentId);
286 String principalId = lcd == null ? null : lcd.getPrincipalId();
287 LeaveBlock leaveBlock = eligibleTransfers.get(0);
288 Date effectiveDate = leaveBlock.getLeaveDate();
289 String accrualCategoryRuleId = leaveBlock.getAccrualCategoryRuleId();
290 if(!StringUtils.isBlank(accrualCategoryRuleId)) {
291
292 AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualCategoryRuleId);
293 AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getLmAccrualCategoryId());
294 BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(principalId, accrualCategory, leaveBlock.getLeaveDate());
295
296 BalanceTransfer balanceTransfer = TkServiceLocator.getBalanceTransferService().initializeTransfer(principalId, accrualCategoryRuleId, accruedBalance, effectiveDate);
297
298 balanceTransfer.setLeaveCalendarDocumentId(leaveCalendarDocumentId);
299
300 if(ObjectUtils.isNotNull(balanceTransfer)) {
301 if(StringUtils.equals(accrualRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
302
303 //TkServiceLocator.getBalanceTransferService().submitToWorkflow(balanceTransfer);
304 balanceTransfer = TkServiceLocator.getBalanceTransferService().transfer(balanceTransfer);
305 // May need to update to save the business object to KPME's tables for record keeping.
306 LeaveBlock forfeitedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(balanceTransfer.getForfeitedLeaveBlockId());
307 KRADServiceLocator.getBusinessObjectService().save(balanceTransfer);
308 forfeitedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED);
309 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(forfeitedLeaveBlock, principalId);
310
311 if(ObjectUtils.isNotNull(leaveCalendarDocumentId)) {
312 if(StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) ||
313 StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
314 ActionForward loseForward = new ActionForward(mapping.findForward("leaveCalendarTransferSuccess"));
315 loseForward.setPath(loseForward.getPath()+"?documentId="+leaveCalendarDocumentId+"&action=R&methodToCall=approveLeaveCalendar");
316 return loseForward;
317 }
318 //on demand handled in separate action forward.
319 }
320
321 } else {
322 btf.setLeaveCalendarDocumentId(leaveCalendarDocumentId);
323 btf.setBalanceTransfer(balanceTransfer);
324 btf.setTransferAmount(balanceTransfer.getTransferAmount());
325 return forward;
326 }
327 }
328 throw new RuntimeException("could not initialize balance transfer");
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
337 public ActionForward approveTimesheet(ActionMapping mapping, ActionForm form,
338 HttpServletRequest request, HttpServletResponse response)
339 throws Exception {
340
341 GlobalVariables.getMessageMap().putWarning("document.newMaintainableObj.transferAmount","balanceTransfer.transferAmount.adjust");
342 BalanceTransferForm btf = (BalanceTransferForm) form;
343
344 List<LeaveBlock> eligibleTransfers = (List<LeaveBlock>) request.getSession().getAttribute("eligibilities");
345 if(!eligibleTransfers.isEmpty()) {
346
347 Collections.sort(eligibleTransfers, new Comparator() {
348
349 @Override
350 public int compare(Object o1, Object o2) {
351 LeaveBlock l1 = (LeaveBlock) o1;
352 LeaveBlock l2 = (LeaveBlock) o2;
353 return l1.getLeaveDate().compareTo(l2.getLeaveDate());
354 }
355
356 });
357
358 //This is the leave calendar document that triggered this balance transfer.
359
360 String timesheetDocumentId = request.getParameter("documentId");
361 ActionForward forward = new ActionForward(mapping.findForward("basic"));
362 TimesheetDocument tsd = TkServiceLocator.getTimesheetService().getTimesheetDocument(timesheetDocumentId);
363 String principalId = tsd == null ? null : tsd.getPrincipalId();
364
365 LeaveBlock leaveBlock = eligibleTransfers.get(0);
366 Date effectiveDate = leaveBlock.getLeaveDate();
367 String accrualCategoryRuleId = leaveBlock.getAccrualCategoryRuleId();
368 if(!StringUtils.isBlank(accrualCategoryRuleId)) {
369 AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualCategoryRuleId);
370 AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getLmAccrualCategoryId());
371 BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(principalId, accrualCategory, leaveBlock.getLeaveDate());
372
373 BalanceTransfer balanceTransfer = TkServiceLocator.getBalanceTransferService().initializeTransfer(principalId, accrualCategoryRuleId, accruedBalance, effectiveDate);
374 balanceTransfer.setLeaveCalendarDocumentId(timesheetDocumentId);
375
376 if(ObjectUtils.isNotNull(balanceTransfer)) {
377
378 if(StringUtils.equals(accrualRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
379 // TODO: Redirect user to prompt stating excess leave will be forfeited and ask for confirmation.
380 // Do not submit the object to workflow for this max balance action.
381 balanceTransfer = TkServiceLocator.getBalanceTransferService().transfer(balanceTransfer);
382 KRADServiceLocator.getBusinessObjectService().save(balanceTransfer);
383
384 // May need to update to save the business object to KPME's tables for record keeping.
385 LeaveBlock forfeitedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(balanceTransfer.getForfeitedLeaveBlockId());
386 forfeitedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED);
387 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(forfeitedLeaveBlock, principalId);
388
389 if(ObjectUtils.isNotNull(timesheetDocumentId)) {
390 if(StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) ||
391 StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
392 ActionForward loseForward = new ActionForward(mapping.findForward("timesheetTransferSuccess"));
393 loseForward.setPath(loseForward.getPath()+"?documentId="+timesheetDocumentId+"&action=R&methodToCall=approveTimesheet");
394 return loseForward;
395 }
396 //on demand handled in separate action forward.
397 }
398
399 } else {
400 btf.setLeaveCalendarDocumentId(timesheetDocumentId);
401 btf.setBalanceTransfer(balanceTransfer);
402 btf.setTransferAmount(balanceTransfer.getTransferAmount());
403 return forward;
404 }
405
406 }
407 throw new RuntimeException("could not initialize balance transfer");
408
409 }
410 else
411 throw new RuntimeException("unable to fetch the accrual category that triggerred this transfer");
412 }
413 else
414 throw new RuntimeException("no eligible transfers exist");
415 }
416
417 public ActionForward closeBalanceTransferDoc(ActionMapping mapping, ActionForm form,
418 HttpServletRequest request, HttpServletResponse response)
419 throws Exception {
420 return mapping.findForward("closeBalanceTransferDoc");
421 }
422
423 /* Delete system scheduled time off usage leave block from Leave or Time Calendar
424 */
425 public ActionForward deleteSSTOLeaveBlock(ActionMapping mapping, ActionForm form,
426 HttpServletRequest request, HttpServletResponse response)
427 throws Exception {
428 BalanceTransferForm btf = (BalanceTransferForm) form;
429 buildBalanceTransferForLeaveBlock(btf, request.getParameter("leaveBlockId"));
430
431 return new ActionForward(mapping.findForward("basic"));
432 }
433
434 /* Build balance transfer based on the to-be-deleted leave block
435 */
436 private void buildBalanceTransferForLeaveBlock(BalanceTransferForm btf, String lbId) {
437 LeaveBlock lb = TkServiceLocator.getLeaveBlockService().getLeaveBlock(lbId);
438 // this leave block is a ssto usage block, need to use it fo find the accrualed leave block which has a positive amount
439 if(lb == null || StringUtils.isEmpty(lb.getScheduleTimeOffId())) {
440 throw new RuntimeException("could not find the System Scheduled Time Off leave block that needs to be transferred!");
441 }
442 SystemScheduledTimeOff ssto = TkServiceLocator.getSysSchTimeOffService().getSystemScheduledTimeOff(lb.getScheduleTimeOffId());
443 BigDecimal amountTransferred = ssto.getTransferConversionFactor() == null ? lb.getLeaveAmount() : lb.getLeaveAmount().multiply(ssto.getTransferConversionFactor());
444 EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(ssto.getTransfertoEarnCode(), lb.getLeaveDate());
445
446 BalanceTransfer bt = new BalanceTransfer();
447 bt.setTransferAmount(lb.getLeaveAmount().abs()); // the usage leave block's leave amount is negative
448 bt.setFromAccrualCategory(lb.getAccrualCategory());
449 bt.setAmountTransferred(amountTransferred.abs());
450 bt.setToAccrualCategory(ec.getAccrualCategory());
451 bt.setSstoId(lb.getScheduleTimeOffId());
452 bt.setEffectiveDate(lb.getLeaveDate());
453 bt.setPrincipalId(lb.getPrincipalId());
454
455 btf.setBalanceTransfer(bt);
456 btf.setTransferAmount(bt.getTransferAmount());
457 GlobalVariables.getMessageMap().putWarning("document.newMaintainableObj.transferAmount","balanceTransfer.transferSSTO",
458 bt.getTransferAmount().toString(), bt.getAmountTransferred().toString());
459 }
460 /*
461 * Submit a balance transfer document when deleting a ssto usage leave block from current Leave/time calendar
462 * delete both accrued and usage ssto leave blocks, a pending transferred leave block is created by the BT doc
463 */
464 public ActionForward balanceTransferOnSSTO(ActionMapping mapping, ActionForm form,
465 HttpServletRequest request, HttpServletResponse response) throws Exception {
466 BalanceTransferForm btf = (BalanceTransferForm) form;
467 BalanceTransfer bt = btf.getBalanceTransfer();
468
469 if(StringUtils.isEmpty(bt.getSstoId())) {
470 throw new RuntimeException("System Scheduled Time Off not found for this balance transfer!");
471 }
472 List<LeaveBlock> lbList = TkServiceLocator.getLeaveBlockService().getSSTOLeaveBlocks(bt.getPrincipalId(), bt.getSstoId(), bt.getEffectiveDate());
473 if(CollectionUtils.isEmpty(lbList) || (CollectionUtils.isNotEmpty(lbList) && lbList.size() != 2)) {
474 throw new RuntimeException("There should be 2 system scheduled time off leave blocks!");
475 }
476 TkServiceLocator.getBalanceTransferService().submitToWorkflow(bt);
477 // delete both SSTO accrualed and usage leave blocks
478 for(LeaveBlock lb : lbList) {
479 TkServiceLocator.getLeaveBlockService().deleteLeaveBlock(lb.getLmLeaveBlockId(), lb.getPrincipalId());
480 }
481 return mapping.findForward("closeBalanceTransferDoc");
482 }
483
484 }