From 8ed8d0fc516c3a924d32814dc4455a21550cdaa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E5=AE=87=E5=A5=87?= Date: Thu, 10 Apr 2025 14:22:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=85=A5=E8=B4=A6=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ruoyi/common/constant/Constants.java | 2 + .../domain/ExternalAccountTransDetail.java | 6 + .../domain/InternalAccountTransDetail.java | 6 + .../ExternalAccountTransDetailDTO.java | 4 + .../InternalAccountTransDetailDTO.java | 4 + .../xkt/service/IExternalAccountService.java | 9 ++ .../xkt/service/IInternalAccountService.java | 32 ++-- .../impl/ExternalAccountServiceImpl.java | 73 ++++++++- .../service/impl/FinanceBillServiceImpl.java | 7 +- .../impl/InternalAccountServiceImpl.java | 153 ++++++++++++++---- 10 files changed, 235 insertions(+), 61 deletions(-) diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java index b0c9364eb..ac10be5ee 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java @@ -202,6 +202,8 @@ public class Constants */ public static final Integer ORDER_NUM_1 = 1; + public static final String VERSION_LOCK_ERROR_COMMON_MSG = "系统繁忙,请稍后再试"; + diff --git a/xkt/src/main/java/com/ruoyi/xkt/domain/ExternalAccountTransDetail.java b/xkt/src/main/java/com/ruoyi/xkt/domain/ExternalAccountTransDetail.java index 54860219e..cfee21743 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/domain/ExternalAccountTransDetail.java +++ b/xkt/src/main/java/com/ruoyi/xkt/domain/ExternalAccountTransDetail.java @@ -1,5 +1,6 @@ package com.ruoyi.xkt.domain; +import com.baomidou.mybatisplus.annotation.Version; import com.ruoyi.common.core.domain.SimpleEntity; import lombok.Data; import lombok.EqualsAndHashCode; @@ -54,4 +55,9 @@ public class ExternalAccountTransDetail extends SimpleEntity { * 备注 */ private String remark; + /** + * 版本号 + */ + @Version + private Long version; } diff --git a/xkt/src/main/java/com/ruoyi/xkt/domain/InternalAccountTransDetail.java b/xkt/src/main/java/com/ruoyi/xkt/domain/InternalAccountTransDetail.java index f27aae267..1830b2851 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/domain/InternalAccountTransDetail.java +++ b/xkt/src/main/java/com/ruoyi/xkt/domain/InternalAccountTransDetail.java @@ -1,5 +1,6 @@ package com.ruoyi.xkt.domain; +import com.baomidou.mybatisplus.annotation.Version; import com.ruoyi.common.core.domain.SimpleEntity; import lombok.Data; import lombok.EqualsAndHashCode; @@ -58,4 +59,9 @@ public class InternalAccountTransDetail extends SimpleEntity { * 备注 */ private String remark; + /** + * 版本号 + */ + @Version + private Long version; } diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/finance/ExternalAccountTransDetailDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/finance/ExternalAccountTransDetailDTO.java index 8318fa978..81da922fb 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/finance/ExternalAccountTransDetailDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/finance/ExternalAccountTransDetailDTO.java @@ -73,4 +73,8 @@ public class ExternalAccountTransDetailDTO { * 更新时间 */ private Date updateTime; + /** + * 版本号 + */ + private Long version; } diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/finance/InternalAccountTransDetailDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/finance/InternalAccountTransDetailDTO.java index 04f4fb7dc..577721570 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/finance/InternalAccountTransDetailDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/finance/InternalAccountTransDetailDTO.java @@ -77,4 +77,8 @@ public class InternalAccountTransDetailDTO { * 更新时间 */ private Date updateTime; + /** + * 版本号 + */ + private Long version; } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IExternalAccountService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IExternalAccountService.java index 2e0c31481..f9e903303 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IExternalAccountService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IExternalAccountService.java @@ -3,6 +3,7 @@ package com.ruoyi.xkt.service; import com.ruoyi.xkt.domain.ExternalAccount; import com.ruoyi.xkt.dto.finance.TransInfo; import com.ruoyi.xkt.enums.EEntryStatus; +import com.ruoyi.xkt.enums.EFinBillType; import com.ruoyi.xkt.enums.ELoanDirection; /** @@ -30,4 +31,12 @@ public interface IExternalAccountService { int addTransDetail(Long externalAccountId, TransInfo transInfo, ELoanDirection loanDirection, EEntryStatus entryStatus); + /** + * 交易明细入账 + * + * @param srcBillId + * @param srcBillType + */ + void entryTransDetail(Long srcBillId, EFinBillType srcBillType); + } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IInternalAccountService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IInternalAccountService.java index 05bde1e7b..a658136c5 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IInternalAccountService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IInternalAccountService.java @@ -3,45 +3,41 @@ package com.ruoyi.xkt.service; import com.ruoyi.xkt.domain.InternalAccount; import com.ruoyi.xkt.dto.finance.TransInfo; import com.ruoyi.xkt.enums.EEntryStatus; +import com.ruoyi.xkt.enums.EFinBillType; import com.ruoyi.xkt.enums.ELoanDirection; -import java.util.Collection; -import java.util.List; - /** * @author liangyq * @date 2025-04-08 21:14 */ public interface IInternalAccountService { - /** - * 获取内部账户(加锁) + * 通过ID获取内部账户 * * @param id * @return */ - InternalAccount getWithLock(Long id); - - /** - * 获取内部账户列表(加锁) - * - * @param ids - * @return - */ - List listWithLock(Collection ids); + InternalAccount getById(Long id); /** * 添加交易明细 - * 余额会根据明细更新 - * 调用方法时入参账户必须处于加锁状态! * - * @param internalAccount + * @param internalAccountId * @param transInfo * @param loanDirection * @param entryStatus * @return */ - int addTransDetail(InternalAccount internalAccount, TransInfo transInfo, ELoanDirection loanDirection, + int addTransDetail(Long internalAccountId, TransInfo transInfo, ELoanDirection loanDirection, EEntryStatus entryStatus); + /** + * 交易明细入账 + * 根据来源单据获取待入账的交易明细执行入账 + * + * @param srcBillId + * @param srcBillType + */ + void entryTransDetail(Long srcBillId, EFinBillType srcBillType); + } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/ExternalAccountServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/ExternalAccountServiceImpl.java index ba2b6b450..fe68e2e5c 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/ExternalAccountServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/ExternalAccountServiceImpl.java @@ -1,7 +1,10 @@ package com.ruoyi.xkt.service.impl; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.NumberUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.SimpleEntity; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.bean.BeanValidators; import com.ruoyi.xkt.domain.ExternalAccount; @@ -9,21 +12,27 @@ import com.ruoyi.xkt.domain.ExternalAccountTransDetail; import com.ruoyi.xkt.dto.finance.TransInfo; import com.ruoyi.xkt.enums.EAccountStatus; import com.ruoyi.xkt.enums.EEntryStatus; +import com.ruoyi.xkt.enums.EFinBillType; import com.ruoyi.xkt.enums.ELoanDirection; import com.ruoyi.xkt.mapper.ExternalAccountMapper; import com.ruoyi.xkt.mapper.ExternalAccountTransDetailMapper; import com.ruoyi.xkt.service.IExternalAccountService; import io.jsonwebtoken.lang.Assert; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author liangyq * @date 2025-04-08 21:14 */ +@Slf4j @Service public class ExternalAccountServiceImpl implements IExternalAccountService { @@ -42,13 +51,9 @@ public class ExternalAccountServiceImpl implements IExternalAccountService { @Override public int addTransDetail(Long externalAccountId, TransInfo transInfo, ELoanDirection loanDirection, EEntryStatus entryStatus) { - ExternalAccount account = getById(externalAccountId); - if (!BeanValidators.exists(account)) { - throw new ServiceException("外部账户[" + externalAccountId + "]不存在"); - } - if (!EAccountStatus.NORMAL.getValue().equals(account.getAccountStatus())) { - throw new ServiceException("外部账户[" + externalAccountId + "]已冻结"); - } + Assert.notNull(externalAccountId); + ExternalAccount account = externalAccountMapper.selectById(externalAccountId); + checkAccountStatus(account); ExternalAccountTransDetail transDetail = new ExternalAccountTransDetail(); transDetail.setExternalAccountId(externalAccountId); transDetail.setSrcBillId(transInfo.getSrcBillId()); @@ -62,8 +67,62 @@ public class ExternalAccountServiceImpl implements IExternalAccountService { transDetail.setHandlerId(transInfo.getHandlerId()); transDetail.setEntryStatus(entryStatus.getValue()); transDetail.setRemark(transInfo.getRemark()); + transDetail.setVersion(0L); transDetail.setDelFlag(Constants.UNDELETED); return externalAccountTransDetailMapper.insert(transDetail); } + @Transactional + @Override + public void entryTransDetail(Long srcBillId, EFinBillType srcBillType) { + Assert.notNull(srcBillId); + Assert.notNull(srcBillType); + List transDetails = externalAccountTransDetailMapper.selectList(Wrappers + .lambdaQuery(ExternalAccountTransDetail.class) + .eq(ExternalAccountTransDetail::getSrcBillId, srcBillId) + .eq(ExternalAccountTransDetail::getSrcBillType, srcBillType.getValue()) + .eq(SimpleEntity::getDelFlag, Constants.UNDELETED)); + if (CollUtil.isEmpty(transDetails)) { + log.warn("单据没有关联的交易明细:{}{}", srcBillType.getLabel(), srcBillId); + return; + } + List accountIds = transDetails.stream().map(ExternalAccountTransDetail::getExternalAccountId).distinct() + .collect(Collectors.toList()); + Assert.notEmpty(accountIds); + Map accountMap = externalAccountMapper.selectByIds(accountIds) + .stream() + .collect(Collectors.toMap(SimpleEntity::getId, o -> o)); + //开始入账 + for (ExternalAccountTransDetail transDetail : transDetails) { + ExternalAccount account = accountMap.get(transDetail.getExternalAccountId()); + checkAccountStatus(account); + if (EEntryStatus.WAITING.getValue().equals(transDetail.getEntryStatus())) { + //明细未入账 + transDetail.setEntryStatus(EEntryStatus.FINISH.getValue()); + //更新交易明细 + int r = externalAccountTransDetailMapper.updateById(transDetail); + if (r == 0) { + throw new ServiceException(Constants.VERSION_LOCK_ERROR_COMMON_MSG); + } + } else { + log.warn("单据重复调用入账方法:{}{}", srcBillType.getLabel(), srcBillId); + } + } + } + + /** + * 检查账户状态 + * + * @param externalAccount + */ + private void checkAccountStatus(ExternalAccount externalAccount) { + Assert.notNull(externalAccount, "账户不存在"); + if (!BeanValidators.exists(externalAccount)) { + throw new ServiceException("账户[" + externalAccount.getId() + "]不存在"); + } + if (!EAccountStatus.NORMAL.getValue().equals(externalAccount.getAccountStatus())) { + throw new ServiceException("账户[" + externalAccount.getId() + "]已冻结"); + } + } + } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/FinanceBillServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/FinanceBillServiceImpl.java index 949ae9ced..6de32ee7f 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/FinanceBillServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/FinanceBillServiceImpl.java @@ -4,7 +4,6 @@ import cn.hutool.core.util.IdUtil; import com.ruoyi.common.constant.Constants; import com.ruoyi.xkt.domain.FinanceBill; import com.ruoyi.xkt.domain.FinanceBillDetail; -import com.ruoyi.xkt.domain.InternalAccount; import com.ruoyi.xkt.domain.StoreOrderDetail; import com.ruoyi.xkt.dto.finance.FinanceBillInfo; import com.ruoyi.xkt.dto.finance.TransInfo; @@ -48,7 +47,6 @@ public class FinanceBillServiceImpl implements IFinanceBillService { Assert.notNull(payId); Assert.notNull(payChannel); //获取平台内部账户并加锁 - InternalAccount ia = internalAccountService.getWithLock(Constants.PLATFORM_INTERNAL_ACCOUNT_ID); FinanceBill bill = new FinanceBill(); bill.setBillNo(generateBillNo(EFinBillType.COLLECTION)); bill.setBillType(EFinBillType.COLLECTION.getValue()); @@ -61,7 +59,7 @@ public class FinanceBillServiceImpl implements IFinanceBillService { //支付渠道+回调ID构成业务唯一键,防止重复创建收款单 String businessUniqueKey = payChannel.getPrefix() + payId; bill.setBusinessUniqueKey(businessUniqueKey); - bill.setInputInternalAccountId(ia.getId()); + bill.setInputInternalAccountId(Constants.PLATFORM_INTERNAL_ACCOUNT_ID); bill.setInputExternalAccountId(payChannel.getPlatformExternalAccountId()); bill.setBusinessAmount(orderInfo.getOrder().getTotalAmount()); bill.setTransAmount(orderInfo.getOrder().getRealTotalAmount()); @@ -89,7 +87,8 @@ public class FinanceBillServiceImpl implements IFinanceBillService { .remark("订单支付完成") .build(); //内部账户 - internalAccountService.addTransDetail(ia, transInfo, ELoanDirection.DEBIT, EEntryStatus.FINISH); + internalAccountService.addTransDetail(Constants.PLATFORM_INTERNAL_ACCOUNT_ID, transInfo, + ELoanDirection.DEBIT, EEntryStatus.FINISH); //外部账户 externalAccountService.addTransDetail(payChannel.getPlatformExternalAccountId(), transInfo, ELoanDirection.DEBIT, EEntryStatus.FINISH); diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/InternalAccountServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/InternalAccountServiceImpl.java index 146b9875b..8c12b4410 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/InternalAccountServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/InternalAccountServiceImpl.java @@ -1,31 +1,36 @@ package com.ruoyi.xkt.service.impl; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.NumberUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.SimpleEntity; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.bean.BeanValidators; import com.ruoyi.xkt.domain.InternalAccount; import com.ruoyi.xkt.domain.InternalAccountTransDetail; import com.ruoyi.xkt.dto.finance.TransInfo; -import com.ruoyi.xkt.enums.EAccountStatus; -import com.ruoyi.xkt.enums.EEntryExecuted; -import com.ruoyi.xkt.enums.EEntryStatus; -import com.ruoyi.xkt.enums.ELoanDirection; +import com.ruoyi.xkt.enums.*; import com.ruoyi.xkt.mapper.InternalAccountMapper; import com.ruoyi.xkt.mapper.InternalAccountTransDetailMapper; import com.ruoyi.xkt.service.IInternalAccountService; import io.jsonwebtoken.lang.Assert; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; -import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; /** * @author liangyq * @date 2025-04-08 21:14 */ +@Slf4j @Service public class InternalAccountServiceImpl implements IInternalAccountService { @@ -34,29 +39,19 @@ public class InternalAccountServiceImpl implements IInternalAccountService { @Autowired private InternalAccountTransDetailMapper internalAccountTransDetailMapper; - @Transactional @Override - public InternalAccount getWithLock(Long id) { - return internalAccountMapper.getForUpdate(id); + public InternalAccount getById(Long id) { + Assert.notNull(id); + return internalAccountMapper.selectById(id); } @Transactional @Override - public List listWithLock(Collection ids) { - return internalAccountMapper.listForUpdate(ids); - } - - @Transactional - @Override - public int addTransDetail(InternalAccount internalAccount, TransInfo transInfo, ELoanDirection loanDirection, + public int addTransDetail(Long internalAccountId, TransInfo transInfo, ELoanDirection loanDirection, EEntryStatus entryStatus) { - Assert.notNull(internalAccount, "内部账户不存在"); - if (!BeanValidators.exists(internalAccount)) { - throw new ServiceException("内部账户[" + internalAccount.getId() + "]不存在"); - } - if (!EAccountStatus.NORMAL.getValue().equals(internalAccount.getAccountStatus())) { - throw new ServiceException("内部账户[" + internalAccount.getId() + "]已冻结"); - } + Assert.notNull(internalAccountId); + InternalAccount internalAccount = internalAccountMapper.getForUpdate(internalAccountId); + checkAccountStatus(internalAccount); InternalAccountTransDetail transDetail = new InternalAccountTransDetail(); transDetail.setInternalAccountId(internalAccount.getId()); transDetail.setSrcBillId(transInfo.getSrcBillId()); @@ -73,11 +68,13 @@ public class InternalAccountServiceImpl implements IInternalAccountService { transDetail.setEntryExecuted(EEntryStatus.FINISH == entryStatus ? EEntryExecuted.FINISH.getValue() : EEntryExecuted.WAITING.getValue()); transDetail.setRemark(transInfo.getRemark()); + transDetail.setVersion(0L); + transDetail.setDelFlag(Constants.UNDELETED); switch (loanDirection) { case DEBIT: //借 - if (EEntryExecuted.FINISH.getValue().equals(transDetail.getEntryExecuted())) { - //已执行 + if (EEntryStatus.FINISH.getValue().equals(transDetail.getEntryStatus())) { + //已入账&已执行 //余额 = 余额 + 交易金额 internalAccount.setBalance(internalAccount.getBalance() .add(transDetail.getTransAmount())); @@ -86,7 +83,7 @@ public class InternalAccountServiceImpl implements IInternalAccountService { .add(transDetail.getTransAmount())); //支付中金额不变 } else { - //未执行 + //未入账 //余额不变 //可用余额不变 //支付中金额不变 @@ -94,8 +91,8 @@ public class InternalAccountServiceImpl implements IInternalAccountService { break; case CREDIT: //贷 - if (EEntryExecuted.FINISH.getValue().equals(transDetail.getEntryExecuted())) { - //已执行 + if (EEntryStatus.FINISH.getValue().equals(transDetail.getEntryStatus())) { + //已入账&已执行 //余额 = 余额 - 交易金额 internalAccount.setBalance(internalAccount.getBalance() .subtract(transDetail.getTransAmount())); @@ -104,7 +101,7 @@ public class InternalAccountServiceImpl implements IInternalAccountService { .subtract(transDetail.getTransAmount())); //支付中金额不变 } else { - //未执行 + //未入账 //余额不变 //可用余额 = 可用余额 - 交易金额 internalAccount.setUsableBalance(internalAccount.getUsableBalance() @@ -118,6 +115,102 @@ public class InternalAccountServiceImpl implements IInternalAccountService { throw new ServiceException("未知借贷方向"); } //检查账户余额,不允许出现负数 + checkAccountAmount(internalAccount); + //更新账户余额 + internalAccountMapper.updateById(internalAccount); + //交易明细 + return internalAccountTransDetailMapper.insert(transDetail); + } + + @Transactional + @Override + public void entryTransDetail(Long srcBillId, EFinBillType srcBillType) { + Assert.notNull(srcBillId); + Assert.notNull(srcBillType); + List transDetails = internalAccountTransDetailMapper.selectList(Wrappers + .lambdaQuery(InternalAccountTransDetail.class) + .eq(InternalAccountTransDetail::getSrcBillId, srcBillId) + .eq(InternalAccountTransDetail::getSrcBillType, srcBillType.getValue()) + .eq(SimpleEntity::getDelFlag, Constants.UNDELETED)); + if (CollUtil.isEmpty(transDetails)) { + log.warn("单据没有关联的交易明细:{}{}", srcBillType.getLabel(), srcBillId); + return; + } + List accountIds = transDetails.stream().map(InternalAccountTransDetail::getInternalAccountId).distinct() + .collect(Collectors.toList()); + //获取账户并加锁 + List accounts = internalAccountMapper.listForUpdate(accountIds); + Map accountMap = accounts.stream().collect(Collectors.toMap(SimpleEntity::getId, o -> o)); + //开始入账 + for (InternalAccountTransDetail transDetail : transDetails) { + InternalAccount internalAccount = accountMap.get(transDetail.getInternalAccountId()); + checkAccountStatus(internalAccount); + if (EEntryStatus.WAITING.getValue().equals(transDetail.getEntryStatus())) { + //明细未入账 + transDetail.setEntryStatus(EEntryStatus.FINISH.getValue()); + //不考虑热点账户问题,已入账 => 已执行 + transDetail.setEntryExecuted(EEntryExecuted.FINISH.getValue()); + switch (Objects.requireNonNull(ELoanDirection.of(transDetail.getLoanDirection()))) { + case DEBIT: + //借 + //余额 = 余额 + 交易金额 + internalAccount.setBalance(internalAccount.getBalance() + .add(transDetail.getTransAmount())); + //可用余额 = 可用余额 + 交易金额 + internalAccount.setUsableBalance(internalAccount.getUsableBalance() + .add(transDetail.getTransAmount())); + //支付中金额不变 + break; + case CREDIT: + //贷 + //余额 = 余额 - 交易金额 + internalAccount.setBalance(internalAccount.getBalance() + .subtract(transDetail.getTransAmount())); + //可用余额不变 + //支付中金额 = 支付中金额 - 交易金额 + internalAccount.setPaymentAmount(internalAccount.getPaymentAmount() + .subtract(transDetail.getTransAmount())); + break; + default: + throw new ServiceException("未知借贷方向"); + } + //检查账户余额,不允许出现负数 + checkAccountAmount(internalAccount); + //更新账户余额 + internalAccountMapper.updateById(internalAccount); + //更新交易明细 + int r = internalAccountTransDetailMapper.updateById(transDetail); + if (r == 0) { + throw new ServiceException(Constants.VERSION_LOCK_ERROR_COMMON_MSG); + } + } else { + log.warn("单据重复调用入账方法:{}{}", srcBillType.getLabel(), srcBillId); + } + } + } + + + /** + * 检查账户状态 + * + * @param internalAccount + */ + private void checkAccountStatus(InternalAccount internalAccount) { + Assert.notNull(internalAccount, "账户不存在"); + if (!BeanValidators.exists(internalAccount)) { + throw new ServiceException("账户[" + internalAccount.getId() + "]已删除"); + } + if (!EAccountStatus.NORMAL.getValue().equals(internalAccount.getAccountStatus())) { + throw new ServiceException("账户[" + internalAccount.getId() + "]已冻结"); + } + } + + /** + * 检查账户余额 + * + * @param internalAccount + */ + private void checkAccountAmount(InternalAccount internalAccount) { if (less0(internalAccount.getBalance())) { throw new ServiceException("账户[" + internalAccount.getId() + "]余额不足"); } @@ -127,10 +220,6 @@ public class InternalAccountServiceImpl implements IInternalAccountService { if (less0(internalAccount.getPaymentAmount())) { throw new ServiceException("账户[" + internalAccount.getId() + "]支付中金额异常"); } - //更新账户余额 - internalAccountMapper.updateById(internalAccount); - //交易明细 - return internalAccountTransDetailMapper.insert(transDetail); } /**