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.getCalendarEntry(); 088 strutsActionForward = "timesheetTransferSuccess"; 089 methodToCall = "approveTimesheet"; 090 } 091 else { 092 LeaveCalendarDocument lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(documentId); 093 calendarEntry = lcd.getCalendarEntry(); 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 TimesheetDocument tsd = null; 208 LeaveCalendarDocument lcd = null; 209 String principalId = null; 210 211 if(isTimesheet) { 212 tsd = TkServiceLocator.getTimesheetService().getTimesheetDocument(documentId); 213 principalId = tsd.getPrincipalId(); 214 } 215 else { 216 lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(documentId); 217 principalId = lcd.getPrincipalId(); 218 } 219 220 AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualRuleId); 221 AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getLmAccrualCategoryId()); 222 BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(principalId, accrualCategory, TKUtils.getCurrentDate()); 223 224 BalanceTransfer balanceTransfer = TkServiceLocator.getBalanceTransferService().initializeTransfer(principalId, aRule.getLmAccrualCategoryRuleId(), accruedBalance, TKUtils.getCurrentDate()); 225 balanceTransfer.setLeaveCalendarDocumentId(documentId); 226 if(ObjectUtils.isNotNull(balanceTransfer)) { 227 if(StringUtils.equals(aRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) { 228 // this particular combination of action / action frequency does not particularly make sense 229 // unless for some reason users still need to be prompted to submit the loss. 230 // For now, we treat as though it is a valid use-case. 231 //TkServiceLocator.getBalanceTransferService().submitToWorkflow(balanceTransfer); 232 // May need to update to save the business object to KPME's tables for record keeping. 233 balanceTransfer = TkServiceLocator.getBalanceTransferService().transfer(balanceTransfer); 234 // May need to update to save the business object to KPME's tables for record keeping. 235 LeaveBlock forfeitedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(balanceTransfer.getForfeitedLeaveBlockId()); 236 forfeitedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED); 237 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(forfeitedLeaveBlock, principalId); 238 return mapping.findForward("closeBalanceTransferDoc"); 239 } 240 else { 241 ActionForward forward = mapping.findForward("basic"); 242 btf.setLeaveCalendarDocumentId(documentId); 243 btf.setBalanceTransfer(balanceTransfer); 244 btf.setTransferAmount(balanceTransfer.getTransferAmount()); 245 return forward; 246 } 247 } 248 else 249 throw new RuntimeException("could not initialize a balance transfer"); 250 251 } 252 } 253 else 254 throw new RuntimeException("No rule for this accrual category could be found"); 255 } 256 else 257 throw new RuntimeException("No accrual category rule id has been sent in the request."); 258 } 259 260 //Entry point for BalanceTransfer.do for accrual category rule triggered transfers with action frequency Leave Approve. 261 //TODO: Rename method to differentiate from ActionForward with same name in LeaveCalendarSubmit. 262 public ActionForward approveLeaveCalendar(ActionMapping mapping, ActionForm form, 263 HttpServletRequest request, HttpServletResponse response) 264 throws Exception { 265 266 GlobalVariables.getMessageMap().putWarning("document.newMaintainableObj.transferAmount","balanceTransfer.transferAmount.adjust"); 267 BalanceTransferForm btf = (BalanceTransferForm) form; 268 269 List<LeaveBlock> eligibleTransfers = (List<LeaveBlock>) request.getSession().getAttribute("eligibilities"); 270 if(!eligibleTransfers.isEmpty()) { 271 272 Collections.sort(eligibleTransfers, new Comparator() { 273 274 @Override 275 public int compare(Object o1, Object o2) { 276 LeaveBlock l1 = (LeaveBlock) o1; 277 LeaveBlock l2 = (LeaveBlock) o2; 278 return l1.getLeaveDate().compareTo(l2.getLeaveDate()); 279 } 280 281 }); 282 283 //This is the leave calendar document that triggered this balance transfer. 284 285 String leaveCalendarDocumentId = request.getParameter("documentId"); 286 ActionForward forward = new ActionForward(mapping.findForward("basic")); 287 LeaveCalendarDocument lcd = TkServiceLocator.getLeaveCalendarService().getLeaveCalendarDocument(leaveCalendarDocumentId); 288 289 LeaveBlock leaveBlock = eligibleTransfers.get(0); 290 Date effectiveDate = leaveBlock.getLeaveDate(); 291 String accrualCategoryRuleId = leaveBlock.getAccrualCategoryRuleId(); 292 if(!StringUtils.isBlank(accrualCategoryRuleId)) { 293 294 AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualCategoryRuleId); 295 AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getLmAccrualCategoryId()); 296 BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(lcd.getPrincipalId(), accrualCategory, leaveBlock.getLeaveDate()); 297 298 BalanceTransfer balanceTransfer = TkServiceLocator.getBalanceTransferService().initializeTransfer(lcd.getPrincipalId(), accrualCategoryRuleId, accruedBalance, effectiveDate); 299 300 balanceTransfer.setLeaveCalendarDocumentId(leaveCalendarDocumentId); 301 302 if(ObjectUtils.isNotNull(balanceTransfer)) { 303 if(StringUtils.equals(accrualRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) { 304 305 //TkServiceLocator.getBalanceTransferService().submitToWorkflow(balanceTransfer); 306 balanceTransfer = TkServiceLocator.getBalanceTransferService().transfer(balanceTransfer); 307 // May need to update to save the business object to KPME's tables for record keeping. 308 LeaveBlock forfeitedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(balanceTransfer.getForfeitedLeaveBlockId()); 309 KRADServiceLocator.getBusinessObjectService().save(balanceTransfer); 310 forfeitedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED); 311 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(forfeitedLeaveBlock, lcd.getPrincipalId()); 312 313 if(ObjectUtils.isNotNull(leaveCalendarDocumentId)) { 314 if(StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) || 315 StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) { 316 ActionForward loseForward = new ActionForward(mapping.findForward("leaveCalendarTransferSuccess")); 317 loseForward.setPath(loseForward.getPath()+"?documentId="+leaveCalendarDocumentId+"&action=R&methodToCall=approveLeaveCalendar"); 318 return loseForward; 319 } 320 //on demand handled in separate action forward. 321 } 322 323 } else { 324 btf.setLeaveCalendarDocumentId(leaveCalendarDocumentId); 325 btf.setBalanceTransfer(balanceTransfer); 326 btf.setTransferAmount(balanceTransfer.getTransferAmount()); 327 return forward; 328 } 329 } 330 throw new RuntimeException("could not initialize balance transfer"); 331 } else { 332 throw new RuntimeException("unable to fetch the accrual category that triggerred this transfer"); 333 } 334 } else { 335 throw new RuntimeException("No infractions given"); 336 } 337 } 338 339 public ActionForward approveTimesheet(ActionMapping mapping, ActionForm form, 340 HttpServletRequest request, HttpServletResponse response) 341 throws Exception { 342 343 GlobalVariables.getMessageMap().putWarning("document.newMaintainableObj.transferAmount","balanceTransfer.transferAmount.adjust"); 344 BalanceTransferForm btf = (BalanceTransferForm) form; 345 346 List<LeaveBlock> eligibleTransfers = (List<LeaveBlock>) request.getSession().getAttribute("eligibilities"); 347 if(!eligibleTransfers.isEmpty()) { 348 349 Collections.sort(eligibleTransfers, new Comparator() { 350 351 @Override 352 public int compare(Object o1, Object o2) { 353 LeaveBlock l1 = (LeaveBlock) o1; 354 LeaveBlock l2 = (LeaveBlock) o2; 355 return l1.getLeaveDate().compareTo(l2.getLeaveDate()); 356 } 357 358 }); 359 360 //This is the leave calendar document that triggered this balance transfer. 361 362 String timesheetDocumentId = request.getParameter("documentId"); 363 ActionForward forward = new ActionForward(mapping.findForward("basic")); 364 TimesheetDocument tsd = TkServiceLocator.getTimesheetService().getTimesheetDocument(timesheetDocumentId); 365 366 LeaveBlock leaveBlock = eligibleTransfers.get(0); 367 Date effectiveDate = leaveBlock.getLeaveDate(); 368 String accrualCategoryRuleId = leaveBlock.getAccrualCategoryRuleId(); 369 if(!StringUtils.isBlank(accrualCategoryRuleId)) { 370 AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualCategoryRuleId); 371 AccrualCategory accrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getLmAccrualCategoryId()); 372 BigDecimal accruedBalance = TkServiceLocator.getAccrualCategoryService().getAccruedBalanceForPrincipal(tsd.getPrincipalId(), accrualCategory, leaveBlock.getLeaveDate()); 373 374 BalanceTransfer balanceTransfer = TkServiceLocator.getBalanceTransferService().initializeTransfer(tsd.getPrincipalId(), accrualCategoryRuleId, accruedBalance, effectiveDate); 375 balanceTransfer.setLeaveCalendarDocumentId(timesheetDocumentId); 376 377 if(ObjectUtils.isNotNull(balanceTransfer)) { 378 379 if(StringUtils.equals(accrualRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) { 380 // TODO: Redirect user to prompt stating excess leave will be forfeited and ask for confirmation. 381 // Do not submit the object to workflow for this max balance action. 382 balanceTransfer = TkServiceLocator.getBalanceTransferService().transfer(balanceTransfer); 383 KRADServiceLocator.getBusinessObjectService().save(balanceTransfer); 384 385 // May need to update to save the business object to KPME's tables for record keeping. 386 LeaveBlock forfeitedLeaveBlock = TkServiceLocator.getLeaveBlockService().getLeaveBlock(balanceTransfer.getForfeitedLeaveBlockId()); 387 forfeitedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED); 388 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(forfeitedLeaveBlock, tsd.getPrincipalId()); 389 390 if(ObjectUtils.isNotNull(timesheetDocumentId)) { 391 if(StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.LEAVE_APPROVE) || 392 StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(), LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) { 393 ActionForward loseForward = new ActionForward(mapping.findForward("timesheetTransferSuccess")); 394 loseForward.setPath(loseForward.getPath()+"?documentId="+timesheetDocumentId+"&action=R&methodToCall=approveTimesheet"); 395 return loseForward; 396 } 397 //on demand handled in separate action forward. 398 } 399 400 } else { 401 btf.setLeaveCalendarDocumentId(timesheetDocumentId); 402 btf.setBalanceTransfer(balanceTransfer); 403 btf.setTransferAmount(balanceTransfer.getTransferAmount()); 404 return forward; 405 } 406 407 } 408 throw new RuntimeException("could not initialize balance transfer"); 409 410 } 411 else 412 throw new RuntimeException("unable to fetch the accrual category that triggerred this transfer"); 413 } 414 else 415 throw new RuntimeException("no eligible transfers exist"); 416 } 417 418 public ActionForward closeBalanceTransferDoc(ActionMapping mapping, ActionForm form, 419 HttpServletRequest request, HttpServletResponse response) 420 throws Exception { 421 return mapping.findForward("closeBalanceTransferDoc"); 422 } 423 424 /* Delete system scheduled time off usage leave block from Leave or Time Calendar 425 */ 426 public ActionForward deleteSSTOLeaveBlock(ActionMapping mapping, ActionForm form, 427 HttpServletRequest request, HttpServletResponse response) 428 throws Exception { 429 BalanceTransferForm btf = (BalanceTransferForm) form; 430 buildBalanceTransferForLeaveBlock(btf, request.getParameter("leaveBlockId")); 431 432 return new ActionForward(mapping.findForward("basic")); 433 } 434 435 /* Build balance transfer based on the to-be-deleted leave block 436 */ 437 private void buildBalanceTransferForLeaveBlock(BalanceTransferForm btf, String lbId) { 438 LeaveBlock lb = TkServiceLocator.getLeaveBlockService().getLeaveBlock(lbId); 439 // this leave block is a ssto usage block, need to use it fo find the accrualed leave block which has a positive amount 440 if(lb == null || StringUtils.isEmpty(lb.getScheduleTimeOffId())) { 441 throw new RuntimeException("could not find the System Scheduled Time Off leave block that needs to be transferred!"); 442 } 443 SystemScheduledTimeOff ssto = TkServiceLocator.getSysSchTimeOffService().getSystemScheduledTimeOff(lb.getScheduleTimeOffId()); 444 BigDecimal amountTransferred = ssto.getTransferConversionFactor() == null ? lb.getLeaveAmount() : lb.getLeaveAmount().multiply(ssto.getTransferConversionFactor()); 445 EarnCode ec = TkServiceLocator.getEarnCodeService().getEarnCode(ssto.getTransfertoEarnCode(), lb.getLeaveDate()); 446 447 BalanceTransfer bt = new BalanceTransfer(); 448 bt.setTransferAmount(lb.getLeaveAmount().abs()); // the usage leave block's leave amount is negative 449 bt.setFromAccrualCategory(lb.getAccrualCategory()); 450 bt.setAmountTransferred(amountTransferred.abs()); 451 bt.setToAccrualCategory(ec.getAccrualCategory()); 452 bt.setSstoId(lb.getScheduleTimeOffId()); 453 bt.setEffectiveDate(lb.getLeaveDate()); 454 bt.setPrincipalId(lb.getPrincipalId()); 455 456 btf.setBalanceTransfer(bt); 457 btf.setTransferAmount(bt.getTransferAmount()); 458 GlobalVariables.getMessageMap().putWarning("document.newMaintainableObj.transferAmount","balanceTransfer.transferSSTO", 459 bt.getTransferAmount().toString(), bt.getAmountTransferred().toString()); 460 } 461 /* 462 * Submit a balance transfer document when deleting a ssto usage leave block from current Leave/time calendar 463 * delete both accrued and usage ssto leave blocks, a pending transferred leave block is created by the BT doc 464 */ 465 public ActionForward balanceTransferOnSSTO(ActionMapping mapping, ActionForm form, 466 HttpServletRequest request, HttpServletResponse response) throws Exception { 467 BalanceTransferForm btf = (BalanceTransferForm) form; 468 BalanceTransfer bt = btf.getBalanceTransfer(); 469 470 if(StringUtils.isEmpty(bt.getSstoId())) { 471 throw new RuntimeException("System Scheduled Time Off not found for this balance transfer!"); 472 } 473 List<LeaveBlock> lbList = TkServiceLocator.getLeaveBlockService().getSSTOLeaveBlocks(bt.getPrincipalId(), bt.getSstoId(), bt.getEffectiveDate()); 474 if(CollectionUtils.isEmpty(lbList) || (CollectionUtils.isNotEmpty(lbList) && lbList.size() != 2)) { 475 throw new RuntimeException("There should be 2 system scheduled time off leave blocks!"); 476 } 477 TkServiceLocator.getBalanceTransferService().submitToWorkflow(bt); 478 // delete both SSTO accrualed and usage leave blocks 479 for(LeaveBlock lb : lbList) { 480 TkServiceLocator.getLeaveBlockService().deleteLeaveBlock(lb.getLmLeaveBlockId(), lb.getPrincipalId()); 481 } 482 return mapping.findForward("closeBalanceTransferDoc"); 483 } 484 485 }