diff --git a/src/main/java/com/bim/api/config/JacksonConfig.java b/src/main/java/com/bim/api/config/JacksonConfig.java new file mode 100644 index 0000000..0f4e4d5 --- /dev/null +++ b/src/main/java/com/bim/api/config/JacksonConfig.java @@ -0,0 +1,17 @@ +package com.bim.api.config; + +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JacksonConfig { + + @Bean + public Jackson2ObjectMapperBuilderCustomizer longToStringCustomizer() { + return builder -> builder + .serializerByType(Long.class, ToStringSerializer.instance) + .serializerByType(Long.TYPE, ToStringSerializer.instance); + } +} diff --git a/src/main/java/com/bim/api/controller/BimController.java b/src/main/java/com/bim/api/controller/BimController.java index b126eb5..46af206 100644 --- a/src/main/java/com/bim/api/controller/BimController.java +++ b/src/main/java/com/bim/api/controller/BimController.java @@ -47,13 +47,15 @@ public class BimController { } @GetMapping("/progressData") - public Map getProgressData(@RequestParam String date) { - return progressDataService.getOrCreateTask(date); + public Map getProgressData(@RequestParam String date, + @RequestParam(required = false) Long modelId) { + return progressDataService.getOrCreateTask(date, modelId); } @GetMapping("/progressData/result") - public Map getProgressDataResult(@RequestParam String date) { - return progressDataService.getTaskResultByDate(date); + public Map getProgressDataResult(@RequestParam String date, + @RequestParam(required = false) Long modelId) { + return progressDataService.getTaskResultByDate(date, modelId); } @PostMapping("/getPjDayListByPositionId") diff --git a/src/main/java/com/bim/api/service/ProgressDataService.java b/src/main/java/com/bim/api/service/ProgressDataService.java index 2d04b92..092ec4d 100644 --- a/src/main/java/com/bim/api/service/ProgressDataService.java +++ b/src/main/java/com/bim/api/service/ProgressDataService.java @@ -1,5 +1,6 @@ package com.bim.api.service; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.bim.api.entity.ActAmtResponse; import com.bim.api.entity.PartCodeRelation; @@ -15,6 +16,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -42,36 +44,38 @@ public class ProgressDataService extends ServiceImpl getOrCreateTask(String date) { + public Map getOrCreateTask(String date, Long modelId) { String normalizedDate = normalizeDate(date); + String taskScope = buildTaskScope(normalizedDate, modelId); Map result = new HashMap<>(); result.put("date", normalizedDate); + result.put("modelId", modelId == null ? null : String.valueOf(modelId)); - String status = getTaskStatusByDate(normalizedDate); + String status = getTaskStatusByDate(taskScope); if ("COMPLETED".equals(status)) { - Object cachedData = redisTemplate.opsForValue().get(buildTaskKey(normalizedDate, SUFFIX_RESULT)); + Object cachedData = redisTemplate.opsForValue().get(buildTaskKey(taskScope, SUFFIX_RESULT)); if (cachedData != null) { - Integer cachedTotal = (Integer) redisTemplate.opsForValue().get(buildTaskKey(normalizedDate, SUFFIX_TOTAL)); - int dbTotal = list().size(); - if (cachedTotal != null && cachedTotal == dbTotal) { + Integer cachedTotal = (Integer) redisTemplate.opsForValue().get(buildTaskKey(taskScope, SUFFIX_TOTAL)); + int dbTotal = listRelationsByModel(modelId).size(); + if (cachedTotal != null && cachedTotal == dbTotal && hasCurrentResultShape(cachedData)) { result.put("status", "COMPLETED"); return result; } - clearTaskCache(normalizedDate); + clearTaskCache(taskScope); } else { result.put("status", "COMPLETED"); return result; } } - String processing = (String) redisTemplate.opsForValue().get(buildProcessingKey(normalizedDate)); + String processing = (String) redisTemplate.opsForValue().get(buildProcessingKey(taskScope)); if (processing != null) { result.put("status", "PROCESSING"); return result; } Boolean lockResult = redisTemplate.opsForValue().setIfAbsent( - buildProcessingKey(normalizedDate), + buildProcessingKey(taskScope), "1", TASK_TTL_MINUTES, TimeUnit.MINUTES @@ -81,29 +85,31 @@ public class ProgressDataService extends ServiceImpl getTaskResultByDate(String date) { + public Map getTaskResultByDate(String date, Long modelId) { String normalizedDate = normalizeDate(date); + String taskScope = buildTaskScope(normalizedDate, modelId); Map result = new HashMap<>(); result.put("date", normalizedDate); + result.put("modelId", modelId == null ? null : String.valueOf(modelId)); - String status = getTaskStatusByDate(normalizedDate); + String status = getTaskStatusByDate(taskScope); result.put("status", status); if (status == null) { - String processing = (String) redisTemplate.opsForValue().get(buildProcessingKey(normalizedDate)); + String processing = (String) redisTemplate.opsForValue().get(buildProcessingKey(taskScope)); result.put("status", processing != null ? "PROCESSING" : "NOT_FOUND"); return result; } - Integer total = (Integer) redisTemplate.opsForValue().get(buildTaskKey(normalizedDate, SUFFIX_TOTAL)); - Integer current = (Integer) redisTemplate.opsForValue().get(buildTaskKey(normalizedDate, SUFFIX_CURRENT)); + Integer total = (Integer) redisTemplate.opsForValue().get(buildTaskKey(taskScope, SUFFIX_TOTAL)); + Integer current = (Integer) redisTemplate.opsForValue().get(buildTaskKey(taskScope, SUFFIX_CURRENT)); result.put("total", total != null ? total : 0); result.put("current", current != null ? current : 0); @@ -115,12 +121,12 @@ public class ProgressDataService extends ServiceImpl buildActAmtRequest(String projectId, String positionId, String period) { @@ -175,25 +185,28 @@ public class ProgressDataService extends ServiceImpl { try { - List relations = list(); + List relations = listRelationsByModel(modelId); int total = relations.size(); - setTaskValue(date, SUFFIX_TOTAL, total); - setTaskValue(date, SUFFIX_CURRENT, 0); + setTaskValue(taskScope, SUFFIX_TOTAL, total); + setTaskValue(taskScope, SUFFIX_CURRENT, 0); List> results = new ArrayList<>(); List> rawActAmtResults = new ArrayList<>(); int current = 0; - for (PartCodeRelation relation : relations) { + Map> groupedRelations = groupRelationsByPart(relations); + for (List partRelations : groupedRelations.values()) { + PartCodeRelation relation = partRelations.get(0); Map item = new HashMap<>(); item.put("partId", relation.getPartId()); item.put("codeData", relation.getCodeData()); + item.put("codeList", buildCodeList(partRelations)); item.put("isLeaf", relation.getIsLeaf()); try { @@ -213,7 +226,7 @@ public class ProgressDataService extends ServiceImpl listRelationsByModel(Long modelId) { + return list(new LambdaQueryWrapper() + .eq(modelId != null, PartCodeRelation::getModelId, modelId)); + } + + private boolean hasCurrentResultShape(Object cachedData) { + if (!(cachedData instanceof List cachedList)) { + return false; } - double sum = 0; - int count = 0; + if (cachedList.isEmpty()) { + return true; + } + Object first = cachedList.get(0); + return first instanceof Map cachedItem + && cachedItem.containsKey("codeList") + && cachedItem.containsKey("progressNumerator") + && cachedItem.containsKey("progressDenominator"); + } + + private Map> groupRelationsByPart(List relations) { + Map> grouped = new LinkedHashMap<>(); + for (PartCodeRelation relation : relations) { + if (relation == null || relation.getPartId() == null || relation.getPartId().isBlank()) { + continue; + } + String key = relation.getPartId() + "|" + relation.getIsLeaf(); + grouped.computeIfAbsent(key, ignored -> new ArrayList<>()).add(relation); + } + return grouped; + } + + private List> buildCodeList(List relations) { + List> codeList = new ArrayList<>(); + for (PartCodeRelation relation : relations) { + Map codeItem = new HashMap<>(); + codeItem.put("codeId", relation.getCodeId()); + codeItem.put("code", relation.getCodeId()); + codeItem.put("codeData", relation.getCodeData()); + codeItem.put("modelId", relation.getModelId() == null ? null : String.valueOf(relation.getModelId())); + codeList.add(codeItem); + } + return codeList; + } + + private ProgressAmount calculateProgressAmountByActAmt(ActAmtResponse response) { + if (response == null || response.getData() == null || response.getData().isEmpty()) { + return new ProgressAmount(0, 0); + } + double numeratorSum = 0; + double denominatorSum = 0; for (ActAmtResponse.ActAmtData data : response.getData()) { if (data == null) { continue; - } - Double numerator = data.getActAmt(); - Double denominator = data.getMeteringAmt(); - double ratio = 0; - if (numerator != null && denominator != null && denominator != 0) { - ratio = numerator / denominator; } - sum += ratio; - count++; - } - return count == 0 ? 0 : sum / count; + numeratorSum += safeDouble(data.getActAmt()); + denominatorSum += safeDouble(data.getMeteringAmt()); + } + return new ProgressAmount(numeratorSum, denominatorSum); } - private double calculateAverageByPjDay(PjDayListResponse response) { + private ProgressAmount calculateProgressAmountByPjDay(PjDayListResponse response) { if (response == null || response.getData() == null || response.getData().isEmpty()) { - return 0; + return new ProgressAmount(0, 0); } - double sum = 0; - int count = 0; + double numeratorSum = 0; + double denominatorSum = 0; for (PjDayListResponse.PjDayData data : response.getData()) { if (data == null) { continue; } - Double numerator = data.getTotalAmt(); - Double denominator = data.getMeteringAmt(); - double ratio = 0; - if (numerator != null && denominator != null && denominator != 0) { - ratio = numerator / denominator; - } - sum += ratio; - count++; + numeratorSum += safeDouble(data.getTotalAmt()); + denominatorSum += safeDouble(data.getMeteringAmt()); + } + return new ProgressAmount(numeratorSum, denominatorSum); + } + + private double safeDouble(Double value) { + return value == null || Double.isNaN(value) || Double.isInfinite(value) ? 0 : value; + } + + private record ProgressAmount(double numerator, double denominator) { + double ratio() { + return denominator == 0 ? 0 : numerator / denominator; } - return count == 0 ? 0 : sum / count; } }