禅道bug#1699修复

This commit is contained in:
gaoqr
2026-06-16 16:26:10 +08:00
parent 446f6e8446
commit 76200f4c38
5 changed files with 177 additions and 131 deletions
@@ -113,6 +113,16 @@ public class PlanDO extends BaseDO {
*/
private String goodsId;
/**
* 实际优化材质编号
*/
private String optimizeGoodsId;
/**
* 优化时间
*/
private LocalDateTime optimizeTime;
/**
* 已优化板件数
*/
@@ -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<PlanDO> {
* @return
*/
int batchUpdatePlanSort(@Param("sortList") List<SortVO> sortVOList);
/**
* 查询时间区间用量最大的10种商品编号
*
* @param reqVO
* @return
*/
List<String> selectPlanGoodsTopTen(@Param("req") OrderStatisticsReqVO reqVO);
/**
* 查询商品编号范围按优化时间分组
*
* @param goodsCodes
* @param reqVO
* @return
*/
List<OrderGoodsPlateRespVO> selectTopTenBoardCountGroupByOptimizeTime(@Param("goodsCodes") List<String> goodsCodes, @Param("req") OrderStatisticsReqVO reqVO);
}
@@ -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<String> 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<String> 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<PlanDO>()
planMapper.update(new LambdaUpdateWrapperX<PlanDO>()
.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())
);
}
}
@@ -411,137 +411,98 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService {
@Override
public Map<String, Object> getBigPlateCountGroup(OrderStatisticsReqVO reqVO) {
Map<String, Object> resultMap = new LinkedHashMap<>();
Integer unit = reqVO.getUnit();
// 所有的日期集合
List<String> dateList = getDateList(reqVO);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
SearchResponse<Map> 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<String> goodsCodes = planMapper.selectPlanGoodsTopTen(reqVO);
response = client.search(searchRequest, Map.class);
Map<String, Aggregate> goodsCountAggMap = response.aggregations();
Aggregate goodsCountAgg = goodsCountAggMap.get(ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME);
List<String> goodsIds = new ArrayList<>();
// 构建map:日期:goodsId、count
Map<String, List<OrderGoodsPlateRespVO>> goodsDateGroupMap = new HashMap<>();
/**
* 获取数量最大前十的goodsId列表
*/
goodsCountAgg.sterms().buckets().array().forEach(e -> goodsIds.add(e.key().stringValue()));
if (CollUtil.isNotEmpty(goodsIds)) {
List<FieldValue> 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<String, Aggregate> 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+数量存入mapkey:时间轴
List<OrderGoodsPlateRespVO> 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<OrderGoodsPlateRespVO> goodsPlateRespVOS = new ArrayList<>();
goodsPlateRespVOS.add(vo);
goodsDateGroupMap.put(dateStr, goodsPlateRespVOS);
}
});
});
// 前十goods_id基于时间分组
Map<String, List<OrderGoodsPlateRespVO>> 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()));
}
// 遍历所有goods_id
List<Map<String, Object>> series = new ArrayList<>();
for (String goodsId : goodsIds) {
// 遍历top10材质
for (String goodsCode : goodsCodes) {
Map<String, Object> seriesItem = new HashMap<>();
int[] countArr = new int[dateList.size()];
// 遍历完整的日期范围
int index = 0;
// 遍历完整时间轴
for (String dateStr : dateList) {
// 查找匹配的goodsId
List<OrderGoodsPlateRespVO> orderGoodsPlateRespVOS = goodsDateGroupMap.get(dateStr);
List<OrderGoodsPlateRespVO> respVOS = orderGoodsPlateRespMap.get(dateStr);
int count = 0;
if (orderGoodsPlateRespVOS != null) {
count = orderGoodsPlateRespVOS.stream()
.filter(respVO -> Objects.equals(goodsId, respVO.getGoodsId()))
if (CollUtil.isNotEmpty(respVOS)) {
count = respVOS.stream()
.filter(vo -> Objects.equals(goodsCode, vo.getGoodsId()))
.map(OrderGoodsPlateRespVO::getOrderCount)
.findFirst().orElse(0);
.findFirst()
.orElse(0);
}
countArr[index++] = count;
}
seriesItem.put("data", countArr);
seriesItem.put("id", goodsId);
// 材质-商品名称-颜色-纹理-宽-高-厚-品牌
List<PlateGoodDO> plateGoodDOList = plateGoodMapper.selectList(new LambdaQueryWrapperX<PlateGoodDO>().eq(PlateGoodDO::getGoodsId, goodsId));
seriesItem.put("id", goodsCode);
// 查询大板信息
List<PlateGoodDO> plateGoodDOList = plateGoodMapper.selectList(
new LambdaQueryWrapperX<PlateGoodDO>()
.eq(PlateGoodDO::getGoodsId, goodsCode));
if (CollUtil.isEmpty(plateGoodDOList)) {
// 没有对应大板不展示
log.error("[getBigPlateCountGroup][统计大板数量,查询大板{} 不存在]", goodsId);
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());
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);
}
// x轴
resultMap.put(
DATELIST_FIELD_NAME,
dateList.stream()
.map(date -> generateDateRangeAxis(date, reqVO.getUnit()))
.toList());
// series
resultMap.put(
SERIES_FIELD_NAME,
series);
return resultMap;
}
@@ -348,4 +348,51 @@
</foreach>
</update>
<select id="selectPlanGoodsTopTen" resultType="java.lang.String">
SELECT
optimize_goods_id AS optimizeGoodsId,
SUM(scheduled_board_num) AS totalScheduledBoardNum
FROM order_plan
WHERE deleted = false
AND optimize_goods_id IS NOT NULL
AND optimize_goods_id != ''
AND optimize_time BETWEEN #{req.createTime[0]} AND #{req.createTime[1]}
GROUP BY optimize_goods_id
ORDER BY totalScheduledBoardNum DESC
LIMIT 10
</select>
<select id="selectTopTenBoardCountGroupByOptimizeTime" resultType="com.cf.imes.module.executor.controller.admin.order.vo.order.OrderGoodsPlateRespVO">
SELECT
p.optimize_goods_id AS goodsId,
<if test="req.unit == @com.cf.imes.framework.common.enums.StatisticsUnit@QUARTER.getValue()">
CONCAT(YEAR(p.optimize_time), '-', QUARTER(p.optimize_time))
</if>
<if test="req.unit == @com.cf.imes.framework.common.enums.StatisticsUnit@MONTH.getValue()">
CONCAT(YEAR(p.optimize_time), '-', MONTH(p.optimize_time))
</if>
<if test="req.unit == @com.cf.imes.framework.common.enums.StatisticsUnit@WEEK.getValue()">
CONCAT(YEAR(p.optimize_time), '-', MONTH(p.optimize_time), '-', FLOOR((DayOfMonth(p.optimize_time)-1)/7)+1)
</if>
<if test="req.unit == @com.cf.imes.framework.common.enums.StatisticsUnit@DAY.getValue()">
CONCAT(YEAR(p.optimize_time), '-', MONTH(p.optimize_time), '-', DAY(p.optimize_time))
</if>
AS orderDate,
SUM(p.scheduled_board_num) AS orderCount
FROM order_plan p
WHERE p.deleted = false
AND p.optimize_time BETWEEN #{req.createTime[0]} AND #{req.createTime[1]}
AND p.optimize_goods_id IN
<foreach collection="goodsCodes" item="goodsCode" open="(" separator="," close=")">
#{goodsCode}
</foreach>
GROUP BY
p.optimize_goods_id,
orderDate
</select>
</mapper>