From 977fdca68a16ed6f3714707f277caa3d7f24a599 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 15 Feb 2026 14:03:59 +0800 Subject: [PATCH] feat(mes): 新增物料产品分类与物料产品管理 --- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemController.java | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemTypeController.java | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemPageReqVO.java | 36 ++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemRespVO.java | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemSaveReqVO.java | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeListReqVO.java | 16 ++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeRespVO.java | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeSaveReqVO.java | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemDO.java | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemTypeDO.java | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java | 46 ++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemTypeMapper.java | 38 ++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java | 9 +++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeService.java | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeServiceImpl.java | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 17 files changed, 1337 insertions(+), 0 deletions(-) create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemController.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemTypeController.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemPageReqVO.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemRespVO.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemSaveReqVO.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeListReqVO.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeRespVO.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeSaveReqVO.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemDO.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemTypeDO.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemTypeMapper.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeService.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeServiceImpl.java diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemController.java new file mode 100644 index 0000000..cb89fac --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemController.java @@ -0,0 +1,106 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +@Tag(name = "管理后台 - MES 物料产品") +@RestController +@RequestMapping("/mes/md/item") +@Validated +public class MesMdItemController { + + @Resource + private MesMdItemService itemService; + + @PostMapping("/create") + @Operation(summary = "创建物料产品") + @PreAuthorize("@ss.hasPermission('mes:md-item:create')") + public CommonResult createItem(@Valid @RequestBody MesMdItemSaveReqVO createReqVO) { + return success(itemService.createItem(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新物料产品") + @PreAuthorize("@ss.hasPermission('mes:md-item:update')") + public CommonResult updateItem(@Valid @RequestBody MesMdItemSaveReqVO updateReqVO) { + itemService.updateItem(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除物料产品") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-item:delete')") + public CommonResult deleteItem(@RequestParam("id") Long id) { + itemService.deleteItem(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得物料产品") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult getItem(@RequestParam("id") Long id) { + MesMdItemDO item = itemService.getItem(id); + return success(BeanUtils.toBean(item, MesMdItemRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得物料产品分页") + @PreAuthorize("@ss.hasPermission('mes:md-item:query')") + public CommonResult> getItemPage(@Valid MesMdItemPageReqVO pageReqVO) { + return success(itemService.getItemVOPage(pageReqVO)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得物料产品精简列表", description = "只包含被开启的物料,主要用于前端的下拉选项") + public CommonResult> getItemSimpleList() { + List list = itemService.getItemVOListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, item -> new MesMdItemRespVO() + .setId(item.getId()).setName(item.getName()).setCode(item.getCode()) + .setItemTypeId(item.getItemTypeId()).setItemTypeName(item.getItemTypeName()) + .setUnitOfMeasure(item.getUnitOfMeasure()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出物料产品 Excel") + @PreAuthorize("@ss.hasPermission('mes:md-item:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportItemExcel(@Valid MesMdItemPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = itemService.getItemVOPage(pageReqVO); + // 导出 Excel + ExcelUtils.write(response, "物料产品.xls", "数据", MesMdItemRespVO.class, + pageResult.getList()); + } + + // TODO @AI:缺少批量导入; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemTypeController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemTypeController.java new file mode 100644 index 0000000..dc1db0e --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/MesMdItemTypeController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +@Tag(name = "管理后台 - MES 物料产品分类") +@RestController +@RequestMapping("/mes/md/item-type") +@Validated +public class MesMdItemTypeController { + + @Resource + private MesMdItemTypeService itemTypeService; + + @PostMapping("/create") + @Operation(summary = "创建物料产品分类") + @PreAuthorize("@ss.hasPermission('mes:md-item-type:create')") + public CommonResult createItemType(@Valid @RequestBody MesMdItemTypeSaveReqVO createReqVO) { + return success(itemTypeService.createItemType(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新物料产品分类") + @PreAuthorize("@ss.hasPermission('mes:md-item-type:update')") + public CommonResult updateItemType(@Valid @RequestBody MesMdItemTypeSaveReqVO updateReqVO) { + itemTypeService.updateItemType(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除物料产品分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:md-item-type:delete')") + public CommonResult deleteItemType(@RequestParam("id") Long id) { + itemTypeService.deleteItemType(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得物料产品分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:md-item-type:query')") + public CommonResult getItemType(@RequestParam("id") Long id) { + MesMdItemTypeDO itemType = itemTypeService.getItemType(id); + return success(BeanUtils.toBean(itemType, MesMdItemTypeRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得物料产品分类列表") + @PreAuthorize("@ss.hasPermission('mes:md-item-type:query')") + public CommonResult> getItemTypeList(@Valid MesMdItemTypeListReqVO listReqVO) { + List list = itemTypeService.getItemTypeList(listReqVO); + return success(BeanUtils.toBean(list, MesMdItemTypeRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得物料产品分类精简列表", description = "只包含被开启的分类,主要用于前端的下拉选项") + public CommonResult> getItemTypeSimpleList() { + List list = itemTypeService.getItemTypeList( + new MesMdItemTypeListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus())); + return success(convertList(list, itemType -> new MesMdItemTypeRespVO() + .setId(itemType.getId()).setName(itemType.getName()).setParentId(itemType.getParentId()))); + } + + // TODO @AI:不需要导出; + @GetMapping("/export-excel") + @Operation(summary = "导出物料产品分类 Excel") + @PreAuthorize("@ss.hasPermission('mes:md-item-type:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportItemTypeExcel(@Valid MesMdItemTypeListReqVO listReqVO, + HttpServletResponse response) throws IOException { + List list = itemTypeService.getItemTypeList(listReqVO); + // 导出 Excel + ExcelUtils.write(response, "物料产品分类.xls", "数据", MesMdItemTypeRespVO.class, + BeanUtils.toBean(list, MesMdItemTypeRespVO.class)); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemPageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemPageReqVO.java new file mode 100644 index 0000000..ab0a5a6 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemPageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.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 org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - MES 物料产品分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class MesMdItemPageReqVO extends PageParam { + + @Schema(description = "物料编码", example = "ITEM001") + private String code; + + @Schema(description = "物料名称", example = "螺丝") + private String name; + + @Schema(description = "物料分类编号", example = "1") + private Long itemTypeId; + + @Schema(description = "状态", example = "0") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemRespVO.java new file mode 100644 index 0000000..355e201 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemRespVO.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 物料产品 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesMdItemRespVO { + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("物料编号") + private Long id; + + @Schema(description = "物料编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM001") + @ExcelProperty("物料编码") + private String code; + + @Schema(description = "物料名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "螺丝") + @ExcelProperty("物料名称") + private String name; + + @Schema(description = "规格型号", example = "M6*20") + @ExcelProperty("规格型号") + private String specification; + + @Schema(description = "单位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "pcs") + @ExcelProperty("单位编码") + private String unitOfMeasure; + + @Schema(description = "物料分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long itemTypeId; + @Schema(description = "物料分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原材料") + @ExcelProperty("物料分类") + private String itemTypeName; + + @Schema(description = "物料/产品标识", example = "ITEM") + @ExcelProperty("物料/产品标识") + private String itemOrProduct; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "是否启用安全库存", example = "false") + @ExcelProperty("是否启用安全库存") + private Boolean safeStockFlag; + + @Schema(description = "最低库存量", example = "100.0000") + @ExcelProperty("最低库存量") + private BigDecimal minStock; + + @Schema(description = "最高库存量", example = "10000.0000") + @ExcelProperty("最高库存量") + private BigDecimal maxStock; + + @Schema(description = "是否高值物料", example = "false") + @ExcelProperty("是否高值物料") + private Boolean highValue; + + @Schema(description = "是否启用批次管理", example = "true") + @ExcelProperty("是否启用批次管理") + private Boolean batchFlag; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "预留字段1") + private String attr1; + + @Schema(description = "预留字段2") + private String attr2; + + @Schema(description = "预留字段3") + private Integer attr3; + + @Schema(description = "预留字段4") + private Integer attr4; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemSaveReqVO.java new file mode 100644 index 0000000..5846a32 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemSaveReqVO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - MES 物料产品新增/修改 Request VO") +@Data +public class MesMdItemSaveReqVO { + + @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "物料编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM001") + @NotEmpty(message = "物料编码不能为空") + private String code; + + @Schema(description = "物料名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "螺丝") + @NotEmpty(message = "物料名称不能为空") + private String name; + + @Schema(description = "规格型号", example = "M6*20") + private String specification; + + @Schema(description = "单位编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "pcs") + @NotEmpty(message = "单位编码不能为空") + private String unitOfMeasure; + + @Schema(description = "物料分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "物料分类编号不能为空") + private Long itemTypeId; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "是否启用安全库存", example = "false") + private Boolean safeStockFlag; + + @Schema(description = "最低库存量", example = "100.0000") + private BigDecimal minStock; + + @Schema(description = "最高库存量", example = "10000.0000") + private BigDecimal maxStock; + + @Schema(description = "是否高值物料", example = "false") + private Boolean highValue; + + @Schema(description = "是否启用批次管理", example = "true") + private Boolean batchFlag; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "预留字段1") + private String attr1; + + @Schema(description = "预留字段2") + private String attr2; + + @Schema(description = "预留字段3") + private Integer attr3; + + @Schema(description = "预留字段4") + private Integer attr4; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeListReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeListReqVO.java new file mode 100644 index 0000000..fde88cb --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeListReqVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - MES 物料产品分类列表 Request VO") +@Data +public class MesMdItemTypeListReqVO { + + @Schema(description = "分类名称", example = "原材料") + private String name; + + @Schema(description = "状态", example = "0") + private Integer status; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeRespVO.java new file mode 100644 index 0000000..f08ea44 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeRespVO.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - MES 物料产品分类 Response VO") +@Data +@ExcelIgnoreUnannotated +public class MesMdItemTypeRespVO { + + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("分类编号") + private Long id; + + @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty("父分类编号") + private Long parentId; + + @Schema(description = "分类编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "RAW") + @ExcelProperty("分类编码") + private String code; + + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原材料") + @ExcelProperty("分类名称") + private String name; + + @Schema(description = "物料/产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM") + @ExcelProperty("物料/产品标识") + private String itemOrProduct; + + @Schema(description = "显示排序", example = "0") + @ExcelProperty("显示排序") + private Integer sort; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "预留字段1") + private String attr1; + + @Schema(description = "预留字段2") + private String attr2; + + @Schema(description = "预留字段3") + private Integer attr3; + + @Schema(description = "预留字段4") + private Integer attr4; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeSaveReqVO.java new file mode 100644 index 0000000..b3ca294 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeSaveReqVO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 物料产品分类新增/修改 Request VO") +@Data +public class MesMdItemTypeSaveReqVO { + + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long id; + + @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "父分类编号不能为空") + private Long parentId; + + @Schema(description = "分类编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "RAW") + @NotEmpty(message = "分类编码不能为空") + private String code; + + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原材料") + @NotEmpty(message = "分类名称不能为空") + private String name; + + @Schema(description = "物料/产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM") + @NotEmpty(message = "物料/产品标识不能为空") + private String itemOrProduct; + + @Schema(description = "显示排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "显示排序不能为空") + private Integer sort; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + + @Schema(description = "预留字段1") + private String attr1; + + @Schema(description = "预留字段2") + private String attr2; + + @Schema(description = "预留字段3") + private Integer attr3; + + @Schema(description = "预留字段4") + private Integer attr4; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemDO.java new file mode 100644 index 0000000..9ccbd47 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemDO.java @@ -0,0 +1,100 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.item; + +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.*; + +import java.math.BigDecimal; + +/** + * MES 物料产品 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_item") +@KeySequence("mes_md_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdItemDO extends BaseDO { + + /** + * 物料编号 + */ + @TableId + private Long id; + /** + * 物料编码 + */ + private String code; + /** + * 物料名称 + */ + private String name; + /** + * 规格型号 + */ + private String specification; + /** + * 单位编码 + */ + private String unitOfMeasure; + /** + * 物料分类编号 + * + * 关联 {@link MesMdItemTypeDO#getId()} + */ + private Long itemTypeId; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 是否启用安全库存 + */ + private Boolean safeStockFlag; + /** + * 最低库存量 + */ + private BigDecimal minStock; + /** + * 最高库存量 + */ + private BigDecimal maxStock; + /** + * 是否高值物料 + */ + private Boolean highValue; + /** + * 是否启用批次管理 + */ + private Boolean batchFlag; + /** + * 备注 + */ + private String remark; + /** + * 预留字段1 + */ + private String attr1; + /** + * 预留字段2 + */ + private String attr2; + /** + * 预留字段3 + */ + private Integer attr3; + /** + * 预留字段4 + */ + private Integer attr4; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemTypeDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemTypeDO.java new file mode 100644 index 0000000..04651f7 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemTypeDO.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.item; + +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.*; + +/** + * MES 物料产品分类 DO + * + * @author 芋道源码 + */ +@TableName("mes_md_item_type") +@KeySequence("mes_md_item_type_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdItemTypeDO extends BaseDO { + + public static final Long PARENT_ID_ROOT = 0L; + + /** + * 分类编号 + */ + @TableId + private Long id; + /** + * 分类编码 + */ + private String code; + /** + * 分类名称 + */ + private String name; + /** + * 父分类编号 + */ + private Long parentId; + /** + * 物料/产品标识 + */ + private String itemOrProduct; + /** + * 显示排序 + */ + private Integer sort; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 预留字段1 + */ + private String attr1; + /** + * 预留字段2 + */ + private String attr2; + /** + * 预留字段3 + */ + private Integer attr3; + /** + * 预留字段4 + */ + private Integer attr4; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java new file mode 100644 index 0000000..173a9fe --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemMapper.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.item; + +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.md.item.vo.MesMdItemPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 物料产品 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdItemMapper extends BaseMapperX { + + default PageResult selectPage(MesMdItemPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesMdItemDO::getCode, reqVO.getCode()) + .likeIfPresent(MesMdItemDO::getName, reqVO.getName()) + .eqIfPresent(MesMdItemDO::getItemTypeId, reqVO.getItemTypeId()) + .eqIfPresent(MesMdItemDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesMdItemDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesMdItemDO::getId)); + } + + default MesMdItemDO selectByCode(String code) { + return selectOne(MesMdItemDO::getCode, code); + } + + default MesMdItemDO selectByName(String name) { + return selectOne(MesMdItemDO::getName, name); + } + + default Long selectCountByItemTypeId(Long itemTypeId) { + return selectCount(MesMdItemDO::getItemTypeId, itemTypeId); + } + + default List selectListByStatus(Integer status) { + return selectList(MesMdItemDO::getStatus, status); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemTypeMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemTypeMapper.java new file mode 100644 index 0000000..6dbddff --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/item/MesMdItemTypeMapper.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.item; + +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.md.item.vo.type.MesMdItemTypeListReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 物料产品分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdItemTypeMapper extends BaseMapperX { + + default List selectList(MesMdItemTypeListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(MesMdItemTypeDO::getName, reqVO.getName()) + .eqIfPresent(MesMdItemTypeDO::getStatus, reqVO.getStatus()) + .orderByAsc(MesMdItemTypeDO::getSort)); + } + + default MesMdItemTypeDO selectByParentIdAndName(Long parentId, String name) { + return selectOne(MesMdItemTypeDO::getParentId, parentId, MesMdItemTypeDO::getName, name); + } + + default MesMdItemTypeDO selectByParentIdAndCode(Long parentId, String code) { + return selectOne(MesMdItemTypeDO::getParentId, parentId, MesMdItemTypeDO::getCode, code); + } + + default Long selectCountByParentId(Long parentId) { + return selectCount(MesMdItemTypeDO::getParentId, parentId); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java index 9cd8b1b..17d7b3f 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java @@ -11,12 +11,21 @@ public interface ErrorCodeConstants { // ========== MES 基础数据-物料分类(1-040-100-000) ========== ErrorCode MD_ITEM_TYPE_NOT_EXISTS = new ErrorCode(1_040_100_000, "物料分类不存在"); + ErrorCode MD_ITEM_TYPE_EXITS_CHILDREN = new ErrorCode(1_040_100_001, "存在子分类,无法删除"); + ErrorCode MD_ITEM_TYPE_PARENT_NOT_EXITS = new ErrorCode(1_040_100_002, "父级分类不存在"); + ErrorCode MD_ITEM_TYPE_PARENT_ERROR = new ErrorCode(1_040_100_003, "不能设置自己为父分类"); + ErrorCode MD_ITEM_TYPE_NAME_DUPLICATE = new ErrorCode(1_040_100_004, "同一父分类下已存在该名称的分类"); + ErrorCode MD_ITEM_TYPE_CODE_DUPLICATE = new ErrorCode(1_040_100_005, "同一父分类下已存在该编码的分类"); + ErrorCode MD_ITEM_TYPE_PARENT_IS_CHILD = new ErrorCode(1_040_100_006, "不能设置自己的子分类为父分类"); + ErrorCode MD_ITEM_TYPE_EXITS_ITEM = new ErrorCode(1_040_100_007, "该分类下存在物料,无法删除"); // ========== MES 基础数据-计量单位(1-040-101-000) ========== ErrorCode MD_UNIT_MEASURE_NOT_EXISTS = new ErrorCode(1_040_101_000, "计量单位不存在"); // ========== MES 基础数据-物料(1-040-102-000) ========== ErrorCode MD_ITEM_NOT_EXISTS = new ErrorCode(1_040_102_000, "物料不存在"); + ErrorCode MD_ITEM_CODE_DUPLICATE = new ErrorCode(1_040_102_001, "物料编码已存在"); + ErrorCode MD_ITEM_NAME_DUPLICATE = new ErrorCode(1_040_102_002, "物料名称已存在"); // ========== MES 基础数据-客户(1-040-103-000) ========== ErrorCode MD_CLIENT_NOT_EXISTS = new ErrorCode(1_040_103_000, "客户不存在"); diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java new file mode 100644 index 0000000..c85fb66 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 物料产品 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdItemService { + + /** + * 创建物料产品 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createItem(@Valid MesMdItemSaveReqVO createReqVO); + + /** + * 更新物料产品 + * + * @param updateReqVO 更新信息 + */ + void updateItem(@Valid MesMdItemSaveReqVO updateReqVO); + + /** + * 删除物料产品 + * + * @param id 编号 + */ + void deleteItem(Long id); + + /** + * 获得物料产品 + * + * @param id 编号 + * @return 物料产品 + */ + MesMdItemDO getItem(Long id); + + /** + * 获得物料产品 VO 分页 + * + * @param pageReqVO 分页查询 + * @return 物料产品分页 + */ + PageResult getItemVOPage(MesMdItemPageReqVO pageReqVO); + + /** + * 获得指定状态的物料产品 VO 列表 + * + * @param status 状态 + * @return 物料产品 VO 列表 + */ + List getItemVOListByStatus(Integer status); + + /** + * 获得物料产品 VO 列表 + * + * @param ids 编号数组 + * @return 物料产品 VO 列表 + */ + List getItemVOList(Collection ids); + + /** + * 获得物料产品 VO Map + * + * @param ids 编号数组 + * @return 物料产品 VO Map + */ + default Map getItemVOMap(Collection ids) { + return convertMap(getItemVOList(ids), MesMdItemRespVO::getId); + } + + /** + * 基于物料分类编号,获得物料数量 + * + * @param itemTypeId 物料分类编号 + * @return 物料数量 + */ + Long getItemCountByItemTypeId(Long itemTypeId); + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java new file mode 100644 index 0000000..6dced80 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java @@ -0,0 +1,182 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.MesMdItemSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdItemMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 物料产品 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdItemServiceImpl implements MesMdItemService { + + @Resource + private MesMdItemMapper itemMapper; + + @Resource + private MesMdItemTypeService itemTypeService; + + @Override + public Long createItem(MesMdItemSaveReqVO createReqVO) { + // 校验物料编码的唯一性 + validateItemCodeUnique(null, createReqVO.getCode()); + // 校验物料名称的唯一性 + validateItemNameUnique(null, createReqVO.getName()); + // 校验物料分类存在 + validateItemTypeExists(createReqVO.getItemTypeId()); + + // 插入 + MesMdItemDO item = BeanUtils.toBean(createReqVO, MesMdItemDO.class); + // 如果未启用安全库存,清零库存上下限 + clearStockIfNotSafe(item); + itemMapper.insert(item); + // 返回 + return item.getId(); + } + + @Override + public void updateItem(MesMdItemSaveReqVO updateReqVO) { + // 校验存在 + validateItemExists(updateReqVO.getId()); + // 校验物料编码的唯一性 + validateItemCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + // 校验物料名称的唯一性 + validateItemNameUnique(updateReqVO.getId(), updateReqVO.getName()); + // 校验物料分类存在 + validateItemTypeExists(updateReqVO.getItemTypeId()); + + // 更新 + MesMdItemDO updateObj = BeanUtils.toBean(updateReqVO, MesMdItemDO.class); + // 如果未启用安全库存,清零库存上下限 + clearStockIfNotSafe(updateObj); + itemMapper.updateById(updateObj); + } + + @Override + public void deleteItem(Long id) { + // 校验存在 + validateItemExists(id); + // 删除 + itemMapper.deleteById(id); + } + + private void validateItemExists(Long id) { + if (itemMapper.selectById(id) == null) { + throw exception(MD_ITEM_NOT_EXISTS); + } + } + + private void validateItemCodeUnique(Long id, String code) { + MesMdItemDO item = itemMapper.selectByCode(code); + if (item == null) { + return; + } + if (id == null) { + throw exception(MD_ITEM_CODE_DUPLICATE); + } + if (!Objects.equals(item.getId(), id)) { + throw exception(MD_ITEM_CODE_DUPLICATE); + } + } + + private void validateItemNameUnique(Long id, String name) { + MesMdItemDO item = itemMapper.selectByName(name); + if (item == null) { + return; + } + if (id == null) { + throw exception(MD_ITEM_NAME_DUPLICATE); + } + if (!Objects.equals(item.getId(), id)) { + throw exception(MD_ITEM_NAME_DUPLICATE); + } + } + + private void validateItemTypeExists(Long itemTypeId) { + if (itemTypeService.getItemType(itemTypeId) == null) { + throw exception(MD_ITEM_TYPE_NOT_EXISTS); + } + } + + /** + * 如果未启用安全库存,清零库存上下限 + */ + private void clearStockIfNotSafe(MesMdItemDO item) { + if (Boolean.TRUE.equals(item.getSafeStockFlag())) { + return; + } + item.setMinStock(BigDecimal.ZERO); + item.setMaxStock(BigDecimal.ZERO); + } + + @Override + public MesMdItemDO getItem(Long id) { + return itemMapper.selectById(id); + } + + @Override + public PageResult getItemVOPage(MesMdItemPageReqVO pageReqVO) { + PageResult pageResult = itemMapper.selectPage(pageReqVO); + return new PageResult<>(buildItemVOList(pageResult.getList()), pageResult.getTotal()); + } + + @Override + public List getItemVOListByStatus(Integer status) { + List list = itemMapper.selectListByStatus(status); + return buildItemVOList(list); + } + + @Override + public List getItemVOList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + List list = itemMapper.selectByIds(ids); + return buildItemVOList(list); + } + + private List buildItemVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + Map itemTypeMap = itemTypeService.getItemTypeMap( + convertSet(list, MesMdItemDO::getItemTypeId)); + return BeanUtils.toBean(list, MesMdItemRespVO.class, item -> { + MapUtils.findAndThen(itemTypeMap, item.getItemTypeId(), + itemType -> { + item.setItemTypeName(itemType.getName()); + item.setItemOrProduct(itemType.getItemOrProduct()); + }); + }); + } + + @Override + public Long getItemCountByItemTypeId(Long itemTypeId) { + return itemMapper.selectCountByItemTypeId(itemTypeId); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeService.java new file mode 100644 index 0000000..e756e4e --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeService.java @@ -0,0 +1,77 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * MES 物料产品分类 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdItemTypeService { + + /** + * 创建物料产品分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createItemType(@Valid MesMdItemTypeSaveReqVO createReqVO); + + /** + * 更新物料产品分类 + * + * @param updateReqVO 更新信息 + */ + void updateItemType(@Valid MesMdItemTypeSaveReqVO updateReqVO); + + /** + * 删除物料产品分类 + * + * @param id 编号 + */ + void deleteItemType(Long id); + + /** + * 获得物料产品分类 + * + * @param id 编号 + * @return 物料产品分类 + */ + MesMdItemTypeDO getItemType(Long id); + + /** + * 获得物料产品分类列表 + * + * @param listReqVO 查询条件 + * @return 物料产品分类列表 + */ + List getItemTypeList(MesMdItemTypeListReqVO listReqVO); + + /** + * 获得物料产品分类列表 + * + * @param ids 编号数组 + * @return 物料产品分类列表 + */ + List getItemTypeList(Collection ids); + + /** + * 获得物料产品分类 Map + * + * @param ids 编号数组 + * @return 物料产品分类 Map + */ + default Map getItemTypeMap(Collection ids) { + return convertMap(getItemTypeList(ids), MesMdItemTypeDO::getId); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeServiceImpl.java new file mode 100644 index 0000000..0fbccb9 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemTypeServiceImpl.java @@ -0,0 +1,167 @@ +package cn.iocoder.yudao.module.mes.service.md.item; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeListReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type.MesMdItemTypeSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdItemTypeMapper; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; + +/** + * MES 物料产品分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdItemTypeServiceImpl implements MesMdItemTypeService { + + @Resource + private MesMdItemTypeMapper itemTypeMapper; + + @Resource + @Lazy // 延迟加载,避免循环依赖 + private MesMdItemService itemService; + + @Override + public Long createItemType(MesMdItemTypeSaveReqVO createReqVO) { + // 校验父分类编号的有效性 + validateParentItemType(null, createReqVO.getParentId()); + // 校验分类名称的唯一性 + validateItemTypeNameUnique(null, createReqVO.getParentId(), createReqVO.getName()); + // 校验分类编码的唯一性 + validateItemTypeCodeUnique(null, createReqVO.getParentId(), createReqVO.getCode()); + + // 插入 + MesMdItemTypeDO itemType = BeanUtils.toBean(createReqVO, MesMdItemTypeDO.class); + itemTypeMapper.insert(itemType); + // 返回 + return itemType.getId(); + } + + @Override + public void updateItemType(MesMdItemTypeSaveReqVO updateReqVO) { + // 校验存在 + validateItemTypeExists(updateReqVO.getId()); + // 校验父分类编号的有效性 + validateParentItemType(updateReqVO.getId(), updateReqVO.getParentId()); + // 校验分类名称的唯一性 + validateItemTypeNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); + // 校验分类编码的唯一性 + validateItemTypeCodeUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getCode()); + + // 更新 + MesMdItemTypeDO updateObj = BeanUtils.toBean(updateReqVO, MesMdItemTypeDO.class); + itemTypeMapper.updateById(updateObj); + } + + @Override + public void deleteItemType(Long id) { + // 1.1 校验存在 + validateItemTypeExists(id); + // 1.2 校验是否有子分类 + if (itemTypeMapper.selectCountByParentId(id) > 0) { + throw exception(MD_ITEM_TYPE_EXITS_CHILDREN); + } + // 1.3 校验是否有物料 + if (itemService.getItemCountByItemTypeId(id) > 0) { + throw exception(MD_ITEM_TYPE_EXITS_ITEM); + } + // 2. 删除 + itemTypeMapper.deleteById(id); + } + + private void validateItemTypeExists(Long id) { + if (itemTypeMapper.selectById(id) == null) { + throw exception(MD_ITEM_TYPE_NOT_EXISTS); + } + } + + private void validateParentItemType(Long id, Long parentId) { + if (parentId == null || MesMdItemTypeDO.PARENT_ID_ROOT.equals(parentId)) { + return; + } + // 1. 不能设置自己为父分类 + if (Objects.equals(id, parentId)) { + throw exception(MD_ITEM_TYPE_PARENT_ERROR); + } + // 2. 父分类不存在 + MesMdItemTypeDO parentItemType = itemTypeMapper.selectById(parentId); + if (parentItemType == null) { + throw exception(MD_ITEM_TYPE_PARENT_NOT_EXITS); + } + // 3. 递归校验父分类,如果父分类是自己的子分类,则报错,避免形成环路 + if (id == null) { // id 为空,说明新增,不需要考虑环路 + return; + } + for (int i = 0; i < Short.MAX_VALUE; i++) { + // 3.1 校验环路 + parentId = parentItemType.getParentId(); + if (Objects.equals(id, parentId)) { + throw exception(MD_ITEM_TYPE_PARENT_IS_CHILD); + } + // 3.2 继续递归下一级父分类 + if (parentId == null || MesMdItemTypeDO.PARENT_ID_ROOT.equals(parentId)) { + break; + } + parentItemType = itemTypeMapper.selectById(parentId); + if (parentItemType == null) { + break; + } + } + } + + private void validateItemTypeNameUnique(Long id, Long parentId, String name) { + MesMdItemTypeDO itemType = itemTypeMapper.selectByParentIdAndName(parentId, name); + if (itemType == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的分类 + if (id == null) { + throw exception(MD_ITEM_TYPE_NAME_DUPLICATE); + } + if (!Objects.equals(itemType.getId(), id)) { + throw exception(MD_ITEM_TYPE_NAME_DUPLICATE); + } + } + + private void validateItemTypeCodeUnique(Long id, Long parentId, String code) { + MesMdItemTypeDO itemType = itemTypeMapper.selectByParentIdAndCode(parentId, code); + if (itemType == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的分类 + if (id == null) { + throw exception(MD_ITEM_TYPE_CODE_DUPLICATE); + } + if (!Objects.equals(itemType.getId(), id)) { + throw exception(MD_ITEM_TYPE_CODE_DUPLICATE); + } + } + + @Override + public MesMdItemTypeDO getItemType(Long id) { + return itemTypeMapper.selectById(id); + } + + @Override + public List getItemTypeList(MesMdItemTypeListReqVO listReqVO) { + return itemTypeMapper.selectList(listReqVO); + } + + @Override + public List getItemTypeList(Collection ids) { + return itemTypeMapper.selectByIds(ids); + } + +} -- libgit2 0.21.4