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.sql.Date;
020    import java.util.ArrayList;
021    import java.util.HashMap;
022    import java.util.List;
023    import java.util.Map;
024    
025    import org.apache.commons.collections.CollectionUtils;
026    import org.apache.commons.lang.StringUtils;
027    
028    import org.kuali.hr.lm.LMConstants;
029    import org.kuali.hr.lm.accrual.AccrualCategory;
030    import org.kuali.hr.lm.accrual.AccrualCategoryRule;
031    import org.kuali.hr.lm.balancetransfer.BalanceTransfer;
032    import org.kuali.hr.lm.balancetransfer.dao.BalanceTransferDao;
033    import org.kuali.hr.lm.employeeoverride.EmployeeOverride;
034    import org.kuali.hr.lm.leaveblock.LeaveBlock;
035    import org.kuali.hr.lm.leaveblock.LeaveBlockHistory;
036    
037    import org.kuali.hr.time.service.base.TkServiceLocator;
038    import org.kuali.hr.time.util.TKUtils;
039    
040    import org.kuali.rice.kew.api.exception.WorkflowException;
041    import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
042    import org.kuali.rice.kim.api.services.KimApiServiceLocator;
043    import org.kuali.rice.krad.maintenance.MaintenanceDocument;
044    import org.kuali.rice.krad.service.KRADServiceLocator;
045    import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
046    import org.kuali.rice.krad.util.KRADConstants;
047    import org.kuali.rice.krad.util.ObjectUtils;
048    
049    public class BalanceTransferServiceImpl implements BalanceTransferService {
050    
051            private BalanceTransferDao balanceTransferDao;
052            
053            @Override
054            public List<BalanceTransfer> getAllBalanceTransfersForPrincipalId(
055                            String principalId) {
056                    return balanceTransferDao.getAllBalanceTransfersForPrincipalId(principalId);
057            }
058    
059            @Override
060            public List<BalanceTransfer> getAllBalanceTransferForPrincipalIdAsOfDate(
061                            String principalId, Date effectiveDate) {
062                    return balanceTransferDao.getAllBalanceTransferForPrincipalIdAsOfDate(principalId,effectiveDate);
063            }
064    
065            @Override
066            public List<BalanceTransfer> getAllBalanceTransferByEffectiveDate(
067                            Date effectiveDate) {
068                    return balanceTransferDao.getAllBalanceTransferByEffectiveDate(effectiveDate);
069            }
070    
071            @Override
072            public BalanceTransfer getBalanceTransferById(String balanceTransferId) {
073                    return balanceTransferDao.getBalanceTransferById(balanceTransferId);
074            }
075            
076            @Override
077            public BalanceTransfer initializeTransfer(String principalId, String accrualCategoryRule, BigDecimal accruedBalance, Date effectiveDate) {
078                    //Initially, principals may be allowed to edit the transfer amount when prompted to submit this balance transfer, however,
079                    //a base transfer amount together with a forfeited amount is calculated to bring the balance back to its limit in accordance
080                    //with transfer limits. This "default" transfer object is used to adjust forfeiture when the user changes the transfer amount.
081                    BalanceTransfer bt = null;
082                    AccrualCategoryRule accrualRule = TkServiceLocator.getAccrualCategoryRuleService().getAccrualCategoryRule(accrualCategoryRule);
083    
084                    if(ObjectUtils.isNotNull(accrualRule) && ObjectUtils.isNotNull(accruedBalance)) {
085                            bt = new BalanceTransfer();
086                            //These two objects are essential to balance transfers triggered when the employee submits their leave calendar for approval.
087                            //Neither of these objects should be null, otherwise this method could not have been called.
088                            AccrualCategory fromAccrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getLmAccrualCategoryId());
089                            AccrualCategory toAccrualCategory = TkServiceLocator.getAccrualCategoryService().getAccrualCategory(accrualRule.getMaxBalanceTransferToAccrualCategory(),effectiveDate);
090                            BigDecimal fullTimeEngagement = TkServiceLocator.getJobService().getFteSumForAllActiveLeaveEligibleJobs(principalId, effectiveDate);
091                            
092                            BigDecimal transferConversionFactor = null;
093                            if(ObjectUtils.isNotNull(accrualRule.getMaxBalanceTransferConversionFactor()))
094                                    transferConversionFactor = accrualRule.getMaxBalanceTransferConversionFactor();
095                            
096                            // AccrualRule.maxBalance == null -> no balance limit. No balance limit -> no accrual triggered transfer / payout / lose.
097                            // execution point should not be here if max balance on accrualRule is null, unless there exists an employee override.
098                            BigDecimal maxBalance = accrualRule.getMaxBalance();
099                            BigDecimal adjustedMaxBalance = maxBalance.multiply(fullTimeEngagement).setScale(2);
100                            
101                            BigDecimal maxTransferAmount = null;
102                            BigDecimal adjustedMaxTransferAmount = null;
103                            if(ObjectUtils.isNotNull(accrualRule.getMaxTransferAmount())) {
104                                    maxTransferAmount = new BigDecimal(accrualRule.getMaxTransferAmount());
105                                    adjustedMaxTransferAmount = maxTransferAmount.multiply(fullTimeEngagement).setScale(2);
106                            }
107                            else {
108                                    // no limit on transfer amount
109                                    maxTransferAmount = new BigDecimal(Long.MAX_VALUE);
110                                    adjustedMaxTransferAmount = maxTransferAmount;
111                            }
112    
113                            BigDecimal maxCarryOver = null;
114                            BigDecimal adjustedMaxCarryOver = null;
115                            if(ObjectUtils.isNotNull(accrualRule.getMaxCarryOver())) {
116                                    maxCarryOver = new BigDecimal(accrualRule.getMaxCarryOver());
117                                    adjustedMaxCarryOver = maxCarryOver.multiply(fullTimeEngagement).setScale(2);
118                            }
119                            else {
120                                    //no limit to carry over.
121                                    maxCarryOver = new BigDecimal(Long.MAX_VALUE);
122                                    adjustedMaxCarryOver = maxCarryOver;
123                            }
124    
125                            List<EmployeeOverride> overrides = TkServiceLocator.getEmployeeOverrideService().getEmployeeOverrides(principalId, effectiveDate);
126                            for(EmployeeOverride override : overrides) {
127                                    if(StringUtils.equals(override.getAccrualCategory(),fromAccrualCategory.getAccrualCategory())) {
128                                            //Do not pro-rate override values for FTE.
129                                            if(StringUtils.equals(override.getOverrideType(),"MB"))
130                                                    adjustedMaxBalance = new BigDecimal(override.getOverrideValue());
131                                            if(StringUtils.equals(override.getOverrideType(),"MTA"))
132                                                    adjustedMaxTransferAmount = new BigDecimal(override.getOverrideValue());
133                                            if(StringUtils.equals(override.getOverrideType(),"MAC"))
134                                                    adjustedMaxCarryOver = new BigDecimal(override.getOverrideValue());
135                                    }
136                            }
137                            
138                            BigDecimal transferAmount = accruedBalance.subtract(adjustedMaxBalance);
139                            if(StringUtils.equals(accrualRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)) {
140                                    //Move all time in excess of employee's fte adjusted max balance to forfeiture.
141                                    bt.setForfeitedAmount(transferAmount);
142                                    //There is no transfer to another accrual category.
143                                    bt.setTransferAmount(BigDecimal.ZERO);
144                                    bt.setAmountTransferred(BigDecimal.ZERO);
145                                    // to accrual category is a required field on maintenance document. Set as from accrual category
146                                    // to remove validation errors when routing, approving, etc.
147                                    bt.setToAccrualCategory(fromAccrualCategory.getAccrualCategory());
148                            }
149                            else {
150                                    // ACTION_AT_MAX_BAL = TRANSFER
151                                    bt.setToAccrualCategory(toAccrualCategory.getAccrualCategory());
152                                    if(transferAmount.compareTo(adjustedMaxTransferAmount) > 0) {
153                                            //there's forfeiture.
154                                            //bring transfer amount down to the adjusted maximum transfer amount, and place excess in forfeiture.
155                                            //accruedBalance - adjustedMaxTransferAmount - adjustedMaxBalance = forfeiture.
156                                            //transferAmount = accruedBalance - adjustedMaxBalance; forfeiture = transferAmount - adjustedMaxTransferAmount.
157                                            BigDecimal forfeiture = transferAmount.subtract(adjustedMaxTransferAmount).setScale(2);
158                                            forfeiture = forfeiture.stripTrailingZeros();
159                                            bt.setForfeitedAmount(forfeiture);
160                                            bt.setTransferAmount(adjustedMaxTransferAmount);
161                                    }
162                                    else {
163                                            bt.setTransferAmount(transferAmount);
164                                            bt.setForfeitedAmount(BigDecimal.ZERO);
165                                    }
166                            }
167                            
168                            assert(adjustedMaxBalance.compareTo(accruedBalance.subtract(bt.getTransferAmount().add(bt.getForfeitedAmount()))) == 0);
169    
170                            // Max Carry Over logic for Year End transfers.
171                            if(StringUtils.equals(accrualRule.getMaxBalanceActionFrequency(),LMConstants.MAX_BAL_ACTION_FREQ.YEAR_END)) {
172    
173                                    //At this point, transfer amount and forfeiture have been set so that the new accrued balance will be the
174                                    //adjusted max balance, so this amount is used to check against carry over.
175                                    if(adjustedMaxBalance.compareTo(adjustedMaxCarryOver) > 0) {
176                                            BigDecimal carryOverDiff = adjustedMaxBalance.subtract(adjustedMaxCarryOver);
177                                            
178                                            if(StringUtils.equals(accrualRule.getActionAtMaxBalance(),LMConstants.ACTION_AT_MAX_BAL.LOSE)){
179                                                    //add carry over excess to forfeiture.
180                                                    bt.setForfeitedAmount(bt.getForfeitedAmount().add(carryOverDiff));
181                                            }
182                                            else {
183                                                    //maximize the transfer amount.
184                                                    BigDecimal potentialTransferAmount = bt.getTransferAmount().add(carryOverDiff);
185    
186                                                    //Can this amount be added to the transfer amount without exceeding adjusted max transfer amount??
187                                                    if(potentialTransferAmount.compareTo(adjustedMaxTransferAmount) <= 0) {
188                                                            //yes
189                                                            bt.setTransferAmount(bt.getTransferAmount().add(carryOverDiff));
190                                                    }
191                                                    else {
192                                                            //no
193                                                            BigDecimal carryOverExcess = potentialTransferAmount.subtract(adjustedMaxTransferAmount);
194                                                            //move excess to forfeiture
195                                                            bt.setForfeitedAmount(bt.getForfeitedAmount().add(carryOverExcess));
196                                                            //the remainder (if any) can be added to the transfer amount.
197                                                            bt.setTransferAmount(bt.getTransferAmount().add(carryOverDiff.subtract(carryOverExcess)));
198                                                            
199                                                            assert(bt.getTransferAmount().compareTo(adjustedMaxTransferAmount)==0);
200                                                            // assert that the new balance will be equal to the adjusted max carry over < adjusted max balance.
201                                                    }
202                                            }
203                                            assert(adjustedMaxCarryOver.compareTo(accruedBalance.subtract(bt.getTransferAmount().add(bt.getForfeitedAmount()))) == 0);
204                                    }
205                                    //otherwise, given balance will be at or under the max annual carry over.
206                            }
207                            
208                            bt.setEffectiveDate(effectiveDate);
209                            bt.setAccrualCategoryRule(accrualCategoryRule);
210                            bt.setFromAccrualCategory(fromAccrualCategory.getAccrualCategory());
211                            bt.setPrincipalId(principalId);
212                            if(ObjectUtils.isNotNull(transferConversionFactor))
213                                    bt.setAmountTransferred(bt.getTransferAmount().multiply(transferConversionFactor).setScale(2));
214                            else
215                                    bt.setAmountTransferred(bt.getTransferAmount());
216                    }
217                    return bt;
218            }
219    
220            @Override
221            public BalanceTransfer transfer(BalanceTransfer balanceTransfer) {
222                    if(ObjectUtils.isNull(balanceTransfer))
223                            throw new RuntimeException("did not supply a valid BalanceTransfer object.");
224                    else {
225                            List<LeaveBlock> leaveBlocks = new ArrayList<LeaveBlock>();
226                            BigDecimal transferAmount = balanceTransfer.getTransferAmount();
227                            LeaveBlock aLeaveBlock = null;
228    
229                            if(ObjectUtils.isNotNull(balanceTransfer.getAmountTransferred())) {
230                                    if(balanceTransfer.getAmountTransferred().compareTo(BigDecimal.ZERO) > 0 ) {
231    
232                                            aLeaveBlock = new LeaveBlock();
233                                            //Create a leave block that adds the adjusted transfer amount to the "transfer to" accrual category.
234                                            aLeaveBlock.setPrincipalId(balanceTransfer.getPrincipalId());
235                                            aLeaveBlock.setLeaveDate(balanceTransfer.getEffectiveDate());
236                                            aLeaveBlock.setEarnCode(balanceTransfer.getCreditedAccrualCategory().getEarnCode());
237                                            aLeaveBlock.setAccrualCategory(balanceTransfer.getToAccrualCategory());
238                                            aLeaveBlock.setDescription("Amount transferred");
239                                            aLeaveBlock.setLeaveAmount(balanceTransfer.getAmountTransferred());
240                                            aLeaveBlock.setAccrualGenerated(true);
241                                            aLeaveBlock.setTransactionDocId(balanceTransfer.getDocumentHeaderId());
242                                            aLeaveBlock.setLeaveBlockType(LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER);
243                                            aLeaveBlock.setDocumentId(balanceTransfer.getLeaveCalendarDocumentId());
244                                            aLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.REQUESTED);
245                                            aLeaveBlock.setBlockId(0L);
246    
247                                            //Want to store the newly created leave block id on this maintainable object
248                                            //when the status of the maintenance document encapsulating this maintainable changes
249                                            //the id will be used to fetch and update the leave block statuses.
250                                            aLeaveBlock = KRADServiceLocator.getBusinessObjectService().save(aLeaveBlock);
251    
252                                            balanceTransfer.setAccruedLeaveBlockId(aLeaveBlock.getLmLeaveBlockId());
253                                            // save history
254                                            LeaveBlockHistory lbh = new LeaveBlockHistory(aLeaveBlock);
255                                            lbh.setAction(LMConstants.ACTION.ADD);
256                                            TkServiceLocator.getLeaveBlockHistoryService().saveLeaveBlockHistory(lbh);
257                                            leaveBlocks.add(aLeaveBlock);
258                                    }
259                            }
260    
261                            if(ObjectUtils.isNotNull(transferAmount)) {
262                                    if(transferAmount.compareTo(BigDecimal.ZERO) > 0) {                                  
263                                            //Create leave block that removes the correct transfer amount from the originating accrual category.
264                                            aLeaveBlock = new LeaveBlock();
265                                            aLeaveBlock.setPrincipalId(balanceTransfer.getPrincipalId());
266                                            aLeaveBlock.setLeaveDate(balanceTransfer.getEffectiveDate());
267                                            aLeaveBlock.setEarnCode(balanceTransfer.getDebitedAccrualCategory().getEarnCode());
268                                            aLeaveBlock.setAccrualCategory(balanceTransfer.getFromAccrualCategory());
269                                            aLeaveBlock.setDescription("Transferred amount");
270                                            aLeaveBlock.setLeaveAmount(balanceTransfer.getTransferAmount().negate());
271                                            aLeaveBlock.setAccrualGenerated(true);
272                                            aLeaveBlock.setTransactionDocId(balanceTransfer.getDocumentHeaderId());
273                                            aLeaveBlock.setLeaveBlockType(LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER);
274                                            aLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.REQUESTED);
275                                            aLeaveBlock.setDocumentId(balanceTransfer.getLeaveCalendarDocumentId());
276                                            aLeaveBlock.setBlockId(0L);
277    
278                                            //Want to store the newly created leave block id on this maintainable object.
279                                            //when the status of the maintenance document encapsulating this maintainable changes
280                                            //the id will be used to fetch and update the leave block statuses.
281                                            aLeaveBlock = KRADServiceLocator.getBusinessObjectService().save(aLeaveBlock);
282    
283                                            balanceTransfer.setDebitedLeaveBlockId(aLeaveBlock.getLmLeaveBlockId());
284                                            // save history
285                                            LeaveBlockHistory lbh = new LeaveBlockHistory(aLeaveBlock);
286                                            lbh.setAction(LMConstants.ACTION.ADD);
287                                            TkServiceLocator.getLeaveBlockHistoryService().saveLeaveBlockHistory(lbh);
288    
289                                            leaveBlocks.add(aLeaveBlock);
290                                    }
291                            }
292    
293                            BigDecimal forfeitedAmount = balanceTransfer.getForfeitedAmount();
294                            if(ObjectUtils.isNotNull(forfeitedAmount)) {
295                                    //Any amount forfeited must come out of the originating accrual category in order to bring balance back to max.
296                                    if(forfeitedAmount.compareTo(BigDecimal.ZERO) > 0) {
297                                            //for balance transfers with action = lose, transfer amount must be moved to forfeitedAmount
298                                            aLeaveBlock = new LeaveBlock();
299                                            aLeaveBlock.setPrincipalId(balanceTransfer.getPrincipalId());
300                                            aLeaveBlock.setLeaveDate(balanceTransfer.getEffectiveDate());
301                                            aLeaveBlock.setEarnCode(balanceTransfer.getDebitedAccrualCategory().getEarnCode());
302                                            aLeaveBlock.setAccrualCategory(balanceTransfer.getFromAccrualCategory());
303                                            aLeaveBlock.setDescription("Forfeited balance transfer amount");
304                                            aLeaveBlock.setLeaveAmount(forfeitedAmount.negate());
305                                            aLeaveBlock.setAccrualGenerated(true);
306                                            aLeaveBlock.setTransactionDocId(balanceTransfer.getDocumentHeaderId());
307                                            aLeaveBlock.setLeaveBlockType(LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER);
308                                            aLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.REQUESTED);
309                                            aLeaveBlock.setDocumentId(balanceTransfer.getLeaveCalendarDocumentId());
310                                            aLeaveBlock.setBlockId(0L);
311    
312                                            //Want to store the newly created leave block id on this maintainable object
313                                            //when the status of the maintenance document encapsulating this maintainable changes
314                                            //the id will be used to fetch and update the leave block statuses.
315                                            aLeaveBlock = KRADServiceLocator.getBusinessObjectService().save(aLeaveBlock);
316    
317                                            balanceTransfer.setForfeitedLeaveBlockId(aLeaveBlock.getLmLeaveBlockId());
318                                            // save history
319                                            LeaveBlockHistory lbh = new LeaveBlockHistory(aLeaveBlock);
320                                            lbh.setAction(LMConstants.ACTION.ADD);
321                                            TkServiceLocator.getLeaveBlockHistoryService().saveLeaveBlockHistory(lbh);
322    
323                                            leaveBlocks.add(aLeaveBlock);
324                                    }
325                            }
326    
327                            return balanceTransfer;
328                    }
329            }
330            
331            public BalanceTransferDao getBalanceTransferDao() {
332                    return balanceTransferDao;
333            }
334            
335            public void setBalanceTransferDao(BalanceTransferDao balanceTransferDao) {
336                    this.balanceTransferDao = balanceTransferDao;
337            }
338    
339            @Override
340            public void submitToWorkflow(BalanceTransfer balanceTransfer)
341                            throws WorkflowException {
342                    
343                    //balanceTransfer.setStatus(TkConstants.ROUTE_STATUS.ENROUTE);
344            EntityNamePrincipalName principalName = null;
345            if (balanceTransfer.getPrincipalId() != null) {
346                principalName = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(balanceTransfer.getPrincipalId());
347            }
348    
349                    MaintenanceDocument document = KRADServiceLocatorWeb.getMaintenanceDocumentService().setupNewMaintenanceDocument(BalanceTransfer.class.getName(),
350                                    "BalanceTransferDocumentType",KRADConstants.MAINTENANCE_NEW_ACTION);
351    
352            String personName = (principalName != null  && principalName.getDefaultName() != null) ? principalName.getDefaultName().getCompositeName() : StringUtils.EMPTY;
353            String date = TKUtils.formatDate(new java.sql.Date(balanceTransfer.getEffectiveDate().getTime()));
354            document.getDocumentHeader().setDocumentDescription(personName + " (" + balanceTransfer.getPrincipalId() + ")  - " + date);
355                    Map<String,String[]> params = new HashMap<String,String[]>();
356                    
357                    KRADServiceLocatorWeb.getMaintenanceDocumentService().setupMaintenanceObject(document, KRADConstants.MAINTENANCE_NEW_ACTION, params);
358                    BalanceTransfer btObj = (BalanceTransfer) document.getNewMaintainableObject().getDataObject();
359                    
360                    btObj.setAccrualCategoryRule(balanceTransfer.getAccrualCategoryRule());
361                    btObj.setEffectiveDate(balanceTransfer.getEffectiveDate());
362                    btObj.setForfeitedAmount(balanceTransfer.getForfeitedAmount());
363                    btObj.setFromAccrualCategory(balanceTransfer.getFromAccrualCategory());
364                    btObj.setPrincipalId(balanceTransfer.getPrincipalId());
365                    btObj.setToAccrualCategory(balanceTransfer.getToAccrualCategory());
366                    btObj.setTransferAmount(balanceTransfer.getTransferAmount());
367                    btObj.setAmountTransferred(balanceTransfer.getAmountTransferred());
368                    btObj.setLeaveCalendarDocumentId(balanceTransfer.getLeaveCalendarDocumentId());
369                    btObj.setSstoId(balanceTransfer.getSstoId());
370                    btObj.setDocumentHeaderId(document.getDocumentHeader().getWorkflowDocument().getDocumentId());
371    /*        TkServiceLocator.getBalanceTransferService().saveOrUpdate(btObj);
372                    document.getNewMaintainableObject().setDataObject(btObj);*/
373                    KRADServiceLocatorWeb.getDocumentService().saveDocument(document);
374                    document.getDocumentHeader().getWorkflowDocument().saveDocument("");
375    
376                    document.getDocumentHeader().getWorkflowDocument().route("");
377                    
378            }
379            
380            @Override
381            public BalanceTransfer transferSsto(BalanceTransfer balanceTransfer) {
382                    if(ObjectUtils.isNull(balanceTransfer))
383                            throw new RuntimeException("did not supply a valid BalanceTransfer object.");
384                    else {
385                            List<LeaveBlock> sstoLbList = TkServiceLocator.getLeaveBlockService().getSSTOLeaveBlocks(balanceTransfer.getPrincipalId(), balanceTransfer.getSstoId(), balanceTransfer.getEffectiveDate());
386                            String leaveDocId = "";
387                            if(CollectionUtils.isNotEmpty(sstoLbList)) {
388                                    leaveDocId = sstoLbList.get(0).getDocumentId();
389                            }
390                            List<LeaveBlock> lbList = new ArrayList<LeaveBlock>();
391                            // create a new leave block with transferred amount, make sure system scheduled timeoff id is added to it
392                            LeaveBlock aLeaveBlock = new LeaveBlock();
393                            aLeaveBlock.setPrincipalId(balanceTransfer.getPrincipalId());
394                            aLeaveBlock.setLeaveDate(balanceTransfer.getEffectiveDate());
395                            aLeaveBlock.setEarnCode(balanceTransfer.getCreditedAccrualCategory().getEarnCode());
396                            aLeaveBlock.setAccrualCategory(balanceTransfer.getToAccrualCategory());
397                            aLeaveBlock.setDescription("System Scheduled Time off Amount transferred");
398                            aLeaveBlock.setLeaveAmount(balanceTransfer.getAmountTransferred());
399                            aLeaveBlock.setAccrualGenerated(false);
400                            aLeaveBlock.setLeaveBlockType(LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER);
401                            aLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.REQUESTED);
402                            aLeaveBlock.setBlockId(0L);
403                            aLeaveBlock.setScheduleTimeOffId(balanceTransfer.getSstoId());
404                            aLeaveBlock.setDocumentId(leaveDocId);
405                            
406                            lbList.add(aLeaveBlock);
407                            TkServiceLocator.getLeaveBlockService().saveLeaveBlocks(lbList);
408    
409                    balanceTransfer.setAccruedLeaveBlockId(aLeaveBlock.getLmLeaveBlockId());        
410                            return balanceTransfer;
411                    }
412            }
413    
414            @Override
415            public List<BalanceTransfer> getBalanceTransfers(String viewPrincipal,
416                            Date beginPeriodDate, Date endPeriodDate) {
417                    // TODO Auto-generated method stub
418                    return balanceTransferDao.getBalanceTransfers(viewPrincipal, beginPeriodDate, endPeriodDate);
419            }
420    
421            @Override
422            public void saveOrUpdate(BalanceTransfer balanceTransfer) {
423                    // TODO Auto-generated method stub
424                    balanceTransferDao.saveOrUpdate(balanceTransfer);
425            }
426    }