From e4f71a9fb7b2381a4fe212ca96299ed4c16cf84c Mon Sep 17 00:00:00 2001 From: liuzhaotian Date: Wed, 25 Sep 2024 10:34:48 +0800 Subject: [PATCH 01/13] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=BA=90=E5=A2=9E=E5=8A=A0=E9=85=8D=E4=BB=B6=E7=9A=84=E5=A4=87?= =?UTF-8?q?=E6=B3=A8=E4=BF=A1=E6=81=AF=EF=BC=8C=E9=85=8D=E4=BB=B6=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E5=A2=9E=E5=8A=A0=E7=B1=BB=E5=9E=8B=E7=AD=89=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/plan/bo/OrderSource.java | 8 +- .../saveOptimize/PrintOrderPartsRespVO.java | 21 +- .../admin/plan/vo/OrderGoodsResp.java | 2 + .../optimizeplan/OptimizePlanService.java | 4 + .../optimizeplan/OptimizePlanServiceImpl.java | 29 +++ .../service/order/OrderServiceImpl.java | 183 +++++++++--------- .../service/plan/PlanServiceImpl.java | 2 +- .../resources/mapper/order/OrderMapper.xml | 6 +- .../mapper/orderParts/OrderPartsMapper.xml | 48 ++++- .../dal/mysql/pack/OrderPackageMapper.java | 4 +- .../dal/mysql/pack/OrderPackageMapper.xml | 1 + .../system/enums/ErrorCodeConstants.java | 1 + 12 files changed, 198 insertions(+), 111 deletions(-) diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderSource.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderSource.java index 6e2b665fa..8cf82d1e5 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderSource.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/bo/OrderSource.java @@ -1,5 +1,6 @@ package com.cf.imes.module.executor.controller.admin.plan.bo; +import com.cf.imes.module.executor.controller.admin.orderParts.vo.OrderPartsRemark; import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.OptimizeRemainPlate; import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.PrintOrderPackReqVO; import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.PrintOrderPartsRespVO; @@ -16,8 +17,6 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.Valid; -import javax.validation.constraints.NotNull; import java.util.List; /** @@ -61,6 +60,11 @@ public class OrderSource { private List orderPartsRespVOS; + @Schema(description = "生产单配件的备注信息") + private List orderPartsRemarks; + + + @Schema(description = "生产单包裹信息") private List orderPackReqVOS; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/PrintOrderPartsRespVO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/PrintOrderPartsRespVO.java index 63d2929c3..0abcb3516 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/PrintOrderPartsRespVO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/PrintOrderPartsRespVO.java @@ -1,25 +1,37 @@ package com.cf.imes.module.executor.controller.admin.plan.saveOptimize; -import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.util.List; + @Schema(description = "管理后台 - 标签对应的生产单配件信息") @Data public class PrintOrderPartsRespVO { + @Schema(description = "房间ID", requiredMode = Schema.RequiredMode.REQUIRED) + private Long roomId; + + @Schema(description = "房间名称", requiredMode = Schema.RequiredMode.REQUIRED) private String roomName; + @Schema(description = "柜体ID", requiredMode = Schema.RequiredMode.REQUIRED) + private Long bodyId; + + @Schema(description = "柜体名称", requiredMode = Schema.RequiredMode.REQUIRED) private String bodyName; + @Schema(description = "加工组ID", requiredMode = Schema.RequiredMode.REQUIRED) + private List groupId; + + @Schema(description = "配件 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "29347") - @ExcelProperty("配件 ID") private Long id; @@ -27,6 +39,7 @@ public class PrintOrderPartsRespVO { private Long orderId; + @Schema(description = "配件数量", requiredMode = Schema.RequiredMode.REQUIRED) private Long partsNum; @@ -51,4 +64,8 @@ public class PrintOrderPartsRespVO { private String factory; + @Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED) + private String type; + + } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderGoodsResp.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderGoodsResp.java index 29b51d55f..0f0f85b4a 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderGoodsResp.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/vo/OrderGoodsResp.java @@ -42,6 +42,8 @@ public class OrderGoodsResp { @Schema(description = "板件数量") private int num; + @Schema(description = "备注") + private String remark; @Schema(description = "生产单信息") private List orderList; diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanService.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanService.java index ee9b38924..e4a93e700 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanService.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/optimizeplan/OptimizePlanService.java @@ -19,6 +19,10 @@ public interface OptimizePlanService { String ORDER_REMAIN_PLATE_MODEL = "imes_order_optimize_plate_model"; + + String ORDER_PARTS_REMARK_MODEL = "imes_order_parts_remark_model"; + + List getPlateListByPlanId(Long planId); Boolean addRemain(AddRemainReqVO vo); 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 bee00fa0e..13346b00f 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 @@ -16,6 +16,7 @@ import com.cf.imes.framework.common.util.Assert.AssertUtils; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.es.core.service.ESDocumentService; import com.cf.imes.framework.security.core.LoginUser; +import com.cf.imes.module.executor.controller.admin.orderParts.vo.OrderPartsRemark; import com.cf.imes.module.executor.controller.admin.plan.bo.OrderSource; import com.cf.imes.module.executor.controller.admin.plan.bo.ProcessGroupList; import com.cf.imes.module.executor.controller.admin.plan.bo.ProcessStepAreaIds; @@ -607,6 +608,9 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { // 查询生产单对应的配件信息 List printOrderPartsRespVOS = orderPartsMapper.selectPartList(orderIds, getUserOrganId()); + // 查询生产单对应的配件的ES信息 + List orderPartsRemarks = buildOrderPartsByOrderId(orderIds, ORDER_PARTS_REMARK_MODEL, printOrderPartsRespVOS.size()); + // 查询生产单对应的包裹信息 List printOrderPackReqVOS = plateMapper.selectPlanPackList(ids,getUserOrganId()); @@ -631,6 +635,7 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { .optimizeBoardModelDOS(optimizeBoardModelDOS) .optimizeRemainPlates(optimizeRemainPlates) .orderPartsRespVOS(printOrderPartsRespVOS) + .orderPartsRemarks(orderPartsRemarks) .orderPackReqVOS(printOrderPackReqVOS) .build(); } @@ -943,6 +948,30 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { } + public List buildOrderPartsByOrderId(List orderIds, String index, Integer size) { + List fieldValues = orderIds.stream().map(FieldValue::of).toList(); + SearchRequest.Builder builder = new SearchRequest.Builder(); + builder.index(index); + builder.size(size); + builder.query(q -> q.terms(b -> b.field("orderId").terms(e -> e.value(fieldValues)))); + try { + SearchResponse search = elasticsearchClient.search(builder.build(), OrderPartsRemark.class); + List> hits = search.hits().hits(); + if (CollectionUtil.isNotEmpty(hits)) { + return hits.stream().map(Hit::source).collect(Collectors.toList()); + } + return new ArrayList<>(); + } catch (IOException e) { + log.error(e.getMessage()); + throw new ServiceException(INTERNAL_SERVER_ERROR); + } + } + + + + + + public void deleteByPlanId(List planIds, String index) { List fieldValues = planIds.stream().map(FieldValue::of).toList(); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java index 85bfe26d8..5088a7d51 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java @@ -274,6 +274,8 @@ public class OrderServiceImpl implements OrderService { if (bodyIds.size() != 0){ List plateDOList = plateMapper.selectPlateTypeByRoomId(orderId, bodyIds, getUserOrganId(), index); + + List plateIds = plateDOList.stream().map(PlateDO::getId).toList(); List goodsIds = plateDOList.stream().map(PlateDO::getGoodsId).distinct().toList(); @@ -284,63 +286,60 @@ public class OrderServiceImpl implements OrderService { if (!plateDOList.isEmpty()) { plateMapper.updateDeletedById(plateIds, status, getUserOrganId(), orderId);// 删小板 - } + // 删除包裹,只需删除,无需还原 + List packIds = orderItemMapper.selectPackId(bodyIds, getUserOrganId()).stream().map(OrderItemDO::getPackageId).distinct().toList(); - // 删除包裹,只需删除,无需还原 - List packIds = orderItemMapper.selectPackId(bodyIds, getUserOrganId()).stream().map(OrderItemDO::getPackageId).distinct().toList(); + orderPackageMapper.updatePackList(orderId, packIds, getUserOrganId()); - orderPackageMapper.updatePackList(orderId, packIds, getUserOrganId()); + orderItemMapper.deletePackList(orderId, packIds, getUserOrganId()); - orderItemMapper.deletePackList(orderId, packIds, getUserOrganId()); + orderPrepackagedMapper.deletePacked(orderId, getUserOrganId()); - orderPrepackagedMapper.deletePacked(orderId,getUserOrganId()); + List orderPackageDOS = orderPackageMapper.selectPackStatusList(orderId, getUserOrganId()); - List orderPackageDOS = orderPackageMapper.selectPackStatusList(orderId, getUserOrganId()); + if (orderPackageDOS.isEmpty()) { - if(orderPackageDOS.isEmpty()){ + OrderDO orderDO = orderMapper.selectById(orderId); - OrderDO orderDO = orderMapper.selectById(orderId); + orderDO.setPackaged(OrderPackageStatusEnum.UNPACKED.getStatus()); - orderDO.setPackaged(OrderPackageStatusEnum.UNPACKED.getStatus()); + orderMapper.updateById(orderDO); - orderMapper.updateById(orderDO); - - } - - - // 删除大板 - List goodsList = plateMapper.selectPlateDeletedStatus(orderId, goodsIds, getUserOrganId()); - - List goodsIdList = goodsList.stream().map(PlateDO::getGoodsId).distinct().toList(); - - List goodsIdDeleted = Stream.concat( - goodsIds.stream().filter(str -> !goodsIdList.contains(str)), - goodsIdList.stream().filter(str -> !goodsIds.contains(str))) - .toList(); - - if (goodsIdDeleted.size() > 0) { - - goodsMapper.updateDeletedById(goodsIdDeleted, status, getUserOrganId()); - - } - - - if(!planIds.isEmpty()) { - // 判断删除的柜体对应的板材是否和排单板材一样 - List goodsDOS = goodsMapper.selectPlanGoodsListByPlanIdList(planIds, getUserOrganId()); - - // 一样,同时删除排单的信息 - if(goodsDOS.isEmpty() && status.equals(1)){ - planService.deletePlan(planIds); } - // 只要有排单,不管删除的柜体的板材数和排单数一样,都要删除排单对应的优化数据(不用这种写法进行删除时,有时会报错,原因目前还没找到) - planService.deleteByPlanId(planIds, ORDER_REMAIN_PLATE_MODEL); + + // 删除大板 + List goodsList = plateMapper.selectPlateDeletedStatus(orderId, goodsIds, getUserOrganId()); + + List goodsIdList = goodsList.stream().map(PlateDO::getGoodsId).distinct().toList(); + + List goodsIdDeleted = Stream.concat( + goodsIds.stream().filter(str -> !goodsIdList.contains(str)), + goodsIdList.stream().filter(str -> !goodsIds.contains(str))) + .toList(); + + if (goodsIdDeleted.size() > 0) { + + goodsMapper.updateDeletedById(goodsIdDeleted, status, getUserOrganId()); + + } + if (!planIds.isEmpty()) { + // 判断删除的柜体对应的板材是否和排单板材一样 + List goodsDOS = goodsMapper.selectPlanGoodsListByPlanIdList(planIds, getUserOrganId()); + + // 一样,同时删除排单的信息 + if (goodsDOS.isEmpty()) { + planService.deletePlan(planIds); + } else { + // 只要有排单,不管删除的柜体的板材数和排单数一样,都要删除排单对应的优化数据(不用这种写法进行删除时,有时会报错,原因目前还没找到) + planService.deleteByPlanId(planIds, ORDER_REMAIN_PLATE_MODEL); + } + + } } - List partsList = orderPartsMapper.selectPartsIdListByBodyId(bodyIds, getUserOrganId(), orderId); // 配件 if (partsList != null && partsList.size() != 0){ orderPartsMapper.updateDeletedById(partsList, status, getUserOrganId()); @@ -391,67 +390,67 @@ public class OrderServiceImpl implements OrderService { // 小板还原 if (!plateDOList.isEmpty()) { plateMapper.updateDeletedById(plateIds, status, getUserOrganId(), orderId); - } - - // 还原大板 - List goodsDOS = goodsMapper.selectGoodsListByStatus(orderId, goodsIds, getUserOrganId()); - if(!goodsDOS.isEmpty()){ - goodsMapper.updateBatch(goodsDOS.stream().map(m -> m.setDeleted(false)).toList()); - } - // 当大板对应的小板已经排单时,新建相同类型的大板,并将其他未排单的小板对应的大板ID修改为新的大板ID - List goodsDOList = goodsMapper.selectNoPlanGoodsList(orderId, goodsIds, getUserOrganId()); - - List goodsList = BeanUtils.toBean(goodsDOList, GoodsDO.class); - - if(!goodsDOList.isEmpty()){ - - // 新增的大板信息 - List list = goodsDOList.stream() - .peek(m -> { - m.setId(null); - m.setPlanId(0L); - m.setCreateTime(LocalDateTime.now()); - m.setUpdateTime(LocalDateTime.now()); - }) - .toList(); - - goodsMapper.insertBatch(list); - - // 构建新的数据集,保存新的大板ID和旧的大板ID,大板的实际ID关联这两个信息 - List orderGoodsIds = BeanUtils.toBean(list, OrderGoodsIds.class); - - List orderGoodsIdsList = new ArrayList<>(); - - for (GoodsDO goodsDO : goodsList) { - orderGoodsIdsList.addAll(orderGoodsIds.stream() - .filter(f -> f.getGoodsId().equals(goodsDO.getGoodsId())) -// .filter(a -> a.getOldId() == null) - .map(m -> m.setOldId(goodsDO.getId())).toList()); - + // 还原大板 + List goodsDOS = goodsMapper.selectGoodsListByStatus(orderId, goodsIds, getUserOrganId()); + if (!goodsDOS.isEmpty()) { + goodsMapper.updateBatch(goodsDOS.stream().map(m -> m.setDeleted(false)).toList()); } - // 需要修改的小板为未排单的部分,无论其是否删除,都需要修改,但只需修改大板ID即可,其他信息无需修改 - List plateDOS = plateMapper.selectNoPlanPlate(orderId, goodsIds, getUserOrganId()); - List plateList = new ArrayList<>(); + // 当大板对应的小板已经排单时,新建相同类型的大板,并将其他未排单的小板对应的大板ID修改为新的大板ID + List goodsDOList = goodsMapper.selectNoPlanGoodsList(orderId, goodsIds, getUserOrganId()); - for (OrderGoodsIds ids : orderGoodsIdsList) { + List goodsList = BeanUtils.toBean(goodsDOList, GoodsDO.class); - plateList.addAll(plateDOS.stream() - .filter(f->f.getGoodsId().equals(ids.getOldId())) - .peek(m->{ - m.setGoodsId(ids.getId()); + if (!goodsDOList.isEmpty()) { + + // 新增的大板信息 + List list = goodsDOList.stream() + .peek(m -> { + m.setId(null); + m.setPlanId(0L); + m.setCreateTime(LocalDateTime.now()); + m.setUpdateTime(LocalDateTime.now()); }) - .toList()); + .toList(); + + goodsMapper.insertBatch(list); + + // 构建新的数据集,保存新的大板ID和旧的大板ID,大板的实际ID关联这两个信息 + List orderGoodsIds = BeanUtils.toBean(list, OrderGoodsIds.class); + + List orderGoodsIdsList = new ArrayList<>(); + + for (GoodsDO goodsDO : goodsList) { + orderGoodsIdsList.addAll(orderGoodsIds.stream() + .filter(f -> f.getGoodsId().equals(goodsDO.getGoodsId())) +// .filter(a -> a.getOldId() == null) + .map(m -> m.setOldId(goodsDO.getId())).toList()); + + } + + // 需要修改的小板为未排单的部分,无论其是否删除,都需要修改,但只需修改大板ID即可,其他信息无需修改 + List plateDOS = plateMapper.selectNoPlanPlate(orderId, goodsIds, getUserOrganId()); + + List plateList = new ArrayList<>(); + + for (OrderGoodsIds ids : orderGoodsIdsList) { + + plateList.addAll(plateDOS.stream() + .filter(f -> f.getGoodsId().equals(ids.getOldId())) + .peek(m -> { + m.setGoodsId(ids.getId()); + }) + .toList()); + } + + plateMapper.updateBatch(plateList); + } - - plateMapper.updateBatch(plateList); - } - List partsList = orderPartsMapper.selectPartsIdListByBodyId(bodyIds, getUserOrganId(), orderId); // 配件 if (partsList != null && partsList.size() != 0){ orderPartsMapper.updateDeletedById(partsList, status, getUserOrganId()); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java index ad3c44871..8c965b94f 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java @@ -631,7 +631,7 @@ public class PlanServiceImpl implements PlanService { .in("order_id",orderIds) .eq("is_optimized",false) .inIfPresent("goods_id",goodsIds) - .inIfPresent("id",pageReqVO.getIds()) + .inIfPresent("goods_id",pageReqVO.getIds()) .eqIfPresent("is_special_shaped", pageReqVO.getRectangle() != null ? false: null) .eqIfPresent("is_special_shaped", pageReqVO.getSpecialShaped()) .eqIfPresent("is_sculpt", pageReqVO.getSculpt()) diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml index 737fda190..c2e66121a 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml @@ -45,7 +45,7 @@ from orders o join order_goods og on o.organ_id = og.organ_id and o.id = og.order_id and og.plan_id = 0 and o.deleted = og.deleted - join order_plate op on o.organ_id = op.organ_id and o.deleted = op.deleted and o.id = op.order_id and op.is_optimized = false + join order_plate op on o.organ_id = op.organ_id and o.deleted = op.deleted and o.id = op.order_id and op.is_optimized = false and og.id = op.goods_id ${ew.customSqlSegment} @@ -219,6 +219,7 @@ + @@ -251,13 +252,14 @@ og.width, og.height, og.brand, + og.remark, og.spec from orders o join order_goods og on o.organ_id = og.organ_id and o.id = og.order_id and og.plan_id = 0 and o.deleted = og.deleted - join order_plate op on o.organ_id = op.organ_id and o.deleted = op.deleted and o.id = op.order_id and op.is_optimized = false + join order_plate op on o.organ_id = op.organ_id and o.deleted = op.deleted and o.id = op.order_id and op.is_optimized = false and og.id = op.goods_id ${ew.customSqlSegment} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderParts/OrderPartsMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderParts/OrderPartsMapper.xml index f1497a40c..322aeec16 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderParts/OrderPartsMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderParts/OrderPartsMapper.xml @@ -87,19 +87,47 @@ AND organ_id = #{organId} - + + select distinct oi.group_id as groupId, + oi.num as partsNum, + oi.body_id as bodyId, + oi.room_id as roomId, ob.name as bodyName, ob.room_name as roomName, - op.id, - op.spec, - op.brand, - op.factory, - op.model, - op.name, - op.order_id + op.id as id, + op.spec as spec, + op.brand as brand, + op.factory as factory, + op.model as model , + op.name as name, + op.order_id as orderId, + op.type as type from order_parts op left join order_item oi on op.organ_id = oi.organ_id and op.order_id = oi.order_id and op.id = oi.parts_id left join order_body ob on oi.organ_id = ob.organ_id and oi.order_id = ob.order_id and oi.body_id = ob.id diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.java index ba45e6d7d..af3dd2216 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.java @@ -105,8 +105,8 @@ public interface OrderPackageMapper extends BaseMapperX { return selectList(new LambdaQueryWrapperX() .eq(OrderPackageDO::getOrganId,organId) .eq(OrderPackageDO::getDeleted,false) - .eq(OrderPackageDO::getStatus,OrderPackageStatusEnum.PACKAGED.getStatus()) - .eqIfPresent(OrderPackageDO::getOrderId, orderId)); + .eqIfPresent(OrderPackageDO::getOrderId, orderId) + .eq(OrderPackageDO::getStatus,OrderPackageStatusEnum.PACKAGED.getStatus())); } } diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.xml b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.xml index 612528ec4..1ea412656 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.xml +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/pack/OrderPackageMapper.xml @@ -62,6 +62,7 @@ and op.type = 0 + and op.status in (1,2,3) and oi.package_id != 0 and oi.plate_id != 0; diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java index 1b4d22daf..c6801deca 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java @@ -298,6 +298,7 @@ public interface ErrorCodeConstants { ErrorCode ORDER_PLAN_PLATE_MODEL_DATE_ERROR = new ErrorCode(1_002_041_009, "当前排单对应的板材造型数据为空,请检查板材信息或者联系客服"); ErrorCode ORDER_GOODS_DATA_ERROR = new ErrorCode(1_002_041_010, "当前大板数据异常,请检查大板信息或者联系客服"); ErrorCode ORDER_PACK_DATA_ERROR = new ErrorCode(1_002_041_011, "当前包裹数据为空,请重新查看包裹数据或联系客服"); + ErrorCode ORDER_BODY_DATA_ERROR = new ErrorCode(1_002_041_012, "当前柜体对应的板材数据为空,无法删除"); From b6ada0e251c9dbbbe133d4351401fdfc7f42f78a Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Wed, 25 Sep 2024 16:03:41 +0800 Subject: [PATCH 02/13] =?UTF-8?q?1=E3=80=81=E9=92=89=E9=92=89=E7=9F=AD?= =?UTF-8?q?=E4=BF=A1=E6=B8=A0=E9=81=93=E9=94=99=E8=AF=AF=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E6=8D=95=E8=8E=B7=E5=AD=97=E6=AE=B5=E4=BF=AE=E6=AD=A3=EF=BC=9B?= =?UTF-8?q?2=E3=80=81infra=E5=BE=AE=E6=9C=8D=E5=8A=A1=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=B8=85=E7=90=86=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/debug/DebugDingTalkSmsClient.java | 2 +- .../demo/demo01/Demo01ContactController.java | 93 -------- .../demo01/vo/Demo01ContactPageReqVO.java | 30 --- .../demo/demo01/vo/Demo01ContactRespVO.java | 46 ---- .../demo01/vo/Demo01ContactSaveReqVO.java | 36 --- .../demo/demo02/Demo02CategoryController.java | 90 -------- .../demo02/vo/Demo02CategoryListReqVO.java | 25 -- .../demo/demo02/vo/Demo02CategoryRespVO.java | 31 --- .../demo02/vo/Demo02CategorySaveReqVO.java | 24 -- .../demo/demo03/Demo03StudentController.java | 197 ---------------- .../admin/demo/demo03/package-info.java | 1 - .../demo03/vo/Demo03StudentPageReqVO.java | 33 --- .../demo/demo03/vo/Demo03StudentRespVO.java | 42 ---- .../demo03/vo/Demo03StudentSaveReqVO.java | 41 ---- .../controller/admin/demo/package-info.java | 8 - .../demo/demo01/Demo01ContactDO.java | 54 ----- .../demo/demo02/Demo02CategoryDO.java | 40 ---- .../demo/demo03/Demo03CourseDO.java | 42 ---- .../dataobject/demo/demo03/Demo03GradeDO.java | 42 ---- .../demo/demo03/Demo03StudentDO.java | 50 ---- .../demo/demo01/Demo01ContactMapper.java | 26 --- .../demo/demo02/Demo02CategoryMapper.java | 35 --- .../mysql/demo/demo03/Demo03CourseMapper.java | 34 --- .../mysql/demo/demo03/Demo03GradeMapper.java | 32 --- .../demo/demo03/Demo03StudentMapper.java | 27 --- .../demo/demo01/Demo01ContactService.java | 55 ----- .../demo/demo01/Demo01ContactServiceImpl.java | 72 ------ .../demo/demo02/Demo02CategoryService.java | 55 ----- .../demo02/Demo02CategoryServiceImpl.java | 134 ----------- .../demo/demo03/Demo03StudentService.java | 158 ------------- .../demo/demo03/Demo03StudentServiceImpl.java | 217 ------------------ 31 files changed, 1 insertion(+), 1771 deletions(-) delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/Demo01ContactController.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/vo/Demo01ContactPageReqVO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/vo/Demo01ContactSaveReqVO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/Demo02CategoryController.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryListReqVO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/vo/Demo02CategorySaveReqVO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/Demo03StudentController.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/package-info.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/vo/Demo03StudentPageReqVO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/vo/Demo03StudentRespVO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/vo/Demo03StudentSaveReqVO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/package-info.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo01/Demo01ContactDO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo02/Demo02CategoryDO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo03/Demo03CourseDO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo03/Demo03GradeDO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo03/Demo03StudentDO.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo01/Demo01ContactMapper.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo02/Demo02CategoryMapper.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo03/Demo03CourseMapper.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo03/Demo03GradeMapper.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo03/Demo03StudentMapper.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo01/Demo01ContactService.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo01/Demo01ContactServiceImpl.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo02/Demo02CategoryService.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo02/Demo02CategoryServiceImpl.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo03/Demo03StudentService.java delete mode 100644 cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo03/Demo03StudentServiceImpl.java diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java index 542ec58bb..f91b4f525 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java @@ -64,7 +64,7 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { Map responseObj = JsonUtils.parseObject(responseText, Map.class); String errorCode = MapUtil.getStr(responseObj, "errcode"); return new SmsSendRespDTO().setSuccess(Objects.equals(errorCode, "0")).setSerialNo(StrUtil.uuid()) - .setApiCode(errorCode).setApiMsg(MapUtil.getStr(responseObj, "errorMsg")).setMobile(mobile).setChannelCode(properties.getChannel()); + .setApiCode(errorCode).setApiMsg(MapUtil.getStr(responseObj, "errmsg")).setMobile(mobile).setChannelCode(properties.getChannel()); } /** diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/Demo01ContactController.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/Demo01ContactController.java deleted file mode 100644 index 8f1d5a54b..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/Demo01ContactController.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo01; - -import com.cf.imes.framework.common.pojo.CommonResult; -import com.cf.imes.framework.common.pojo.PageParam; -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.common.util.object.BeanUtils; -import com.cf.imes.framework.excel.core.util.ExcelUtils; -import com.cf.imes.framework.operatelog.core.annotations.OperateLog; -import com.cf.imes.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO; -import com.cf.imes.module.infra.controller.admin.demo.demo01.vo.Demo01ContactRespVO; -import com.cf.imes.module.infra.controller.admin.demo.demo01.vo.Demo01ContactSaveReqVO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO; -import com.cf.imes.module.infra.service.demo.demo01.Demo01ContactService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.io.IOException; -import java.util.List; - -import static com.cf.imes.framework.common.pojo.CommonResult.success; -import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; - -@Tag(name = "管理后台 - 示例联系人") -@RestController -@RequestMapping("/infra/demo01-contact") -@Validated -public class Demo01ContactController { - - @Resource - private Demo01ContactService demo01ContactService; - - @PostMapping("/create") - @Operation(summary = "创建示例联系人") - @PreAuthorize("@ss.hasPermission('infra:demo01-contact:create')") - public CommonResult createDemo01Contact(@Valid @RequestBody Demo01ContactSaveReqVO createReqVO) { - return success(demo01ContactService.createDemo01Contact(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新示例联系人") - @PreAuthorize("@ss.hasPermission('infra:demo01-contact:update')") - public CommonResult updateDemo01Contact(@Valid @RequestBody Demo01ContactSaveReqVO updateReqVO) { - demo01ContactService.updateDemo01Contact(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除示例联系人") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('infra:demo01-contact:delete')") - public CommonResult deleteDemo01Contact(@RequestParam("id") Long id) { - demo01ContactService.deleteDemo01Contact(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得示例联系人") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('infra:demo01-contact:query')") - public CommonResult getDemo01Contact(@RequestParam("id") Long id) { - Demo01ContactDO demo01Contact = demo01ContactService.getDemo01Contact(id); - return success(BeanUtils.toBean(demo01Contact, Demo01ContactRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得示例联系人分页") - @PreAuthorize("@ss.hasPermission('infra:demo01-contact:query')") - public CommonResult> getDemo01ContactPage(@Valid Demo01ContactPageReqVO pageReqVO) { - PageResult pageResult = demo01ContactService.getDemo01ContactPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, Demo01ContactRespVO.class)); - } - - @GetMapping("/export-excel") - @Operation(summary = "导出示例联系人 Excel") - @PreAuthorize("@ss.hasPermission('infra:demo01-contact:export')") - @OperateLog(type = EXPORT) - public void exportDemo01ContactExcel(@Valid Demo01ContactPageReqVO pageReqVO, - HttpServletResponse response) throws IOException { - pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - List list = demo01ContactService.getDemo01ContactPage(pageReqVO).getList(); - // 导出 Excel - ExcelUtils.write(response, "示例联系人.xls", "数据", Demo01ContactRespVO.class, - BeanUtils.toBean(list, Demo01ContactRespVO.class)); - } - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/vo/Demo01ContactPageReqVO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/vo/Demo01ContactPageReqVO.java deleted file mode 100644 index 4d53504c3..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/vo/Demo01ContactPageReqVO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo01.vo; - -import com.cf.imes.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 示例联系人分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class Demo01ContactPageReqVO extends PageParam { - - @Schema(description = "名字", example = "张三") - private String name; - - @Schema(description = "性别", example = "1") - private Integer sex; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java deleted file mode 100644 index e3b7068cd..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo01.vo; - -import com.cf.imes.framework.excel.core.annotations.DictFormat; -import com.cf.imes.framework.excel.core.convert.DictConvert; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - 示例联系人 Response VO") -@Data -@ExcelIgnoreUnannotated -public class Demo01ContactRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21555") - @ExcelProperty("编号") - private Long id; - - @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") - @ExcelProperty("名字") - private String name; - - @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @ExcelProperty(value = "性别", converter = DictConvert.class) - @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 - private Integer sex; - - @Schema(description = "出生年", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("出生年") - private LocalDateTime birthday; - - @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") - @ExcelProperty("简介") - private String description; - - @Schema(description = "头像") - @ExcelProperty("头像") - private String avatar; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/vo/Demo01ContactSaveReqVO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/vo/Demo01ContactSaveReqVO.java deleted file mode 100644 index 21ba7e28c..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo01/vo/Demo01ContactSaveReqVO.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo01.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - 示例联系人新增/修改 Request VO") -@Data -public class Demo01ContactSaveReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21555") - private Long id; - - @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") - @NotEmpty(message = "名字不能为空") - private String name; - - @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "性别不能为空") - private Integer sex; - - @Schema(description = "出生年", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "出生年不能为空") - private LocalDateTime birthday; - - @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "你说的对") - @NotEmpty(message = "简介不能为空") - private String description; - - @Schema(description = "头像") - private String avatar; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/Demo02CategoryController.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/Demo02CategoryController.java deleted file mode 100644 index e6b849c8c..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/Demo02CategoryController.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo02; - -import com.cf.imes.framework.common.pojo.CommonResult; -import com.cf.imes.framework.common.util.object.BeanUtils; -import com.cf.imes.framework.excel.core.util.ExcelUtils; -import com.cf.imes.framework.operatelog.core.annotations.OperateLog; -import com.cf.imes.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO; -import com.cf.imes.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryRespVO; -import com.cf.imes.module.infra.controller.admin.demo.demo02.vo.Demo02CategorySaveReqVO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO; -import com.cf.imes.module.infra.service.demo.demo02.Demo02CategoryService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.io.IOException; -import java.util.List; - -import static com.cf.imes.framework.common.pojo.CommonResult.success; -import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; - -@Tag(name = "管理后台 - 示例分类") -@RestController -@RequestMapping("/infra/demo02-category") -@Validated -public class Demo02CategoryController { - - @Resource - private Demo02CategoryService demo02CategoryService; - - @PostMapping("/create") - @Operation(summary = "创建示例分类") - @PreAuthorize("@ss.hasPermission('infra:demo02-category:create')") - public CommonResult createDemo02Category(@Valid @RequestBody Demo02CategorySaveReqVO createReqVO) { - return success(demo02CategoryService.createDemo02Category(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新示例分类") - @PreAuthorize("@ss.hasPermission('infra:demo02-category:update')") - public CommonResult updateDemo02Category(@Valid @RequestBody Demo02CategorySaveReqVO updateReqVO) { - demo02CategoryService.updateDemo02Category(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除示例分类") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('infra:demo02-category:delete')") - public CommonResult deleteDemo02Category(@RequestParam("id") Long id) { - demo02CategoryService.deleteDemo02Category(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得示例分类") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('infra:demo02-category:query')") - public CommonResult getDemo02Category(@RequestParam("id") Long id) { - Demo02CategoryDO demo02Category = demo02CategoryService.getDemo02Category(id); - return success(BeanUtils.toBean(demo02Category, Demo02CategoryRespVO.class)); - } - - @GetMapping("/list") - @Operation(summary = "获得示例分类列表") - @PreAuthorize("@ss.hasPermission('infra:demo02-category:query')") - public CommonResult> getDemo02CategoryList(@Valid Demo02CategoryListReqVO listReqVO) { - List list = demo02CategoryService.getDemo02CategoryList(listReqVO); - return success(BeanUtils.toBean(list, Demo02CategoryRespVO.class)); - } - - @GetMapping("/export-excel") - @Operation(summary = "导出示例分类 Excel") - @PreAuthorize("@ss.hasPermission('infra:demo02-category:export')") - @OperateLog(type = EXPORT) - public void exportDemo02CategoryExcel(@Valid Demo02CategoryListReqVO listReqVO, - HttpServletResponse response) throws IOException { - List list = demo02CategoryService.getDemo02CategoryList(listReqVO); - // 导出 Excel - ExcelUtils.write(response, "示例分类.xls", "数据", Demo02CategoryRespVO.class, - BeanUtils.toBean(list, Demo02CategoryRespVO.class)); - } - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryListReqVO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryListReqVO.java deleted file mode 100644 index c63e062ce..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryListReqVO.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo02.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 示例分类列表 Request VO") -@Data -public class Demo02CategoryListReqVO { - - @Schema(description = "名字", example = "晨丰") - private String name; - - @Schema(description = "父级编号", example = "6080") - private Long parentId; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java deleted file mode 100644 index 2988846c9..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo02.vo; - -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - 示例分类 Response VO") -@Data -@ExcelIgnoreUnannotated -public class Demo02CategoryRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10304") - @ExcelProperty("编号") - private Long id; - - @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰") - @ExcelProperty("名字") - private String name; - - @Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6080") - @ExcelProperty("父级编号") - private Long parentId; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/vo/Demo02CategorySaveReqVO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/vo/Demo02CategorySaveReqVO.java deleted file mode 100644 index fbcf442cb..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo02/vo/Demo02CategorySaveReqVO.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo02.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -@Schema(description = "管理后台 - 示例分类新增/修改 Request VO") -@Data -public class Demo02CategorySaveReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10304") - private Long id; - - @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰") - @NotEmpty(message = "名字不能为空") - private String name; - - @Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6080") - @NotNull(message = "父级编号不能为空") - private Long parentId; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/Demo03StudentController.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/Demo03StudentController.java deleted file mode 100644 index 58f2cc5d3..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/Demo03StudentController.java +++ /dev/null @@ -1,197 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo03; - -import com.cf.imes.framework.common.pojo.CommonResult; -import com.cf.imes.framework.common.pojo.PageParam; -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.common.util.object.BeanUtils; -import com.cf.imes.framework.excel.core.util.ExcelUtils; -import com.cf.imes.framework.operatelog.core.annotations.OperateLog; -import com.cf.imes.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO; -import com.cf.imes.module.infra.controller.admin.demo.demo03.vo.Demo03StudentRespVO; -import com.cf.imes.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO; -import com.cf.imes.module.infra.service.demo.demo03.Demo03StudentService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.io.IOException; -import java.util.List; - -import static com.cf.imes.framework.common.pojo.CommonResult.success; -import static com.cf.imes.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; - -@Tag(name = "管理后台 - 学生") -@RestController -@RequestMapping("/infra/demo03-student") -@Validated -public class Demo03StudentController { - - @Resource - private Demo03StudentService demo03StudentService; - - @PostMapping("/create") - @Operation(summary = "创建学生") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:create')") - public CommonResult createDemo03Student(@Valid @RequestBody Demo03StudentSaveReqVO createReqVO) { - return success(demo03StudentService.createDemo03Student(createReqVO)); - } - - @PutMapping("/update") - @Operation(summary = "更新学生") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:update')") - public CommonResult updateDemo03Student(@Valid @RequestBody Demo03StudentSaveReqVO updateReqVO) { - demo03StudentService.updateDemo03Student(updateReqVO); - return success(true); - } - - @DeleteMapping("/delete") - @Operation(summary = "删除学生") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')") - public CommonResult deleteDemo03Student(@RequestParam("id") Long id) { - demo03StudentService.deleteDemo03Student(id); - return success(true); - } - - @GetMapping("/get") - @Operation(summary = "获得学生") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") - public CommonResult getDemo03Student(@RequestParam("id") Long id) { - Demo03StudentDO demo03Student = demo03StudentService.getDemo03Student(id); - return success(BeanUtils.toBean(demo03Student, Demo03StudentRespVO.class)); - } - - @GetMapping("/page") - @Operation(summary = "获得学生分页") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") - public CommonResult> getDemo03StudentPage(@Valid Demo03StudentPageReqVO pageReqVO) { - PageResult pageResult = demo03StudentService.getDemo03StudentPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, Demo03StudentRespVO.class)); - } - - @GetMapping("/export-excel") - @Operation(summary = "导出学生 Excel") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:export')") - @OperateLog(type = EXPORT) - public void exportDemo03StudentExcel(@Valid Demo03StudentPageReqVO pageReqVO, - HttpServletResponse response) throws IOException { - pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - List list = demo03StudentService.getDemo03StudentPage(pageReqVO).getList(); - // 导出 Excel - ExcelUtils.write(response, "学生.xls", "数据", Demo03StudentRespVO.class, - BeanUtils.toBean(list, Demo03StudentRespVO.class)); - } - - // ==================== 子表(学生课程) ==================== - - @GetMapping("/demo03-course/page") - @Operation(summary = "获得学生课程分页") - @Parameter(name = "studentId", description = "学生编号") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") - public CommonResult> getDemo03CoursePage(PageParam pageReqVO, - @RequestParam("studentId") Long studentId) { - return success(demo03StudentService.getDemo03CoursePage(pageReqVO, studentId)); - } - - @PostMapping("/demo03-course/create") - @Operation(summary = "创建学生课程") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:create')") - public CommonResult createDemo03Course(@Valid @RequestBody Demo03CourseDO demo03Course) { - return success(demo03StudentService.createDemo03Course(demo03Course)); - } - - @PutMapping("/demo03-course/update") - @Operation(summary = "更新学生课程") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:update')") - public CommonResult updateDemo03Course(@Valid @RequestBody Demo03CourseDO demo03Course) { - demo03StudentService.updateDemo03Course(demo03Course); - return success(true); - } - - @DeleteMapping("/demo03-course/delete") - @Parameter(name = "id", description = "编号", required = true) - @Operation(summary = "删除学生课程") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')") - public CommonResult deleteDemo03Course(@RequestParam("id") Long id) { - demo03StudentService.deleteDemo03Course(id); - return success(true); - } - - @GetMapping("/demo03-course/get") - @Operation(summary = "获得学生课程") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") - public CommonResult getDemo03Course(@RequestParam("id") Long id) { - return success(demo03StudentService.getDemo03Course(id)); - } - - @GetMapping("/demo03-course/list-by-student-id") - @Operation(summary = "获得学生课程列表") - @Parameter(name = "studentId", description = "学生编号") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") - public CommonResult> getDemo03CourseListByStudentId(@RequestParam("studentId") Long studentId) { - return success(demo03StudentService.getDemo03CourseListByStudentId(studentId)); - } - - // ==================== 子表(学生班级) ==================== - - @GetMapping("/demo03-grade/page") - @Operation(summary = "获得学生班级分页") - @Parameter(name = "studentId", description = "学生编号") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") - public CommonResult> getDemo03GradePage(PageParam pageReqVO, - @RequestParam("studentId") Long studentId) { - return success(demo03StudentService.getDemo03GradePage(pageReqVO, studentId)); - } - - @PostMapping("/demo03-grade/create") - @Operation(summary = "创建学生班级") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:create')") - public CommonResult createDemo03Grade(@Valid @RequestBody Demo03GradeDO demo03Grade) { - return success(demo03StudentService.createDemo03Grade(demo03Grade)); - } - - @PutMapping("/demo03-grade/update") - @Operation(summary = "更新学生班级") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:update')") - public CommonResult updateDemo03Grade(@Valid @RequestBody Demo03GradeDO demo03Grade) { - demo03StudentService.updateDemo03Grade(demo03Grade); - return success(true); - } - - @DeleteMapping("/demo03-grade/delete") - @Parameter(name = "id", description = "编号", required = true) - @Operation(summary = "删除学生班级") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:delete')") - public CommonResult deleteDemo03Grade(@RequestParam("id") Long id) { - demo03StudentService.deleteDemo03Grade(id); - return success(true); - } - - @GetMapping("/demo03-grade/get") - @Operation(summary = "获得学生班级") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") - public CommonResult getDemo03Grade(@RequestParam("id") Long id) { - return success(demo03StudentService.getDemo03Grade(id)); - } - - @GetMapping("/demo03-grade/get-by-student-id") - @Operation(summary = "获得学生班级") - @Parameter(name = "studentId", description = "学生编号") - @PreAuthorize("@ss.hasPermission('infra:demo03-student:query')") - public CommonResult getDemo03GradeByStudentId(@RequestParam("studentId") Long studentId) { - return success(demo03StudentService.getDemo03GradeByStudentId(studentId)); - } - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/package-info.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/package-info.java deleted file mode 100644 index f2f82e1ab..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo03; diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/vo/Demo03StudentPageReqVO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/vo/Demo03StudentPageReqVO.java deleted file mode 100644 index 2ac985baa..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/vo/Demo03StudentPageReqVO.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo03.vo; - -import com.cf.imes.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 学生分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class Demo03StudentPageReqVO extends PageParam { - - @Schema(description = "名字", example = "晨丰") - private String name; - - @Schema(description = "性别") - private Integer sex; - - @Schema(description = "简介", example = "随便") - private String description; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/vo/Demo03StudentRespVO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/vo/Demo03StudentRespVO.java deleted file mode 100644 index 39e1fdd96..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/vo/Demo03StudentRespVO.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo03.vo; - -import com.cf.imes.framework.excel.core.annotations.DictFormat; -import com.cf.imes.framework.excel.core.convert.DictConvert; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - 学生 Response VO") -@Data -@ExcelIgnoreUnannotated -public class Demo03StudentRespVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8525") - @ExcelProperty("编号") - private Long id; - - @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰") - @ExcelProperty("名字") - private String name; - - @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty(value = "性别", converter = DictConvert.class) - @DictFormat("system_user_sex") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 - private Integer sex; - - @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("出生日期") - private LocalDateTime birthday; - - @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "随便") - @ExcelProperty("简介") - private String description; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/vo/Demo03StudentSaveReqVO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/vo/Demo03StudentSaveReqVO.java deleted file mode 100644 index 8d6c1fcff..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/demo03/vo/Demo03StudentSaveReqVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.cf.imes.module.infra.controller.admin.demo.demo03.vo; - -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; -import java.util.List; - -@Schema(description = "管理后台 - 学生新增/修改 Request VO") -@Data -public class Demo03StudentSaveReqVO { - - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8525") - private Long id; - - @Schema(description = "名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰") - @NotEmpty(message = "名字不能为空") - private String name; - - @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "性别不能为空") - private Integer sex; - - @Schema(description = "出生日期", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "出生日期不能为空") - private LocalDateTime birthday; - - @Schema(description = "简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "随便") - @NotEmpty(message = "简介不能为空") - private String description; - - - private List demo03Courses; - - private Demo03GradeDO demo03Grade; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/package-info.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/package-info.java deleted file mode 100644 index 66fb29eed..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/controller/admin/demo/package-info.java +++ /dev/null @@ -1,8 +0,0 @@ -/** - * 代码生成示例 - * - * 1. demo01:单表(增删改查) - * 2. demo02:单表(树形结构) - * 3. demo03:主子表(标准模式)+ 主子表(ERP 模式)+ 主子表(内嵌模式) - */ -package com.cf.imes.module.infra.controller.admin.demo; diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo01/Demo01ContactDO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo01/Demo01ContactDO.java deleted file mode 100644 index 44809cc98..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo01/Demo01ContactDO.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.cf.imes.module.infra.dal.dataobject.demo.demo01; - -import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -import java.time.LocalDateTime; - -/** - * 示例联系人 DO - * - * @author 晨丰科技 - */ -@TableName("infra_demo01_contact") -@KeySequence("infra_demo01_contact_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class Demo01ContactDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 名字 - */ - private String name; - /** - * 性别 - * - * 枚举 {@link TODO system_user_sex 对应的类} - */ - private Integer sex; - /** - * 出生年 - */ - private LocalDateTime birthday; - /** - * 简介 - */ - private String description; - /** - * 头像 - */ - private String avatar; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo02/Demo02CategoryDO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo02/Demo02CategoryDO.java deleted file mode 100644 index 78d5c6c43..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo02/Demo02CategoryDO.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.cf.imes.module.infra.dal.dataobject.demo.demo02; - -import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * 示例分类 DO - * - * @author 晨丰科技 - */ -@TableName("infra_demo02_category") -@KeySequence("infra_demo02_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class Demo02CategoryDO extends BaseDO { - - public static final Long PARENT_ID_ROOT = 0L; - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 名字 - */ - private String name; - /** - * 父级编号 - */ - private Long parentId; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo03/Demo03CourseDO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo03/Demo03CourseDO.java deleted file mode 100644 index f6634780c..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo03/Demo03CourseDO.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.cf.imes.module.infra.dal.dataobject.demo.demo03; - -import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * 学生课程 DO - * - * @author 晨丰科技 - */ -@TableName("infra_demo03_course") -@KeySequence("infra_demo03_course_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class Demo03CourseDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 学生编号 - */ - private Long studentId; - /** - * 名字 - */ - private String name; - /** - * 分数 - */ - private Integer score; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo03/Demo03GradeDO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo03/Demo03GradeDO.java deleted file mode 100644 index a0ed7ebe9..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo03/Demo03GradeDO.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.cf.imes.module.infra.dal.dataobject.demo.demo03; - -import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -/** - * 学生班级 DO - * - * @author 晨丰科技 - */ -@TableName("infra_demo03_grade") -@KeySequence("infra_demo03_grade_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class Demo03GradeDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 学生编号 - */ - private Long studentId; - /** - * 名字 - */ - private String name; - /** - * 班主任 - */ - private String teacher; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo03/Demo03StudentDO.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo03/Demo03StudentDO.java deleted file mode 100644 index ebc374a1f..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/dataobject/demo/demo03/Demo03StudentDO.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.cf.imes.module.infra.dal.dataobject.demo.demo03; - -import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.*; - -import java.time.LocalDateTime; - -/** - * 学生 DO - * - * @author 晨丰科技 - */ -@TableName("infra_demo03_student") -@KeySequence("infra_demo03_student_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@Builder -@NoArgsConstructor -@AllArgsConstructor -public class Demo03StudentDO extends BaseDO { - - /** - * 编号 - */ - @TableId - private Long id; - /** - * 名字 - */ - private String name; - /** - * 性别 - * - * 枚举 {@link TODO system_user_sex 对应的类} - */ - private Integer sex; - /** - * 出生日期 - */ - private LocalDateTime birthday; - /** - * 简介 - */ - private String description; - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo01/Demo01ContactMapper.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo01/Demo01ContactMapper.java deleted file mode 100644 index dfc1763ea..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo01/Demo01ContactMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.cf.imes.module.infra.dal.mysql.demo.demo01; - -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; -import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.cf.imes.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * 示例联系人 Mapper - * - * @author 晨丰科技 - */ -@Mapper -public interface Demo01ContactMapper extends BaseMapperX { - - default PageResult selectPage(Demo01ContactPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(Demo01ContactDO::getName, reqVO.getName()) - .eqIfPresent(Demo01ContactDO::getSex, reqVO.getSex()) - .betweenIfPresent(Demo01ContactDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(Demo01ContactDO::getId)); - } - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo02/Demo02CategoryMapper.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo02/Demo02CategoryMapper.java deleted file mode 100644 index 7be39a040..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo02/Demo02CategoryMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.cf.imes.module.infra.dal.mysql.demo.demo02; - -import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; -import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.cf.imes.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * 示例分类 Mapper - * - * @author 晨丰科技 - */ -@Mapper -public interface Demo02CategoryMapper extends BaseMapperX { - - default List selectList(Demo02CategoryListReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .likeIfPresent(Demo02CategoryDO::getName, reqVO.getName()) - .eqIfPresent(Demo02CategoryDO::getParentId, reqVO.getParentId()) - .betweenIfPresent(Demo02CategoryDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(Demo02CategoryDO::getId)); - } - - default Demo02CategoryDO selectByParentIdAndName(Long parentId, String name) { - return selectOne(Demo02CategoryDO::getParentId, parentId, Demo02CategoryDO::getName, name); - } - - default Long selectCountByParentId(Long parentId) { - return selectCount(Demo02CategoryDO::getParentId, parentId); - } - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo03/Demo03CourseMapper.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo03/Demo03CourseMapper.java deleted file mode 100644 index 3de825440..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo03/Demo03CourseMapper.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.cf.imes.module.infra.dal.mysql.demo.demo03; - -import com.cf.imes.framework.common.pojo.PageParam; -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; -import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * 学生课程 Mapper - * - * @author 晨丰科技 - */ -@Mapper -public interface Demo03CourseMapper extends BaseMapperX { - - default PageResult selectPage(PageParam reqVO, Long studentId) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eq(Demo03CourseDO::getStudentId, studentId) - .orderByDesc(Demo03CourseDO::getId)); - } - - default List selectListByStudentId(Long studentId) { - return selectList(Demo03CourseDO::getStudentId, studentId); - } - - default int deleteByStudentId(Long studentId) { - return delete(Demo03CourseDO::getStudentId, studentId); - } - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo03/Demo03GradeMapper.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo03/Demo03GradeMapper.java deleted file mode 100644 index af0e570e4..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo03/Demo03GradeMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.cf.imes.module.infra.dal.mysql.demo.demo03; - -import com.cf.imes.framework.common.pojo.PageParam; -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; -import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * 学生班级 Mapper - * - * @author 晨丰科技 - */ -@Mapper -public interface Demo03GradeMapper extends BaseMapperX { - - default PageResult selectPage(PageParam reqVO, Long studentId) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eq(Demo03GradeDO::getStudentId, studentId) - .orderByDesc(Demo03GradeDO::getId)); - } - - default Demo03GradeDO selectByStudentId(Long studentId) { - return selectOne(Demo03GradeDO::getStudentId, studentId); - } - - default int deleteByStudentId(Long studentId) { - return delete(Demo03GradeDO::getStudentId, studentId); - } - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo03/Demo03StudentMapper.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo03/Demo03StudentMapper.java deleted file mode 100644 index a14877575..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/dal/mysql/demo/demo03/Demo03StudentMapper.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.cf.imes.module.infra.dal.mysql.demo.demo03; - -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; -import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; -import com.cf.imes.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * 学生 Mapper - * - * @author 晨丰科技 - */ -@Mapper -public interface Demo03StudentMapper extends BaseMapperX { - - default PageResult selectPage(Demo03StudentPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(Demo03StudentDO::getName, reqVO.getName()) - .eqIfPresent(Demo03StudentDO::getSex, reqVO.getSex()) - .eqIfPresent(Demo03StudentDO::getDescription, reqVO.getDescription()) - .betweenIfPresent(Demo03StudentDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(Demo03StudentDO::getId)); - } - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo01/Demo01ContactService.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo01/Demo01ContactService.java deleted file mode 100644 index 5a78781fd..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo01/Demo01ContactService.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.cf.imes.module.infra.service.demo.demo01; - -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO; -import com.cf.imes.module.infra.controller.admin.demo.demo01.vo.Demo01ContactSaveReqVO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO; - -import javax.validation.Valid; - -/** - * 示例联系人 Service 接口 - * - * @author 晨丰科技 - */ -public interface Demo01ContactService { - - /** - * 创建示例联系人 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createDemo01Contact(@Valid Demo01ContactSaveReqVO createReqVO); - - /** - * 更新示例联系人 - * - * @param updateReqVO 更新信息 - */ - void updateDemo01Contact(@Valid Demo01ContactSaveReqVO updateReqVO); - - /** - * 删除示例联系人 - * - * @param id 编号 - */ - void deleteDemo01Contact(Long id); - - /** - * 获得示例联系人 - * - * @param id 编号 - * @return 示例联系人 - */ - Demo01ContactDO getDemo01Contact(Long id); - - /** - * 获得示例联系人分页 - * - * @param pageReqVO 分页查询 - * @return 示例联系人分页 - */ - PageResult getDemo01ContactPage(Demo01ContactPageReqVO pageReqVO); - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo01/Demo01ContactServiceImpl.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo01/Demo01ContactServiceImpl.java deleted file mode 100644 index 6cddb345e..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo01/Demo01ContactServiceImpl.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.cf.imes.module.infra.service.demo.demo01; - -import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.common.util.object.BeanUtils; -import com.cf.imes.module.infra.controller.admin.demo.demo01.vo.Demo01ContactPageReqVO; -import com.cf.imes.module.infra.controller.admin.demo.demo01.vo.Demo01ContactSaveReqVO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo01.Demo01ContactDO; -import com.cf.imes.module.infra.dal.mysql.demo.demo01.Demo01ContactMapper; -import com.cf.imes.module.infra.enums.ErrorCodeConstants; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; - -import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; - -/** - * 示例联系人 Service 实现类 - * - * @author 晨丰科技 - */ -@Service -@Validated -public class Demo01ContactServiceImpl implements Demo01ContactService { - - @Resource - private Demo01ContactMapper demo01ContactMapper; - - @Override - public Long createDemo01Contact(Demo01ContactSaveReqVO createReqVO) { - // 插入 - Demo01ContactDO demo01Contact = BeanUtils.toBean(createReqVO, Demo01ContactDO.class); - demo01ContactMapper.insert(demo01Contact); - // 返回 - return demo01Contact.getId(); - } - - @Override - public void updateDemo01Contact(Demo01ContactSaveReqVO updateReqVO) { - // 校验存在 - validateDemo01ContactExists(updateReqVO.getId()); - // 更新 - Demo01ContactDO updateObj = BeanUtils.toBean(updateReqVO, Demo01ContactDO.class); - demo01ContactMapper.updateById(updateObj); - } - - @Override - public void deleteDemo01Contact(Long id) { - // 校验存在 - validateDemo01ContactExists(id); - // 删除 - demo01ContactMapper.deleteById(id); - } - - private void validateDemo01ContactExists(Long id) { - if (demo01ContactMapper.selectById(id) == null) { - throw ServiceExceptionUtil.exception(ErrorCodeConstants.DEMO01_CONTACT_NOT_EXISTS); - } - } - - @Override - public Demo01ContactDO getDemo01Contact(Long id) { - return demo01ContactMapper.selectById(id); - } - - @Override - public PageResult getDemo01ContactPage(Demo01ContactPageReqVO pageReqVO) { - return demo01ContactMapper.selectPage(pageReqVO); - } - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo02/Demo02CategoryService.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo02/Demo02CategoryService.java deleted file mode 100644 index f63cf2b80..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo02/Demo02CategoryService.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.cf.imes.module.infra.service.demo.demo02; - -import com.cf.imes.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO; -import com.cf.imes.module.infra.controller.admin.demo.demo02.vo.Demo02CategorySaveReqVO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO; - -import javax.validation.Valid; -import java.util.List; - -/** - * 示例分类 Service 接口 - * - * @author 晨丰科技 - */ -public interface Demo02CategoryService { - - /** - * 创建示例分类 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createDemo02Category(@Valid Demo02CategorySaveReqVO createReqVO); - - /** - * 更新示例分类 - * - * @param updateReqVO 更新信息 - */ - void updateDemo02Category(@Valid Demo02CategorySaveReqVO updateReqVO); - - /** - * 删除示例分类 - * - * @param id 编号 - */ - void deleteDemo02Category(Long id); - - /** - * 获得示例分类 - * - * @param id 编号 - * @return 示例分类 - */ - Demo02CategoryDO getDemo02Category(Long id); - - /** - * 获得示例分类列表 - * - * @param listReqVO 查询条件 - * @return 示例分类列表 - */ - List getDemo02CategoryList(Demo02CategoryListReqVO listReqVO); - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo02/Demo02CategoryServiceImpl.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo02/Demo02CategoryServiceImpl.java deleted file mode 100644 index 30e22e35a..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo02/Demo02CategoryServiceImpl.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.cf.imes.module.infra.service.demo.demo02; - -import com.cf.imes.framework.common.util.object.BeanUtils; -import com.cf.imes.module.infra.controller.admin.demo.demo02.vo.Demo02CategoryListReqVO; -import com.cf.imes.module.infra.controller.admin.demo.demo02.vo.Demo02CategorySaveReqVO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo02.Demo02CategoryDO; -import com.cf.imes.module.infra.dal.mysql.demo.demo02.Demo02CategoryMapper; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.List; -import java.util.Objects; - -import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; -import static com.cf.imes.module.infra.enums.ErrorCodeConstants.*; - -/** - * 示例分类 Service 实现类 - * - * @author 晨丰科技 - */ -@Service -@Validated -public class Demo02CategoryServiceImpl implements Demo02CategoryService { - - @Resource - private Demo02CategoryMapper demo02CategoryMapper; - - @Override - public Long createDemo02Category(Demo02CategorySaveReqVO createReqVO) { - // 校验父级编号的有效性 - validateParentDemo02Category(null, createReqVO.getParentId()); - // 校验名字的唯一性 - validateDemo02CategoryNameUnique(null, createReqVO.getParentId(), createReqVO.getName()); - - // 插入 - Demo02CategoryDO demo02Category = BeanUtils.toBean(createReqVO, Demo02CategoryDO.class); - demo02CategoryMapper.insert(demo02Category); - // 返回 - return demo02Category.getId(); - } - - @Override - public void updateDemo02Category(Demo02CategorySaveReqVO updateReqVO) { - // 校验存在 - validateDemo02CategoryExists(updateReqVO.getId()); - // 校验父级编号的有效性 - validateParentDemo02Category(updateReqVO.getId(), updateReqVO.getParentId()); - // 校验名字的唯一性 - validateDemo02CategoryNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); - - // 更新 - Demo02CategoryDO updateObj = BeanUtils.toBean(updateReqVO, Demo02CategoryDO.class); - demo02CategoryMapper.updateById(updateObj); - } - - @Override - public void deleteDemo02Category(Long id) { - // 校验存在 - validateDemo02CategoryExists(id); - // 校验是否有子示例分类 - if (demo02CategoryMapper.selectCountByParentId(id) > 0) { - throw exception(DEMO02_CATEGORY_EXITS_CHILDREN); - } - // 删除 - demo02CategoryMapper.deleteById(id); - } - - private void validateDemo02CategoryExists(Long id) { - if (demo02CategoryMapper.selectById(id) == null) { - throw exception(DEMO02_CATEGORY_NOT_EXISTS); - } - } - - private void validateParentDemo02Category(Long id, Long parentId) { - if (parentId == null || Demo02CategoryDO.PARENT_ID_ROOT.equals(parentId)) { - return; - } - // 1. 不能设置自己为父示例分类 - if (Objects.equals(id, parentId)) { - throw exception(DEMO02_CATEGORY_PARENT_ERROR); - } - // 2. 父示例分类不存在 - Demo02CategoryDO parentDemo02Category = demo02CategoryMapper.selectById(parentId); - if (parentDemo02Category == null) { - throw exception(DEMO02_CATEGORY_PARENT_NOT_EXITS); - } - // 3. 递归校验父示例分类,如果父示例分类是自己的子示例分类,则报错,避免形成环路 - if (id == null) { // id 为空,说明新增,不需要考虑环路 - return; - } - for (int i = 0; i < Short.MAX_VALUE; i++) { - // 3.1 校验环路 - parentId = parentDemo02Category.getParentId(); - if (Objects.equals(id, parentId)) { - throw exception(DEMO02_CATEGORY_PARENT_IS_CHILD); - } - // 3.2 继续递归下一级父示例分类 - if (parentId == null || Demo02CategoryDO.PARENT_ID_ROOT.equals(parentId)) { - break; - } - parentDemo02Category = demo02CategoryMapper.selectById(parentId); - if (parentDemo02Category == null) { - break; - } - } - } - - private void validateDemo02CategoryNameUnique(Long id, Long parentId, String name) { - Demo02CategoryDO demo02Category = demo02CategoryMapper.selectByParentIdAndName(parentId, name); - if (demo02Category == null) { - return; - } - // 如果 id 为空,说明不用比较是否为相同 id 的示例分类 - if (id == null) { - throw exception(DEMO02_CATEGORY_NAME_DUPLICATE); - } - if (!Objects.equals(demo02Category.getId(), id)) { - throw exception(DEMO02_CATEGORY_NAME_DUPLICATE); - } - } - - @Override - public Demo02CategoryDO getDemo02Category(Long id) { - return demo02CategoryMapper.selectById(id); - } - - @Override - public List getDemo02CategoryList(Demo02CategoryListReqVO listReqVO) { - return demo02CategoryMapper.selectList(listReqVO); - } - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo03/Demo03StudentService.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo03/Demo03StudentService.java deleted file mode 100644 index 58a4ef1d0..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo03/Demo03StudentService.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.cf.imes.module.infra.service.demo.demo03; - -import com.cf.imes.framework.common.pojo.PageParam; -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO; -import com.cf.imes.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO; - -import javax.validation.Valid; -import java.util.List; - -/** - * 学生 Service 接口 - * - * @author 晨丰科技 - */ -public interface Demo03StudentService { - - /** - * 创建学生 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createDemo03Student(@Valid Demo03StudentSaveReqVO createReqVO); - - /** - * 更新学生 - * - * @param updateReqVO 更新信息 - */ - void updateDemo03Student(@Valid Demo03StudentSaveReqVO updateReqVO); - - /** - * 删除学生 - * - * @param id 编号 - */ - void deleteDemo03Student(Long id); - - /** - * 获得学生 - * - * @param id 编号 - * @return 学生 - */ - Demo03StudentDO getDemo03Student(Long id); - - /** - * 获得学生分页 - * - * @param pageReqVO 分页查询 - * @return 学生分页 - */ - PageResult getDemo03StudentPage(Demo03StudentPageReqVO pageReqVO); - - - // ==================== 子表(学生课程) ==================== - - /** - * 获得学生课程列表 - * - * @param studentId 学生编号 - * @return 学生课程列表 - */ - List getDemo03CourseListByStudentId(Long studentId); - - /** - * 获得学生课程分页 - * - * @param pageReqVO 分页查询 - * @param studentId 学生编号 - * @return 学生课程分页 - */ - PageResult getDemo03CoursePage(PageParam pageReqVO, Long studentId); - - /** - * 创建学生课程 - * - * @param demo03Course 创建信息 - * @return 编号 - */ - Long createDemo03Course(@Valid Demo03CourseDO demo03Course); - - /** - * 更新学生课程 - * - * @param demo03Course 更新信息 - */ - void updateDemo03Course(@Valid Demo03CourseDO demo03Course); - - /** - * 删除学生课程 - * - * @param id 编号 - */ - void deleteDemo03Course(Long id); - - /** - * 获得学生课程 - * - * @param id 编号 - * @return 学生课程 - */ - Demo03CourseDO getDemo03Course(Long id); - - // ==================== 子表(学生班级) ==================== - - /** - * 获得学生班级 - * - * @param studentId 学生编号 - * @return 学生班级 - */ - Demo03GradeDO getDemo03GradeByStudentId(Long studentId); - - /** - * 获得学生班级分页 - * - * @param pageReqVO 分页查询 - * @param studentId 学生编号 - * @return 学生班级分页 - */ - PageResult getDemo03GradePage(PageParam pageReqVO, Long studentId); - - /** - * 创建学生班级 - * - * @param demo03Grade 创建信息 - * @return 编号 - */ - Long createDemo03Grade(@Valid Demo03GradeDO demo03Grade); - - /** - * 更新学生班级 - * - * @param demo03Grade 更新信息 - */ - void updateDemo03Grade(@Valid Demo03GradeDO demo03Grade); - - /** - * 删除学生班级 - * - * @param id 编号 - */ - void deleteDemo03Grade(Long id); - - /** - * 获得学生班级 - * - * @param id 编号 - * @return 学生班级 - */ - Demo03GradeDO getDemo03Grade(Long id); - -} diff --git a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo03/Demo03StudentServiceImpl.java b/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo03/Demo03StudentServiceImpl.java deleted file mode 100644 index d1b5a667f..000000000 --- a/cf-module-infra/cf-module-infra-biz/src/main/java/com/cf/imes/module/infra/service/demo/demo03/Demo03StudentServiceImpl.java +++ /dev/null @@ -1,217 +0,0 @@ -package com.cf.imes.module.infra.service.demo.demo03; - -import com.cf.imes.framework.common.pojo.PageParam; -import com.cf.imes.framework.common.pojo.PageResult; -import com.cf.imes.framework.common.util.object.BeanUtils; -import com.cf.imes.module.infra.controller.admin.demo.demo03.vo.Demo03StudentPageReqVO; -import com.cf.imes.module.infra.controller.admin.demo.demo03.vo.Demo03StudentSaveReqVO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03CourseDO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03GradeDO; -import com.cf.imes.module.infra.dal.dataobject.demo.demo03.Demo03StudentDO; -import com.cf.imes.module.infra.dal.mysql.demo.demo03.Demo03CourseMapper; -import com.cf.imes.module.infra.dal.mysql.demo.demo03.Demo03GradeMapper; -import com.cf.imes.module.infra.dal.mysql.demo.demo03.Demo03StudentMapper; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.List; - -import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; -import static com.cf.imes.module.infra.enums.ErrorCodeConstants.*; - -/** - * 学生 Service 实现类 - * - * @author 晨丰科技 - */ -@Service -@Validated -public class Demo03StudentServiceImpl implements Demo03StudentService { - - @Resource - private Demo03StudentMapper demo03StudentMapper; - @Resource - private Demo03CourseMapper demo03CourseMapper; - @Resource - private Demo03GradeMapper demo03GradeMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public Long createDemo03Student(Demo03StudentSaveReqVO createReqVO) { - // 插入 - Demo03StudentDO demo03Student = BeanUtils.toBean(createReqVO, Demo03StudentDO.class); - demo03StudentMapper.insert(demo03Student); - - // 插入子表 - createDemo03CourseList(demo03Student.getId(), createReqVO.getDemo03Courses()); - createDemo03Grade(demo03Student.getId(), createReqVO.getDemo03Grade()); - // 返回 - return demo03Student.getId(); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateDemo03Student(Demo03StudentSaveReqVO updateReqVO) { - // 校验存在 - validateDemo03StudentExists(updateReqVO.getId()); - // 更新 - Demo03StudentDO updateObj = BeanUtils.toBean(updateReqVO, Demo03StudentDO.class); - demo03StudentMapper.updateById(updateObj); - - // 更新子表 - updateDemo03CourseList(updateReqVO.getId(), updateReqVO.getDemo03Courses()); - updateDemo03Grade(updateReqVO.getId(), updateReqVO.getDemo03Grade()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteDemo03Student(Long id) { - // 校验存在 - validateDemo03StudentExists(id); - // 删除 - demo03StudentMapper.deleteById(id); - - // 删除子表 - deleteDemo03CourseByStudentId(id); - deleteDemo03GradeByStudentId(id); - } - - private void validateDemo03StudentExists(Long id) { - if (demo03StudentMapper.selectById(id) == null) { - throw exception(DEMO03_STUDENT_NOT_EXISTS); - } - } - - @Override - public Demo03StudentDO getDemo03Student(Long id) { - return demo03StudentMapper.selectById(id); - } - - @Override - public PageResult getDemo03StudentPage(Demo03StudentPageReqVO pageReqVO) { - return demo03StudentMapper.selectPage(pageReqVO); - } - - // ==================== 子表(学生课程) ==================== - - @Override - public List getDemo03CourseListByStudentId(Long studentId) { - return demo03CourseMapper.selectListByStudentId(studentId); - } - - private void createDemo03CourseList(Long studentId, List list) { - if (list != null) { - list.forEach(o -> o.setStudentId(studentId)); - } - demo03CourseMapper.insertBatch(list); - } - - private void updateDemo03CourseList(Long studentId, List list) { - deleteDemo03CourseByStudentId(studentId); - list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新 - createDemo03CourseList(studentId, list); - } - - private void deleteDemo03CourseByStudentId(Long studentId) { - demo03CourseMapper.deleteByStudentId(studentId); - } - - @Override - public PageResult getDemo03CoursePage(PageParam pageReqVO, Long studentId) { - return demo03CourseMapper.selectPage(pageReqVO, studentId); - } - - @Override - public Long createDemo03Course(Demo03CourseDO demo03Course) { - demo03CourseMapper.insert(demo03Course); - return demo03Course.getId(); - } - - @Override - public void updateDemo03Course(Demo03CourseDO demo03Course) { - demo03CourseMapper.updateById(demo03Course); - } - - @Override - public void deleteDemo03Course(Long id) { - demo03CourseMapper.deleteById(id); - } - - @Override - public Demo03CourseDO getDemo03Course(Long id) { - return demo03CourseMapper.selectById(id); - } - - // ==================== 子表(学生班级) ==================== - - @Override - public Demo03GradeDO getDemo03GradeByStudentId(Long studentId) { - return demo03GradeMapper.selectByStudentId(studentId); - } - - private void createDemo03Grade(Long studentId, Demo03GradeDO demo03Grade) { - if (demo03Grade == null) { - return; - } - demo03Grade.setStudentId(studentId); - demo03GradeMapper.insert(demo03Grade); - } - - private void updateDemo03Grade(Long studentId, Demo03GradeDO demo03Grade) { - if (demo03Grade == null) { - return; - } - demo03Grade.setStudentId(studentId); - demo03Grade.setUpdater(null).setUpdateTime(null); // 解决更新情况下:updateTime 不更新 - demo03GradeMapper.insertOrUpdate(demo03Grade); - } - - private void deleteDemo03GradeByStudentId(Long studentId) { - demo03GradeMapper.deleteByStudentId(studentId); - } - - @Override - public PageResult getDemo03GradePage(PageParam pageReqVO, Long studentId) { - return demo03GradeMapper.selectPage(pageReqVO, studentId); - } - - @Override - public Long createDemo03Grade(Demo03GradeDO demo03Grade) { - // 校验是否已经存在 - if (demo03GradeMapper.selectByStudentId(demo03Grade.getStudentId()) != null) { - throw exception(DEMO03_GRADE_EXISTS); - } - demo03GradeMapper.insert(demo03Grade); - return demo03Grade.getId(); - } - - @Override - public void updateDemo03Grade(Demo03GradeDO demo03Grade) { - // 校验存在 - validateDemo03GradeExists(demo03Grade.getId()); - // 更新 - demo03GradeMapper.updateById(demo03Grade); - } - - @Override - public void deleteDemo03Grade(Long id) { - // 校验存在 - validateDemo03GradeExists(id); - // 删除 - demo03GradeMapper.deleteById(id); - } - - @Override - public Demo03GradeDO getDemo03Grade(Long id) { - return demo03GradeMapper.selectById(id); - } - - private void validateDemo03GradeExists(Long id) { - if (demo03GradeMapper.selectById(id) == null) { - throw exception(DEMO03_GRADE_NOT_EXISTS); - } - } - -} From 8bcbb3eb9fed3f8f92cd45fa782a4e8ef7fb2e4a Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Thu, 26 Sep 2024 18:28:25 +0800 Subject: [PATCH 03/13] =?UTF-8?q?1=E3=80=81gateway=E7=BD=91=E5=85=B3?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AF=B7=E6=B1=82=E5=A4=A7=E5=B0=8F=E9=99=90?= =?UTF-8?q?=E5=88=B6=E9=85=8D=E7=BD=AE=EF=BC=8810M=EF=BC=89=E3=80=81?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0accesslog=E8=BF=87=E6=BB=A4=E5=99=A8=E5=AF=B9?= =?UTF-8?q?=E9=83=A8=E5=88=86=E8=BF=87=E5=A4=A7=E8=AF=B7=E6=B1=82=E7=9A=84?= =?UTF-8?q?=E6=89=93=E5=8D=B0=E5=86=85=E5=AE=B9=E5=87=8F=E5=B0=91=EF=BC=9B?= =?UTF-8?q?2=E3=80=81=E6=95=B0=E6=8D=AE=E9=9B=86=E5=A2=9E=E6=94=B9organid?= =?UTF-8?q?=E5=92=8C=E6=95=B0=E6=8D=AE=E6=BA=90=E7=BB=9F=E4=B8=80=E3=80=81?= =?UTF-8?q?ureport=E5=AF=B9=E8=B1=A1floatimages=E8=A1=A5=E5=85=85=EF=BC=9B?= =?UTF-8?q?3=E3=80=81=E6=8A=A5=E8=A1=A8=E9=A2=84=E8=A7=88=E5=86=85?= =?UTF-8?q?=E7=BD=AE=E6=95=B0=E6=8D=AE=E6=BA=90=E5=A4=84=E7=90=86=E9=A2=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E3=80=81=E9=85=8D=E7=BD=AE=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gateway/config/CfGatewayProperties.java | 25 +++++++++++ .../filter/logging/AccessLogFilter.java | 34 ++++++++++++--- .../src/main/resources/application.yaml | 9 ++++ .../report/config/CfReportProperties.java | 23 +++++++++++ .../service/dataset/ReportDatasetService.java | 15 +------ .../dataset/ReportDatasetServiceImpl.java | 39 ++++++++---------- .../template/ReportTemplateServiceImpl.java | 10 +++++ .../src/main/resources/application.yaml | 18 +++++++- .../lib/ureport-core-2.3.0-SNAPSHOT.jar | Bin 919377 -> 926280 bytes 9 files changed, 131 insertions(+), 42 deletions(-) create mode 100644 cf-gateway/src/main/java/com/cf/imes/gateway/config/CfGatewayProperties.java create mode 100644 cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/config/CfReportProperties.java diff --git a/cf-gateway/src/main/java/com/cf/imes/gateway/config/CfGatewayProperties.java b/cf-gateway/src/main/java/com/cf/imes/gateway/config/CfGatewayProperties.java new file mode 100644 index 000000000..af40d29bc --- /dev/null +++ b/cf-gateway/src/main/java/com/cf/imes/gateway/config/CfGatewayProperties.java @@ -0,0 +1,25 @@ +package com.cf.imes.gateway.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.Collections; +import java.util.Set; + +/** + * 网关配置 + * + * @author 晨丰科技 + */ +@Configuration +@ConfigurationProperties(prefix = "chenfeng.gateway") +@Data +public class CfGatewayProperties { + + + /** + * 需要忽略打印requestBody和responseBody的请求地址列表 + */ + private Set accessLogIgnoreUrls = Collections.emptySet(); +} diff --git a/cf-gateway/src/main/java/com/cf/imes/gateway/filter/logging/AccessLogFilter.java b/cf-gateway/src/main/java/com/cf/imes/gateway/filter/logging/AccessLogFilter.java index 0fcf41319..ddc5a254e 100644 --- a/cf-gateway/src/main/java/com/cf/imes/gateway/filter/logging/AccessLogFilter.java +++ b/cf-gateway/src/main/java/com/cf/imes/gateway/filter/logging/AccessLogFilter.java @@ -1,9 +1,11 @@ package com.cf.imes.gateway.filter.logging; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.json.JSONUtil; import com.cf.imes.framework.common.util.json.JsonUtils; +import com.cf.imes.gateway.config.CfGatewayProperties; import com.cf.imes.gateway.util.SecurityFrameworkUtils; import com.cf.imes.gateway.util.WebFrameworkUtils; import com.alibaba.nacos.common.utils.StringUtils; @@ -60,6 +62,22 @@ public class AccessLogFilter implements GlobalFilter, Ordered { @Resource private CodecConfigurer codecConfigurer; + @Resource + private CfGatewayProperties cfGatewayProperties; + + /** + * 是否需要打印请求体和响应体 + * + * @param requestUrl 请求路径 + * @return + */ + protected boolean shouldLogParamAndBody(String requestUrl) { + if (CollUtil.isEmpty(cfGatewayProperties.getAccessLogIgnoreUrls())) { + return true; + } + return !cfGatewayProperties.getAccessLogIgnoreUrls().stream().anyMatch(excludeUrl -> requestUrl.contains(excludeUrl)); + } + /** * 打印日志 * @@ -78,14 +96,20 @@ public class AccessLogFilter implements GlobalFilter, Ordered { values.put("userType", gatewayLog.getUserType()); values.put("routeId", gatewayLog.getRoute() != null ? gatewayLog.getRoute().getId() : null); values.put("schema", gatewayLog.getSchema()); - values.put("requestUrl", gatewayLog.getRequestUrl()); + String requestUrl = gatewayLog.getRequestUrl(); + values.put("requestUrl", requestUrl); values.put("queryParams", gatewayLog.getQueryParams().toSingleValueMap()); - values.put("requestBody", JsonUtils.isJson(gatewayLog.getRequestBody()) ? // 保证 body 的展示好看 - JSONUtil.parse(gatewayLog.getRequestBody()) : gatewayLog.getRequestBody()); + values.put("requestHeaders", JsonUtils.toJsonString(gatewayLog.getRequestHeaders().toSingleValueMap())); values.put("userIp", gatewayLog.getUserIp()); - values.put("responseBody", JsonUtils.isJson(gatewayLog.getResponseBody()) ? // 保证 body 的展示好看 - JSONUtil.parse(gatewayLog.getResponseBody()) : gatewayLog.getResponseBody()); + // 过滤特定大请求不打印日志 + if (shouldLogParamAndBody(requestUrl)) { + values.put("requestBody", JsonUtils.isJson(gatewayLog.getRequestBody()) ? // 保证 body 的展示好看 + JSONUtil.parse(gatewayLog.getRequestBody()) : gatewayLog.getRequestBody()); + + values.put("responseBody", JsonUtils.isJson(gatewayLog.getResponseBody()) ? // 保证 body 的展示好看 + JSONUtil.parse(gatewayLog.getResponseBody()) : gatewayLog.getResponseBody()); + } values.put("responseHeaders", gatewayLog.getResponseHeaders() != null ? JsonUtils.toJsonString(gatewayLog.getResponseHeaders().toSingleValueMap()) : null); values.put("httpStatus", gatewayLog.getHttpStatus()); diff --git a/cf-gateway/src/main/resources/application.yaml b/cf-gateway/src/main/resources/application.yaml index 874f0678c..97e9eab42 100644 --- a/cf-gateway/src/main/resources/application.yaml +++ b/cf-gateway/src/main/resources/application.yaml @@ -1,6 +1,9 @@ spring: main: allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。 + codec: + # getway请求大小限制10M:1024 * 1024 * 10 + max-in-memory-size: 10485760 cloud: # Spring Cloud Gateway 配置项,对应 GatewayProperties 类 @@ -99,3 +102,9 @@ knife4j: - name: report-server service-name: report-server url: /admin-api/report/v3/api-docs + +chenfeng: + gateway: + access-log-ignore-urls: + - /report/template/ + - /system/captcha/get \ No newline at end of file diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/config/CfReportProperties.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/config/CfReportProperties.java new file mode 100644 index 000000000..da9ab15b8 --- /dev/null +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/config/CfReportProperties.java @@ -0,0 +1,23 @@ +package com.cf.imes.module.report.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import java.util.Set; + +/** + * 报表配置 + * + * @author Gqr + * @since 2024/9/26 16:41 + */ +@Configuration +@ConfigurationProperties("chenfeng.report") +@Data +public class CfReportProperties { + /** + * 多租户表名称列表 + */ + private Set tenantTableNames; +} diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/dataset/ReportDatasetService.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/dataset/ReportDatasetService.java index 154dd68eb..d8eb00519 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/dataset/ReportDatasetService.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/dataset/ReportDatasetService.java @@ -22,12 +22,6 @@ public interface ReportDatasetService { */ Long createDataset(@Valid ReportDatasetSaveReqVO createReqVO); - /** - * 批量创建报表数据集 - * @param createReqVOList - */ - void batchCreateDataset(@Valid List createReqVOList); - /** * 更新报表数据集 * @@ -35,13 +29,6 @@ public interface ReportDatasetService { */ void updateDataset(@Valid ReportDatasetSaveReqVO updateReqVO); - - /** - * 批量更新报表数据集 - * @param createReqVOList - */ - void batchUpdateDataset(@Valid List createReqVOList); - /** * 删除报表数据集 * @@ -60,7 +47,7 @@ public interface ReportDatasetService { /** * 获得报表数据集分页 * - * @param pageReqVO 分页查询 + * @param reqVO 分页查询 * @return 报表数据集分页 */ List getDatasetList(ReportDatasetReqVO reqVO); diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/dataset/ReportDatasetServiceImpl.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/dataset/ReportDatasetServiceImpl.java index a7c386a8c..c3a9573c9 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/dataset/ReportDatasetServiceImpl.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/dataset/ReportDatasetServiceImpl.java @@ -1,6 +1,5 @@ package com.cf.imes.module.report.service.dataset; -import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; @@ -41,41 +40,29 @@ public class ReportDatasetServiceImpl implements ReportDatasetService { @Override public Long createDataset(ReportDatasetSaveReqVO createReqVO) { // 校验内置模板操作权限 - validateSystemDataset(createReqVO.getDatasourceId()); + ReportDatasourceDO reportDatasourceDO = validateSystemDataset(createReqVO.getDatasourceId()); // 插入 ReportDatasetDO dataset = BeanUtils.toBean(createReqVO, ReportDatasetDO.class); + // 数据集机构id和数据源统一 + dataset.setOrganId(reportDatasourceDO.getOrganId()); datasetMapper.insert(dataset); // 返回 return dataset.getId(); } - @Override - public void batchCreateDataset(List createReqVOList) { - List reportDatasetDOS = BeanUtils.toBean(createReqVOList, ReportDatasetDO.class); - if (CollUtil.isNotEmpty(reportDatasetDOS)) { - datasetMapper.insertBatch(reportDatasetDOS); - } - } - @Override public void updateDataset(ReportDatasetSaveReqVO updateReqVO) { // 校验内置模板操作权限 - validateSystemDataset(updateReqVO.getDatasourceId()); + ReportDatasourceDO reportDatasourceDO = validateSystemDataset(updateReqVO.getDatasourceId()); // 校验存在 validateDatasetExists(updateReqVO.getId()); // 更新 ReportDatasetDO updateObj = BeanUtils.toBean(updateReqVO, ReportDatasetDO.class); + // 数据集机构id和数据源统一 + updateObj.setOrganId(reportDatasourceDO.getOrganId()); datasetMapper.updateById(updateObj); } - @Override - public void batchUpdateDataset(List createReqVOList) { - List reportDatasetDOS = BeanUtils.toBean(createReqVOList, ReportDatasetDO.class); - if (CollUtil.isNotEmpty(reportDatasetDOS)) { - datasetMapper.updateBatch(reportDatasetDOS); - } - } - @Override public void deleteDataset(Long id) { // 校验存在 @@ -100,15 +87,23 @@ public class ReportDatasetServiceImpl implements ReportDatasetService { * * @param datasourceId 数据源id */ - private void validateSystemDataset(Long datasourceId) { - ReportDatasourceDO reportDatasourceDO = reportDatasourceMapper.selectNormalDatasourceById(datasourceId, SecurityFrameworkUtils.getUserOrganId()); + private ReportDatasourceDO validateSystemDataset(Long datasourceId) { + ReportDatasourceDO reportDatasourceDO = null; + boolean superAdmin = SecurityFrameworkUtils.isSuperAdmin(); + // 超管查所有,其他人查机构下 + if (superAdmin) { + reportDatasourceDO = reportDatasourceMapper.selectById(datasourceId); + } else { + reportDatasourceDO = reportDatasourceMapper.selectNormalDatasourceById(datasourceId, SecurityFrameworkUtils.getUserOrganId()); + } if (ObjectUtil.isNull(reportDatasourceDO)) { throw exception(DATASOURCE_NOT_EXISTS); } // 非超管不能操作内置模板 - if (ReportTemplateTypeEnum.SYSTEM.equals(reportDatasourceDO.getBuildinType()) && Boolean.FALSE.equals(SecurityFrameworkUtils.isSuperAdmin())) { + if (ReportTemplateTypeEnum.SYSTEM.equals(reportDatasourceDO.getBuildinType()) && Boolean.FALSE.equals(superAdmin)) { throw exception(DATASOURCE_BUILDIN_OPERATION_PERMISSION_ERROR); } + return reportDatasourceDO; } @Override diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java index 3b60bedf5..c754bd873 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java @@ -35,6 +35,7 @@ import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; import com.cf.imes.framework.security.core.LoginUser; import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; import com.cf.imes.module.report.api.template.dto.ReportTemplateGenerateReqDTO; +import com.cf.imes.module.report.config.CfReportProperties; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateReqVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateRespVO; import com.cf.imes.module.report.controller.admin.template.vo.ReportTemplateSaveReqVO; @@ -89,6 +90,9 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { private static final String UTF8_CHARSET = CharsetUtil.UTF_8; + @Resource + private CfReportProperties cfReportProperties; + @Override @Transactional(rollbackFor = Exception.class) public ReportTemplateRespVO createReportTemplate(ReportTemplateSaveReqVO createReqVO) { @@ -353,6 +357,12 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { ReportRender reportRender = new ReportRender(); ReportDefinition reportDefinition = getReportDefinition(reportRender, params); Map parameters = params.getQuery(); + // imes多租户业务表表名列表 + Set tenantTableNames = cfReportProperties.getTenantTableNames(); + if (CollUtil.isNotEmpty(tenantTableNames)) { + parameters.put("tenantTableNames", cfReportProperties.getTenantTableNames()); + parameters.put("organId", SecurityFrameworkUtils.getUserOrganId()); + } Report report = reportRender.render(reportDefinition, parameters); return htmlProducer.produce(reportDefinition, report); } diff --git a/cf-module-report/cf-module-report-biz/src/main/resources/application.yaml b/cf-module-report/cf-module-report-biz/src/main/resources/application.yaml index 6b8f9c838..14843fb48 100644 --- a/cf-module-report/cf-module-report-biz/src/main/resources/application.yaml +++ b/cf-module-report/cf-module-report-biz/src/main/resources/application.yaml @@ -105,4 +105,20 @@ chenfeng: ignore-tables: encrypt: enable: false - publicKey: cfimes \ No newline at end of file + publicKey: cfimes + tenant-table-names: + - system_dept + - system_user + - system_organization + - order_body + - order_goods + - order_group + - order_item + - order_parts + - order_plan + - order_plan_item + - order_plate + - order_prepackaged + - order_remain_plate + - orders + - plate \ No newline at end of file diff --git a/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar b/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar index 2a6a166865fafd871a8e1929534dbefa8b754a45..a6900ecfd7cb884b9602167365e26fcc1bc1cb69 100644 GIT binary patch delta 43964 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 J^aMZC`X9+spNRkf delta 37651 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 From 360efa0421877c4d15fa2330ed87b5a10289cd36 Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Fri, 27 Sep 2024 15:29:59 +0800 Subject: [PATCH 04/13] =?UTF-8?q?=E6=8A=A5=E8=A1=A8=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=EF=BC=9A=E5=86=85=E7=BD=AE=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=BA=90=E4=B8=8B=E7=9A=84sql=E6=95=B0=E6=8D=AE=E9=9B=86?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=A4=9A=E7=A7=9F=E6=88=B7=E5=AD=97=E6=AE=B5?= =?UTF-8?q?organ=5Fid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yaml | 2 +- .../report/config/CfReportProperties.java | 2 +- .../ReportDatasourceServiceImpl.java | 5 +-- .../template/ReportTemplateServiceImpl.java | 31 +++++++++++++++--- .../src/main/resources/application.yaml | 3 +- .../lib/ureport-core-2.3.0-SNAPSHOT.jar | Bin 926280 -> 928541 bytes 6 files changed, 34 insertions(+), 9 deletions(-) diff --git a/cf-gateway/src/main/resources/application.yaml b/cf-gateway/src/main/resources/application.yaml index 97e9eab42..3b1c0aae3 100644 --- a/cf-gateway/src/main/resources/application.yaml +++ b/cf-gateway/src/main/resources/application.yaml @@ -106,5 +106,5 @@ knife4j: chenfeng: gateway: access-log-ignore-urls: - - /report/template/ + - /report/template - /system/captcha/get \ No newline at end of file diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/config/CfReportProperties.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/config/CfReportProperties.java index da9ab15b8..15b6a5b06 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/config/CfReportProperties.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/config/CfReportProperties.java @@ -13,7 +13,7 @@ import java.util.Set; * @since 2024/9/26 16:41 */ @Configuration -@ConfigurationProperties("chenfeng.report") +@ConfigurationProperties(prefix = "chenfeng.report") @Data public class CfReportProperties { /** diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java index bf065e7d7..fabd876f3 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/datasource/ReportDatasourceServiceImpl.java @@ -13,6 +13,7 @@ import com.bstek.datasource.bean.PreviewParams; import com.bstek.ureport.definition.dataset.Field; import com.bstek.ureport.definition.dataset.Parameter; import com.bstek.ureport.definition.dataset.SqlDatasetDefinition; +import com.bstek.ureport.definition.dataset.TenantParams; import com.bstek.ureport.utils.ProcedureUtils; import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; @@ -230,9 +231,9 @@ public class ReportDatasourceServiceImpl implements ReportDatasourceService { sqlDatasetDefinition.setSql(sql); sqlDatasetDefinition.setParameters(BeanUtils.toBean(parameters, Parameter.class)); - Map params = new HashMap(); + Map params = new HashMap<>(); Map pmap = sqlDatasetDefinition.buildParameters(params); - String sqlForUse = sqlDatasetDefinition.parseSql(pmap); + String sqlForUse = sqlDatasetDefinition.parseSql(pmap, new TenantParams()); if (ProcedureUtils.isProcedure(sqlForUse)) { return ProcedureUtils.procedureColumnsQuery(sqlForUse, pmap, conn); } diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java index c754bd873..d9fc5ccf9 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/service/template/ReportTemplateServiceImpl.java @@ -64,6 +64,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.cf.imes.module.report.enums.ErrorCodeConstants.TEMPLATE_BUILDIN_OPERATION_PERMISSION_ERROR; @@ -353,15 +354,37 @@ public class ReportTemplateServiceImpl implements ReportTemplateService { @Override public HtmlReport preview(PreviewParameters params) { + Long userOrganId = SecurityFrameworkUtils.getUserOrganId(); + HtmlProducer htmlProducer = new HtmlProducer(); ReportRender reportRender = new ReportRender(); ReportDefinition reportDefinition = getReportDefinition(reportRender, params); Map parameters = params.getQuery(); - // imes多租户业务表表名列表 - Set tenantTableNames = cfReportProperties.getTenantTableNames(); - if (CollUtil.isNotEmpty(tenantTableNames)) { + if (Boolean.FALSE.equals(SecurityFrameworkUtils.isSuperAdmin())) { + // 根据前端传递的数据集id,判断是不是内置数据源下的,是就把name传给ureport + List datasetIds = (List) parameters.get("datasetIds"); + if (CollUtil.isNotEmpty(datasetIds)) { + // 内置数据集名称列表 + List buildinDsNames = new ArrayList<>(); + // 遍历获取所有上级数据源 + List reportDatasetDOS = datasetMapper.selectNormalDatasetList(datasetIds.stream().collect(Collectors.toSet())); + for (ReportDatasetDO datasetDO : reportDatasetDOS) { + Long datasourceId = datasetDO.getDatasourceId(); + // 查询数据源,如果是内置数据源则把数据集的name传给ureport + // 机构下 + 内置数据源查询 + ReportDatasourceDO datasourceDO = datasourceMapper.selectNormalDatasourceById(datasourceId, userOrganId); + if (ObjectUtil.equal(datasourceDO.getBuildinType(), ReportTemplateTypeEnum.SYSTEM)) { + buildinDsNames.add(datasetDO.getName()); + } + } + if (CollUtil.isNotEmpty(buildinDsNames)) { + parameters.put("buildinDsNames", buildinDsNames); + } + } + // imes多租户业务表表名列表 parameters.put("tenantTableNames", cfReportProperties.getTenantTableNames()); - parameters.put("organId", SecurityFrameworkUtils.getUserOrganId()); + // 用户组织id + parameters.put("organId", userOrganId); } Report report = reportRender.render(reportDefinition, parameters); return htmlProducer.produce(reportDefinition, report); diff --git a/cf-module-report/cf-module-report-biz/src/main/resources/application.yaml b/cf-module-report/cf-module-report-biz/src/main/resources/application.yaml index 14843fb48..25bdc81f9 100644 --- a/cf-module-report/cf-module-report-biz/src/main/resources/application.yaml +++ b/cf-module-report/cf-module-report-biz/src/main/resources/application.yaml @@ -106,7 +106,8 @@ chenfeng: encrypt: enable: false publicKey: cfimes - tenant-table-names: + report: + tenant-table-names: - system_dept - system_user - system_organization diff --git a/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar b/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar index a6900ecfd7cb884b9602167365e26fcc1bc1cb69..ba225c0e2b561cc85ff268d94884473118be548f 100644 GIT binary patch delta 49409 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%0DaJ`xj0e5CJRqe*I*7p6jf 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 Date: Fri, 27 Sep 2024 15:42:51 +0800 Subject: [PATCH 05/13] =?UTF-8?q?=E8=8E=B7=E5=BE=97=E6=9C=BA=E5=8F=B0?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=93=81=E7=89=8C=E4=BF=A1=E6=81=AF=EF=BC=8C?= =?UTF-8?q?=E6=8E=92=E5=8D=95=EF=BC=8C=E6=89=93=E5=8C=85=E8=A1=A5=E5=85=A8?= =?UTF-8?q?=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/enums/OrderItemTypeEnum.java | 27 ++ .../enums/GlobalErrorCodeConstants.java | 7 +- .../core/handler/GlobalExceptionHandler.java | 10 +- .../executor/dal/dataobject/plan/PlanDO.java | 10 +- .../dal/dataobject/rawgoods/RawGoodsDO.java | 6 +- .../executor/dal/mysql/goods/GoodsMapper.java | 24 +- .../dal/mysql/orderItem/OrderItemMapper.java | 17 +- .../executor/dal/mysql/plan/PlanMapper.java | 5 +- .../executor/dal/mysql/plate/PlateMapper.java | 37 -- .../optimizeplan/OptimizePlanServiceImpl.java | 125 +++---- .../service/order/OrderServiceImpl.java | 6 +- .../executor/service/plan/PlanService.java | 1 - .../service/plan/PlanServiceImpl.java | 42 +-- .../resources/mapper/goods/GoodsMapper.xml | 72 +--- .../resources/mapper/order/OrderMapper.xml | 4 +- .../mapper/orderItem/OrderItemMapper.xml | 12 - .../main/resources/mapper/plan/PlanMapper.xml | 114 +----- .../resources/mapper/plate/PlateMapper.xml | 353 +----------------- .../dal/dataobject/process/OrderDO.java | 4 + .../dal/dataobject/query/OrderItemDO.java | 5 +- .../remainplaten/RemainPlateDO.java | 3 +- .../dal/mysql/pack/OrderPackageMapper.java | 11 - .../mysql/pack/OrderPrepackagedMapper.java | 9 - .../dal/mysql/process/OrdersMapper.java | 5 +- .../manage/service/pack/PackServiceImpl.java | 2 + .../dal/mysql/pack/OrderPackageMapper.xml | 63 ---- .../manage/dal/mysql/process/OrdersMapper.xml | 43 +-- .../datasource/vo/DataSourceFiledReqVO.java | 3 +- .../admin/machine/vo/CuttingRespVO.java | 36 +- .../service/machine/MachineServiceImpl.java | 13 +- .../src/main/resources/application.yaml | 1 + 31 files changed, 198 insertions(+), 872 deletions(-) create mode 100644 cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/enums/OrderItemTypeEnum.java diff --git a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/enums/OrderItemTypeEnum.java b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/enums/OrderItemTypeEnum.java new file mode 100644 index 000000000..b686913b1 --- /dev/null +++ b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/enums/OrderItemTypeEnum.java @@ -0,0 +1,27 @@ +package com.cf.imes.framework.common.enums; + + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum OrderItemTypeEnum { + + PLATE(1, "板材"), + PARTS(2, "五金/配件"), + OTHER(3, "其他"), + QUOTATIONACCESSORIES(4, "报价配件"); + + private final Integer type; + private String description; + + public boolean equals(Integer status) { + return this.type .equals(status) ; + } + + public boolean equals(OrderItemTypeEnum enableStatusEnum) { + return enableStatusEnum != null && enableStatusEnum.type .equals(this.getType()) ; + } + +} diff --git a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/exception/enums/GlobalErrorCodeConstants.java b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/exception/enums/GlobalErrorCodeConstants.java index 7d3b717ca..4edb02b89 100644 --- a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/exception/enums/GlobalErrorCodeConstants.java +++ b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/exception/enums/GlobalErrorCodeConstants.java @@ -33,8 +33,11 @@ public interface GlobalErrorCodeConstants { ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "系统异常,请联系客服处理"); ErrorCode NOT_IMPLEMENTED = new ErrorCode(501, "功能未实现/未开启"); ErrorCode ERROR_CONFIGURATION = new ErrorCode(502, "错误的配置项"); - ErrorCode ES_ERROR_UPDATE = new ErrorCode(503, "ES文档更新失败"); - ErrorCode ES_ERROR_DELETE = new ErrorCode(504, "ES文档删除失败"); + + // ES文档更新失败 + ErrorCode ES_ERROR_UPDATE = new ErrorCode(503, "数据异常,请勿点击过快,请稍等再试"); + // ES文档删除失败 + ErrorCode ES_ERROR_DELETE = new ErrorCode(504, "数据异常,请勿点击过快,请稍等再试"); ErrorCode DATA_EXCEPTION_ERROR = new ErrorCode(505, "数据异常,请联系客服处理"); // ========== 自定义错误段 ========== diff --git a/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/web/core/handler/GlobalExceptionHandler.java b/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/web/core/handler/GlobalExceptionHandler.java index 70601c32c..d21c0b7fa 100644 --- a/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/web/core/handler/GlobalExceptionHandler.java +++ b/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/web/core/handler/GlobalExceptionHandler.java @@ -236,9 +236,13 @@ public class GlobalExceptionHandler { return tableNotExistsResult; } -// if(ex instanceof NullPointerException){ -// return CommonResult.error(DATA_EXCEPTION_ERROR.getCode(), DATA_EXCEPTION_ERROR.getMsg()); -// } + if(ex instanceof NullPointerException){ + // 处理异常 + log.error("[defaultExceptionHandler]", ex); + // 插入异常日志 + this.createExceptionLog(req, ex); + return CommonResult.error(DATA_EXCEPTION_ERROR.getCode(), DATA_EXCEPTION_ERROR.getMsg()); + } // 情况二:部分特殊的库的处理 if (Objects.equals("io.github.resilience4j.ratelimiter.RequestNotPermitted", ex.getClass().getName())) { 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 3d68915a7..b2616549d 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 @@ -1,14 +1,10 @@ package com.cf.imes.module.executor.dal.dataobject.plan; -import com.cf.imes.framework.organ.core.db.OrganBaseDO; -import lombok.*; -import java.util.*; -import java.time.LocalDateTime; -import java.time.LocalDateTime; -import java.time.LocalDateTime; -import java.time.LocalDateTime; import com.baomidou.mybatisplus.annotation.*; import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; +import lombok.*; + +import java.time.LocalDateTime; /** * 生产单开料排单 DO diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/rawgoods/RawGoodsDO.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/rawgoods/RawGoodsDO.java index c59a9fcfb..ae9dc3b99 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/rawgoods/RawGoodsDO.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/dataobject/rawgoods/RawGoodsDO.java @@ -1,12 +1,8 @@ package com.cf.imes.module.executor.dal.dataobject.rawgoods; -import com.cf.imes.framework.organ.core.db.OrganBaseDO; -import lombok.*; -import java.util.*; -import java.time.LocalDateTime; -import java.time.LocalDateTime; import com.baomidou.mybatisplus.annotation.*; import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; +import lombok.*; /** * 生产单设计商品表 order_raw_goods_{N} DO diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/goods/GoodsMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/goods/GoodsMapper.java index 1f0cc2d2e..16968bbb7 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/goods/GoodsMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/goods/GoodsMapper.java @@ -75,7 +75,7 @@ public interface GoodsMapper extends BaseMapperX { } // 删板材,批量 - void updateDeletedById(@Param("ids") List ids, @Param("deleted") Integer deleted, @Param("organId") Long organId); + void updateDeletedById(@Param("orderId") Long orderId,@Param("ids") List ids, @Param("deleted") Integer deleted, @Param("organId") Long organId); void deletedById(@Param("ids") List ids, @Param("organId") Long organId); @@ -108,15 +108,6 @@ public interface GoodsMapper extends BaseMapperX { - default List selectListByGoodsIdList(List goodsIds,List orderIds, Long organId) { - return selectList(new LambdaQueryWrapperX() - .eq(GoodsDO::getOrganId, organId) - .eq(GoodsDO::getDeleted, false) - .in(GoodsDO::getGoodsId, goodsIds) - .in(GoodsDO::getOrderId, orderIds)); - - } - List selectPlanGoodsDataSource(@Param("filed") String filed,@Param("planId") Long planId ,@Param("organId") Long organId); @@ -133,9 +124,6 @@ public interface GoodsMapper extends BaseMapperX { - IPage selectOrderGoodsList(@Param("page") IPage page, @Param(Constants.WRAPPER) Wrapper wrapper); - - List selectOrderGoodsPlateList(@Param("planIds") List planIds, @Param("organId") Long organId); @@ -160,7 +148,6 @@ public interface GoodsMapper extends BaseMapperX { } - List selectGoodsListByGoodsId(@Param(Constants.WRAPPER) Wrapper wrapper); IPage selectPlanGoodsListByPlanId(@Param("page") IPage page, @Param(Constants.WRAPPER) Wrapper wrapper); @@ -168,23 +155,23 @@ public interface GoodsMapper extends BaseMapperX { List selectGoodsAndRemainPlate(@Param("ids") List ids,@Param("organId") Long organId); - IPage selectNoPlanOrderList(@Param("page") IPage page, @Param(Constants.WRAPPER) Wrapper wrapper); - - default int deletePlanGoods(List ids, Long organId) { + default int deletePlanGoods(List orderIds,List ids, Long organId) { return update(new LambdaUpdateWrapper() .set(GoodsDO::getPlanId, 0) .eq(GoodsDO::getOrganId, organId) + .in(GoodsDO::getOrderId, orderIds) .in(GoodsDO::getPlanId, ids)); } - default List selectPlanGoodsListByPlanIdList(List planIds, Long organId) { + default List selectPlanGoodsListByPlanIdList(List orderIds,List planIds, Long organId) { return selectList(new LambdaQueryWrapperX() .eq(GoodsDO::getOrganId, organId) .eq(GoodsDO::getDeleted, false) + .inIfPresent(GoodsDO::getOrderId,orderIds) .in(GoodsDO::getPlanId,planIds) .select(GoodsDO::getGoodsId,GoodsDO::getId,GoodsDO::getOrderId)); @@ -196,7 +183,6 @@ public interface GoodsMapper extends BaseMapperX { List selectNoPlanRoomBody(@Param("orderIds") List orderIds, @Param("organId") Long organId); - IPage selectOrderPlate(@Param("page") IPage page,@Param("organId") Long organId); List selectPlanOrderList(@Param("orderId") Long orderId,@Param("roomIds") Set roomIds, @Param("bodyId") Long bodyId,@Param("organId") Long organId); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderItem/OrderItemMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderItem/OrderItemMapper.java index 5228abcd9..b81f00137 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderItem/OrderItemMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/orderItem/OrderItemMapper.java @@ -5,7 +5,6 @@ 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.OrderPlatesDetailRespVO; import com.cf.imes.module.executor.controller.admin.orderParts.vo.OrderPartsRespVO; -import com.cf.imes.module.executor.controller.admin.plan.vo.OrderRespVOCopy; import com.cf.imes.module.executor.controller.admin.plate.vo.PlateDetailReqVO; import com.cf.imes.module.executor.controller.admin.plate.vo.PlateDetailRespVO; import com.cf.imes.module.executor.controller.admin.plate.vo.PlateRespVO; @@ -79,17 +78,6 @@ public interface OrderItemMapper extends BaseMapperX { - default List selectPlateIdList(List plateIds, Long organId) { - return selectList(new LambdaQueryWrapperX() - .eq(OrderItemDO::getOrganId,organId) - .inIfPresent(OrderItemDO::getPlateId, plateIds) - .select(OrderItemDO::getBodyId,OrderItemDO::getRoomId,OrderItemDO::getGroupId)); - - } - - - - default List selectPartsList(List partIds,List orderIds, Long organId) { return selectList(new LambdaQueryWrapperX() @@ -100,12 +88,11 @@ public interface OrderItemMapper extends BaseMapperX { } - IPage selectTestNum(@Param("page") IPage page,@Param("organId") Long organId); - - default List selectPackId(List bodyIds, Long organId) { + default List selectPackId(Long orderId,List bodyIds, Long organId) { return selectList(new LambdaQueryWrapperX() .eq(OrderItemDO::getOrganId,organId) + .eq(OrderItemDO::getOrderId,orderId) .inIfPresent(OrderItemDO::getBodyId,bodyIds) .select(OrderItemDO::getPackageId)); 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 d512fb682..8f6c755fa 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 @@ -74,9 +74,6 @@ public interface PlanMapper extends BaseMapperX { List selectPlateListByPlanId(@Param("planId") Long planId, @Param("organId") Long organId); - OptimizeParamRespVO getOptimizePlanParam(Long planId); - - PlanDO selectPlanByOrderIds(@Param("ids") List ids); @@ -116,6 +113,8 @@ public interface PlanMapper extends BaseMapperX { List selectPlanStatus(@Param("planIds") List planIds,@Param("organId") Long organId); + void updatePlanStatus(@Param("planId") Long planId,@Param("status") Integer status,@Param("organId") Long organId); + // List seleTestSQL(@Param("sql") String sql); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plate/PlateMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plate/PlateMapper.java index ce04622e3..ebc53ac3e 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plate/PlateMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plate/PlateMapper.java @@ -8,8 +8,6 @@ import com.cf.imes.framework.common.enums.OrderPlateTypeEnum; import com.cf.imes.framework.common.pojo.PageResult; 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.plan.bo.GoodsNum; -import com.cf.imes.module.executor.controller.admin.plan.bo.OrderIds; import com.cf.imes.module.executor.controller.admin.plan.saveOptimize.PrintOrderPackReqVO; import com.cf.imes.module.executor.controller.admin.plan.vo.*; import com.cf.imes.module.executor.controller.admin.plate.vo.PlateGoodsIdVO; @@ -75,11 +73,7 @@ public interface PlateMapper extends BaseMapperX { } // IPage selectPlatePage(@Param("page") IPage page, @Param("orderId")Long organId, @Param("goodsId") String goodsId); - List selectPlatePage( @Param("orderId") Long orderId,@Param("organId") Long organId/*, @Param("goodsId") String goodsId*/); - IPage selectPlateByPlanId(@Param("page") IPage page, @Param(Constants.WRAPPER) Wrapper wrapper); - - List selectPlateList(Long planId); IPage selectProductList(@Param("page") IPage page , @Param("orderId")Long orderId, @Param("roomId")Long roomId , @Param("bodyId")Long bodyId,@Param("organId") Long organId); @@ -92,9 +86,6 @@ public interface PlateMapper extends BaseMapperX { List selectPlateDetialList(@Param("orderId") Long orderId,@Param("organId") Long organId); - List selectPlateDetialListByIds(@Param("orderIds") List orderIds,@Param("organId") Long organId); - - List selectPlateGoodsList(@Param("orderId") Long orderId, @Param("organId") Long organId, @Param("deleted") Integer deleted); // 明细 List selectPlateGoodsListSummary(@Param("orderId") Long orderId, @Param("organId") Long organId, @Param("deleted") Integer deleted); // 汇总 @@ -131,15 +122,9 @@ public interface PlateMapper extends BaseMapperX { List selectGoodsPage( @Param(Constants.WRAPPER) Wrapper wrapper); - IPage selectGoodsList(@Param("page") IPage page,@Param("goodsIds") List goodsIds,@Param("organId") Long organId); - - - List selectOrderIds(@Param("orderIds") List orderIds,@Param("organId") Long organId); - void deletedById(@Param("plateIds") List plateIds, @Param("organId") Long organId); - List selectGoodsNum(@Param("orderIds") List orderIds,@Param("organId") Long organId); default List selectPlateNum(Long orderId, Long organId) { return selectList(new LambdaQueryWrapperX() @@ -173,18 +158,6 @@ public interface PlateMapper extends BaseMapperX { - default List selectGoodsPlateList(List goodIds, Long organId) { - return selectList(new LambdaQueryWrapperX() - .eq(PlateDO::getOrganId,organId) - .inIfPresent(PlateDO::getGoodsId, goodIds)); - - - } - - - List selectPlateListByGoodIds(@Param("goodIds") List goodIds,@Param("organId") Long organId); - - // List selectPlateArea(@Param("orderIdsList") List orderIdsList,@Param("organId") Long organId); @@ -227,16 +200,6 @@ public interface PlateMapper extends BaseMapperX { - default List selectPlateIds(OrderPageReqVOCopy pageReqVO, Long organId) { - return selectList(new LambdaQueryWrapperX() - .eq(PlateDO::getOrganId,organId) - .eq(PlateDO::getDeleted,false) - .eqIfPresent(PlateDO::getIsSpecialShaped,pageReqVO.getSpecialShaped()) - .eqIfPresent(PlateDO::getIsDoor,pageReqVO.getIsDoor()) - .select(PlateDO::getGoodsId)); - - } - List selectNoPlanPlateList(@Param(Constants.WRAPPER) Wrapper queryWrapperX2); 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 13346b00f..fea5a5677 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 @@ -8,14 +8,12 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch._types.FieldValue; import co.elastic.clients.elasticsearch.core.*; import co.elastic.clients.elasticsearch.core.search.Hit; -import com.alibaba.fastjson.JSON; import com.cf.imes.framework.common.enums.OrderStatusEnum; import com.cf.imes.framework.common.enums.PlanStatusEnum; import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.util.Assert.AssertUtils; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.es.core.service.ESDocumentService; -import com.cf.imes.framework.security.core.LoginUser; import com.cf.imes.module.executor.controller.admin.orderParts.vo.OrderPartsRemark; import com.cf.imes.module.executor.controller.admin.plan.bo.OrderSource; import com.cf.imes.module.executor.controller.admin.plan.bo.ProcessGroupList; @@ -30,7 +28,6 @@ import com.cf.imes.module.executor.dal.dataobject.order.OrderDO; import com.cf.imes.module.executor.dal.dataobject.ordermodel.OrderModelDO; import com.cf.imes.module.executor.dal.dataobject.plan.PlanDO; import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO; -import com.cf.imes.module.executor.dal.dataobject.processStep.ProcessStepDO; import com.cf.imes.module.executor.dal.dataobject.remainplaten.RemainPlateDO; import com.cf.imes.module.executor.dal.mysql.goods.GoodsMapper; import com.cf.imes.module.executor.dal.mysql.order.OrderMapper; @@ -48,7 +45,6 @@ import com.cf.imes.module.infra.api.file.FileApi; import com.cf.imes.module.system.api.dataSource.DataSourceApi; import com.cf.imes.module.system.api.machine.MachineApi; import com.cf.imes.module.system.api.process.ProcessApi; -import com.cf.imes.module.system.api.process.dto.ProcessDTO; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -61,10 +57,10 @@ import java.io.IOException; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; import static com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants.*; import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; -import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getLoginUser; import static com.cf.imes.framework.security.core.util.SecurityFrameworkUtils.getUserOrganId; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_NOT_EXISTS; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.PLAN_NOT_EXISTS; @@ -221,16 +217,18 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { long cutedBoardNumber = cutedBoardInfo.getCutedBoardNumber() == null ? 0 : cutedBoardInfo.getCutedBoardNumber(); - cutedBoardNumber += goodsNo.size(); - - // 获取原排单的已开料的大板编号 List cutedBoardList = cutedBoardInfo.getCutedBoardList() == null ? new ArrayList<>() : cutedBoardInfo.getCutedBoardList(); + goodsNo.addAll(cutedBoardList); // 将新开料的大板编号添加到已开料的大板编号中 - cutedBoardList.addAll(goodsNo); + cutedBoardList.addAll(Stream.concat( + cutedBoardList.stream().filter(str -> !goodsNo.contains(str)), + goodsNo.stream().filter(str -> !cutedBoardList.contains(str))) + .toList()); + cutedBoardNumber = cutedBoardList.size(); // 将需要更新更新的数据更新到原数据中 cutedBoardInfo.setCutedBoardNumber(cutedBoardNumber); @@ -325,16 +323,16 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { if(cutedBoardInfo.getCutedBoardNumber() == 0){ - planDO.setStatus(PlanStatusEnum.NOCUTTING.getStatus()); - planDO.setProduceTime(null); - planMapper.updateById(planDO); +// planDO.setStatus(PlanStatusEnum.NOCUTTING.getStatus()); +// planDO.setProduceTime(null); + planMapper.updatePlanStatus(planId,PlanStatusEnum.NOCUTTING.getStatus(),getUserOrganId()); } if(planDO.getStatus().equals(PlanStatusEnum.OPENED.getStatus()) && cutedBoardInfo.getCutedBoardNumber() > 0 && cutedBoardInfo.getCutedBoardNumber() < optimizeBoardModelDO.getBoardCount() ){ - planDO.setStatus(PlanStatusEnum.OPENING.getStatus()); - planDO.setProduceTime(null); - planMapper.updateById(planDO); +// planDO.setStatus(PlanStatusEnum.OPENING.getStatus()); +// planDO.setProduceTime(null); + planMapper.updatePlanStatus(planId,PlanStatusEnum.OPENING.getStatus(),getUserOrganId()); } } @@ -350,46 +348,48 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { @Override @Transactional(rollbackFor = Exception.class) public Boolean endCutting(Long planId) { - PlanDO planDO = planMapper.selectById(planId); - if (Objects.isNull(planDO)) { - throw exception(PLAN_NOT_EXISTS); - } - planMapper.updateById(PlanDO.builder() - .id(planId) - .status(PlanStatusEnum.OPENED.getStatus()) - .produceTime(LocalDateTime.now()) - .build()); - - LoginUser loginUser = getLoginUser(); - List userProcess = processApi.getUserProcess(loginUser.getId()); - - if(!userProcess.isEmpty()) { - - List processStepIds = new ArrayList<>(); - - List orderIds = JSON.parseArray(planDO.getOrderNos()).toJavaList(Long.class); - - List processStepDOS = processStepMapper.selectOrderList(orderIds, getUserOrganId()); - - - for (ProcessDTO process : userProcess) { - processStepIds.addAll(processStepDOS.stream().filter(f -> Objects.equals(f.getProcessinfoId(), process.getId())) - .map(ProcessStepDO::getId).toList()); - } - - - if(!processStepIds.isEmpty()) { - - List processStepSalaryIds = calculateSalary(processStepIds); - - // 修改生产明细表和步骤表的工序状态 - processStepMapper.updateStatus(processStepSalaryIds, loginUser.getNickname()); - - processStepItemMapper.updateStatus(processStepIds); - - } - - } + // 目前结束开料已去掉,所以这些代码先注释,后面如果加再修改逻辑 +// +// PlanDO planDO = planMapper.selectById(planId); +// if (Objects.isNull(planDO)) { +// throw exception(PLAN_NOT_EXISTS); +// } +// planMapper.updateById(PlanDO.builder() +// .id(planId) +// .status(PlanStatusEnum.OPENED.getStatus()) +// .produceTime(LocalDateTime.now()) +// .build()); +// +// LoginUser loginUser = getLoginUser(); +// List userProcess = processApi.getUserProcess(loginUser.getId()); +// +// if(!userProcess.isEmpty()) { +// +// List processStepIds = new ArrayList<>(); +// +// List orderIds = JSON.parseArray(planDO.getOrderNos()).toJavaList(Long.class); +// +// List processStepDOS = processStepMapper.selectOrderList(orderIds, getUserOrganId()); +// +// +// for (ProcessDTO process : userProcess) { +// processStepIds.addAll(processStepDOS.stream().filter(f -> Objects.equals(f.getProcessinfoId(), process.getId())) +// .map(ProcessStepDO::getId).toList()); +// } +// +// +// if(!processStepIds.isEmpty()) { +// +// List processStepSalaryIds = calculateSalary(processStepIds); +// +// // 修改生产明细表和步骤表的工序状态 +// processStepMapper.updateStatus(processStepSalaryIds, loginUser.getNickname()); +// +// processStepItemMapper.updateStatus(processStepIds); +// +// } +// +// } return Boolean.TRUE; @@ -504,6 +504,10 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { List printOrderPartsRespVOS = orderPartsMapper.selectPartList(Collections.singletonList(orderId), getUserOrganId()); + // 查询生产单对应的配件的ES信息 + List orderPartsRemarks = buildOrderPartsByOrderId(Collections.singletonList(orderId), ORDER_PARTS_REMARK_MODEL, printOrderPartsRespVOS.size()); + + // 查询生产单对应的包裹信息 List printOrderPackReqVOS = plateMapper.selectOrderPackList(orderId,getUserOrganId()); @@ -515,14 +519,6 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { .forEach(f->f.setPackNum(printOrderPackReqVOS.stream().filter(e -> e.getOrderId().equals(orderId)).map(PrintOrderPackReqVO::getPackId).toList().size())); -// orderSource.setOrderList(Collections.singletonList(orderDO)); -// orderSource.setPlateList(plateDOS); -// orderSource.setGoodsList(goodsDOS); -// orderSource.setPlateModels(orderModelDOS); -// orderSource.setOptimizeBoardModelDOS(optimizeBoardModelDOS); -// orderSource.setOrderPartsRespVOS(printOrderPartsRespVOS); -// orderSource.setOrderPackReqVOS(printOrderPackReqVOS); - return OrderSource.builder() .orderList(Collections.singletonList(orderDO)) .goodsList(goodsDOS) @@ -530,6 +526,7 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { .plateModels(orderModelDOS) .optimizeBoardModelDOS(optimizeBoardModelDOS) .orderPartsRespVOS(printOrderPartsRespVOS) + .orderPartsRemarks(orderPartsRemarks) .orderPackReqVOS(printOrderPackReqVOS) .build(); @@ -712,7 +709,7 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { // 保存优化后的大板数据 batchSaveBoardModel(req.getOptimizeBoardModelDOS()); - List goodsDOS = goodsMapper.selectPlanGoodsListByPlanIdList(planIds, getUserOrganId()); + List goodsDOS = goodsMapper.selectPlanGoodsListByPlanIdList(null,planIds, getUserOrganId()); List ids = goodsDOS.stream().map(GoodsDO::getId).distinct().toList(); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java index 5b408d798..ac1463554 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java @@ -288,7 +288,7 @@ public class OrderServiceImpl implements OrderService { plateMapper.updateDeletedById(plateIds, status, getUserOrganId(), orderId);// 删小板 // 删除包裹,只需删除,无需还原 - List packIds = orderItemMapper.selectPackId(bodyIds, getUserOrganId()).stream().map(OrderItemDO::getPackageId).distinct().toList(); + List packIds = orderItemMapper.selectPackId(orderId,bodyIds, getUserOrganId()).stream().map(OrderItemDO::getPackageId).distinct().toList(); orderPackageMapper.updatePackList(orderId, packIds, getUserOrganId()); @@ -321,14 +321,14 @@ public class OrderServiceImpl implements OrderService { if (goodsIdDeleted.size() > 0) { - goodsMapper.updateDeletedById(goodsIdDeleted, status, getUserOrganId()); + goodsMapper.updateDeletedById(orderId,goodsIdDeleted, status, getUserOrganId()); } if (!planIds.isEmpty()) { // 判断删除的柜体对应的板材是否和排单板材一样 - List goodsDOS = goodsMapper.selectPlanGoodsListByPlanIdList(planIds, getUserOrganId()); + List goodsDOS = goodsMapper.selectPlanGoodsListByPlanIdList(null,planIds, getUserOrganId()); // 一样,同时删除排单的信息 if (goodsDOS.isEmpty()) { diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanService.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanService.java index 671ce92ec..bb8dbdbe0 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanService.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanService.java @@ -61,7 +61,6 @@ public interface PlanService { PageResult getOrderGoodsPage(OrderPageReqVOCopy pageReqVO); - List getNotPlanPlateListPage(PlateReqPageVO pageVO); Boolean addPlate(AddPlateReq req); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java index 8c965b94f..04866b571 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java @@ -151,7 +151,7 @@ public class PlanServiceImpl implements PlanService { orderIdList.addAll(orderIds); - // 创建计划 + // 创建排单 PlanDO plan = BeanUtils.toBean(createReqVO, PlanDO.class); plan.setId(identifierGenerator.nextId(plan).longValue()); plan.setSort(0L); @@ -191,7 +191,7 @@ public class PlanServiceImpl implements PlanService { public void updatePlan(PlanSaveReqVO updateReqVO) { // 校验排单是否存在,是否开料 - validatePlanExists(updateReqVO.getId()); + Long machineId = validatePlanExists(updateReqVO.getId()); // 更新 PlanDO plan = BeanUtils.toBean(updateReqVO, PlanDO.class); @@ -243,6 +243,12 @@ public class PlanServiceImpl implements PlanService { } + if(!machineId.equals(plan.getMachineId())){ + + deleteByPlanId(Collections.singletonList(plan.getId()),ORDER_REMAIN_PLATE_MODEL); + + } + planMapper.updateById(plan); @@ -322,7 +328,7 @@ public class PlanServiceImpl implements PlanService { List orderIds = new ArrayList<>(); for (PlanDO planDO : planDOS) { - orderIds.addAll(JSON.parseArray(planDO.getOrderNos()).toJavaList(Long.class)); + orderIds.addAll(JSON.parseArray(planDO.getOrderNos()).toJavaList(Long.class).stream().distinct().toList()); } @@ -337,7 +343,7 @@ public class PlanServiceImpl implements PlanService { if(!boardModelDOS.isEmpty()) { - List goodsIdList = goodsMapper.selectPlanGoodsListByPlanIdList(ids, getUserOrganId()).stream().map(GoodsDO::getId).toList(); + List goodsIdList = goodsMapper.selectPlanGoodsListByPlanIdList(orderIds,ids, getUserOrganId()).stream().map(GoodsDO::getId).toList(); if(!goodsIdList.isEmpty()) { // 修改删除的大板对应的小板为未优化 @@ -350,7 +356,11 @@ public class PlanServiceImpl implements PlanService { plateMapper.deleteBatchIds(plateIds); - orderItemMapper.delete(new LambdaQueryWrapperX().in(OrderItemDO::getPlateId, plateIds)); + orderItemMapper.delete(new LambdaQueryWrapperX() + .eq(OrderItemDO::getOrganId,getUserOrganId()) + .in(OrderItemDO::getOrderId,orderIds) + .in(OrderItemDO::getPlateId, plateIds)); + } @@ -361,7 +371,7 @@ public class PlanServiceImpl implements PlanService { } // 删除商品表里的 planId - goodsMapper.deletePlanGoods(ids,getUserOrganId()); + goodsMapper.deletePlanGoods(orderIds,ids,getUserOrganId()); List orderIdList = new ArrayList<>(); @@ -594,9 +604,7 @@ public class PlanServiceImpl implements PlanService { .eqIfPresent("op.is_door", pageReqVO.getIsDoor()) .betweenIfPresent("op.height", new BigDecimal[]{pageReqVO.getLongMinRang(), pageReqVO.getLongMaxRang()}) .betweenIfPresent("op.width", new BigDecimal[]{pageReqVO.getWidthMinRang(), pageReqVO.getWidthMaxRang()}) -// .groupBy("o.id", " o.order_date", "o.delivery_date", "o.customer", "o.address", "o.custom_order_no","o.status") -// .having("count(op.id) != 0") - .orderByDesc("o.order_date"); + .orderByDesc("o.id"); String filterTypes = ""; if (Objects.nonNull(pageReqVO.getHoleThrough()) && pageReqVO.getHoleThrough()) { @@ -872,15 +880,6 @@ public class PlanServiceImpl implements PlanService { - - - @Override - public List getNotPlanPlateListPage(PlateReqPageVO pageVO) { - - List pageRes = plateMapper.selectPlatePage(/*page, */pageVO.getOrderId(),getUserOrganId()/*, pageVO.getGoodsId()*/); - return pageRes; - } - @Override @Transactional(rollbackFor = Exception.class) public Boolean addPlate(AddPlateReq req) { @@ -1123,17 +1122,16 @@ public class PlanServiceImpl implements PlanService { - private void validatePlanExists(Long id) { + private Long validatePlanExists(Long id) { PlanDO planDO = planMapper.selectById(id); -// if ( planDO== null) { -// throw exception(PLAN_NOT_EXISTS); -// } AssertUtils.notEmpty(planDO,PLAN_NOT_EXISTS); if(planDO.getStatus().equals(PlanStatusEnum.OPENING.getStatus()) || planDO.getStatus().equals(PlanStatusEnum.OPENED.getStatus())){ throw exception(LIST_CHANGES_ARE_PROHIBITED); } + + return planDO.getMachineId(); } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/goods/GoodsMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/goods/GoodsMapper.xml index 73c00cb3a..873055b3e 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/goods/GoodsMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/goods/GoodsMapper.xml @@ -42,11 +42,12 @@ UPDATE order_goods SET deleted = #{deleted},plan_id = 0 - WHERE id IN + WHERE organ_id = #{organId} + and order_id = #{orderId} + and id IN #{id} - AND organ_id = #{organId} DELETE FROM order_goods @@ -87,29 +88,6 @@ - - - @@ -187,23 +165,6 @@ - - - - - - - - select distinct order_id, - create_time as updateTime - from order_goods - where organ_id = #{organId} - and deleted = false - and plan_id = 0 - order by create_time; - - diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml index c2e66121a..48fcb61ed 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml @@ -44,8 +44,8 @@ o.status as status from orders o - join order_goods og on o.organ_id = og.organ_id and o.id = og.order_id and og.plan_id = 0 and o.deleted = og.deleted - join order_plate op on o.organ_id = op.organ_id and o.deleted = op.deleted and o.id = op.order_id and op.is_optimized = false and og.id = op.goods_id + STRAIGHT_JOIN order_goods og on o.organ_id = og.organ_id and o.id = og.order_id and og.plan_id = 0 and o.deleted = og.deleted + STRAIGHT_JOIN order_plate op on o.organ_id = op.organ_id and o.deleted = op.deleted and o.id = op.order_id and op.is_optimized = false and og.id = op.goods_id ${ew.customSqlSegment} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderItem/OrderItemMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderItem/OrderItemMapper.xml index 5e7e0037f..880522688 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderItem/OrderItemMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/orderItem/OrderItemMapper.xml @@ -186,18 +186,6 @@ - \ No newline at end of file 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 1caa4916e..97baf4b55 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 @@ -9,103 +9,6 @@ 文档可见:https://www.cf.com/MyBatis/x-plugins/ --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + UPDATE order_plan + + SET status = #{status}, produce_time = null + + WHERE organ_id = #{organId} + and deleted = false + and id = #{planId} + + + + + + \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plate/PlateMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plate/PlateMapper.xml index b55b697af..9e83ed856 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plate/PlateMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/plate/PlateMapper.xml @@ -3,57 +3,6 @@ - - - - - - - - - - select distinct - c.goods_id as goodsId, - c.width as width, - c.height as height, - c.thickness as thickness, - c.goods_name as goodsName, - c.material as material, - c.color as color, - count(distinct a.id) - - from order_plate a - LEFT JOIN order_item oi on a.id = oi.plate_id and a.order_id = oi.order_id and a.organ_id = oi.organ_id --- LEFT JOIN `orders` b on a.order_id = b.id and a.organ_id = b.organ_id - LEFT JOIN order_goods c on a.goods_id = c.id and a.organ_id = c.organ_id - left join order_plan_item opi on oi.id = opi.item_id and oi.organ_id = opi.organ_id - where - c.organ_id = #{organId} - and a.is_cancel = 0 - and b.status = 2 - and a.deleted = false - and opi.item_id is null - and c.goods_id in - - #{goodsIds} - - - group by c.goods_id,c.id,b.id ,c.goods_name,c.width,c.height,c.thickness, c.material, c.color; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - select DISTINCT - ob.room_name as roomName, - ob.name as bodyName, - op.id as palteId, - op.name as plateName, - ogs.material as plateMaterial, - ogs.color as palteColor, - op.height as plateHeight, - op.width as plateWidth, - op.thickness as plateThickness, - op.area as plateArea, - op.texture as texture, - op.remark as remark, - op.is_special_shaped as specialShaped, - op.is_sculpt as profiling, - op.is_row_hole AS rowHole - - from order_plate op - join order_goods ogs on op.goods_id = ogs.id and op.organ_id = ogs.organ_id - join order_item oi on op.id = oi.plate_id and op.organ_id = oi.organ_id - join order_body ob on oi.body_id = ob.id and oi.organ_id = ob.organ_id - - where - oi.order_id = #{orderNo} - and - oi.organ_id = #{organId} - and oi.plate_id != 0 - and - op.id not in ( - select DISTINCT oi2.plate_id - from order_item oi2 - where oi2.order_id = #{orderNo} and oi2.package_id <> ''); - - - - diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/process/OrdersMapper.xml b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/process/OrdersMapper.xml index e2367ba45..ff8494b5b 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/process/OrdersMapper.xml +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/resources/com/cf/imes/module/manage/dal/mysql/process/OrdersMapper.xml @@ -22,7 +22,7 @@ splitter as splitter, packaged as packaged FROM orders - WHERE organ_id = #{organId} and deleted = false and status != 0 and create_time >= #{createTime} and id != #{orderId} + WHERE organ_id = #{organId} and deleted = false and status in (1,2,3,4) and create_time >= #{createTime} and id != #{orderId} ORDER BY create_time LIMIT 1 ; @@ -49,7 +49,7 @@ splitter as splitter, packaged as packaged FROM orders - WHERE organ_id = #{organId} and deleted = false and status != 0 and create_time <= #{createTime} and id != #{orderId} + WHERE organ_id = #{organId} and deleted = false and status != 0 and create_time <= #{createTime} and id != #{orderId} ORDER BY create_time desc LIMIT 1 ; @@ -81,43 +81,6 @@ - - @@ -200,7 +163,7 @@ - order by order_date desc + order by create_time desc diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/datasource/vo/DataSourceFiledReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/datasource/vo/DataSourceFiledReqVO.java index 5c1b6bd4b..dc6c4fee1 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/datasource/vo/DataSourceFiledReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/datasource/vo/DataSourceFiledReqVO.java @@ -3,7 +3,6 @@ package com.cf.imes.module.system.controller.admin.datasource.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; import lombok.ToString; import java.util.List; @@ -17,7 +16,7 @@ public class DataSourceFiledReqVO { @Schema(description = "主键ID") private Long id; - @Schema(description = "数据源id") + @Schema(description = "数据源id-父级ID") private String sourceId; @Schema(description = "字段名称") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/machine/vo/CuttingRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/machine/vo/CuttingRespVO.java index f8cbbc83d..2e61b3c4a 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/machine/vo/CuttingRespVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/machine/vo/CuttingRespVO.java @@ -1,12 +1,15 @@ package com.cf.imes.module.system.controller.admin.machine.vo; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.fastjson.JSONObject; -import com.cf.imes.module.system.dal.dataobject.machine.CuttingSettingDO; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; @Schema(description = "管理后台 - 机台 Response VO") @Data @@ -16,55 +19,42 @@ import com.alibaba.excel.annotation.*; @AllArgsConstructor public class CuttingRespVO { + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "14092") @ExcelProperty("主键") private Long id; + @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") @ExcelProperty("名称") private String name; + @Schema(description = "1机台设备 2CNC设备", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @ExcelProperty("1机台设备 2CNC设备") private Integer machineType; + @Schema(description = "标签id") private Long labelId; + @Schema(description = "品牌ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") @ExcelProperty("品牌ID") private Long brandId; + @Schema(description = "品牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + private String brand; -// @Schema(description = "品牌", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") -// @ExcelProperty("品牌") -// private String brand; - - -// @Schema(description = "型号", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") -// @ExcelProperty("型号") -// private String model; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("创建时间") private LocalDateTime createTime; - /* @Schema(description = "机台配置") - private CuttingSettingDO machineSettingDO;*/ @Schema(description = "机台配置") private JSONObject machineSettingDO; - /** - * 机台权限相关配置 - */ - @Schema(description ="加工模式 开料机加工模式 默认true,显示开料机工作模式(是否排钻/造型,sc)配置") - private Boolean showPriorFacing; - @Schema(description = "双工位") - private Boolean showDualWorkstation; - @Schema(description = "自动贴标") - private Boolean showAutoNotePrinter; - } \ No newline at end of file diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/machine/MachineServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/machine/MachineServiceImpl.java index 72d56a515..6e55d82fb 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/machine/MachineServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/machine/MachineServiceImpl.java @@ -385,13 +385,14 @@ public class MachineServiceImpl implements MachineService { // 对机台的配置进行解压 machineDO.setSetting(JsonUtils.unzipString(machineDO.getSetting())); - LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); - assert loginUser != null; -// MachineLimitDO machineLimitDO = machineLimitMapper.selectOne(new LambdaQueryWrapperX() -// .eq(MachineLimitDO::getMachineId, id) -// .eq(MachineLimitDO::getOrganId, loginUser.getOrganId()) -// ); + Long brandId = machineDO.getBrandId(); + + MachineBrandDO machineBrandDO = machineBrandMapper.selectById(brandId); + CuttingRespVO respVO = MachineConvert.convert(machineDO); + + respVO.setBrand(machineBrandDO.getBrand()); + return respVO; } diff --git a/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml b/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml index 085a8f37d..ef2ab1101 100644 --- a/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml +++ b/cf-module-system/cf-module-system-biz/src/main/resources/application.yaml @@ -194,6 +194,7 @@ chenfeng: - system_notify_message_readinfo - system_data_source_field - system_machine_brand + - system_machine_limit use-data-code: imes_prod #动态数据源标识,后期添加的数据源需要修改此值 sms-code: # 短信验证码相关的配置项 From 4f33449cf1dc03c806518bf91b2e6735f2a42dff Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Fri, 27 Sep 2024 17:15:57 +0800 Subject: [PATCH 06/13] =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=EF=BC=9A=E8=AF=B7=E6=B1=82=E5=85=A5=E5=8F=82?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E5=AF=B9=E9=BD=90=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E9=95=BF=E5=BA=A6=E9=99=90=E5=88=B6=EF=BC=8C=E4=B8=BB=E8=A6=81?= =?UTF-8?q?=E9=92=88=E5=AF=B9String=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/dataset/vo/ReportDatasetSaveReqVO.java | 5 +++++ .../datasource/vo/ReportDatasourceSaveReqVO.java | 12 +++++++++--- .../admin/template/vo/ReportTemplateSaveReqVO.java | 5 ++++- .../notify/vo/template/NotifyTemplateSaveReqVO.java | 5 +++++ .../admin/organ/vo/organ/OrganSaveReqVO.java | 1 + .../organ/vo/packages/TenantPackageSaveReqVO.java | 2 +- .../admin/sms/vo/template/SmsTemplateSaveReqVO.java | 5 +++++ 7 files changed, 30 insertions(+), 5 deletions(-) diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/vo/ReportDatasetSaveReqVO.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/vo/ReportDatasetSaveReqVO.java index 4c7b44432..1a3ea848e 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/vo/ReportDatasetSaveReqVO.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/dataset/vo/ReportDatasetSaveReqVO.java @@ -5,7 +5,9 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.io.Serial; import java.io.Serializable; @@ -29,6 +31,8 @@ public class ReportDatasetSaveReqVO implements Serializable { private Long id; @Schema(description = "数据集名称", example = "测试数据集") + @NotBlank + @Length(min = 1, max = 64, message = "数据集名称长度不能超过64个字符") private String name; @Schema(description = "数据源id", example = "1") @@ -39,6 +43,7 @@ public class ReportDatasetSaveReqVO implements Serializable { private String sql; @Schema(description = "bean数据源方法名") + @Length(min = 1, max = 64, message = "bean数据源方法名长度不能超过64个字符") private String method; @Schema(description = "参数列表") diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java index c97a4ee05..daf1de1de 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/datasource/vo/ReportDatasourceSaveReqVO.java @@ -1,18 +1,17 @@ package com.cf.imes.module.report.controller.admin.datasource.vo; -import com.cf.imes.module.report.controller.admin.dataset.vo.ReportDatasetSaveReqVO; import com.cf.imes.module.report.validation.datasource.ReportDatasourceTypeInEnum; import com.cf.imes.module.report.validation.template.ReportTemplateTypeInEnum; -import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; +import javax.validation.constraints.NotBlank; import java.io.Serial; import java.io.Serializable; -import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -33,6 +32,8 @@ public class ReportDatasourceSaveReqVO implements Serializable { private Long id; @Schema(description = "数据源名称", example = "测试库") + @NotBlank + @Length(min = 1, max = 64, message = "数据源名称长度不能超过64个字符") private String name; @Schema(description = "数据源类型,jdbc、spring、api", example = "1") @@ -44,18 +45,23 @@ public class ReportDatasourceSaveReqVO implements Serializable { private Integer buildinType; @Schema(description = "spring型数据源id") + @Length(max = 64, message = "spring型数据源id长度不能超过64个字符") private String beanId; @Schema(description = "数据源驱动类",example = "com.mysql.cj.jdbc.Driver") + @Length(max = 64, message = "数据源驱动类长度不能超过64个字符") private String driver; @Schema(description = "数据源地址", example = "https://www.cf.com") + @Length(max = 255, message = "数据源地址长度不能超过255个字符") private String url; @Schema(description = "数据源用户名", example = "晨丰") + @Length(max = 64, message = "数据源用户名长度不能超过64个字符") private String username; @Schema(description = "数据源密码", example = "晨丰") + @Length(max = 64, message = "数据源密码长度不能超过64个字符") private String password; @Schema(description = "备注", example = "该模板仅供生产使用") diff --git a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/vo/ReportTemplateSaveReqVO.java b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/vo/ReportTemplateSaveReqVO.java index 9ac133146..ceb5d597a 100644 --- a/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/vo/ReportTemplateSaveReqVO.java +++ b/cf-module-report/cf-module-report-biz/src/main/java/com/cf/imes/module/report/controller/admin/template/vo/ReportTemplateSaveReqVO.java @@ -5,8 +5,9 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.hibernate.validator.constraints.Length; -import java.util.List; +import javax.validation.constraints.NotBlank; import java.util.Set; /** @@ -24,6 +25,8 @@ public class ReportTemplateSaveReqVO { private Long id; @Schema(description = "模板名称", example = "生产单模板") + @NotBlank + @Length(min = 1, max = 30, message = "模板名称长度不能超过30个字符") private String name; @Schema(description = "报表模板") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/notify/vo/template/NotifyTemplateSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/notify/vo/template/NotifyTemplateSaveReqVO.java index 904180ece..eb17319a4 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/notify/vo/template/NotifyTemplateSaveReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/notify/vo/template/NotifyTemplateSaveReqVO.java @@ -4,6 +4,7 @@ import com.cf.imes.framework.common.enums.CommonStatusEnum; import com.cf.imes.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; @@ -17,10 +18,12 @@ public class NotifyTemplateSaveReqVO { @Schema(description = "模版名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试模版") @NotEmpty(message = "模版名称不能为空") + @Length(min = 1, max = 64, message = "模版名称长度不能超过64个字符") private String name; @Schema(description = "模版编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "SEND_TEST") @NotNull(message = "模版编码不能为空") + @Length(min = 1, max = 64, message = "模版编码长度不能超过64个字符") private String code; @Schema(description = "模版类型,对应 system_notify_template_type 字典", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @@ -29,10 +32,12 @@ public class NotifyTemplateSaveReqVO { @Schema(description = "发送人名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "土豆") @NotEmpty(message = "发送人名称不能为空") + @Length(min = 1, max = 255, message = "发送人名称长度不能超过255个字符") private String nickname; @Schema(description = "模版内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是模版内容") @NotEmpty(message = "模版内容不能为空") + @Length(min = 1, max = 1024, message = "模版内容长度不能超过1024个字符") private String content; @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganSaveReqVO.java index 57cea191f..edaa91c84 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganSaveReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganSaveReqVO.java @@ -19,6 +19,7 @@ public class OrganSaveReqVO { @Schema(description = "组织名", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰") @NotNull(message = "组织名不能为空") + @Length(min = 1, max = 30, message = "组织名长度不能超过30个字符") private String name; @Schema(description = "联系人", requiredMode = Schema.RequiredMode.REQUIRED, example = "晨丰") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/packages/TenantPackageSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/packages/TenantPackageSaveReqVO.java index 173557beb..47c2dd4b0 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/packages/TenantPackageSaveReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/packages/TenantPackageSaveReqVO.java @@ -19,7 +19,7 @@ public class TenantPackageSaveReqVO { @Schema(description = "套餐名", requiredMode = Schema.RequiredMode.REQUIRED, example = "VIP") @NotEmpty(message = "套餐名不能为空") - @Length(min = 1, max = 30, message = "套餐名长度不能超过30位") + @Length(min = 1, max = 30, message = "套餐名长度不能超过30个字符") private String name; @Schema(description = "状态,参见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/sms/vo/template/SmsTemplateSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/sms/vo/template/SmsTemplateSaveReqVO.java index c84742f33..5ae4e3caa 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/sms/vo/template/SmsTemplateSaveReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/sms/vo/template/SmsTemplateSaveReqVO.java @@ -2,6 +2,7 @@ package com.cf.imes.module.system.controller.admin.sms.vo.template; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.hibernate.validator.constraints.Length; import javax.validation.constraints.NotNull; @@ -22,14 +23,17 @@ public class SmsTemplateSaveReqVO { @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01") @NotNull(message = "模板编码不能为空") + @Length(min = 1, max = 64, message = "模板编码长度不能超过64个字符") private String code; @Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "chenfeng") @NotNull(message = "模板名称不能为空") + @Length(min = 1, max = 64, message = "模板名称长度不能超过64个字符") private String name; @Schema(description = "模板内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "你好,{name}。你长的太{like}啦!") @NotNull(message = "模板内容不能为空") + @Length(min = 1, max = 255, message = "模板内容长度不能超过255个字符") private String content; @Schema(description = "备注", example = "哈哈哈") @@ -37,6 +41,7 @@ public class SmsTemplateSaveReqVO { @Schema(description = "短信 API 的模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4383920") @NotNull(message = "短信 API 的模板编号不能为空") + @Length(min = 1, max = 64, message = "短信 API 的模板编号长度不能超过64个字符") private String apiTemplateId; @Schema(description = "短信渠道编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") From eeafc5f2a63bc88253756f953ed3410805821940 Mon Sep 17 00:00:00 2001 From: liuzhaotian Date: Sun, 29 Sep 2024 14:45:03 +0800 Subject: [PATCH 07/13] =?UTF-8?q?=E7=BB=84=E7=BB=87=E6=9C=BA=E5=8F=B0?= =?UTF-8?q?=E6=8E=88=E6=9D=83=E6=96=B0=E5=A2=9E=E6=9C=80=E5=A4=A7=E6=95=B0?= =?UTF-8?q?=E9=87=8F=E5=BC=82=E5=B8=B8=E4=BF=A1=E6=81=AF=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=EF=BC=8C=E6=8E=92=E5=8D=95=E4=BC=98=E5=8C=96=E7=94=9F=E4=BA=A7?= =?UTF-8?q?ES=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84=E4=BD=99=E6=96=99?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=93=81=E7=89=8C=E7=AD=89=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plan/saveOptimize/RemainBoardList.java | 15 ++++++++- .../optimizeplan/OptimizePlanServiceImpl.java | 14 +++++++++ .../resources/mapper/order/OrderMapper.xml | 6 ++-- .../system/enums/ErrorCodeConstants.java | 3 ++ .../datasource/DataSourceController.java | 8 ++--- .../admin/machine/MachineController.java | 5 ++- .../service/machine/MachineService.java | 2 +- .../service/machine/MachineServiceImpl.java | 31 ++++++++++++++++--- 8 files changed, 66 insertions(+), 18 deletions(-) diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/RemainBoardList.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/RemainBoardList.java index 3838a9254..28e5d499f 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/RemainBoardList.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/controller/admin/plan/saveOptimize/RemainBoardList.java @@ -45,7 +45,7 @@ public class RemainBoardList { @Schema(description = "纹路 纹路(0正纹1可翻转2反纹)") - private Integer texture; + private Boolean texture; @@ -53,4 +53,17 @@ public class RemainBoardList { private Boolean isHandAdd; + @Schema(description = "品牌", requiredMode = Schema.RequiredMode.REQUIRED) + private String brand; + + + @Schema(description = "仓库", requiredMode = Schema.RequiredMode.REQUIRED) + private String store; + + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED) + private String remark; + + + } 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 fea5a5677..71dabf409 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 @@ -170,6 +170,13 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { OptimizeBoardModelDO optimizeBoardModelDO = optimizeBoardModelDOS.get(0); + if(!optimizeBoardModelDO.getIsOptimized()){ + + throw exception(ORDER_PLAN_NO_OPTIMIZE_ERROR); + + } + + List plateNo = new ArrayList<>(); // 创建一个列表存储 BlockPlaceInfo 对象,将优化的小板信息拿出,获取到小板编号,查询生产单,修改生产单的状态 @@ -288,6 +295,13 @@ public class OptimizePlanServiceImpl implements OptimizePlanService { OptimizeBoardModelDO optimizeBoardModelDO = optimizeBoardModelDOS.get(0); + if(!optimizeBoardModelDO.getIsOptimized()){ + + throw exception(ORDER_PLAN_NO_OPTIMIZE_UPDATE_ERROR); + + } + + CutedBoardInfo cutedBoardInfo = optimizeBoardModelDO.getCutedBoardInfo() == null ? new CutedBoardInfo() : optimizeBoardModelDO.getCutedBoardInfo(); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml index 48fcb61ed..24c2d97cb 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/resources/mapper/order/OrderMapper.xml @@ -44,8 +44,8 @@ o.status as status from orders o - STRAIGHT_JOIN order_goods og on o.organ_id = og.organ_id and o.id = og.order_id and og.plan_id = 0 and o.deleted = og.deleted - STRAIGHT_JOIN order_plate op on o.organ_id = op.organ_id and o.deleted = op.deleted and o.id = op.order_id and op.is_optimized = false and og.id = op.goods_id + join order_goods og on o.organ_id = og.organ_id and o.id = og.order_id and og.plan_id = 0 and o.deleted = og.deleted + join order_plate op on o.organ_id = op.organ_id and o.deleted = op.deleted and o.id = op.order_id and op.is_optimized = false and og.id = op.goods_id ${ew.customSqlSegment} @@ -240,8 +240,6 @@ select distinct --- og.order_id as orderId, --- og.id as id, og.goods_id as goodsId, og.goods_name, diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java index c6801deca..1053bcb3a 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java @@ -217,6 +217,7 @@ public interface ErrorCodeConstants { ErrorCode LABELINGMACHINE_RELATED_DATA_ERROR = new ErrorCode(1_002_029_014, "当前机台关联的贴标机数据有误,请在高级配置中重新配置贴标机或选择其他模板"); ErrorCode DRILLMACHINE_RELATED_DATA_ERROR = new ErrorCode(1_002_029_015, "当前机台关联的钻孔机数据有误,请在钻孔模块中重新配置钻孔机或选择其他模板"); ErrorCode MACHINE_DATA_ERROR = new ErrorCode(1_002_029_016, "当前组织还未进行机台授权,请联系组织管理员在基础管理里对当前组织进行机台授权,或联系客服进行授权"); + ErrorCode MACHINE_NUM_DATA_ERROR = new ErrorCode(1_002_029_017, "组织授权的机台数量不能超过127台"); // ========== 标签模板 1-002-300-000 ========== @@ -299,6 +300,8 @@ public interface ErrorCodeConstants { ErrorCode ORDER_GOODS_DATA_ERROR = new ErrorCode(1_002_041_010, "当前大板数据异常,请检查大板信息或者联系客服"); ErrorCode ORDER_PACK_DATA_ERROR = new ErrorCode(1_002_041_011, "当前包裹数据为空,请重新查看包裹数据或联系客服"); ErrorCode ORDER_BODY_DATA_ERROR = new ErrorCode(1_002_041_012, "当前柜体对应的板材数据为空,无法删除"); + ErrorCode ORDER_PLAN_NO_OPTIMIZE_ERROR = new ErrorCode(1_002_041_013, "当前排单还未保存优化结果,无法进行开料"); + ErrorCode ORDER_PLAN_NO_OPTIMIZE_UPDATE_ERROR = new ErrorCode(1_002_041_014, "当前排单还未保存优化结果,无法对开料结果进行修改"); diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/datasource/DataSourceController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/datasource/DataSourceController.java index 6910d4dce..2b930da8f 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/datasource/DataSourceController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/datasource/DataSourceController.java @@ -76,7 +76,7 @@ public class DataSourceController { }*/ @GetMapping("/list") - @Operation(summary = "获得系统数据源列表") + @Operation(summary = "获得系统数据源列表-获取标签数据源") //@PreAuthorize("@ss.hasPermission('system:data-source:query')") public CommonResult> list( ) { return success(dataSourceService.list()); @@ -99,17 +99,17 @@ public class DataSourceController { @GetMapping("/getList") - @Operation(summary = "获取数据源参数") + @Operation(summary = "获取数据源参数-获取机台数据源") @Parameter(name = "type", description = "标签类型", required = true, example = "9") //@PreAuthorize("@ss.hasPermission('system:data-source:query')") public CommonResult> getList(@RequestParam("type") Integer type ) { - return success(dataSourceService.getList( type)); + return success(dataSourceService.getList(type)); } @GetMapping("/getKeyNameData") - @Operation(summary = "数据源对应字段数据查询") + @Operation(summary = "机台数据源对应字段数据查询") @Parameters({ @Parameter(name = "machineId", description = "机台ID", required = true), @Parameter(name = "planId", description = "排单ID", required = true) diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/machine/MachineController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/machine/MachineController.java index 2eda29d72..804f7b01a 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/machine/MachineController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/machine/MachineController.java @@ -6,7 +6,6 @@ import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.es.core.valid.CreateGroup; import com.cf.imes.framework.es.core.valid.UpdateGroup; import com.cf.imes.framework.operatelog.core.annotations.OperateLog; -import com.cf.imes.framework.organ.core.context.OrganContextHolder; import com.cf.imes.module.system.controller.admin.machine.vo.*; import com.cf.imes.module.system.dal.dataobject.machine.MachineDO; import com.cf.imes.module.system.service.machine.MachineService; @@ -110,8 +109,8 @@ public class MachineController { @GetMapping(value = {"/list-all-simple", "/simple-list"}) @Operation(summary = "获取机台精简信息列表", description = "主要用于前端的下拉选项") public CommonResult> getSimpleDeptList(@RequestParam(required = false) Long organId,@RequestParam(required = false) Long type) { - organId = organId == null ? OrganContextHolder.getOrganId() : organId; - List list = machineService.simpleList(organId,type); +// organId = organId == null ? OrganContextHolder.getOrganId() : organId; + List list = machineService.simpleList(type); return success(list); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/machine/MachineService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/machine/MachineService.java index b1592a080..33a745008 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/machine/MachineService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/machine/MachineService.java @@ -80,7 +80,7 @@ public interface MachineService { PageResult page(MachinePageReqVO pageParam); - List simpleList(Long organId,Long type); + List simpleList(Long type); List getBrandAndModel(Integer type); diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/machine/MachineServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/machine/MachineServiceImpl.java index 6e55d82fb..7a7217dce 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/machine/MachineServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/machine/MachineServiceImpl.java @@ -443,12 +443,26 @@ public class MachineServiceImpl implements MachineService { @Override public Boolean authInsert(MachineOrgAuthReq vo) { + OrganizationDO tenant = organMapper.selectById(vo.getOrganId()); + if (tenant == null) { + throw exception(ORGAN_NOT_EXISTS); + } + MachineLimitDO machineLimit = machineLimitMapper.selectById(vo.getOrganId()); if (machineLimit != null) { throw exception(ORGAN_ALREADY_EXISTS); } + Integer[] limits = {vo.getCutLimit(), vo.getDrillLimit(), vo.getLabelLimit(), vo.getSawLimit(), vo.getSealedgeLimit()}; + + for (Integer limit : limits) { + if (limit > 127) { + throw exception(MACHINE_NUM_DATA_ERROR); + } + } + + MachineLimitDO machineLimitDO = MachineLimitDO.builder() .organId(vo.getOrganId()) .cutLimit(vo.getCutLimit()) @@ -456,7 +470,6 @@ public class MachineServiceImpl implements MachineService { .labelLimit(vo.getLabelLimit()) .sawLimit(vo.getSawLimit()) .sealedgeLimit(vo.getSealedgeLimit()) -// .setting(vo.getMachineAuthIds().toString()) .build(); machineLimitMapper.insert(machineLimitDO); @@ -473,6 +486,16 @@ public class MachineServiceImpl implements MachineService { throw exception(ORGAN_NOT_EXISTS); } + + Integer[] limits = {vo.getCutLimit(), vo.getDrillLimit(), vo.getLabelLimit(), vo.getSawLimit(), vo.getSealedgeLimit()}; + + for (Integer limit : limits) { + if (limit > 127) { + throw exception(MACHINE_NUM_DATA_ERROR); + } + } + + LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); assert loginUser != null; @@ -483,8 +506,6 @@ public class MachineServiceImpl implements MachineService { .labelLimit(vo.getLabelLimit()) .sawLimit(vo.getSawLimit()) .sealedgeLimit(vo.getSealedgeLimit()) - -// .setting(vo.getMachineAuthIds().toString()) .build(); machineLimitDO.setUpdateTime(LocalDateTime.now()); @@ -537,9 +558,9 @@ public class MachineServiceImpl implements MachineService { @Override @OrganIgnore - public List simpleList(Long organId, Long type) { + public List simpleList( Long type) { List machineDOS = machineMapper.selectList(new LambdaQueryWrapperX() - .eqIfPresent(MachineDO::getOrganId, organId) + .eqIfPresent(MachineDO::getOrganId, getUserOrganId()) .eqIfPresent(MachineDO::getMachineType, type) .select(MachineDO::getId, MachineDO::getName, MachineDO::getMachineType) ); From 3b6e24e5b6bea7841dee58d9aa4e4b94ce61b404 Mon Sep 17 00:00:00 2001 From: liuzhaotian Date: Sun, 29 Sep 2024 16:45:06 +0800 Subject: [PATCH 08/13] =?UTF-8?q?=E7=A6=85=E9=81=93Bug-530=EF=BC=8C527?= =?UTF-8?q?=E8=A7=A3=E5=86=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../executor/enums/ErrorCodeConstants.java | 1 + .../executor/dal/mysql/plate/PlateMapper.java | 10 +++++++ .../service/order/OrderServiceImpl.java | 14 ++++++--- .../service/plan/PlanServiceImpl.java | 29 +++++++++---------- 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java index b9ab72dc9..e0f520c0f 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java +++ b/cf-module-prod-executor/cf-module-prod-executor-api/src/main/java/com/cf/imes/module/executor/enums/ErrorCodeConstants.java @@ -33,6 +33,7 @@ public interface ErrorCodeConstants { ErrorCode ORDER_NOT_CANCEL = new ErrorCode(1_001_109_000, "生产单已排单,小板操作无效"); ErrorCode ORDER_CANCEL = new ErrorCode(1_001_109_000, "生产单未作废,还原无效"); ErrorCode ORDER_PLAN_ERROR = new ErrorCode(1_001_109_001, "选中删除对象有已开料板件,请联系管理员修改开料状态后再删除!"); + ErrorCode ORDER_ERROR = new ErrorCode(1_001_109_002, "当前生产单柜体,房间已全部删除!"); // ========== 生产单 TODO 补充编号 ========== ErrorCode MODULE_NOT_EXISTS = new ErrorCode(1_001_110_000, "模块不存在"); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plate/PlateMapper.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plate/PlateMapper.java index ebc53ac3e..5f36ee97d 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plate/PlateMapper.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/dal/mysql/plate/PlateMapper.java @@ -227,6 +227,16 @@ public interface PlateMapper extends BaseMapperX { } + + default List selectPlateIsOptimized(Long orderId, Long organId) { + return selectList(new LambdaQueryWrapperX() + .eq(PlateDO::getOrganId,organId) + .eq(PlateDO::getDeleted,false) + .eqIfPresent(PlateDO::getOrderId,orderId) + .eq(PlateDO::getIsOptimized,true)); + + } + // List selectTestSQL(@Param("sql") String sql); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java index ac1463554..3a8fbb9d8 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java @@ -60,6 +60,7 @@ import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.OrderX import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.XmlTypeRealize; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ObjectUtils; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; @@ -259,7 +260,7 @@ public class OrderServiceImpl implements OrderService { @Transactional(rollbackFor = Exception.class) public void updateDeleteBody(Long orderId, Set roomIds, Long bodyId, Integer status) { // 要删除传1,还原传0 // 判断生产单的状态和生产单柜体对应的板擦是否已开料 - List planIds = validateOrderStatus(orderId, roomIds, bodyId, getUserOrganId(), OrderDeletedEnum.NOT_DELETED.getStatus()); + List planIds = validateOrderStatus(orderId, roomIds, bodyId, getUserOrganId()); List bodyIds = new ArrayList<>(); Integer index = status == 1 ? 0 : 1; @@ -348,7 +349,7 @@ public class OrderServiceImpl implements OrderService { // 生产单柜体数量判断 - if (orderBodyMapper.selectCountByOrderId(orderId, getUserOrganId(), OrderDeletedEnum.NOT_DELETED.getStatus()) == 0) { + if (orderBodyMapper.selectCountByOrderId(orderId, getUserOrganId(), OrderDeletedEnum.NOT_DELETED.getStatus()) == 0 ) { orderMapper.updateOrderStatus(orderId, OrderStatusEnum.EMPTY.getStatus(), getUserOrganId()); }else { orderMapper.updateOrderStatus(orderId, OrderStatusEnum.NEW_ORDER.getStatus(), getUserOrganId()); @@ -993,15 +994,20 @@ public class OrderServiceImpl implements OrderService { } // 判断生产单状态是否符合(如果已开料,不允许删除) - private List validateOrderStatus(Long orderId,Set roomIds, Long bodyId, Long organId, Integer status) { + private List validateOrderStatus(Long orderId,Set roomIds, Long bodyId, Long organId) { // 校验存在 OrderDO orderDO = orderMapper.selectOrderOne(orderId, organId); if (orderDO == null) throw exception(ORDER_NOT_EXISTS); + + if (ObjectUtils.isEmpty(roomIds) && ObjectUtils.isEmpty(bodyId)) { + throw exception(ORDER_ERROR); + } + // 判断小板是否已开料,已开料不允许删除 List planIds = goodsMapper.selectPlanOrderList(orderId, roomIds, bodyId, organId); - if(!planIds.isEmpty() && status.equals(1)) { + if(!planIds.isEmpty()) { List planDOS = planMapper.selectPlanStatus(planIds, organId); diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java index 04866b571..535cc96a0 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/plan/PlanServiceImpl.java @@ -337,34 +337,31 @@ public class PlanServiceImpl implements PlanService { remainPlateMapper.deletePlanRemainPlate(ids,getUserOrganId()); + List goodsIdList = goodsMapper.selectPlanGoodsListByPlanIdList(orderIds,ids, getUserOrganId()).stream().map(GoodsDO::getId).toList(); - // 排单对应的自增板的删除 todo 目前值解决了非混单的情况 - List boardModelDOS = buildBoardByPlanIds(ids, ORDER_REMAIN_PLATE_MODEL, ids.size()); - if(!boardModelDOS.isEmpty()) { + if(!goodsIdList.isEmpty()) { + // 修改删除的大板对应的小板为未优化 + plateMapper.updateNoPlateOptimized(orderIds, goodsIdList, getUserOrganId()); - - List goodsIdList = goodsMapper.selectPlanGoodsListByPlanIdList(orderIds,ids, getUserOrganId()).stream().map(GoodsDO::getId).toList(); - - if(!goodsIdList.isEmpty()) { - // 修改删除的大板对应的小板为未优化 - plateMapper.updateNoPlateOptimized(orderIds, goodsIdList, getUserOrganId()); - } - - List plateDOS = plateMapper.selectPlateIdList(orderIds,goodsIdList, getUserOrganId()); - if(!plateDOS.isEmpty()) { + List plateDOS = plateMapper.selectPlateIdList(orderIds, goodsIdList, getUserOrganId()); + if (!plateDOS.isEmpty()) { List plateIds = plateDOS.stream().map(PlateDO::getId).toList(); plateMapper.deleteBatchIds(plateIds); orderItemMapper.delete(new LambdaQueryWrapperX() - .eq(OrderItemDO::getOrganId,getUserOrganId()) - .in(OrderItemDO::getOrderId,orderIds) + .eq(OrderItemDO::getOrganId, getUserOrganId()) + .in(OrderItemDO::getOrderId, orderIds) .in(OrderItemDO::getPlateId, plateIds)); } + } + // 排单对应的自增板的删除 todo 目前值解决了非混单的情况 + List boardModelDOS = buildBoardByPlanIds(ids, ORDER_REMAIN_PLATE_MODEL, ids.size()); + if(!boardModelDOS.isEmpty()) { // 删除排单对应的优化生产数据 deleteByPlanId(ids, ORDER_REMAIN_PLATE_MODEL); @@ -378,7 +375,7 @@ public class PlanServiceImpl implements PlanService { List diff; // 根据生产单ID查询ES的优化数据 - List optimizeBoardModelDOS = optimizePlanService.buildBoardByOrderIds(orderIds, ORDER_REMAIN_PLATE_MODEL, 999); + List optimizeBoardModelDOS = optimizePlanService.buildBoardByOrderIds(orderIds, ORDER_REMAIN_PLATE_MODEL, 100); if(optimizeBoardModelDOS.isEmpty()){ From e5d91f7e22ec300b73840b0a4d8e40ca2048c80b Mon Sep 17 00:00:00 2001 From: liuzhaotian Date: Sun, 29 Sep 2024 17:43:34 +0800 Subject: [PATCH 09/13] =?UTF-8?q?=E5=88=86=E5=A0=86=E6=89=93=E5=8C=85?= =?UTF-8?q?=E6=8B=86=E5=8C=85=E6=95=B0=E6=8D=AE=E6=AD=A3=E7=A1=AE=E6=80=A7?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/manage/service/pack/PackServiceImpl.java | 10 ++++++++++ .../imes/module/system/enums/ErrorCodeConstants.java | 1 + 2 files changed, 11 insertions(+) diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/pack/PackServiceImpl.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/pack/PackServiceImpl.java index 16c82418e..1dbd53388 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/pack/PackServiceImpl.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/pack/PackServiceImpl.java @@ -455,12 +455,22 @@ public class PackServiceImpl implements PackService { // 拆包 @Override + @Transactional(rollbackFor = Exception.class) public OrderPackRespVO unpacking(Long packageID) { OrderPackageDO packageDO = orderPackageMapper.selectById(packageID); AssertUtils.notEmpty(packageDO,ORDER_PACK_DATA_ERROR ); + Long orderId = packageDO.getOrderId(); + + OrderDO orderDO = ordersMapper.selectById(orderId); + + AssertUtils.notEmpty(orderDO,ORDER_NO_DATA_ERROR); + + orderDO.setPackaged(OrderPackageStatusEnum.UNPACKED.getStatus()); + ordersMapper.updateById(orderDO); + packageDO.setStatus(OrderPackageStatusEnum.UNPACKED.getStatus()); orderPackageMapper.updateById(packageDO); return typeConversion(packageDO); diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java index 1053bcb3a..a7065f462 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java @@ -302,6 +302,7 @@ public interface ErrorCodeConstants { ErrorCode ORDER_BODY_DATA_ERROR = new ErrorCode(1_002_041_012, "当前柜体对应的板材数据为空,无法删除"); ErrorCode ORDER_PLAN_NO_OPTIMIZE_ERROR = new ErrorCode(1_002_041_013, "当前排单还未保存优化结果,无法进行开料"); ErrorCode ORDER_PLAN_NO_OPTIMIZE_UPDATE_ERROR = new ErrorCode(1_002_041_014, "当前排单还未保存优化结果,无法对开料结果进行修改"); + ErrorCode ORDER_NO_DATA_ERROR = new ErrorCode(1_002_041_001, "生产单信息错误,请重新进行拆包"); From dcab45d2a1d45173f0f9ca10210e2bb9e2c89aef Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Sun, 29 Sep 2024 18:25:06 +0800 Subject: [PATCH 10/13] =?UTF-8?q?=E6=8A=A5=E8=A1=A8=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=EF=BC=9Aureport=E6=97=B6=E9=97=B4=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/ureport-core-2.3.0-SNAPSHOT.jar | Bin 928541 -> 925690 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar b/cf-module-report/cf-module-report-biz/src/main/resources/lib/ureport-core-2.3.0-SNAPSHOT.jar index ba225c0e2b561cc85ff268d94884473118be548f..fa2621d2e73525449c43184e7096af0ae31e1483 100644 GIT binary patch delta 79373 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

W$96tzUr*CpiwS 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

tf>Sno27SiwHCE5U`t2gn_5@#6 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 Hi4Fe%-uQmd From f651fb643f2e2398feb10ef4c9d7da92f18f3e48 Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Mon, 30 Sep 2024 15:07:18 +0800 Subject: [PATCH 11/13] =?UTF-8?q?=E5=88=86=E6=9E=90=E9=A1=B5=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1=EF=BC=9A1=E3=80=81=E5=A4=A7=E6=9D=BF=E6=95=B0?= =?UTF-8?q?=E9=87=8Fcreatetime=E5=92=8Cgoodsid=E6=9F=A5=E8=AF=A2=E5=A4=B1?= =?UTF-8?q?=E6=95=88=E4=BF=AE=E5=A4=8D=E3=80=81=E5=88=86=E7=BB=84=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E4=BF=AE=E5=A4=8D=EF=BC=9B2=E3=80=81=E5=B0=8F?= =?UTF-8?q?=E6=9D=BF=E9=9D=A2=E7=A7=AF=E6=8C=89=E9=9D=A2=E7=A7=AF=E5=80=92?= =?UTF-8?q?=E5=BA=8F=E5=A4=B1=E6=95=88=E4=BF=AE=E5=A4=8D=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/OrderStatisticsServiceImpl.java | 61 +++++++++++-------- .../plate/OrderPlateStatisticsMapper.xml | 2 +- 2 files changed, 37 insertions(+), 26 deletions(-) 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 9f9e8d7a5..8128e335f 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 @@ -11,7 +11,6 @@ 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.mybatis.core.query.LambdaQueryWrapperX; @@ -86,6 +85,7 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { 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 ORDER_REMAIN_PLATE_MODEL_DATE_GROUP_NAME = "date_group"; 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"; private static final String ORDER_REMAIN_PLATE_MODEL_GOODS_ID_NAME = "goodsId"; @@ -427,10 +427,12 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { 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)))) - ) + .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"))) @@ -456,16 +458,20 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { 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.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)))))) + ) ) - .query(q -> q.bool(b -> b.must(m -> m.terms(t -> t.field(ORDER_REMAIN_PLATE_MODEL_GOODS_ID_NAME).terms(tv -> tv.value(goodsIdFieldValueList)))))) - .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(ORDER_REMAIN_PLATE_MODEL_GOODS_ID_NAME).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"))) + .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); @@ -475,17 +481,22 @@ public class OrderStatisticsServiceImpl implements OrderStatisticsService { goodsDateAgg.sterms().buckets().array().forEach(goodsDateAggBucket -> { // 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(goodsDateAggBucket.key().stringValue()).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); - } + 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); + } + }); }); } 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 2354fd008..7d210d7dc 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 @@ -60,7 +60,7 @@ where g.deleted = 0 and o.order_date between #{req.createTime[0]} and #{req.createTime[1]} group by g.goods_id - order by orderArea + order by orderArea desc limit 10; From 4fe3cfda62fcab762159ac3560e391f73c64d18e Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Tue, 8 Oct 2024 14:23:17 +0800 Subject: [PATCH 12/13] =?UTF-8?q?=E7=A6=85=E9=81=93=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E7=AB=99=E5=86=85=E4=BF=A1=E6=A8=A1?= =?UTF-8?q?=E7=89=88/=E6=B6=88=E6=81=AF=E3=80=81=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E3=80=81=E7=BB=84=E7=BB=87=E6=9D=83=E9=99=90?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=97=B6=E9=97=B4=E5=8C=BA=E9=97=B4=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=BD=93=E6=97=A5=E6=95=B0=E6=8D=AE=E5=A4=B1=E6=95=88?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/date/LocalDateTimeUtils.java | 16 ++++++++++++++++ .../admin/logger/OperateLogController.java | 2 ++ .../admin/notify/NotifyMessageController.java | 2 ++ .../admin/notify/NotifyTemplateController.java | 2 ++ .../admin/organ/TenantPackageController.java | 2 ++ 5 files changed, 24 insertions(+) diff --git a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/date/LocalDateTimeUtils.java b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/date/LocalDateTimeUtils.java index 682b669ea..2e2042122 100644 --- a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/date/LocalDateTimeUtils.java +++ b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/date/LocalDateTimeUtils.java @@ -1,6 +1,7 @@ package com.cf.imes.framework.common.util.date; import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.ObjectUtil; import java.time.Duration; import java.time.LocalDate; @@ -132,4 +133,19 @@ public class LocalDateTimeUtils { return LocalDateTimeUtil.between(dateTime, LocalDateTime.now(), ChronoUnit.DAYS); } + /** + * 生成起时间0点和止时间12点的区间 + * + * @param dateSection + * @return + */ + public static LocalDateTime[] generateTimeSection(LocalDateTime[] dateSection) { + if (ObjectUtil.isNotNull(dateSection) && dateSection.length == 2) { + LocalDateTime[] result = new LocalDateTime[2]; + result[0] = dateSection[0].withHour(0).withMinute(0).withSecond(0); + result[1] = dateSection[1].withHour(23).withMinute(59).withSecond(59); + return result; + } + return dateSection; + } } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/logger/OperateLogController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/logger/OperateLogController.java index 18b2f598b..6999be56b 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/logger/OperateLogController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/logger/OperateLogController.java @@ -3,6 +3,7 @@ package com.cf.imes.module.system.controller.admin.logger; import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.pojo.PageParam; import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.date.LocalDateTimeUtils; import com.cf.imes.framework.excel.core.util.ExcelUtils; import com.cf.imes.framework.operatelog.core.annotations.OperateLog; import com.cf.imes.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; @@ -46,6 +47,7 @@ public class OperateLogController { @Operation(summary = "查看操作日志分页列表") @PreAuthorize("@ss.hasPermission('system:operate-log:query')") public CommonResult> pageOperateLog(@Valid OperateLogPageReqVO pageReqVO) { + pageReqVO.setStartTime(LocalDateTimeUtils.generateTimeSection(pageReqVO.getStartTime())); PageResult pageResult = operateLogService.getOperateLogPage(pageReqVO); // 获得拼接需要的数据 Map userMap = userService.getUserMap( diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/notify/NotifyMessageController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/notify/NotifyMessageController.java index 1bb12e6cd..54cf250da 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/notify/NotifyMessageController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/notify/NotifyMessageController.java @@ -3,6 +3,7 @@ package com.cf.imes.module.system.controller.admin.notify; import com.cf.imes.framework.common.enums.UserTypeEnum; import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.date.LocalDateTimeUtils; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.module.system.controller.admin.notify.vo.message.NotifyMessagePageReqVO; import com.cf.imes.module.system.controller.admin.notify.vo.message.NotifyMessageRespVO; @@ -47,6 +48,7 @@ public class NotifyMessageController { @PreAuthorize("@ss.hasPermission('system:notify-message:query')") public CommonResult> getNotifyMessagePage(@Valid NotifyMessagePageReqVO pageVO) { pageVO.setUserId(getLoginUserId()); + pageVO.setCreateTime(LocalDateTimeUtils.generateTimeSection(pageVO.getCreateTime())); PageResult pageResult = notifyMessageService.getMyMyNotifyMessagePage(pageVO); return success(BeanUtils.toBean(pageResult, NotifyMessageRespVO.class)); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/notify/NotifyTemplateController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/notify/NotifyTemplateController.java index 755d9af57..f51d28f61 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/notify/NotifyTemplateController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/notify/NotifyTemplateController.java @@ -2,6 +2,7 @@ package com.cf.imes.module.system.controller.admin.notify; import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.date.LocalDateTimeUtils; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.module.system.controller.admin.notify.vo.template.NotifyTemplatePageReqVO; import com.cf.imes.module.system.controller.admin.notify.vo.template.NotifyTemplateRespVO; @@ -71,6 +72,7 @@ public class NotifyTemplateController { @Operation(summary = "获得站内信模版分页") @PreAuthorize("@ss.hasPermission('system:notify-template:query')") public CommonResult> getNotifyTemplatePage(@Valid NotifyTemplatePageReqVO pageVO) { + pageVO.setCreateTime(LocalDateTimeUtils.generateTimeSection(pageVO.getCreateTime())); PageResult pageResult = notifyTemplateService.getNotifyTemplatePage(pageVO); return success(BeanUtils.toBean(pageResult, NotifyTemplateRespVO.class)); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/TenantPackageController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/TenantPackageController.java index b83e8ac4f..2b125e4a6 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/TenantPackageController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/TenantPackageController.java @@ -3,6 +3,7 @@ package com.cf.imes.module.system.controller.admin.organ; import com.cf.imes.framework.common.enums.CommonStatusEnum; import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.date.LocalDateTimeUtils; import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.module.system.controller.admin.organ.vo.packages.TenantPackagePageReqVO; import com.cf.imes.module.system.controller.admin.organ.vo.packages.TenantPackageRespVO; @@ -69,6 +70,7 @@ public class TenantPackageController { @Operation(summary = "获得组织套餐分页") @PreAuthorize("@ss.hasPermission('system:tenant-package:query')") public CommonResult> getTenantPackagePage(@Valid TenantPackagePageReqVO pageVO) { + pageVO.setCreateTime(LocalDateTimeUtils.generateTimeSection(pageVO.getCreateTime())); PageResult pageResult = tenantPackageService.getTenantPackagePage(pageVO); return success(BeanUtils.toBean(pageResult, TenantPackageRespVO.class)); } From 73b4051641e7efb95915669895e0ab5cfb875daa Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Tue, 8 Oct 2024 16:52:56 +0800 Subject: [PATCH 13/13] =?UTF-8?q?sonarqube=E8=B4=A8=E9=87=8F=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../imes/framework/common/core/KeyValue.java | 22 - .../common/util/collection/MapUtils.java | 4 +- .../dict/core/util/DictFrameworkUtils.java | 20 +- .../PayClientFactoryImplIntegrationTest.java | 6 + .../weixin/WxBarPayClientIntegrationTest.java | 7 + .../WxNativePayClientIntegrationTest.java | 4 + .../framework/sms/core/client/SmsClient.java | 4 +- .../client/impl/aliyun/AliyunSmsClient.java | 4 +- .../impl/debug/DebugDingTalkSmsClient.java | 4 +- .../client/impl/tencent/TencentSmsClient.java | 10 +- .../impl/aliyun/AliyunSmsClientTest.java | 10 +- .../impl/tencent/TencentSmsClientTest.java | 10 +- .../core/client/ftp/FtpFileClientTest.java | 4 + .../client/local/LocalFileClientTest.java | 4 + .../core/client/sftp/SftpFileClientTest.java | 4 + .../service/SecurityFrameworkServiceImpl.java | 20 +- .../ChenfengJacksonAutoConfiguration.java | 6 +- ...lizer.java => CustomNumberSerializer.java} | 6 +- .../service/DefaultDatabaseQueryTest.java | 4 + .../service/order/OrderServiceImpl.java | 6 +- .../service/goods/GoodsServiceImplTest.java | 84 - .../service/plan/PlanServiceImplTest.java | 116 - .../executor/service/zlib/ZlibTest.java | 160 - .../service/zlib/order_block_plan_result.json | 3637 ----------------- .../service/voice/VoiceServiceImpl.java | 44 +- .../open/OAuth2OpenAuthorizeInfoRespVO.java | 4 +- .../convert/oauth2/OAuth2OpenConvert.java | 6 +- .../system/mq/message/sms/SmsSendMessage.java | 4 +- .../system/mq/producer/sms/SmsProducer.java | 4 +- .../service/sms/SmsSendServiceImpl.java | 10 +- .../sms/handler/SmsSendAfterSendHandler.java | 4 +- .../impl/SmsSendAfterSendHandlerImpl.java | 6 +- .../controller/admin/oauth2/EsTest.java | 57 +- .../oauth2/OAuth2OpenControllerTest.java | 8 +- .../auth/AdminAuthServiceImplTest.java | 100 +- .../machine/MachineServiceImplTest.java | 33 +- .../service/mail/MailSendServiceImplTest.java | 2 + .../oauth2/OAuth2GrantServiceImplTest.java | 67 - .../oauth2/OAuth2TokenServiceImplTest.java | 32 - .../service/organ/TenantServiceImplTest.java | 3 +- .../service/sms/SmsSendServiceImplTest.java | 11 +- 41 files changed, 151 insertions(+), 4400 deletions(-) delete mode 100644 cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/core/KeyValue.java rename cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/jackson/core/databind/{NumberSerializer.java => CustomNumberSerializer.java} (78%) delete mode 100644 cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/zlib/ZlibTest.java delete mode 100644 cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/zlib/order_block_plan_result.json diff --git a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/core/KeyValue.java b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/core/KeyValue.java deleted file mode 100644 index e1c9767ba..000000000 --- a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/core/KeyValue.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.cf.imes.framework.common.core; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.io.Serializable; - -/** - * Key Value 的键值对 - * - * @author 晨丰科技 - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class KeyValue implements Serializable { - - private K key; - private V value; - -} diff --git a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/collection/MapUtils.java b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/collection/MapUtils.java index 6a5a923d3..8c74382ba 100644 --- a/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/collection/MapUtils.java +++ b/cf-framework/cf-common/src/main/java/com/cf/imes/framework/common/util/collection/MapUtils.java @@ -1,7 +1,7 @@ package com.cf.imes.framework.common.util.collection; import cn.hutool.core.collection.CollUtil; -import com.cf.imes.framework.common.core.KeyValue; +import cn.hutool.core.lang.Pair; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; @@ -56,7 +56,7 @@ public class MapUtils { consumer.accept(value); } - public static Map convertMap(List> keyValues) { + public static Map convertMap(List> keyValues) { Map map = Maps.newLinkedHashMapWithExpectedSize(keyValues.size()); keyValues.forEach(keyValue -> map.put(keyValue.getKey(), keyValue.getValue())); return map; diff --git a/cf-framework/cf-spring-boot-starter-biz-dict/src/main/java/com/cf/imes/framework/dict/core/util/DictFrameworkUtils.java b/cf-framework/cf-spring-boot-starter-biz-dict/src/main/java/com/cf/imes/framework/dict/core/util/DictFrameworkUtils.java index 53988e89b..69335d8ee 100644 --- a/cf-framework/cf-spring-boot-starter-biz-dict/src/main/java/com/cf/imes/framework/dict/core/util/DictFrameworkUtils.java +++ b/cf-framework/cf-spring-boot-starter-biz-dict/src/main/java/com/cf/imes/framework/dict/core/util/DictFrameworkUtils.java @@ -1,7 +1,7 @@ package com.cf.imes.framework.dict.core.util; +import cn.hutool.core.lang.Pair; import cn.hutool.core.util.ObjectUtil; -import com.cf.imes.framework.common.core.KeyValue; import com.cf.imes.framework.common.util.cache.CacheUtils; import com.cf.imes.module.system.api.dict.DictDataApi; import com.cf.imes.module.system.api.dict.dto.DictDataRespDTO; @@ -27,12 +27,12 @@ public class DictFrameworkUtils { /** * 针对 {@link #getDictDataLabel(String, String)} 的缓存 */ - private static final LoadingCache, DictDataRespDTO> GET_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache( + private static final LoadingCache, DictDataRespDTO> GET_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache( Duration.ofMinutes(1L), // 过期时间 1 分钟 - new CacheLoader, DictDataRespDTO>() { + new CacheLoader<>() { @Override - public DictDataRespDTO load(KeyValue key) { + public DictDataRespDTO load(Pair key) { return ObjectUtil.defaultIfNull(dictDataApi.getDictData(key.getKey(), key.getValue()).getCheckedData(), DICT_DATA_NULL); } @@ -42,12 +42,12 @@ public class DictFrameworkUtils { /** * 针对 {@link #parseDictDataValue(String, String)} 的缓存 */ - private static final LoadingCache, DictDataRespDTO> PARSE_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache( + private static final LoadingCache, DictDataRespDTO> PARSE_DICT_DATA_CACHE = CacheUtils.buildAsyncReloadingCache( Duration.ofMinutes(1L), // 过期时间 1 分钟 - new CacheLoader, DictDataRespDTO>() { + new CacheLoader<>() { @Override - public DictDataRespDTO load(KeyValue key) { + public DictDataRespDTO load(Pair key) { return ObjectUtil.defaultIfNull(dictDataApi.parseDictData(key.getKey(), key.getValue()).getCheckedData(), DICT_DATA_NULL); } @@ -61,17 +61,17 @@ public class DictFrameworkUtils { @SneakyThrows public static String getDictDataLabel(String dictType, Integer value) { - return GET_DICT_DATA_CACHE.get(new KeyValue<>(dictType, String.valueOf(value))).getLabel(); + return GET_DICT_DATA_CACHE.get(new Pair<>(dictType, String.valueOf(value))).getLabel(); } @SneakyThrows public static String getDictDataLabel(String dictType, String value) { - return GET_DICT_DATA_CACHE.get(new KeyValue<>(dictType, value)).getLabel(); + return GET_DICT_DATA_CACHE.get(new Pair<>(dictType, value)).getLabel(); } @SneakyThrows public static String parseDictDataValue(String dictType, String label) { - return PARSE_DICT_DATA_CACHE.get(new KeyValue<>(dictType, label)).getValue(); + return PARSE_DICT_DATA_CACHE.get(new Pair<>(dictType, label)).getValue(); } } diff --git a/cf-framework/cf-spring-boot-starter-biz-pay/src/test/java/com/cf/imes/framework/pay/core/client/impl/PayClientFactoryImplIntegrationTest.java b/cf-framework/cf-spring-boot-starter-biz-pay/src/test/java/com/cf/imes/framework/pay/core/client/impl/PayClientFactoryImplIntegrationTest.java index 003d2c63c..f15a79ec3 100644 --- a/cf-framework/cf-spring-boot-starter-biz-pay/src/test/java/com/cf/imes/framework/pay/core/client/impl/PayClientFactoryImplIntegrationTest.java +++ b/cf-framework/cf-spring-boot-starter-biz-pay/src/test/java/com/cf/imes/framework/pay/core/client/impl/PayClientFactoryImplIntegrationTest.java @@ -16,6 +16,8 @@ import org.junit.jupiter.api.Test; import java.io.FileInputStream; import java.io.FileNotFoundException; +import static org.junit.jupiter.api.Assertions.assertNotNull; + /** * {@link PayClientFactoryImpl} 的集成测试 * @@ -43,6 +45,7 @@ public class PayClientFactoryImplIntegrationTest { Long channelId = RandomUtil.randomLong(); payClientFactory.createOrUpdatePayClient(channelId, PayChannelEnum.WX_PUB.getCode(), config); PayClient client = payClientFactory.getPayClient(channelId); + assertNotNull(client); // 发起支付 PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(); // CommonResult result = client.unifiedOrder(reqDTO); @@ -66,6 +69,7 @@ public class PayClientFactoryImplIntegrationTest { Long channelId = RandomUtil.randomLong(); payClientFactory.createOrUpdatePayClient(channelId, PayChannelEnum.WX_PUB.getCode(), config); PayClient client = payClientFactory.getPayClient(channelId); + assertNotNull(client); // 发起支付 PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(); // CommonResult result = client.unifiedOrder(reqDTO); @@ -89,6 +93,7 @@ public class PayClientFactoryImplIntegrationTest { Long channelId = RandomUtil.randomLong(); payClientFactory.createOrUpdatePayClient(channelId, PayChannelEnum.ALIPAY_QR.getCode(), config); PayClient client = payClientFactory.getPayClient(channelId); + assertNotNull(client); // 发起支付 PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(); reqDTO.setNotifyUrl("http://yunai.natapp1.cc/admin-api/pay/notify/callback/18"); // TODO @tina: 这里改成你的 natapp 回调地址 @@ -113,6 +118,7 @@ public class PayClientFactoryImplIntegrationTest { Long channelId = RandomUtil.randomLong(); payClientFactory.createOrUpdatePayClient(channelId, PayChannelEnum.ALIPAY_WAP.getCode(), config); PayClient client = payClientFactory.getPayClient(channelId); + assertNotNull(client); // 发起支付 PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(); // CommonResult result = client.unifiedOrder(reqDTO); diff --git a/cf-framework/cf-spring-boot-starter-biz-pay/src/test/java/com/cf/imes/framework/pay/core/client/impl/weixin/WxBarPayClientIntegrationTest.java b/cf-framework/cf-spring-boot-starter-biz-pay/src/test/java/com/cf/imes/framework/pay/core/client/impl/weixin/WxBarPayClientIntegrationTest.java index ee38d68c8..e2c739b7f 100644 --- a/cf-framework/cf-spring-boot-starter-biz-pay/src/test/java/com/cf/imes/framework/pay/core/client/impl/weixin/WxBarPayClientIntegrationTest.java +++ b/cf-framework/cf-spring-boot-starter-biz-pay/src/test/java/com/cf/imes/framework/pay/core/client/impl/weixin/WxBarPayClientIntegrationTest.java @@ -18,6 +18,8 @@ import org.junit.jupiter.api.Test; import java.time.Duration; +import static org.junit.jupiter.api.Assertions.assertNotNull; + /** * {@link WxBarPayClient} 的集成测试,用于快速调试微信条码支付 * @@ -48,6 +50,8 @@ public class WxBarPayClientIntegrationTest { System.out.println(JsonUtils.toJsonPrettyString(request)); WxPayMicropayResult response = client.micropay(request); System.out.println("========= response =========="); + assertNotNull(response); + assertNotNull(response.getTransactionId()); System.out.println(JsonUtils.toJsonPrettyString(response)); } @@ -62,6 +66,7 @@ public class WxBarPayClientIntegrationTest { // 执行解析 String xml = "SUCCESS"; WxPayRefundNotifyResult response = client.parseRefundNotifyResult(xml); + assertNotNull(response.getReqInfo().getTransactionId()); System.out.println(response.getReqInfo()); } @@ -84,6 +89,7 @@ public class WxBarPayClientIntegrationTest { System.out.println(JsonUtils.toJsonPrettyString(request)); WxPayRefundResult response = client.refund(request); System.out.println("========= response =========="); + assertNotNull(response.getTransactionId()); System.out.println(JsonUtils.toJsonPrettyString(response)); } @@ -105,6 +111,7 @@ public class WxBarPayClientIntegrationTest { System.out.println(JsonUtils.toJsonPrettyString(request)); WxPayRefundV3Result response = client.refundV3(request); System.out.println("========= response =========="); + assertNotNull(response.getTransactionId()); System.out.println(JsonUtils.toJsonPrettyString(response)); } diff --git a/cf-framework/cf-spring-boot-starter-biz-pay/src/test/java/com/cf/imes/framework/pay/core/client/impl/weixin/WxNativePayClientIntegrationTest.java b/cf-framework/cf-spring-boot-starter-biz-pay/src/test/java/com/cf/imes/framework/pay/core/client/impl/weixin/WxNativePayClientIntegrationTest.java index 35141fab4..cbc3e5a25 100644 --- a/cf-framework/cf-spring-boot-starter-biz-pay/src/test/java/com/cf/imes/framework/pay/core/client/impl/weixin/WxNativePayClientIntegrationTest.java +++ b/cf-framework/cf-spring-boot-starter-biz-pay/src/test/java/com/cf/imes/framework/pay/core/client/impl/weixin/WxNativePayClientIntegrationTest.java @@ -15,6 +15,8 @@ import org.junit.jupiter.api.Test; import java.time.Duration; +import static org.junit.jupiter.api.Assertions.assertNotNull; + /** * {@link WxNativePayClient} 的集成测试,用于快速调试微信扫码支付 * @@ -43,6 +45,7 @@ public class WxNativePayClientIntegrationTest { System.out.println(JsonUtils.toJsonPrettyString(request)); String response = client.createOrderV3(TradeTypeEnum.NATIVE, request); System.out.println("========= response =========="); + assertNotNull(response); System.out.println(JsonUtils.toJsonPrettyString(response)); } @@ -64,6 +67,7 @@ public class WxNativePayClientIntegrationTest { System.out.println(JsonUtils.toJsonPrettyString(request)); WxPayRefundV3Result response = client.refundV3(request); System.out.println("========= response =========="); + assertNotNull(response.getTransactionId()); System.out.println(JsonUtils.toJsonPrettyString(response)); } diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/SmsClient.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/SmsClient.java index 0ee4eeba4..a3b20c62a 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/SmsClient.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/SmsClient.java @@ -1,6 +1,6 @@ package com.cf.imes.framework.sms.core.client; -import com.cf.imes.framework.common.core.KeyValue; +import cn.hutool.core.lang.Pair; import com.cf.imes.framework.sms.core.client.dto.SmsReceiveRespDTO; import com.cf.imes.framework.sms.core.client.dto.SmsSendRespDTO; import com.cf.imes.framework.sms.core.client.dto.SmsTemplateRespDTO; @@ -24,7 +24,7 @@ public interface SmsClient { * @return 短信发送结果 */ SmsSendRespDTO sendSms(Long logId, String mobile, String apiTemplateId, - List> templateParams) throws Throwable; + List> templateParams) throws Throwable; /** * 解析接收短信的接收结果 diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java index 37c1e8a9b..cc158a0a1 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java @@ -1,9 +1,9 @@ package com.cf.imes.framework.sms.core.client.impl.aliyun; import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.Pair; import cn.hutool.core.util.ObjectUtil; import com.aliyuncs.auth.Credential; -import com.cf.imes.framework.common.core.KeyValue; import com.cf.imes.framework.common.util.collection.MapUtils; import com.cf.imes.framework.common.util.json.JsonUtils; import com.cf.imes.framework.sms.core.client.dto.SmsReceiveRespDTO; @@ -89,7 +89,7 @@ public class AliyunSmsClient extends AbstractSmsClient { @Override public SmsSendRespDTO sendSms(Long sendLogId, String mobile, String apiTemplateId, - List> templateParams) throws Throwable { + List> templateParams) throws Throwable { // 构建请求 SendSmsRequest request = new SendSmsRequest(); request.setPhoneNumbers(mobile); diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java index f91b4f525..0365e1277 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java @@ -2,13 +2,13 @@ package com.cf.imes.framework.sms.core.client.impl.debug; import cn.hutool.core.codec.Base64; import cn.hutool.core.lang.Assert; +import cn.hutool.core.lang.Pair; import cn.hutool.core.map.MapUtil; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.digest.DigestUtil; import cn.hutool.crypto.digest.HmacAlgorithm; import cn.hutool.http.HttpUtil; -import com.cf.imes.framework.common.core.KeyValue; import com.cf.imes.framework.common.util.collection.MapUtils; import com.cf.imes.framework.common.util.json.JsonUtils; import com.cf.imes.framework.sms.core.client.dto.SmsReceiveRespDTO; @@ -50,7 +50,7 @@ public class DebugDingTalkSmsClient extends AbstractSmsClient { @Override public SmsSendRespDTO sendSms(Long sendLogId, String mobile, - String apiTemplateId, List> templateParams) throws Throwable { + String apiTemplateId, List> templateParams) throws Throwable { // 构建请求 String url = buildUrl("robot/send"); Map params = new HashMap<>(); diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClient.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClient.java index 03301d7aa..9d49797fb 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClient.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/main/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClient.java @@ -1,8 +1,8 @@ package com.cf.imes.framework.sms.core.client.impl.tencent; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.StrUtil; -import com.cf.imes.framework.common.core.KeyValue; +import cn.hutool.core.lang.Pair; +import cn.hutool.core.text.CharSequenceUtil; import com.cf.imes.framework.common.util.collection.ArrayUtils; import com.cf.imes.framework.common.util.json.JsonUtils; import com.cf.imes.framework.sms.core.client.dto.SmsReceiveRespDTO; @@ -91,16 +91,16 @@ public class TencentSmsClient extends AbstractSmsClient { } private String getSdkAppId() { - return StrUtil.subAfter(properties.getApiKey(), " ", true); + return CharSequenceUtil.subAfter(properties.getApiKey(), " ", true); } private String getApiKey() { - return StrUtil.subBefore(properties.getApiKey(), " ", true); + return CharSequenceUtil.subBefore(properties.getApiKey(), " ", true); } @Override public SmsSendRespDTO sendSms(Long sendLogId, String mobile, - String apiTemplateId, List> templateParams) throws Throwable { + String apiTemplateId, List> templateParams) throws Throwable { // 构建请求 SendSmsRequest request = new SendSmsRequest(); request.setSmsSdkAppId(getSdkAppId()); diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java index 1fce4400b..96e2ea1f6 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java @@ -1,7 +1,7 @@ package com.cf.imes.framework.sms.core.client.impl.aliyun; +import cn.hutool.core.lang.Pair; import cn.hutool.core.util.ReflectUtil; -import com.cf.imes.framework.common.core.KeyValue; import com.cf.imes.framework.common.util.collection.MapUtils; import com.cf.imes.framework.sms.core.client.dto.SmsReceiveRespDTO; import com.cf.imes.framework.sms.core.client.dto.SmsSendRespDTO; @@ -65,8 +65,8 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { Long sendLogId = randomLongId(); String mobile = randomString(); String apiTemplateId = randomString(); - List> templateParams = Lists.newArrayList( - new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); + List> templateParams = Lists.newArrayList( + new Pair<>("code", 1234), new Pair<>("op", "login")); // mock 方法 SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> o.setCode("OK")); when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { @@ -95,8 +95,8 @@ public class AliyunSmsClientTest extends BaseMockitoUnitTest { Long sendLogId = randomLongId(); String mobile = randomString(); String apiTemplateId = randomString(); - List> templateParams = Lists.newArrayList( - new KeyValue<>("code", 1234), new KeyValue<>("op", "login")); + List> templateParams = Lists.newArrayList( + new Pair<>("code", 1234), new Pair<>("op", "login")); // mock 方法 SendSmsResponse response = randomPojo(SendSmsResponse.class, o -> o.setCode("ERROR")); when(client.getAcsResponse(argThat((ArgumentMatcher) acsRequest -> { diff --git a/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java b/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java index 2833228c0..004eee6d3 100644 --- a/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java +++ b/cf-framework/cf-spring-boot-starter-biz-sms/src/test/java/com/cf/imes/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java @@ -1,7 +1,7 @@ package com.cf.imes.framework.sms.core.client.impl.tencent; +import cn.hutool.core.lang.Pair; import cn.hutool.core.util.ReflectUtil; -import com.cf.imes.framework.common.core.KeyValue; import com.cf.imes.framework.common.util.collection.ArrayUtils; import com.cf.imes.framework.common.util.collection.MapUtils; import com.cf.imes.framework.common.util.json.JsonUtils; @@ -80,8 +80,8 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { Long sendLogId = randomLongId(); String mobile = randomString(); String apiTemplateId = randomString(); - List> templateParams = Lists.newArrayList( - new KeyValue<>("1", 1234), new KeyValue<>("2", "login")); + List> templateParams = Lists.newArrayList( + new Pair<>("1", 1234), new Pair<>("2", "login")); String requestId = randomString(); String serialNo = randomString(); // mock 方法 @@ -121,8 +121,8 @@ public class TencentSmsClientTest extends BaseMockitoUnitTest { Long sendLogId = randomLongId(); String mobile = randomString(); String apiTemplateId = randomString(); - List> templateParams = Lists.newArrayList( - new KeyValue<>("1", 1234), new KeyValue<>("2", "login")); + List> templateParams = Lists.newArrayList( + new Pair<>("1", 1234), new Pair<>("2", "login")); String requestId = randomString(); String serialNo = randomString(); // mock 方法 diff --git a/cf-framework/cf-spring-boot-starter-file/src/test/java/com/cf/imes/framework/file/core/client/ftp/FtpFileClientTest.java b/cf-framework/cf-spring-boot-starter-file/src/test/java/com/cf/imes/framework/file/core/client/ftp/FtpFileClientTest.java index 9ef045297..08b93859e 100644 --- a/cf-framework/cf-spring-boot-starter-file/src/test/java/com/cf/imes/framework/file/core/client/ftp/FtpFileClientTest.java +++ b/cf-framework/cf-spring-boot-starter-file/src/test/java/com/cf/imes/framework/file/core/client/ftp/FtpFileClientTest.java @@ -6,6 +6,8 @@ import cn.hutool.extra.ftp.FtpMode; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertNotNull; + public class FtpFileClientTest { @Test @@ -21,11 +23,13 @@ public class FtpFileClientTest { config.setPassword(""); config.setMode(FtpMode.Passive.name()); FtpFileClient client = new FtpFileClient(0L, config); + assertNotNull(client); client.init(); // 上传文件 String path = IdUtil.fastSimpleUUID() + ".jpg"; byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); String fullPath = client.upload(content, path, "image/jpeg"); + assertNotNull(fullPath); System.out.println("访问地址:" + fullPath); if (false) { byte[] bytes = client.getContent(path); diff --git a/cf-framework/cf-spring-boot-starter-file/src/test/java/com/cf/imes/framework/file/core/client/local/LocalFileClientTest.java b/cf-framework/cf-spring-boot-starter-file/src/test/java/com/cf/imes/framework/file/core/client/local/LocalFileClientTest.java index cca90a1b0..a36ba2e16 100644 --- a/cf-framework/cf-spring-boot-starter-file/src/test/java/com/cf/imes/framework/file/core/client/local/LocalFileClientTest.java +++ b/cf-framework/cf-spring-boot-starter-file/src/test/java/com/cf/imes/framework/file/core/client/local/LocalFileClientTest.java @@ -5,6 +5,8 @@ import cn.hutool.core.util.IdUtil; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertNotNull; + public class LocalFileClientTest { @Test @@ -15,11 +17,13 @@ public class LocalFileClientTest { config.setDomain("http://127.0.0.1:48080"); config.setBasePath("/Users/yunai/file_test"); LocalFileClient client = new LocalFileClient(0L, config); + assertNotNull(client); client.init(); // 上传文件 String path = IdUtil.fastSimpleUUID() + ".jpg"; byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); String fullPath = client.upload(content, path, "image/jpeg"); + assertNotNull(fullPath); System.out.println("访问地址:" + fullPath); client.delete(path); } diff --git a/cf-framework/cf-spring-boot-starter-file/src/test/java/com/cf/imes/framework/file/core/client/sftp/SftpFileClientTest.java b/cf-framework/cf-spring-boot-starter-file/src/test/java/com/cf/imes/framework/file/core/client/sftp/SftpFileClientTest.java index e5cbe9d8d..05656998c 100644 --- a/cf-framework/cf-spring-boot-starter-file/src/test/java/com/cf/imes/framework/file/core/client/sftp/SftpFileClientTest.java +++ b/cf-framework/cf-spring-boot-starter-file/src/test/java/com/cf/imes/framework/file/core/client/sftp/SftpFileClientTest.java @@ -5,6 +5,8 @@ import cn.hutool.core.util.IdUtil; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertNotNull; + public class SftpFileClientTest { @Test @@ -19,11 +21,13 @@ public class SftpFileClientTest { config.setUsername(""); config.setPassword(""); SftpFileClient client = new SftpFileClient(0L, config); + assertNotNull(client); client.init(); // 上传文件 String path = IdUtil.fastSimpleUUID() + ".jpg"; byte[] content = ResourceUtil.readBytes("file/erweima.jpg"); String fullPath = client.upload(content, path, "image/jpeg"); + assertNotNull(fullPath); System.out.println("访问地址:" + fullPath); if (false) { byte[] bytes = client.getContent(path); diff --git a/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/service/SecurityFrameworkServiceImpl.java b/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/service/SecurityFrameworkServiceImpl.java index 2e2486de9..6719c5450 100644 --- a/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/service/SecurityFrameworkServiceImpl.java +++ b/cf-framework/cf-spring-boot-starter-security/src/main/java/com/cf/imes/framework/security/core/service/SecurityFrameworkServiceImpl.java @@ -1,7 +1,7 @@ package com.cf.imes.framework.security.core.service; import cn.hutool.core.collection.CollUtil; -import com.cf.imes.framework.common.core.KeyValue; +import cn.hutool.core.lang.Pair; import com.cf.imes.framework.common.util.cache.CacheUtils; import com.cf.imes.framework.security.core.LoginUser; import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils; @@ -28,12 +28,12 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService { /** * 针对 {@link #hasAnyRoles(String...)} 的缓存 */ - private final LoadingCache>, Boolean> hasAnyRolesCache = CacheUtils.buildCache( + private final LoadingCache>, Boolean> hasAnyRolesCache = CacheUtils.buildCache( Duration.ofMinutes(1L), // 过期时间 1 分钟 - new CacheLoader>, Boolean>() { + new CacheLoader<>() { @Override - public Boolean load(KeyValue> key) { + public Boolean load(Pair> key) { return permissionApi.hasAnyRoles(key.getKey(), key.getValue().toArray(new String[0])).getCheckedData(); } @@ -42,12 +42,12 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService { /** * 针对 {@link #hasAnyPermissions(String...)} 的缓存 */ - private final LoadingCache>, Boolean> hasAnyPermissionsCache = CacheUtils.buildCache( + private final LoadingCache>, Boolean> hasAnyPermissionsCache = CacheUtils.buildCache( Duration.ofMinutes(1L), // 过期时间 1 分钟 - new CacheLoader>, Boolean>() { + new CacheLoader<>() { @Override - public Boolean load(KeyValue> key) { + public Boolean load(Pair> key) { Boolean checkedData = permissionApi.hasAnyPermissions(key.getKey(), key.getValue().toArray(new String[0])).getCheckedData(); return checkedData; } @@ -62,7 +62,7 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService { @Override @SneakyThrows public boolean hasAnyPermissions(String... permissions) { - return hasAnyPermissionsCache.get(new KeyValue<>(SecurityFrameworkUtils.getLoginUserId(), Arrays.asList(permissions))); + return hasAnyPermissionsCache.get(new Pair<>(SecurityFrameworkUtils.getLoginUserId(), Arrays.asList(permissions))); } @Override @@ -78,13 +78,13 @@ public class SecurityFrameworkServiceImpl implements SecurityFrameworkService { @Override @SneakyThrows public boolean hasAnyRoles(String... roles) { - return hasAnyRolesCache.get(new KeyValue<>(SecurityFrameworkUtils.getLoginUserId(), Arrays.asList(roles))); + return hasAnyRolesCache.get(new Pair<>(SecurityFrameworkUtils.getLoginUserId(), Arrays.asList(roles))); } @Override @SneakyThrows public boolean hasAnyRoles(Long userId, String... roles) { - return hasAnyRolesCache.get(new KeyValue<>(userId, Arrays.asList(roles))); + return hasAnyRolesCache.get(new Pair<>(userId, Arrays.asList(roles))); } @Override diff --git a/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/jackson/config/ChenfengJacksonAutoConfiguration.java b/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/jackson/config/ChenfengJacksonAutoConfiguration.java index 90193e699..8f68414b1 100644 --- a/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/jackson/config/ChenfengJacksonAutoConfiguration.java +++ b/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/jackson/config/ChenfengJacksonAutoConfiguration.java @@ -2,9 +2,9 @@ package com.cf.imes.framework.jackson.config; import cn.hutool.core.collection.CollUtil; import com.cf.imes.framework.common.util.json.JsonUtils; +import com.cf.imes.framework.jackson.core.databind.CustomNumberSerializer; import com.cf.imes.framework.jackson.core.databind.LocalDateTimeDeserializer; import com.cf.imes.framework.jackson.core.databind.LocalDateTimeSerializer; -import com.cf.imes.framework.jackson.core.databind.NumberSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; @@ -31,8 +31,8 @@ public class ChenfengJacksonAutoConfiguration { SimpleModule simpleModule = new SimpleModule(); simpleModule // 新增 Long 类型序列化规则,数值超过 2^53-1,在 JS 会出现精度丢失问题,因此 Long 自动序列化为字符串类型 - .addSerializer(Long.class, NumberSerializer.INSTANCE) - .addSerializer(Long.TYPE, NumberSerializer.INSTANCE) + .addSerializer(Long.class, CustomNumberSerializer.CUSTOM_INSTANCE) + .addSerializer(Long.TYPE, CustomNumberSerializer.CUSTOM_INSTANCE) .addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE) .addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE) .addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE) diff --git a/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/jackson/core/databind/NumberSerializer.java b/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/jackson/core/databind/CustomNumberSerializer.java similarity index 78% rename from cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/jackson/core/databind/NumberSerializer.java rename to cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/jackson/core/databind/CustomNumberSerializer.java index 9bf886b0e..dc0b81966 100644 --- a/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/jackson/core/databind/NumberSerializer.java +++ b/cf-framework/cf-spring-boot-starter-web/src/main/java/com/cf/imes/framework/jackson/core/databind/CustomNumberSerializer.java @@ -14,14 +14,14 @@ import java.io.IOException; * @author 星语 */ @JacksonStdImpl -public class NumberSerializer extends com.fasterxml.jackson.databind.ser.std.NumberSerializer { +public class CustomNumberSerializer extends com.fasterxml.jackson.databind.ser.std.NumberSerializer { private static final long MAX_SAFE_INTEGER = 9007199254740991L; private static final long MIN_SAFE_INTEGER = -9007199254740991L; - public static final NumberSerializer INSTANCE = new NumberSerializer(Number.class); + public static final CustomNumberSerializer CUSTOM_INSTANCE = new CustomNumberSerializer(Number.class); - public NumberSerializer(Class rawType) { + public CustomNumberSerializer(Class rawType) { super(rawType); } diff --git a/cf-module-infra/cf-module-infra-biz/src/test/java/com/cf/imes/module/infra/service/DefaultDatabaseQueryTest.java b/cf-module-infra/cf-module-infra-biz/src/test/java/com/cf/imes/module/infra/service/DefaultDatabaseQueryTest.java index 240e0ed83..23193eeeb 100644 --- a/cf-module-infra/cf-module-infra-biz/src/test/java/com/cf/imes/module/infra/service/DefaultDatabaseQueryTest.java +++ b/cf-module-infra/cf-module-infra-biz/src/test/java/com/cf/imes/module/infra/service/DefaultDatabaseQueryTest.java @@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.generator.config.po.TableInfo; import java.util.List; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + public class DefaultDatabaseQueryTest { public static void main(String[] args) { @@ -23,6 +25,7 @@ public class DefaultDatabaseQueryTest { long time = System.currentTimeMillis(); List tableInfos = query.queryTables(); + assertNotEquals(0, tableInfos.size()); for (TableInfo tableInfo : tableInfos) { if (StrUtil.startWithAny(tableInfo.getName().toLowerCase(), "act_", "flw_", "qrtz_")) { continue; @@ -30,6 +33,7 @@ public class DefaultDatabaseQueryTest { System.out.println(String.format("CREATE SEQUENCE %s_seq MINVALUE 1;", tableInfo.getName())); // System.out.println(String.format("DELETE FROM %s WHERE deleted = '1';", tableInfo.getName())); } + System.out.println(tableInfos.size()); System.out.println(System.currentTimeMillis() - time); } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java index 3a8fbb9d8..d4b1a2ea0 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/main/java/com/cf/imes/module/executor/service/order/OrderServiceImpl.java @@ -58,6 +58,7 @@ import com.cf.imes.module.executor.util.fileConversion.admin.files.excel.ExcelTy import com.cf.imes.module.executor.util.fileConversion.admin.files.excel.OrderPlateImportExcelVO; import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.VO.OrderXmlVO; import com.cf.imes.module.executor.util.fileConversion.admin.files.xml.XmlTypeRealize; +import org.apache.commons.io.IOUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; @@ -663,6 +664,7 @@ public class OrderServiceImpl implements OrderService { @Override public void exportTemplate(HttpServletResponse response, String value) { // 根据type获取文件名称 + InputStream fis = null; try { // path是指想要下载的文件的路径 File file = new File(getSavePath() + File.separator + value); @@ -673,7 +675,7 @@ public class OrderServiceImpl implements OrderService { // 将文件写入输入流 FileInputStream fileInputStream = new FileInputStream(file); - InputStream fis = new BufferedInputStream(fileInputStream); + fis = new BufferedInputStream(fileInputStream); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); @@ -688,6 +690,8 @@ public class OrderServiceImpl implements OrderService { outputStream.flush(); } catch (IOException ex) { ex.printStackTrace(); + } finally { + IOUtils.closeQuietly(fis); } } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/goods/GoodsServiceImplTest.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/goods/GoodsServiceImplTest.java index 4d6d0cc5d..c5fb74b31 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/goods/GoodsServiceImplTest.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/goods/GoodsServiceImplTest.java @@ -42,20 +42,6 @@ public class GoodsServiceImplTest extends BaseDbUnitTest { @Resource private GoodsMapper goodsMapper; - @Test - public void testCreateGoods_success() { -// // 准备参数 -// GoodsSaveReqVO createReqVO = randomPojo(GoodsSaveReqVO.class).setId(null); -// -// // 调用 -// Long goodsId = goodsService.createCorrespondsGoods(createReqVO); -// // 断言 -// assertNotNull(goodsId); -// // 校验记录的属性是否正确 -// GoodsDO goods = goodsMapper.selectById(goodsId); -// assertPojoEquals(createReqVO, goods, "id"); - } - @Test public void testUpdateGoods_success() { // mock 数据 @@ -105,74 +91,4 @@ public class GoodsServiceImplTest extends BaseDbUnitTest { assertServiceException(() -> goodsService.deleteGoods(id), GOODS_NOT_EXISTS); } - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetGoodsPage() { - /* // mock 数据 - GoodsDO dbGoods = randomPojo(GoodsDO.class, o -> { // 等会查询到 - o.setOrderId(null); - o.setGoodsId(null); - o.setGoodsName(null); - o.setMaterial(null); - o.setColor(null); - o.setWidth(null); - o.setHeight(null); - o.setThickness(null); - o.setPrice(null); - o.setBrand(null); - o.setSpec(null); - o.setRemark(null); - o.setCreateTime(null); - }); - goodsMapper.insert(dbGoods); - // 测试 orderNo 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setOrderId(null))); - // 测试 goodsId 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setGoodsId(null))); - // 测试 goodsName 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setGoodsName(null))); - // 测试 material 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setMaterial(null))); - // 测试 color 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setColor(null))); - // 测试 width 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setWidth(null))); - // 测试 height 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setHeight(null))); - // 测试 thickness 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setThickness(null))); - // 测试 price 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setPrice(null))); - // 测试 brand 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setBrand(null))); - // 测试 spec 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setSpec(null))); - // 测试 remark 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setRemark(null))); - // 测试 createTime 不匹配 - goodsMapper.insert(cloneIgnoreId(dbGoods, o -> o.setCreateTime(null))); - // 准备参数 - GoodsPageReqVO reqVO = new GoodsPageReqVO(); - reqVO.setOrderId(null); - reqVO.setGoodsId(null); - reqVO.setGoodsName(null); - reqVO.setMaterial(null); - reqVO.setColor(null); - reqVO.setWidth(null); - reqVO.setHeight(null); - reqVO.setThickness(null); - reqVO.setPrice(null); - reqVO.setBrand(null); - reqVO.setSpec(null); - reqVO.setRemark(null); - reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - - // 调用 - PageResult pageResult = goodsService.getGoodsPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbGoods, pageResult.getList().get(0));*/ - } - } \ No newline at end of file diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/plan/PlanServiceImplTest.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/plan/PlanServiceImplTest.java index 55402288a..041f2bd2c 100644 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/plan/PlanServiceImplTest.java +++ b/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/plan/PlanServiceImplTest.java @@ -1,8 +1,6 @@ package com.cf.imes.module.executor.service.plan; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; import javax.annotation.Resource; @@ -11,23 +9,12 @@ import com.cf.imes.framework.test.core.ut.BaseDbUnitTest; import com.cf.imes.module.executor.controller.admin.plan.vo.*; import com.cf.imes.module.executor.dal.dataobject.plan.PlanDO; import com.cf.imes.module.executor.dal.mysql.plan.PlanMapper; -import com.cf.imes.framework.common.pojo.PageResult; -import javax.annotation.Resource; import org.springframework.context.annotation.Import; -import java.util.*; -import java.time.LocalDateTime; -import static cn.hutool.core.util.RandomUtil.*; import static com.cf.imes.module.executor.enums.ErrorCodeConstants.*; import static com.cf.imes.framework.test.core.util.AssertUtils.*; import static com.cf.imes.framework.test.core.util.RandomUtils.*; -import static com.cf.imes.framework.common.util.date.LocalDateTimeUtils.*; -import static com.cf.imes.framework.common.util.object.ObjectUtils.*; -import static com.cf.imes.framework.common.util.date.DateUtils.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - /** * {@link PlanServiceImpl} 的单元测试类 * @@ -42,20 +29,6 @@ public class PlanServiceImplTest extends BaseDbUnitTest { @Resource private PlanMapper planMapper; -// @Test -// public void testCreatePlan_success() { -// // 准备参数 -// PlanSaveReqVO createReqVO = randomPojo(PlanSaveReqVO.class).setId(null); -// -// // 调用 -// Long planId = planService.createPlan(createReqVO); -// // 断言 -// assertNotNull(planId); -// // 校验记录的属性是否正确 -// PlanDO plan = planMapper.selectById(planId); -// assertPojoEquals(createReqVO, plan, "id"); -// } - @Test public void testUpdatePlan_success() { // mock 数据 @@ -82,93 +55,4 @@ public class PlanServiceImplTest extends BaseDbUnitTest { assertServiceException(() -> planService.updatePlan(updateReqVO), PLAN_NOT_EXISTS); } -// @Test -// public void testDeletePlan_success() { -// // mock 数据 -// PlanDO dbPlan = randomPojo(PlanDO.class); -// planMapper.insert(dbPlan);// @Sql: 先插入出一条存在的数据 -// // 准备参数 -// Long id = dbPlan.getId(); -// -// // 调用 -// planService.deletePlan(id); -// // 校验数据不存在了 -// assertNull(planMapper.selectById(id)); -// } - -// @Test -// public void testDeletePlan_notExists() { -// // 准备参数 -// Long id = randomLongId(); -// -// // 调用, 并断言异常 -// assertServiceException(() -> planService.deletePlan(id), PLAN_NOT_EXISTS); -// } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetPlanPage() { - // // mock 数据 - // PlanDO dbPlan = randomPojo(PlanDO.class, o -> { // 等会查询到 - // o.setPlanNo(null); - // o.setSort(null); - // o.setType(null); - // o.setStatus(null); - // o.setIsPay(null); - // o.setMachineId(null); - // o.setPlanTime(null); - // o.setOrderNos(null); - // o.setRemark(null); - // o.setCreateTime(null); - // o.setOperator(null); - // o.setProduceTime(null); - // }); - // planMapper.insert(dbPlan); - // // 测试 planNo 不匹配 - // planMapper.insert(cloneIgnoreId(dbPlan, o -> o.setPlanNo(null))); - // // 测试 sort 不匹配 - // planMapper.insert(cloneIgnoreId(dbPlan, o -> o.setSort(null))); - // // 测试 type 不匹配 - // planMapper.insert(cloneIgnoreId(dbPlan, o -> o.setType(null))); - // // 测试 status 不匹配 - // planMapper.insert(cloneIgnoreId(dbPlan, o -> o.setStatus(null))); - // // 测试 isPay 不匹配 - // planMapper.insert(cloneIgnoreId(dbPlan, o -> o.setIsPay(null))); - // // 测试 machineId 不匹配 - // planMapper.insert(cloneIgnoreId(dbPlan, o -> o.setMachineId(null))); - // // 测试 planTime 不匹配 - // planMapper.insert(cloneIgnoreId(dbPlan, o -> o.setPlanTime(null))); - // // 测试 orderNos 不匹配 - // planMapper.insert(cloneIgnoreId(dbPlan, o -> o.setOrderNos(null))); - // // 测试 remark 不匹配 - // planMapper.insert(cloneIgnoreId(dbPlan, o -> o.setRemark(null))); - // // 测试 createTime 不匹配 - // planMapper.insert(cloneIgnoreId(dbPlan, o -> o.setCreateTime(null))); - // // 测试 operator 不匹配 - // planMapper.insert(cloneIgnoreId(dbPlan, o -> o.setOperator(null))); - // // 测试 produceTime 不匹配 - // planMapper.insert(cloneIgnoreId(dbPlan, o -> o.setProduceTime(null))); - // // 准备参数 - // PlanPageReqVO reqVO = new PlanPageReqVO(); - // reqVO.setPlanNo(null); - // reqVO.setSort(null); - // reqVO.setType(null); - // reqVO.setStatus(null); - // reqVO.setIsPay(null); - // reqVO.setMachineId(null); - // reqVO.setPlanTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - // reqVO.setOrderNos(null); - // reqVO.setRemark(null); - // reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - // reqVO.setOperator(null); - // reqVO.setProduceTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - - // // 调用 - // PageResult pageResult = planService.getPlanPage(reqVO); - // // 断言 - // assertEquals(1, pageResult.getTotal()); - // assertEquals(1, pageResult.getList().size()); - // assertPojoEquals(dbPlan, pageResult.getList().get(0)); - } - } diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/zlib/ZlibTest.java b/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/zlib/ZlibTest.java deleted file mode 100644 index 69b628d54..000000000 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/zlib/ZlibTest.java +++ /dev/null @@ -1,160 +0,0 @@ -package com.cf.imes.module.executor.service.zlib; - -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.IoUtil; -import cn.hutool.json.JSONObject; -import com.alibaba.druid.pool.DruidDataSource; -import com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.handler.codec.compression.JdkZlibDecoder; -import com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.handler.codec.compression.ZlibDecoder; -import com.cf.imes.module.executor.util.CompressTest; -import com.cf.imes.module.executor.util.ZLibUtils; -import lombok.Data; -import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.core.io.Resource; -import org.springframework.http.*; -import org.springframework.jdbc.core.BeanPropertyRowMapper; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; - -import java.io.*; -import java.net.URI; -import java.sql.PreparedStatement; -import java.time.LocalDateTime; -import java.util.*; -import java.util.zip.Inflater; - -public class ZlibTest { - - private JdbcTemplate jdbcTemplate; - - @BeforeEach - public void init() { - DruidDataSource druidDataSource = new DruidDataSource(); - druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); - druidDataSource.setUrl("jdbc:mysql://192.168.1.245:3306/cferp_test_1"); - druidDataSource.setUsername("mes_visitor"); - druidDataSource.setPassword("cf123456"); - //创建jdbc模板对象 - JdbcTemplate jdbcTemplate = new JdbcTemplate(); - jdbcTemplate.setDataSource(druidDataSource); - this.jdbcTemplate = jdbcTemplate; - } - - @Test - void getOrderBoxBlock() throws IOException { - List list = jdbcTemplate.query("select * from order_box_block limit 10", new BeanPropertyRowMapper(OrderBoxBlock.class)); - for (OrderBoxBlock bean : list) { - if (!Objects.isNull(bean.Data)) { - byte[] bytes = Arrays.copyOfRange(bean.Data, 2, bean.Data.length - 1); - System.out.println( new String(bean.Data)); - System.out.println( CompressTest.uncompress(new String(bytes))); - //System.out.println(new String(ZLibUtils.decompress(bean.Data))); - System.err.println("------------------------------------------"); - } - } - } - - @Test - void getOrderBlockPlanResult() throws UnsupportedEncodingException { - List list = jdbcTemplate.query("select * from order_block_plan_result limit 1", new BeanPropertyRowMapper(OrderBlockPlanResult.class)); - for (OrderBlockPlanResult bean : list) { - if (!Objects.isNull(bean.PlaceData)) { - System.out.println(new String(ZLibUtils.decompress(bean.PlaceData))); - System.err.println("------------------------------------------"); - } - } - } - - @Test - void test() { - String source = "xxxxxxxxxxaassad"; - //压缩 - byte[] compress = ZLibUtils.compress(source.getBytes()); - String str = new String(compress); - System.out.println(str); - //解压 - System.out.println(new String(ZLibUtils.decompress(new ByteArrayInputStream(compress)))); - - - } - - public void insertByteArray(String tableName, byte[] data, String columnName) { - final String sql = "INSERT INTO " + tableName + " (" + columnName + ") VALUES (?)"; - jdbcTemplate.update( - conn -> { - PreparedStatement ps = conn.prepareStatement(sql); - ps.setBinaryStream(1, new ByteArrayInputStream(data), data.length); - return ps; - } - ); - } - - - public static String uncompress(byte[] input) throws IOException { - Inflater inflater = new Inflater(); - inflater.setInput(input); - ByteArrayOutputStream baos = new ByteArrayOutputStream(input.length); - try { - byte[] buff = new byte[1024]; - while (!inflater.finished()) { - int count = inflater.inflate(buff); - baos.write(buff, 0, count); - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - baos.close(); - } - inflater.end(); - byte[] output = baos.toByteArray(); - return new String(output, "UTF-8"); - } - - - @Data - public static class OrderBoxBlock { - long BoxID; - long ShardKey; - long OrderNo; - byte[] Data; - long CompanyID; - } - - @Data - public static class OrderBlockPlanResult { - long ID; - LocalDateTime SaveTime; - byte[] PlaceData; - long CompanyID; - } - - @Test - void getRes() throws IOException { - //创建url路径 - String url = "https://chenfeng.tech:777/api/v1/OrderBlockPlan/GetPlanOrderData"; - RestTemplate restTemplate = new RestTemplate(); - HttpHeaders headers = new HttpHeaders(); - MultiValueMap map = new LinkedMultiValueMap<>(); - //接口参数 - map.add("id",1306667105); - //头部类型 - headers.set("Cookie", ".AspNetCore.Cookies=CfDJ8CGzP7BhamtAnTFO8HhkPcxGBkdd4sCOIjQMV-nb37GAFKr4y6C0JA0B3JzRsDAckabiUgBXQaWyDNjCqVTvBNYwbHwVbI5b-eKdXwkIFqsJZObZA-RoLdsu1d9yy1LwBLQwJxDGKTSQzFtrs_eHDeDEuG8CWEF1Iq96X0goR_cFMn0EHWVeRnOlThmDzLkmTMhysVSludR6qV0HrD54GOv5MQvBzzcE-WlsrKTo5Uf0hT8z1fGMY8Hofa6UDh8yyJsz2LFTQTy4NpmklvyXIkwv0fw9bOynHLllUh5ToF0wgrxYFU3Rzgf863uAdtfRP1DY2Rqvf-51uvQHip-SIT_b5p7TaSRiG-M7pZTlI0oOVPZRhng7k-NeIJRdYQmj0h3G3WJHCTH7g1-YQjAGbYQkJFcZdAsZpR-kjOlp3sHpNCDUe0NucYrLNp4tTXesCL_-t8X5GsXMYGlX-oKU10I"); - //构造实体对象 - HttpEntity> param = new HttpEntity<>(map, headers); - //发起请求,服务地址,请求参数,返回消息体的数据类型 - ResponseEntity response = restTemplate.postForEntity(url, param, Resource.class); - //body - InputStream inputStream = response.getBody().getInputStream(); - BufferedOutputStream out = FileUtil.getOutputStream("C:\\Users\\Beal\\Desktop\\新建文件夹\\xx.txt"); - long copySize = IoUtil.copy(inputStream, out, IoUtil.DEFAULT_BUFFER_SIZE); - IoUtil.close(inputStream); - IoUtil.close(out); - - - } -} diff --git a/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/zlib/order_block_plan_result.json b/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/zlib/order_block_plan_result.json deleted file mode 100644 index 7d894303d..000000000 --- a/cf-module-prod-executor/cf-module-prod-executor-biz/src/test/java/com/cf/imes/module/executor/service/zlib/order_block_plan_result.json +++ /dev/null @@ -1,3637 +0,0 @@ -{ - "OrgData": { - "AreaID": 3755, - "AreaName": "开料机台", - "PlanOrder": { - "ID": 131360, - "WorkAreaID": 3755, - "PlanCode": "O20220701022805", - "CreateTime": "2022-07-27T09:57:25", - "CreatorID": 79, - "State": 0, - "PlanTime": "2022-07-27T09:57:25", - "CompanyID": 818, - "Remark": "", - "IsSelected": true - }, - "MetrialList": [ - { - "OrderNo": "O20220701022805", - "GoodsID": 997, - "GoodsName": "测试", - "Specification": "11", - "Metrial": "188", - "Color": "腾拓9-50#", - "Brank": "11", - "Width": 3000, - "Length": 4000, - "Thickness": 18, - "Border": 3, - "CutDia": 8, - "CutGap": 1, - "IsSorted": true, - "BoardCount": 1, - "MinBoardID": 1, - "MaxBoardID": 1, - "AvgLyr_All": 7.288800000000001, - "AvgLyr_NoLastOne": 7.288800000000001, - "Lyr_LastOne": 7.288800000000001, - "CompanyID": 0, - "UsedBoardMessage": [ - { - "Bi": 1, - "W": 3000, - "L": 4000, - "Si": 0, - "So": "", - "No": "", - "LK": false, - "scrapPts": null, - "scrapBlocks": [] - } - ], - "BlockPlaceMessage": [ - { - "Bi": 1, - "Bo": "220708337474", - "X": 2010, - "Y": 3, - "Pi": 2, - "Ps": 0, - "Ci": 3, - "Ca": 0, - "CP": 0, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337475", - "X": 3, - "Y": 3, - "Pi": 1, - "Ps": 7, - "Ci": 9, - "Ca": 0, - "CP": 1, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337476", - "X": 610, - "Y": 1217, - "Pi": 5, - "Ps": 1, - "Ci": 5, - "Ca": 0, - "CP": 2, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337477", - "X": 1781, - "Y": 2010, - "Pi": 8, - "Ps": 7, - "Ci": 1, - "Ca": 0, - "CP": 3, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337478", - "X": 610, - "Y": 2431, - "Pi": 9, - "Ps": 0, - "Ci": 2, - "Ca": 0, - "CP": 2, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337479", - "X": 3, - "Y": 610, - "Pi": 3, - "Ps": 4, - "Ci": 8, - "Ca": 0, - "CP": 0, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337480", - "X": 3, - "Y": 1781, - "Pi": 6, - "Ps": 0, - "Ci": 6, - "Ca": 0, - "CP": 1, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337481", - "X": 610, - "Y": 610, - "Pi": 4, - "Ps": 7, - "Ci": 7, - "Ca": 0, - "CP": 3, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337482", - "X": 610, - "Y": 1824, - "Pi": 7, - "Ps": 1, - "Ci": 4, - "Ca": 0, - "CP": 2, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - } - ], - "State": 0, - "HasWave": false, - "OrgWidth": 3000, - "OrgLength": 4000, - "BoardCount_Remain": 0, - "RemainBoardMessage": "[]", - "ScrapBoardList": [] - } - ], - "OrderList": [ - { - "CustomerID": 8014, - "CustomerName": "典佳的店铺", - "CustomerPhone": "15396058598", - "SaleDate": "2022-07-01T10:34:28", - "SalePersonNo": 79, - "Consignee": "1", - "ConsigneePhone": "11111111111", - "ConsigneeAddress": "1", - "OrderState": 4, - "OrderMoney": 140.16, - "Remark": "", - "CustomOrderNo": "", - "DeliveryDate": "2022-07-21T00:00:00", - "PushConfig": false, - "OfferListStr": null, - "CancelState": 0, - "ItemList": null, - "GoodsList": null, - "OfferList": null, - "TotalOrderOfferList": null, - "BlockList": null, - "DataBlockList": null, - "ObjectList": null, - "DataObjectList": null, - "GoodsInfoList": null, - "OrderProcessList": null, - "EditFun": { - "customer": 1 - }, - "SalePerson": "dj", - "OrderNo": 20220701022805, - "CreateTime": "2022-07-01T10:34:28", - "CompanyID": 818, - "SchduleDeliveryDate": "0001-01-01T00:00:00", - "OrderType": 2, - "OrderSort": 0, - "CadDataType": 0, - "Deleted": false, - "ProcessState": null - } - ], - "ConfigList": [ - { - "Type": 1, - "Setting": { - "UseWorkPanelSize": false, - "BoardWidth": 4008, - "BoardLength": 4008, - "BoardSizeList": [ - { - "width": 3800, - "length": 3800, - "name": "未命名", - "isDefault": true - }, - { - "width": 122, - "length": 244, - "name": "未命名", - "isDefault": false - } - ], - "BoardBorder": 3, - "BoardBorder_B": 3, - "CutBorderOff1": 0, - "CutBorderOff2": 0, - "KnifeDia": 6, - "CutGap": 1, - "OriginPointPosition": 0, - "WidthSideAxis": 0, - "LengthSideAxis": 2, - "LocatorPosition": 0, - "UseLocator4Place": false, - "OffsetX_Board1": 0, - "OffsetY_Board1": 0, - "LocatorPosition_Block": 0, - "OffsetX_Block": 0, - "OffsetY_Block": 0, - "scrapBlockSquare": 200, - "srcapBlockWidthMin": 100, - "scrapBlockWidthMax": 600, - "FreeHeight": 40, - "FreeLocationX": 0, - "FreeLocationY": 2440, - "FreeSpeed": 15000, - "WorkStartHeight": 0, - "WorkStartSpeed": 3000, - "WorkStartDistance": 25, - "WorkPreDistance": 5, - "WorkSpeed": 10000, - "WorkCornerSpeed": 3000, - "WorkEndSpeed": 3000, - "WorkEndDistace": 35, - "sameBorderHighSpeed": 0, - "innerCornerDistence": 0, - "innerCornerSpeed": 3000, - "HoleFreeSpeed": 5000, - "HoleFirstDepth": 0, - "HoleFirstSpeed": 800, - "HoleSpeed": 1200, - "ModelSpeed": 8000, - "AllowDoubleHoleFirstSort": true, - "ShowDoubleHoleFirst4Place": false, - "AutoSortingMinWidth": 200, - "FirstCutBorderInFaceB": true, - "TongHoleOnlyOneTime": false, - "TongHoleUseTwoTime": false, - "AllowDoubleSplit": true, - "SplitDepth": 18, - "LimitDouleSplit": false, - "DoubleSplitWidth": 100, - "DoubleSplitLength": 100, - "SplitBlockSeqIds": "", - "UseSecondKnifeBlockWidth": 0, - "UseSecondKnifeBlockLength": 0, - "UseDianZiJuMethod": false, - "DisposeCutBlock": false, - "ThroughModelSkewCutLength": 0, - "UseNewKnifeModule": true, - "KnifeIDForHole": 1, - "Knifes4Hole": "1,", - "ModelKnifeGroup": [], - "KnifeList": [ - { - "KnifeID": 1, - "KnifeName": "T1", - "AxleID": 0, - "AllowCut": true, - "AllowHole": false, - "AllowModel": true, - "AllowPrevRun": false, - "Diameter": 8, - "Diameter2": 0, - "Length": 40, - "GroupType": "", - "OffsetX": 0, - "OffsetY": 0, - "OffsetZ": 0, - "VKnifAngle": 0, - "Speed": 0, - "PushDepthIncres": "", - "RunCode": "", - "SwitchCode": "G80nT0nM15nG79 Z0nM06 T1nM03 S18000nM53nM49n;h1", - "StopCode": "", - "IsAdvanceHole": false, - "RePlaceKnifeID": 0, - "AdvanceHoleCode": "", - "AdvanceHolePoints": [], - "IsAdvanceHoleGroup": false, - "IsOutBlockDown": false - }, - { - "KnifeID": 2, - "KnifeName": "T2", - "AxleID": 0, - "AllowCut": true, - "AllowHole": false, - "AllowModel": true, - "AllowPrevRun": false, - "Diameter": 4, - "Diameter2": 0, - "Length": 40, - "GroupType": "", - "OffsetX": 0, - "OffsetY": 0, - "OffsetZ": 0, - "VKnifAngle": 0, - "Speed": 0, - "PushDepthIncres": "", - "RunCode": "", - "SwitchCode": "G80nT0nM15nG79 Z0nM06 T2nM03 S18000nM53nM49n;h2", - "StopCode": "", - "IsAdvanceHole": false, - "RePlaceKnifeID": 0, - "AdvanceHoleCode": "", - "AdvanceHolePoints": [], - "IsAdvanceHoleGroup": false, - "IsOutBlockDown": false - }, - { - "KnifeID": 3, - "KnifeName": "T3", - "AxleID": 0, - "AllowCut": true, - "AllowHole": false, - "AllowModel": true, - "AllowPrevRun": false, - "Diameter": 6, - "Diameter2": 0, - "Length": 40, - "GroupType": "", - "OffsetX": 0, - "OffsetY": 0, - "OffsetZ": 0, - "VKnifAngle": 0, - "Speed": 0, - "PushDepthIncres": "", - "RunCode": "", - "SwitchCode": "G80nT0nM15nG79 Z0nM06 T3nM03 S18000nM53nM49n;h3", - "StopCode": "", - "IsAdvanceHole": false, - "RePlaceKnifeID": 0, - "AdvanceHoleCode": "", - "AdvanceHolePoints": [], - "IsAdvanceHoleGroup": false, - "IsOutBlockDown": false - }, - { - "KnifeID": 4, - "KnifeName": "T4", - "AxleID": 0, - "AllowCut": true, - "AllowHole": false, - "AllowModel": true, - "AllowPrevRun": false, - "Diameter": 8, - "Diameter2": 0, - "Length": 40, - "GroupType": "", - "OffsetX": 0, - "OffsetY": 0, - "OffsetZ": 0, - "VKnifAngle": 0, - "Speed": 0, - "PushDepthIncres": "", - "RunCode": "", - "SwitchCode": "G80nT0nM15nG79 Z0nM06 T4nM03 S18000nM53nM49n;h4", - "StopCode": "", - "IsAdvanceHole": false, - "RePlaceKnifeID": 0, - "AdvanceHoleCode": "", - "AdvanceHolePoints": [], - "IsAdvanceHoleGroup": false, - "IsOutBlockDown": false - } - ], - "UseHelpCutKnife": false, - "HelpCutKnifeNo": 0, - "HelpCutKnifeDepth": 2, - "HelpCutKnifeWaitingCode": "", - "ExportOrderPathName": "{0}_{1}_{2}", - "ExportBoardPathName": "{0}_{2}_{3}", - "BoardFileA": "{0,#3}_Z.nc", - "BoardFileB": "{0,#3}_F.nc", - "BlockFile": "{0}.nc", - "NcFileHead": "@@function@@nlet pm =obj.thePlaceMetrial; nlet lines = [];nlet filename = `${ (1000 + obj.theBoardID).toFixed(0).substring(1)}_${obj.IsBackFace ?'F':'Z'}`;nlines.push( `;材料名称:${pm.Thickness}mm-${pm.Color}-${pm.Metral} 尺寸:${pm.Width}*${pm.Length}*${pm.Thickness}`);nlines.push( `;程序名:(${filename}-${pm.GoodsName})`);nlines.push( `;板材尺寸:${pm.Width}*${pm.Length}*${pm.Thickness}`);nlines.push( `;BCHD=${pm.Thickness}`);nlines.push( `;M405`);nlines.push( `#@PS=1`);nlines.push( `#@PE=1`);nlines.push( `G90`);nlines.push( `G40`);nlines.push( `G80`);nlines.push( `G79 Z0`);nlines.push( `T0`);nlines.push( `M52`);nlines.push( `(UAO,1)`);nreturn lines.join('rn');", - "NcFileEnd": ";t&nM05nM52nG79 Z0nM405n#@PS=0n#@PE=0nM02n", - "NcFileHead_B": "@@function@@nlet pm =obj.thePlaceMetrial; nlet lines = [];nlet filename = `${ (1000 + obj.theBoardID).toFixed(0).substring(1)}_${obj.IsBackFace ?'F':'Z'}`;nlines.push( `;材料名称:${pm.Thickness}mm-${pm.Color}-${pm.Metral} 尺寸:${pm.Width}*${pm.Length}*${pm.Thickness}`);nlines.push( `;程序名:(${filename}-${pm.GoodsName})`);nlines.push( `;板材尺寸:${pm.Width}*${pm.Length}*${pm.Thickness}`);nlines.push( `;BCHD=${pm.Thickness}`);nlines.push( `;M405`);nlines.push( `#@PS=1`);nlines.push( `#@PE=1`);nlines.push( `G90`);nlines.push( `G40`);nlines.push( `G80`);nlines.push( `G79 Z0`);nlines.push( `T0`);nlines.push( `M52`);nlines.push( `(UAO,1)`);nreturn lines.join('rn');", - "NcFileEnd_B": ";t&nM05nM52nG79 Z0nM405n#@PS=0n#@PE=0nM02n", - "NcFileHead_Block": "@@function@@nlet pm =obj.thePlaceMetrial; nlet lines = [];nlet filename = `${ (1000 + obj.theBoardID).toFixed(0).substring(1)}_${obj.IsBackFace ?'F':'Z'}`;nlines.push( `;材料名称:${pm.Thickness}mm-${pm.Color}-${pm.Metral} 尺寸:${pm.Width}*${pm.Length}*${pm.Thickness}`);nlines.push( `;程序名:(${filename}-${pm.GoodsName})`);nlines.push( `;板材尺寸:${pm.Width}*${pm.Length}*${pm.Thickness}`);nlines.push( `;BCHD=${pm.Thickness}`);nlines.push( `;M405`);nlines.push( `#@PS=1`);nlines.push( `#@PE=1`);nlines.push( `G90`);nlines.push( `G40`);nlines.push( `G80`);nlines.push( `G79 Z0`);nlines.push( `T0`);nlines.push( `M52`);nlines.push( `(UAO,1)`);nreturn lines.join('rn');", - "NcFileEnd_Block": ";t&nM05nM52nG79 Z0nM405n#@PS=0n#@PE=0nM02n", - "RegularBlockFilletCurve": false, - "UnregularBlockFilletCurve": true, - "DealCircleWithIJ": false, - "IsTurnOverG2G3": false, - "ArcLineMaxLength": 0, - "AllowNCComments": false, - "AllowAddGcodeEndChar": false, - "GcodeEndChar": "", - "NcFileIsGB2312": true, - "AllowExportNC_BackFace": true, - "OneBoardFile": false, - "AllowExportNC_block": false, - "AllowExportDataFile": true, - "AllowExportBoardDxf": false, - "isNcSimpleXYZ": false, - "showTwoWorkSpace": false, - "showChooseCutKnife": true, - "showPriorFacing": true, - "showAutoLoadBoard": false, - "showHoleGroup": false, - "showAutoNotePrinter": false, - "showCustomBlockNo": false, - "showMachine": false, - "AllowDoubleWorkSpace": false, - "SameOriginPointPosition": false, - "OffsetX_WorkNum2": 0, - "OffsetY_WorkNum2": 2600, - "OriginPointPosition2": 0, - "WidthSideAxis2": 0, - "LengthSideAxis2": 2, - "LocatorPosition2": 0, - "OffsetX_Board2": 0, - "OffsetY_Board2": 0, - "AllowCombineNCWithDoubleWorkSpace": false, - "CombineNCFileName": "{5}mm_{0}_{1}_{2}_{3}-{4}.nc", - "IsOddNumInWorkSpace1": true, - "IsHoleBlockInSpace1": true, - "NcFileHead_WorkSpace2": "", - "NcFileEnd_WorkSpace2": "", - "NcFileHead_B_WorkSpace2": "", - "NcFileEnd_B_WorkSpace2": "", - "AllowChangeCutKnifeWithThickness": true, - "AllowChangeCutKnifeWidthID": true, - "BoardKnifeList": [ - { - "Thickness": 25, - "KnifeDia": 4 - } - ], - "IsPriorFacing_RoleNum": 5, - "DisPloseHoleRole": false, - "IsIgnore_HolingModeling": true, - "IsForceHoling_MultiSide_Minimum": false, - "IgnoreValue_MultiSide_Minimum": 10, - "IsForceHoling_SingleSide_Minimum": false, - "IgnoreValue_SingleSide_Minimum": 10, - "IsForceHoling_SingleSide_Maximum": false, - "IgnoreValue_SingleSide_Maximum": 2440, - "IsForceHoling_MultiSide_Maximun": false, - "IgnoreValue_MultiSide_Maximun": 1220, - "IsForceHoling_UnRegularBlock": false, - "IsForceHoling_HasModel": false, - "IsIgnore_Modeling": true, - "doModel_hasModel": false, - "doModel_UnRegular": false, - "doModel_twoSmall": false, - "doModel_twoSmall_Value": 10, - "doModel_oneSmall": false, - "doModel_oneSmall_Value": 10, - "doModel_twoBig": false, - "doModel_twoBig_Value": 1220, - "doModel_oneBig": false, - "doModel_oneBig_Value": 2440, - "AllowChangeIgnore": true, - "IsFoceModeling_hasModel": false, - "IsFoceModeling_SameHoling": false, - "IsFoceModeling_MultiLine": false, - "IsForceModeling_Arc": false, - "IsForceModeling_Through": false, - "IsPriorFacing_KaiLiaoMian": false, - "IsPriorFacing_Reverse": false, - "IsPriorFacing_SingleModel": true, - "IsPriorFacing_SingleModel_Front": true, - "IsPriorFacing_DoubleModel": true, - "IsPriorFacing_DoubleModel_Front": true, - "IsPriorFacing_SingleHole": true, - "IsPriorFacing_SingleHole_Front": true, - "IsPriorFacing_BigHole": true, - "IsPriorFacing_BigHole_Front": true, - "IsPriorFacing_DoubleHole": true, - "IsPriorFacing_DoubleHole_More": true, - "IsPriorFacing_CustomFunction": "", - "wr6_OverRun_WdthS": 50, - "wr6_OverRun_WdthE": 1220, - "wr6_OverRun_LengthS": 50, - "wr6_OverRun_LengthE": 2440, - "wr6_OverRun_hasThroghModel": false, - "wr6_OverRun_hasThroghModel_r": 30, - "wr6_OverRun_hasThroghModel_size": 30, - "wr6_OverRun_UnRegular": false, - "wr6_OverRun_MaxChamferR": 0, - "wr6_OverRun_MaxInnerLength": 0, - "wr6_unModel_all": true, - "wr6_unModel_isThrogh": true, - "wr6_unModel_isArc": false, - "wr6_unModel_hasMulLines": false, - "wr6_unModel_checkRadius": false, - "wr6_unModel_isRadius": "", - "wr6_unModel_checkName": false, - "wr6_unModel_isName": "", - "wr6_unModel_checkDepth": false, - "wr6_unModel_isDepth": "", - "wr6_unModel_isVKnifeModel": true, - "wr6_unModel_is3VModell": true, - "wr6_unModel_isLaChao": false, - "wr6_unModel_notLaChao": false, - "wr6_laChao_maxWidth": 50, - "wr6_lachao_minLength": 100, - "wr6_unHole_all": true, - "wr6_unHole_checkRadius": false, - "wr6_unHole_isRadius": "", - "wr6_unHole_checkType": false, - "wr6_unHole_isType": "", - "wr6_unHole_checkDepth": false, - "wr6_unHole_isDepth": "", - "wr6_unHole_isNoHoleKnife": false, - "wr6_dragUndo_m2m": false, - "wr6_dragUndo_m2m_2face": false, - "wr6_dragUndo_m2h": false, - "wr6_dragUndo_m2h_2face": false, - "wr6_dragUndo_h2m": false, - "wr6_dragUndo_h2m_2face": false, - "wr6_dragUndo_h2h": false, - "wr6_dragUndo_h2h_2face": false, - "wr6_cncDo_modelR": false, - "wr6_cncDo_modelR_str": "", - "wr6_cncDo_modelD": false, - "wr6_cncDo_modelD_str": "", - "wr6_cncDo_holeR": false, - "wr6_cncDo_holeR_str": "", - "wr6_cncDo_holeD": false, - "wr6_cncDo_holeD_str": "", - "wr6_doStyle_1Face": 0, - "wr6_doStyle_1Face_hole": true, - "wr6_doStyle_1Face_model": true, - "wr6_doStyle_1Face_face": false, - "wr6_doStyle_1Face_pbm": false, - "wr6_doStyle_2Face": 0, - "wr6_doStyle_2Face_hole": true, - "wr6_doStyle_2Face_model": true, - "wr6_doStyle_2Face_role": "df,cn,mm,bh,mh", - "wr6_turnFace_roleSeq": "df,mm,bh,mh", - "wr6_CustomFun_use": false, - "wr6_CustomFun_text": "let canCheckBlock = false;rnlet canCheckModel = false;rnlet canCheckHole = false;rnlet canDoWith = false;rnlet canSplit = false;rnlet canDoFace = false;rnfunction checkBlock(obj) { return false; }rnfunction checkModel(obj) { return false; }rnfunction checkHole(obj) { return false; }rnfunction doWith(obj) { return; }rnfunction split(obj) { return; }rnfunction doFace(obj) { return false; }rnreturn { canCheckBlock, canCheckModel, canCheckHole, canDoWith, canSplit, canDoFace, checkBlock, checkModel, checkHole, doWith, split, doFace };", - "IsLoadBoardBeforeFileHead": true, - "NcLoadBoard": "", - "NcFileHoleBegin": "", - "NcFileHoleEnd": "", - "HolingByKnifeDia": true, - "NoteAutoPrinter": false, - "NoteNcName": "print_{0}.nc", - "NotePicName": "标签/{0}_{1}.bmp", - "NotePicType": "jpg", - "NotePicBit": "24", - "NotePrintOnFaceA": true, - "NotePositionAvoidHole": true, - "NoteWidth": 60, - "NOteHeight": 40, - "NoteContent": "", - "NotePushInNcFile": false, - "NoteGB2312": false, - "NoteOtherExport": false, - "NoteOtherFun": "", - "AllowBlockNo_Note": false, - "BlockNo_Note": "return obj.BlockNo;", - "BoardName": "{0}_{1}_{2}_{3}", - "MinBlockWidth": 10, - "MinHoleRadius": 1, - "MinHoleDepth": 1, - "MinModelDepth": 0, - "MinModelRadius": 1, - "MaxBorderThickness": 10, - "Ignore2in1SideHole": false, - "Ignore2in1SideHoleGap": 0.01, - "canReloadPlaceInfo": false, - "MiniumSpaceSize": 5, - "NeatenSpaceGap": 0, - "ResetPositionWithLocator": false, - "NcNumberFixNumber": 3, - "NcFileRemoveEmptyLine": false, - "HoleWaitingCode": "", - "prevRunActionCount": 5, - "ShearBorderFaceA": false, - "AllowOppositeDealChuanHole": false, - "DelayDoCountBeforeChangeKnife": 0, - "DelayCodeBeforeChangeKnife": "G04 X2.0", - "UseBoardFaceZ": false, - "PushNcLineIDStr": { - "enable": false, - "beginLine": 0, - "endLine": 0, - "ignoreEmptyLine": false, - "format": "N[4]", - "lineID": 1 - }, - "ManagerPassword": "cftech123456789", - "Remark": "", - "YuLiaoBoardDo2FaceBlock": false, - "WebQueryPageSize": 1000, - "ExportRootPath": "C:", - "AllowSelectExportPath": false, - "AllowExportImage": false, - "ManualSortingCornerWidth": 2, - "dt_Knifes4Hole": 1657768785334 - }, - "MachineID": 3755 - }, - { - "Type": 2, - "Setting": { - "companyID": 0, - "noteName": "标签-宽60mm高40mm", - "width": 480, - "height": 312, - "objects": [ - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "材质", - "X": 10, - "Y": 50, - "Width": 300, - "Height": 30, - "Visible": true, - "IsScrapBlock": false, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "188腾拓9-50#", - "DataExpression": "return obj.MetrialName+obj.Color;", - "DisplayType": 0, - "BarcodeType": "CODE39", - "FontSize": 30, - "FontWeight": 800, - "FontFamily": "黑体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - }, - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "柜名", - "X": 10, - "Y": 130, - "Width": 300, - "Height": 30, - "Visible": true, - "IsScrapBlock": false, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "一楼洗手台立板", - "DataExpression": "return obj.BoxName+obj.BlockName+obj.Remark1+obj.Remark2+obj.Remark3+obj.Remark4+obj.Remark5;", - "DisplayType": 0, - "BarcodeType": "CODE39", - "FontSize": 30, - "FontWeight": 800, - "FontFamily": "黑体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - }, - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "地址", - "X": 198, - "Y": 7, - "Width": 350, - "Height": 30, - "Visible": true, - "IsScrapBlock": false, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "1", - "DataExpression": "return obj.ConsigneeAddress;", - "DisplayType": 0, - "BarcodeType": "CODE39", - "FontSize": 30, - "FontWeight": 800, - "FontFamily": "黑体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - }, - { - "Type": 6, - "ObjcectID": 0, - "ObjectName": "封边图", - "X": 20, - "Y": 210, - "Width": 140, - "Height": 80, - "Visible": true, - "IsScrapBlock": false, - "VisibleExpression": "return true;", - "ShowData": true, - "DataWidth": 15, - "DataFix": 1, - "DisplayFB": -1, - "FontSize": 18, - "FontWeight": 800, - "FontFamily": "黑体", - "ShowCncDict": true, - "CncDictType": 1, - "ShowSideHole": true, - "SideHoleFlag": "#" - }, - { - "Type": 5, - "ObjcectID": 0, - "ObjectName": "位置图", - "X": 200, - "Y": 195, - "Width": 250, - "Height": 100, - "Visible": true, - "IsScrapBlock": false, - "VisibleExpression": "return true;", - "LineHeight": 1, - "LineColor": "rgb(0,0,0)", - "FillColor": "rgb(0,0,0)", - "Angle": 0 - }, - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "成品尺寸", - "X": 10, - "Y": 90, - "Width": 300, - "Height": 30, - "Visible": true, - "IsScrapBlock": false, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "590*578*18", - "DataExpression": "return obj.CuttingLength + '*' +obj.CuttingWidth+'*'+obj.Thickness;", - "DisplayType": 0, - "BarcodeType": "CODE39", - "FontSize": 30, - "FontWeight": 800, - "FontFamily": "黑体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - }, - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "板编号", - "X": 10, - "Y": 170, - "Width": 200, - "Height": 25, - "Visible": true, - "IsScrapBlock": false, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "220408120747", - "DataExpression": "return obj.BlockNo;", - "DisplayType": 0, - "BarcodeType": "CODE39", - "FontSize": 25, - "FontWeight": 800, - "FontFamily": "黑体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - }, - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "页码", - "X": 370, - "Y": 10, - "Width": 100, - "Height": 30, - "Visible": true, - "IsScrapBlock": false, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "1-60", - "DataExpression": "return obj.BoardID + '-' + obj.CutSortID;", - "DisplayType": 0, - "BarcodeType": "CODE39", - "FontSize": 30, - "FontWeight": 800, - "FontFamily": "黑体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - }, - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "余料板编号", - "X": 330, - "Y": 70, - "Width": 100, - "Height": 100, - "Visible": true, - "IsScrapBlock": true, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "210600495474", - "DataExpression": "return obj.BlockNo;", - "DisplayType": 2, - "BarcodeType": "CODE39", - "FontSize": "40", - "FontWeight": "400", - "FontFamily": "宋体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - }, - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "余料板尺寸", - "X": 30, - "Y": 13, - "Width": 300, - "Height": 40, - "Visible": true, - "IsScrapBlock": true, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "2178.1*1218.0", - "DataExpression": "return obj.Length.toFixed(1) + '*' + obj.Width.toFixed(1);", - "DisplayType": 0, - "BarcodeType": "CODE39", - "FontSize": "40", - "FontWeight": "400", - "FontFamily": "宋体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - }, - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "余料板颜色", - "X": 30, - "Y": 99, - "Width": 350, - "Height": 40, - "Visible": true, - "IsScrapBlock": true, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "多层板 世纪冰川", - "DataExpression": "return obj.MetrialName + ' ' + obj.Color ;", - "DisplayType": 0, - "BarcodeType": "CODE39", - "FontSize": "40", - "FontWeight": "400", - "FontFamily": "宋体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - }, - { - "Type": 5, - "ObjcectID": 0, - "ObjectName": "余料板位置图", - "X": 30, - "Y": 145, - "Width": 218, - "Height": 80, - "Visible": true, - "IsScrapBlock": true, - "VisibleExpression": "return true;", - "LineHeight": 1, - "LineColor": "rgb(0,0,0)", - "FillColor": "rgb(0,0,0)", - "Angle": 0 - }, - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "条码", - "X": 367, - "Y": 109, - "Width": 73, - "Height": 68, - "Visible": true, - "IsScrapBlock": false, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "220408120747", - "DataExpression": "return obj.BlockNo;", - "DisplayType": 2, - "BarcodeType": "CODE128", - "FontSize": "20", - "FontWeight": "400", - "FontFamily": "宋体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - }, - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "房间分组编号", - "X": 270, - "Y": 69, - "Width": 161, - "Height": 20, - "Visible": true, - "IsScrapBlock": false, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "柜体分组:5-4", - "DataExpression": "return '柜体分组:'+util.groupCount('OrderNo','RoomName','BoxName')+'-' +util.groupNum(obj,'OrderNo','RoomName','BoxName');", - "DisplayType": 0, - "BarcodeType": "CODE39", - "FontSize": "30", - "FontWeight": "600", - "FontFamily": "黑体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - }, - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "分组数量", - "X": 256, - "Y": 148, - "Width": 60, - "Height": 20, - "Visible": true, - "IsScrapBlock": false, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "分组数量:", - "DataExpression": "return '分组:'+util.groupCount('OrderNo','RoomName','BoxName');", - "DisplayType": 0, - "BarcodeType": "CODE39", - "FontSize": "30", - "FontWeight": "600", - "FontFamily": "黑体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - }, - { - "Type": 4, - "ObjcectID": 0, - "ObjectName": "分组数量", - "X": 242, - "Y": 106, - "Width": 60, - "Height": 20, - "Visible": true, - "IsScrapBlock": false, - "VisibleExpression": "return true;", - "IsVertical": false, - "DataText": "分组数量:", - "DataExpression": "return '分组数量:'+util.groupCount('OrderNo','RoomName','BoxName');", - "DisplayType": 0, - "BarcodeType": "CODE39", - "FontSize": "30", - "FontWeight": "600", - "FontFamily": "黑体", - "TextAlign": "left", - "TextBaseline": "top", - "QrcodeErrorRate": "M" - } - ] - }, - "MachineID": 3755 - }, - { - "Type": 3, - "Setting": { - "BoardBorder": 40, - "GlobalAlpha": 0.95, - "WorkSpaceColor": "#6A6C6B", - "WorkSpaceBorderColor": "#000000", - "ShowAxis": true, - "AxisPos": -10, - "AxisNodeWidth0": 3, - "AxisNodeWidth1": 5, - "AxisNodeWidth2": 10, - "AxisblockFlagWidth": 30, - "AxisColor": "#8a8c8e", - "BlockInfoInAxisFont": "bold 16px arial", - "BlockInfoInAxisColor": "#0000FF", - "BlockInfoInAxisColor2": "#00FF00", - "BoardColor": "#FFFFFF", - "BoardColor2": "#BAE6C7", - "BoardBorderColor": "#000000", - "BlockFillColor": "#FFFFFF", - "BlockFillColor2": "#CFD0D3", - "BlockFillColor_overLap1": "#FF0000", - "BlockFillColor_overLap2": "#f391a9", - "BlockFillColor_draging": "#00FF00", - "BlockFillColor_closest": "#90d7ec", - "BlockBorderColor": "#000000", - "BlockBorderColor2": "#FF0000", - "BlockBorderWidth": 4, - "PointFillColor_draging": "#FF0000", - "PointFillColor_closest": "#0000FF", - "ModelLineColor": "#F90212", - "HoleColor": "#007d65", - "HoleColor2": "#F90212", - "CutPoint_Radius": 6, - "PointFillColor_cutPoint": "#FF0000", - "CutSortID_Radius": 10, - "CutSortID_font": "18px arial", - "CutSortID_color": "#0000FF", - "BlockDirectionShow": true, - "BlockNoShow": true, - "BlockNoColor": "#000000", - "BlockNoFont": "18px arial", - "BlockSizeShow": false, - "BlockSizeColor": "#000000", - "BlockSizeFont": "10px arial", - "ScrapBlockStrokeColor": "black", - "ScrapBlockFocusColor": "#D3F767", - "ScrapPlaceBlock": "#F9F8BE", - "HelpKnifeBlockColor": "#EAE3EE" - }, - "MachineID": 3755 - } - ], - "SourceType": 2, - "BlockList": [ - { - "RoomName": "F-01", - "BoxName": "G-01", - "OrderNo": 20220701022805, - "BlockID": 3847597, - "GoodsID": 997, - "OldBlockID": 3847597, - "BlockNo": "220708337474", - "NoteNo": "", - "BlockName": "左侧板", - "Width": 600, - "Length": 2000, - "Thickness": 18, - "IsHXDJX": false, - "BorderLeft": 1, - "BorderRight": 1, - "BorderUpper": 1, - "BorderUnder": 1, - "Wave": 0, - "PaiKong": 2, - "BorderLengthLight": 0, - "BorderLengthHeavy": 0, - "RemarkJson": [], - "CadDataType": 2, - "ProcessGroupName": "", - "Type": "柜体", - "OpenDoorType": 0, - "ExtraRemark": null, - "ItemID": 7825470 - }, - { - "RoomName": "F-01", - "BoxName": "G-01", - "OrderNo": 20220701022805, - "BlockID": 3847598, - "GoodsID": 997, - "OldBlockID": 3847598, - "BlockNo": "220708337475", - "NoteNo": "", - "BlockName": "右侧板", - "Width": 600, - "Length": 2000, - "Thickness": 18, - "IsHXDJX": false, - "BorderLeft": 1, - "BorderRight": 1, - "BorderUpper": 1, - "BorderUnder": 1, - "Wave": 0, - "PaiKong": 2, - "BorderLengthLight": 0, - "BorderLengthHeavy": 0, - "RemarkJson": "[]", - "CadDataType": 2, - "ProcessGroupName": "", - "Type": "柜体", - "OpenDoorType": 0, - "ExtraRemark": null, - "ItemID": 7825471 - }, - { - "RoomName": "F-01", - "BoxName": "G-01", - "OrderNo": 20220701022805, - "BlockID": 3847599, - "GoodsID": 997, - "OldBlockID": 3847599, - "BlockNo": "220708337476", - "NoteNo": "", - "BlockName": "层板", - "Width": 600, - "Length": 1164, - "Thickness": 18, - "IsHXDJX": false, - "BorderLeft": 1, - "BorderRight": 1, - "BorderUpper": 1, - "BorderUnder": 1, - "Wave": 0, - "PaiKong": 2, - "BorderLengthLight": 0, - "BorderLengthHeavy": 0, - "RemarkJson": "[]", - "CadDataType": 2, - "ProcessGroupName": "", - "Type": "柜体", - "OpenDoorType": 0, - "ExtraRemark": null, - "ItemID": 7825472 - }, - { - "RoomName": "F-01", - "BoxName": "G-01", - "OrderNo": 20220701022805, - "BlockID": 3847600, - "GoodsID": 997, - "OldBlockID": 3847600, - "BlockNo": "220708337477", - "NoteNo": "", - "BlockName": "层板", - "Width": 600, - "Length": 1164, - "Thickness": 18, - "IsHXDJX": false, - "BorderLeft": 1, - "BorderRight": 1, - "BorderUpper": 1, - "BorderUnder": 1, - "Wave": 0, - "PaiKong": 2, - "BorderLengthLight": 0, - "BorderLengthHeavy": 0, - "RemarkJson": "[]", - "CadDataType": 2, - "ProcessGroupName": "", - "Type": "柜体", - "OpenDoorType": 0, - "ExtraRemark": null, - "ItemID": 7825473 - }, - { - "RoomName": "F-01", - "BoxName": "G-01", - "OrderNo": 20220701022805, - "BlockID": 3847601, - "GoodsID": 997, - "OldBlockID": 3847601, - "BlockNo": "220708337478", - "NoteNo": "", - "BlockName": "层板", - "Width": 600, - "Length": 1164, - "Thickness": 18, - "IsHXDJX": false, - "BorderLeft": 1, - "BorderRight": 1, - "BorderUpper": 1, - "BorderUnder": 1, - "Wave": 0, - "PaiKong": 2, - "BorderLengthLight": 0, - "BorderLengthHeavy": 0, - "RemarkJson": "[]", - "CadDataType": 2, - "ProcessGroupName": "", - "Type": "柜体", - "OpenDoorType": 0, - "ExtraRemark": null, - "ItemID": 7825474 - }, - { - "RoomName": "F-01", - "BoxName": "G-01", - "OrderNo": 20220701022805, - "BlockID": 3847602, - "GoodsID": 997, - "OldBlockID": 3847602, - "BlockNo": "220708337479", - "NoteNo": "", - "BlockName": "层板", - "Width": 600, - "Length": 1164, - "Thickness": 18, - "IsHXDJX": false, - "BorderLeft": 1, - "BorderRight": 1, - "BorderUpper": 1, - "BorderUnder": 1, - "Wave": 0, - "PaiKong": 2, - "BorderLengthLight": 0, - "BorderLengthHeavy": 0, - "RemarkJson": "[]", - "CadDataType": 2, - "ProcessGroupName": "", - "Type": "柜体", - "OpenDoorType": 0, - "ExtraRemark": null, - "ItemID": 7825475 - }, - { - "RoomName": "F-01", - "BoxName": "G-01", - "OrderNo": 20220701022805, - "BlockID": 3847603, - "GoodsID": 997, - "OldBlockID": 3847603, - "BlockNo": "220708337480", - "NoteNo": "", - "BlockName": "层板", - "Width": 600, - "Length": 1164, - "Thickness": 18, - "IsHXDJX": false, - "BorderLeft": 1, - "BorderRight": 1, - "BorderUpper": 1, - "BorderUnder": 1, - "Wave": 0, - "PaiKong": 2, - "BorderLengthLight": 0, - "BorderLengthHeavy": 0, - "RemarkJson": "[]", - "CadDataType": 2, - "ProcessGroupName": "", - "Type": "柜体", - "OpenDoorType": 0, - "ExtraRemark": null, - "ItemID": 7825476 - }, - { - "RoomName": "F-01", - "BoxName": "G-01", - "OrderNo": 20220701022805, - "BlockID": 3847604, - "GoodsID": 997, - "OldBlockID": 3847604, - "BlockNo": "220708337481", - "NoteNo": "", - "BlockName": "层板", - "Width": 600, - "Length": 1164, - "Thickness": 18, - "IsHXDJX": false, - "BorderLeft": 1, - "BorderRight": 1, - "BorderUpper": 1, - "BorderUnder": 1, - "Wave": 0, - "PaiKong": 2, - "BorderLengthLight": 0, - "BorderLengthHeavy": 0, - "RemarkJson": "[]", - "CadDataType": 2, - "ProcessGroupName": "", - "Type": "柜体", - "OpenDoorType": 0, - "ExtraRemark": null, - "ItemID": 7825477 - }, - { - "RoomName": "F-01", - "BoxName": "G-01", - "OrderNo": 20220701022805, - "BlockID": 3847605, - "GoodsID": 997, - "OldBlockID": 3847605, - "BlockNo": "220708337482", - "NoteNo": "", - "BlockName": "层板", - "Width": 600, - "Length": 1164, - "Thickness": 18, - "IsHXDJX": false, - "BorderLeft": 1, - "BorderRight": 1, - "BorderUpper": 1, - "BorderUnder": 1, - "Wave": 0, - "PaiKong": 2, - "BorderLengthLight": 0, - "BorderLengthHeavy": 0, - "RemarkJson": "[]", - "CadDataType": 2, - "ProcessGroupName": "", - "Type": "柜体", - "OpenDoorType": 0, - "ExtraRemark": null, - "ItemID": 7825478 - } - ], - "BlockDetailList": [ - { - "ID": 3847597, - "OrderNo": 20220701022805, - "PointDetail": [], - "ModelDetail": [], - "HoleDetail": [ - { - "HoleID": 1, - "HoleType": 10, - "Face": 0, - "PointX": 49, - "PointY": 1335.3333333333335, - "PointZ": -18, - "Radius": 5, - "Depth": 13.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 2, - "HoleType": 10, - "Face": 0, - "PointX": 549, - "PointY": 1335.3333333333335, - "PointZ": -18, - "Radius": 5, - "Depth": 13.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 3, - "HoleType": 10, - "Face": 0, - "PointX": 81, - "PointY": 1335.3333333333335, - "PointZ": -46, - "Radius": 4, - "Depth": 13, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 4, - "HoleType": 10, - "Face": 0, - "PointX": 517, - "PointY": 1335.3333333333335, - "PointZ": -46, - "Radius": 4, - "Depth": 13, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 5, - "HoleType": 10, - "Face": 0, - "PointX": 49.00000000000004, - "PointY": 1671.6666666666667, - "PointZ": -18, - "Radius": 1.05, - "Depth": 14.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 6, - "HoleType": 10, - "Face": 0, - "PointX": 549, - "PointY": 1671.6666666666667, - "PointZ": -18, - "Radius": 1.05, - "Depth": 14.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 7, - "HoleType": 10, - "Face": 0, - "PointX": 49, - "PointY": 999.0000000000001, - "PointZ": -18, - "Radius": 1.5, - "Depth": 9, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 8, - "HoleType": 10, - "Face": 0, - "PointX": 549, - "PointY": 999.0000000000001, - "PointZ": -18, - "Radius": 1.5, - "Depth": 9, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 9, - "HoleType": 10, - "Face": 0, - "PointX": 35.50000000000009, - "PointY": 326.33333333333337, - "PointZ": -18, - "Radius": 3.5999999999999996, - "Depth": 9, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 10, - "HoleType": 10, - "Face": 0, - "PointX": 535.5000000000001, - "PointY": 326.33333333333337, - "PointZ": -18, - "Radius": 3.5999999999999996, - "Depth": 9, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 11, - "HoleType": 10, - "Face": 0, - "PointX": 49, - "PointY": 1839.833333333333, - "PointZ": -18, - "Radius": 2.5, - "Depth": 12, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 12, - "HoleType": 10, - "Face": 0, - "PointX": 549, - "PointY": 1839.833333333333, - "PointZ": -18, - "Radius": 2.5, - "Depth": 12, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 13, - "HoleType": 10, - "Face": 0, - "PointX": 199, - "PointY": 158.16666666666666, - "PointZ": -18, - "Radius": 3, - "Depth": 13, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 14, - "HoleType": 10, - "Face": 0, - "PointX": 399, - "PointY": 158.16666666666666, - "PointZ": -18, - "Radius": 3, - "Depth": 13, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 15, - "HoleType": 10, - "Face": 0, - "PointX": 231, - "PointY": 158.16666666666666, - "PointZ": -56, - "Radius": 5, - "Depth": 13, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 16, - "HoleType": 10, - "Face": 0, - "PointX": 367, - "PointY": 158.16666666666666, - "PointZ": -56, - "Radius": 5, - "Depth": 13, - "EndPoint": "", - "Angle": 0 - } - ], - "OffSet": { - "x": 1, - "y": 1, - "z": 0 - }, - "NewVersion": false, - "OrgPointDetail": [], - "KaiLiaoSize": { - "width": 598, - "height": 1998 - }, - "SideModelDetail": [], - "SideHoleDetail": [] - }, - { - "ID": 3847598, - "OrderNo": 20220701022805, - "PointDetail": [], - "ModelDetail": [], - "HoleDetail": [ - { - "HoleID": 1, - "HoleType": 10, - "Face": 1, - "PointX": 49, - "PointY": 1335.3333333333335, - "PointZ": 0, - "Radius": 5, - "Depth": 13.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 2, - "HoleType": 10, - "Face": 1, - "PointX": 549, - "PointY": 1335.3333333333335, - "PointZ": 0, - "Radius": 5, - "Depth": 13.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 3, - "HoleType": 10, - "Face": 1, - "PointX": 81, - "PointY": 1335.3333333333335, - "PointZ": 28, - "Radius": 4, - "Depth": 13, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 4, - "HoleType": 10, - "Face": 1, - "PointX": 517, - "PointY": 1335.3333333333335, - "PointZ": 28, - "Radius": 4, - "Depth": 13, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 5, - "HoleType": 10, - "Face": 1, - "PointX": 49.00000000000004, - "PointY": 1671.6666666666667, - "PointZ": 0, - "Radius": 1.05, - "Depth": 14.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 6, - "HoleType": 10, - "Face": 1, - "PointX": 549, - "PointY": 1671.6666666666667, - "PointZ": 0, - "Radius": 1.05, - "Depth": 14.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 7, - "HoleType": 10, - "Face": 1, - "PointX": 49, - "PointY": 999.0000000000001, - "PointZ": 0, - "Radius": 1.5, - "Depth": 9, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 8, - "HoleType": 10, - "Face": 1, - "PointX": 549, - "PointY": 999.0000000000001, - "PointZ": 0, - "Radius": 1.5, - "Depth": 9, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 9, - "HoleType": 10, - "Face": 1, - "PointX": 35.50000000000009, - "PointY": 326.33333333333337, - "PointZ": 0, - "Radius": 3.5999999999999996, - "Depth": 9, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 10, - "HoleType": 10, - "Face": 1, - "PointX": 535.5000000000001, - "PointY": 326.33333333333337, - "PointZ": 0, - "Radius": 3.5999999999999996, - "Depth": 9, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 11, - "HoleType": 10, - "Face": 1, - "PointX": 49, - "PointY": 1839.833333333333, - "PointZ": 0, - "Radius": 2.5, - "Depth": 12, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 12, - "HoleType": 10, - "Face": 1, - "PointX": 549, - "PointY": 1839.833333333333, - "PointZ": 0, - "Radius": 2.5, - "Depth": 12, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 13, - "HoleType": 10, - "Face": 1, - "PointX": 199, - "PointY": 158.16666666666666, - "PointZ": 0, - "Radius": 3, - "Depth": 13, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 14, - "HoleType": 10, - "Face": 1, - "PointX": 399, - "PointY": 158.16666666666666, - "PointZ": 0, - "Radius": 3, - "Depth": 13, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 15, - "HoleType": 10, - "Face": 1, - "PointX": 231, - "PointY": 158.16666666666666, - "PointZ": 38, - "Radius": 5, - "Depth": 13, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 16, - "HoleType": 10, - "Face": 1, - "PointX": 367, - "PointY": 158.16666666666666, - "PointZ": 38, - "Radius": 5, - "Depth": 13, - "EndPoint": "", - "Angle": 0 - } - ], - "OffSet": { - "x": 1, - "y": 1, - "z": 0 - }, - "NewVersion": false, - "OrgPointDetail": [], - "KaiLiaoSize": { - "width": 598, - "height": 1998 - }, - "SideModelDetail": [], - "SideHoleDetail": [] - }, - { - "ID": 3847599, - "OrderNo": 20220701022805, - "PointDetail": [], - "ModelDetail": [], - "HoleDetail": [], - "OffSet": { - "x": 1, - "y": 1, - "z": 0 - }, - "NewVersion": false, - "OrgPointDetail": [], - "KaiLiaoSize": { - "width": 598, - "height": 1162 - }, - "SideModelDetail": [], - "SideHoleDetail": [ - { - "HoleID": 1, - "HoleType": 10, - "Face": 2, - "PointX": 200, - "PointY": 1164, - "PointZ": -9, - "Radius": 3, - "Depth": 18.09999999999991, - "EndPoint": "", - "PointX2": 200, - "PointY2": 1145.9 - }, - { - "HoleID": 2, - "HoleType": 10, - "Face": 2, - "PointX": 400, - "PointY": 1164, - "PointZ": -9, - "Radius": 3, - "Depth": 18.09999999999991, - "EndPoint": "", - "PointX2": 400, - "PointY2": 1145.9 - }, - { - "HoleID": 3, - "HoleType": 10, - "Face": 0, - "PointX": 200, - "PointY": -1.3877787807814457e-17, - "PointZ": -9, - "Radius": 3, - "Depth": 18.1, - "EndPoint": "", - "PointX2": 200, - "PointY2": 18.1 - }, - { - "HoleID": 4, - "HoleType": 10, - "Face": 0, - "PointX": 400, - "PointY": -1.3877787807814457e-17, - "PointZ": -9, - "Radius": 3, - "Depth": 18.1, - "EndPoint": "", - "PointX2": 400, - "PointY2": 18.1 - } - ] - }, - { - "ID": 3847600, - "OrderNo": 20220701022805, - "PointDetail": [], - "ModelDetail": [], - "HoleDetail": [ - { - "HoleID": 1, - "HoleType": 0, - "Face": 1, - "PointX": 49, - "PointY": 1129, - "PointZ": -13.5, - "Radius": 7.5, - "Depth": 13.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 2, - "HoleType": 0, - "Face": 1, - "PointX": 549, - "PointY": 1129, - "PointZ": -13.5, - "Radius": 7.5, - "Depth": 13.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 3, - "HoleType": 0, - "Face": 1, - "PointX": 49, - "PointY": 33, - "PointZ": -13.5, - "Radius": 7.5, - "Depth": 13.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 4, - "HoleType": 0, - "Face": 1, - "PointX": 549, - "PointY": 33, - "PointZ": -13.5, - "Radius": 7.5, - "Depth": 13.5, - "EndPoint": "", - "Angle": 0 - } - ], - "OffSet": { - "x": 1, - "y": 1, - "z": 0 - }, - "NewVersion": false, - "OrgPointDetail": [], - "KaiLiaoSize": { - "width": 598, - "height": 1162 - }, - "SideModelDetail": [], - "SideHoleDetail": [ - { - "HoleID": 1, - "HoleType": 10, - "Face": 2, - "PointX": 50, - "PointY": 1164, - "PointZ": -9, - "Radius": 4, - "Depth": 34.09999999999991, - "EndPoint": "", - "PointX2": 50, - "PointY2": 1129.9 - }, - { - "HoleID": 2, - "HoleType": 10, - "Face": 2, - "PointX": 550, - "PointY": 1164, - "PointZ": -9, - "Radius": 4, - "Depth": 34.09999999999991, - "EndPoint": "", - "PointX2": 550, - "PointY2": 1129.9 - }, - { - "HoleID": 3, - "HoleType": 10, - "Face": 2, - "PointX": 82, - "PointY": 1164, - "PointZ": -9, - "Radius": 4, - "Depth": 28.09999999999991, - "EndPoint": "", - "PointX2": 82, - "PointY2": 1135.9 - }, - { - "HoleID": 4, - "HoleType": 10, - "Face": 2, - "PointX": 518, - "PointY": 1164, - "PointZ": -9, - "Radius": 4, - "Depth": 28.09999999999991, - "EndPoint": "", - "PointX2": 518, - "PointY2": 1135.9 - }, - { - "HoleID": 5, - "HoleType": 10, - "Face": 0, - "PointX": 50, - "PointY": 0, - "PointZ": -9, - "Radius": 4, - "Depth": 34.1, - "EndPoint": "", - "PointX2": 50, - "PointY2": 34.1 - }, - { - "HoleID": 6, - "HoleType": 10, - "Face": 0, - "PointX": 550, - "PointY": 0, - "PointZ": -9, - "Radius": 4, - "Depth": 34.1, - "EndPoint": "", - "PointX2": 550, - "PointY2": 34.1 - }, - { - "HoleID": 7, - "HoleType": 10, - "Face": 0, - "PointX": 82, - "PointY": 0, - "PointZ": -9, - "Radius": 4, - "Depth": 28.1, - "EndPoint": "", - "PointX2": 82, - "PointY2": 28.1 - }, - { - "HoleID": 8, - "HoleType": 10, - "Face": 0, - "PointX": 518, - "PointY": 0, - "PointZ": -9, - "Radius": 4, - "Depth": 28.1, - "EndPoint": "", - "PointX2": 518, - "PointY2": 28.1 - } - ] - }, - { - "ID": 3847601, - "OrderNo": 20220701022805, - "PointDetail": [], - "ModelDetail": [], - "HoleDetail": [], - "OffSet": { - "x": 1, - "y": 1, - "z": 0 - }, - "NewVersion": false, - "OrgPointDetail": [], - "KaiLiaoSize": { - "width": 598, - "height": 1162 - }, - "SideModelDetail": [], - "SideHoleDetail": [ - { - "HoleID": 1, - "HoleType": 10, - "Face": 2, - "PointX": 50.00000000000004, - "PointY": 1164, - "PointZ": -8.999999999999954, - "Radius": 1.05, - "Depth": 14.5, - "EndPoint": "", - "PointX2": 50.00000000000004, - "PointY2": 1149.5 - }, - { - "HoleID": 2, - "HoleType": 10, - "Face": 2, - "PointX": 550, - "PointY": 1164, - "PointZ": -8.999999999999954, - "Radius": 1.05, - "Depth": 14.5, - "EndPoint": "", - "PointX2": 550, - "PointY2": 1149.5 - }, - { - "HoleID": 3, - "HoleType": 10, - "Face": 0, - "PointX": 50.00000000000004, - "PointY": 0, - "PointZ": -8.999999999999954, - "Radius": 1.05, - "Depth": 14.5, - "EndPoint": "", - "PointX2": 50.00000000000004, - "PointY2": 14.5 - }, - { - "HoleID": 4, - "HoleType": 10, - "Face": 0, - "PointX": 550, - "PointY": 0, - "PointZ": -8.999999999999954, - "Radius": 1.05, - "Depth": 14.5, - "EndPoint": "", - "PointX2": 550, - "PointY2": 14.5 - } - ] - }, - { - "ID": 3847602, - "OrderNo": 20220701022805, - "PointDetail": [], - "ModelDetail": [ - { - "ModelID": 1, - "LineID": 1, - "Face": 1, - "KnifeName": "", - "KnifeRadius": 2.5, - "Depth": 14, - "PointList": [ - { - "LineID": 1, - "PointID": 1, - "PointX": 44.5, - "PointY": 1161, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 1, - "PointID": 2, - "PointX": 53.5, - "PointY": 1161, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 1, - "PointID": 3, - "PointX": 53.5, - "PointY": 1163, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 1, - "PointID": 4, - "PointX": 44.5, - "PointY": 1163, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 1, - "PointID": 5, - "PointX": 44.5, - "PointY": 1161, - "Radius": 0, - "Depth": 14, - "Curve": 0 - } - ], - "OffsetList": [], - "OriginModeling": { - "outline": { - "pts": [ - { - "x": 43, - "y": 1159.5 - }, - { - "x": 43, - "y": 1164 - }, - { - "x": 57, - "y": 1164 - }, - { - "x": 57, - "y": 1159.5 - }, - { - "x": 43, - "y": 1159.5 - } - ], - "buls": [ - 0, - 0, - 0, - 0, - 0 - ] - }, - "holes": [], - "thickness": 0, - "dir": 0, - "knifeRadius": 0, - "addLen": 0, - "addWidth": 0, - "addDepth": 0 - } - }, - { - "ModelID": 2, - "LineID": 2, - "Face": 1, - "KnifeName": "", - "KnifeRadius": 2.5, - "Depth": 14, - "PointList": [ - { - "LineID": 2, - "PointID": 1, - "PointX": 544.5, - "PointY": 1161, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 2, - "PointID": 2, - "PointX": 553.5, - "PointY": 1161, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 2, - "PointID": 3, - "PointX": 553.5, - "PointY": 1163, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 2, - "PointID": 4, - "PointX": 544.5, - "PointY": 1163, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 2, - "PointID": 5, - "PointX": 544.5, - "PointY": 1161, - "Radius": 0, - "Depth": 14, - "Curve": 0 - } - ], - "OffsetList": [], - "OriginModeling": { - "outline": { - "pts": [ - { - "x": 543, - "y": 1159.5 - }, - { - "x": 543, - "y": 1164 - }, - { - "x": 557, - "y": 1164 - }, - { - "x": 557, - "y": 1159.5 - }, - { - "x": 543, - "y": 1159.5 - } - ], - "buls": [ - 0, - 0, - 0, - 0, - 0 - ] - }, - "holes": [], - "thickness": 0, - "dir": 0, - "knifeRadius": 0, - "addLen": 0, - "addWidth": 0, - "addDepth": 0 - } - }, - { - "ModelID": 3, - "LineID": 3, - "Face": 1, - "KnifeName": "", - "KnifeRadius": 2.5, - "Depth": 14, - "PointList": [ - { - "LineID": 3, - "PointID": 1, - "PointX": 44.5, - "PointY": -1, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 3, - "PointID": 2, - "PointX": 53.5, - "PointY": -1, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 3, - "PointID": 3, - "PointX": 53.5, - "PointY": 1, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 3, - "PointID": 4, - "PointX": 44.5, - "PointY": 1, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 3, - "PointID": 5, - "PointX": 44.5, - "PointY": -1, - "Radius": 0, - "Depth": 14, - "Curve": 0 - } - ], - "OffsetList": [], - "OriginModeling": { - "outline": { - "pts": [ - { - "x": 43, - "y": 4.5 - }, - { - "x": 57, - "y": 4.5 - }, - { - "x": 57, - "y": 0 - }, - { - "x": 43, - "y": 0 - }, - { - "x": 43, - "y": 4.5 - } - ], - "buls": [ - 0, - 0, - 0, - 0, - 0 - ] - }, - "holes": [], - "thickness": 0, - "dir": 0, - "knifeRadius": 0, - "addLen": 0, - "addWidth": 0, - "addDepth": 0 - } - }, - { - "ModelID": 4, - "LineID": 4, - "Face": 1, - "KnifeName": "", - "KnifeRadius": 2.5, - "Depth": 14, - "PointList": [ - { - "LineID": 4, - "PointID": 1, - "PointX": 544.5, - "PointY": -1, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 4, - "PointID": 2, - "PointX": 553.5, - "PointY": -1, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 4, - "PointID": 3, - "PointX": 553.5, - "PointY": 1, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 4, - "PointID": 4, - "PointX": 544.5, - "PointY": 1, - "Radius": 0, - "Depth": 14, - "Curve": 0 - }, - { - "LineID": 4, - "PointID": 5, - "PointX": 544.5, - "PointY": -1, - "Radius": 0, - "Depth": 14, - "Curve": 0 - } - ], - "OffsetList": [], - "OriginModeling": { - "outline": { - "pts": [ - { - "x": 543, - "y": 4.5 - }, - { - "x": 557, - "y": 4.5 - }, - { - "x": 557, - "y": 0 - }, - { - "x": 543, - "y": 0 - }, - { - "x": 543, - "y": 4.5 - } - ], - "buls": [ - 0, - 0, - 0, - 0, - 0 - ] - }, - "holes": [], - "thickness": 0, - "dir": 0, - "knifeRadius": 0, - "addLen": 0, - "addWidth": 0, - "addDepth": 0 - } - } - ], - "HoleDetail": [ - { - "HoleID": 1, - "HoleType": 10, - "Face": 1, - "PointX": 42.25, - "PointY": 1153, - "PointZ": 0, - "Radius": 2.5, - "Depth": 11, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 2, - "HoleType": 10, - "Face": 1, - "PointX": 55.75, - "PointY": 1153, - "PointZ": 0, - "Radius": 2.5, - "Depth": 11, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 3, - "HoleType": 10, - "Face": 1, - "PointX": 542.25, - "PointY": 1153, - "PointZ": 0, - "Radius": 2.5, - "Depth": 11, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 4, - "HoleType": 10, - "Face": 1, - "PointX": 555.75, - "PointY": 1153, - "PointZ": 0, - "Radius": 2.5, - "Depth": 11, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 5, - "HoleType": 10, - "Face": 1, - "PointX": 42.25, - "PointY": 9, - "PointZ": 0, - "Radius": 2.5, - "Depth": 11, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 6, - "HoleType": 10, - "Face": 1, - "PointX": 55.75, - "PointY": 9, - "PointZ": 0, - "Radius": 2.5, - "Depth": 11, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 7, - "HoleType": 10, - "Face": 1, - "PointX": 542.25, - "PointY": 9, - "PointZ": 0, - "Radius": 2.5, - "Depth": 11, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 8, - "HoleType": 10, - "Face": 1, - "PointX": 555.75, - "PointY": 9, - "PointZ": 0, - "Radius": 2.5, - "Depth": 11, - "EndPoint": "", - "Angle": 0 - } - ], - "OffSet": { - "x": 1, - "y": 1, - "z": 0 - }, - "NewVersion": false, - "OrgPointDetail": [], - "KaiLiaoSize": { - "width": 598, - "height": 1162 - }, - "SideModelDetail": [], - "SideHoleDetail": [] - }, - { - "ID": 3847603, - "OrderNo": 20220701022805, - "PointDetail": [], - "ModelDetail": [], - "HoleDetail": [], - "OffSet": { - "x": 1, - "y": 1, - "z": 0 - }, - "NewVersion": false, - "OrgPointDetail": [], - "KaiLiaoSize": { - "width": 598, - "height": 1162 - }, - "SideModelDetail": [], - "SideHoleDetail": [ - { - "HoleID": 1, - "HoleType": 10, - "Face": 2, - "PointX": 50, - "PointY": 1164, - "PointZ": -9, - "Radius": 4, - "Depth": 34, - "EndPoint": "", - "PointX2": 50, - "PointY2": 1130 - }, - { - "HoleID": 2, - "HoleType": 10, - "Face": 2, - "PointX": 550, - "PointY": 1164, - "PointZ": -9, - "Radius": 4, - "Depth": 34, - "EndPoint": "", - "PointX2": 550, - "PointY2": 1130 - }, - { - "HoleID": 3, - "HoleType": 10, - "Face": 0, - "PointX": 50, - "PointY": 0, - "PointZ": -9, - "Radius": 4, - "Depth": 34, - "EndPoint": "", - "PointX2": 50, - "PointY2": 34 - }, - { - "HoleID": 4, - "HoleType": 10, - "Face": 0, - "PointX": 550, - "PointY": 0, - "PointZ": -9, - "Radius": 4, - "Depth": 34, - "EndPoint": "", - "PointX2": 550, - "PointY2": 34 - } - ] - }, - { - "ID": 3847604, - "OrderNo": 20220701022805, - "PointDetail": [], - "ModelDetail": [], - "HoleDetail": [ - { - "HoleID": 1, - "HoleType": 0, - "Face": 1, - "PointX": 49, - "PointY": 1153, - "PointZ": -13.5, - "Radius": 10, - "Depth": 13.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 2, - "HoleType": 0, - "Face": 1, - "PointX": 549, - "PointY": 1153, - "PointZ": -13.5, - "Radius": 10, - "Depth": 13.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 3, - "HoleType": 0, - "Face": 1, - "PointX": 49, - "PointY": 9, - "PointZ": -13.5, - "Radius": 10, - "Depth": 13.5, - "EndPoint": "", - "Angle": 0 - }, - { - "HoleID": 4, - "HoleType": 0, - "Face": 1, - "PointX": 549, - "PointY": 9, - "PointZ": -13.5, - "Radius": 10, - "Depth": 13.5, - "EndPoint": "", - "Angle": 0 - } - ], - "OffSet": { - "x": 1, - "y": 1, - "z": 0 - }, - "NewVersion": false, - "OrgPointDetail": [], - "KaiLiaoSize": { - "width": 598, - "height": 1162 - }, - "SideModelDetail": [], - "SideHoleDetail": [ - { - "HoleID": 1, - "HoleType": 10, - "Face": 2, - "PointX": 50, - "PointY": 1164, - "PointZ": -9, - "Radius": 4, - "Depth": 10.099999999999909, - "EndPoint": "", - "PointX2": 50, - "PointY2": 1153.9 - }, - { - "HoleID": 2, - "HoleType": 10, - "Face": 2, - "PointX": 550, - "PointY": 1164, - "PointZ": -9, - "Radius": 4, - "Depth": 10.099999999999909, - "EndPoint": "", - "PointX2": 550, - "PointY2": 1153.9 - }, - { - "HoleID": 3, - "HoleType": 10, - "Face": 0, - "PointX": 50, - "PointY": -1.3877787807814457e-17, - "PointZ": -9, - "Radius": 4, - "Depth": 10.1, - "EndPoint": "", - "PointX2": 50, - "PointY2": 10.1 - }, - { - "HoleID": 4, - "HoleType": 10, - "Face": 0, - "PointX": 550, - "PointY": -1.3877787807814457e-17, - "PointZ": -9, - "Radius": 4, - "Depth": 10.1, - "EndPoint": "", - "PointX2": 550, - "PointY2": 10.1 - } - ] - }, - { - "ID": 3847605, - "OrderNo": 20220701022805, - "PointDetail": [], - "ModelDetail": [], - "HoleDetail": [], - "OffSet": { - "x": 1, - "y": 1, - "z": 0 - }, - "NewVersion": false, - "OrgPointDetail": [], - "KaiLiaoSize": { - "width": 598, - "height": 1162 - }, - "SideModelDetail": [], - "SideHoleDetail": [ - { - "HoleID": 1, - "HoleType": 10, - "Face": 2, - "PointX": 200, - "PointY": 1164, - "PointZ": -9, - "Radius": 3, - "Depth": 18.09999999999991, - "EndPoint": "", - "PointX2": 200, - "PointY2": 1145.9 - }, - { - "HoleID": 2, - "HoleType": 10, - "Face": 2, - "PointX": 400, - "PointY": 1164, - "PointZ": -9, - "Radius": 3, - "Depth": 18.09999999999991, - "EndPoint": "", - "PointX2": 400, - "PointY2": 1145.9 - }, - { - "HoleID": 3, - "HoleType": 10, - "Face": 2, - "PointX": 232, - "PointY": 1164, - "PointZ": -9, - "Radius": 5, - "Depth": 38.09999999999991, - "EndPoint": "", - "PointX2": 232, - "PointY2": 1125.9 - }, - { - "HoleID": 4, - "HoleType": 10, - "Face": 2, - "PointX": 368, - "PointY": 1164, - "PointZ": -9, - "Radius": 5, - "Depth": 38.09999999999991, - "EndPoint": "", - "PointX2": 368, - "PointY2": 1125.9 - }, - { - "HoleID": 5, - "HoleType": 10, - "Face": 0, - "PointX": 200, - "PointY": -1.3877787807814457e-17, - "PointZ": -9, - "Radius": 3, - "Depth": 18.1, - "EndPoint": "", - "PointX2": 200, - "PointY2": 18.1 - }, - { - "HoleID": 6, - "HoleType": 10, - "Face": 0, - "PointX": 400, - "PointY": -1.3877787807814457e-17, - "PointZ": -9, - "Radius": 3, - "Depth": 18.1, - "EndPoint": "", - "PointX2": 400, - "PointY2": 18.1 - }, - { - "HoleID": 7, - "HoleType": 10, - "Face": 0, - "PointX": 232, - "PointY": 1.7763568394002505e-15, - "PointZ": -9, - "Radius": 5, - "Depth": 38.1, - "EndPoint": "", - "PointX2": 232, - "PointY2": 38.1 - }, - { - "HoleID": 8, - "HoleType": 10, - "Face": 0, - "PointX": 368, - "PointY": 1.7763568394002505e-15, - "PointZ": -9, - "Radius": 5, - "Depth": 38.1, - "EndPoint": "", - "PointX2": 368, - "PointY2": 38.1 - } - ] - } - ] - }, - "PlaceResult": [ - { - "OrderNo": "O20220701022805", - "GoodsID": 997, - "GoodsName": "测试", - "Specification": "11", - "Metrial": "188", - "Color": "腾拓9-50#", - "Brank": "11", - "Width": 3000, - "Length": 4000, - "Thickness": 18, - "Border": 3, - "CutDia": 8, - "CutGap": 1, - "IsSorted": true, - "BoardCount": 1, - "MinBoardID": 1, - "MaxBoardID": 1, - "AvgLyr_All": 7.288800000000001, - "AvgLyr_NoLastOne": 7.288800000000001, - "Lyr_LastOne": 7.288800000000001, - "CompanyID": 0, - "UsedBoardMessage": [ - { - "Bi": 1, - "W": 3000, - "L": 4000, - "Si": 0, - "So": "", - "No": "", - "LK": false, - "scrapPts": null, - "scrapBlocks": [] - } - ], - "BlockPlaceMessage": [ - { - "Bi": 1, - "Bo": "220708337474", - "X": 2010, - "Y": 3, - "Pi": 2, - "Ps": 0, - "Ci": 3, - "Ca": 0, - "CP": 0, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337475", - "X": 3, - "Y": 3, - "Pi": 1, - "Ps": 7, - "Ci": 9, - "Ca": 0, - "CP": 1, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337476", - "X": 610, - "Y": 1217, - "Pi": 5, - "Ps": 1, - "Ci": 5, - "Ca": 0, - "CP": 2, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337477", - "X": 1781, - "Y": 2010, - "Pi": 8, - "Ps": 7, - "Ci": 1, - "Ca": 0, - "CP": 3, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337478", - "X": 610, - "Y": 2431, - "Pi": 9, - "Ps": 0, - "Ci": 2, - "Ca": 0, - "CP": 2, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337479", - "X": 3, - "Y": 610, - "Pi": 3, - "Ps": 4, - "Ci": 8, - "Ca": 0, - "CP": 0, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337480", - "X": 3, - "Y": 1781, - "Pi": 6, - "Ps": 0, - "Ci": 6, - "Ca": 0, - "CP": 1, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337481", - "X": 610, - "Y": 610, - "Pi": 4, - "Ps": 7, - "Ci": 7, - "Ca": 0, - "CP": 3, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - }, - { - "Bi": 1, - "Bo": "220708337482", - "X": 610, - "Y": 1824, - "Pi": 7, - "Ps": 1, - "Ci": 4, - "Ca": 0, - "CP": 2, - "iA": true, - "iO": false, - "W": 0, - "L": 0, - "ZFB": 0, - "YFB": 0, - "SFB": 0, - "XFB": 0, - "Dh": false, - "Dm": false, - "OF": 0, - "type": 0, - "points": [], - "OrgSizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": true - }, - "SizeOutOff": { - "left": 0, - "right": 0, - "upper": 0, - "under": 0, - "width": 0, - "length": 0, - "hasDone": false - }, - "PlaceOffX": 0, - "PlaceOffY": 0 - } - ], - "State": 0, - "HasWave": false, - "OrgWidth": 3000, - "OrgLength": 4000, - "BoardCount_Remain": 0, - "RemainBoardMessage": "[]", - "ScrapBoardList": [] - } - ] -} diff --git a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/voice/VoiceServiceImpl.java b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/voice/VoiceServiceImpl.java index 6c109959e..8ef61b7b7 100644 --- a/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/voice/VoiceServiceImpl.java +++ b/cf-module-prod-manage/cf-module-prod-manage-biz/src/main/java/com/cf/imes/module/manage/service/voice/VoiceServiceImpl.java @@ -6,6 +6,7 @@ import com.jacob.activeX.ActiveXComponent; import com.jacob.com.Dispatch; import com.jacob.com.Variant; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpStatus; @@ -16,35 +17,20 @@ import javax.annotation.Resource; import java.io.*; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -import com.jacob.activeX.ActiveXComponent; -import com.jacob.com.Dispatch; -import com.jacob.com.Variant; -import javax.sql.rowset.serial.SerialBlob; -import java.io.BufferedReader; -import java.io.FileReader; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.sql.Blob; -import java.sql.SQLException; import java.util.Objects; import java.io.File; import java.io.FileInputStream; -import java.io.IOException; -import java.net.http.WebSocket; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel; -import java.util.Objects; import java.util.Random; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; -import static org.aspectj.weaver.tools.cache.SimpleCacheFactory.path; - @Service @Slf4j public class VoiceServiceImpl implements VoiceService{ @@ -68,7 +54,7 @@ public class VoiceServiceImpl implements VoiceService{ String path = vocieParameters.getPath(); // 设置音频的质量( 越大越好,目前最大好像 22,最小为 4 ) - Long quality = vocieParameters.getQuality();; + Long quality = vocieParameters.getQuality(); // 朗读声音大小 Long soundSize = vocieParameters.getSoundSize(); @@ -108,7 +94,7 @@ public class VoiceServiceImpl implements VoiceService{ Dispatch.call(spVoice, "Speak", new Variant(data)); - System.out.println("输出语音文件成功!"); + log.info("输出语音文件成功!"); return filePath; @@ -151,7 +137,6 @@ public class VoiceServiceImpl implements VoiceService{ } byte[] audioBytes = byteArrayOutputStream.toByteArray(); - ByteArrayResource byteArrayResource = new ByteArrayResource(audioBytes); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.parseMediaType("audio/mpeg")); @@ -179,15 +164,14 @@ public class VoiceServiceImpl implements VoiceService{ **/ @Override public void zipFiles(String fileNames, String zipOutName) throws IOException { - ZipOutputStream zipOutputStream = null; WritableByteChannel writableByteChannel = null; ByteBuffer buffer = ByteBuffer.allocate(2048); - try { - zipOutputStream = new ZipOutputStream(new FileOutputStream(zipOutName)); + FileChannel fileChannel = null; + try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipOutName))) { writableByteChannel = Channels.newChannel(zipOutputStream); File source = new File(fileNames); zipOutputStream.putNextEntry(new ZipEntry(source.getName())); - FileChannel fileChannel = new FileInputStream(fileNames).getChannel(); + fileChannel = new FileInputStream(fileNames).getChannel(); while (fileChannel.read(buffer) != -1) { //更新缓存区位置 buffer.flip(); @@ -198,14 +182,14 @@ public class VoiceServiceImpl implements VoiceService{ } fileChannel.close(); - System.out.println("文件压缩成功"); + log.info("文件压缩成功"); } catch (Exception e) { log.error("batchZipFiles error fileNames:"); } finally { - zipOutputStream.close(); - writableByteChannel.close(); + IOUtils.closeQuietly(writableByteChannel); + IOUtils.closeQuietly(fileChannel); buffer.clear(); } } @@ -217,26 +201,26 @@ public class VoiceServiceImpl implements VoiceService{ // 检查文件路径是否为空 if (sourceFile == null || sourceFile.isEmpty()) { - System.out.println("文件路径为空"); + log.error("文件路径为空"); } File file = new File(sourceFile); // 检查文件是否存在 if (!file.exists()) { - System.out.println("文件不存在:" + sourceFile); + log.error("文件不存在:" + sourceFile); } // 检查是否是文件 if (!file.isFile()) { - System.out.println("路径指向的不是文件:" + sourceFile); + log.error("路径指向的不是文件:" + sourceFile); } // 尝试删除文件 if (file.delete()) { - System.out.println("文件删除成功:" + sourceFile); + log.error("文件删除成功:" + sourceFile); } else { - System.out.println("文件删除失败:" + sourceFile); + log.error("文件删除失败:" + sourceFile); } } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/oauth2/vo/open/OAuth2OpenAuthorizeInfoRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/oauth2/vo/open/OAuth2OpenAuthorizeInfoRespVO.java index f8b41a939..7f04008d0 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/oauth2/vo/open/OAuth2OpenAuthorizeInfoRespVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/oauth2/vo/open/OAuth2OpenAuthorizeInfoRespVO.java @@ -1,6 +1,6 @@ package com.cf.imes.module.system.controller.admin.oauth2.vo.open; -import com.cf.imes.framework.common.core.KeyValue; +import cn.hutool.core.lang.Pair; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; @@ -20,7 +20,7 @@ public class OAuth2OpenAuthorizeInfoRespVO { private Client client; @Schema(description = "scope 的选中信息,使用 List 保证有序性,Key 是 scope,Value 为是否选中", requiredMode = Schema.RequiredMode.REQUIRED) - private List> scopes; + private List> scopes; @Data @NoArgsConstructor diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/convert/oauth2/OAuth2OpenConvert.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/convert/oauth2/OAuth2OpenConvert.java index 96388047a..378e4750d 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/convert/oauth2/OAuth2OpenConvert.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/convert/oauth2/OAuth2OpenConvert.java @@ -1,7 +1,7 @@ package com.cf.imes.module.system.convert.oauth2; import cn.hutool.core.date.LocalDateTimeUtil; -import com.cf.imes.framework.common.core.KeyValue; +import cn.hutool.core.lang.Pair; import com.cf.imes.framework.common.enums.UserTypeEnum; import com.cf.imes.framework.common.util.collection.CollectionUtils; import com.cf.imes.framework.common.util.object.BeanUtils; @@ -42,11 +42,11 @@ public interface OAuth2OpenConvert { default OAuth2OpenAuthorizeInfoRespVO convert(OAuth2ClientDO client, List approves) { // 构建 scopes - List> scopes = new ArrayList<>(client.getScopes().size()); + List> scopes = new ArrayList<>(client.getScopes().size()); Map approveMap = CollectionUtils.convertMap(approves, OAuth2ApproveDO::getScope); client.getScopes().forEach(scope -> { OAuth2ApproveDO approve = approveMap.get(scope); - scopes.add(new KeyValue<>(scope, approve != null ? approve.getApproved() : false)); + scopes.add(new Pair<>(scope, approve != null ? approve.getApproved() : false)); }); // 拼接返回 return new OAuth2OpenAuthorizeInfoRespVO( diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/message/sms/SmsSendMessage.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/message/sms/SmsSendMessage.java index 502c9bc91..4252eda8b 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/message/sms/SmsSendMessage.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/message/sms/SmsSendMessage.java @@ -1,6 +1,6 @@ package com.cf.imes.module.system.mq.message.sms; -import com.cf.imes.framework.common.core.KeyValue; +import cn.hutool.core.lang.Pair; import lombok.Data; import javax.validation.constraints.NotNull; @@ -37,7 +37,7 @@ public class SmsSendMessage { /** * 短信模板参数 */ - private List> templateParams; + private List> templateParams; /** * 短信消息模板类型:system_sms_template.type diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/producer/sms/SmsProducer.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/producer/sms/SmsProducer.java index 88981e9a9..850d7aa05 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/producer/sms/SmsProducer.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/mq/producer/sms/SmsProducer.java @@ -1,6 +1,6 @@ package com.cf.imes.module.system.mq.producer.sms; -import com.cf.imes.framework.common.core.KeyValue; +import cn.hutool.core.lang.Pair; import com.cf.imes.module.system.dal.dataobject.sms.SmsTemplateDO; import com.cf.imes.module.system.mq.message.sms.SmsSendMessage; import lombok.extern.slf4j.Slf4j; @@ -32,7 +32,7 @@ public class SmsProducer { * @param template 模板信息 * @param templateParams 短信模板参数 */ - public void sendSmsSendMessage(Long logId, String mobile, SmsTemplateDO template, List> templateParams) { + public void sendSmsSendMessage(Long logId, String mobile, SmsTemplateDO template, List> templateParams) { SmsSendMessage message = new SmsSendMessage().setLogId(logId).setMobile(mobile); message.setChannelId(template.getChannelId()).setApiTemplateId(template.getApiTemplateId()).setTemplateType(template.getType()).setTemplateParams(templateParams); // event异步发送短信,保证子线程内部request不为空 diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsSendServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsSendServiceImpl.java index de56919f6..0530716e8 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsSendServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/SmsSendServiceImpl.java @@ -3,7 +3,7 @@ package com.cf.imes.module.system.service.sms; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.lang.Assert; -import com.cf.imes.framework.common.core.KeyValue; +import cn.hutool.core.lang.Pair; import com.cf.imes.framework.common.enums.CommonStatusEnum; import com.cf.imes.framework.common.enums.UserTypeEnum; import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; @@ -88,7 +88,7 @@ public class SmsSendServiceImpl implements SmsSendService { // 校验手机号码是否存在 mobile = validateMobile(mobile); // 构建有序的模板参数。为什么放在这个位置,是提前保证模板参数的正确性,而不是到了插入发送日志 - List> newTemplateParams = buildTemplateParams(template, templateParams); + List> newTemplateParams = buildTemplateParams(template, templateParams); // 创建发送日志。如果模板被禁用,则不发送短信,只记录日志 Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus()); @@ -123,13 +123,13 @@ public class SmsSendServiceImpl implements SmsSendService { * @return 处理后的参数 */ @VisibleForTesting - List> buildTemplateParams(SmsTemplateDO template, Map templateParams) { + List> buildTemplateParams(SmsTemplateDO template, Map templateParams) { return template.getParams().stream().map(key -> { Object value = templateParams.get(key); if (value == null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS, key); } - return new KeyValue<>(key, value); + return new Pair<>(key, value); }).collect(Collectors.toList()); } @@ -147,7 +147,7 @@ public class SmsSendServiceImpl implements SmsSendService { SmsClient smsClient = smsChannelService.getSmsClient(); Assert.notNull(smsClient, "短信客户端({}) 不存在", message.getChannelId()); - List> templateParams = message.getTemplateParams(); + List> templateParams = message.getTemplateParams(); String channelCode = null; // 发送短信 try { diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/SmsSendAfterSendHandler.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/SmsSendAfterSendHandler.java index 897635319..6526ccc2b 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/SmsSendAfterSendHandler.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/SmsSendAfterSendHandler.java @@ -1,6 +1,6 @@ package com.cf.imes.module.system.service.sms.handler; -import com.cf.imes.framework.common.core.KeyValue; +import cn.hutool.core.lang.Pair; import com.cf.imes.framework.sms.core.client.dto.SmsSendRespDTO; import java.util.List; @@ -21,5 +21,5 @@ public interface SmsSendAfterSendHandler { boolean checkTemplateType(Integer templateType); - void afterSend(SmsSendRespDTO sendResponse, List> params); + void afterSend(SmsSendRespDTO sendResponse, List> params); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/impl/SmsSendAfterSendHandlerImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/impl/SmsSendAfterSendHandlerImpl.java index 37b488055..eda0c1191 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/impl/SmsSendAfterSendHandlerImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/sms/handler/impl/SmsSendAfterSendHandlerImpl.java @@ -1,7 +1,7 @@ package com.cf.imes.module.system.service.sms.handler.impl; +import cn.hutool.core.lang.Pair; import cn.hutool.core.util.ObjectUtil; -import com.cf.imes.framework.common.core.KeyValue; import com.cf.imes.framework.sms.core.client.dto.SmsSendRespDTO; import com.cf.imes.module.system.dal.redis.RedisKeyConstants; import com.cf.imes.module.system.enums.sms.SmsTemplateTypeEnum; @@ -33,10 +33,10 @@ public class SmsSendAfterSendHandlerImpl implements SmsSendAfterSendHandler { } @Override - public void afterSend(SmsSendRespDTO sendResponse, List> params) { + public void afterSend(SmsSendRespDTO sendResponse, List> params) { // 发送成功把验证码存入redis if (sendResponse.getSuccess()) { - for (KeyValue keyValue : params) { + for (Pair keyValue : params) { if ("code".equals(keyValue.getKey())) { redisTemplate.opsForValue().set(String.format(RedisKeyConstants.SMS_CAPTCHA_VERIFICATION, sendResponse.getMobile()), keyValue.getValue(), smsCodeProperties.getExpireTimes()); } diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/controller/admin/oauth2/EsTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/controller/admin/oauth2/EsTest.java index 331805da9..d5e084246 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/controller/admin/oauth2/EsTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/controller/admin/oauth2/EsTest.java @@ -1,9 +1,6 @@ package com.cf.imes.module.system.controller.admin.oauth2; -import co.elastic.clients.elasticsearch.core.IndexResponse; import com.cf.imes.framework.es.core.service.ESDocumentService; -import com.cf.imes.framework.es.core.service.ESDocumentServiceImpl; -import com.cf.imes.framework.mybatis.core.generator.SnowFlake; import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @@ -11,7 +8,9 @@ import org.springframework.boot.test.context.SpringBootTest; import javax.annotation.Resource; import java.io.IOException; import java.util.HashMap; -import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class EsTest extends BaseMockitoUnitTest { @@ -19,61 +18,17 @@ public class EsTest extends BaseMockitoUnitTest { @Resource private ESDocumentService esDocumentService; - private SnowFlake snowFlake = new SnowFlake(1,1); - @Test public void t1() throws IOException { HashMap test2 = esDocumentService.getById("test2", "145116052710363136", HashMap.class); + assertNotNull(test2); System.out.println(test2); } - @Test - public void c1() throws Exception { - String json = """ - { - "ID": 0, - "MachineID": 5511, - "CompanyID": 1678, - "Name": "通用电子锯-备份", - "Type": 5, - "Setting": { - "templateName": "通用电子锯表格", - "encodingName": "", - "fileA": "", - "fileB": "", - "fileCreateType": "", - "codeContent": "// @changelog 2022-05-09 xzh 添加可配置压缩包名称n//参数可配置通用电子锯nnif(order == null || helper == null) return getArgList();nnfunction getArgList()n{ntlet args= { list:[],add(name,value,remark){ this.list.push({name,value,remark});return this;}};ntreturn argsn .add('zipFileName','cnc-{0}-{1}-{5}-{3}.zip', '导出zip文件名(0:日期时间,1:排单号,2:排单备注,3:地址列表,4:订单号列表,5:客户名称列表)')ntt.add('filename','{0}_{1}_{2}_{3}.csv','文件名(按板材导出时 0:板材名 1:材质 2:颜色 3:厚度 4:品牌rn按订单导出时 0:订单号 1:自定义单号 2:经销商 3:客户 4:地址)')ntt.add('gb2312',true,'中文编码方式(false:UTF-8 true:GB-2312)')ntt.add('groupByPM',true,'文件导出方式(fasle:按订单导出 true:按板材导出)')ntt.add('showTitle',true,'是否显示标题') n .add('fn_Filter','return false;','板件过滤函数(b板件)@b') ntt.add('fn_row',let texts = [];nlet isTitle = i ==0;nnaddV('订单号',b.OrderNo);naddV('柜号',b.BoxName);naddV('板件编号',b.BlockNo);nlet ztm = (b.FrontHoleCount+b.FrontModelCount>0 || b.BackHoleCount+b.BackModelCount==0 && b.HoleCount_Side>0 || b.IsUnRegular) ? b.BlockNo+'A' : '';nlet ftm = b.BackHoleCount+b.BackModelCount>0 ? b.BlockNo+'B' : '';naddV('正面条码',ztm);naddV('反面条码',ftm);naddV('产品名称',b.BlockName);naddV('成品名称',b.BlockName);naddV('材质名称',b.Thickness+'mm'+b.MetrialName+b.Color);nlet fL = getNum(b.Wave==2 ? b.Width : b.Length,1);nlet fW = getNum(b.Wave==2 ? b.Length : b.Width,1);naddV('成品长度',fL);naddV('成品宽度',fW);naddV('成品厚度',b.Thickness);nlet cL = getNum(b.Wave==2 ? b.CuttingWidth : b.CuttingLength,1);nlet cW = getNum(b.Wave==2 ? b.CuttingLength : b.CuttingWidth,1);naddV('开料长度',cL);naddV('开料宽度',cW);naddV('开料厚度',b.Thickness);naddV('纹路方向',b.Wave==2 ? '横纹' : '竖纹');naddV('需切数量',1);nlet fc1 = b.IsUnRegular ? '-' : getNum(b.Wave==2 ? b.BorderUpper : b.BorderLeft,1);nlet fc2 = b.IsUnRegular ? '-' : getNum(b.Wave==2 ? b.BorderUnder : b.BorderRight,1);nlet fk1 = b.IsUnRegular ? '-' : getNum(b.Wave==2 ? b.BorderLeft : b.BorderUpper,1);nlet fk2 = b.IsUnRegular ? '-' : getNum(b.Wave==2 ? b.BorderRight : b.BorderUnder,1);naddV('封长1',fc1);naddV('封宽1',fk1);naddV('封长2',fc2);naddV('封宽2',fk2);naddV('订单类型',b.RoomName);naddV('客户信息',b.ConsigneeAddress);naddV('加盟店',b.CustomerName);naddV('异形',b.IsUnRegular ? '异形' : '');naddV('旋转','');naddV('正面槽',b.FrontModelCount);naddV('是否开槽',b.FrontModelCount+b.BackModelCount>0 ? '槽' : '');naddV('反面槽',b.BackModelCount);naddV('正面孔',b.FrontHoleCount);naddV('是否打孔',b.FrontHoleCount+b.BackHoleCount>0 ? '孔' : '');naddV('反面孔',b.BackHoleCount);naddV('拉槽标识',b.FrontModelCount+b.BackModelCount>0 ? '槽' : '');naddV('排钻标识',b.FrontHoleCount+b.BackHoleCount+b.HoleCount_Side>0 ? '钻' : '');naddV('钻孔',b.FrontHoleCount>0 && b.BackHoleCount>0 ? '双' : (b.FrontHoleCount+b.HoleCount_Side>0 || b.BackHoleCount+b.HoleCount_Side>0 ? '单' : ''));naddV('异形ID','');nnreturn texts.join(',');nnfunction addV(title,v)n{n if(v == undefined) v = '';n texts.push(isTitle ? title : v.toString());n}nnfunction getNum(v,b)n{n return v.toFixed(b);n},'数据行(helper帮助类,i行号,pm板材,b板)@helper,i,pm,b')ntt.list;n}nnlet filename = helper.getArg('filename','{0}_{1}_{2}_{3}.xls');nlet groupByPM = helper.getArg('groupByPM',true);nlet isGb2312 = helper.getArg('gb2312',true);nlet showTitle = helper.getArg('showTitle',true);nlet fn_Filter = helper.newFn('板件过滤函数','fn_Filter','return false;','b'); //板件过滤函数nlet fn_row = helper.newFn('数据行','fn_row',let texts = [];nlet isTitle = i ==0;nnaddV('订单号',b.OrderNo);naddV('柜号',b.BoxName);naddV('板件编号',b.BlockNo);nlet ztm = (b.FrontHoleCount+b.FrontModelCount>0 || b.BackHoleCount+b.BackModelCount==0 && b.HoleCount_Side>0 || b.IsUnRegular) ? b.BlockNo+'A' : '';nlet ftm = b.BackHoleCount+b.BackModelCount>0 ? b.BlockNo+'B' : '';naddV('正面条码',ztm);naddV('反面条码',ftm);naddV('产品名称',b.BlockName);naddV('成品名称',b.BlockName);naddV('材质名称',b.Thickness+'mm'+b.MetrialName+b.Color);nlet fL = getNum(b.Wave==2 ? b.Width : b.Length,1);nlet fW = getNum(b.Wave==2 ? b.Length : b.Width,1);naddV('成品长度',fL);naddV('成品宽度',fW);naddV('成品厚度',b.Thickness);nlet cL = getNum(b.Wave==2 ? b.CuttingWidth : b.CuttingLength,1);nlet cW = getNum(b.Wave==2 ? b.CuttingLength : b.CuttingWidth,1);naddV('开料长度',cL);naddV('开料宽度',cW);naddV('开料厚度',b.Thickness);naddV('纹路方向',b.Wave==2 ? '横纹' : '竖纹');naddV('需切数量',1);nlet fc1 = b.IsUnRegular ? '-' : getNum(b.Wave==2 ? b.BorderUpper : b.BorderLeft,1);nlet fc2 = b.IsUnRegular ? '-' : getNum(b.Wave==2 ? b.BorderUnder : b.BorderRight,1);nlet fk1 = b.IsUnRegular ? '-' : getNum(b.Wave==2 ? b.BorderLeft : b.BorderUpper,1);nlet fk2 = b.IsUnRegular ? '-' : getNum(b.Wave==2 ? b.BorderRight : b.BorderUnder,1);naddV('封长1',fc1);naddV('封宽1',fk1);naddV('封长2',fc2);naddV('封宽2',fk2);naddV('订单类型',b.RoomName);naddV('客户信息',b.ConsigneeAddress);naddV('加盟店',b.CustomerName);naddV('异形',b.IsUnRegular ? '异形' : '');naddV('旋转','');naddV('正面槽',b.FrontModelCount);naddV('是否开槽',b.FrontModelCount+b.BackModelCount>0 ? '槽' : '');naddV('反面槽',b.BackModelCount);naddV('正面孔',b.FrontHoleCount);naddV('是否打孔',b.FrontHoleCount+b.BackHoleCount>0 ? '孔' : '');naddV('反面孔',b.BackHoleCount);naddV('拉槽标识',b.FrontModelCount+b.BackModelCount>0 ? '槽' : '');naddV('排钻标识',b.FrontHoleCount+b.BackHoleCount+b.HoleCount_Side>0 ? '钻' : '');naddV('钻孔',b.FrontHoleCount>0 && b.BackHoleCount>0 ? '双' : (b.FrontHoleCount+b.HoleCount_Side>0 || b.BackHoleCount+b.HoleCount_Side>0 ? '单' : ''));naddV('异形ID','');nnreturn texts.join(',');nnfunction addV(title,v)n{n if(v == undefined) v = '';n texts.push(isTitle ? title : v.toString());n}nnfunction getNum(v,b)n{n return v.toFixed(b);n},'helper','i','pm','b');nnlet hasTitle = false;nlet cache = [];nlet orderFileName='';nlet rowID = 0;nnfor(let pm of order.MetrialList) //按板材 0:板材名 1:材质 2:颜色 3:厚度 4:品牌n{ntif(groupByPM)nt{nttcache = [];nttrowID = 0;nt}ntfor(let i = 1; i <= pm.BlockList.length; i ++)nt{nttlet str_line = '';nttlet block = pm.BlockList[i-1];nttrowID = rowID + 1;nn let isValid = helper.exec(fn_Filter,block); //板件过滤函数nttif(isValid == true) continue; //过滤板件nntt//标题nttif(showTitle && !hasTitle)ntt{ntttlet str_title = helper.exec(fn_row,helper,0,pm,block);ntttcache.push(str_title);nttthasTitle = true;ntt}nntttryntt{ntttstr_line = helper.exec(fn_row,helper,rowID,pm,block);ntt}nttcatch (error)ntt{ntttstr_line = '执行失败';ntt}nttcache.push(str_line); nnttif(!groupByPM && orderFileName=='') //按订单生成 0:订单号 1:自定义单号 2:经销商 3:客户 4:地址ntt{ntttorderFileName = helper.format(filename,block.OrderNo,block.CustomOrderNo,block.CustomerName,block.Consignee,block.ConsigneeAddress);ntt}nt}nntif(groupByPM)nt{nttlet fname = helper.format(filename,pm.GoodsName,pm.Metrial,pm.Color,pm.Thickness,pm.Brank);nttisGb2312 ? helper.pushFile_gb2312(fname,cache.join('rn')) : helper.pushFile(fname,cache.join('rn'));nt}n}nnif(!groupByPM)n{ntisGb2312 ? helper.pushFile_gb2312(orderFileName,cache.join('rn')) : helper.pushFile(orderFileName,cache.join('rn'));n}nn//参数可配置通用电子锯", - "Remark": "", - "cncConfig": { - "zipFileName": "{3}-电子锯文件.zip", - "filename": "{0}_{1}_{2}_{3}.csv", - "gb2312": true, - "groupByPM": true, - "showTitle": true, - "fn_Filter": "return false;", - "fn_row": "let texts = [];nlet isTitle = i ==0;nnaddV('订单号',b.util);naddV('订单号',b.OrderNo);naddV('柜号',b.BoxName);naddV('板件编号',b.BlockNo);nlet ztm = (b.FrontHoleCount+b.FrontModelCount>0 || b.BackHoleCount+b.BackModelCount==0 && b.HoleCount_Side>0 || b.IsUnRegular) ? b.BlockNo+'A' : '';nlet ftm = b.BackHoleCount+b.BackModelCount>0 ? b.BlockNo+'B' : '';naddV('正面条码',ztm);naddV('反面条码',ftm);naddV('产品名称',b.BlockName);naddV('成品名称',b.BlockName);naddV('材质名称',b.Thickness+'mm'+b.MetrialName+b.Color);nlet fL = getNum(b.Wave==2 ? b.Width : b.Length,1);nlet fW = getNum(b.Wave==2 ? b.Length : b.Width,1);naddV('成品长度',fL);naddV('成品宽度',fW);naddV('成品厚度',b.Thickness);nlet cL = getNum(b.Wave==2 ? b.CuttingWidth : b.CuttingLength,1);nlet cW = getNum(b.Wave==2 ? b.CuttingLength : b.CuttingWidth,1);naddV('开料长度',cL);naddV('开料宽度',cW);naddV('开料厚度',b.Thickness);naddV('纹路方向',b.Wave==2 ? '横纹' : '竖纹');naddV('需切数量',1);nlet fc1 = b.IsUnRegular ? '-' : getNum(b.Wave==2 ? b.BorderUpper : b.BorderLeft,1);nlet fc2 = b.IsUnRegular ? '-' : getNum(b.Wave==2 ? b.BorderUnder : b.BorderRight,1);nlet fk1 = b.IsUnRegular ? '-' : getNum(b.Wave==2 ? b.BorderLeft : b.BorderUpper,1);nlet fk2 = b.IsUnRegular ? '-' : getNum(b.Wave==2 ? b.BorderRight : b.BorderUnder,1);naddV('封长1',fc1);naddV('封宽1',fk1);naddV('封长2',fc2);naddV('封宽2',fk2);naddV('订单类型',b.RoomName);naddV('客户信息',b.ConsigneeAddress);naddV('加盟店',b.CustomerName);naddV('异形',b.IsUnRegular ? '异形' : '');naddV('旋转','');naddV('正面槽',b.FrontModelCount);naddV('是否开槽',b.FrontModelCount+b.BackModelCount>0 ? '槽' : '');naddV('反面槽',b.BackModelCount);naddV('正面孔',b.FrontHoleCount);naddV('是否打孔',b.FrontHoleCount+b.BackHoleCount>0 ? '孔' : '');naddV('反面孔',b.BackHoleCount);naddV('拉槽标识',b.FrontModelCount+b.BackModelCount>0 ? '槽' : '');naddV('排钻标识',b.FrontHoleCount+b.BackHoleCount+b.HoleCount_Side>0 ? '钻' : '');naddV('钻孔',b.FrontHoleCount>0 && b.BackHoleCount>0 ? '双' : (b.FrontHoleCount+b.HoleCount_Side>0 || b.BackHoleCount+b.HoleCount_Side>0 ? '单' : ''));naddV('异形ID','');nnreturn texts.join(',');nnfunction addV(title,v)n{n if(v == undefined) v = '';n texts.push(isTitle ? title : v.toString());n}nnfunction getNum(v,b)n{n return v.toFixed(b);n}}" - } - }, - "Remark": "品牌:通用 备注:2020.05.09" - } - """; - json = """ - {"name": "a", "age":2} - """; - IndexResponse indexResponse = esDocumentService.createByJson("t1", String.valueOf(snowFlake.nextId()), json); - System.out.println(indexResponse); - } - - @Test - public void u1() throws IOException { - HashMap objectObjectHashMap = new HashMap<>(); - objectObjectHashMap.put("organId",new int[]{4, 5}); - esDocumentService.updateById("t3", "145455371992043520", HashMap.class, objectObjectHashMap); - } - @Test public void d1() throws IOException { - esDocumentService.deleteById("t1", "145125592260546560"); + Boolean delete = esDocumentService.deleteById("t1", "145125592260546560"); + assertTrue(delete); } diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/controller/admin/oauth2/OAuth2OpenControllerTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/controller/admin/oauth2/OAuth2OpenControllerTest.java index b50781f95..29f920a40 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/controller/admin/oauth2/OAuth2OpenControllerTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/controller/admin/oauth2/OAuth2OpenControllerTest.java @@ -2,8 +2,8 @@ package com.cf.imes.module.system.controller.admin.oauth2; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.lang.Pair; import cn.hutool.core.map.MapUtil; -import com.cf.imes.framework.common.core.KeyValue; import com.cf.imes.framework.common.enums.UserTypeEnum; import com.cf.imes.framework.common.exception.ErrorCode; import com.cf.imes.framework.common.pojo.CommonResult; @@ -211,9 +211,9 @@ public class OAuth2OpenControllerTest extends BaseMockitoUnitTest { // 断言 assertEquals(0, result.getCode()); assertPojoEquals(client, result.getData().getClient()); - assertEquals(new KeyValue<>("read", true), result.getData().getScopes().get(0)); - assertEquals(new KeyValue<>("write", false), result.getData().getScopes().get(1)); - assertEquals(new KeyValue<>("all", false), result.getData().getScopes().get(2)); + assertEquals(new Pair<>("read", true), result.getData().getScopes().get(0)); + assertEquals(new Pair<>("write", false), result.getData().getScopes().get(1)); + assertEquals(new Pair<>("all", false), result.getData().getScopes().get(2)); } @Test diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImplTest.java index 99d651035..2d461c0cc 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/auth/AdminAuthServiceImplTest.java @@ -14,9 +14,7 @@ import com.cf.imes.module.system.enums.logger.LoginLogTypeEnum; import com.cf.imes.module.system.enums.logger.LoginResultEnum; import com.cf.imes.module.system.enums.sms.SmsSceneEnum; import com.cf.imes.module.system.service.logger.LoginLogService; -import com.cf.imes.module.system.service.member.MemberService; import com.cf.imes.module.system.service.oauth2.OAuth2TokenService; -import com.cf.imes.module.system.service.social.SocialUserService; import com.cf.imes.module.system.service.user.AdminUserService; import com.xingyuv.captcha.model.common.ResponseModel; import com.xingyuv.captcha.service.CaptchaService; @@ -28,7 +26,6 @@ import org.springframework.context.annotation.Import; import javax.annotation.Resource; import javax.validation.ConstraintViolationException; import javax.validation.Validation; -import javax.validation.Validator; import static cn.hutool.core.util.RandomUtil.randomEle; import static com.cf.imes.framework.test.core.util.AssertUtils.assertPojoEquals; @@ -53,16 +50,11 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { private CaptchaService captchaService; @MockBean private LoginLogService loginLogService; - @MockBean - private SocialUserService socialUserService; + @MockBean private SmsCodeApi smsCodeApi; @MockBean private OAuth2TokenService oauth2TokenService; - @MockBean - private MemberService memberService; - @MockBean - private Validator validator; @BeforeEach public void setUp() { @@ -148,41 +140,6 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { ); } - @Test - public void testLogin_success() { - /* // 准备参数 - AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class, o -> - o.setUsername("test_username").setPassword("test_password") - .setSocialType(randomEle(SocialTypeEnum.values()).getType())); - - // mock 验证码正确 - ReflectUtil.setFieldValue(authService, "captchaEnable", false); - // mock user 数据 - AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L).setUsername("test_username") - .setPassword("test_password").setStatus(CommonStatusEnum.ENABLE.getStatus())); - when(userService.getUserByUsername(eq("test_username"))).thenReturn(user); - // mock password 匹配 - when(userService.isPasswordMatch(eq("test_password"), eq(user.getPassword()))).thenReturn(true); - // mock 缓存登录用户到 Redis - OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L) - .setUserType(UserTypeEnum.ADMIN.getValue())); - when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull())) - .thenReturn(accessTokenDO); - - // 调用,并校验 - AuthLoginRespVO loginRespVO = authService.login(reqVO); - assertPojoEquals(accessTokenDO, loginRespVO); - // 校验调用参数 - verify(loginLogService).createLoginLog( - argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType()) - && o.getResult().equals(LoginResultEnum.SUCCESS.getResult()) - && o.getUserId().equals(user.getId())) - ); - verify(socialUserService).bindSocialUser(eq(new SocialUserBindReqDTO( - user.getId(), UserTypeEnum.ADMIN.getValue(), - reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState())));*/ - } - @Test public void testSendSmsCode() { // 准备参数 @@ -202,61 +159,6 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { return true; })); } - - @Test - public void testSmsLogin_success() { - /* // 准备参数 - String mobile = randomString(); - String scene = randomString(); - AuthSmsLoginReqVO reqVO = new AuthSmsLoginReqVO(mobile, scene); - // mock 方法(用户信息) - AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L)); - when(userService.getUserByMobile(eq(mobile))).thenReturn(user); - // mock 缓存登录用户到 Redis - OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L) - .setUserType(UserTypeEnum.ADMIN.getValue())); - when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull())) - .thenReturn(accessTokenDO); - - // 调用,并断言 - AuthLoginRespVO loginRespVO = authService.smsLogin(reqVO); - assertPojoEquals(accessTokenDO, loginRespVO); - // 断言调用 - verify(loginLogService).createLoginLog( - argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_MOBILE.getType()) - && o.getResult().equals(LoginResultEnum.SUCCESS.getResult()) - && o.getUserId().equals(user.getId())) - );*/ - } - - @Test - public void testSocialLogin_success() { - /* // 准备参数 - AuthSocialLoginReqVO reqVO = randomPojo(AuthSocialLoginReqVO.class); - // mock 方法(绑定的用户编号) - Long userId = 1L; - when(socialUserService.getSocialUserByCode(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()), - eq(reqVO.getCode()), eq(reqVO.getState()))).thenReturn(new SocialUserRespDTO(randomString(), randomString(), randomString(), userId)); - // mock(用户) - AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId)); - when(userService.getUser(eq(userId))).thenReturn(user); - // mock 缓存登录用户到 Redis - OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L) - .setUserType(UserTypeEnum.ADMIN.getValue())); - when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq("default"), isNull())) - .thenReturn(accessTokenDO); - - // 调用,并断言 - AuthLoginRespVO loginRespVO = authService.socialLogin(reqVO); - assertPojoEquals(accessTokenDO, loginRespVO); - // 断言调用 - verify(loginLogService).createLoginLog( - argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_SOCIAL.getType()) - && o.getResult().equals(LoginResultEnum.SUCCESS.getResult()) - && o.getUserId().equals(user.getId())) - );*/ - } - @Test public void testValidateCaptcha_successWithEnable() { // 准备参数 diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/machine/MachineServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/machine/MachineServiceImplTest.java index b71439c8d..11e0a25ba 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/machine/MachineServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/machine/MachineServiceImplTest.java @@ -2,42 +2,29 @@ package com.cf.imes.module.system.service.machine; import com.cf.imes.framework.organ.core.context.OrganContextHolder; import com.cf.imes.module.system.controller.admin.machine.vo.CuttingSaveReqVO; +import com.fasterxml.jackson.core.JsonProcessingException; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import javax.annotation.Resource; import static com.cf.imes.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.assertThrows; @SpringBootTest class MachineServiceImplTest { @Resource private MachineService machineService; -// @Test -// void create() { -// OrganContextHolder.setOrganId(1L); -// for (int i = 0; i < 20; i++) { -// CuttingSaveReqVO saveReqVO = randomPojo(CuttingSaveReqVO.class); -// saveReqVO.setId(null); -// Long aLong = machineService.createCutting(saveReqVO); -// } -// -// } - @Test - void update() { - } + void create() { + OrganContextHolder.setOrganId(1L); + for (int i = 0; i < 20; i++) { + CuttingSaveReqVO saveReqVO = randomPojo(CuttingSaveReqVO.class); + saveReqVO.setId(null); + // 调用,并断言 + assertThrows(JsonProcessingException.class, () -> machineService.createCutting(saveReqVO)); + } - @Test - void delete() { - } - - @Test - void get() { - } - - @Test - void getPage() { } } \ No newline at end of file diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/mail/MailSendServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/mail/MailSendServiceImplTest.java index a1e1cc5bd..a05536b9f 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/mail/MailSendServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/mail/MailSendServiceImplTest.java @@ -29,6 +29,7 @@ import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceExce import static com.cf.imes.framework.test.core.util.RandomUtils.*; import static com.cf.imes.module.system.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; @@ -63,6 +64,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { .setHost("smtp.163.com").setPort(465).setSslEnable(true) // SMTP 服务器 .setAuth(true).setUser("ydym_test@163.com").setPass("WBZTEINMIFVRYSOE"); // 登录账号密码 String messageId = MailUtil.send(mailAccount, "7685413@qq.com", "主题", "内容", false); + assertNotNull(messageId); System.out.println("发送结果:" + messageId); } diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/oauth2/OAuth2GrantServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/oauth2/OAuth2GrantServiceImplTest.java index bb9215d10..87e415abb 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/oauth2/OAuth2GrantServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/oauth2/OAuth2GrantServiceImplTest.java @@ -4,8 +4,6 @@ import com.cf.imes.framework.common.enums.UserTypeEnum; import com.cf.imes.framework.test.core.ut.BaseMockitoUnitTest; import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import com.cf.imes.module.system.dal.dataobject.oauth2.OAuth2CodeDO; -import com.cf.imes.module.system.dal.dataobject.user.AdminUserDO; -import com.cf.imes.module.system.service.auth.AdminAuthService; import com.google.common.collect.Lists; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; @@ -35,25 +33,6 @@ public class OAuth2GrantServiceImplTest extends BaseMockitoUnitTest { private OAuth2TokenService oauth2TokenService; @Mock private OAuth2CodeService oauth2CodeService; - @Mock - private AdminAuthService adminAuthService; - - @Test - public void testGrantImplicit() { - /*// 准备参数 - Long userId = randomLongId(); - Integer userType = randomEle(UserTypeEnum.values()).getValue(); - String clientId = randomString(); - List scopes = Lists.newArrayList("read", "write"); - // mock 方法 - OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class); - when(oauth2TokenService.createAccessToken(eq(userId), eq(userType), - eq(clientId), eq(scopes))).thenReturn(accessTokenDO); - - // 调用,并断言 - assertPojoEquals(accessTokenDO, oauth2GrantService.grantImplicit( - userId, userType, clientId, scopes));*/ - } @Test public void testGrantAuthorizationCodeForCode() { @@ -74,52 +53,6 @@ public class OAuth2GrantServiceImplTest extends BaseMockitoUnitTest { clientId, scopes, redirectUri, state)); } - @Test - public void testGrantAuthorizationCodeForAccessToken() { - /*// 准备参数 - String clientId = randomString(); - String code = randomString(); - List scopes = Lists.newArrayList("read", "write"); - String redirectUri = randomString(); - String state = randomString(); - // mock 方法(code) - OAuth2CodeDO codeDO = randomPojo(OAuth2CodeDO.class, o -> { - o.setClientId(clientId); - o.setRedirectUri(redirectUri); - o.setState(state); - o.setScopes(scopes); - }); - when(oauth2CodeService.consumeAuthorizationCode(eq(code))).thenReturn(codeDO); - // mock 方法(创建令牌) - OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class); - when(oauth2TokenService.createAccessToken(eq(codeDO.getUserId()), eq(codeDO.getUserType()), - eq(codeDO.getClientId()), eq(codeDO.getScopes()))).thenReturn(accessTokenDO); - - // 调用,并断言 - assertPojoEquals(accessTokenDO, oauth2GrantService.grantAuthorizationCodeForAccessToken( - clientId, code, redirectUri, state));*/ - } - - @Test - public void testGrantPassword() { - /*// 准备参数 - String username = randomString(); - String password = randomString(); - String clientId = randomString(); - List scopes = Lists.newArrayList("read", "write"); - // mock 方法(认证) - AdminUserDO user = randomPojo(AdminUserDO.class); - when(adminAuthService.authenticate(eq(username), eq(password))).thenReturn(user); - // mock 方法(访问令牌) - OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class); - when(oauth2TokenService.createAccessToken(eq(user.getId()), eq(UserTypeEnum.ADMIN.getValue()), - eq(clientId), eq(scopes))).thenReturn(accessTokenDO); - - // 调用,并断言 - assertPojoEquals(accessTokenDO, oauth2GrantService.grantPassword( - username, password, clientId, scopes));*/ - } - @Test public void testGrantRefreshToken() { // 准备参数 diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/oauth2/OAuth2TokenServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/oauth2/OAuth2TokenServiceImplTest.java index 5946b0566..59342d9fd 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/oauth2/OAuth2TokenServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/oauth2/OAuth2TokenServiceImplTest.java @@ -50,38 +50,6 @@ public class OAuth2TokenServiceImplTest extends BaseDbAndRedisUnitTest { @MockBean private OAuth2ClientService oauth2ClientService; - @Test - public void testCreateAccessToken() { - /* TenantContextHolder.setOrganId(0L); - // 准备参数 - Long userId = randomLongId(); - Integer userType = RandomUtil.randomEle(UserTypeEnum.values()).getValue(); - String clientId = randomString(); - List scopes = Lists.newArrayList("read", "write"); - // mock 方法 - OAuth2ClientDO clientDO = randomPojo(OAuth2ClientDO.class).setClientId(clientId) - .setAccessTokenValiditySeconds(30).setRefreshTokenValiditySeconds(60); - when(oauth2ClientService.validOAuthClientFromCache(eq(clientId))).thenReturn(clientDO); - - // 调用 - OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, userType, clientId, scopes); - // 断言访问令牌 - OAuth2AccessTokenDO dbAccessTokenDO = oauth2AccessTokenMapper.selectByAccessToken(accessTokenDO.getAccessToken()); - assertPojoEquals(accessTokenDO, dbAccessTokenDO, "createTime", "updateTime", "deleted"); - assertEquals(userId, accessTokenDO.getUserId()); - assertEquals(userType, accessTokenDO.getUserType()); - assertEquals(clientId, accessTokenDO.getClientId()); - assertEquals(scopes, accessTokenDO.getScopes()); - assertFalse(DateUtils.isExpired(accessTokenDO.getExpiresTime())); - // 断言访问令牌的缓存 - OAuth2AccessTokenDO redisAccessTokenDO = oauth2AccessTokenRedisDAO.get(accessTokenDO.getAccessToken()); - assertPojoEquals(accessTokenDO, redisAccessTokenDO, "createTime", "updateTime", "deleted"); - // 断言刷新令牌 - OAuth2RefreshTokenDO refreshTokenDO = oauth2RefreshTokenMapper.selectList().get(0); - assertPojoEquals(accessTokenDO, refreshTokenDO, "id", "expiresTime", "createTime", "updateTime", "deleted"); - assertFalse(DateUtils.isExpired(refreshTokenDO.getExpiresTime()));*/ - } - @Test public void testRefreshAccessToken_null() { // 准备参数 diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/organ/TenantServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/organ/TenantServiceImplTest.java index 73c69078d..380f9de15 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/organ/TenantServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/organ/TenantServiceImplTest.java @@ -1,6 +1,7 @@ package com.cf.imes.module.system.service.organ; import com.cf.imes.framework.common.enums.CommonStatusEnum; +import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.organ.config.OrganProperties; import com.cf.imes.framework.organ.core.context.OrganContextHolder; @@ -123,7 +124,7 @@ public class TenantServiceImplTest extends BaseDbUnitTest { tenantMapper.insert(tenant); // 调用,并断言业务异常 - tenantService.validOrgan(1L); + assertServiceException(() -> tenantService.validOrgan(1L), ORGAN_NOT_EXISTS, ORGAN_DISABLE, ORGAN_EXPIRE); } @Test diff --git a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsSendServiceImplTest.java b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsSendServiceImplTest.java index a21c8b6ef..b5816b223 100644 --- a/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsSendServiceImplTest.java +++ b/cf-module-system/cf-module-system-biz/src/test/java/com/cf/imes/module/system/service/sms/SmsSendServiceImplTest.java @@ -1,7 +1,7 @@ package com.cf.imes.module.system.service.sms; +import cn.hutool.core.lang.Pair; import cn.hutool.core.map.MapUtil; -import com.cf.imes.framework.common.core.KeyValue; import com.cf.imes.framework.common.enums.CommonStatusEnum; import com.cf.imes.framework.common.enums.UserTypeEnum; import com.cf.imes.framework.sms.core.client.SmsClient; @@ -30,6 +30,7 @@ import static com.cf.imes.framework.test.core.util.AssertUtils.assertServiceExce import static com.cf.imes.framework.test.core.util.RandomUtils.*; import static com.cf.imes.module.system.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; @@ -86,7 +87,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { assertEquals(smsLogId, resultSmsLogId); // 断言调用 verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(user.getMobile()), eq(template), - eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login")))); + eq(Lists.newArrayList(new Pair<>("code", "1234"), new Pair<>("op", "login")))); } @Test @@ -124,7 +125,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { assertEquals(smsLogId, resultSmsLogId); // 断言调用 verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(mobile), eq(template), - eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login")))); + eq(Lists.newArrayList(new Pair<>("code", "1234"), new Pair<>("op", "login")))); } /** @@ -163,7 +164,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { assertEquals(smsLogId, resultSmsLogId); // 断言调用 verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(mobile), eq(template), - eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login")))); + eq(Lists.newArrayList(new Pair<>("code", "1234"), new Pair<>("op", "login")))); } /** @@ -285,7 +286,7 @@ public class SmsSendServiceImplTest extends BaseMockitoUnitTest { List receiveResults = randomPojoList(SmsReceiveRespDTO.class); // 调用 - smsSendService.receiveSmsStatus(channelCode, text); + assertThrows(Throwable.class, () -> smsSendService.receiveSmsStatus(channelCode, text)); // 断言 receiveResults.forEach(result -> smsLogService.updateSmsReceiveResult(eq(result.getLogId()), eq(result.getSuccess()), eq(result.getReceiveTime()), eq(result.getErrorCode()), eq(result.getErrorCode())));