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 }