diff --git a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/encrypt/AesUtils.java b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/encrypt/AesUtils.java new file mode 100644 index 000000000..77a3b4733 --- /dev/null +++ b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/encrypt/AesUtils.java @@ -0,0 +1,99 @@ +package com.cf.imes.framework.common.util.encrypt; + +import cn.hutool.core.util.CharsetUtil; +import lombok.extern.slf4j.Slf4j; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import java.security.GeneralSecurityException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Base64; + +/** + * AES对称加密工具 + * + * @author Gqr + * @since 2024/8/23 16:38 + */ +@Slf4j +public class AesUtils { + + private static final String AES_ALG = "AES"; + + private static final String AES_CBC_PCK_ALG = "AES/CBC/PKCS5Padding"; + + + /** + * 解密 + * + * @param content + * @param aesKey + * @return + * @throws Exception + */ + public static String decrypt(String content, String aesKey) { + try { + Cipher cipher = Cipher.getInstance(AES_CBC_PCK_ALG); + IvParameterSpec iv = new IvParameterSpec(initIv(AES_CBC_PCK_ALG)); + cipher.init(Cipher.DECRYPT_MODE, generateKey(aesKey.getBytes()), iv); + + byte[] cleanBytes = cipher.doFinal(Base64.getDecoder().decode(content.getBytes())); + return new String(cleanBytes, CharsetUtil.UTF_8); + } catch (Exception e) { + log.error("[AesUtils][decrypt]解密失败:{}", e.getMessage(), e); + // nacos热发布配置,空字符串会导致nacos轮训刷新配置 + return "default"; + } + } + + /** + * 生成key + * + * @param bytes + * @return + * @throws NoSuchAlgorithmException + */ + private static SecretKey generateKey(byte[] bytes) throws NoSuchAlgorithmException { + // 生成随机数 + SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); + // 设置随机数种子 + random.setSeed(bytes); + + // aes算法生成器 + KeyGenerator keyGen = KeyGenerator.getInstance(AES_ALG); + keyGen.init(128, random); // 使用128位的密钥 + return keyGen.generateKey(); + } + + + /** + * 初始向量的方法, 全部为0. 这里的写法适合于其它算法,针对AES算法的话,IV值一定是128位的(16字节). + * + * @param fullAlg + * @return + * @throws GeneralSecurityException + */ + private static byte[] initIv(String fullAlg) { + + try { + Cipher cipher = Cipher.getInstance(fullAlg); + int blockSize = cipher.getBlockSize(); + byte[] iv = new byte[blockSize]; + for (int i = 0; i < blockSize; ++i) { + iv[i] = 0; + } + return iv; + } catch (Exception e) { + + int blockSize = 16; + byte[] iv = new byte[blockSize]; + for (int i = 0; i < blockSize; ++i) { + iv[i] = 0; + } + return iv; + } + } +} diff --git a/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/type/CompressStringTypeHandler.java b/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/type/CompressStringTypeHandler.java index 0b805096d..1dbdf562b 100644 --- a/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/type/CompressStringTypeHandler.java +++ b/cf-framework/cf-spring-boot-starter-mybatis/src/main/java/com/cf/imes/framework/mybatis/core/type/CompressStringTypeHandler.java @@ -20,10 +20,11 @@ public class CompressStringTypeHandler extends StringTypeHandler { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { + String compressString = null; if (StringUtils.isNotEmpty(parameter)) { - String compressString = JsonUtils.zipString(parameter); - ps.setString(i, compressString); + compressString = JsonUtils.zipString(parameter); } + ps.setString(i, compressString); } @Override diff --git a/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/util/SecurityFrameworkUtils.java b/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/util/SecurityFrameworkUtils.java index 48cfd8025..4f26f0557 100644 --- a/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/util/SecurityFrameworkUtils.java +++ b/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/util/SecurityFrameworkUtils.java @@ -1,6 +1,5 @@ package com.cf.imes.framework.security.core.util; -import cn.hutool.core.util.StrUtil; import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants; import com.cf.imes.framework.security.core.LoginUser; @@ -44,7 +43,7 @@ public class SecurityFrameworkUtils { String headerName, String parameterName) { // 1. 获得 Token。优先级:Header > Parameter String token = request.getHeader(headerName); - if (StrUtil.isEmpty(token)) { + if (StringUtils.isEmpty(token)) { token = request.getParameter(parameterName); } if (!StringUtils.hasText(token)) { @@ -63,7 +62,7 @@ public class SecurityFrameworkUtils { public static Authentication getAuthentication() { SecurityContext context = SecurityContextHolder.getContext(); if (context == null) { - return null; + throw new ServiceException(GlobalErrorCodeConstants.UNAUTHORIZED); } return context.getAuthentication(); } @@ -90,10 +89,7 @@ public class SecurityFrameworkUtils { @Nullable public static Long getLoginUserId() { LoginUser loginUser = getLoginUser(); - if (loginUser == null) { - throw new ServiceException(GlobalErrorCodeConstants.UNAUTHORIZED); - } - return loginUser.getId(); + return loginUser != null ? loginUser.getId() : null; } /** diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/order/OrderStatisticsController.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/order/OrderStatisticsController.java index 22d0f16c4..2b75e2ff1 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/order/OrderStatisticsController.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/order/OrderStatisticsController.java @@ -90,7 +90,7 @@ public class OrderStatisticsController { @GetMapping("/bigPlateCount/group") @Operation(summary = "大板数量分组统计") public CommonResult> getBigPlateCount(@Valid OrderStatisticsReqVO reqVO) { - return success(null); + return success(orderStatisticsService.getBigPlateCountGroup(reqVO)); } } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/order/OrderStatisticsMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/order/OrderStatisticsMapper.java index fc2d6a061..31e06864e 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/order/OrderStatisticsMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/order/OrderStatisticsMapper.java @@ -6,13 +6,12 @@ import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisti import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsReqVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsStatusRespVO; import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; +import com.cf.imes.module.executor.enums.OrderDeletedEnum; import com.cf.imes.module.executor.enums.OrderStatusEnum; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; import java.util.List; /** @@ -27,7 +26,7 @@ public interface OrderStatisticsMapper extends BaseMapperX { */ default Integer selectOrderCount() { return Math.toIntExact(selectCount(new LambdaQueryWrapperX() - .eq(OrderDO::getDeleted, 0))); + .eq(OrderDO::getDeleted, OrderDeletedEnum.NOT_DELETED.getStatus()))); } /** @@ -36,6 +35,7 @@ public interface OrderStatisticsMapper extends BaseMapperX { */ default Integer selectOrderCountToday() { return Math.toIntExact(selectCount(new LambdaQueryWrapperX() + .eq(OrderDO::getDeleted, OrderDeletedEnum.NOT_DELETED.getStatus()) .eq(OrderDO::getOrderDate, LocalDate.now()))); } @@ -46,7 +46,9 @@ public interface OrderStatisticsMapper extends BaseMapperX { */ default Integer selectOrderCountTodayFinish() { return Math.toIntExact(selectCount(new LambdaQueryWrapperX() - .between(OrderDO::getFinishTime, LocalDateTime.of(LocalDate.now(), LocalTime.MIN), LocalDateTime.of(LocalDate.now(), LocalTime.MAX)))); + .eq(OrderDO::getDeleted, OrderDeletedEnum.NOT_DELETED.getStatus()) + .eq(OrderDO::getStatus, OrderStatusEnum.FINISH_PRODUCTION.getStatus()) + .eq(OrderDO::getFinishTime, LocalDate.now()))); } /** @@ -55,13 +57,14 @@ public interface OrderStatisticsMapper extends BaseMapperX { */ default Integer selectOrderCountProduce() { return Math.toIntExact(selectCount(new LambdaQueryWrapperX() + .eq(OrderDO::getDeleted, OrderDeletedEnum.NOT_DELETED.getStatus()) .eq(OrderDO::getStatus, OrderStatusEnum.IN_PRODUCTION.getStatus()))); } /** * 生产中生产平方数 * - * @param organId + * @param * @return */ Integer selectOrderSquareProduce(); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsService.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsService.java index 51d8ad19a..e7645b35c 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsService.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderStatisticsService.java @@ -72,4 +72,12 @@ public interface OrderStatisticsService { * @return */ Map getOrderPlateAreaGroup(OrderStatisticsReqVO reqVO); + + /** + * 大板数量分组统计 + * + * @param reqVO + * @return + */ + Map getBigPlateCountGroup(OrderStatisticsReqVO reqVO); } 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 f98679ff6..ccb8c2f99 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 @@ -1,24 +1,41 @@ package com.cf.imes.module.executor.service.order; import cn.hutool.core.util.ObjectUtil; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.FieldValue; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.aggregations.Aggregate; + +import co.elastic.clients.elasticsearch._types.aggregations.CalendarInterval; +import co.elastic.clients.elasticsearch._types.aggregations.DateHistogramAggregation; +import co.elastic.clients.elasticsearch.core.SearchRequest; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.json.JsonData; +import co.elastic.clients.util.NamedValue; import com.cf.imes.framework.common.enums.OrderStatusEnum; +import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderGoodsPlateRespVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsAreaRespVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsReqVO; import com.cf.imes.module.executor.controller.admin.order.vo.order.OrderStatisticsStatusRespVO; import com.cf.imes.module.executor.controller.admin.plan.vo.OrderPlanStatisticsAreaRespVO; import com.cf.imes.module.executor.controller.admin.plan.vo.OrderPlanStatisticsCountRespVO; +import com.cf.imes.module.executor.dal.dataobject.plate.PlateGoodDO; import com.cf.imes.module.executor.dal.mysql.order.OrderStatisticsMapper; import com.cf.imes.module.executor.dal.mysql.plan.PlanMapper; import com.cf.imes.module.executor.dal.mysql.plate.OrderPlateStatisticsMapper; +import com.cf.imes.module.executor.dal.mysql.plate.PlateGoodMapper; import com.cf.imes.module.executor.enums.OrderStatisticsUnit; +import com.cf.imes.module.executor.service.optimizeplan.OptimizePlanService; import com.cf.imes.module.system.api.dict.DictDataApi; import com.cf.imes.module.system.api.dict.dto.DictDataRespDTO; import com.cf.imes.module.system.enums.DictTypeConstants; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.io.IOException; import java.math.BigDecimal; import java.time.LocalDate; import java.time.format.DateTimeFormatter; @@ -40,6 +57,7 @@ import java.util.stream.Collectors; */ @Service @Validated +@Slf4j public class OrderStatisticsServiceImpl implements OrderStatisticsService { @Resource private OrderStatisticsMapper orderStatisticsMapper; @@ -53,9 +71,20 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { @Resource private DictDataApi dictDataApi; + @Resource + private PlateGoodMapper plateGoodMapper; + + @Resource + private ElasticsearchClient client; + // 常用的字段key private static final String DATELIST_FIELD_NAME = "dateList"; private static final String SERIES_FIELD_NAME = "series"; + private static final String ORDER_REMAIN_PLATE_MODEL_CREATE_TIME_FIELDNAME = "createTime"; + private static final String ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME = "goods_group"; + private static final String ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME = "goods_count"; + private static final String DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH = "yyyy-M"; + private static final String DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH_DAY = "yyyy-M-d"; @Override public Integer orderCount() { @@ -206,13 +235,10 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { // 所有的日期集合 List dateList = getDateList(reqVO); - // 查询时间段内数量最多的小板,排序列出数量前10的goods_id + // 查询时间段内数量最多的小板,列出数量前10的goods_id List topTenCountGoodsId = orderPlateStatisticsMapper.selectPlateCountList(reqVO).stream() - .sorted(Comparator.comparingLong(OrderGoodsPlateRespVO::getOrderCount).reversed()) .map(OrderGoodsPlateRespVO::getGoodsId) - .limit(10) - .collect(Collectors.toList()); - + .toList(); // 前十goods_id基于时间分组 Map> orderGoodsPlateRespMap = orderPlateStatisticsMapper.selectTopTenPlateCountListGroupByOrderDate(topTenCountGoodsId, reqVO).stream() @@ -225,7 +251,7 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { List list = orderGoodsPlateRespMap.values().stream() .flatMap(List::stream) .filter(vo -> vo.getGoodsId().equals(id)) - .collect(Collectors.toList()); + .toList(); if (!list.isEmpty()) { // goodsId相同,其他属性任取 goodsMap.put(id, list.get(0)); @@ -277,12 +303,10 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { // 所有的日期集合 List dateList = getDateList(reqVO); - // 查询时间段内面积最多的小板,排序列出前10面积的goods_id + // 查询时间段内面积最多的小板,列出前10面积的goods_id List topTenCountGoodsId = orderPlateStatisticsMapper.selectPlateAreaList(reqVO).stream() - .sorted(Comparator.comparing(OrderGoodsPlateRespVO::getOrderArea).reversed()) .map(OrderGoodsPlateRespVO::getGoodsId) - .limit(10) - .collect(Collectors.toList()); + .toList(); // 前十goods_id基于时间分组 @@ -296,7 +320,7 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { List list = orderGoodsPlateRespMap.values().stream() .flatMap(List::stream) .filter(vo -> vo.getGoodsId().equals(id)) - .collect(Collectors.toList()); + .toList(); if (!list.isEmpty()) { // goodsId相同,其他属性任取 goodsMap.put(id, list.get(0)); @@ -341,6 +365,167 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { return resultMap; } + @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(OptimizePlanService.ORDER_REMAIN_PLATE_MODEL) + .query(q -> q.range(r -> r.field(ORDER_REMAIN_PLATE_MODEL_CREATE_TIME_FIELDNAME) + .gte(JsonData.of(reqVO.getCreateTime()[0].format(dateTimeFormatter))) + .lte(JsonData.of(reqVO.getCreateTime()[1].format(dateTimeFormatter)))) + ) + .aggregations(ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME, + agg -> agg.terms(terms -> terms.field("id").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(); + + 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<>(); + + /** + * 获取数量最大前十的goodsId列表 + */ + goodsCountAgg.sterms().buckets().array().forEach(e -> goodsIds.add(e.key())); + // 查询创建时间段内,数量最多的goods_id前十下的数据,按goods_id和日期分组 + SearchRequest dateGroupRequest = new SearchRequest.Builder() + .size(0) + .index(OptimizePlanService.ORDER_REMAIN_PLATE_MODEL) + .query(q -> q.range(r -> r.field(ORDER_REMAIN_PLATE_MODEL_CREATE_TIME_FIELDNAME) + .gte(JsonData.of(reqVO.getCreateTime()[0].format(dateTimeFormatter))) + .lte(JsonData.of(reqVO.getCreateTime()[1].format(dateTimeFormatter)))) + ) + .query(q -> q.bool(b -> b.must(m -> m.terms(t -> t.field("goods_id").terms(tv -> tv.value(goodsIds)))))) + .query(q -> q.match(m -> m.field("organId").query(SecurityFrameworkUtils.getUserOrganId()))) + .aggregations(ORDER_REMAIN_PLATE_MODEL_GOODS_GROUP_NAME, + agg -> agg.terms(terms -> terms.field("id").order(new NamedValue<>(ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME, SortOrder.Desc))) + .aggregations("date_group", 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); + + // 构建map:{日期:{goodsId、count}} + Map> goodsDateGroupMap = new HashMap<>(); + goodsDateAgg.sterms().buckets().array().forEach(goodsDateAggBucket -> { + String goodsId = goodsDateAggBucket.key().stringValue(); + // todo 目前没有发现好的es统计月周的方式,先把年月日查出来转周,后续优化 + String dateStr = dateToWeekMonth(goodsDateAggBucket.aggregations().get("date_group").dateHistogram().buckets().array().get(0).keyAsString(), unit); + double goodsCount = goodsDateAggBucket.aggregations().get(ORDER_REMAIN_PLATE_MODEL_GOODS_COUNT_NAME).sum().value(); + OrderGoodsPlateRespVO vo = OrderGoodsPlateRespVO.builder().goodsId(Long.parseLong(goodsId)).orderDate(dateStr).orderCount((int) goodsCount).build(); + List orderGoodsPlateRespVOS = goodsDateGroupMap.get(dateStr); + 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 (FieldValue goodsIdFieldValue : goodsIds) { + String goodsIdStr = goodsIdFieldValue.stringValue(); + Long goodsId = Long.parseLong(goodsIdStr); + 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); + // 材质-商品名称-颜色-纹理-宽-高-厚-品牌 + PlateGoodDO plateGoodDO = plateGoodMapper.selectById(goodsId); + if (ObjectUtil.isNull(plateGoodDO)) { + // 没有对应大板不展示 + log.error("[getBigPlateCountGroup][统计大板数量,查询大板{} 不存在]", goodsId); + continue; + } + // 获取纹路描述 + DictDataRespDTO grainDTO = dictDataApi.getDictData(DictTypeConstants.GRAIN_TYPE, String.valueOf(plateGoodDO.getTexture())).getData(); + String texture = ObjectUtil.isNotNull(grainDTO) ? grainDTO.getLabel() : ""; + seriesItem.put("name", plateGoodDO.getMaterial() + "-" + plateGoodDO.getGoodsName() + + "-" + plateGoodDO.getColor() + "-" + texture + "-" + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getWidth())) + + "×" + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getHeight())) + "×" + stripTrailingZeros(BigDecimal.valueOf(plateGoodDO.getThickness())) + "-" + plateGoodDO.getBrand()); + series.add(seriesItem); + } + 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); + } + return resultMap; + } + + /** + * 根据统计维度获取es分组的dateHistogram + * + * @return + */ + private DateHistogramAggregation.Builder getDateHistogram(Integer unit, DateHistogramAggregation.Builder builder) { + switch (OrderStatisticsUnit.fromValue(unit)) { + case QUARTER: + return builder.calendarInterval(CalendarInterval.Quarter).format("yyyy-Q"); + case MONTH: + return builder.calendarInterval(CalendarInterval.Month).format(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH); + case DAY, WEEK: + default: + return builder.calendarInterval(CalendarInterval.Day).format(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH_DAY); + } + } + + + /** + * 年月日转年月周 + * + * @param dateStr + * @return + */ + private String dateToWeekMonth(String dateStr, Integer unit) { + if (OrderStatisticsUnit.WEEK.getValue().equals(unit)) { + LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH_DAY)); + // 年月 + String outDateStr = date.format(DateTimeFormatter.ofPattern(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH)); + // 计算从月份第一天到当前日期经过了多少周 + LocalDate monthStart = date.with(TemporalAdjusters.firstDayOfMonth()); + long weeksInMonth = ChronoUnit.WEEKS.between(monthStart, date) + 1; + return outDateStr + "-" + weeksInMonth; + } + return dateStr; + } + + + /** * 获取日期区间格式下的所有日期字符串 * 1、reqVO设置机构id @@ -372,8 +557,8 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { endTime = now; switch (OrderStatisticsUnit.fromValue(reqVO.getUnit())) { case QUARTER: - // 从now往前的2年 - startTime = now.minusYears(2); + // 从now往前的1年 + startTime = now.minusYears(1); break; case MONTH: // 包含now往前的12个月 @@ -419,22 +604,17 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { startDate = startDate.plusMonths(3); break; case MONTH: - dateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-M")); + dateStr = startDate.format(DateTimeFormatter.ofPattern(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH)); // 加一月 startDate = startDate.plusMonths(1); break; case WEEK: - // 使用自定义格式表示月份 - dateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-M")); - // 计算从月份第一天到当前日期经过了多少周 - LocalDate monthStart = startDate.with(TemporalAdjusters.firstDayOfMonth()); - long weeksInMonth = ChronoUnit.WEEKS.between(monthStart, startDate) + 1; - dateStr = dateStr + "-" + weeksInMonth; + dateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-M-W")); // 加一周 startDate = startDate.plusWeeks(1); break; case DAY: - dateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-M-d")); + dateStr = startDate.format(DateTimeFormatter.ofPattern(DATE_TIME_FORMATTER_PATTERN_YEAR_MONTH_DAY)); // 加一天 startDate = startDate.plusDays(1); break; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderStatisticsMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderStatisticsMapper.xml index 565163bf0..cfa743c1f 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderStatisticsMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderStatisticsMapper.xml @@ -3,8 +3,8 @@ 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 397f531d3..6f9bff1be 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 @@ -140,8 +140,7 @@ ,CONCAT(YEAR(p.create_time), '-', MONTH(p.create_time), '-', DAY(p.create_time)) as date from order_plan p - where p.organ_id = #{req.organId} - and p.create_time between #{req.createTime[0]} and #{req.createTime[1]} + where p.create_time between #{req.createTime[0]} and #{req.createTime[1]} and p.deleted = 0 group by date; @@ -162,11 +161,10 @@ ,CONCAT(YEAR(p.create_time), '-', MONTH(p.create_time), '-', DAY(p.create_time)) as date from order_plan p - join order_plan_item opi on p.id = opi.plan_id and opi.organ_id = #{req.organId} - join order_item oi on oi.id = opi.item_id and oi.organ_id = #{req.organId} - join order_plate op on oi.plate_id = op.id and op.organ_id = #{req.organId} - where p.organ_id = #{req.organId} - and p.create_time between #{req.createTime[0]} and #{req.createTime[1]} + join order_plan_item opi on p.id = opi.plan_id + join order_item oi on oi.id = opi.item_id + join order_plate op on oi.plate_id = op.id + where p.create_time between #{req.createTime[0]} and #{req.createTime[1]} and p.deleted = 0 group by date; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plate/OrderPlateStatisticsMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plate/OrderPlateStatisticsMapper.xml index 30c9e277b..2354fd008 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plate/OrderPlateStatisticsMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plate/OrderPlateStatisticsMapper.xml @@ -6,12 +6,12 @@ count(a.id) as orderCount from order_goods g left join order_plate a ON g.id = a.goods_id and a.deleted = 0 - left join orders o ON o.id = a.order_id and o.deleted = 0 + join orders o ON o.id = a.order_id and o.deleted = 0 where g.deleted = 0 and o.order_date between #{req.createTime[0]} and #{req.createTime[1]} group by g.goods_id - having orderCount > 0 - order by null; + order by orderCount desc + limit 10;