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 550eec895..12cba2fde 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,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); + } + /** * 退款 */ diff --git a/mhd_bms/src/main/java/com/mhd/bms/application/server/reportForm/ReportFormApplicationService.java b/mhd_bms/src/main/java/com/mhd/bms/application/server/reportForm/ReportFormApplicationService.java index a70cc7510..fab3417de 100644 --- a/mhd_bms/src/main/java/com/mhd/bms/application/server/reportForm/ReportFormApplicationService.java +++ b/mhd_bms/src/main/java/com/mhd/bms/application/server/reportForm/ReportFormApplicationService.java @@ -575,6 +575,8 @@ public class ReportFormApplicationService { //收款单 QueryWrapper 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; 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 02a767d95..aa2b88a53 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 @@ -681,6 +681,72 @@ public class BillManageDomainService { } + /** + * 撤销收款:恢复账单信息并保存撤销收款操作日志 + */ + 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()); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(BillManage::getBillManageId,billManageIds); + 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() + "已收金额小于待撤销金额,无法撤销收款,请刷新后重试"); + } + 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; + } + /** * 更改账单状态(付款) */ diff --git a/mhd_bms/src/main/java/com/mhd/bms/domain/billOperationLog/entity/BillOperationLog.java b/mhd_bms/src/main/java/com/mhd/bms/domain/billOperationLog/entity/BillOperationLog.java index 3a653b8f6..846162667 100644 --- a/mhd_bms/src/main/java/com/mhd/bms/domain/billOperationLog/entity/BillOperationLog.java +++ b/mhd_bms/src/main/java/com/mhd/bms/domain/billOperationLog/entity/BillOperationLog.java @@ -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("操作信息") diff --git a/mhd_bms/src/main/java/com/mhd/bms/domain/receiptManage/service/ReceiptDetailDomainService.java b/mhd_bms/src/main/java/com/mhd/bms/domain/receiptManage/service/ReceiptDetailDomainService.java index 7b6d93988..817cb217c 100644 --- a/mhd_bms/src/main/java/com/mhd/bms/domain/receiptManage/service/ReceiptDetailDomainService.java +++ b/mhd_bms/src/main/java/com/mhd/bms/domain/receiptManage/service/ReceiptDetailDomainService.java @@ -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 queryListByIdSet(Set orderIdSet) { LambdaQueryWrapper queryWrapperDetail = new LambdaQueryWrapper<>(); queryWrapperDetail.in(ReceiptDetail::getReceiptManageId, orderIdSet); + queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1); return receiptDetailService.list(queryWrapperDetail); } + + /** + * 撤销收款:批量逻辑删除收款明细 + */ + public Boolean cancelCollectionDetails(List receiptDetails) { + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (ObjectUtil.isNull(loginUser)) { + throw new DigitalLogisticsException(UserError.TIMEOUT); + } + List 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); + } } 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 c22c5f92d..de0f85653 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 @@ -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 billManageIdSet = Stream.of(receiptManageDO.getBillManageIds().split(",")).filter(StringUtils::isNotEmpty).map(String::trim).map(Long::valueOf).collect(Collectors.toSet()); + 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("部分账单收款记录不存在或已撤销,请刷新后重试"); + } + //恢复账单信息并保存撤销收款操作日志 + 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 queryWrapperDetail = new LambdaQueryWrapper<>(); + queryWrapperDetail.eq(ReceiptDetail::getReceiptManageId, receiptManage.getReceiptManageId()); + queryWrapperDetail.eq(ReceiptDetail::getDelFlag, 1); + List 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); + } + /** * 查询收款单详情 */ diff --git a/mhd_bms/src/main/java/com/mhd/bms/infrastructure/constant/BillLogsConstants.java b/mhd_bms/src/main/java/com/mhd/bms/infrastructure/constant/BillLogsConstants.java index 4c1eb32ba..0df79851a 100644 --- a/mhd_bms/src/main/java/com/mhd/bms/infrastructure/constant/BillLogsConstants.java +++ b/mhd_bms/src/main/java/com/mhd/bms/infrastructure/constant/BillLogsConstants.java @@ -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 = "收款单号:{},撤销收款金额:{}元(实收{}元,优惠{}元)"; + + /** * 付款 * 付款单号:{},付款金额:{}元 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 7aa97686c..b0b76e2eb 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,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 locks = new ArrayList<>(); + //收款单id与账单id去重后加锁,避免同一把锁重复加锁 + Set 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("撤销收款释放了锁"); + } + } + } + /** * 批量删除收款单管理 */ diff --git a/mhd_bms/src/main/resources/mapper/ReceiptManageMapper.xml b/mhd_bms/src/main/resources/mapper/ReceiptManageMapper.xml index 951e90838..3242d96cb 100644 --- a/mhd_bms/src/main/resources/mapper/ReceiptManageMapper.xml +++ b/mhd_bms/src/main/resources/mapper/ReceiptManageMapper.xml @@ -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 @@ -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 \ No newline at end of file