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().getLeaveBlocksForDocumentId(balanceTransfer.getLeaveCalendarDocumentId());
126 //List<LeaveBlock> leaveBlocks = TkServiceLocator.getLeaveBlockService().getLeaveBlocksForDate(balanceTransfer.getPrincipalId(), balanceTransfer.getEffectiveDate());
127 for(LeaveBlock lb : leaveBlocks) {
128 if(StringUtils.equals(lb.getAccrualCategory(),balanceTransfer.getFromAccrualCategory())
129 && StringUtils.equals(lb.getLeaveBlockType(),LMConstants.LEAVE_BLOCK_TYPE.CARRY_OVER_ADJUSTMENT)) {
130 //KPME-2253
131 BigDecimal adjustment = new BigDecimal(0);
132 if(balanceTransfer.getTransferAmount() != null)
133 adjustment = adjustment.add(balanceTransfer.getTransferAmount().abs());
134 if(balanceTransfer.getForfeitedAmount() != null)
135 adjustment = adjustment.add(balanceTransfer.getForfeitedAmount().abs());
136 BigDecimal adjustedLeaveAmount = lb.getLeaveAmount().abs().subtract(adjustment);
137 lb.setLeaveAmount(adjustedLeaveAmount.negate());
138 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(lb, routedByPrincipalId);
139 }
140 }
141 } else if (DocumentStatus.CANCELED.equals(newDocumentStatus)) {
142 //When transfer document is canceled, set all leave block's request statuses to deferred
143
144 for(LeaveBlock lb : balanceTransfer.getLeaveBlocks()) {
145 if(ObjectUtils.isNotNull(lb)) {
146 lb.setRequestStatus(LMConstants.REQUEST_STATUS.DEFERRED);
147 TkServiceLocator.getLeaveBlockService().updateLeaveBlock(lb, routedByPrincipalId);
148 }
149 }
150 }
151 }
152
153 private List<LeaveBlock> buildSstoLeaveBlockList(BalanceTransfer bt) {
154 String leaveDocId = CollectionUtils.isNotEmpty(bt.getLeaveBlocks())? bt.getLeaveBlocks().get(0).getDocumentId() : "";
155 List<LeaveBlock> lbList = new ArrayList<LeaveBlock>();
156 AccrualCategory fromAC = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(bt.getFromAccrualCategory(), bt.getEffectiveDate());
157
158 LeaveBlock accruedLeaveBlock = new LeaveBlock();
159 accruedLeaveBlock.setAccrualCategory(bt.getFromAccrualCategory());
160 accruedLeaveBlock.setLeaveDate(bt.getEffectiveDate());
161 accruedLeaveBlock.setPrincipalId(bt.getPrincipalId());
162 accruedLeaveBlock.setEarnCode(fromAC.getEarnCode());
163 accruedLeaveBlock.setDateAndTime(TKUtils.getCurrentTimestamp());
164 accruedLeaveBlock.setAccrualGenerated(true);
165 accruedLeaveBlock.setBlockId(0L);
166 accruedLeaveBlock.setScheduleTimeOffId(bt.getSstoId());
167 accruedLeaveBlock.setLeaveAmount(bt.getTransferAmount());
168 accruedLeaveBlock.setLeaveBlockType(LMConstants.LEAVE_BLOCK_TYPE.ACCRUAL_SERVICE);
169 accruedLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED);
170 accruedLeaveBlock.setDocumentId(leaveDocId);
171 accruedLeaveBlock.setPrincipalIdModified(TKContext.getPrincipalId());
172 lbList.add(accruedLeaveBlock);
173
174 LeaveBlock usageLeaveBlock = new LeaveBlock();
175 usageLeaveBlock.setAccrualCategory(bt.getFromAccrualCategory());
176 usageLeaveBlock.setLeaveDate(bt.getEffectiveDate());
177 usageLeaveBlock.setPrincipalId(bt.getPrincipalId());
178 usageLeaveBlock.setEarnCode(fromAC.getEarnCode());
179 usageLeaveBlock.setDateAndTime(TKUtils.getCurrentTimestamp());
180 usageLeaveBlock.setAccrualGenerated(true);
181 usageLeaveBlock.setBlockId(0L);
182 usageLeaveBlock.setScheduleTimeOffId(bt.getSstoId());
183 usageLeaveBlock.setLeaveAmount(bt.getTransferAmount().negate());
184 usageLeaveBlock.setLeaveBlockType(LMConstants.LEAVE_BLOCK_TYPE.ACCRUAL_SERVICE);
185 usageLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.APPROVED);
186 usageLeaveBlock.setDocumentId(leaveDocId);
187 usageLeaveBlock.setPrincipalIdModified(TKContext.getPrincipalId());
188 lbList.add(usageLeaveBlock);
189
190 return lbList;
191 }
192 }