From 76200f4c3871ce387cd6c00acd248fb4114c75b9 Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Tue, 16 Jun 2026 16:26:10 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A6=85=E9=81=93bug#1699=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../executor/dal/dataobject/plan/PlanDO.java | 10 + .../executor/dal/mysql/plan/PlanMapper.java | 18 ++ .../optimizeplan/OptimizePlanServiceImpl.java | 22 +- .../order/OrderStatisticsServiceImpl.java | 211 +++++++----------- .../main/resources/mapper/plan/PlanMapper.xml | 47 ++++ 5 files changed, 177 insertions(+), 131 deletions(-) diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/plan/PlanDO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/plan/PlanDO.java index 6eae82129..157f654ea 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/plan/PlanDO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/plan/PlanDO.java @@ -113,6 +113,16 @@ public class PlanDO extends BaseDO { */ private String goodsId; + /** + * 实际优化材质编号 + */ + private String optimizeGoodsId; + + /** + * 优化时间 + */ + private LocalDateTime optimizeTime; + /** * 已优化板件数 */ diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plan/PlanMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plan/PlanMapper.java index f8da540fe..c18753b6f 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plan/PlanMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plan/PlanMapper.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.toolkit.Constants; import com.cf.imes.framework.common.enums.PlanStatusEnum; import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderGoodsPlateRespVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsReqVO; import com.cf.imes.module.executor.controller.admin.plan.vo.OrderGoodsResp; import com.cf.imes.module.executor.controller.admin.plan.vo.OrderPlanPlateStatisticsRespVO; @@ -174,4 +175,21 @@ public interface PlanMapper extends BaseMapperX { * @return */ int batchUpdatePlanSort(@Param("sortList") List sortVOList); + + /** + * 查询时间区间用量最大的10种商品编号 + * + * @param reqVO + * @return + */ + List selectPlanGoodsTopTen(@Param("req") OrderStatisticsReqVO reqVO); + + /** + * 查询商品编号范围按优化时间分组 + * + * @param goodsCodes + * @param reqVO + * @return + */ + List selectTopTenBoardCountGroupByOptimizeTime(@Param("goodsCodes") List goodsCodes, @Param("req") OrderStatisticsReqVO reqVO); } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanServiceImpl.java index 229435bf3..3e0957977 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanServiceImpl.java @@ -39,6 +39,7 @@ import com.cf.imes.framework.common.util.Assert.AssertUtils; import com.cf.imes.framework.common.util.json.JsonUtils; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.es.core.service.ESDocumentService; +import com.cf.imes.framework.mybatis.core.query.LambdaUpdateWrapperX; import com.cf.imes.framework.mybatis.core.query.QueryWrapperX; import com.cf.imes.module.executor.controller.admin.plan.bo.OrderIds; import com.cf.imes.module.executor.controller.admin.plan.bo.OrderSource; @@ -302,7 +303,7 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { return orderSource; } - throw new ServiceException(ErrorCodeConstants.SOURCE_NOT_EXITS_ERROR); + throw new ServiceException(SOURCE_NOT_EXITS_ERROR); } @@ -324,7 +325,7 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { plateDOS.stream() .map(PlateDetailDO::getModelData) .filter(StringUtils::isNotBlank) - .map(json -> JsonUtils.parseObject(json, OrderModelDO.class)) + .map(json -> parseObject(json, OrderModelDO.class)) .toList(); AssertUtils.notEmpty(models, ORDER_PLATE_MODEL_DATE_ERROR); @@ -391,7 +392,7 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { plateDetailRespVOS.stream() .map(PlateDetailDO::getModelData) .filter(StringUtils::isNotBlank) - .map(json -> JsonUtils.parseObject(json, OrderModelDO.class)) + .map(json -> parseObject(json, OrderModelDO.class)) .toList(); AssertUtils.notEmpty(models, ORDER_PLAN_PLATE_MODEL_DATE_ERROR); @@ -790,7 +791,7 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { resultPlateList.stream() .map(PlateDetailDO::getModelData) .filter(StringUtils::isNotBlank) - .map(json -> JsonUtils.parseObject(json, OrderModelDO.class)) + .map(json -> parseObject(json, OrderModelDO.class)) .toList(); AssertUtils.notEmpty(plateDetailRespVOS, ORDER_PLATE_MODEL_DATE_ERROR); @@ -1835,19 +1836,28 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { resetPlanPlateOptimizeStatus(planId, orderIds); if (CollUtil.isNotEmpty(layoutResultSummary)) { List optimizatePlateNoList = layoutResultSummary.stream().flatMap(summary -> summary.getPlacedBlockIds().stream()).toList(); + BoardLayoutResultSummary boardLayoutResultSummary = layoutResultSummary.get(0); // 已排大板数量 - int boardCount = layoutResultSummary.stream().mapToInt(BoardLayoutResultSummary::getBoardCount).sum(); + int boardCount = boardLayoutResultSummary.getBoardCount(); + // 优化大板编号 + List materialIds = boardLayoutResultSummary.getMaterialIds(); + String materialId = null; + if (CollUtil.isNotEmpty(materialIds)) { + materialId = materialIds.get(0); + } // 更新参与优化的板材的优化状态 int updatedCount = plateMapper.updatePlanPlateOptimizeStatus(planId, orderIds, optimizatePlateNoList);; if (updatedCount > 0) { - planMapper.update(new LambdaUpdateWrapper() + planMapper.update(new LambdaUpdateWrapperX() .eq(PlanDO::getId, planId) .eq(PlanDO::getDeleted, DeletedCodeEnum.NOT_DELETED.getStatus()) + .setIfPresent(PlanDO::getOptimizeGoodsId, materialId) .set(PlanDO::getOptimizedPlateNum, updatedCount) .set(PlanDO::getStatus, PlanStatusEnum.OPTIMIZED.getStatus()) .set(PlanDO::getScheduledBoardNum, boardCount) + .set(PlanDO::getOptimizeTime, LocalDateTime.now()) ); } } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsServiceImpl.java index 8763f4d65..7baf02609 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsServiceImpl.java @@ -411,137 +411,98 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { @Override public Map getBigPlateCountGroup(OrderStatisticsReqVO reqVO) { Map resultMap = new LinkedHashMap<>(); - Integer unit = reqVO.getUnit(); // 所有的日期集合 List dateList = getDateList(reqVO); - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - SearchResponse response; - try { - // 查询创建时间段内,数量最多的goods_id前十 - SearchRequest searchRequest = new SearchRequest.Builder() - .size(0) - .index(ORDER_OPTIMIZE_PLATE_MODEL.getIndex()) - .query(q -> - q.bool(b -> b - .must(m -> m.range(m1 -> m1.field(ORDER_REMAIN_PLATE_MODEL_CREATE_TIME_FIELDNAME) - .from(reqVO.getCreateTime()[0].format(dateTimeFormatter)) - .to(reqVO.getCreateTime()[1].format(dateTimeFormatter)))) - .must(m -> m.match(m2 -> m2.field("organId").query(SecurityFrameworkUtils.getUserOrganId()))))) - .aggregations(ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME, - agg -> agg.terms(terms -> terms.field(ORDER_REMAIN_PLATE_MODEL_GOODS_ID_NAME).size(10).order(new NamedValue<>(ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME, SortOrder.Desc))) - .aggregations(ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME, sumAgg -> sumAgg.sum(sum -> sum.field("boardCount"))) - ) - .build(); + // 查询满足时间条件的最大用量材质编号 + List goodsCodes = planMapper.selectPlanGoodsTopTen(reqVO); - response = client.search(searchRequest, Map.class); - - Map goodsCountAggMap = response.aggregations(); - Aggregate goodsCountAgg = goodsCountAggMap.get(ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME); - - List goodsIds = new ArrayList<>(); - // 构建map:日期:goodsId、count - Map> goodsDateGroupMap = new HashMap<>(); - /** - * 获取数量最大前十的goodsId列表 - */ - goodsCountAgg.sterms().buckets().array().forEach(e -> goodsIds.add(e.key().stringValue())); - - if (CollUtil.isNotEmpty(goodsIds)) { - List goodsIdFieldValueList = goodsIds.stream().map(FieldValue::of).toList(); - // 查询创建时间段内,数量最多的goods_id前十下的数据,按goods_id和日期分组 - SearchRequest dateGroupRequest = new SearchRequest.Builder() - .size(0) - .index(ORDER_OPTIMIZE_PLATE_MODEL.getIndex()) - .query(q -> - q.bool(b -> b - .must(m -> m.range(m1 -> m1.field(ORDER_REMAIN_PLATE_MODEL_CREATE_TIME_FIELDNAME) - .from(reqVO.getCreateTime()[0].format(dateTimeFormatter)) - .to(reqVO.getCreateTime()[1].format(dateTimeFormatter)))) - .must(m -> m.match(m2 -> m2.field("organId").query(SecurityFrameworkUtils.getUserOrganId()))) - .must(m -> m.bool(m3 -> m3.must(t -> t.terms(gi -> gi.field(ORDER_REMAIN_PLATE_MODEL_GOODS_ID_NAME).terms(tv -> tv.value(goodsIdFieldValueList)))))) - ) - ) - .aggregations(ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME, agg -> - agg.terms(terms -> terms.field(ORDER_REMAIN_PLATE_MODEL_GOODS_ID_NAME)) - .aggregations(ORDER_REMAIN_PLATE_MODEL_DATE_GROUP_NAME, dateAgg -> dateAgg.dateHistogram(date -> getDateHistogram(unit, date.field(ORDER_REMAIN_PLATE_MODEL_CREATE_TIME_FIELDNAME))) - .aggregations(ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME, sumAgg -> sumAgg.sum(sum -> sum.field("boardCount"))) - ) - ) - .build(); - response = client.search(dateGroupRequest, Map.class); - Map goodsDateCountAggMap = response.aggregations(); - Aggregate goodsDateAgg = goodsDateCountAggMap.get(ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME); - - - goodsDateAgg.sterms().buckets().array().forEach(goodsDateAggBucket -> { - // todo 目前没有发现好的es统计月周的方式,先把年月日查出来转周,后续优化 - goodsDateAggBucket.aggregations().get(ORDER_REMAIN_PLATE_MODEL_DATE_GROUP_NAME).dateHistogram().buckets().array().forEach(dateHistogramBucket -> { - // 时间轴 - String dateStr = dateToWeekMonth(dateHistogramBucket.keyAsString(), unit); - // 时间轴下的boardCount - double goodsCount = dateHistogramBucket.aggregations().get(ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME).sum().value(); - // goodsid+数量存入map,key:时间轴 - List orderGoodsPlateRespVOS = goodsDateGroupMap.get(dateStr); - OrderGoodsPlateRespVO vo = OrderGoodsPlateRespVO.builder().goodsId(goodsDateAggBucket.key().stringValue()).orderDate(dateStr).orderCount((int) goodsCount).build(); - if (ObjectUtil.isNotNull(orderGoodsPlateRespVOS)) { - orderGoodsPlateRespVOS.add(vo); - } else { - ArrayList goodsPlateRespVOS = new ArrayList<>(); - goodsPlateRespVOS.add(vo); - goodsDateGroupMap.put(dateStr, goodsPlateRespVOS); - } - }); - }); - } - - // 遍历所有goods_id - List> series = new ArrayList<>(); - for (String goodsId : goodsIds) { - Map seriesItem = new HashMap<>(); - int[] countArr = new int[dateList.size()]; - - // 遍历完整的日期范围 - int index = 0; - for (String dateStr : dateList) { - // 查找匹配的goodsId - List orderGoodsPlateRespVOS = goodsDateGroupMap.get(dateStr); - int count = 0; - if (orderGoodsPlateRespVOS != null) { - count = orderGoodsPlateRespVOS.stream() - .filter(respVO -> Objects.equals(goodsId, respVO.getGoodsId())) - .map(OrderGoodsPlateRespVO::getOrderCount) - .findFirst().orElse(0); - } - countArr[index++] = count; - } - - seriesItem.put("data", countArr); - seriesItem.put("id", goodsId); - // 材质-商品名称-颜色-纹理-宽-高-厚-品牌 - List plateGoodDOList = plateGoodMapper.selectList(new LambdaQueryWrapperX().eq(PlateGoodDO::getGoodsId, goodsId)); - if (CollUtil.isEmpty(plateGoodDOList)) { - // 没有对应大板不展示 - log.error("[getBigPlateCountGroup][统计大板数量,查询大板{} 不存在]", goodsId); - continue; - } - // 任意取一个类型 - PlateGoodDO plateGoodDO = plateGoodDOList.get(0); - String specification = formatGoodsName('x', stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getWidth())), - stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getHeight())), stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getThickness()))); - String goodsName = formatGoodsName('-', plateGoodDO.getMaterial(), plateGoodDO.getGoodsName(), plateGoodDO.getColor(), getTextureFromDict(plateGoodDO.getTexture()), specification, plateGoodDO.getBrand()); - seriesItem.put("name", goodsName); - series.add(seriesItem); - } - - // x轴时间区间字符串 - resultMap.put(DATELIST_FIELD_NAME, dateList.stream().map(date -> generateDateRangeAxis(date, unit)).toList()); - // 类别:大板信息:大板数量数组 - resultMap.put(SERIES_FIELD_NAME, series); - } catch (IOException e) { - log.error("[getBigPlateCountGroup][统计大板数量异常:{}]", e.getMessage(), e); + // 前十goods_id基于时间分组 + Map> orderGoodsPlateRespMap = new HashMap<>(); + if (CollUtil.isNotEmpty(goodsCodes)) { + orderGoodsPlateRespMap = planMapper.selectTopTenBoardCountGroupByOptimizeTime(goodsCodes, reqVO).stream() + .sorted(Comparator.naturalOrder()) + .collect(Collectors.groupingBy(OrderGoodsPlateRespVO::getOrderDate, LinkedHashMap::new, Collectors.toList())); } + + + List> series = new ArrayList<>(); + + // 遍历top10材质 + for (String goodsCode : goodsCodes) { + + Map seriesItem = new HashMap<>(); + + int[] countArr = new int[dateList.size()]; + + int index = 0; + + // 遍历完整时间轴 + for (String dateStr : dateList) { + + List respVOS = orderGoodsPlateRespMap.get(dateStr); + + int count = 0; + + if (CollUtil.isNotEmpty(respVOS)) { + count = respVOS.stream() + .filter(vo -> Objects.equals(goodsCode, vo.getGoodsId())) + .map(OrderGoodsPlateRespVO::getOrderCount) + .findFirst() + .orElse(0); + } + + countArr[index++] = count; + } + + seriesItem.put("data", countArr); + seriesItem.put("id", goodsCode); + + // 查询大板信息 + List plateGoodDOList = plateGoodMapper.selectList( + new LambdaQueryWrapperX() + .eq(PlateGoodDO::getGoodsId, goodsCode)); + + if (CollUtil.isEmpty(plateGoodDOList)) { + log.error("[getBigPlateCountGroup][统计大板数量,查询大板{}不存在]", goodsCode); + continue; + } + + PlateGoodDO plateGoodDO = plateGoodDOList.get(0); + + String specification = formatGoodsName( + 'x', + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getWidth())), + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getHeight())), + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getThickness()))); + + String goodsName = formatGoodsName( + '-', + plateGoodDO.getMaterial(), + plateGoodDO.getGoodsName(), + plateGoodDO.getColor(), + getTextureFromDict(plateGoodDO.getTexture()), + specification, + plateGoodDO.getBrand()); + + seriesItem.put("name", goodsName); + + series.add(seriesItem); + } + + // x轴 + resultMap.put( + DATELIST_FIELD_NAME, + dateList.stream() + .map(date -> generateDateRangeAxis(date, reqVO.getUnit())) + .toList()); + + // series + resultMap.put( + SERIES_FIELD_NAME, + series); + return resultMap; } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plan/PlanMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plan/PlanMapper.xml index e83234a24..e2eb0ca45 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plan/PlanMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plan/PlanMapper.xml @@ -348,4 +348,51 @@ + + + + \ No newline at end of file