cr 21 цаг өмнө
parent
commit
bc868b09dd

+ 33 - 237
blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/MiddleMeterApplyServiceImpl.java

@@ -698,256 +698,52 @@ public class MiddleMeterApplyServiceImpl extends BaseServiceImpl<MiddleMeterAppl
 
     @Override
     public String getMeterNumber(MiddleMeterApply apply) {
-        if (apply.getContractPeriodId() == -1) {
+        //如果计量期id为-1则代表不用查询
+        if (apply.getContractPeriodId() == -1){
             return "";
         }
-
-        String lockKey = "meter_number_lock:" + apply.getContractId() + ":" + apply.getContractPeriodId();
-        String requestId = UUID.randomUUID().toString();
-
-        try {
-            // 获取分布式锁
-            if (!tryLock(lockKey, requestId, 10L)) {
-                return "";
-            }
-
-            // 生成并检查编号
-            int maxRetries = 5;
-            for (int retryCount = 0; retryCount < maxRetries; retryCount++) {
-                String number = generateMeterNumber(apply);
-                if (StringUtils.isBlank(number)) {
-                    continue;
-                }
-
-                // 在Redis中预占编号
-                if (reserveNumber(number)) {
-                    return number;
-                }
-
-                try {
-                    Thread.sleep(100 * (retryCount + 1));
-                } catch (InterruptedException e) {
-                    Thread.currentThread().interrupt();
-                    break;
-                }
-            }
-            return "";
-
-        } finally {
-            releaseLock(lockKey, requestId);
-        }
-    }
-
-    /**
-     * 使用setEx实现分布式锁
-     */
-    private boolean tryLock(String lockKey, String requestId, long expireSeconds) {
-        int maxRetry = 3;
-        for (int i = 0; i < maxRetry; i++) {
-            // 先检查是否已存在锁
-            if (!bladeRedis.exists(lockKey)) {
-                // 不存在时尝试设置锁
-                bladeRedis.setEx(lockKey, requestId, expireSeconds);
-
-                // 再次检查确认自己是锁的持有者
-                String currentOwner = bladeRedis.get(lockKey);
-                if (requestId.equals(currentOwner)) {
-                    return true;
-                }
-            }
-
-            if (i < maxRetry - 1) {
-                try {
-                    Thread.sleep(100 * (i + 1));
-                } catch (InterruptedException e) {
-                    Thread.currentThread().interrupt();
-                    break;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * 安全释放锁
-     */
-    private void releaseLock(String lockKey, String requestId) {
-        try {
-            String currentValue = bladeRedis.get(lockKey);
-            if (requestId.equals(currentValue)) {
-                bladeRedis.del(lockKey);
-            }
-        } catch (Exception e) {
-            log.error("释放锁失败", e);
-        }
-    }
-
-    /**
-     * 预占编号 - 使用setEx + 检查机制
-     */
-    private boolean reserveNumber(String number) {
-        String numberKey = "meter_number_reserve:" + number;
-
-        // 先检查是否已存在
-        if (bladeRedis.exists(numberKey)) {
-            return false;
-        }
-
-        // 尝试设置,如果在此期间有其他线程设置,可能会覆盖,但通过value来区分
-        String reserveValue = "reserved:" + System.currentTimeMillis() + ":" + Thread.currentThread().getId();
-        bladeRedis.setEx(numberKey, reserveValue, 300L); // 5分钟过期
-
-        // 再次检查确认我们是设置者
-        String currentValue = bladeRedis.get(numberKey);
-        return reserveValue.equals(currentValue);
-    }
-
-    private String generateMeterNumber(MiddleMeterApply apply) {
         StringBuilder str = new StringBuilder();
-
-        // 获取合同信息
+        //获取合同信息
         ContractInfo info = baseMapper.getContractInfo(apply.getContractId());
         String contractNumber = info.getContractNumber();
-        if (StringUtils.isBlank(contractNumber)) {
-            return "";
+        if (StringUtils.isBlank(contractNumber)){
+            throw new ServiceException("未获取到当前合同段编号信息");
         }
-        str.append(contractNumber).append("-");
-
-        // 获取计量期信息
+        str.append(contractNumber+"-");
+        //获取计量期信息
         ContractMeterPeriod contractMeterPeriod = contractMeterPeriodService.getById(apply.getContractPeriodId());
-        if (contractMeterPeriod == null || StringUtils.isBlank(contractMeterPeriod.getPeriodNumber())) {
-            return "";
-        }
-        str.append(contractMeterPeriod.getPeriodNumber()).append("-");
-
-        // 从Redis获取流水号
-        Integer nextSerial = getNextSerialNumber(apply);
-        if (nextSerial == null) {
-            log.error("获取流水号失败");
-            return "";
-        }
-        str.append(nextSerial);
-        return str.toString();
-    }
-
-    /**
-     * 使用Redis管理可用流水号
-     */
-    private Integer getNextSerialNumber(MiddleMeterApply apply) {
-        String serialKey = "meter_serial_available:" + apply.getContractId() + ":" + apply.getContractPeriodId();
-
-        try {
-            // 先尝试从Redis获取最小可用流水号
-            String minSerial = bladeRedis.lIndex(serialKey, 0);
-            if (minSerial != null) {
-                // 弹出最小的可用流水号
-                String popped = bladeRedis.lPop(serialKey);
-                if (popped != null) {
-                    return Integer.parseInt(popped);
-                }
-            }
-
-            // Redis中没有可用流水号,从数据库初始化
-            return initAndGetSerialFromRedis(apply);
-
-        } catch (Exception e) {
-            log.error("Redis获取流水号异常", e);
-            return getNextSerialNumberFromDB(apply);
+        if (contractMeterPeriod == null || StringUtils.isBlank(contractMeterPeriod.getPeriodNumber())){
+            throw new ServiceException("未获取到计量期期号信息");
         }
-    }
-
-    /**
-     * 初始化Redis中的流水号池
-     */
-    private Integer initAndGetSerialFromRedis(MiddleMeterApply apply) {
-        String lockKey = "serial_init_lock:" + apply.getContractId() + ":" + apply.getContractPeriodId();
-        String requestId = UUID.randomUUID().toString();
-
-        try {
-            // 加锁防止重复初始化
-            if (tryLock(lockKey, requestId, 10L)) {
-                // 再次检查,防止其他线程已经初始化完成
-                String serialKey = "meter_serial_available:" + apply.getContractId() + ":" + apply.getContractPeriodId();
-                if (bladeRedis.lLen(serialKey) > 0) {
-                    String popped = bladeRedis.lPop(serialKey);
-                    return popped != null ? Integer.parseInt(popped) : null;
-                }
-
-                // 从数据库获取已使用的流水号
-                List<Integer> usedSerials = getUsedSerialsFromDB(apply);
-                int nextSerial = findNextAvailableSerial(usedSerials);
-
-                // 将后续的可用流水号预先放入Redis
-                for (int i = nextSerial + 1; i <= nextSerial + 10; i++) {
-                    bladeRedis.rPush(serialKey, String.valueOf(i));
+        str.append(contractMeterPeriod.getPeriodNumber()+"-");
+        //获取流水号:当前合同段存在的当前计量期的申请单总数+1
+        List<MiddleMeterApply> allAPPly = baseMapper.getAllAPPly(apply.getContractId(), apply.getContractPeriodId());
+        if (allAPPly.size() == 0){
+            str.append(1);
+        }else {
+            List<Integer> list = allAPPly.stream().filter(l -> l.getApproveStatus() != null).map(l -> l.getApproveStatus()).sorted().collect(Collectors.toList());
+            if (list.size() == 0 || list.get(0) != 1){
+                str.append(1);
+            }else {
+                for (int i = 0; i < list.size() - 1; i++) {
+                    Integer num = list.get(i);
+                    if (num .equals(list.get(i+1)) ){
+                        throw new ServiceException("计量期期号出现相同,请联系管理员");
+                    }
+                    Integer j = ++num;
+                    String j2 = j.toString();
+                    String j3 = list.get(i + 1).toString();
+                    if (!j2.equals(j3)){
+                        str.append(num);
+                        return str.toString();
+                    }
                 }
-                bladeRedis.expire(serialKey, 86400L);
-
-                return nextSerial;
-            } else {
-                // 等待其他线程初始化完成
-                Thread.sleep(100);
-                return getNextSerialNumber(apply); // 重试
+                str.append(list.size()+1);
             }
-        } catch (Exception e) {
-            log.error("初始化流水号池失败", e);
-            return getNextSerialNumberFromDB(apply);
-        } finally {
-            releaseLock(lockKey, requestId);
-        }
-    }
-
-    /**
-     * 从数据库获取已使用的流水号
-     */
-    private List<Integer> getUsedSerialsFromDB(MiddleMeterApply apply) {
-        try {
-            List<MiddleMeterApply> allApply = baseMapper.getAllAPPly(apply.getContractId(), apply.getContractPeriodId());
-            return allApply.stream()
-                    .filter(l -> l.getApproveStatus() != null)
-                    .map(MiddleMeterApply::getApproveStatus)
-                    .sorted()
-                    .collect(Collectors.toList());
-        } catch (Exception e) {
-            log.error("从数据库获取已使用流水号失败", e);
-            return new ArrayList<>();
-        }
-    }
 
-    /**
-     * 查找下一个可用的流水号
-     */
-    private int findNextAvailableSerial(List<Integer> usedSerials) {
-        if (usedSerials.isEmpty()) {
-            return 1;
-        }
-
-        // 查找第一个可用的流水号
-        for (int i = 0; i < usedSerials.size(); i++) {
-            if (usedSerials.get(i) != i + 1) {
-                return i + 1;
-            }
-        }
-
-        // 如果所有序号都连续,返回下一个
-        return usedSerials.size() + 1;
-    }
-
-    /**
-     * 从数据库获取流水号(备用方案)
-     */
-    private Integer getNextSerialNumberFromDB(MiddleMeterApply apply) {
-        try {
-            List<Integer> usedSerials = getUsedSerialsFromDB(apply);
-            return findNextAvailableSerial(usedSerials);
-        } catch (Exception e) {
-            log.error("从数据库获取流水号失败", e);
-            return null;
         }
+        return str.toString();
     }
-
-
-
     /**
      * 获取本期计量总金额
      */