From d3925e729d59db76c2674b28c894479a08a7f355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=81=E5=AE=87=E5=A5=87?= Date: Thu, 21 Aug 2025 15:01:56 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xkt/service/IInternalAccountService.java | 21 +++++++++++++ .../service/impl/FinanceBillServiceImpl.java | 31 +++++++++++++------ .../impl/InternalAccountServiceImpl.java | 15 +++++++++ 3 files changed, 58 insertions(+), 9 deletions(-) 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 d987ae1fb..25e41a83b 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IInternalAccountService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IInternalAccountService.java @@ -11,6 +11,7 @@ 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; /** @@ -26,6 +27,14 @@ public interface IInternalAccountService { */ InternalAccount getById(Long id); + /** + * 通过ids获取内部账户(锁) + * + * @param ids + * @return + */ + List listByIdsForUpdate(Collection ids); + /** * 获取内部账户 * @@ -56,6 +65,18 @@ public interface IInternalAccountService { int addTransDetail(Long internalAccountId, TransInfo transInfo, ELoanDirection loanDirection, EEntryStatus entryStatus); + /** + * 添加交易明细 + * + * @param internalAccount + * @param transInfo + * @param loanDirection + * @param entryStatus + * @return + */ + int addTransDetail(InternalAccount internalAccount, TransInfo transInfo, ELoanDirection loanDirection, + EEntryStatus entryStatus); + /** * 交易明细入账 * 根据来源单据获取待入账的交易明细执行入账 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 463e797ef..ede0ebb1f 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 @@ -6,6 +6,7 @@ import cn.hutool.core.collection.ListUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; import cn.hutool.core.text.CharSequenceUtil; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.NumberUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -125,7 +126,6 @@ public class FinanceBillServiceImpl implements IFinanceBillService { @Transactional(rollbackFor = Exception.class) @Override public FinanceBillExt createOrderCompletedTransferBill(StoreOrderExt orderExt) { - //TODO 需要先批量获取内部账户避免出现死锁? Assert.notNull(orderExt); FinanceBill bill = new FinanceBill(); bill.setBillNo(generateBillNo(EFinBillType.TRANSFER)); @@ -172,9 +172,11 @@ public class FinanceBillServiceImpl implements IFinanceBillService { .remark("订单完成") .build(); //内部账户 - internalAccountService.addTransDetail(Constants.PLATFORM_INTERNAL_ACCOUNT_ID, transInfo, + Map accountMap = getInternalAccountMapForUpdate(Constants.PLATFORM_INTERNAL_ACCOUNT_ID, + inputInternalAccountId); + internalAccountService.addTransDetail(accountMap.get(Constants.PLATFORM_INTERNAL_ACCOUNT_ID), transInfo, ELoanDirection.CREDIT, EEntryStatus.FINISH); - internalAccountService.addTransDetail(inputInternalAccountId, transInfo, + internalAccountService.addTransDetail(accountMap.get(inputInternalAccountId), transInfo, ELoanDirection.DEBIT, EEntryStatus.FINISH); return new FinanceBillExt(bill, billDetails); } @@ -183,7 +185,6 @@ public class FinanceBillServiceImpl implements IFinanceBillService { @Override public FinanceBillExt createOrderCompletedTransferBill(StoreOrderExt orderExt, List afterSaleOrderExts) { - //TODO 需要先批量获取内部账户避免出现死锁? Assert.notNull(orderExt); FinanceBill bill = new FinanceBill(); bill.setBillNo(generateBillNo(EFinBillType.TRANSFER)); @@ -294,9 +295,11 @@ public class FinanceBillServiceImpl implements IFinanceBillService { .remark("订单完成") .build(); //内部账户 - internalAccountService.addTransDetail(Constants.PLATFORM_INTERNAL_ACCOUNT_ID, transInfo, + Map accountMap = getInternalAccountMapForUpdate(Constants.PLATFORM_INTERNAL_ACCOUNT_ID, + inputInternalAccountId); + internalAccountService.addTransDetail(accountMap.get(Constants.PLATFORM_INTERNAL_ACCOUNT_ID), transInfo, ELoanDirection.CREDIT, EEntryStatus.FINISH); - internalAccountService.addTransDetail(inputInternalAccountId, transInfo, + internalAccountService.addTransDetail(accountMap.get(inputInternalAccountId), transInfo, ELoanDirection.DEBIT, EEntryStatus.FINISH); return new FinanceBillExt(bill, billDetails); } @@ -541,7 +544,6 @@ public class FinanceBillServiceImpl implements IFinanceBillService { public FinanceBillExt createInternalTransferBill(Long inputAccountId, Long outputAccountId, BigDecimal amount, Integer srcType, Long srcId, Integer relType, Long relId, String remark) { - //TODO 需要先批量获取内部账户避免出现死锁? Assert.notNull(inputAccountId); Assert.notNull(outputAccountId); Assert.notNull(amount); @@ -574,9 +576,11 @@ public class FinanceBillServiceImpl implements IFinanceBillService { .remark(remark) .build(); //内部账户 - internalAccountService.addTransDetail(outputAccountId, transInfo, + Map accountMap = getInternalAccountMapForUpdate(outputAccountId, + inputAccountId); + internalAccountService.addTransDetail(accountMap.get(outputAccountId), transInfo, ELoanDirection.CREDIT, EEntryStatus.FINISH); - internalAccountService.addTransDetail(inputAccountId, transInfo, + internalAccountService.addTransDetail(accountMap.get(inputAccountId), transInfo, ELoanDirection.DEBIT, EEntryStatus.FINISH); return new FinanceBillExt(bill, ListUtil.empty()); } @@ -607,6 +611,15 @@ public class FinanceBillServiceImpl implements IFinanceBillService { return IdUtil.simpleUUID(); } + private Map getInternalAccountMapForUpdate(Long... ids) { + if (ArrayUtil.isEmpty(ids)) { + return MapUtil.empty(); + } + return internalAccountService.listByIdsForUpdate(CollUtil.toList(ids)) + .stream() + .collect(Collectors.toMap(SimpleEntity::getId, Function.identity())); + } + private T prepareInsert(T obj) { String username = SecurityUtils.getUsernameSafe(); obj.setCreateBy(username); 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 8ab11337f..4fa73fd29 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 @@ -26,6 +26,7 @@ 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; @@ -50,6 +51,13 @@ public class InternalAccountServiceImpl implements IInternalAccountService { return internalAccountMapper.selectById(id); } + @Transactional(rollbackFor = Exception.class) + @Override + public List listByIdsForUpdate(Collection ids) { + Assert.notEmpty(ids); + return internalAccountMapper.listForUpdate(ids); + } + @Override public InternalAccount getAccount(Long ownerId, EAccountOwnerType ownerType) { Assert.notNull(ownerId); @@ -80,6 +88,13 @@ public class InternalAccountServiceImpl implements IInternalAccountService { EEntryStatus entryStatus) { Assert.notNull(internalAccountId); InternalAccount internalAccount = internalAccountMapper.getForUpdate(internalAccountId); + return addTransDetail(internalAccount, transInfo, loanDirection, entryStatus); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public int addTransDetail(InternalAccount internalAccount, TransInfo transInfo, ELoanDirection loanDirection, + EEntryStatus entryStatus) { checkAccountStatus(internalAccount); InternalAccountTransDetail transDetail = new InternalAccountTransDetail(); transDetail.setInternalAccountId(internalAccount.getId());