撤销付款逻辑修改;

This commit is contained in:
王奎兴
2026-09-11 15:33:59 +08:00
parent 0077e5d673
commit c1bbda9f9a
4 changed files with 100 additions and 60 deletions
@@ -159,6 +159,13 @@ public class ReceiptManageApplicationService {
return receiptManageDomainService.cancelCollection(receiptManageDO);
}
/**
* 撤销收款-查询账单涉及的收款单id(用于加锁,防止并发撤销时收款单金额重算冲突)
*/
public Set<Long> queryCancelCollectionReceiptManageIds(String billManageIds) {
return receiptManageDomainService.queryReceiptManageIdsByBillManageIds(billManageIds);
}
/**
* 退款
*/
@@ -710,62 +710,49 @@ public class BillManageDomainService {
/**
* 撤销收款:恢复账单信息并保存撤销收款操作日志
* 撤销收款:账单恢复为收款为0状态并保存撤销收款操作日志
*/
public Boolean cancelCollectionInfo(List<ReceiptDetail> receiptDetails) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT);
}
List<Long> billManageIds = receiptDetails.stream().map(ReceiptDetail::getBillManageId).collect(Collectors.toList());
//按账单分组收款明细(一个账单可能对应多个收款单)
Map<Long, List<ReceiptDetail>> billDetailMap = receiptDetails.stream().collect(Collectors.groupingBy(ReceiptDetail::getBillManageId));
LambdaQueryWrapper<BillManage> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(BillManage::getBillManageId,billManageIds);
queryWrapper.in(BillManage::getBillManageId,billDetailMap.keySet());
List<BillManage> billManageList = billManageService.list(queryWrapper);
if(billManageList == null || billManageList.size()==0){
throw new ServiceException("账单信息未找到");
}
List<BillManage> billManageListSave = new ArrayList<>();
List<BillOperationLog> 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<ReceiptDetail> 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) {
//账单恢复为收款为0状态
billManageSave.setBillAmountSettlement(BigDecimal.ZERO);
billManageSave.setBillAmountUnsettled(billManage.getBillAmount());
billManageSave.setActualReceivedAmount(BigDecimal.ZERO);
billManageSave.setSettlementDiscountsAmount(BigDecimal.ZERO);
billManageSave.setBillState(3);
} else if (billManageSave.getBillAmountUnsettled().compareTo(BigDecimal.ZERO) == 0) {
billManageSave.setBillState(5);
} else {
billManageSave.setBillState(4);
}
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);
@@ -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<Long> 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<BillManage> queryWrapperBill = new LambdaQueryWrapper<>();
queryWrapperBill.in(BillManage::getBillManageId, billManageIdSet);
queryWrapperBill.eq(BillManage::getDelFlag, 1);
List<BillManage> billManageList = billManageDomainService.queryListLambda(queryWrapperBill);
if (null == billManageList || billManageList.size() == 0) {
throw new ServiceException("账单信息未找到");
}
if (billManageList.size() != billManageIdSet.size()) {
throw new ServiceException("部分账单信息未找到,请刷新后重试");
}
//查询账单的全部有效收款明细一个账单可能对应多个收款单
LambdaQueryWrapper<ReceiptDetail> queryWrapperDetail = new LambdaQueryWrapper<>();
queryWrapperDetail.eq(ReceiptDetail::getReceiptManageId, receiptManageDO.getReceiptManageId());
queryWrapperDetail.in(ReceiptDetail::getBillManageId, billManageIdSet);
queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1);
List<ReceiptDetail> receiptDetails = receiptDetailDomainService.queryListByLambda(queryWrapperDetail);
if (null == receiptDetails || receiptDetails.size() == 0) {
throw new ServiceException("账单收款记录不存在或已撤销,请刷新后重试");
}
if (receiptDetails.size() != billManageIdSet.size()) {
throw new ServiceException("部分账单收款记录不存在或已撤销,请刷新后重试");
//校验每个账单都有收款记录
Map<Long, List<ReceiptDetail>> billDetailMap = receiptDetails.stream().collect(Collectors.groupingBy(ReceiptDetail::getBillManageId));
for (BillManage billManage : billManageList) {
if (!billDetailMap.containsKey(billManage.getBillManageId())) {
throw new ServiceException("账单" + billManage.getBillNumber() + "收款记录不存在或已撤销,请刷新后重试");
}
//恢复账单信息并保存撤销收款操作日志
}
//校验收款单退款状态已退款的收款单不能撤销收款
Set<Long> receiptManageIdSet = receiptDetails.stream().map(ReceiptDetail::getReceiptManageId).collect(Collectors.toSet());
LambdaQueryWrapper<ReceiptManage> queryWrapperManage = new LambdaQueryWrapper<>();
queryWrapperManage.in(ReceiptManage::getReceiptManageId, receiptManageIdSet);
List<ReceiptManage> 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<ReceiptDetail> queryWrapperDetail = new LambdaQueryWrapper<>();
queryWrapperDetail.eq(ReceiptDetail::getReceiptManageId, receiptManage.getReceiptManageId());
queryWrapperDetail.eq(ReceiptDetail::getReceiptManageId, receiptManageId);
queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1);
List<ReceiptDetail> 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<Long> queryReceiptManageIdsByBillManageIds(String billManageIds) {
Set<Long> receiptManageIdSet = new HashSet<>();
if (StringUtils.isEmpty(billManageIds)) {
return receiptManageIdSet;
}
Set<Long> billManageIdSet = Stream.of(billManageIds.split(",")).filter(StringUtils::isNotEmpty).map(String::trim).map(Long::valueOf).collect(Collectors.toSet());
if (billManageIdSet.size() == 0) {
return receiptManageIdSet;
}
LambdaQueryWrapper<ReceiptDetail> queryWrapperDetail = new LambdaQueryWrapper<>();
queryWrapperDetail.in(ReceiptDetail::getBillManageId, billManageIdSet);
queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1);
List<ReceiptDetail> receiptDetails = receiptDetailDomainService.queryListByLambda(queryWrapperDetail);
if (null == receiptDetails || receiptDetails.size() == 0) {
return receiptManageIdSet;
}
receiptDetails.forEach(receiptDetail -> receiptManageIdSet.add(receiptDetail.getReceiptManageId()));
return receiptManageIdSet;
}
/**
* 查询收款单详情
*/
@@ -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<RLock> locks = new ArrayList<>();
//收款单id与单id去重后加锁避免同一把锁重复加锁
//单id与涉及的收款单id去重后加锁避免同一把锁重复加锁
Set<String> 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<Long> 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));