|
@@ -16,19 +16,25 @@
|
|
|
*/
|
|
|
package org.springblade.meter.controller;
|
|
|
|
|
|
+import com.alibaba.nacos.shaded.com.google.protobuf.ServiceException;
|
|
|
import io.swagger.annotations.*;
|
|
|
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
|
|
import lombok.AllArgsConstructor;
|
|
|
|
|
|
import javax.validation.Valid;
|
|
|
|
|
|
+import org.redisson.Redisson;
|
|
|
+import org.redisson.api.RLock;
|
|
|
+import org.redisson.api.RedissonClient;
|
|
|
import org.springblade.core.mp.support.Query;
|
|
|
+import org.springblade.core.redis.cache.BladeRedis;
|
|
|
import org.springblade.core.tool.api.R;
|
|
|
import org.springblade.core.tool.utils.Func;
|
|
|
import org.springblade.meter.dto.MiddleMeterApplyDTO;
|
|
|
import org.springblade.meter.dto.WbsNodeDTO;
|
|
|
import org.springblade.meter.entity.AttachmentForm;
|
|
|
import org.springblade.meter.vo.*;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
import org.springframework.web.bind.annotation.RequestParam;
|
|
@@ -39,6 +45,7 @@ import org.springblade.core.boot.ctrl.BladeController;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
import java.util.List;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
/**
|
|
|
* 中间计量申请表 控制器
|
|
@@ -53,6 +60,9 @@ import java.util.List;
|
|
|
public class MiddleMeterApplyController extends BladeController {
|
|
|
|
|
|
private final IMiddleMeterApplyService middleMeterApplyService;
|
|
|
+ private final BladeRedis bladeRedis;
|
|
|
+ @Autowired
|
|
|
+ private RedissonClient redissonClient;
|
|
|
|
|
|
|
|
|
/**
|
|
@@ -205,10 +215,59 @@ public class MiddleMeterApplyController extends BladeController {
|
|
|
@ApiImplicitParam(name = "contractId", value = "合同id", required = true),
|
|
|
@ApiImplicitParam(name = "contractPeriodId", value = "合同计量期id", required = true)
|
|
|
})
|
|
|
- public R<String> getMeterNumber(MiddleMeterApply middleMeterApply) {
|
|
|
- return R.data(middleMeterApplyService.getMeterNumber(middleMeterApply));
|
|
|
+ public R<String> getMeterNumber(MiddleMeterApply middleMeterApply) throws ServiceException {
|
|
|
+ RLock lock = redissonClient.getLock("getMeterNumber:" + middleMeterApply.getContractId() + ":" + middleMeterApply.getContractPeriodId());
|
|
|
+ // 不指定leaseTime,Redisson会自动续期(默认30秒,可通过Config配置)
|
|
|
+ lock.lock();
|
|
|
+ try {
|
|
|
+ String meterNumber = middleMeterApplyService.getMeterNumber(middleMeterApply);
|
|
|
+ String redisKey = "getMeterNumber:" + middleMeterApply.getContractId() + ":" + middleMeterApply.getContractPeriodId() + ":" + meterNumber;
|
|
|
+
|
|
|
+ if (bladeRedis.exists(redisKey)) {
|
|
|
+ // 初始编号已存在,生成新编号
|
|
|
+ String meterNumber1 = getMeterNumber1(meterNumber, middleMeterApply.getContractId(), middleMeterApply.getContractPeriodId());
|
|
|
+ String newRedisKey = "getMeterNumber:" + middleMeterApply.getContractId() + ":" + middleMeterApply.getContractPeriodId() + ":" + meterNumber1;
|
|
|
+ bladeRedis.setEx(newRedisKey, meterNumber1, 300L);
|
|
|
+ return R.data(meterNumber1); // 返回新编号
|
|
|
+ } else {
|
|
|
+ bladeRedis.setEx(redisKey, meterNumber, 300L);
|
|
|
+ return R.data(meterNumber);
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ // 确保锁释放(判断是否持有锁,避免异常场景下误释放)
|
|
|
+ if (lock.isHeldByCurrentThread()) {
|
|
|
+ lock.unlock();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getMeterNumber1(String meterNumber, Long contractId, Long contractPeriodId) throws ServiceException {
|
|
|
+ // 校验编号格式,避免substring异常
|
|
|
+ int lastDashIndex = meterNumber.lastIndexOf("-");
|
|
|
+ if (lastDashIndex == -1) {
|
|
|
+ throw new ServiceException("编号格式错误,缺少分隔符 '-'");
|
|
|
+ }
|
|
|
+ String prefix = meterNumber.substring(0, lastDashIndex + 1);
|
|
|
+ int lastNumber = Integer.parseInt(meterNumber.substring(lastDashIndex + 1));
|
|
|
+
|
|
|
+ // 循环生成新编号,直到不存在于Redis中
|
|
|
+ while (true) {
|
|
|
+ lastNumber++;
|
|
|
+ String newMeterNumber = prefix + lastNumber;
|
|
|
+ String redisKey = "getMeterNumber:" + contractId + ":" + contractPeriodId + ":" + newMeterNumber;
|
|
|
+ // 如果新编号不存在,则返回
|
|
|
+ if (!bladeRedis.exists(redisKey)) {
|
|
|
+ return newMeterNumber;
|
|
|
+ }
|
|
|
+ // 防止无限循环(极端情况:连续N个编号都被占用,可加最大次数限制)
|
|
|
+ if (lastNumber > 1000) { // 例如最多尝试1000次
|
|
|
+ throw new ServiceException("生成编号失败,尝试次数过多");
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 获取本期计量总金额
|
|
|
*/
|