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.setRequestStatus(LMConstants.REQUEST_STATUS.REQUESTED);
244                                            aLeaveBlock.setBlockId(0L);
245    
246                                            //Want to store the newly created leave block id on this maintainable object
247                                            //when the status of the maintenance document encapsulating this maintainable changes
248                                            //the id will be used to fetch and update the leave block statuses.
249                                            aLeaveBlock = KRADServiceLocator.getBusinessObjectService().save(aLeaveBlock);
250    
251                                            balanceTransfer.setAccruedLeaveBlockId(aLeaveBlock.getLmLeaveBlockId());
252                                            // save history
253                                            LeaveBlockHistory lbh = new LeaveBlockHistory(aLeaveBlock);
254                                            lbh.setAction(LMConstants.ACTION.ADD);
255                                            TkServiceLocator.getLeaveBlockHistoryService().saveLeaveBlockHistory(lbh);
256                                            leaveBlocks.add(aLeaveBlock);
257                                    }
258                            }
259    
260                            if(ObjectUtils.isNotNull(transferAmount)) {
261                                    if(transferAmount.compareTo(BigDecimal.ZERO) > 0) {                                  
262                                            //Create leave block that removes the correct transfer amount from the originating accrual category.
263                                            aLeaveBlock = new LeaveBlock();
264                                            aLeaveBlock.setPrincipalId(balanceTransfer.getPrincipalId());
265                                            aLeaveBlock.setLeaveDate(balanceTransfer.getEffectiveDate());
266                                            aLeaveBlock.setEarnCode(balanceTransfer.getDebitedAccrualCategory().getEarnCode());
267                                            aLeaveBlock.setAccrualCategory(balanceTransfer.getFromAccrualCategory());
268                                            aLeaveBlock.setDescription("Transferred amount");
269                                            aLeaveBlock.setLeaveAmount(balanceTransfer.getTransferAmount().negate());
270                                            aLeaveBlock.setAccrualGenerated(true);
271                                            aLeaveBlock.setTransactionDocId(balanceTransfer.getDocumentHeaderId());
272                                            aLeaveBlock.setLeaveBlockType(LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER);
273                                            aLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.REQUESTED);
274                                            aLeaveBlock.setBlockId(0L);
275    
276                                            //Want to store the newly created leave block id on this maintainable object.
277                                            //when the status of the maintenance document encapsulating this maintainable changes
278                                            //the id will be used to fetch and update the leave block statuses.
279                                            aLeaveBlock = KRADServiceLocator.getBusinessObjectService().save(aLeaveBlock);
280    
281                                            balanceTransfer.setDebitedLeaveBlockId(aLeaveBlock.getLmLeaveBlockId());
282                                            // save history
283                                            LeaveBlockHistory lbh = new LeaveBlockHistory(aLeaveBlock);
284                                            lbh.setAction(LMConstants.ACTION.ADD);
285                                            TkServiceLocator.getLeaveBlockHistoryService().saveLeaveBlockHistory(lbh);
286    
287                                            leaveBlocks.add(aLeaveBlock);
288                                    }
289                            }
290    
291                            BigDecimal forfeitedAmount = balanceTransfer.getForfeitedAmount();
292                            if(ObjectUtils.isNotNull(forfeitedAmount)) {
293                                    //Any amount forfeited must come out of the originating accrual category in order to bring balance back to max.
294                                    if(forfeitedAmount.compareTo(BigDecimal.ZERO) > 0) {
295                                            //for balance transfers with action = lose, transfer amount must be moved to forfeitedAmount
296                                            aLeaveBlock = new LeaveBlock();
297                                            aLeaveBlock.setPrincipalId(balanceTransfer.getPrincipalId());
298                                            aLeaveBlock.setLeaveDate(balanceTransfer.getEffectiveDate());
299                                            aLeaveBlock.setEarnCode(balanceTransfer.getDebitedAccrualCategory().getEarnCode());
300                                            aLeaveBlock.setAccrualCategory(balanceTransfer.getFromAccrualCategory());
301                                            aLeaveBlock.setDescription("Forfeited balance transfer amount");
302                                            aLeaveBlock.setLeaveAmount(forfeitedAmount.negate());
303                                            aLeaveBlock.setAccrualGenerated(true);
304                                            aLeaveBlock.setTransactionDocId(balanceTransfer.getDocumentHeaderId());
305                                            aLeaveBlock.setLeaveBlockType(LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER);
306                                            aLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.REQUESTED);
307                                            aLeaveBlock.setBlockId(0L);
308    
309                                            //Want to store the newly created leave block id on this maintainable object
310                                            //when the status of the maintenance document encapsulating this maintainable changes
311                                            //the id will be used to fetch and update the leave block statuses.
312                                            aLeaveBlock = KRADServiceLocator.getBusinessObjectService().save(aLeaveBlock);
313    
314                                            balanceTransfer.setForfeitedLeaveBlockId(aLeaveBlock.getLmLeaveBlockId());
315                                            // save history
316                                            LeaveBlockHistory lbh = new LeaveBlockHistory(aLeaveBlock);
317                                            lbh.setAction(LMConstants.ACTION.ADD);
318                                            TkServiceLocator.getLeaveBlockHistoryService().saveLeaveBlockHistory(lbh);
319    
320                                            leaveBlocks.add(aLeaveBlock);
321                                    }
322                            }
323    
324                            return balanceTransfer;
325                    }
326            }
327            
328            public BalanceTransferDao getBalanceTransferDao() {
329                    return balanceTransferDao;
330            }
331            
332            public void setBalanceTransferDao(BalanceTransferDao balanceTransferDao) {
333                    this.balanceTransferDao = balanceTransferDao;
334            }
335    
336            @Override
337            public void submitToWorkflow(BalanceTransfer balanceTransfer)
338                            throws WorkflowException {
339                    
340                    //balanceTransfer.setStatus(TkConstants.ROUTE_STATUS.ENROUTE);
341            EntityNamePrincipalName principalName = null;
342            if (balanceTransfer.getPrincipalId() != null) {
343                principalName = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(balanceTransfer.getPrincipalId());
344            }
345    
346                    MaintenanceDocument document = KRADServiceLocatorWeb.getMaintenanceDocumentService().setupNewMaintenanceDocument(BalanceTransfer.class.getName(),
347                                    "BalanceTransferDocumentType",KRADConstants.MAINTENANCE_NEW_ACTION);
348    
349            String personName = (principalName != null  && principalName.getDefaultName() != null) ? principalName.getDefaultName().getCompositeName() : StringUtils.EMPTY;
350            String date = TKUtils.formatDate(new java.sql.Date(balanceTransfer.getEffectiveDate().getTime()));
351            document.getDocumentHeader().setDocumentDescription(personName + " (" + balanceTransfer.getPrincipalId() + ")  - " + date);
352                    Map<String,String[]> params = new HashMap<String,String[]>();
353                    
354                    KRADServiceLocatorWeb.getMaintenanceDocumentService().setupMaintenanceObject(document, KRADConstants.MAINTENANCE_NEW_ACTION, params);
355                    BalanceTransfer btObj = (BalanceTransfer) document.getNewMaintainableObject().getDataObject();
356                    
357                    btObj.setAccrualCategoryRule(balanceTransfer.getAccrualCategoryRule());
358                    btObj.setEffectiveDate(balanceTransfer.getEffectiveDate());
359                    btObj.setForfeitedAmount(balanceTransfer.getForfeitedAmount());
360                    btObj.setFromAccrualCategory(balanceTransfer.getFromAccrualCategory());
361                    btObj.setPrincipalId(balanceTransfer.getPrincipalId());
362                    btObj.setToAccrualCategory(balanceTransfer.getToAccrualCategory());
363                    btObj.setTransferAmount(balanceTransfer.getTransferAmount());
364                    btObj.setAmountTransferred(balanceTransfer.getAmountTransferred());
365                    btObj.setSstoId(balanceTransfer.getSstoId());
366                    btObj.setDocumentHeaderId(document.getDocumentHeader().getWorkflowDocument().getDocumentId());
367    /*        TkServiceLocator.getBalanceTransferService().saveOrUpdate(btObj);
368                    document.getNewMaintainableObject().setDataObject(btObj);*/
369                    KRADServiceLocatorWeb.getDocumentService().saveDocument(document);
370                    document.getDocumentHeader().getWorkflowDocument().saveDocument("");
371    
372                    document.getDocumentHeader().getWorkflowDocument().route("");
373                    
374            }
375            
376            @Override
377            public BalanceTransfer transferSsto(BalanceTransfer balanceTransfer) {
378                    if(ObjectUtils.isNull(balanceTransfer))
379                            throw new RuntimeException("did not supply a valid BalanceTransfer object.");
380                    else {
381                            List<LeaveBlock> sstoLbList = TkServiceLocator.getLeaveBlockService().getSSTOLeaveBlocks(balanceTransfer.getPrincipalId(), balanceTransfer.getSstoId(), balanceTransfer.getEffectiveDate());
382                            String leaveDocId = "";
383                            if(CollectionUtils.isNotEmpty(sstoLbList)) {
384                                    leaveDocId = sstoLbList.get(0).getDocumentId();
385                            }
386                            List<LeaveBlock> lbList = new ArrayList<LeaveBlock>();
387                            // create a new leave block with transferred amount, make sure system scheduled timeoff id is added to it
388                            LeaveBlock aLeaveBlock = new LeaveBlock();
389                            aLeaveBlock.setPrincipalId(balanceTransfer.getPrincipalId());
390                            aLeaveBlock.setLeaveDate(balanceTransfer.getEffectiveDate());
391                            aLeaveBlock.setEarnCode(balanceTransfer.getCreditedAccrualCategory().getEarnCode());
392                            aLeaveBlock.setAccrualCategory(balanceTransfer.getToAccrualCategory());
393                            aLeaveBlock.setDescription("System Scheduled Time off Amount transferred");
394                            aLeaveBlock.setLeaveAmount(balanceTransfer.getAmountTransferred());
395                            aLeaveBlock.setAccrualGenerated(false);
396                            aLeaveBlock.setLeaveBlockType(LMConstants.LEAVE_BLOCK_TYPE.BALANCE_TRANSFER);
397                            aLeaveBlock.setRequestStatus(LMConstants.REQUEST_STATUS.REQUESTED);
398                            aLeaveBlock.setBlockId(0L);
399                            aLeaveBlock.setScheduleTimeOffId(balanceTransfer.getSstoId());
400                            aLeaveBlock.setDocumentId(leaveDocId);
401                            
402                            lbList.add(aLeaveBlock);
403                            TkServiceLocator.getLeaveBlockService().saveLeaveBlocks(lbList);
404    
405                    balanceTransfer.setAccruedLeaveBlockId(aLeaveBlock.getLmLeaveBlockId());        
406                            return balanceTransfer;
407                    }
408            }
409    
410            @Override
411            public List<BalanceTransfer> getBalanceTransfers(String viewPrincipal,
412                            Date beginPeriodDate, Date endPeriodDate) {
413                    // TODO Auto-generated method stub
414                    return balanceTransferDao.getBalanceTransfers(viewPrincipal, beginPeriodDate, endPeriodDate);
415            }
416    
417            @Override
418            public void saveOrUpdate(BalanceTransfer balanceTransfer) {
419                    // TODO Auto-generated method stub
420                    balanceTransferDao.saveOrUpdate(balanceTransfer);
421            }
422    }