批量红冲;

This commit is contained in:
王奎兴
2026-09-11 16:36:23 +08:00
parent 0ca8548c06
commit 6613eeb3fb
3 changed files with 53 additions and 21 deletions
@@ -658,7 +658,7 @@ public class BillManageApplicationService {
if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT);
}
if (billManageDTO.getBillManageId() == null) {
if (StringUtils.isEmpty(billManageDTO.getBillManageIds())) {
throw new ServiceException("账单id不能为空");
}
return billManageDomainService.redFlushBill(billManageDTO);
@@ -764,25 +764,48 @@ public class BillManageDomainService {
/**
* 应收账单红冲:生成一条金额为负数的红冲账单对冲原账单,不操作收款单等数据
* 应收账单红冲:生成金额为负数的红冲账单对冲原账单,不操作收款单等数据(支持批量)
*/
public Boolean redFlushBill(BillManageDTO billManageDTO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT);
}
if (null == billManageDTO.getBillManageId()) {
if (StringUtils.isEmpty(billManageDTO.getBillManageIds())) {
throw new ServiceException("账单id不能为空");
}
BillManage originalBill = billManageService.getById(billManageDTO.getBillManageId());
if (null == originalBill || ObjectUtil.equal(originalBill.getDelFlag(), 2)) {
throw new ServiceException("账单信息未找到,请刷新后重试");
Set<Long> billManageIdSet = Stream.of(billManageDTO.getBillManageIds().split(",")).filter(StringUtils::isNotEmpty).map(String::trim).map(Long::valueOf).collect(Collectors.toSet());
if (billManageIdSet.size() == 0) {
throw new ServiceException("账单id不能为空");
}
//查询账单信息
LambdaQueryWrapper<BillManage> queryWrapperBill = new LambdaQueryWrapper<>();
queryWrapperBill.in(BillManage::getBillManageId, billManageIdSet);
queryWrapperBill.eq(BillManage::getDelFlag, 1);
List<BillManage> billManageList = billManageService.list(queryWrapperBill);
if (null == billManageList || billManageList.size() == 0) {
throw new ServiceException("账单信息未找到");
}
if (billManageList.size() != billManageIdSet.size()) {
throw new ServiceException("部分账单信息未找到,请刷新后重试");
}
//逐个账单红冲,任一账单校验不通过时事务整体回滚
Boolean flag = true;
for (BillManage originalBill : billManageList) {
flag = redFlushSingleBill(originalBill, billManageDTO.getRedFlushRemark(), loginUser) && flag;
}
return flag;
}
/**
* 红冲单个账单:生成金额为负数的红冲账单对冲原账单,同步镜像计费流水与账单明细
*/
private Boolean redFlushSingleBill(BillManage originalBill, String redFlushRemark, LoginUser loginUser) {
if (ObjectUtil.equal(originalBill.getBillType(), 2)) {
throw new ServiceException("仅支持应收账单红冲");
throw new ServiceException("账单" + originalBill.getBillNumber() + "为付款账单,仅支持应收账单红冲");
}
if (!ObjectUtil.equal(originalBill.getBillState(), 5)) {
throw new ServiceException("仅已收款状态的账单可以红冲,请刷新后重试");
throw new ServiceException("账单" + originalBill.getBillNumber() + "不是已收款状态,仅已收款状态的账单可以红冲,请刷新后重试");
}
//校验账单是否已红冲,避免重复生成红冲账单
BillOperationLogDO redFlushLogQuery = new BillOperationLogDO();
@@ -790,7 +813,7 @@ public class BillManageDomainService {
redFlushLogQuery.setOperationType(13);
List<BillOperationLogPO> redFlushLogList = billOperationLogDomainService.queryList(redFlushLogQuery);
if (null != redFlushLogList && redFlushLogList.stream().anyMatch(info -> ObjectUtil.equal(info.getDelFlag(), 1))) {
throw new ServiceException("账单已红冲,不能重复红冲");
throw new ServiceException("账单" + originalBill.getBillNumber() + "已红冲,不能重复红冲");
}
//生成红冲账单编号
String billNumber = OrderSequence.getOrderCode("ZD");
@@ -832,8 +855,8 @@ public class BillManageDomainService {
redBill.setSkNcId(null);
//红冲原因写入账单备注
String billRemark = "红冲原账单编号:" + originalBill.getBillNumber();
if (StringUtils.isNotEmpty(billManageDTO.getRedFlushRemark())) {
billRemark = billRemark + ",红冲原因:" + billManageDTO.getRedFlushRemark();
if (StringUtils.isNotEmpty(redFlushRemark)) {
billRemark = billRemark + ",红冲原因:" + redFlushRemark;
}
redBill.setBillRemark(billRemark);
redBill.setDelFlag(1);
@@ -18,6 +18,7 @@ import com.mhd.bms.infrastructure.utils.UniqueKeyUtil;
import com.mhd.bms.interfaces.dto.billingStatement.BillingStatementDTO;
import com.mhd.bms.interfaces.dto.billManage.BillManageExportVO;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.core.utils.poi.ExcelUtil;
import com.mhd.common.log.annotation.Log;
import com.mhd.common.log.enums.BusinessType;
@@ -400,18 +401,26 @@ public class BillManageApi extends BaseController{
@PostMapping("/redFlushBill")
public AjaxResult redFlushBill(@RequestBody BillManageDTO billManageDTO)
{
if(billManageDTO.getBillManageId() == null){
if(!StringUtils.isNotEmpty(billManageDTO.getBillManageIds())){
throw new ServiceException("账单id不能为空");
}
//加锁
RLock lock = null;
RedisLockTypeEnum redisLockTypeEnum = RedisLockTypeEnum.BMS;
String key = redisLockTypeEnum.getUniqueKey(UniqueKeyUtil.getBillingKey(String.valueOf(billManageDTO.getBillManageId())));
//批量加锁
RedissonMultiLock redissonMultiLock = null;
boolean lockFlag = false;
try {
lock = redisLock.getRLock(key);
RedisLockTypeEnum redisLockTypeEnum = RedisLockTypeEnum.BMS;
List<RLock> locks = new ArrayList<>();
Set<String> billIdSet = Stream.of(billManageDTO.getBillManageIds().split(",")).filter(StringUtils::isNotEmpty).map(String::trim).collect(Collectors.toSet());
billIdSet.forEach(x -> {
//获取唯一key值
String key = redisLockTypeEnum.getUniqueKey(UniqueKeyUtil.getBillingKey(x));
locks.add(redisLock.getRLock(key));
});
redissonMultiLock = new RedissonMultiLock(locks.toArray(new RLock[billIdSet.size()]));
//尝试获取锁 不等待 持有锁10分钟
if (!lock.tryLock(-1, 10, TimeUnit.MINUTES)) {
lock = null;
lockFlag = redissonMultiLock.tryLock(-1, 10, TimeUnit.MINUTES);
if (!lockFlag) {
redissonMultiLock = null;
throw new ServiceException("账单正在操作中,请稍后重试");
}
log.info("红冲账单加锁成功");
@@ -420,8 +429,8 @@ public class BillManageApi extends BaseController{
}catch (Exception e){
return AjaxResult.error("红冲账单失败:"+e.getMessage());
} finally {
if (lock != null && lock.isHeldByCurrentThread()){
lock.unlock();
if (redissonMultiLock != null && lockFlag){
redissonMultiLock.unlock();
log.info("红冲账单释放锁成功");
}
}