feat: 记账逻辑
parent
b41e6c5297
commit
3b2d3cdacb
|
|
@ -192,6 +192,10 @@ public class Constants
|
|||
* 平台内部账户ID
|
||||
*/
|
||||
public static final Long PLATFORM_INTERNAL_ACCOUNT_ID = 1L;
|
||||
/**
|
||||
* 平台外部账户ID-支付宝账户
|
||||
*/
|
||||
public static final Long PLATFORM_ALIPAY_EXTERNAL_ACCOUNT_ID = 1L;
|
||||
|
||||
/**
|
||||
* 排序值1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
package com.ruoyi.xkt.dto.finance;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-04-09 23:47
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class TransInfo {
|
||||
// /**
|
||||
// * 账户ID
|
||||
// */
|
||||
// private Long accountId;
|
||||
/**
|
||||
* 来源单据ID
|
||||
*/
|
||||
private Long srcBillId;
|
||||
/**
|
||||
* 来源单据类型
|
||||
*
|
||||
* @see com.ruoyi.xkt.enums.EFinBillType
|
||||
*/
|
||||
private Integer srcBillType;
|
||||
// /**
|
||||
// * 借贷方向
|
||||
// *
|
||||
// * @see com.ruoyi.xkt.enums.ELoanDirection
|
||||
// */
|
||||
// private Integer loanDirection;
|
||||
/**
|
||||
* 交易金额
|
||||
*/
|
||||
private BigDecimal transAmount;
|
||||
/**
|
||||
* 交易时间
|
||||
*/
|
||||
private Date transTime;
|
||||
/**
|
||||
* 经办人ID
|
||||
*/
|
||||
private Long handlerId;
|
||||
// /**
|
||||
// * 入账状态
|
||||
// *
|
||||
// * @see com.ruoyi.xkt.enums.EEntryStatus
|
||||
// */
|
||||
// private Integer entryStatus;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.ruoyi.xkt.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-04-02 23:42
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum EAccountStatus {
|
||||
|
||||
NORMAL(1, "正常"),
|
||||
FREEZE(2, "冻结");
|
||||
|
||||
private final Integer value;
|
||||
private final String label;
|
||||
|
||||
public static EAccountStatus of(Integer value) {
|
||||
for (EAccountStatus e : EAccountStatus.values()) {
|
||||
if (e.getValue().equals(value)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.ruoyi.xkt.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-04-02 23:42
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum EEntryExecuted {
|
||||
|
||||
FINISH(1, "已执行"),
|
||||
WAITING(2, "未执行");
|
||||
|
||||
private final Integer value;
|
||||
private final String label;
|
||||
|
||||
public static EEntryExecuted of(Integer value) {
|
||||
for (EEntryExecuted e : EEntryExecuted.values()) {
|
||||
if (e.getValue().equals(value)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package com.ruoyi.xkt.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-04-02 23:42
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum EEntryStatus {
|
||||
|
||||
FINISH(1, "已入账"),
|
||||
WAITING(2, "待入账");
|
||||
|
||||
private final Integer value;
|
||||
private final String label;
|
||||
|
||||
public static EEntryStatus of(Integer value) {
|
||||
for (EEntryStatus e : EEntryStatus.values()) {
|
||||
if (e.getValue().equals(value)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.ruoyi.xkt.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-04-02 23:42
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ELoanDirection {
|
||||
|
||||
DEBIT(1, "借", "D"),
|
||||
CREDIT(2, "贷", "C");
|
||||
|
||||
private final Integer value;
|
||||
private final String label;
|
||||
private final String code;
|
||||
|
||||
public static ELoanDirection of(Integer value) {
|
||||
for (ELoanDirection e : ELoanDirection.values()) {
|
||||
if (e.getValue().equals(value)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.ruoyi.xkt.enums;
|
||||
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
|
|
@ -11,10 +12,12 @@ import lombok.Getter;
|
|||
@AllArgsConstructor
|
||||
public enum EPayChannel {
|
||||
|
||||
ALI_PAY(1, "支付宝");
|
||||
ALI_PAY(1, "支付宝", "ALIPAY_", Constants.PLATFORM_ALIPAY_EXTERNAL_ACCOUNT_ID);
|
||||
|
||||
private final Integer value;
|
||||
private final String label;
|
||||
private final String prefix;
|
||||
private final Long platformExternalAccountId;
|
||||
|
||||
public static EPayChannel of(Integer value) {
|
||||
for (EPayChannel e : EPayChannel.values()) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
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.ELoanDirection;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-04-08 21:14
|
||||
*/
|
||||
public interface IExternalAccountService {
|
||||
/**
|
||||
* 通过ID获取外部账户
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
ExternalAccount getById(Long id);
|
||||
|
||||
/**
|
||||
* 添加交易明细
|
||||
*
|
||||
* @param externalAccountId
|
||||
* @param transInfo
|
||||
* @param loanDirection
|
||||
* @param entryStatus
|
||||
* @return
|
||||
*/
|
||||
int addTransDetail(Long externalAccountId, TransInfo transInfo, ELoanDirection loanDirection,
|
||||
EEntryStatus entryStatus);
|
||||
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.ruoyi.xkt.service;
|
|||
|
||||
import com.ruoyi.xkt.dto.finance.FinanceBillInfo;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderInfo;
|
||||
import com.ruoyi.xkt.enums.EPayChannel;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
|
|
@ -12,8 +13,9 @@ public interface IFinanceBillService {
|
|||
* 根据订单创建收款单
|
||||
*
|
||||
* @param orderInfo
|
||||
* @param srcId
|
||||
* @param payId
|
||||
* @param payChannel
|
||||
* @return
|
||||
*/
|
||||
FinanceBillInfo createCollectionBillAfterOrderPaid(StoreOrderInfo orderInfo, String srcId);
|
||||
FinanceBillInfo createCollectionBillAfterOrderPaid(StoreOrderInfo orderInfo, Long payId, EPayChannel payChannel);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
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.ELoanDirection;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
|
@ -27,4 +30,18 @@ public interface IInternalAccountService {
|
|||
*/
|
||||
List<InternalAccount> listWithLock(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 添加交易明细
|
||||
* 余额会根据明细更新
|
||||
* 调用方法时入参账户必须处于加锁状态!
|
||||
*
|
||||
* @param internalAccount
|
||||
* @param transInfo
|
||||
* @param loanDirection
|
||||
* @param entryStatus
|
||||
* @return
|
||||
*/
|
||||
int addTransDetail(InternalAccount internalAccount, TransInfo transInfo, ELoanDirection loanDirection,
|
||||
EEntryStatus entryStatus);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
package com.ruoyi.xkt.service.impl;
|
||||
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.bean.BeanValidators;
|
||||
import com.ruoyi.xkt.domain.ExternalAccount;
|
||||
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.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 org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-04-08 21:14
|
||||
*/
|
||||
@Service
|
||||
public class ExternalAccountServiceImpl implements IExternalAccountService {
|
||||
|
||||
@Autowired
|
||||
private ExternalAccountMapper externalAccountMapper;
|
||||
@Autowired
|
||||
private ExternalAccountTransDetailMapper externalAccountTransDetailMapper;
|
||||
|
||||
@Override
|
||||
public ExternalAccount getById(Long id) {
|
||||
Assert.notNull(id);
|
||||
return externalAccountMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@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 + "]已冻结");
|
||||
}
|
||||
ExternalAccountTransDetail transDetail = new ExternalAccountTransDetail();
|
||||
transDetail.setExternalAccountId(externalAccountId);
|
||||
transDetail.setSrcBillId(transInfo.getSrcBillId());
|
||||
transDetail.setSrcBillType(transInfo.getSrcBillType());
|
||||
transDetail.setLoanDirection(loanDirection.getValue());
|
||||
if (NumberUtil.isLess(transInfo.getTransAmount(), BigDecimal.ZERO)) {
|
||||
throw new ServiceException("交易金额异常");
|
||||
}
|
||||
transDetail.setTransAmount(transInfo.getTransAmount());
|
||||
transDetail.setTransTime(transInfo.getTransTime());
|
||||
transDetail.setHandlerId(transInfo.getHandlerId());
|
||||
transDetail.setEntryStatus(entryStatus.getValue());
|
||||
transDetail.setRemark(transInfo.getRemark());
|
||||
transDetail.setDelFlag(Constants.UNDELETED);
|
||||
return externalAccountTransDetailMapper.insert(transDetail);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,17 +1,29 @@
|
|||
package com.ruoyi.xkt.service.impl;
|
||||
|
||||
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;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderInfo;
|
||||
import com.ruoyi.xkt.enums.*;
|
||||
import com.ruoyi.xkt.mapper.FinanceBillDetailMapper;
|
||||
import com.ruoyi.xkt.mapper.FinanceBillMapper;
|
||||
import com.ruoyi.xkt.service.IExternalAccountService;
|
||||
import com.ruoyi.xkt.service.IFinanceBillService;
|
||||
import com.ruoyi.xkt.service.IInternalAccountService;
|
||||
import io.jsonwebtoken.lang.Assert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-04-08 21:14
|
||||
|
|
@ -25,12 +37,74 @@ public class FinanceBillServiceImpl implements IFinanceBillService {
|
|||
private FinanceBillDetailMapper financeBillDetailMapper;
|
||||
@Autowired
|
||||
private IInternalAccountService internalAccountService;
|
||||
@Autowired
|
||||
private IExternalAccountService externalAccountService;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public FinanceBillInfo createCollectionBillAfterOrderPaid(StoreOrderInfo orderInfo, String srcId) {
|
||||
//获取平台账户并加锁
|
||||
InternalAccount ca = internalAccountService.getWithLock(Constants.PLATFORM_INTERNAL_ACCOUNT_ID);
|
||||
return null;
|
||||
public FinanceBillInfo createCollectionBillAfterOrderPaid(StoreOrderInfo orderInfo, Long payId,
|
||||
EPayChannel payChannel) {
|
||||
Assert.notNull(orderInfo);
|
||||
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());
|
||||
//直接标记成功
|
||||
bill.setBillStatus(EFinBillStatus.SUCCESS.getValue());
|
||||
bill.setSrcType(EFinBillSrcType.STORE_ORDER_PAID.getValue());
|
||||
bill.setSrcId(payId);
|
||||
bill.setRelType(EFinBillRelType.STORE_ORDER.getValue());
|
||||
bill.setRelId(orderInfo.getOrder().getId());
|
||||
//支付渠道+回调ID构成业务唯一键,防止重复创建收款单
|
||||
String businessUniqueKey = payChannel.getPrefix() + payId;
|
||||
bill.setBusinessUniqueKey(businessUniqueKey);
|
||||
bill.setInputInternalAccountId(ia.getId());
|
||||
bill.setInputExternalAccountId(payChannel.getPlatformExternalAccountId());
|
||||
bill.setBusinessAmount(orderInfo.getOrder().getTotalAmount());
|
||||
bill.setTransAmount(orderInfo.getOrder().getRealTotalAmount());
|
||||
bill.setVersion(0L);
|
||||
bill.setDelFlag(Constants.UNDELETED);
|
||||
financeBillMapper.insert(bill);
|
||||
List<FinanceBillDetail> billDetails = new ArrayList<>(orderInfo.getOrderDetails().size());
|
||||
for (StoreOrderDetail orderDetail : orderInfo.getOrderDetails()) {
|
||||
FinanceBillDetail billDetail = new FinanceBillDetail();
|
||||
billDetail.setFinanceBillId(bill.getId());
|
||||
billDetail.setRelType(EFinBillDetailRelType.STORE_ORDER_DETAIL.getValue());
|
||||
billDetail.setRelId(orderDetail.getId());
|
||||
billDetail.setBusinessAmount(orderDetail.getTotalAmount());
|
||||
billDetail.setTransAmount(orderDetail.getRealTotalAmount());
|
||||
billDetail.setDelFlag(Constants.UNDELETED);
|
||||
financeBillDetailMapper.insert(billDetail);
|
||||
billDetails.add(billDetail);
|
||||
}
|
||||
TransInfo transInfo = TransInfo.builder()
|
||||
.srcBillId(bill.getId())
|
||||
.srcBillType(bill.getBillType())
|
||||
.transAmount(bill.getTransAmount())
|
||||
.transTime(new Date())
|
||||
.handlerId(null)
|
||||
.remark("订单支付完成")
|
||||
.build();
|
||||
//内部账户
|
||||
internalAccountService.addTransDetail(ia, transInfo, ELoanDirection.DEBIT, EEntryStatus.FINISH);
|
||||
//外部账户
|
||||
externalAccountService.addTransDetail(payChannel.getPlatformExternalAccountId(), transInfo,
|
||||
ELoanDirection.DEBIT, EEntryStatus.FINISH);
|
||||
return new FinanceBillInfo(bill, billDetails);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 生成单号
|
||||
*
|
||||
* @param billType
|
||||
* @return
|
||||
*/
|
||||
public String generateBillNo(EFinBillType billType) {
|
||||
//未确定规则,暂时用UUID代替
|
||||
return IdUtil.simpleUUID();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,24 @@
|
|||
package com.ruoyi.xkt.service.impl;
|
||||
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
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.mapper.InternalAccountMapper;
|
||||
import com.ruoyi.xkt.mapper.InternalAccountTransDetailMapper;
|
||||
import com.ruoyi.xkt.service.IInternalAccountService;
|
||||
import io.jsonwebtoken.lang.Assert;
|
||||
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;
|
||||
|
||||
|
|
@ -34,4 +45,101 @@ public class InternalAccountServiceImpl implements IInternalAccountService {
|
|||
public List<InternalAccount> listWithLock(Collection<Long> ids) {
|
||||
return internalAccountMapper.listForUpdate(ids);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public int addTransDetail(InternalAccount internalAccount, 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() + "]已冻结");
|
||||
}
|
||||
InternalAccountTransDetail transDetail = new InternalAccountTransDetail();
|
||||
transDetail.setInternalAccountId(internalAccount.getId());
|
||||
transDetail.setSrcBillId(transInfo.getSrcBillId());
|
||||
transDetail.setSrcBillType(transInfo.getSrcBillType());
|
||||
transDetail.setLoanDirection(loanDirection.getValue());
|
||||
if (less0(transInfo.getTransAmount())) {
|
||||
throw new ServiceException("交易金额异常");
|
||||
}
|
||||
transDetail.setTransAmount(transInfo.getTransAmount());
|
||||
transDetail.setTransTime(transInfo.getTransTime());
|
||||
transDetail.setHandlerId(transInfo.getHandlerId());
|
||||
transDetail.setEntryStatus(entryStatus.getValue());
|
||||
//不考虑热点账户问题,已入账 => 已执行
|
||||
transDetail.setEntryExecuted(EEntryStatus.FINISH == entryStatus ?
|
||||
EEntryExecuted.FINISH.getValue() : EEntryExecuted.WAITING.getValue());
|
||||
transDetail.setRemark(transInfo.getRemark());
|
||||
switch (loanDirection) {
|
||||
case DEBIT:
|
||||
//借
|
||||
if (EEntryExecuted.FINISH.getValue().equals(transDetail.getEntryExecuted())) {
|
||||
//已执行
|
||||
//余额 = 余额 + 交易金额
|
||||
internalAccount.setBalance(internalAccount.getBalance()
|
||||
.add(transDetail.getTransAmount()));
|
||||
//可用余额 = 可用余额 + 交易金额
|
||||
internalAccount.setUsableBalance(internalAccount.getUsableBalance()
|
||||
.add(transDetail.getTransAmount()));
|
||||
//支付中金额不变
|
||||
} else {
|
||||
//未执行
|
||||
//余额不变
|
||||
//可用余额不变
|
||||
//支付中金额不变
|
||||
}
|
||||
break;
|
||||
case CREDIT:
|
||||
//贷
|
||||
if (EEntryExecuted.FINISH.getValue().equals(transDetail.getEntryExecuted())) {
|
||||
//已执行
|
||||
//余额 = 余额 - 交易金额
|
||||
internalAccount.setBalance(internalAccount.getBalance()
|
||||
.subtract(transDetail.getTransAmount()));
|
||||
//可用余额 = 可用余额 - 交易金额
|
||||
internalAccount.setUsableBalance(internalAccount.getUsableBalance()
|
||||
.subtract(transDetail.getTransAmount()));
|
||||
//支付中金额不变
|
||||
} else {
|
||||
//未执行
|
||||
//余额不变
|
||||
//可用余额 = 可用余额 - 交易金额
|
||||
internalAccount.setUsableBalance(internalAccount.getUsableBalance()
|
||||
.subtract(transDetail.getTransAmount()));
|
||||
//支付中金额 = 支付中金额 + 交易金额
|
||||
internalAccount.setPaymentAmount(internalAccount.getPaymentAmount()
|
||||
.add(transDetail.getTransAmount()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ServiceException("未知借贷方向");
|
||||
}
|
||||
//检查账户余额,不允许出现负数
|
||||
if (less0(internalAccount.getBalance())) {
|
||||
throw new ServiceException("账户[" + internalAccount.getId() + "]余额不足");
|
||||
}
|
||||
if (less0(internalAccount.getUsableBalance())) {
|
||||
throw new ServiceException("账户[" + internalAccount.getId() + "]可用余额不足");
|
||||
}
|
||||
if (less0(internalAccount.getPaymentAmount())) {
|
||||
throw new ServiceException("账户[" + internalAccount.getId() + "]支付中金额异常");
|
||||
}
|
||||
//更新账户余额
|
||||
internalAccountMapper.updateById(internalAccount);
|
||||
//交易明细
|
||||
return internalAccountTransDetailMapper.insert(transDetail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断数字是否小于0
|
||||
*
|
||||
* @param num
|
||||
* @return
|
||||
*/
|
||||
private boolean less0(BigDecimal num) {
|
||||
return NumberUtil.isLess(num, BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue