From c1bbda9f9a3f95c6dba3411a7f427836568a64f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=A5=8E=E5=85=B4?= <2220574228@qq.com> Date: Fri, 11 Sep 2026 15:33:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=92=A4=E9=94=80=E4=BB=98=E6=AC=BE=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E4=BF=AE=E6=94=B9;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ReceiptManageApplicationService.java | 7 ++ .../service/BillManageDomainService.java | 53 +++++------ .../service/ReceiptManageDomainService.java | 87 ++++++++++++++----- .../facadeApi/ReceiptManageApi.java | 13 +-- 4 files changed, 100 insertions(+), 60 deletions(-) diff --git a/mhd_bms/src/main/java/com/mhd/bms/application/server/receiptManage/ReceiptManageApplicationService.java b/mhd_bms/src/main/java/com/mhd/bms/application/server/receiptManage/ReceiptManageApplicationService.java index ab4a85b5a..b098b3443 100644 --- a/mhd_bms/src/main/java/com/mhd/bms/application/server/receiptManage/ReceiptManageApplicationService.java +++ b/mhd_bms/src/main/java/com/mhd/bms/application/server/receiptManage/ReceiptManageApplicationService.java @@ -159,6 +159,13 @@ public class ReceiptManageApplicationService { return receiptManageDomainService.cancelCollection(receiptManageDO); } + /** + * 撤销收款-查询账单涉及的收款单id(用于加锁,防止并发撤销时收款单金额重算冲突) + */ + public Set queryCancelCollectionReceiptManageIds(String billManageIds) { + return receiptManageDomainService.queryReceiptManageIdsByBillManageIds(billManageIds); + } + /** * 退款 */ diff --git a/mhd_bms/src/main/java/com/mhd/bms/domain/billManage/service/BillManageDomainService.java b/mhd_bms/src/main/java/com/mhd/bms/domain/billManage/service/BillManageDomainService.java index ccfc7dc66..e45e9b25e 100644 --- a/mhd_bms/src/main/java/com/mhd/bms/domain/billManage/service/BillManageDomainService.java +++ b/mhd_bms/src/main/java/com/mhd/bms/domain/billManage/service/BillManageDomainService.java @@ -710,62 +710,49 @@ public class BillManageDomainService { /** - * 撤销收款:恢复账单信息并保存撤销收款操作日志 + * 撤销收款:账单恢复为收款为0状态并保存撤销收款操作日志 */ public Boolean cancelCollectionInfo(List receiptDetails) { LoginUser loginUser = SecurityUtils.getLoginUser(); if (ObjectUtil.isNull(loginUser)) { throw new DigitalLogisticsException(UserError.TIMEOUT); } - List billManageIds = receiptDetails.stream().map(ReceiptDetail::getBillManageId).collect(Collectors.toList()); + //按账单分组收款明细(一个账单可能对应多个收款单) + Map> billDetailMap = receiptDetails.stream().collect(Collectors.groupingBy(ReceiptDetail::getBillManageId)); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.in(BillManage::getBillManageId,billManageIds); + queryWrapper.in(BillManage::getBillManageId,billDetailMap.keySet()); List billManageList = billManageService.list(queryWrapper); if(billManageList == null || billManageList.size()==0){ throw new ServiceException("账单信息未找到"); } List billManageListSave = new ArrayList<>(); List billOperationLogSave = new ArrayList<>(); - for (ReceiptDetail receiptDetail : receiptDetails) { - BillManage billManage = billManageList.stream().filter(billManage1 -> ObjectUtil.equal(billManage1.getBillManageId(),receiptDetail.getBillManageId())).findAny().orElse(null); - if(null == billManage){ - throw new ServiceException("账单" + receiptDetail.getBillNumber() + "信息未找到,请刷新后重试"); - } - BigDecimal collectedDiscount = receiptDetail.getCollectedDiscount() == null ? BigDecimal.ZERO : receiptDetail.getCollectedDiscount(); - BigDecimal collectedAmount = receiptDetail.getCollectedAmount() == null ? BigDecimal.ZERO : receiptDetail.getCollectedAmount(); - BigDecimal all = collectedAmount.add(collectedDiscount); - BigDecimal billAmountSettlement = billManage.getBillAmountSettlement() == null ? BigDecimal.ZERO : billManage.getBillAmountSettlement(); - //校验已收金额是否足够撤销,避免出现负数 - if (billAmountSettlement.compareTo(all) < 0) { - throw new ServiceException("账单" + billManage.getBillNumber() + "已收金额小于待撤销金额,无法撤销收款,请刷新后重试"); + for (BillManage billManage : billManageList) { + List receiptDetailList = billDetailMap.get(billManage.getBillManageId()); + if(null == receiptDetailList || receiptDetailList.size() == 0){ + continue; } BillManage billManageSave = new BillManage(); billManageSave.setBillManageId(billManage.getBillManageId()); - //扣减已收金额,重新计算未收金额 - billManageSave.setBillAmountSettlement(billAmountSettlement.subtract(all)); - billManageSave.setBillAmountUnsettled(billManage.getBillAmount().subtract(billManageSave.getBillAmountSettlement())); - //扣减实收金额 - BigDecimal actualReceivedAmount = billManage.getActualReceivedAmount() == null ? BigDecimal.ZERO : billManage.getActualReceivedAmount(); - billManageSave.setActualReceivedAmount(actualReceivedAmount.subtract(collectedAmount)); - //扣减结算单优惠金额 - BigDecimal settlementDiscountsAmount = billManage.getSettlementDiscountsAmount() == null ? BigDecimal.ZERO : billManage.getSettlementDiscountsAmount(); - billManageSave.setSettlementDiscountsAmount(settlementDiscountsAmount.subtract(collectedDiscount)); - //恢复账单状态:已收金额为0回到未收款,未收金额为0为已收款,否则为部分收款 - if (billManageSave.getBillAmountSettlement().compareTo(BigDecimal.ZERO) == 0) { - billManageSave.setBillState(3); - } else if (billManageSave.getBillAmountUnsettled().compareTo(BigDecimal.ZERO) == 0) { - billManageSave.setBillState(5); - } else { - billManageSave.setBillState(4); - } + //账单恢复为收款为0状态 + billManageSave.setBillAmountSettlement(BigDecimal.ZERO); + billManageSave.setBillAmountUnsettled(billManage.getBillAmount()); + billManageSave.setActualReceivedAmount(BigDecimal.ZERO); + billManageSave.setSettlementDiscountsAmount(BigDecimal.ZERO); + billManageSave.setBillState(3); billManageSave.setUpdateBy(loginUser.getUserPo().getUserId()); billManageSave.setUpdateByName(loginUser.getUserPo().getUserName()); billManageSave.setUpdateTime(new Date()); billManageListSave.add(billManageSave); + //汇总该账单本次撤销的收款金额与收款单号 + BigDecimal collectedDiscount = receiptDetailList.stream().map(info -> info.getCollectedDiscount() == null ? BigDecimal.ZERO : info.getCollectedDiscount()).reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal collectedAmount = receiptDetailList.stream().map(info -> info.getCollectedAmount() == null ? BigDecimal.ZERO : info.getCollectedAmount()).reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal all = collectedAmount.add(collectedDiscount); + String collectionNums = receiptDetailList.stream().map(ReceiptDetail::getCollectionNum).filter(StringUtils::isNotEmpty).distinct().collect(Collectors.joining(",")); //保存账单操作记录 BillOperationLog billOperationLog = new BillOperationLog(); billOperationLog.setBillManageId(billManage.getBillManageId()); - billOperationLog.setOperationInfo(StringUtils.format(BillLogsConstants.cancel_collection_bill_text,receiptDetail.getCollectionNum(),all,collectedAmount,collectedDiscount)); + billOperationLog.setOperationInfo(StringUtils.format(BillLogsConstants.cancel_collection_bill_text,collectionNums,all,collectedAmount,collectedDiscount)); billOperationLog.setOperationType(12); billOperationLog.setDelFlag(1); billOperationLogSave.add(billOperationLog); diff --git a/mhd_bms/src/main/java/com/mhd/bms/domain/receiptManage/service/ReceiptManageDomainService.java b/mhd_bms/src/main/java/com/mhd/bms/domain/receiptManage/service/ReceiptManageDomainService.java index de0f85653..80a695289 100644 --- a/mhd_bms/src/main/java/com/mhd/bms/domain/receiptManage/service/ReceiptManageDomainService.java +++ b/mhd_bms/src/main/java/com/mhd/bms/domain/receiptManage/service/ReceiptManageDomainService.java @@ -42,7 +42,9 @@ import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -308,57 +310,77 @@ public class ReceiptManageDomainService { if (ObjectUtil.isNull(loginUser)) { throw new DigitalLogisticsException(UserError.TIMEOUT); } - if (null == receiptManageDO.getReceiptManageId()) { - throw new ServiceException("收款单id不能为空"); - } if (StringUtils.isEmpty(receiptManageDO.getBillManageIds())) { throw new ServiceException("撤销账单不能为空"); } - //查询收款单信息 - ReceiptManage receiptManage = receiptManageService.getById(receiptManageDO.getReceiptManageId()); - if (null == receiptManage || ObjectUtil.equal(receiptManage.getDelFlag(), 2)) { - throw new ServiceException("收款单信息未找到或已撤销,请刷新后重试"); - } - if (ObjectUtil.equal(receiptManage.getPaymentStatus(), 2)) { - throw new ServiceException("该收款单已退款,无法撤销收款"); - } - //查询待撤销账单对应的收款明细 Set billManageIdSet = Stream.of(receiptManageDO.getBillManageIds().split(",")).filter(StringUtils::isNotEmpty).map(String::trim).map(Long::valueOf).collect(Collectors.toSet()); + if (billManageIdSet.size() == 0) { + throw new ServiceException("撤销账单不能为空"); + } + //查询账单信息 + LambdaQueryWrapper queryWrapperBill = new LambdaQueryWrapper<>(); + queryWrapperBill.in(BillManage::getBillManageId, billManageIdSet); + queryWrapperBill.eq(BillManage::getDelFlag, 1); + List billManageList = billManageDomainService.queryListLambda(queryWrapperBill); + if (null == billManageList || billManageList.size() == 0) { + throw new ServiceException("账单信息未找到"); + } + if (billManageList.size() != billManageIdSet.size()) { + throw new ServiceException("部分账单信息未找到,请刷新后重试"); + } + //查询账单的全部有效收款明细(一个账单可能对应多个收款单) LambdaQueryWrapper queryWrapperDetail = new LambdaQueryWrapper<>(); - queryWrapperDetail.eq(ReceiptDetail::getReceiptManageId, receiptManageDO.getReceiptManageId()); queryWrapperDetail.in(ReceiptDetail::getBillManageId, billManageIdSet); queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1); List receiptDetails = receiptDetailDomainService.queryListByLambda(queryWrapperDetail); if (null == receiptDetails || receiptDetails.size() == 0) { throw new ServiceException("账单收款记录不存在或已撤销,请刷新后重试"); } - if (receiptDetails.size() != billManageIdSet.size()) { - throw new ServiceException("部分账单收款记录不存在或已撤销,请刷新后重试"); + //校验每个账单都有收款记录 + Map> billDetailMap = receiptDetails.stream().collect(Collectors.groupingBy(ReceiptDetail::getBillManageId)); + for (BillManage billManage : billManageList) { + if (!billDetailMap.containsKey(billManage.getBillManageId())) { + throw new ServiceException("账单" + billManage.getBillNumber() + "收款记录不存在或已撤销,请刷新后重试"); + } } - //恢复账单信息并保存撤销收款操作日志 + //校验收款单退款状态,已退款的收款单不能撤销收款 + Set receiptManageIdSet = receiptDetails.stream().map(ReceiptDetail::getReceiptManageId).collect(Collectors.toSet()); + LambdaQueryWrapper queryWrapperManage = new LambdaQueryWrapper<>(); + queryWrapperManage.in(ReceiptManage::getReceiptManageId, receiptManageIdSet); + List receiptManageList = receiptManageService.list(queryWrapperManage); + if (null != receiptManageList) { + ReceiptManage refundManage = receiptManageList.stream().filter(info -> ObjectUtil.equal(info.getPaymentStatus(), 2)).findAny().orElse(null); + if (null != refundManage) { + throw new ServiceException("收款单" + refundManage.getCollectionNum() + "已退款,无法撤销收款"); + } + } + //账单恢复为收款为0状态并保存撤销收款操作日志 Boolean flagTwo = billManageDomainService.cancelCollectionInfo(receiptDetails); //逻辑删除收款明细 Boolean flag = receiptDetailDomainService.cancelCollectionDetails(receiptDetails); - //重新计算收款单金额,收款明细已全部撤销时逻辑删除收款单 - Boolean flagThree = updateReceiptManageByCancel(receiptManage); + //按剩余明细重新计算涉及的收款单金额,明细已全部撤销时逻辑删除收款单 + Boolean flagThree = true; + for (Long receiptManageId : receiptManageIdSet) { + flagThree = updateReceiptManageByCancel(receiptManageId) && flagThree; + } return flag && flagTwo && flagThree; } /** * 撤销收款后重新计算收款单信息,收款明细已全部撤销时逻辑删除收款单 */ - private Boolean updateReceiptManageByCancel(ReceiptManage receiptManage) { + private Boolean updateReceiptManageByCancel(Long receiptManageId) { LoginUser loginUser = SecurityUtils.getLoginUser(); if (ObjectUtil.isNull(loginUser)) { throw new DigitalLogisticsException(UserError.TIMEOUT); } //查询收款单下剩余未撤销的收款明细 LambdaQueryWrapper queryWrapperDetail = new LambdaQueryWrapper<>(); - queryWrapperDetail.eq(ReceiptDetail::getReceiptManageId, receiptManage.getReceiptManageId()); + queryWrapperDetail.eq(ReceiptDetail::getReceiptManageId, receiptManageId); queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1); List receiptDetailList = receiptDetailDomainService.queryListByLambda(queryWrapperDetail); ReceiptManage receiptManageSave = new ReceiptManage(); - receiptManageSave.setReceiptManageId(receiptManage.getReceiptManageId()); + receiptManageSave.setReceiptManageId(receiptManageId); receiptManageSave.setUpdateBy(loginUser.getUserPo().getUserId()); receiptManageSave.setUpdateByName(loginUser.getUserPo().getUserName()); receiptManageSave.setUpdateTime(new Date()); @@ -383,6 +405,29 @@ public class ReceiptManageDomainService { return receiptManageService.updateById(receiptManageSave); } + /** + * 撤销收款-查询账单涉及的收款单id(用于加锁,防止并发撤销时收款单金额重算冲突) + */ + public Set queryReceiptManageIdsByBillManageIds(String billManageIds) { + Set receiptManageIdSet = new HashSet<>(); + if (StringUtils.isEmpty(billManageIds)) { + return receiptManageIdSet; + } + Set billManageIdSet = Stream.of(billManageIds.split(",")).filter(StringUtils::isNotEmpty).map(String::trim).map(Long::valueOf).collect(Collectors.toSet()); + if (billManageIdSet.size() == 0) { + return receiptManageIdSet; + } + LambdaQueryWrapper queryWrapperDetail = new LambdaQueryWrapper<>(); + queryWrapperDetail.in(ReceiptDetail::getBillManageId, billManageIdSet); + queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1); + List receiptDetails = receiptDetailDomainService.queryListByLambda(queryWrapperDetail); + if (null == receiptDetails || receiptDetails.size() == 0) { + return receiptManageIdSet; + } + receiptDetails.forEach(receiptDetail -> receiptManageIdSet.add(receiptDetail.getReceiptManageId())); + return receiptManageIdSet; + } + /** * 查询收款单详情 */ diff --git a/mhd_bms/src/main/java/com/mhd/bms/interfaces/facadeApi/ReceiptManageApi.java b/mhd_bms/src/main/java/com/mhd/bms/interfaces/facadeApi/ReceiptManageApi.java index b0b76e2eb..c733bde13 100644 --- a/mhd_bms/src/main/java/com/mhd/bms/interfaces/facadeApi/ReceiptManageApi.java +++ b/mhd_bms/src/main/java/com/mhd/bms/interfaces/facadeApi/ReceiptManageApi.java @@ -123,9 +123,6 @@ public class ReceiptManageApi extends BaseController{ @PostMapping("/cancelCollection") public AjaxResult cancelCollection(@RequestBody ReceiptManageDTO receiptManageDTO) { - if(null == receiptManageDTO.getReceiptManageId()){ - throw new ServiceException("收款单id不能为空"); - } if(!StringUtils.isNotEmpty(receiptManageDTO.getBillManageIds())){ throw new ServiceException("撤销账单不能为空"); } @@ -134,10 +131,14 @@ public class ReceiptManageApi extends BaseController{ try { RedisLockTypeEnum redisLockTypeEnum = RedisLockTypeEnum.BMS; List locks = new ArrayList<>(); - //收款单id与账单id去重后加锁,避免同一把锁重复加锁 + //账单id与涉及的收款单id去重后加锁,避免同一把锁重复加锁 Set lockKeySet = new LinkedHashSet<>(); - lockKeySet.add(String.valueOf(receiptManageDTO.getReceiptManageId())); - lockKeySet.addAll(Stream.of(receiptManageDTO.getBillManageIds().split(",")).collect(Collectors.toSet())); + lockKeySet.addAll(Stream.of(receiptManageDTO.getBillManageIds().split(",")).filter(StringUtils::isNotEmpty).map(String::trim).collect(Collectors.toSet())); + //查询账单涉及的收款单,一并加锁,避免并发撤销时收款单金额重算冲突 + Set receiptManageIdSet = receiptManageApplicationService.queryCancelCollectionReceiptManageIds(receiptManageDTO.getBillManageIds()); + if (null != receiptManageIdSet) { + receiptManageIdSet.forEach(x -> lockKeySet.add(String.valueOf(x))); + } lockKeySet.forEach(x -> { //获取唯一key值 String key = redisLockTypeEnum.getUniqueKey(UniqueKeyUtil.getBillingKey(x));