From 74df3581efd70549c3c20815f028a49feb74ea97 Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Mon, 6 Jul 2026 14:21:50 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E5=88=86=E7=B1=BB=E5=B7=A5=E8=89=BA=E8=B7=AF=E7=BA=BF=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/ErpProductCategoryController.java | 3 +- .../admin/product/ErpProductController.java | 8 ++ ...ProductCategoryProcessRouteItemRespVO.java | 37 ++++++++++ .../vo/category/ErpProductCategoryRespVO.java | 10 +++ .../category/ErpProductCategorySaveReqVO.java | 3 + .../product/ErpProductProcessRouteRespVO.java | 25 +++++++ .../product/vo/product/ErpProductRespVO.java | 10 +++ .../product/ErpProductCategoryDO.java | 9 +++ .../ErpProductCategoryProcessRouteItemDO.java | 35 +++++++++ ...ProductCategoryProcessRouteItemMapper.java | 25 +++++++ .../product/ErpProductCategoryService.java | 7 +- .../ErpProductCategoryServiceImpl.java | 74 ++++++++++++++++++- .../service/product/ErpProductService.java | 3 + .../product/ErpProductServiceImpl.java | 28 +++++++ .../mes/api/processroute/ProcessRouteApi.java | 12 +++ .../dto/ProcessRouteItemSnapshotRespDTO.java | 25 +++++++ .../dto/ProcessRouteSnapshotRespDTO.java | 21 ++++++ .../api/processroute/ProcessRouteApiImpl.java | 40 ++++++++++ 18 files changed, 371 insertions(+), 4 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryProcessRouteItemRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductProcessRouteRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryProcessRouteItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductCategoryProcessRouteItemMapper.java create mode 100644 yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/ProcessRouteApi.java create mode 100644 yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/dto/ProcessRouteItemSnapshotRespDTO.java create mode 100644 yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/dto/ProcessRouteSnapshotRespDTO.java create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/ProcessRouteApiImpl.java diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java index f658f70fa..a72d06509 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java @@ -70,8 +70,7 @@ public class ErpProductCategoryController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('erp:product-category:query')") public CommonResult getProductCategory(@RequestParam("id") Long id) { - ErpProductCategoryDO category = productCategoryService.getProductCategory(id); - return success(BeanUtils.toBean(category, ErpProductCategoryRespVO.class)); + return success(productCategoryService.getProductCategoryResp(id)); } @GetMapping("/list") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java index 3531d5b7b..8d164f472 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java @@ -110,6 +110,14 @@ public class ErpProductController { return success(productService.getProduct(id, code)); } + @GetMapping("/get-process-route") + @Operation(summary = "获得产品对应的工艺路线快照") + @Parameter(name = "productId", description = "产品编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('erp:product:query')") + public CommonResult getProductProcessRoute(@RequestParam("productId") Long productId) { + return success(productService.getProductProcessRoute(productId)); + } + @GetMapping("/page") @Operation(summary = "获得产品分页") @PreAuthorize("@ss.hasPermission('erp:product:query')") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryProcessRouteItemRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryProcessRouteItemRespVO.java new file mode 100644 index 000000000..a346a9323 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryProcessRouteItemRespVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - ERP 产品分类工艺路线明细快照 Response VO") +@Data +public class ErpProductCategoryProcessRouteItemRespVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "产品分类编号", example = "1") + private Long categoryId; + + @Schema(description = "工艺路线编号", example = "1") + private Long processRouteId; + + @Schema(description = "工艺路线明细编号", example = "1") + private Long processRouteItemId; + + @Schema(description = "排序,从 1 开始", example = "1") + private Integer sort; + + @Schema(description = "工艺参数编号", example = "100") + private Long processParameterId; + + @Schema(description = "工艺参数编码") + private String processParameterCode; + + @Schema(description = "工艺参数名称") + private String processParameterName; + + @Schema(description = "备注") + private String remark; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java index 267c40a10..45fd42ced 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java @@ -11,6 +11,7 @@ import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.PRODUCT_CATEGO import static cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS; import java.time.LocalDateTime; +import java.util.List; @Schema(description = "管理后台 - ERP 产品分类 Response VO") @Data @@ -51,4 +52,13 @@ public class ErpProductCategoryRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; + @Schema(description = "工艺路线 ID,对应 /mes/process-route", example = "1") + private Long processRouteId; + + @Schema(description = "工艺路线名称") + private String processRouteName; + + @Schema(description = "工艺路线明细快照") + private List processRouteItems; + } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java index 6ecbe2e6f..d2090b5dd 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java @@ -37,4 +37,7 @@ public class ErpProductCategorySaveReqVO { @NotNull(message = "开启状态不能为空") private Integer status; + @Schema(description = "工艺路线 ID,对应 /mes/process-route", example = "1") + private Long processRouteId; + } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductProcessRouteRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductProcessRouteRespVO.java new file mode 100644 index 000000000..d2a20238a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductProcessRouteRespVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; + +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryProcessRouteItemRespVO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(description = "管理后台 - ERP 产品工艺路线快照 Response VO") +@Data +public class ErpProductProcessRouteRespVO { + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "工艺路线 ID,对应 /mes/process-route", example = "1") + private Long processRouteId; + + @Schema(description = "工艺路线名称") + private String processRouteName; + + @Schema(description = "工艺路线明细快照") + private List processRouteItems; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java index c6577d0b5..140ace001 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryProcessRouteItemRespVO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; @@ -162,4 +163,13 @@ public class ErpProductRespVO extends ErpProductDO { @Schema(description = "默认供应商 ID", example = "1") private Long defaultSupplierId; + + @Schema(description = "产品分类关联的工艺路线 ID,对应 /mes/process-route", example = "1") + private Long processRouteId; + + @Schema(description = "产品分类关联的工艺路线名称") + private String processRouteName; + + @Schema(description = "产品分类保存的工艺路线明细快照") + private List processRouteItems; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryDO.java index a68184cee..41cba9b2e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryDO.java @@ -57,4 +57,13 @@ public class ErpProductCategoryDO extends BaseDO { */ private Integer status; + /** + * 工艺路线 ID + */ + private Long processRouteId; + /** + * 工艺路线名称 + */ + private String processRouteName; + } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryProcessRouteItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryProcessRouteItemDO.java new file mode 100644 index 000000000..9d16999a8 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryProcessRouteItemDO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.product; + +import cn.iocoder.yudao.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.*; + +/** + * ERP 产品分类工艺路线明细快照 DO + */ +@TableName("erp_product_category_process_route_item") +@KeySequence("erp_product_category_process_route_item_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpProductCategoryProcessRouteItemDO extends BaseDO { + + @TableId + private Long id; + + private Long categoryId; + + private Long processRouteId; + private Long processRouteItemId; + private Integer sort; + private Long processParameterId; + private String processParameterCode; + private String processParameterName; + private String remark; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductCategoryProcessRouteItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductCategoryProcessRouteItemMapper.java new file mode 100644 index 000000000..222c42ad0 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductCategoryProcessRouteItemMapper.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.product; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryProcessRouteItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface ErpProductCategoryProcessRouteItemMapper extends BaseMapperX { + + default List selectListByCategoryId(Long categoryId) { + return selectList(new LambdaQueryWrapperX() + .eq(ErpProductCategoryProcessRouteItemDO::getCategoryId, categoryId) + .orderByAsc(ErpProductCategoryProcessRouteItemDO::getSort) + .orderByAsc(ErpProductCategoryProcessRouteItemDO::getId)); + } + + default void deleteByCategoryId(Long categoryId) { + delete(new LambdaQueryWrapperX() + .eq(ErpProductCategoryProcessRouteItemDO::getCategoryId, categoryId)); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java index 00a4cc143..abe0d8b21 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.erp.service.product; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryRespVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategorySaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; @@ -49,6 +50,10 @@ public interface ErpProductCategoryService { */ ErpProductCategoryDO getProductCategory(Long id); + ErpProductCategoryRespVO getProductCategoryResp(Long id); + + ErpProductCategoryRespVO buildProductCategoryResp(ErpProductCategoryDO category); + /** * 获得产品分类列表 * @@ -84,4 +89,4 @@ public interface ErpProductCategoryService { */ ErpProductCategoryDO getProductCategoryByName(String name); -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java index 0b1b2384a..359395c6e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java @@ -2,14 +2,23 @@ package cn.iocoder.yudao.module.erp.service.product; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryProcessRouteItemRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryRespVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategorySaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryProcessRouteItemDO; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductCategoryMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductCategoryProcessRouteItemMapper; +import cn.iocoder.yudao.module.mes.api.processroute.ProcessRouteApi; +import cn.iocoder.yudao.module.mes.api.processroute.dto.ProcessRouteItemSnapshotRespDTO; +import cn.iocoder.yudao.module.mes.api.processroute.dto.ProcessRouteSnapshotRespDTO; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; @@ -29,11 +38,18 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService @Resource private ErpProductCategoryMapper erpProductCategoryMapper; + @Resource + private ErpProductCategoryProcessRouteItemMapper productCategoryProcessRouteItemMapper; + + @Resource + private ProcessRouteApi processRouteApi; + @Resource @Lazy // 延迟加载,避免循环依赖 private ErpProductService productService; @Override + @Transactional(rollbackFor = Exception.class) public Long createProductCategory(ErpProductCategorySaveReqVO createReqVO) { // 校验父分类编号的有效性 validateParentProductCategory(null, createReqVO.getParentId()); @@ -42,12 +58,15 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService // 插入 ErpProductCategoryDO category = BeanUtils.toBean(createReqVO, ErpProductCategoryDO.class); + fillProcessRouteSnapshot(category); erpProductCategoryMapper.insert(category); + saveProcessRouteItemSnapshot(category.getId(), category.getProcessRouteId()); // 返回 return category.getId(); } @Override + @Transactional(rollbackFor = Exception.class) public void updateProductCategory(ErpProductCategorySaveReqVO updateReqVO) { // 校验存在 validateProductCategoryExists(updateReqVO.getId()); @@ -58,7 +77,10 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService // 更新 ErpProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductCategoryDO.class); + fillProcessRouteSnapshot(updateObj); erpProductCategoryMapper.updateById(updateObj); + productCategoryProcessRouteItemMapper.deleteByCategoryId(updateReqVO.getId()); + saveProcessRouteItemSnapshot(updateReqVO.getId(), updateObj.getProcessRouteId()); } @Override @@ -74,9 +96,43 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService throw exception(PRODUCT_CATEGORY_EXITS_PRODUCT); } // 2. 删除 + productCategoryProcessRouteItemMapper.deleteByCategoryId(id); erpProductCategoryMapper.deleteById(id); } + private void fillProcessRouteSnapshot(ErpProductCategoryDO category) { + if (category.getProcessRouteId() == null) { + category.setProcessRouteName(null); + return; + } + ProcessRouteSnapshotRespDTO processRoute = processRouteApi.getProcessRouteSnapshot(category.getProcessRouteId()); + category.setProcessRouteName(processRoute == null ? null : processRoute.getName()); + } + + private void saveProcessRouteItemSnapshot(Long categoryId, Long processRouteId) { + if (categoryId == null || processRouteId == null) { + return; + } + ProcessRouteSnapshotRespDTO processRoute = processRouteApi.getProcessRouteSnapshot(processRouteId); + if (processRoute == null || processRoute.getItems() == null || processRoute.getItems().isEmpty()) { + return; + } + List saveList = new ArrayList<>(); + for (ProcessRouteItemSnapshotRespDTO item : processRoute.getItems()) { + ErpProductCategoryProcessRouteItemDO snapshot = new ErpProductCategoryProcessRouteItemDO(); + snapshot.setCategoryId(categoryId); + snapshot.setProcessRouteId(processRouteId); + snapshot.setProcessRouteItemId(item.getId()); + snapshot.setSort(item.getSort()); + snapshot.setProcessParameterId(item.getProcessParameterId()); + snapshot.setProcessParameterCode(item.getProcessParameterCode()); + snapshot.setProcessParameterName(item.getProcessParameterName()); + snapshot.setRemark(item.getRemark()); + saveList.add(snapshot); + } + productCategoryProcessRouteItemMapper.insertBatch(saveList); + } + private void validateProductCategoryExists(Long id) { if (erpProductCategoryMapper.selectById(id) == null) { throw exception(PRODUCT_CATEGORY_NOT_EXISTS); @@ -136,6 +192,22 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService return erpProductCategoryMapper.selectById(id); } + @Override + public ErpProductCategoryRespVO getProductCategoryResp(Long id) { + return buildProductCategoryResp(getProductCategory(id)); + } + + @Override + public ErpProductCategoryRespVO buildProductCategoryResp(ErpProductCategoryDO category) { + if (category == null) { + return null; + } + ErpProductCategoryRespVO respVO = BeanUtils.toBean(category, ErpProductCategoryRespVO.class); + List items = productCategoryProcessRouteItemMapper.selectListByCategoryId(category.getId()); + respVO.setProcessRouteItems(BeanUtils.toBean(items, ErpProductCategoryProcessRouteItemRespVO.class)); + return respVO; + } + @Override public List getProductCategoryList(ErpProductCategoryListReqVO listReqVO) { return erpProductCategoryMapper.selectList(listReqVO); @@ -151,4 +223,4 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService return erpProductCategoryMapper.selectByName(name); } -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java index 39923fa0e..2ad0a7957 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.erp.service.product; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductImportExcelVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductProcessRouteRespVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductImportRespVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductListReqVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO; @@ -67,6 +68,8 @@ public interface ErpProductService { ErpProductRespVO getProduct(Long id, String code); + ErpProductProcessRouteRespVO getProductProcessRoute(Long productId); + /** * 获得指定状态的产品 VO 列表 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java index 6301e561a..f2071787d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.common.enums.CodeTypeEnum; import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum; import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService; import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryRespVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.*; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpPackagingSchemeDO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; @@ -417,6 +418,12 @@ public class ErpProductServiceImpl implements ErpProductService { .ifPresent(item -> respVO.setDefaultSupplierId(item.getSupplierId())); if (erpProductCategoryDO !=null ){ respVO.setCategoryType(erpProductCategoryDO.getType()); + ErpProductCategoryRespVO categoryRespVO = productCategoryService.buildProductCategoryResp(erpProductCategoryDO); + if (categoryRespVO != null) { + respVO.setProcessRouteId(categoryRespVO.getProcessRouteId()); + respVO.setProcessRouteName(categoryRespVO.getProcessRouteName()); + respVO.setProcessRouteItems(categoryRespVO.getProcessRouteItems()); + } } if (respVO.getPurchaseUnitId() != null && respVO.getPurchaseUnitName() == null) { ErpProductUnitDO purchaseUnit = productUnitService.getProductUnit(respVO.getPurchaseUnitId()); @@ -522,6 +529,27 @@ public class ErpProductServiceImpl implements ErpProductService { throw exception(PRODUCT_NOT_EXISTS); } + @Override + public ErpProductProcessRouteRespVO getProductProcessRoute(Long productId) { + ErpProductDO product = productMapper.selectById(productId); + if (product == null) { + return null; + } + ErpProductProcessRouteRespVO respVO = new ErpProductProcessRouteRespVO(); + respVO.setProductId(productId); + Long categoryId = product.getSubCategoryId() != null ? product.getSubCategoryId() : product.getCategoryId(); + if (categoryId == null) { + return respVO; + } + ErpProductCategoryRespVO categoryRespVO = productCategoryService.buildProductCategoryResp(productCategoryMapper.selectById(categoryId)); + if (categoryRespVO != null) { + respVO.setProcessRouteId(categoryRespVO.getProcessRouteId()); + respVO.setProcessRouteName(categoryRespVO.getProcessRouteName()); + respVO.setProcessRouteItems(categoryRespVO.getProcessRouteItems()); + } + return respVO; + } + private boolean isSpareProductCategory(ErpProductRespVO product) { Long categoryId = product.getSubCategoryId() != null ? product.getSubCategoryId() : product.getCategoryId(); if (categoryId == null) { diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/ProcessRouteApi.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/ProcessRouteApi.java new file mode 100644 index 000000000..0589f8767 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/ProcessRouteApi.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.module.mes.api.processroute; + +import cn.iocoder.yudao.module.mes.api.processroute.dto.ProcessRouteSnapshotRespDTO; + +/** + * 工艺路线 API + */ +public interface ProcessRouteApi { + + ProcessRouteSnapshotRespDTO getProcessRouteSnapshot(Long id); + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/dto/ProcessRouteItemSnapshotRespDTO.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/dto/ProcessRouteItemSnapshotRespDTO.java new file mode 100644 index 000000000..1c1dd1f1e --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/dto/ProcessRouteItemSnapshotRespDTO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.mes.api.processroute.dto; + +import lombok.Data; + +/** + * 工艺路线明细快照 DTO + */ +@Data +public class ProcessRouteItemSnapshotRespDTO { + + private Long id; + + private Long routeId; + + private Integer sort; + + private Long processParameterId; + + private String processParameterCode; + + private String processParameterName; + + private String remark; + +} diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/dto/ProcessRouteSnapshotRespDTO.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/dto/ProcessRouteSnapshotRespDTO.java new file mode 100644 index 000000000..63722c8a1 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/dto/ProcessRouteSnapshotRespDTO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.mes.api.processroute.dto; + +import lombok.Data; + +import java.util.List; + +/** + * 工艺路线快照 DTO + */ +@Data +public class ProcessRouteSnapshotRespDTO { + + private Long id; + + private String code; + + private String name; + + private List items; + +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/ProcessRouteApiImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/ProcessRouteApiImpl.java new file mode 100644 index 000000000..f25d0d18f --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/api/processroute/ProcessRouteApiImpl.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.api.processroute; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.api.processroute.dto.ProcessRouteItemSnapshotRespDTO; +import cn.iocoder.yudao.module.mes.api.processroute.dto.ProcessRouteSnapshotRespDTO; +import cn.iocoder.yudao.module.mes.dal.dataobject.processroute.ProcessRouteDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.processroute.ProcessRouteItemDO; +import cn.iocoder.yudao.module.mes.dal.mysql.processroute.ProcessRouteItemMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.processroute.ProcessRouteMapper; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 工艺路线 API 实现 + */ +@Service +public class ProcessRouteApiImpl implements ProcessRouteApi { + + @Resource + private ProcessRouteMapper processRouteMapper; + @Resource + private ProcessRouteItemMapper processRouteItemMapper; + + @Override + public ProcessRouteSnapshotRespDTO getProcessRouteSnapshot(Long id) { + if (id == null) { + return null; + } + ProcessRouteDO processRoute = processRouteMapper.selectById(id); + if (processRoute == null) { + return null; + } + ProcessRouteSnapshotRespDTO respDTO = BeanUtils.toBean(processRoute, ProcessRouteSnapshotRespDTO.class); + List items = processRouteItemMapper.selectListByRouteId(id); + respDTO.setItems(BeanUtils.toBean(items, ProcessRouteItemSnapshotRespDTO.class)); + return respDTO; + } +} From 20440ed330da520ea7dd9016d1dd3983e86bd760 Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Mon, 6 Jul 2026 16:39:54 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9=E5=87=BA=E5=BA=93?= =?UTF-8?q?=E5=8D=95=E6=8D=AE=E6=98=BE=E7=A4=BA=E9=94=81=E5=AE=9A=E5=BA=93?= =?UTF-8?q?=E5=AD=98=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/pallet/ErpPalletController.java | 18 +++++++- .../admin/pallet/vo/ErpPalletRespVO.java | 3 ++ .../admin/stock/ErpStockController.java | 7 +++ .../admin/stock/vo/stock/ErpStockRespVO.java | 3 ++ .../erp/dal/mysql/pallet/ErpPalletMapper.java | 21 ++++++--- .../erp/dal/mysql/stock/ErpStockMapper.java | 25 +++++++++-- .../mysql/stock/ErpStockOutItemMapper.java | 6 +++ .../stock/ErpStockOutItemPalletMapper.java | 44 +++++++++++++++++++ .../erp/service/pallet/ErpPalletService.java | 3 ++ .../service/pallet/ErpPalletServiceImpl.java | 15 +++++++ .../service/stock/ErpStockOutServiceImpl.java | 16 ++++--- .../mapper/autocode/ErpStockOutItemMapper.xml | 23 ++++++++++ 12 files changed, 167 insertions(+), 17 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/ErpPalletController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/ErpPalletController.java index 53f073510..c37e88a3c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/ErpPalletController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/ErpPalletController.java @@ -25,6 +25,7 @@ import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; import java.util.List; import java.util.Map; @@ -84,7 +85,10 @@ public class ErpPalletController { PageResult pageResult = palletService.getPalletPage(pageReqVO); Map qrcodeMap = qrcodeService.selectQrcodeUrlMapByBizTypeAndIds(QrcodeBizTypeEnum.PALLET.getCode(), convertList(pageResult.getList(), ErpPalletDO::getId)); - List list = convertList(pageResult.getList(), pallet -> buildPalletRespVO(pallet, qrcodeMap)); + Map lockedPackageCountMap = palletService.getLockedPackageCountMap( + convertList(pageResult.getList(), ErpPalletDO::getId)); + List list = convertList(pageResult.getList(), + pallet -> buildPalletRespVO(pallet, qrcodeMap, lockedPackageCountMap)); return success(new PageResult<>(list, pageResult.getTotal())); } @@ -98,7 +102,10 @@ public class ErpPalletController { PageResult pageResult = palletService.getPalletPage(pageReqVO); Map qrcodeMap = qrcodeService.selectQrcodeUrlMapByBizTypeAndIds(QrcodeBizTypeEnum.PALLET.getCode(), convertList(pageResult.getList(), ErpPalletDO::getId)); - List list = convertList(pageResult.getList(), pallet -> buildPalletRespVO(pallet, qrcodeMap)); + Map lockedPackageCountMap = palletService.getLockedPackageCountMap( + convertList(pageResult.getList(), ErpPalletDO::getId)); + List list = convertList(pageResult.getList(), + pallet -> buildPalletRespVO(pallet, qrcodeMap, lockedPackageCountMap)); ExcelUtils.write(response, "托盘.xls", "数据", ErpPalletRespVO.class, list); } @@ -151,6 +158,13 @@ public class ErpPalletController { return respVO; } + private ErpPalletRespVO buildPalletRespVO(ErpPalletDO pallet, Map qrcodeMap, + Map lockedPackageCountMap) { + ErpPalletRespVO respVO = buildPalletRespVO(pallet, qrcodeMap); + respVO.setLockedPackageCount(lockedPackageCountMap.getOrDefault(pallet.getId(), BigDecimal.ZERO)); + return respVO; + } + private void fillPackagingInfo(ErpPalletRespVO respVO) { if (respVO == null) { return; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletRespVO.java index 95335de51..5b7681b44 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletRespVO.java @@ -69,6 +69,9 @@ public class ErpPalletRespVO { @Schema(description = "当前包数", example = "20") private BigDecimal packageCount; + @Schema(description = "锁定包数", example = "5") + private BigDecimal lockedPackageCount; + @Schema(description = "二维码", example = "https://xxx.com/qrcode/pallet/1") @ExcelProperty("二维码") private String qrcode; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java index 334ab92e9..3a182c8d1 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java @@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemMapper; import cn.iocoder.yudao.module.erp.service.pallet.ErpPalletService; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; @@ -70,6 +71,10 @@ public class ErpStockController { private ErpStockRecordService stockRecordService; @Resource private ErpPalletService palletService; + @Resource + private ErpStockOutItemMapper stockOutItemMapper; + + private static final List LOCKED_STOCK_OUT_STATUSES = java.util.Arrays.asList(10, 0, 1); @GetMapping("/get") @Operation(summary = "获得产品库存") @@ -174,6 +179,8 @@ public class ErpStockController { fillPackagingSnapshot(respVO, product); } fillDerivedFields(respVO); + respVO.setLockedStockCount(stockOutItemMapper.selectLockedStockCount( + respVO.getProductId(), respVO.getWarehouseId(), respVO.getAreaId(), LOCKED_STOCK_OUT_STATUSES)); respVO.setPalletCount(getPalletCount(respVO)); respVO.setPackagingRule(buildPackagingRule(respVO)); respVO.setStockDisplay(buildStockDisplay(respVO)); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java index 893779d4e..ea80e6a56 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java @@ -39,6 +39,9 @@ public class ErpStockRespVO { @ExcelProperty("库存数量") private BigDecimal count; + @Schema(description = "锁定库存数量", example = "10") + private BigDecimal lockedStockCount; + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11161") private Long categoryId; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/pallet/ErpPalletMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/pallet/ErpPalletMapper.java index feeca1ca9..4d16caf4a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/pallet/ErpPalletMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/pallet/ErpPalletMapper.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.erp.dal.mysql.pallet; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.enums.ErpPalletStatusEnum; import cn.iocoder.yudao.module.erp.controller.admin.pallet.vo.ErpPalletPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; import org.apache.ibatis.annotations.Mapper; @@ -16,19 +17,29 @@ import java.util.List; public interface ErpPalletMapper extends BaseMapperX { default PageResult selectPage(ErpPalletPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() + LambdaQueryWrapperX query = new LambdaQueryWrapperX() .likeIfPresent(ErpPalletDO::getCode, reqVO.getCode()) .eqIfPresent(ErpPalletDO::getPalletType, reqVO.getPalletType()) - .eqIfPresent(ErpPalletDO::getStatus, reqVO.getStatus()) - .neIfPresent(ErpPalletDO::getStatus, reqVO.getExcludeStatus()) .eqIfPresent(ErpPalletDO::getWarehouseId, reqVO.getWarehouseId()) .eqIfPresent(ErpPalletDO::getAreaId, reqVO.getAreaId()) .likeIfPresent(ErpPalletDO::getPlanCode, reqVO.getPlanCode()) - .eqIfPresent(ErpPalletDO::getProductId, reqVO.getProductId()) .betweenIfPresent(ErpPalletDO::getPurchaseDate, reqVO.getPurchaseDate()) .betweenIfPresent(ErpPalletDO::getUseDate, reqVO.getUseDate()) .betweenIfPresent(ErpPalletDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(ErpPalletDO::getId)); + .orderByDesc(ErpPalletDO::getId); + if (reqVO.getProductId() != null && reqVO.getExcludeStatus() != null && reqVO.getStatus() == null) { + query.and(wrapper -> wrapper + .and(productWrapper -> productWrapper + .eq(ErpPalletDO::getProductId, reqVO.getProductId()) + .ne(ErpPalletDO::getStatus, reqVO.getExcludeStatus())) + .or() + .eq(ErpPalletDO::getStatus, ErpPalletStatusEnum.IDLE.getStatus())); + } else { + query.eqIfPresent(ErpPalletDO::getStatus, reqVO.getStatus()) + .neIfPresent(ErpPalletDO::getStatus, reqVO.getExcludeStatus()) + .eqIfPresent(ErpPalletDO::getProductId, reqVO.getProductId()); + } + return selectPage(reqVO, query); } default ErpPalletDO selectByCode(String code) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java index f6d504660..355c00563 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -85,11 +86,27 @@ public interface ErpStockMapper extends BaseMapperX { } default ErpStockDO selectByProductIdAndWarehouseIdAndAreaId(Long productId, Long warehouseId, Long areaId) { - return selectOne(new LambdaQueryWrapperX() + if (areaId != null) { + return selectOne(new LambdaQueryWrapperX() + .eq(ErpStockDO::getProductId, productId) + .eq(ErpStockDO::getWarehouseId, warehouseId) + .eq(ErpStockDO::getAreaId, areaId)); + } + List stockList = selectList(new LambdaQueryWrapperX() .eq(ErpStockDO::getProductId, productId) - .eq(ErpStockDO::getWarehouseId, warehouseId) - .eq(areaId != null, ErpStockDO::getAreaId, areaId) - .isNull(areaId == null, ErpStockDO::getAreaId)); + .eq(ErpStockDO::getWarehouseId, warehouseId)); + if (CollUtil.isEmpty(stockList)) { + return null; + } + ErpStockDO stock = stockList.get(0); + stock.setId(null); + stock.setAreaId(null); + stock.setAreaName(null); + stock.setCount(stockList.stream() + .map(ErpStockDO::getCount) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add)); + return stock; } default ErpStockDO selectByProductIdAndWarehouseIdAndCategoryType(Long productId, Long warehouseId, Integer categoryType) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemMapper.java index f14a848d4..e1f82569a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemMapper.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import java.math.BigDecimal; import java.util.Collection; import java.util.List; @@ -30,4 +31,9 @@ public interface ErpStockOutItemMapper extends BaseMapperX { List selectOutIds(@Param("productId") Long productId, @Param("warehouseId") Long warehouseId); + BigDecimal selectLockedStockCount(@Param("productId") Long productId, + @Param("warehouseId") Long warehouseId, + @Param("areaId") Long areaId, + @Param("statuses") Collection statuses); + } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemPalletMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemPalletMapper.java index a87bd9e26..ee3d9a6ed 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemPalletMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemPalletMapper.java @@ -3,9 +3,15 @@ package cn.iocoder.yudao.module.erp.dal.mysql.stock; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemPalletDO; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import java.math.BigDecimal; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Mapper public interface ErpStockOutItemPalletMapper extends BaseMapperX { @@ -21,4 +27,42 @@ public interface ErpStockOutItemPalletMapper extends BaseMapperX selectLockedPackageCountMap(Collection palletIds, + Collection statuses, + String outType) { + if (palletIds == null || palletIds.isEmpty()) { + return Collections.emptyMap(); + } + List> list = selectLockedPackageCountList(palletIds, statuses, outType); + if (list == null || list.isEmpty()) { + return Collections.emptyMap(); + } + return list.stream().collect(Collectors.toMap( + item -> ((Number) item.get("palletId")).longValue(), + item -> item.get("lockedPackageCount") == null ? BigDecimal.ZERO + : new BigDecimal(item.get("lockedPackageCount").toString()), + (count1, count2) -> count1)); + } + + @Select({""}) + List> selectLockedPackageCountList(@Param("palletIds") Collection palletIds, + @Param("statuses") Collection statuses, + @Param("outType") String outType); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletService.java index e840d4b10..2800a5efb 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletService.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; import javax.validation.Valid; import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; import java.util.Collection; import java.util.List; import java.util.Map; @@ -34,4 +35,6 @@ public interface ErpPalletService { void regenerateCode(Long id, String code) throws UnsupportedEncodingException; String selectPrintTemplate(); + + Map getLockedPackageCountMap(Collection palletIds); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletServiceImpl.java index 095ba8440..9ed33b691 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletServiceImpl.java @@ -12,6 +12,8 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO; import cn.iocoder.yudao.module.erp.dal.mysql.pallet.ErpPalletMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemPalletMapper; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; import cn.iocoder.yudao.module.erp.service.warehousearea.WarehouseAreaService; @@ -21,6 +23,8 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.io.UnsupportedEncodingException; +import java.math.BigDecimal; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -40,10 +44,15 @@ import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_LOC public class ErpPalletServiceImpl implements ErpPalletService { private static final int ERPPALLET_PRINT_TEMPLATE_TYPE = 8; + private static final String PRODUCT_STOCK_OUT_TYPE = "产品出库"; + private static final List LOCKED_STOCK_OUT_STATUSES = Arrays.asList( + ErpAuditStatus.PROCESS.getStatus(), ErpAuditStatus.DRAFT.getStatus(), ErpAuditStatus.UN_APPROVE.getStatus()); @Resource private ErpPalletMapper palletMapper; @Resource + private ErpStockOutItemPalletMapper stockOutItemPalletMapper; + @Resource private AutoCodeUtil autoCodeUtil; @Resource private ErpWarehouseService warehouseService; @@ -149,6 +158,12 @@ public class ErpPalletServiceImpl implements ErpPalletService { return palletMapper.selectPrintTemplate(ERPPALLET_PRINT_TEMPLATE_TYPE); } + @Override + public Map getLockedPackageCountMap(Collection palletIds) { + return stockOutItemPalletMapper.selectLockedPackageCountMap( + palletIds, LOCKED_STOCK_OUT_STATUSES, PRODUCT_STOCK_OUT_TYPE); + } + private ErpPalletDO validatePalletExists(Long id) { ErpPalletDO pallet = palletMapper.selectById(id); if (pallet == null) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java index e268924bd..051e1936e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java @@ -51,6 +51,7 @@ import cn.iocoder.yudao.module.infra.api.config.ConfigApi; import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -762,12 +763,15 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { if (approve) { BigDecimal remainCount = defaultZero(pallet.getProductCount()).subtract(packageCount); if (remainCount.compareTo(BigDecimal.ZERO) <= 0) { - pallet.setStatus(ErpPalletStatusEnum.IDLE.getStatus()); - pallet.setProductId(null); - pallet.setProductName(null); - pallet.setProductCount(BigDecimal.ZERO); - pallet.setWarehouseId(null); - pallet.setAreaId(null); + palletMapper.update(null, new LambdaUpdateWrapper() + .eq(ErpPalletDO::getId, pallet.getId()) + .set(ErpPalletDO::getStatus, ErpPalletStatusEnum.IDLE.getStatus()) + .set(ErpPalletDO::getProductId, null) + .set(ErpPalletDO::getProductName, null) + .set(ErpPalletDO::getProductCount, BigDecimal.ZERO) + .set(ErpPalletDO::getWarehouseId, null) + .set(ErpPalletDO::getAreaId, null)); + return; } else { pallet.setProductCount(remainCount); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/autocode/ErpStockOutItemMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/autocode/ErpStockOutItemMapper.xml index b324081ad..75c4a26f5 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/autocode/ErpStockOutItemMapper.xml +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/autocode/ErpStockOutItemMapper.xml @@ -15,4 +15,27 @@ + + From 815f405cfa2213a177047e6a38a8881932bd0cec Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Mon, 6 Jul 2026 16:40:20 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9=E7=94=9F=E4=BA=A7?= =?UTF-8?q?=E8=AE=A1=E5=88=92=E5=B7=A5=E8=89=BA=E8=B7=AF=E7=BA=BF=E5=8F=8A?= =?UTF-8?q?=E6=8D=A2=E7=BA=BF=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/plan/PlanController.java | 17 ++-- .../plan/vo/PlanLineChangeBatchReqVO.java | 44 +++++++++ .../vo/PlanLineChangeRecordBatchRespVO.java | 37 ++++++++ .../vo/PlanLineChangeRecordPageReqVO.java | 21 +++++ .../plan/vo/PlanLineChangeRecordRespVO.java | 3 + .../admin/plan/vo/PlanStatusEnum.java | 7 +- .../PlanLineChangeRecordDO.java | 4 + .../PlanLineChangeRecordMapper.java | 9 ++ .../mes/dal/redis/no/MesNoRedisDAO.java | 4 + .../module/mes/service/plan/PlanService.java | 6 +- .../mes/service/plan/PlanServiceImpl.java | 90 ++++++++++++++++--- 11 files changed, 223 insertions(+), 19 deletions(-) create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeBatchReqVO.java create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordBatchRespVO.java create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordPageReqVO.java diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/PlanController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/PlanController.java index 1ecdc1dbc..338090113 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/PlanController.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/PlanController.java @@ -705,12 +705,19 @@ public class PlanController { return success(true); } - @GetMapping("/line-change-record/list") - @Operation(summary = "获得生产计划换线记录列表") - @Parameter(name = "planId", description = "生产计划 ID", required = true, example = "1024") + @PutMapping("/change-line-batch") + @Operation(summary = "生产计划批量换线") + @PreAuthorize("@ss.hasPermission('mes:plan:update')") + public CommonResult changeLineBatch(@Valid @RequestBody PlanLineChangeBatchReqVO reqVO) { + planService.changeLineBatch(reqVO); + return success(true); + } + + @GetMapping("/line-change-record/page") + @Operation(summary = "获得生产计划换线记录分页") @PreAuthorize("@ss.hasPermission('mes:plan:query')") - public CommonResult> getLineChangeRecordList(@RequestParam("planId") Long planId) { - return success(planService.getLineChangeRecordList(planId)); + public CommonResult> getLineChangeRecordPage(@Valid PlanLineChangeRecordPageReqVO pageReqVO) { + return success(planService.getLineChangeRecordPage(pageReqVO)); } diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeBatchReqVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeBatchReqVO.java new file mode 100644 index 000000000..d95b8fa18 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeBatchReqVO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.mes.controller.admin.plan.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +@Schema(description = "管理后台 - 生产计划批量换线 Request VO") +@Data +public class PlanLineChangeBatchReqVO { + + @Schema(description = "生产计划 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "生产计划 ID 不能为空") + private Long planId; + + @Valid + @NotEmpty(message = "换线明细列表不能为空") + @Schema(description = "换线明细列表", implementation = LineChangeItem.class) + private List items; + + @Schema(description = "备注") + private String remark; + + @Data + @Schema(description = "生产计划批量换线明细") + public static class LineChangeItem { + + @Schema(description = "计划工艺流程明细 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "计划工艺流程明细 ID 不能为空") + private Long planProcessRouteItemId; + + @Schema(description = "换线后的设备 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "换线后的设备 ID 不能为空") + private Long deviceId; + + @Schema(description = "备注") + private String remark; + + } + +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordBatchRespVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordBatchRespVO.java new file mode 100644 index 000000000..db598c937 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordBatchRespVO.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.controller.admin.plan.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - 生产计划换线记录批次 Response VO") +@Data +public class PlanLineChangeRecordBatchRespVO { + + @Schema(description = "换线批次号", example = "B20260706000001") + private String changeBatchNo; + + @Schema(description = "生产计划编号", example = "1") + private Long planId; + + @Schema(description = "换线时间") + private LocalDateTime changeTime; + + @Schema(description = "操作人 ID", example = "1") + private Long operatorUserId; + + @Schema(description = "当前计划合格数量", example = "100") + private Long passNumber; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "变更工序数量", example = "2") + private Integer changeCount; + + @Schema(description = "换线明细列表") + private List items; + +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordPageReqVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordPageReqVO.java new file mode 100644 index 000000000..4ed6fe10a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordPageReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.mes.controller.admin.plan.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - 生产计划换线记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class PlanLineChangeRecordPageReqVO extends PageParam { + + @Schema(description = "生产计划 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotNull(message = "生产计划 ID 不能为空") + private Long planId; + +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordRespVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordRespVO.java index 9c589333c..8cb73b6a7 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordRespVO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordRespVO.java @@ -15,6 +15,9 @@ public class PlanLineChangeRecordRespVO { @Schema(description = "生产计划编号", example = "1") private Long planId; + @Schema(description = "换线批次号", example = "B202607060001") + private String changeBatchNo; + @Schema(description = "计划工艺流程明细编号", example = "1") private Long planProcessRouteItemId; diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanStatusEnum.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanStatusEnum.java index 97d3de60a..b16643deb 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanStatusEnum.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanStatusEnum.java @@ -11,11 +11,14 @@ public enum PlanStatusEnum { 已排产(1), 量产(2), 暂停(3), - 完工(4), + + //旧完工-启用 +// 完工(4), 已入库(5), 试产 (6), 待入库(7), - 已开工(8); + 已开工(8), + 完工(9); private final int value; diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/planlinechange/PlanLineChangeRecordDO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/planlinechange/PlanLineChangeRecordDO.java index a1c5e6b85..77ba028ad 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/planlinechange/PlanLineChangeRecordDO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/planlinechange/PlanLineChangeRecordDO.java @@ -30,6 +30,10 @@ public class PlanLineChangeRecordDO extends BaseDO { * 生产计划编号 */ private Long planId; + /** + * 换线批次号 + */ + private String changeBatchNo; /** * 计划工艺流程明细编号 */ diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/planlinechange/PlanLineChangeRecordMapper.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/planlinechange/PlanLineChangeRecordMapper.java index f3abe184d..b2e162b62 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/planlinechange/PlanLineChangeRecordMapper.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/planlinechange/PlanLineChangeRecordMapper.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.mes.dal.mysql.planlinechange; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanLineChangeRecordPageReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.planlinechange.PlanLineChangeRecordDO; import org.apache.ibatis.annotations.Mapper; @@ -17,4 +19,11 @@ public interface PlanLineChangeRecordMapper extends BaseMapperX selectPage(PlanLineChangeRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eq(PlanLineChangeRecordDO::getPlanId, reqVO.getPlanId()) + .orderByDesc(PlanLineChangeRecordDO::getChangeTime) + .orderByDesc(PlanLineChangeRecordDO::getId)); + } + } diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/no/MesNoRedisDAO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/no/MesNoRedisDAO.java index d97cd669d..55dd6433f 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/no/MesNoRedisDAO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/no/MesNoRedisDAO.java @@ -64,6 +64,10 @@ public class MesNoRedisDAO { * 生产报工 */ public static final String REPORT_NO_PREFIX = "WR-"; + /** + * 生产计划换线批次号 + */ + public static final String PLAN_LINE_CHANGE_BATCH_NO_PREFIX = "B"; /** * 能源设备 */ diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/plan/PlanService.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/plan/PlanService.java index 18e4258c7..268277670 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/plan/PlanService.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/plan/PlanService.java @@ -115,9 +115,11 @@ public interface PlanService { PageResult getPlanProductCapacityPage(PlanProductCapacityPageReqVO reqVO); - void changeLine(@Valid PlanLineChangeReqVO reqVO); + void changeLine(@Valid PlanLineChangeReqVO reqVO); - List getLineChangeRecordList(Long planId); + void changeLineBatch(@Valid PlanLineChangeBatchReqVO reqVO); + + PageResult getLineChangeRecordPage(PlanLineChangeRecordPageReqVO pageReqVO); } diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/plan/PlanServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/plan/PlanServiceImpl.java index 201f5f9ed..e7d971f13 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/plan/PlanServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/plan/PlanServiceImpl.java @@ -989,35 +989,105 @@ public class PlanServiceImpl implements PlanService { if (plan == null) { throw exception(PLAN_NOT_EXISTS); } - PlanProcessRouteItemDO planRouteItem = planProcessRouteItemMapper.selectById(reqVO.getPlanProcessRouteItemId()); - if (planRouteItem == null || !Objects.equals(planRouteItem.getPlanId(), reqVO.getPlanId())) { + String changeBatchNo = noRedisDAO.generate6(MesNoRedisDAO.PLAN_LINE_CHANGE_BATCH_NO_PREFIX); + changeLineItem(plan, reqVO.getPlanProcessRouteItemId(), reqVO.getDeviceId(), reqVO.getRemark(), changeBatchNo, + LocalDateTime.now(), getLoginUserId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void changeLineBatch(PlanLineChangeBatchReqVO reqVO) { + PlanDO plan = planMapper.selectById(reqVO.getPlanId()); + if (plan == null) { throw exception(PLAN_NOT_EXISTS); } - DeviceLedgerDO afterDevice = deviceLedgerMapper.selectById(reqVO.getDeviceId()); + String changeBatchNo = null; + LocalDateTime changeTime = LocalDateTime.now(); + Long operatorUserId = getLoginUserId(); + for (PlanLineChangeBatchReqVO.LineChangeItem item : reqVO.getItems()) { + PlanProcessRouteItemDO planRouteItem = planProcessRouteItemMapper.selectById(item.getPlanProcessRouteItemId()); + if (planRouteItem == null || !Objects.equals(planRouteItem.getPlanId(), plan.getId())) { + throw exception(PLAN_NOT_EXISTS); + } + if (Objects.equals(planRouteItem.getDeviceId(), item.getDeviceId())) { + continue; + } + if (changeBatchNo == null) { + changeBatchNo = noRedisDAO.generate6(MesNoRedisDAO.PLAN_LINE_CHANGE_BATCH_NO_PREFIX); + } + String remark = item.getRemark() != null ? item.getRemark() : reqVO.getRemark(); + changeLineItem(plan, planRouteItem, item.getDeviceId(), remark, changeBatchNo, + changeTime, operatorUserId); + } + } + + private void changeLineItem(PlanDO plan, Long planProcessRouteItemId, Long deviceId, String remark, + String changeBatchNo, LocalDateTime changeTime, Long operatorUserId) { + PlanProcessRouteItemDO planRouteItem = planProcessRouteItemMapper.selectById(planProcessRouteItemId); + if (planRouteItem == null || !Objects.equals(planRouteItem.getPlanId(), plan.getId())) { + throw exception(PLAN_NOT_EXISTS); + } + changeLineItem(plan, planRouteItem, deviceId, remark, changeBatchNo, changeTime, operatorUserId); + } + + private void changeLineItem(PlanDO plan, PlanProcessRouteItemDO planRouteItem, Long deviceId, String remark, + String changeBatchNo, LocalDateTime changeTime, Long operatorUserId) { + DeviceLedgerDO afterDevice = deviceLedgerMapper.selectById(deviceId); PlanLineChangeRecordDO record = new PlanLineChangeRecordDO(); record.setPlanId(plan.getId()); + record.setChangeBatchNo(changeBatchNo); record.setPlanProcessRouteItemId(planRouteItem.getId()); record.setProcessParameterId(planRouteItem.getProcessParameterId()); record.setProcessParameterName(planRouteItem.getProcessParameterName()); record.setBeforeDeviceId(planRouteItem.getDeviceId()); record.setBeforeDeviceName(planRouteItem.getDeviceName()); - record.setAfterDeviceId(reqVO.getDeviceId()); + record.setAfterDeviceId(deviceId); record.setAfterDeviceName(afterDevice == null ? null : afterDevice.getDeviceName()); - record.setChangeTime(LocalDateTime.now()); - record.setOperatorUserId(getLoginUserId()); + record.setChangeTime(changeTime); + record.setOperatorUserId(operatorUserId); record.setPassNumber(plan.getPassNumber()); - record.setRemark(reqVO.getRemark()); + record.setRemark(remark); planLineChangeRecordMapper.insert(record); - planRouteItem.setDeviceId(reqVO.getDeviceId()); + planRouteItem.setDeviceId(deviceId); planRouteItem.setDeviceName(afterDevice == null ? null : afterDevice.getDeviceName()); planProcessRouteItemMapper.updateById(planRouteItem); } @Override - public List getLineChangeRecordList(Long planId) { - return BeanUtils.toBean(planLineChangeRecordMapper.selectListByPlanId(planId), PlanLineChangeRecordRespVO.class); + public PageResult getLineChangeRecordPage(PlanLineChangeRecordPageReqVO pageReqVO) { + List records = planLineChangeRecordMapper.selectListByPlanId(pageReqVO.getPlanId()); + if (CollUtil.isEmpty(records)) { + return new PageResult<>(Collections.emptyList(), 0L); + } + Map> batchMap = records.stream() + .collect(Collectors.groupingBy(this::getLineChangeBatchKey, LinkedHashMap::new, Collectors.toList())); + List batchList = batchMap.entrySet().stream() + .map(entry -> buildLineChangeBatchRespVO(entry.getKey(), entry.getValue())) + .collect(Collectors.toList()); + int fromIndex = Math.min((pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize(), batchList.size()); + int toIndex = Math.min(fromIndex + pageReqVO.getPageSize(), batchList.size()); + return new PageResult<>(batchList.subList(fromIndex, toIndex), (long) batchList.size()); + } + + private String getLineChangeBatchKey(PlanLineChangeRecordDO record) { + return StringUtils.isNotBlank(record.getChangeBatchNo()) ? record.getChangeBatchNo() : String.valueOf(record.getId()); + } + + private PlanLineChangeRecordBatchRespVO buildLineChangeBatchRespVO(String changeBatchNo, + List records) { + PlanLineChangeRecordDO firstRecord = records.get(0); + PlanLineChangeRecordBatchRespVO respVO = new PlanLineChangeRecordBatchRespVO(); + respVO.setChangeBatchNo(changeBatchNo); + respVO.setPlanId(firstRecord.getPlanId()); + respVO.setChangeTime(firstRecord.getChangeTime()); + respVO.setOperatorUserId(firstRecord.getOperatorUserId()); + respVO.setPassNumber(firstRecord.getPassNumber()); + respVO.setRemark(firstRecord.getRemark()); + respVO.setChangeCount(records.size()); + respVO.setItems(BeanUtils.toBean(records, PlanLineChangeRecordRespVO.class)); + return respVO; } From 89a8fba7fda1a7174d35234b1544e15775c3e3dc Mon Sep 17 00:00:00 2001 From: HuangHuiKang Date: Mon, 6 Jul 2026 17:54:09 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix:=E6=96=B0=E5=A2=9E=E6=8D=A2=E7=BA=BF?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=93=8D=E4=BD=9C=E4=BA=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/plan/vo/PlanLineChangeRecordBatchRespVO.java | 3 +++ .../yudao/module/mes/service/plan/PlanServiceImpl.java | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordBatchRespVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordBatchRespVO.java index db598c937..9966b5517 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordBatchRespVO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/plan/vo/PlanLineChangeRecordBatchRespVO.java @@ -22,6 +22,9 @@ public class PlanLineChangeRecordBatchRespVO { @Schema(description = "操作人 ID", example = "1") private Long operatorUserId; + @Schema(description = "操作人名字", example = "张三") + private String operatorUserName; + @Schema(description = "当前计划合格数量", example = "100") private Long passNumber; diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/plan/PlanServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/plan/PlanServiceImpl.java index e7d971f13..e0d67aae2 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/plan/PlanServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/plan/PlanServiceImpl.java @@ -1066,6 +1066,11 @@ public class PlanServiceImpl implements PlanService { List batchList = batchMap.entrySet().stream() .map(entry -> buildLineChangeBatchRespVO(entry.getKey(), entry.getValue())) .collect(Collectors.toList()); + Map operatorUserMap = userService.getUserMap( + batchList.stream().map(PlanLineChangeRecordBatchRespVO::getOperatorUserId) + .filter(Objects::nonNull).collect(Collectors.toSet())); + batchList.forEach(batch -> MapUtils.findAndThen(operatorUserMap, batch.getOperatorUserId(), + user -> batch.setOperatorUserName(user.getNickname()))); int fromIndex = Math.min((pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize(), batchList.size()); int toIndex = Math.min(fromIndex + pageReqVO.getPageSize(), batchList.size()); return new PageResult<>(batchList.subList(fromIndex, toIndex), (long) batchList.size());