feat: 入账逻辑
parent
5b8127d109
commit
8ed8d0fc51
|
|
@ -202,6 +202,8 @@ public class Constants
|
|||
*/
|
||||
public static final Integer ORDER_NUM_1 = 1;
|
||||
|
||||
public static final String VERSION_LOCK_ERROR_COMMON_MSG = "系统繁忙,请稍后再试";
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,4 +73,8 @@ public class ExternalAccountTransDetailDTO {
|
|||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
private Long version;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,4 +77,8 @@ public class InternalAccountTransDetailDTO {
|
|||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
private Long version;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<InternalAccount> listWithLock(Collection<Long> 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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<ExternalAccountTransDetail> 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<Long> accountIds = transDetails.stream().map(ExternalAccountTransDetail::getExternalAccountId).distinct()
|
||||
.collect(Collectors.toList());
|
||||
Assert.notEmpty(accountIds);
|
||||
Map<Long, ExternalAccount> 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() + "]已冻结");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<InternalAccount> listWithLock(Collection<Long> 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<InternalAccountTransDetail> 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<Long> accountIds = transDetails.stream().map(InternalAccountTransDetail::getInternalAccountId).distinct()
|
||||
.collect(Collectors.toList());
|
||||
//获取账户并加锁
|
||||
List<InternalAccount> accounts = internalAccountMapper.listForUpdate(accountIds);
|
||||
Map<Long, InternalAccount> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue