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.service; 017 018 import java.math.BigDecimal; 019 import java.util.ArrayList; 020 import java.util.List; 021 import java.util.Map; 022 023 import org.apache.commons.collections.CollectionUtils; 024 import org.apache.commons.lang3.StringUtils; 025 import org.kuali.hr.lm.LMConstants; 026 import org.kuali.hr.lm.accrual.AccrualCategory; 027 import org.kuali.hr.lm.balancetransfer.BalanceTransfer; 028 import org.kuali.hr.lm.leaveblock.LeaveBlock; 029 import org.kuali.hr.time.HrBusinessObject; 030 import org.kuali.hr.time.service.base.TkServiceLocator; 031 import org.kuali.hr.time.util.HrBusinessObjectMaintainableImpl; 032 import org.kuali.hr.time.util.TKContext; 033 import org.kuali.hr.time.util.TKUtils; 034 import org.kuali.rice.kew.api.document.DocumentStatus; 035 import org.kuali.rice.kew.api.exception.WorkflowException; 036 import org.kuali.rice.kns.document.MaintenanceDocument; 037 import org.kuali.rice.krad.bo.DocumentHeader; 038 import org.kuali.rice.krad.service.DocumentService; 039 import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 040 import org.kuali.rice.krad.util.ObjectUtils; 041 042 @SuppressWarnings("deprecation") 043 public class BalanceTransferMaintainableImpl extends 044 HrBusinessObjectMaintainableImpl { 045 046 private static final long serialVersionUID = -789218061798169466L; 047 048 @Override 049 public void saveBusinessObject() { 050 // TODO Auto-generated method stub 051 super.saveBusinessObject(); 052 } 053 054 @Override 055 public HrBusinessObject getObjectById(String id) { 056 return TkServiceLocator.getBalanceTransferService().getBalanceTransferById(id); 057 } 058 059 060 @Override 061 public void doRouteStatusChange(DocumentHeader documentHeader) { 062 //ProcessDocReport pdr = new ProcessDocReport(true, ""); 063 String documentId = documentHeader.getDocumentNumber(); 064 BalanceTransfer balanceTransfer = (BalanceTransfer)this.getDataObject(); 065 DocumentService documentService = KRADServiceLocatorWeb.getDocumentService(); 066 067 DocumentStatus newDocumentStatus = documentHeader.getWorkflowDocument().getStatus(); 068 String routedByPrincipalId = documentHeader.getWorkflowDocument().getRoutedByPrincipalId(); 069 if (DocumentStatus.ENROUTE.equals(newDocumentStatus) 070 && CollectionUtils.isEmpty(balanceTransfer.getLeaveBlocks())) { 071 // this is a balance transfer on a system scheduled time off leave block 072 if(StringUtils.isNotEmpty(balanceTransfer.getSstoId())) { 073 try { 074 MaintenanceDocument md = (MaintenanceDocument)KRADServiceLocatorWeb.getDocumentService().getByDocumentHeaderId(documentId); 075 balanceTransfer = TkServiceLocator.getBalanceTransferService().transferSsto(balanceTransfer); 076 md.getNewMaintainableObject().setDataObject(balanceTransfer); 077 documentService.saveDocument(md); 078 } 079 catch (WorkflowException e) { 080 LOG.error("caught exception while handling doRouteStatusChange -> documentService.getByDocumentHeaderId(" + documentHeader.getDocumentNumber() + "). ", e); 081 throw new RuntimeException("caught exception while handling doRouteStatusChange -> documentService.getByDocumentHeaderId(" + documentHeader.getDocumentNumber() + "). ", e); 082 } 083 } else { 084 //when transfer document is routed, initiate the balance transfer - creating the leave blocks 085 try { 086 MaintenanceDocument md = (MaintenanceDocument)KRADServiceLocatorWeb.getDocumentService().getByDocumentHeaderId(documentId); 087 088 balanceTransfer = TkServiceLocator.getBalanceTransferService().transfer(balanceTransfer); 089 md.getNewMaintainableObject().setDataObject(balanceTransfer); 090 documentService.saveDocument(md); 091 } 092 catch (WorkflowException e) { 093 LOG.error("caught exception while handling doRouteStatusChange -> documentService.getByDocumentHeaderId(" + documentHeader.getDocumentNumber() + "). ", e); 094 throw new RuntimeException("caught exception while handling doRouteStatusChange -> documentService.getByDocumentHeaderId(" + documentHeader.getDocumentNumber() + "). ", e); 095 } 096 } 097 } else if (DocumentStatus.DISAPPROVED.equals(newDocumentStatus)) { 098 /** 099 * TODO: Remove disapproval action 100 */ 101 // this is a balance transfer on a system scheduled time off leave block 102 103 if(StringUtils.isNotEmpty(balanceTransfer.getSstoId())) { 104 // put two accrual service generated leave blocks back, one accrued, one usage 105 List<LeaveBlock> lbList = buildSstoLeaveBlockList(balanceTransfer); 106 TkServiceLocator.getLeaveBlockService().saveLeaveBlocks(lbList); 107 } 108 //When transfer document is disapproved, set all leave block's request statuses to disapproved. 109 for(LeaveBlock lb : balanceTransfer.getLeaveBlocks()) { 110 if(ObjectUtils.isNotNull(lb)) { 111 lb.setRequestStatus(LMConstants.REQUEST_STATUS.DISAPPROVED); 112 TkServiceLocator.getLeaveBlockService().deleteLeaveBlock(lb.getLmLeaveBlockId(), routedByPrincipalId); 113 } 114 } 115 //update status of document and associated leave blocks. 116 } else if (DocumentStatus.FINAL.equals(newDocumentStatus)) { 117 //When transfer document moves to final, set all leave block's request statuses to approved. 118 for(LeaveBlock lb : balanceTransfer.getLeaveBlocks()) { 119 if(ObjectUtils.isNotNull(lb)) { 120 //TODO: What happens when an approver edits the fields in the transfer doc before approving? 121 lb.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED); 122 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(lb, routedByPrincipalId); 123 } 124 } 125 List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForDate(balanceTransfer.getPrincipalId(), balanceTransfer.getEffectiveDate()); 126 LeaveBlock carryOverBlock = null; 127 for(LeaveBlock lb : leaveBlocks) { 128 if(StringUtils.equals(lb.getAccrualCategory(),balanceTransfer.getFromAccrualCategory()) 129 && StringUtils.equals(lb.getDescription(),"Max carry over adjustment")) { 130 carryOverBlock = lb; 131 } 132 } 133 if(carryOverBlock != null) { 134 BigDecimal adjustment = new BigDecimal(0); 135 if(balanceTransfer.getTransferAmount() != null) 136 adjustment = adjustment.add(balanceTransfer.getTransferAmount().abs()); 137 if(balanceTransfer.getForfeitedAmount() != null) 138 adjustment = adjustment.add(balanceTransfer.getForfeitedAmount().abs()); 139 BigDecimal adjustedLeaveAmount = carryOverBlock.getLeaveAmount().abs().subtract(adjustment); 140 carryOverBlock.setLeaveAmount(adjustedLeaveAmount.negate()); 141 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(carryOverBlock, routedByPrincipalId); 142 } 143 } else if (DocumentStatus.CANCELED.equals(newDocumentStatus)) { 144 //When transfer document is canceled, set all leave block's request statuses to deferred 145 146 for(LeaveBlock lb : balanceTransfer.getLeaveBlocks()) { 147 if(ObjectUtils.isNotNull(lb)) { 148 lb.setRequestStatus(LMConstants.REQUEST_STATUS.DEFERRED); 149 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(lb, routedByPrincipalId); 150 } 151 } 152 } 153 } 154 155 private List<LeaveBlock> buildSstoLeaveBlockList(BalanceTransfer bt) { 156 String leaveDocId = CollectionUtils.isNotEmpty(bt.getLeaveBlocks())? bt.getLeaveBlocks().get(0).getDocumentId() : ""; 157 List<LeaveBlock> lbList = new ArrayList<LeaveBlock>(); 158 AccrualCategory fromAC = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(bt.getFromAccrualCategory(), bt.getEffectiveDate()); 159 160 LeaveBlock accruedLeaveBlock = new LeaveBlock(); 161 accruedLeaveBlock.setAccrualCategory(bt.getFromAccrualCategory()); 162 accruedLeaveBlock.setLeaveDate(bt.getEffectiveDate()); 163 accruedLeaveBlock.setPrincipalId(bt.getPrincipalId()); 164 accruedLeaveBlock.setEarnCode(fromAC.getEarnCode()); 165 accruedLeaveBlock.setDateAndTime(TKUtils.getCurrentTimestamp()); 166 accruedLeaveBlock.setAccrualGenerated(true); 167 accruedLeaveBlock.setBlockId(0L); 168 accruedLeaveBlock.setScheduleTimeOffId(bt.getSstoId()); 169 accruedLeaveBlock.setLeaveAmount(bt.getTransferAmount()); 170 accruedLeaveBlock.setLeaveBlockType(LMConstants.LEAVE_BLOCK_TYPE.ACCRUAL_SERVICE); 171 accruedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED); 172 accruedLeaveBlock.setDocumentId(leaveDocId); 173 accruedLeaveBlock.setPrincipalIdModified(TKContext.getPrincipalId()); 174 lbList.add(accruedLeaveBlock); 175 176 LeaveBlock usageLeaveBlock = new LeaveBlock(); 177 usageLeaveBlock.setAccrualCategory(bt.getFromAccrualCategory()); 178 usageLeaveBlock.setLeaveDate(bt.getEffectiveDate()); 179 usageLeaveBlock.setPrincipalId(bt.getPrincipalId()); 180 usageLeaveBlock.setEarnCode(fromAC.getEarnCode()); 181 usageLeaveBlock.setDateAndTime(TKUtils.getCurrentTimestamp()); 182 usageLeaveBlock.setAccrualGenerated(true); 183 usageLeaveBlock.setBlockId(0L); 184 usageLeaveBlock.setScheduleTimeOffId(bt.getSstoId()); 185 usageLeaveBlock.setLeaveAmount(bt.getTransferAmount().negate()); 186 usageLeaveBlock.setLeaveBlockType(LMConstants.LEAVE_BLOCK_TYPE.ACCRUAL_SERVICE); 187 usageLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED); 188 usageLeaveBlock.setDocumentId(leaveDocId); 189 usageLeaveBlock.setPrincipalIdModified(TKContext.getPrincipalId()); 190 lbList.add(usageLeaveBlock); 191 192 return lbList; 193 } 194 }