From ed809e82d47057b3995decd36feae592861c4b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=A5=8E=E5=85=B4?= <2220574228@qq.com> Date: Mon, 14 Sep 2026 15:10:29 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=89=B9=E9=87=8F=E6=94=B6=E6=AC=BE?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=BC=80=E5=8F=91;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../facadeApi/ReceiptManageApi.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) 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 c733bde13..8f6b3b896 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 @@ -1,8 +1,10 @@ package com.mhd.bms.interfaces.facadeApi; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -56,6 +58,11 @@ public class ReceiptManageApi extends BaseController{ @Autowired private RedisLock redisLock; + /** + * 排队批量收款-获取账单锁的最大等待时间(秒),等待期内排队获取锁,避免并发收款直接失败 + */ + private static final long QUEUE_COLLECTION_LOCK_WAIT_SECONDS = 30L; + /** * 分页查询收款单管理列表 */ @@ -115,6 +122,79 @@ public class ReceiptManageApi extends BaseController{ } } + /** + * 排队批量收款 + * 接收多个批量收款请求参数集合,按顺序排队依次处理; + * 同一账单分多次收款时前一笔处理完成后才处理下一笔,避免redis锁冲突导致收款失败 + */ + @ApiOperation("排队批量收款") + @RepeatSubmit + @PostMapping("/queueBatchCollection") + public AjaxResult queueBatchCollection(@RequestBody List receiptManageDTOList) + { + if(StringUtils.isEmpty(receiptManageDTOList)){ + throw new ServiceException("收款账单不能为空"); + } + List> collectionResultList = new ArrayList<>(); + for (ReceiptManageDTO receiptManageDTO : receiptManageDTOList) { + collectionResultList.add(handleQueueBatchCollection(receiptManageDTO)); + } + boolean allSuccess = collectionResultList.stream().allMatch(item -> Boolean.TRUE.equals(item.get("success"))); + if (allSuccess) { + return AjaxResult.success("收款成功", collectionResultList); + } + return AjaxResult.error("部分收款失败,请查看收款结果明细", collectionResultList); + } + + /** + * 排队批量收款-处理单个收款请求(排队获取账单锁,每笔收款独立处理,单笔失败不影响后续请求) + */ + private Map handleQueueBatchCollection(ReceiptManageDTO receiptManageDTO) { + Map result = new LinkedHashMap<>(); + result.put("billManageIds", receiptManageDTO.getBillManageIds()); + RedissonMultiLock redissonMultiLock = null; + boolean payInfoDetailLock = false; + try { + if(!StringUtils.isNotEmpty(receiptManageDTO.getBillManageIds())){ + throw new ServiceException("收款账单不能为空"); + } + RedisLockTypeEnum redisLockTypeEnum = RedisLockTypeEnum.BMS; + List locks = new ArrayList<>(); + Set billingSet = Stream.of(receiptManageDTO.getBillManageIds().split(",")).collect(Collectors.toSet()); + billingSet.forEach(x -> { + //获取唯一key值 + String key = redisLockTypeEnum.getUniqueKey(UniqueKeyUtil.getBillingKey(x.toString())); + locks.add(redisLock.getRLock(key)); + }); + redissonMultiLock = new RedissonMultiLock(locks.toArray(new RLock[billingSet.size()])); + //尝试获取锁 等待指定时间内排队获取 持有锁10分钟 + payInfoDetailLock = redissonMultiLock.tryLock(QUEUE_COLLECTION_LOCK_WAIT_SECONDS, 10, TimeUnit.MINUTES); + if (!payInfoDetailLock) { + redissonMultiLock = null; + result.put("success", false); + result.put("message", "账单正在处理,请稍后再试"); + return result; + } + log.info("排队批量收款-生成账单加锁成功"); + //转换实体 + ReceiptManageDO receiptManageDO = new ReceiptManageDO(); + BeanUtils.copyProperties(receiptManageDTO,receiptManageDO); + Boolean flag = receiptManageApplicationService.batchCollection(receiptManageDO); + result.put("success", Boolean.TRUE.equals(flag)); + result.put("message", Boolean.TRUE.equals(flag) ? "收款成功" : "收款失败"); + return result; + }catch (Exception e){ + result.put("success", false); + result.put("message", "收款失败" + e.getMessage()); + return result; + }finally { + if (redissonMultiLock != null && payInfoDetailLock) { + redissonMultiLock.unlock(); + log.info("排队批量收款-生成账单释放了锁"); + } + } + } + /** * 撤销收款 */ From 81630339e406380b1f7d57492fe97cbf436f6830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=A5=8E=E5=85=B4?= <2220574228@qq.com> Date: Mon, 14 Sep 2026 16:13:40 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=89=B9=E9=87=8F=E6=94=B6=E6=AC=BE?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=BA=8B=E5=8A=A1;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ReceiptManageApplicationService.java | 26 +++++++ .../facadeApi/ReceiptManageApi.java | 72 ++++++++----------- 2 files changed, 54 insertions(+), 44 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 b098b3443..d970e985f 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 @@ -147,6 +147,32 @@ public class ReceiptManageApplicationService { } + /** + * 排队批量收款 + * 接收集合按顺序逐笔处理,任意一笔收款失败则整体回滚 + */ + @Transactional(rollbackFor = Exception.class) + public Boolean queueBatchCollection(List receiptManageDOList) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (ObjectUtil.isNull(loginUser)) { + throw new DigitalLogisticsException(UserError.TIMEOUT); + } + int index = 1; + for (ReceiptManageDO receiptManageDO : receiptManageDOList) { + try { + Boolean flag = batchCollection(receiptManageDO); + if (!Boolean.TRUE.equals(flag)) { + throw new ServiceException("收款数据处理失败"); + } + } catch (Exception e) { + throw new ServiceException("第" + index + "笔收款失败:" + e.getMessage() + ",本次收款已全部回滚"); + } + index++; + } + return true; + } + + /** * 撤销收款 */ 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 8f6b3b896..9b4fe8635 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 @@ -1,11 +1,10 @@ package com.mhd.bms.interfaces.facadeApi; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Set; +import java.util.TreeSet; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -124,8 +123,9 @@ public class ReceiptManageApi extends BaseController{ /** * 排队批量收款 - * 接收多个批量收款请求参数集合,按顺序排队依次处理; - * 同一账单分多次收款时前一笔处理完成后才处理下一笔,避免redis锁冲突导致收款失败 + * 接收多个批量收款请求参数集合,整体加锁后按顺序排队依次处理; + * 同一账单分多次收款时前一笔处理完成后才处理下一笔,避免redis锁冲突导致收款失败; + * 整个集合在同一事务内处理,任意一笔收款失败则全部回滚 */ @ApiOperation("排队批量收款") @RepeatSubmit @@ -135,58 +135,42 @@ public class ReceiptManageApi extends BaseController{ if(StringUtils.isEmpty(receiptManageDTOList)){ throw new ServiceException("收款账单不能为空"); } - List> collectionResultList = new ArrayList<>(); + //汇总所有收款请求涉及的账单id并排序,整体加锁,保证事务期间锁不释放且加锁顺序一致避免死锁 + Set lockKeySet = new TreeSet<>(); for (ReceiptManageDTO receiptManageDTO : receiptManageDTOList) { - collectionResultList.add(handleQueueBatchCollection(receiptManageDTO)); - } - boolean allSuccess = collectionResultList.stream().allMatch(item -> Boolean.TRUE.equals(item.get("success"))); - if (allSuccess) { - return AjaxResult.success("收款成功", collectionResultList); - } - return AjaxResult.error("部分收款失败,请查看收款结果明细", collectionResultList); - } - - /** - * 排队批量收款-处理单个收款请求(排队获取账单锁,每笔收款独立处理,单笔失败不影响后续请求) - */ - private Map handleQueueBatchCollection(ReceiptManageDTO receiptManageDTO) { - Map result = new LinkedHashMap<>(); - result.put("billManageIds", receiptManageDTO.getBillManageIds()); - RedissonMultiLock redissonMultiLock = null; - boolean payInfoDetailLock = false; - try { if(!StringUtils.isNotEmpty(receiptManageDTO.getBillManageIds())){ throw new ServiceException("收款账单不能为空"); } - RedisLockTypeEnum redisLockTypeEnum = RedisLockTypeEnum.BMS; - List locks = new ArrayList<>(); - Set billingSet = Stream.of(receiptManageDTO.getBillManageIds().split(",")).collect(Collectors.toSet()); - billingSet.forEach(x -> { - //获取唯一key值 - String key = redisLockTypeEnum.getUniqueKey(UniqueKeyUtil.getBillingKey(x.toString())); - locks.add(redisLock.getRLock(key)); - }); - redissonMultiLock = new RedissonMultiLock(locks.toArray(new RLock[billingSet.size()])); + lockKeySet.addAll(Stream.of(receiptManageDTO.getBillManageIds().split(",")).filter(StringUtils::isNotEmpty).map(String::trim).collect(Collectors.toSet())); + } + RedisLockTypeEnum redisLockTypeEnum = RedisLockTypeEnum.BMS; + List locks = new ArrayList<>(); + lockKeySet.forEach(x -> { + //获取唯一key值 + String key = redisLockTypeEnum.getUniqueKey(UniqueKeyUtil.getBillingKey(x)); + locks.add(redisLock.getRLock(key)); + }); + RedissonMultiLock redissonMultiLock = new RedissonMultiLock(locks.toArray(new RLock[lockKeySet.size()])); + boolean payInfoDetailLock = false; + try { //尝试获取锁 等待指定时间内排队获取 持有锁10分钟 payInfoDetailLock = redissonMultiLock.tryLock(QUEUE_COLLECTION_LOCK_WAIT_SECONDS, 10, TimeUnit.MINUTES); if (!payInfoDetailLock) { redissonMultiLock = null; - result.put("success", false); - result.put("message", "账单正在处理,请稍后再试"); - return result; + return AjaxResult.error("账单正在处理,请稍后再试"); } log.info("排队批量收款-生成账单加锁成功"); //转换实体 - ReceiptManageDO receiptManageDO = new ReceiptManageDO(); - BeanUtils.copyProperties(receiptManageDTO,receiptManageDO); - Boolean flag = receiptManageApplicationService.batchCollection(receiptManageDO); - result.put("success", Boolean.TRUE.equals(flag)); - result.put("message", Boolean.TRUE.equals(flag) ? "收款成功" : "收款失败"); - return result; + List receiptManageDOList = new ArrayList<>(); + for (ReceiptManageDTO receiptManageDTO : receiptManageDTOList) { + ReceiptManageDO receiptManageDO = new ReceiptManageDO(); + BeanUtils.copyProperties(receiptManageDTO,receiptManageDO); + receiptManageDOList.add(receiptManageDO); + } + //事务内排队逐笔收款,任意一笔失败全部回滚 + return toAjax(receiptManageApplicationService.queueBatchCollection(receiptManageDOList)); }catch (Exception e){ - result.put("success", false); - result.put("message", "收款失败" + e.getMessage()); - return result; + return AjaxResult.error("收款失败:" + e.getMessage()); }finally { if (redissonMultiLock != null && payInfoDetailLock) { redissonMultiLock.unlock(); From 6cb70805f1bca316d052faa008625ed736039013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=A5=8E=E5=85=B4?= <2220574228@qq.com> Date: Mon, 14 Sep 2026 16:26:37 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E6=89=B9=E9=87=8F=E6=94=B6=E6=AC=BE?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=BA=8B=E5=8A=A1;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/receiptManage/ReceiptManageApplicationService.java | 3 +++ .../com/mhd/bms/interfaces/facadeApi/ReceiptManageApi.java | 1 + 2 files changed, 4 insertions(+) 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 d970e985f..c811eca75 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 @@ -18,6 +18,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.interceptor.TransactionAspectSupport; import java.util.ArrayList; import java.util.Date; @@ -165,6 +166,8 @@ public class ReceiptManageApplicationService { throw new ServiceException("收款数据处理失败"); } } catch (Exception e) { + //自己try捕获的异常也要标记事务回滚,确保收款失败时全部回滚 + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); throw new ServiceException("第" + index + "笔收款失败:" + e.getMessage() + ",本次收款已全部回滚"); } index++; 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 9b4fe8635..0bbc6bcf0 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 @@ -170,6 +170,7 @@ public class ReceiptManageApi extends BaseController{ //事务内排队逐笔收款,任意一笔失败全部回滚 return toAjax(receiptManageApplicationService.queueBatchCollection(receiptManageDOList)); }catch (Exception e){ + //异常已在应用服务层事务内标记回滚(收款失败必回滚),此处仅返回失败结果 return AjaxResult.error("收款失败:" + e.getMessage()); }finally { if (redissonMultiLock != null && payInfoDetailLock) { From 0d9ea32f85fec7b4b503db00198c65ea6d5ff431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=A5=8E=E5=85=B4?= <2220574228@qq.com> Date: Mon, 14 Sep 2026 16:48:12 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E5=90=8E=E7=AB=AF=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E8=B4=A6=E5=8D=95=E9=87=91=E9=A2=9D,=E5=B7=B2=E6=94=B6?= =?UTF-8?q?=E6=9C=AA=E6=94=B6=E7=AD=89=E6=95=B0=E6=8D=AE;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ReceiptManageApplicationService.java | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) 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 c811eca75..3ae166165 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 @@ -2,12 +2,14 @@ package com.mhd.bms.application.server.receiptManage; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.mhd.bms.domain.billManage.entity.BillManage; import com.mhd.bms.domain.billManage.service.BillManageDomainService; import com.mhd.bms.domain.receiptManage.entity.ReceiptManage; import com.mhd.bms.domain.receiptManage.repository.po.ReceiptManagePO; import com.mhd.bms.domain.receiptManage.repository.todo.ReceiptManageDO; import com.mhd.bms.domain.receiptManage.service.ReceiptManageDomainService; import com.mhd.bms.infrastructure.utils.CheckPasswordUtil; +import com.mhd.bms.interfaces.dto.receiptManage.ReceiptDetailDTO; import com.mhd.bms.interfaces.dto.receiptManage.ReceiptManageDTO; import com.mhd.common.core.exception.ServiceException; import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException; @@ -20,9 +22,11 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.interceptor.TransactionAspectSupport; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -161,6 +165,8 @@ public class ReceiptManageApplicationService { int index = 1; for (ReceiptManageDO receiptManageDO : receiptManageDOList) { try { + //根据账单id查询账单当前金额数据,替换前端传的账单金额、已收金额、未收金额等(仅保留前端传的收款金额和优惠金额) + fillBillAmountFromBillManage(receiptManageDO); Boolean flag = batchCollection(receiptManageDO); if (!Boolean.TRUE.equals(flag)) { throw new ServiceException("收款数据处理失败"); @@ -176,6 +182,73 @@ public class ReceiptManageApplicationService { } + /** + * 排队批量收款-根据账单id查询账单当前金额,替换前端传的账单金额、已收金额、未收金额、剩余未收(仅保留前端传的收款金额和优惠金额) + */ + private void fillBillAmountFromBillManage(ReceiptManageDO receiptManageDO) { + List receiptDetailDTOList = receiptManageDO.getReceiptDetailDTOList(); + if (null == receiptDetailDTOList || receiptDetailDTOList.size() == 0) { + throw new ServiceException("费用结算明细不能为空"); + } + //汇总收款明细的账单id并查询账单当前数据 + Set billManageIdSet = receiptDetailDTOList.stream().map(ReceiptDetailDTO::getBillManageId).filter(ObjectUtil::isNotNull).collect(Collectors.toSet()); + if (billManageIdSet.size() == 0) { + throw new ServiceException("收款账单不能为空"); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(BillManage::getBillManageId, billManageIdSet); + queryWrapper.eq(BillManage::getDelFlag, 1); + List billManageList = billManageDomainService.queryListLambda(queryWrapper); + if (null == billManageList || billManageList.size() == 0) { + throw new ServiceException("账单信息未找到"); + } + Map billManageMap = billManageList.stream().collect(Collectors.toMap(BillManage::getBillManageId, billManage -> billManage, (oldValue, newValue) -> oldValue)); + //汇总账单金额、已收金额、未收金额、收款金额、优惠金额 + BigDecimal billAmount = BigDecimal.ZERO; + BigDecimal billAmountSettlement = BigDecimal.ZERO; + BigDecimal billAmountUnsettled = BigDecimal.ZERO; + BigDecimal collectedAmount = BigDecimal.ZERO; + BigDecimal collectedDiscount = BigDecimal.ZERO; + for (ReceiptDetailDTO receiptDetailDTO : receiptDetailDTOList) { + BillManage billManage = billManageMap.get(receiptDetailDTO.getBillManageId()); + if (null == billManage) { + throw new ServiceException("账单" + receiptDetailDTO.getBillNumber() + "信息未找到,请刷新后重试"); + } + //只取前端传的收款金额、优惠金额,为空按0处理 + BigDecimal detailCollectedAmount = null == receiptDetailDTO.getCollectedAmount() ? BigDecimal.ZERO : receiptDetailDTO.getCollectedAmount(); + BigDecimal detailCollectedDiscount = null == receiptDetailDTO.getCollectedDiscount() ? BigDecimal.ZERO : receiptDetailDTO.getCollectedDiscount(); + //账单当前金额以数据库为准 + BigDecimal detailBillAmount = billManage.getBillAmount(); + BigDecimal detailBillAmountSettlement = billManage.getBillAmountSettlement(); + BigDecimal detailBillAmountUnsettled = billManage.getBillAmountUnsettled(); + //剩余未收金额 = 未收金额 - 收款金额 - 优惠金额 + BigDecimal detailBillAmountUnsettledResidue = detailBillAmountUnsettled.subtract(detailCollectedAmount).subtract(detailCollectedDiscount); + if (detailBillAmountUnsettledResidue.compareTo(BigDecimal.ZERO) < 0) { + throw new ServiceException("账单" + billManage.getBillNumber() + "未收金额小于本次收款金额与优惠金额之和,无法完成收款,请刷新后重试"); + } + //用数据库当前值替换前端传的账单金额、已收金额、未收金额、剩余未收 + receiptDetailDTO.setBillAmount(detailBillAmount); + receiptDetailDTO.setBillAmountSettlement(detailBillAmountSettlement); + receiptDetailDTO.setBillAmountUnsettled(detailBillAmountUnsettled); + receiptDetailDTO.setBillAmountUnsettledResidue(detailBillAmountUnsettledResidue); + //累计收款单金额 + billAmount = billAmount.add(detailBillAmount); + billAmountSettlement = billAmountSettlement.add(detailBillAmountSettlement); + billAmountUnsettled = billAmountUnsettled.add(detailBillAmountUnsettled); + collectedAmount = collectedAmount.add(detailCollectedAmount); + collectedDiscount = collectedDiscount.add(detailCollectedDiscount); + } + //收款单金额:账单金额、已收金额、未收金额取查询值汇总,收款金额、优惠金额取前端传值汇总 + receiptManageDO.setBillAmount(billAmount); + receiptManageDO.setBillAmountSettlement(billAmountSettlement); + receiptManageDO.setBillAmountUnsettled(billAmountUnsettled); + receiptManageDO.setCollectedAmount(collectedAmount); + receiptManageDO.setCollectedDiscount(collectedDiscount); + //剩余未收 = 未收金额 - 收款金额 - 优惠金额 + receiptManageDO.setUncollectedAmount(billAmountUnsettled.subtract(collectedAmount).subtract(collectedDiscount)); + } + + /** * 撤销收款 */