撤销收款接口

This commit is contained in:
王奎兴
2026-09-10 11:17:58 +08:00
parent 10012b3437
commit bbde788aa4
9 changed files with 256 additions and 3 deletions
@@ -147,6 +147,20 @@ public class ReceiptManageApplicationService {
}
/**
* 撤销收款
*/
@Transactional
public Boolean cancelCollection(ReceiptManageDO receiptManageDO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT);
}
//校验支付密码
CheckPasswordUtil.checkPayPassword(receiptManageDO.getPayPassword(),null);
return receiptManageDomainService.cancelCollection(receiptManageDO);
}
/**
* 退款
*/
@@ -575,6 +575,8 @@ public class ReportFormApplicationService {
//收款单
QueryWrapper<ReceiptManage> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("top_organization_id", loginUser.getUserPo().getTopOrganizationId());
//过滤已撤销(逻辑删除)的收款单
queryWrapper.eq("del_flag", 1);
for (int i = 0; i < formQueryParamsList.size(); i++) {
FormQueryParams formQueryParams = formQueryParamsList.get(i);
FormQueryParams beforeFormQueryParams = null;
@@ -681,6 +681,72 @@ public class BillManageDomainService {
}
/**
* 撤销收款:恢复账单信息并保存撤销收款操作日志
*/
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());
LambdaQueryWrapper<BillManage> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(BillManage::getBillManageId,billManageIds);
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() + "已收金额小于待撤销金额,无法撤销收款,请刷新后重试");
}
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);
}
billManageSave.setUpdateBy(loginUser.getUserPo().getUserId());
billManageSave.setUpdateByName(loginUser.getUserPo().getUserName());
billManageSave.setUpdateTime(new Date());
billManageListSave.add(billManageSave);
//保存账单操作记录
BillOperationLog billOperationLog = new BillOperationLog();
billOperationLog.setBillManageId(billManage.getBillManageId());
billOperationLog.setOperationInfo(StringUtils.format(BillLogsConstants.cancel_collection_bill_text,receiptDetail.getCollectionNum(),all,collectedAmount,collectedDiscount));
billOperationLog.setOperationType(12);
billOperationLog.setDelFlag(1);
billOperationLogSave.add(billOperationLog);
}
Boolean three = billOperationLogDomainService.insertBatch(billOperationLogSave);
Boolean flag = billManageService.updateBatchById(billManageListSave);
return flag && three;
}
/**
* 更改账单状态(付款)
*/
@@ -42,8 +42,8 @@ public class BillOperationLog extends BaseVOEntity{
@Excel(name = "账单管理id")
private Long billManageId;
@ApiModelProperty("操作类型(1-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款)")
@Excel(name = "操作类型", readConverterExp = "1=-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款")
@ApiModelProperty("操作类型(1-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款,12-撤销收款")
@Excel(name = "操作类型", readConverterExp = "1=-创建账单,2-调整账单,3-确认账单,4-发起对账,5-客户确认,6-财务审核,7-收款,8-作废账单,9-删除账单,10-退款,11-付款,12-撤销收款")
private Integer operationType;
@ApiModelProperty("操作信息")
@@ -1,16 +1,22 @@
package com.mhd.bms.domain.receiptManage.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.hutool.core.util.ObjectUtil;
import com.mhd.bms.domain.receiptManage.entity.ReceiptDetail;
import com.mhd.bms.domain.receiptManage.repository.facade.IReceiptDetailService;
import com.mhd.bms.domain.receiptManage.repository.po.ReceiptDetailPO;
import com.mhd.bms.domain.receiptManage.repository.todo.ReceiptDetailDO;
import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException;
import com.mhd.common.core.exception.digitalLogisticsException.UserError;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
@@ -95,6 +101,28 @@ public class ReceiptDetailDomainService {
public List<ReceiptDetail> queryListByIdSet(Set<Long> orderIdSet) {
LambdaQueryWrapper<ReceiptDetail> queryWrapperDetail = new LambdaQueryWrapper<>();
queryWrapperDetail.in(ReceiptDetail::getReceiptManageId, orderIdSet);
queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1);
return receiptDetailService.list(queryWrapperDetail);
}
/**
* 撤销收款批量逻辑删除收款明细
*/
public Boolean cancelCollectionDetails(List<ReceiptDetail> receiptDetails) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT);
}
List<ReceiptDetail> receiptDetailSaveList = new ArrayList<>();
for (ReceiptDetail receiptDetail : receiptDetails) {
ReceiptDetail receiptDetailSave = new ReceiptDetail();
receiptDetailSave.setReceiptDetailId(receiptDetail.getReceiptDetailId());
receiptDetailSave.setDelFlag(2);
receiptDetailSave.setUpdateBy(loginUser.getUserPo().getUserId());
receiptDetailSave.setUpdateByName(loginUser.getUserPo().getUserName());
receiptDetailSave.setUpdateTime(new Date());
receiptDetailSaveList.add(receiptDetailSave);
}
return receiptDetailService.updateBatchById(receiptDetailSaveList);
}
}
@@ -300,6 +300,89 @@ public class ReceiptManageDomainService {
return flag && flagTwo && flagThree;
}
/**
* 撤销收款
*/
public Boolean cancelCollection(ReceiptManageDO receiptManageDO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
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());
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("部分账单收款记录不存在或已撤销,请刷新后重试");
}
//恢复账单信息并保存撤销收款操作日志
Boolean flagTwo = billManageDomainService.cancelCollectionInfo(receiptDetails);
//逻辑删除收款明细
Boolean flag = receiptDetailDomainService.cancelCollectionDetails(receiptDetails);
//重新计算收款单金额收款明细已全部撤销时逻辑删除收款单
Boolean flagThree = updateReceiptManageByCancel(receiptManage);
return flag && flagTwo && flagThree;
}
/**
* 撤销收款后重新计算收款单信息收款明细已全部撤销时逻辑删除收款单
*/
private Boolean updateReceiptManageByCancel(ReceiptManage receiptManage) {
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::getDelFlag, 1);
List<ReceiptDetail> receiptDetailList = receiptDetailDomainService.queryListByLambda(queryWrapperDetail);
ReceiptManage receiptManageSave = new ReceiptManage();
receiptManageSave.setReceiptManageId(receiptManage.getReceiptManageId());
receiptManageSave.setUpdateBy(loginUser.getUserPo().getUserId());
receiptManageSave.setUpdateByName(loginUser.getUserPo().getUserName());
receiptManageSave.setUpdateTime(new Date());
if (null == receiptDetailList || receiptDetailList.size() == 0) {
//收款明细已全部撤销逻辑删除收款单
receiptManageSave.setDelFlag(2);
return receiptManageService.updateById(receiptManageSave);
}
//按剩余明细重新计算收款单金额
BigDecimal billAmount = receiptDetailList.stream().map(ReceiptDetail::getBillAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal collectedDiscount = receiptDetailList.stream().map(ReceiptDetail::getCollectedDiscount).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal collectedAmount = receiptDetailList.stream().map(ReceiptDetail::getCollectedAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal uncollectedAmount = receiptDetailList.stream().map(ReceiptDetail::getBillAmountUnsettledResidue).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal billAmountUnsettled = receiptDetailList.stream().map(ReceiptDetail::getBillAmountUnsettled).reduce(BigDecimal.ZERO, BigDecimal::add);
receiptManageSave.setBillAmount(billAmount);
receiptManageSave.setCollectedDiscount(collectedDiscount);
receiptManageSave.setCollectedAmount(collectedAmount);
receiptManageSave.setUncollectedAmount(uncollectedAmount);
receiptManageSave.setBillAmountUnsettled(billAmountUnsettled);
//账单金额 = 已收金额 + 剩余未收金额 + 收款优惠金额 + 收款金额
receiptManageSave.setBillAmountSettlement(billAmount.subtract(uncollectedAmount).subtract(collectedDiscount).subtract(collectedAmount));
return receiptManageService.updateById(receiptManageSave);
}
/**
* 查询收款单详情
*/
@@ -88,6 +88,14 @@ public class BillLogsConstants
public static final String refund_bill_text = "退款单号:{},退款金额:{}元";
/**
* 撤销收款
* 收款单号{}撤销收款金额{}实收{}优惠{}
*/
public static final String cancel_collection_bill_title = "撤销收款";
public static final String cancel_collection_bill_text = "收款单号:{},撤销收款金额:{}元(实收{}元,优惠{}元)";
/**
* 付款
* 付款单号{}付款金额{}
@@ -1,6 +1,7 @@
package com.mhd.bms.interfaces.facadeApi;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -114,6 +115,56 @@ public class ReceiptManageApi extends BaseController{
}
}
/**
* 撤销收款
*/
@ApiOperation("撤销收款")
@RepeatSubmit
@PostMapping("/cancelCollection")
public AjaxResult cancelCollection(@RequestBody ReceiptManageDTO receiptManageDTO)
{
if(null == receiptManageDTO.getReceiptManageId()){
throw new ServiceException("收款单id不能为空");
}
if(!StringUtils.isNotEmpty(receiptManageDTO.getBillManageIds())){
throw new ServiceException("撤销账单不能为空");
}
RedissonMultiLock redissonMultiLock = null;
boolean payInfoDetailLock = false;
try {
RedisLockTypeEnum redisLockTypeEnum = RedisLockTypeEnum.BMS;
List<RLock> locks = new ArrayList<>();
//收款单id与账单id去重后加锁避免同一把锁重复加锁
Set<String> lockKeySet = new LinkedHashSet<>();
lockKeySet.add(String.valueOf(receiptManageDTO.getReceiptManageId()));
lockKeySet.addAll(Stream.of(receiptManageDTO.getBillManageIds().split(",")).collect(Collectors.toSet()));
lockKeySet.forEach(x -> {
//获取唯一key值
String key = redisLockTypeEnum.getUniqueKey(UniqueKeyUtil.getBillingKey(x));
locks.add(redisLock.getRLock(key));
});
redissonMultiLock = new RedissonMultiLock(locks.toArray(new RLock[lockKeySet.size()]));
//尝试获取锁 不等待 持有锁10分钟
payInfoDetailLock = redissonMultiLock.tryLock(-1, 10, TimeUnit.MINUTES);
if (!payInfoDetailLock) {
redissonMultiLock = null;
return AjaxResult.error("收款单正在处理,请稍后再试");
}
log.info("撤销收款加锁成功");
//转换实体
ReceiptManageDO receiptManageDO = new ReceiptManageDO();
BeanUtils.copyProperties(receiptManageDTO,receiptManageDO);
return toAjax(receiptManageApplicationService.cancelCollection(receiptManageDO));
}catch (Exception e){
return AjaxResult.error("撤销收款失败:" + e.getMessage());
}finally {
if (redissonMultiLock != null && payInfoDetailLock) {
redissonMultiLock.unlock();
log.info("撤销收款释放了锁");
}
}
}
/**
* 批量删除收款单管理
*/
@@ -13,7 +13,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WM_CONCAT(b.bill_number) AS billNumbers
FROM
receipt_manage a
LEFT JOIN receipt_detail b ON a.receipt_manage_id = b.receipt_manage_id
LEFT JOIN receipt_detail b ON a.receipt_manage_id = b.receipt_manage_id AND b.del_flag = 1
WHERE
a.del_flag = 1
<include refid="common_where"/>
@@ -101,6 +101,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
left join PAYMENT_WALLET c on b.payment_card_id = c.PAYMENT_WALLET_ID
WHERE
a.bill_manage_id = #{billManageId}
AND a.del_flag = 1
</select>
</mapper>