|
@@ -28,6 +28,7 @@ import org.springblade.common.utils.SnowFlakeUtil;
|
|
|
import org.springblade.core.log.exception.ServiceException;
|
|
|
import org.springblade.core.mp.base.BaseServiceImpl;
|
|
|
import org.springblade.core.mp.support.Query;
|
|
|
+import org.springblade.core.redis.cache.BladeRedis;
|
|
|
import org.springblade.core.tool.utils.Func;
|
|
|
import org.springblade.core.tool.utils.ObjectUtil;
|
|
|
import org.springblade.manager.entity.ContractInfo;
|
|
@@ -83,6 +84,7 @@ public class MiddleMeterApplyServiceImpl extends BaseServiceImpl<MiddleMeterAppl
|
|
|
|
|
|
private final IAttachmentFormServiceTask attachmentFormServiceTask;
|
|
|
|
|
|
+ private final BladeRedis bladeRedis;
|
|
|
|
|
|
|
|
|
/**
|
|
@@ -699,53 +701,150 @@ public class MiddleMeterApplyServiceImpl extends BaseServiceImpl<MiddleMeterAppl
|
|
|
*/
|
|
|
@Override
|
|
|
public String getMeterNumber(MiddleMeterApply apply) {
|
|
|
- //如果计量期id为-1则代表不用查询
|
|
|
- if (apply.getContractPeriodId() == -1){
|
|
|
+ if (apply.getContractPeriodId() == -1) {
|
|
|
return "";
|
|
|
}
|
|
|
+
|
|
|
+ String lockKey = "meter_number:" + apply.getContractId() + ":" + apply.getContractPeriodId();
|
|
|
+ String requestId = UUID.randomUUID().toString();
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 尝试获取分布式锁
|
|
|
+ boolean locked = false;
|
|
|
+ int lockRetry = 0;
|
|
|
+ int maxLockRetry = 3;
|
|
|
+
|
|
|
+ while (!locked && lockRetry < maxLockRetry) {
|
|
|
+ // 先检查是否已存在锁
|
|
|
+ if (!bladeRedis.exists(lockKey)) {
|
|
|
+ // 不存在时尝试设置锁
|
|
|
+ bladeRedis.setEx(lockKey, requestId,10L);
|
|
|
+ // 再次检查确认自己是锁的持有者
|
|
|
+ String currentOwner = bladeRedis.get(lockKey);
|
|
|
+ if (requestId.equals(currentOwner)) {
|
|
|
+ locked = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!locked) {
|
|
|
+ lockRetry++;
|
|
|
+ try {
|
|
|
+ Thread.sleep(100 * lockRetry);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!locked) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ // 获取锁成功后的业务逻辑
|
|
|
+ int maxRetries = 5;
|
|
|
+ int retryCount = 0;
|
|
|
+ while (retryCount < maxRetries) {
|
|
|
+ try {
|
|
|
+ String number = generateMeterNumber(apply);
|
|
|
+ if (!isNumberExists(number)) {
|
|
|
+ return number;
|
|
|
+ }
|
|
|
+ retryCount++;
|
|
|
+ try {
|
|
|
+ Thread.sleep(100 * retryCount);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ retryCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+
|
|
|
+ } finally {
|
|
|
+ // 安全释放锁
|
|
|
+ try {
|
|
|
+ String currentValue = bladeRedis.get(lockKey);
|
|
|
+ if (requestId.equals(currentValue)) {
|
|
|
+ bladeRedis.del(lockKey);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成计量单编号
|
|
|
+ */
|
|
|
+ private String generateMeterNumber(MiddleMeterApply apply) {
|
|
|
StringBuilder str = new StringBuilder();
|
|
|
- //获取合同信息
|
|
|
+
|
|
|
+ // 获取合同信息
|
|
|
ContractInfo info = baseMapper.getContractInfo(apply.getContractId());
|
|
|
String contractNumber = info.getContractNumber();
|
|
|
- if (StringUtils.isBlank(contractNumber)){
|
|
|
- throw new ServiceException("未获取到当前合同段编号信息");
|
|
|
+ if (StringUtils.isBlank(contractNumber)) {
|
|
|
+ return "";
|
|
|
}
|
|
|
- str.append(contractNumber+"-");
|
|
|
- //获取计量期信息
|
|
|
+ str.append(contractNumber).append("-");
|
|
|
+
|
|
|
+ // 获取计量期信息
|
|
|
ContractMeterPeriod contractMeterPeriod = contractMeterPeriodService.getById(apply.getContractPeriodId());
|
|
|
- if (contractMeterPeriod == null || StringUtils.isBlank(contractMeterPeriod.getPeriodNumber())){
|
|
|
- throw new ServiceException("未获取到计量期期号信息");
|
|
|
+ if (contractMeterPeriod == null || StringUtils.isBlank(contractMeterPeriod.getPeriodNumber())) {
|
|
|
+ return "";
|
|
|
}
|
|
|
- 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();
|
|
|
- }
|
|
|
- }
|
|
|
- str.append(list.size()+1);
|
|
|
- }
|
|
|
+ str.append(contractMeterPeriod.getPeriodNumber()).append("-");
|
|
|
|
|
|
+ // 获取流水号
|
|
|
+ Integer nextSerial = getNextSerialNumber(apply);
|
|
|
+ if (nextSerial == null) {
|
|
|
+ log.error("获取流水号失败");
|
|
|
+ return "";
|
|
|
}
|
|
|
+ str.append(nextSerial);
|
|
|
return str.toString();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取下一个流水号
|
|
|
+ */
|
|
|
+ private Integer getNextSerialNumber(MiddleMeterApply apply) {
|
|
|
+ List<MiddleMeterApply> allApply = baseMapper.getAllAPPly(apply.getContractId(), apply.getContractPeriodId());
|
|
|
+ if (allApply.isEmpty()) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ // 提取已使用的流水号
|
|
|
+ List<Integer> usedSerials = allApply.stream()
|
|
|
+ .filter(l -> l.getApproveStatus() != null)
|
|
|
+ .map(MiddleMeterApply::getApproveStatus)
|
|
|
+ .sorted()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ 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 boolean isNumberExists(String number) {
|
|
|
+ if (StringUtils.isBlank(number)) {
|
|
|
+ return true; // 空编号视为已存在,需要重新生成
|
|
|
+ }
|
|
|
+ LambdaQueryWrapper<MiddleMeterApply> query = new LambdaQueryWrapper<>();
|
|
|
+ query.eq(MiddleMeterApply::getMeterNumber, number);
|
|
|
+ return count(query) > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* 获取本期计量总金额
|
|
|
*/
|