diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodePartController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodePartController.java new file mode 100644 index 0000000..0b1e205 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodePartController.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part.MesMdAutoCodePartRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part.MesMdAutoCodePartSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodePartService; +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.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 编码规则组成") +@RestController +@RequestMapping("/mes/auto-code-part") +@Validated +public class MesMdAutoCodePartController { + + @Resource + private MesMdAutoCodePartService partService; + + @PostMapping("/create") + @Operation(summary = "创建规则组成") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:update')") + public CommonResult createAutoCodePart(@Valid @RequestBody MesMdAutoCodePartSaveReqVO createReqVO) { + return success(partService.createAutoCodePart(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新规则组成") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:update')") + public CommonResult updateAutoCodePart(@Valid @RequestBody MesMdAutoCodePartSaveReqVO updateReqVO) { + partService.updateAutoCodePart(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除规则组成") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:update')") + public CommonResult deleteAutoCodePart(@RequestParam("id") Long id) { + partService.deleteAutoCodePart(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得规则组成") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')") + public CommonResult getAutoCodePart(@RequestParam("id") Long id) { + MesMdAutoCodePartDO part = partService.getAutoCodePart(id); + return success(BeanUtils.toBean(part, MesMdAutoCodePartRespVO.class)); + } + + @GetMapping("/list-by-rule-id") + @Operation(summary = "根据规则 ID 获得规则组成列表") + @Parameter(name = "ruleId", description = "规则 ID", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')") + public CommonResult> getAutoCodePartListByRuleId(@RequestParam("ruleId") Long ruleId) { + List list = partService.getAutoCodePartListByRuleId(ruleId); + return success(BeanUtils.toBean(list, MesMdAutoCodePartRespVO.class)); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRecordController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRecordController.java new file mode 100644 index 0000000..93915fd --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRecordController.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.record.MesMdAutoCodeGenerateReqVO; +import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - MES 编码生成记录") +@RestController +@RequestMapping("/mes/auto-code-record") +@Validated +public class MesMdAutoCodeRecordController { + + @Resource + private MesMdAutoCodeRecordService recordService; + + @PostMapping("/generate") + @Operation(summary = "生成编码") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')") + public CommonResult generateAutoCode(@Valid @RequestBody MesMdAutoCodeGenerateReqVO generateReqVO) { + String code = recordService.generateAutoCode(generateReqVO.getRuleCode(), generateReqVO.getInputChar()); + return success(code); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRuleController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRuleController.java new file mode 100644 index 0000000..2af0fdb --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/MesMdAutoCodeRuleController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode; + +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.autocode.vo.rule.MesMdAutoCodeRulePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRuleRespVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRuleSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRuleService; +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/auto-code-rule") +@Validated +public class MesMdAutoCodeRuleController { + + @Resource + private MesMdAutoCodeRuleService ruleService; + + @PostMapping("/create") + @Operation(summary = "创建编码规则") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:create')") + public CommonResult createAutoCodeRule(@Valid @RequestBody MesMdAutoCodeRuleSaveReqVO createReqVO) { + return success(ruleService.createAutoCodeRule(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新编码规则") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:update')") + public CommonResult updateAutoCodeRule(@Valid @RequestBody MesMdAutoCodeRuleSaveReqVO updateReqVO) { + ruleService.updateAutoCodeRule(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除编码规则") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:delete')") + public CommonResult deleteAutoCodeRule(@RequestParam("id") Long id) { + ruleService.deleteAutoCodeRule(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得编码规则") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')") + public CommonResult getAutoCodeRule(@RequestParam("id") Long id) { + MesMdAutoCodeRuleDO rule = ruleService.getAutoCodeRule(id); + return success(BeanUtils.toBean(rule, MesMdAutoCodeRuleRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得编码规则分页") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:query')") + public CommonResult> getAutoCodeRulePage(@Valid MesMdAutoCodeRulePageReqVO pageReqVO) { + PageResult pageResult = ruleService.getAutoCodeRulePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MesMdAutoCodeRuleRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得编码规则精简列表", description = "只包含被开启的编码规则,主要用于前端的下拉选项") + public CommonResult> getAutoCodeRuleSimpleList() { + List list = ruleService.getAutoCodeRuleListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, rule -> new MesMdAutoCodeRuleRespVO() + .setId(rule.getId()).setName(rule.getName()).setCode(rule.getCode()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出编码规则 Excel") + @PreAuthorize("@ss.hasPermission('mes:auto-code-rule:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportAutoCodeRuleExcel(@Valid MesMdAutoCodeRulePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = ruleService.getAutoCodeRulePage(pageReqVO).getList(); + List data = BeanUtils.toBean(list, MesMdAutoCodeRuleRespVO.class); + ExcelUtils.write(response, "编码规则.xls", "数据", MesMdAutoCodeRuleRespVO.class, data); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java new file mode 100644 index 0000000..a184bc2 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +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 MesMdAutoCodePartRespVO { + + @Schema(description = "分段 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("分段 ID") + private Long id; + + @Schema(description = "规则 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("规则 ID") + private Long ruleId; + + @Schema(description = "分段序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("分段序号") + private Integer sort; + + @Schema(description = "分段类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "分段类型", converter = DictConvert.class) + @DictFormat("mes_auto_code_part_type") + private Integer type; + + @Schema(description = "分段长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "4") + @ExcelProperty("分段长度") + private Integer length; + + @Schema(description = "日期格式", example = "yyyyMMdd") + @ExcelProperty("日期格式") + private String dateFormat; + + @Schema(description = "固定字符", example = "ITEM_") + @ExcelProperty("固定字符") + private String fixCharacter; + + @Schema(description = "流水号起始值", example = "1") + @ExcelProperty("流水号起始值") + private Integer serialStartNo; + + @Schema(description = "流水号步长", example = "1") + @ExcelProperty("流水号步长") + private Integer serialStep; + + @Schema(description = "流水号是否循环", example = "true") + @ExcelProperty("流水号是否循环") + private Boolean cycleFlag; + + @Schema(description = "循环方式", example = "3") + @ExcelProperty(value = "循环方式", converter = DictConvert.class) + @DictFormat("mes_auto_code_cycle_method") + private Integer cycleMethod; + + @Schema(description = "备注", example = "备注") + @ExcelProperty("备注") + private String remark; + + @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/autocode/vo/part/MesMdAutoCodePartSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartSaveReqVO.java new file mode 100644 index 0000000..d1c6502 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartSaveReqVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - MES 编码规则组成新增/修改 Request VO") +@Data +public class MesMdAutoCodePartSaveReqVO { + + @Schema(description = "分段 ID", example = "1024") + private Long id; + + @Schema(description = "规则 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "规则 ID 不能为空") + private Long ruleId; + + @Schema(description = "分段序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "分段序号不能为空") + private Integer sort; + + @Schema(description = "分段类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "分段类型不能为空") + private Integer type; + + @Schema(description = "分段长度", requiredMode = Schema.RequiredMode.REQUIRED, example = "4") + @NotNull(message = "分段长度不能为空") + private Integer length; + + @Schema(description = "日期格式", example = "yyyyMMdd") + private String dateFormat; + + @Schema(description = "固定字符", example = "ITEM_") + private String fixCharacter; + + @Schema(description = "流水号起始值", example = "1") + private Integer serialStartNo; + + @Schema(description = "流水号步长", example = "1") + private Integer serialStep; + + @Schema(description = "流水号是否循环", example = "true") + private Boolean cycleFlag; + + @Schema(description = "循环方式", example = "3") + private Integer cycleMethod; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/record/MesMdAutoCodeGenerateReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/record/MesMdAutoCodeGenerateReqVO.java new file mode 100644 index 0000000..4c808d4 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/record/MesMdAutoCodeGenerateReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.record; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +@Schema(description = "管理后台 - MES 编码生成 Request VO") +@Data +public class MesMdAutoCodeGenerateReqVO { + + @Schema(description = "规则编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM_CODE") + @NotEmpty(message = "规则编码不能为空") + private String ruleCode; + + @Schema(description = "输入字符", example = "A") + private String inputChar; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRulePageReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRulePageReqVO.java new file mode 100644 index 0000000..6c5a0a4 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRulePageReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule; + +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 MesMdAutoCodeRulePageReqVO extends PageParam { + + @Schema(description = "规则编码", example = "ITEM_CODE") + private String code; + + @Schema(description = "规则名称", example = "物料编码规则") + private String name; + + @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/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java new file mode 100644 index 0000000..5c69f74 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule; + +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 MesMdAutoCodeRuleRespVO { + + @Schema(description = "规则 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @ExcelProperty("规则 ID") + private Long id; + + @Schema(description = "规则编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM_CODE") + @ExcelProperty("规则编码") + private String code; + + @Schema(description = "规则名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料编码规则") + @ExcelProperty("规则名称") + private String name; + + @Schema(description = "描述", example = "用于生成物料编码") + @ExcelProperty("描述") + private String description; + + @Schema(description = "最大长度", example = "20") + @ExcelProperty("最大长度") + private Integer maxLength; + + @Schema(description = "是否补齐", example = "true") + @ExcelProperty("是否补齐") + private Boolean padded; + + @Schema(description = "补齐字符", example = "0") + @ExcelProperty("补齐字符") + private String paddedChar; + + @Schema(description = "补齐方式", example = "1") + @ExcelProperty(value = "补齐方式", converter = DictConvert.class) + @DictFormat("mes_auto_code_padded_method") + private Integer paddedMethod; + + @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 = "创建时间", 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/autocode/vo/rule/MesMdAutoCodeRuleSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleSaveReqVO.java new file mode 100644 index 0000000..fd9b769 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleSaveReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule; + +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 MesMdAutoCodeRuleSaveReqVO { + + @Schema(description = "规则 ID", example = "1024") + private Long id; + + @Schema(description = "规则编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM_CODE") + @NotEmpty(message = "规则编码不能为空") + private String code; + + @Schema(description = "规则名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料编码规则") + @NotEmpty(message = "规则名称不能为空") + private String name; + + @Schema(description = "描述", example = "用于生成物料编码") + private String description; + + @Schema(description = "最大长度", example = "20") + private Integer maxLength; + + @Schema(description = "是否补齐", example = "true") + private Boolean padded; + + @Schema(description = "补齐字符", example = "0") + private String paddedChar; + + @Schema(description = "补齐方式", example = "1") + private Integer paddedMethod; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + @NotNull(message = "状态不能为空") + private Integer status; + + @Schema(description = "备注", example = "备注") + private String remark; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodePartDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodePartDO.java new file mode 100644 index 0000000..a76fc50 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodePartDO.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode; + +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_auto_code_part") +@KeySequence("mes_md_auto_code_part_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdAutoCodePartDO extends BaseDO { + + /** + * 分段 ID + */ + @TableId + private Long id; + /** + * 规则 ID + * + * 关联 {@link MesMdAutoCodeRuleDO#getId()} + */ + private Long ruleId; + /** + * 分段序号 + */ + private Integer sort; + /** + * 分段长度 + */ + private Integer length; + /** + * 备注 + */ + private String remark; + /** + * 分段类型 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum} + */ + private Integer type; + + // ========== 当 MesMdAutoCodePartTypeEnum#INPUT_CHAR 时,使用 ========== + /** + * 固定字符 + */ + private String fixCharacter; + + // ========== 当 MesMdAutoCodePartTypeEnum#DATE 时,使用 ========== + /** + * 日期格式 + * + * 例如:yyyyMMdd、yyyyMM、HHmmss + */ + private String dateFormat; + + // ========== 当 MesMdAutoCodePartTypeEnum#SERIAL_NUMBER 时,使用 ========== + /** + * 流水号起始值 + */ + private Integer serialStartNo; + /** + * 流水号步长 + */ + private Integer serialStep; + /** + * 流水号是否循环 + */ + private Boolean cycleFlag; + /** + * 循环方式 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeCycleMethodEnum} + */ + private Integer cycleMethod; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRecordDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRecordDO.java new file mode 100644 index 0000000..5ef12a0 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRecordDO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +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_auto_code_record") +@KeySequence("mes_md_auto_code_record_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdAutoCodeRecordDO extends BaseDO { + + /** + * 记录 ID + */ + @TableId + private Long id; + /** + * 规则 ID + * + * 关联 {@link MesMdAutoCodeRuleDO#getId()} + */ + private Long ruleId; + /** + * 生成的编码 + */ + private String result; + /** + * 生成的流水号 + * + * 当规则组成中包含流水号分段({@link MesMdAutoCodePartTypeEnum#SERIAL_NUMBER})时记录,方便追溯和调试 + */ + private Integer serialNo; + /** + * 传入的参数 + */ + private String inputChar; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRuleDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRuleDO.java new file mode 100644 index 0000000..c198f9b --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRuleDO.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode; + +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_auto_code_rule") +@KeySequence("mes_md_auto_code_rule_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MesMdAutoCodeRuleDO extends BaseDO { + + /** + * 规则 ID + */ + @TableId + private Long id; + /** + * 规则编码 + */ + private String code; + /** + * 规则名称 + */ + private String name; + /** + * 描述 + */ + private String description; + /** + * 最大长度 + */ + private Integer maxLength; + /** + * 是否补齐 + */ + private Boolean padded; + /** + * 补齐字符 + */ + private String paddedChar; + /** + * 补齐方式 + * + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePaddedMethodEnum} + */ + private Integer paddedMethod; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodePartMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodePartMapper.java new file mode 100644 index 0000000..9b7a5df --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodePartMapper.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.autocode; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 编码规则组成 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdAutoCodePartMapper extends BaseMapperX { + + default List selectListByRuleId(Long ruleId) { + return selectList(new LambdaQueryWrapperX() + .eq(MesMdAutoCodePartDO::getRuleId, ruleId) + .orderByAsc(MesMdAutoCodePartDO::getSort)); + } + + default void deleteByRuleId(Long ruleId) { + delete(MesMdAutoCodePartDO::getRuleId, ruleId); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodeRecordMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodeRecordMapper.java new file mode 100644 index 0000000..ed6625c --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodeRecordMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.autocode; + +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.autocode.vo.record.MesMdAutoCodeRecordPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * MES 编码生成记录 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdAutoCodeRecordMapper extends BaseMapperX { + + default PageResult selectPage(MesMdAutoCodeRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(MesMdAutoCodeRecordDO::getRuleId, reqVO.getRuleId()) + .likeIfPresent(MesMdAutoCodeRecordDO::getResult, reqVO.getResult()) + .betweenIfPresent(MesMdAutoCodeRecordDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesMdAutoCodeRecordDO::getId)); + } + + default MesMdAutoCodeRecordDO selectByResult(String result) { + return selectOne(MesMdAutoCodeRecordDO::getResult, result); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodeRuleMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodeRuleMapper.java new file mode 100644 index 0000000..43b7542 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/autocode/MesMdAutoCodeRuleMapper.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.md.autocode; + +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.autocode.vo.rule.MesMdAutoCodeRulePageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * MES 编码规则 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface MesMdAutoCodeRuleMapper extends BaseMapperX { + + default PageResult selectPage(MesMdAutoCodeRulePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(MesMdAutoCodeRuleDO::getCode, reqVO.getCode()) + .likeIfPresent(MesMdAutoCodeRuleDO::getName, reqVO.getName()) + .eqIfPresent(MesMdAutoCodeRuleDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(MesMdAutoCodeRuleDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(MesMdAutoCodeRuleDO::getId)); + } + + default MesMdAutoCodeRuleDO selectByCode(String code) { + return selectOne(MesMdAutoCodeRuleDO::getCode, code); + } + + default List selectListByStatus(Integer status) { + return selectList(MesMdAutoCodeRuleDO::getStatus, status); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/RedisKeyConstants.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/RedisKeyConstants.java new file mode 100644 index 0000000..26ba064 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/RedisKeyConstants.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.mes.dal.redis; + +/** + * MES Redis Key 枚举类 + * + * @author 芋道源码 + */ +public interface RedisKeyConstants { + + /** + * 编码规则的缓存 + * + * KEY 格式:mes:md:auto_code:{ruleId}:{cycleKey} + * VALUE 数据格式:流水号自增 + */ + String AUTO_CODE = "mes:md:auto_code:"; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/md/autocode/MesMdAutoCodeRedisDAO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/md/autocode/MesMdAutoCodeRedisDAO.java new file mode 100644 index 0000000..edd837f --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/redis/md/autocode/MesMdAutoCodeRedisDAO.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.mes.dal.redis.md.autocode; + +import cn.iocoder.yudao.module.mes.dal.redis.RedisKeyConstants; +import jakarta.annotation.Resource; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Repository; + +import java.time.Duration; + +/** + * MES 编码规则的 Redis DAO + * + * @author 芋道源码 + */ +@Repository +public class MesMdAutoCodeRedisDAO { + + @Resource + private StringRedisTemplate stringRedisTemplate; + + /** + * 递增序号(带循环) + * + * @param keySuffix key 后缀(不包含 prefix) + * @param duration 过期时间 + * @param step 步长 + * @return 递增后的值 + */ + public Long increment(String keySuffix, Duration duration, Integer step) { + // 递增值 + String key = RedisKeyConstants.AUTO_CODE + keySuffix; + Long value = stringRedisTemplate.opsForValue().increment(key, step); + + // 设置过期时间 + if (duration != null) { + stringRedisTemplate.expire(key, duration); + } + return value; + } + +} 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 b3bce83..10a81ab 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 @@ -82,6 +82,14 @@ public interface ErrorCodeConstants { ErrorCode MD_PRODUCT_SIP_NOT_EXISTS = new ErrorCode(1_040_109_000, "产品SIP不存在"); ErrorCode MD_PRODUCT_SIP_SORT_DUPLICATE = new ErrorCode(1_040_109_001, "该展示序号已存在"); + // ========== MES 基础数据-编码规则(1-040-110-000) ========== + ErrorCode AUTO_CODE_RULE_NOT_EXISTS = new ErrorCode(1_040_110_000, "编码规则不存在"); + ErrorCode AUTO_CODE_RULE_CODE_DUPLICATE = new ErrorCode(1_040_110_001, "规则编码已存在"); + ErrorCode AUTO_CODE_PART_NOT_EXISTS = new ErrorCode(1_040_110_002, "规则组成不存在"); + ErrorCode AUTO_CODE_REDIS_ERROR = new ErrorCode(1_040_110_003, "编码生成服务不可用,请稍后重试"); + ErrorCode AUTO_CODE_GENERATE_FAILED = new ErrorCode(1_040_110_004, "编码生成失败"); + ErrorCode AUTO_CODE_PART_SERIAL_NUMBER_DUPLICATE = new ErrorCode(1_040_110_005, "流水号分段只能存在一个"); + // ========== MES 日历排班-计划班次(1-040-200-000) ========== ErrorCode CAL_PLAN_SHIFT_NOT_EXISTS = new ErrorCode(1_040_200_000, "计划班次不存在"); ErrorCode CAL_PLAN_SHIFT_COUNT_EXCEED = new ErrorCode(1_040_200_001, "班次数量已达到轮班方式的上限"); diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeCycleMethodEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeCycleMethodEnum.java new file mode 100644 index 0000000..315d9ce --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeCycleMethodEnum.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.mes.enums.md.autocode; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 编码规则循环方式枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesMdAutoCodeCycleMethodEnum implements ArrayValuable { + + YEAR(1, "按年"), + MONTH(2, "按月"), + DAY(3, "按天"), + HOUR(4, "按小时"), + MINUTE(5, "按分钟"), + INPUT_CHAR(10, "按传入字符"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesMdAutoCodeCycleMethodEnum::getMethod).toArray(Integer[]::new); + + /** + * 方式 + */ + private final Integer method; + /** + * 名称 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodePaddedMethodEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodePaddedMethodEnum.java new file mode 100644 index 0000000..f13b91b --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodePaddedMethodEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.md.autocode; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 编码规则补齐方式枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesMdAutoCodePaddedMethodEnum implements ArrayValuable { + + LEFT(1, "左补齐"), + RIGHT(2, "右补齐"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesMdAutoCodePaddedMethodEnum::getMethod).toArray(Integer[]::new); + + /** + * 方式 + */ + private final Integer method; + /** + * 名称 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodePartTypeEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodePartTypeEnum.java new file mode 100644 index 0000000..864b818 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodePartTypeEnum.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.enums.md.autocode; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 编码规则分段类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesMdAutoCodePartTypeEnum implements ArrayValuable { + + INPUT_CHAR(1, "输入字符"), + DATE(2, "当前日期"), + FIXED_CHAR(3, "固定字符"), + SERIAL_NUMBER(4, "流水号"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesMdAutoCodePartTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型 + */ + private final Integer type; + /** + * 名称 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodePartService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodePartService.java new file mode 100644 index 0000000..ea782ed --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodePartService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part.MesMdAutoCodePartSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 编码规则组成 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdAutoCodePartService { + + /** + * 创建规则组成 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createAutoCodePart(@Valid MesMdAutoCodePartSaveReqVO createReqVO); + + /** + * 更新规则组成 + * + * @param updateReqVO 更新信息 + */ + void updateAutoCodePart(@Valid MesMdAutoCodePartSaveReqVO updateReqVO); + + /** + * 删除规则组成 + * + * @param id 编号 + */ + void deleteAutoCodePart(Long id); + + /** + * 获得规则组成 + * + * @param id 编号 + * @return 规则组成 + */ + MesMdAutoCodePartDO getAutoCodePart(Long id); + + /** + * 获得规则组成列表(根据规则 ID) + * + * @param ruleId 规则 ID + * @return 规则组成列表 + */ + List getAutoCodePartListByRuleId(Long ruleId); + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodePartServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodePartServiceImpl.java new file mode 100644 index 0000000..fb9e459 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodePartServiceImpl.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part.MesMdAutoCodePartSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.autocode.MesMdAutoCodePartMapper; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.AUTO_CODE_PART_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.AUTO_CODE_PART_SERIAL_NUMBER_DUPLICATE; + +/** + * MES 编码规则组成 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class MesMdAutoCodePartServiceImpl implements MesMdAutoCodePartService { + + @Resource + private MesMdAutoCodePartMapper partMapper; + + @Resource + private MesMdAutoCodeRuleService ruleService; + + @Override + public Long createAutoCodePart(MesMdAutoCodePartSaveReqVO createReqVO) { + // 校验规则存在 + ruleService.validateAutoCodeRuleExists(createReqVO.getRuleId()); + // 校验流水号分段唯一性 + validateSerialNumberPartUnique(null, createReqVO.getRuleId(), createReqVO.getType()); + + // 插入 + MesMdAutoCodePartDO part = BeanUtils.toBean(createReqVO, MesMdAutoCodePartDO.class); + partMapper.insert(part); + return part.getId(); + } + + @Override + public void updateAutoCodePart(MesMdAutoCodePartSaveReqVO updateReqVO) { + // 校验存在 + validatePartExists(updateReqVO.getId()); + // 校验规则存在 + ruleService.validateAutoCodeRuleExists(updateReqVO.getRuleId()); + // 校验流水号分段唯一性 + validateSerialNumberPartUnique(updateReqVO.getId(), updateReqVO.getRuleId(), updateReqVO.getType()); + + // 更新 + MesMdAutoCodePartDO updateObj = BeanUtils.toBean(updateReqVO, MesMdAutoCodePartDO.class); + partMapper.updateById(updateObj); + } + + @Override + public void deleteAutoCodePart(Long id) { + // 校验存在 + validatePartExists(id); + + // 删除 + partMapper.deleteById(id); + } + + @Override + public MesMdAutoCodePartDO getAutoCodePart(Long id) { + return partMapper.selectById(id); + } + + @Override + public List getAutoCodePartListByRuleId(Long ruleId) { + return partMapper.selectListByRuleId(ruleId); + } + + // ==================== 校验方法 ==================== + + private void validatePartExists(Long id) { + if (partMapper.selectById(id) == null) { + throw exception(AUTO_CODE_PART_NOT_EXISTS); + } + } + + private void validateSerialNumberPartUnique(Long id, Long ruleId, Integer type) { + // 只有流水号类型才需要校验 + if (ObjUtil.notEqual(MesMdAutoCodePartTypeEnum.SERIAL_NUMBER.getType(), type)) { + return; + } + // 查询该规则下所有流水号分段 + List parts = partMapper.selectListByRuleId(ruleId); + long count = parts.stream() + .filter(part -> MesMdAutoCodePartTypeEnum.SERIAL_NUMBER.getType().equals(part.getType())) + .filter(part -> ObjUtil.notEqual(id, part.getId())) // 排除自己 + .count(); + if (count > 0) { + throw exception(AUTO_CODE_PART_SERIAL_NUMBER_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordService.java new file mode 100644 index 0000000..41b8012 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordService.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +/** + * MES 编码生成记录 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdAutoCodeRecordService { + + /** + * 生成编码 + * + * @param ruleCode 规则编码 + * @param inputChar 输入字符 + * @return 生成的编码 + */ + String generateAutoCode(String ruleCode, String inputChar); + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImpl.java new file mode 100644 index 0000000..25cf9ae --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRecordServiceImpl.java @@ -0,0 +1,118 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRecordDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.autocode.MesMdAutoCodeRecordMapper; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePaddedMethodEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodePartStrategy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; +import java.util.Map; + +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 MesMdAutoCodeRecordServiceImpl implements MesMdAutoCodeRecordService { + + @Resource + private MesMdAutoCodeRecordMapper recordMapper; + + @Resource + private MesMdAutoCodeRuleService ruleService; + @Resource + private MesMdAutoCodePartService partService; + + @Resource + private List strategyList; + private Map strategyMap; + + @PostConstruct + public void init() { + strategyMap = CollectionUtils.convertMap(strategyList, MesMdAutoCodePartStrategy::getType); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public String generateAutoCode(String ruleCode, String inputChar) { + // 1.1 查询规则 + MesMdAutoCodeRuleDO rule = ruleService.getAutoCodeRuleByCode(ruleCode); + if (rule == null) { + throw exception(AUTO_CODE_RULE_NOT_EXISTS); + } + // 1.2 查询规则组成 + List parts = partService.getAutoCodePartListByRuleId(rule.getId()); + if (CollUtil.isEmpty(parts)) { + throw exception(AUTO_CODE_GENERATE_FAILED); + } + + // 2.1 构建上下文 + MesMdAutoCodeContext context = new MesMdAutoCodeContext() + .setRule(rule).setParts(parts).setInputChar(inputChar); + // 2.2 遍历分段,生成编码 + StringBuilder codeBuilder = new StringBuilder(); + for (MesMdAutoCodePartDO part : parts) { + MesMdAutoCodePartStrategy strategy = strategyMap.get(part.getType()); + Assert.notNull(strategy, () -> exception(AUTO_CODE_GENERATE_FAILED)); + // 生成分段编码 + String partCode = strategy.generate(part, context); + // 统一截取指定长度 + partCode = StrUtil.sub(partCode, 0, part.getLength()); + // 拼接分段编码 + codeBuilder.append(partCode); + } + // 2.3 补齐处理 + String result = codeBuilder.toString(); + if (Boolean.TRUE.equals(rule.getPadded()) && rule.getMaxLength() != null) { + result = padCode(result, rule); + } + + // 3.1 二次校验(防止重复) + MesMdAutoCodeRecordDO existRecord = recordMapper.selectByResult(result); + if (existRecord != null) { + throw exception(AUTO_CODE_GENERATE_FAILED); + } + // 3.2 保存生成记录 + MesMdAutoCodeRecordDO record = new MesMdAutoCodeRecordDO() + .setRuleId(rule.getId()).setResult(result) + .setSerialNo(context.getSerialNo()).setInputChar(inputChar); + recordMapper.insert(record); + return result; + } + + /** + * 补齐编码 + */ + private String padCode(String code, MesMdAutoCodeRuleDO rule) { + if (code.length() >= rule.getMaxLength()) { + return StrUtil.sub(code, 0, rule.getMaxLength()); + } + String paddedChar = StrUtil.emptyToDefault(rule.getPaddedChar(), "0"); + Integer paddedMethod = rule.getPaddedMethod() != null ? rule.getPaddedMethod() : MesMdAutoCodePaddedMethodEnum.LEFT.getMethod(); + if (MesMdAutoCodePaddedMethodEnum.LEFT.getMethod().equals(paddedMethod)) { + // 左补齐 + return StrUtil.padPre(code, rule.getMaxLength(), paddedChar.charAt(0)); + } else { + // 右补齐 + return StrUtil.padAfter(code, rule.getMaxLength(), paddedChar.charAt(0)); + } + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRuleService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRuleService.java new file mode 100644 index 0000000..c4aebf6 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRuleService.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRulePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRuleSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * MES 编码规则 Service 接口 + * + * @author 芋道源码 + */ +public interface MesMdAutoCodeRuleService { + + /** + * 创建编码规则 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createAutoCodeRule(@Valid MesMdAutoCodeRuleSaveReqVO createReqVO); + + /** + * 更新编码规则 + * + * @param updateReqVO 更新信息 + */ + void updateAutoCodeRule(@Valid MesMdAutoCodeRuleSaveReqVO updateReqVO); + + /** + * 删除编码规则 + * + * @param id 编号 + */ + void deleteAutoCodeRule(Long id); + + /** + * 获得编码规则 + * + * @param id 编号 + * @return 编码规则 + */ + MesMdAutoCodeRuleDO getAutoCodeRule(Long id); + + /** + * 获得编码规则分页 + * + * @param pageReqVO 分页查询 + * @return 编码规则分页 + */ + PageResult getAutoCodeRulePage(MesMdAutoCodeRulePageReqVO pageReqVO); + + /** + * 获得编码规则列表(根据状态) + * + * @param status 状态 + * @return 编码规则列表 + */ + List getAutoCodeRuleListByStatus(Integer status); + + /** + * 根据规则编码获取规则 + * + * @param code 规则编码 + * @return 编码规则 + */ + MesMdAutoCodeRuleDO getAutoCodeRuleByCode(String code); + + /** + * 校验编码规则是否存在 + * + * @param id 编号 + */ + void validateAutoCodeRuleExists(Long id); + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRuleServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRuleServiceImpl.java new file mode 100644 index 0000000..fda34fc --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/MesMdAutoCodeRuleServiceImpl.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode; + +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRulePageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule.MesMdAutoCodeRuleSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import cn.iocoder.yudao.module.mes.dal.mysql.md.autocode.MesMdAutoCodePartMapper; +import cn.iocoder.yudao.module.mes.dal.mysql.md.autocode.MesMdAutoCodeRuleMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +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 MesMdAutoCodeRuleServiceImpl implements MesMdAutoCodeRuleService { + + @Resource + private MesMdAutoCodeRuleMapper ruleMapper; + + @Resource + private MesMdAutoCodePartMapper partMapper; + + @Override + public Long createAutoCodeRule(MesMdAutoCodeRuleSaveReqVO createReqVO) { + // 校验规则编码的唯一性 + validateRuleCodeUnique(null, createReqVO.getCode()); + + // 插入 + MesMdAutoCodeRuleDO rule = BeanUtils.toBean(createReqVO, MesMdAutoCodeRuleDO.class); + ruleMapper.insert(rule); + return rule.getId(); + } + + @Override + public void updateAutoCodeRule(MesMdAutoCodeRuleSaveReqVO updateReqVO) { + // 校验存在 + validateAutoCodeRuleExists(updateReqVO.getId()); + // 校验规则编码的唯一性 + validateRuleCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + + // 更新 + MesMdAutoCodeRuleDO updateObj = BeanUtils.toBean(updateReqVO, MesMdAutoCodeRuleDO.class); + ruleMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteAutoCodeRule(Long id) { + // 校验存在 + validateAutoCodeRuleExists(id); + + // 删除规则 + ruleMapper.deleteById(id); + // 级联删除规则组成 + partMapper.deleteByRuleId(id); + } + + @Override + public MesMdAutoCodeRuleDO getAutoCodeRule(Long id) { + return ruleMapper.selectById(id); + } + + @Override + public PageResult getAutoCodeRulePage(MesMdAutoCodeRulePageReqVO pageReqVO) { + return ruleMapper.selectPage(pageReqVO); + } + + @Override + public List getAutoCodeRuleListByStatus(Integer status) { + return ruleMapper.selectListByStatus(status); + } + + @Override + public MesMdAutoCodeRuleDO getAutoCodeRuleByCode(String code) { + return ruleMapper.selectByCode(code); + } + + @Override + public void validateAutoCodeRuleExists(Long id) { + if (ruleMapper.selectById(id) == null) { + throw exception(AUTO_CODE_RULE_NOT_EXISTS); + } + } + + // ==================== 校验方法 ==================== + + private void validateRuleCodeUnique(Long id, String code) { + MesMdAutoCodeRuleDO rule = ruleMapper.selectByCode(code); + if (rule == null) { + return; + } + if (ObjUtil.notEqual(id, rule.getId())) { + throw exception(AUTO_CODE_RULE_CODE_DUPLICATE); + } + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/MesMdAutoCodeContext.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/MesMdAutoCodeContext.java new file mode 100644 index 0000000..528cc88 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/MesMdAutoCodeContext.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy; + +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodeRuleDO; +import lombok.Data; + +import java.util.List; + +/** + * MES 编码生成上下文 + * + * @author 芋道源码 + */ +@Data +public class MesMdAutoCodeContext { + + /** + * 规则 + */ + private MesMdAutoCodeRuleDO rule; + /** + * 规则组成列表 + */ + private List parts; + + /** + * 输入字符 + */ + private String inputChar; + + /** + * 流水号 + * + * 由流水号策略生成并设置,用于保存到生成记录表。例如:当规则包含流水号分段时,生成编码 "ITEM_20260304_0001",此字段值为 1 + */ + private Integer serialNo; + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/MesMdAutoCodePartStrategy.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/MesMdAutoCodePartStrategy.java new file mode 100644 index 0000000..1d7372a --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/MesMdAutoCodePartStrategy.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy; + +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; + +/** + * MES 编码规则分段策略接口 + * + * @author 芋道源码 + */ +public interface MesMdAutoCodePartStrategy { + + /** + * 获取策略类型 + * + * @return 分段类型 + */ + Integer getType(); + + /** + * 生成分段内容 + * + * @param part 规则组成 + * @param context 上下文 + * @return 分段内容 + */ + String generate(MesMdAutoCodePartDO part, MesMdAutoCodeContext context); + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeDatePartStrategy.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeDatePartStrategy.java new file mode 100644 index 0000000..cabfa19 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeDatePartStrategy.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy.impl; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodePartStrategy; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * MES 编码规则 - 当前日期策略 + * + * @author 芋道源码 + */ +@Component +public class MesMdAutoCodeDatePartStrategy implements MesMdAutoCodePartStrategy { + + @Override + public Integer getType() { + return MesMdAutoCodePartTypeEnum.DATE.getType(); + } + + @Override + public String generate(MesMdAutoCodePartDO part, MesMdAutoCodeContext context) { + String dateFormat = StrUtil.emptyToDefault(part.getDateFormat(), DatePattern.PURE_DATE_PATTERN); + return DateUtil.format(LocalDateTime.now(), dateFormat); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeFixedCharPartStrategy.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeFixedCharPartStrategy.java new file mode 100644 index 0000000..55ece91 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeFixedCharPartStrategy.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy.impl; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodePartStrategy; +import org.springframework.stereotype.Component; + +/** + * MES 编码规则 - 固定字符策略 + * + * @author 芋道源码 + */ +@Component +public class MesMdAutoCodeFixedCharPartStrategy implements MesMdAutoCodePartStrategy { + + @Override + public Integer getType() { + return MesMdAutoCodePartTypeEnum.FIXED_CHAR.getType(); + } + + @Override + public String generate(MesMdAutoCodePartDO part, MesMdAutoCodeContext context) { + return StrUtil.emptyToDefault(part.getFixCharacter(), ""); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeInputCharPartStrategy.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeInputCharPartStrategy.java new file mode 100644 index 0000000..f3c5561 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeInputCharPartStrategy.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy.impl; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodePartStrategy; +import org.springframework.stereotype.Component; + +/** + * MES 编码规则 - 输入字符策略 + * + * @author 芋道源码 + */ +@Component +public class MesMdAutoCodeInputCharPartStrategy implements MesMdAutoCodePartStrategy { + + @Override + public Integer getType() { + return MesMdAutoCodePartTypeEnum.INPUT_CHAR.getType(); + } + + @Override + public String generate(MesMdAutoCodePartDO part, MesMdAutoCodeContext context) { + String inputChar = context.getInputChar(); + return StrUtil.emptyToDefault(inputChar, ""); + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeSerialNumberPartStrategy.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeSerialNumberPartStrategy.java new file mode 100644 index 0000000..7a2ecb8 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/md/autocode/strategy/impl/MesMdAutoCodeSerialNumberPartStrategy.java @@ -0,0 +1,113 @@ +package cn.iocoder.yudao.module.mes.service.md.autocode.strategy.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.autocode.MesMdAutoCodePartDO; +import cn.iocoder.yudao.module.mes.dal.redis.md.autocode.MesMdAutoCodeRedisDAO; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeCycleMethodEnum; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodeContext; +import cn.iocoder.yudao.module.mes.service.md.autocode.strategy.MesMdAutoCodePartStrategy; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.time.LocalDateTime; + +/** + * MES 编码规则 - 流水号策略 + * + * @author 芋道源码 + */ +@Component +public class MesMdAutoCodeSerialNumberPartStrategy implements MesMdAutoCodePartStrategy { + + @Resource + private MesMdAutoCodeRedisDAO redisDAO; + + @Override + public Integer getType() { + return MesMdAutoCodePartTypeEnum.SERIAL_NUMBER.getType(); + } + + @Override + public String generate(MesMdAutoCodePartDO part, MesMdAutoCodeContext context) { + // 1.1 构建 Redis key 后缀 + String keySuffix = buildRedisKeySuffix(part, context); + // 1.2 获取过期时间 + Duration duration = Boolean.TRUE.equals(part.getCycleFlag()) ? getExpireDuration(part.getCycleMethod()) : null; + + // 2.1 获取流水号 + Integer step = part.getSerialStep() != null ? part.getSerialStep() : 1; + Long serialNo = redisDAO.increment(keySuffix, duration, step); + // 2.2 保存流水号到上下文 + context.setSerialNo(serialNo.intValue()); + + // 3. 格式化输出(补零) + String serialStr = String.valueOf(serialNo); + if (serialStr.length() < part.getLength()) { + serialStr = StrUtil.padPre(serialStr, part.getLength(), '0'); + } + return serialStr; + } + + /** + * 构建 Redis key 后缀 + */ + private String buildRedisKeySuffix(MesMdAutoCodePartDO part, MesMdAutoCodeContext context) { + StringBuilder keySuffix = new StringBuilder(); + keySuffix.append(context.getRule().getId()); + + // 如果不循环,直接返回 + if (!Boolean.TRUE.equals(part.getCycleFlag()) || part.getCycleMethod() == null) { + return keySuffix.toString(); + } + + // 根据循环方式构建 key 后缀 + keySuffix.append(":"); + LocalDateTime time = LocalDateTime.now(); + if (part.getCycleMethod().equals(MesMdAutoCodeCycleMethodEnum.YEAR.getMethod())) { + keySuffix.append(DateUtil.format(time, "yyyy")); + } else if (part.getCycleMethod().equals(MesMdAutoCodeCycleMethodEnum.MONTH.getMethod())) { + keySuffix.append(DateUtil.format(time, "yyyyMM")); + } else if (part.getCycleMethod().equals(MesMdAutoCodeCycleMethodEnum.DAY.getMethod())) { + keySuffix.append(DateUtil.format(time, "yyyyMMdd")); + } else if (part.getCycleMethod().equals(MesMdAutoCodeCycleMethodEnum.HOUR.getMethod())) { + keySuffix.append(DateUtil.format(time, "yyyyMMddHH")); + } else if (part.getCycleMethod().equals(MesMdAutoCodeCycleMethodEnum.MINUTE.getMethod())) { + keySuffix.append(DateUtil.format(time, "yyyyMMddHHmm")); + } else if (part.getCycleMethod().equals(MesMdAutoCodeCycleMethodEnum.INPUT_CHAR.getMethod())) { + if (StrUtil.isNotEmpty(context.getInputChar())) { + keySuffix.append(context.getInputChar()); + } + } else { + throw new IllegalArgumentException("未知的循环方式:" + part.getCycleMethod()); + } + return keySuffix.toString(); + } + + /** + * 获取过期时间 + */ + private Duration getExpireDuration(Integer cycleMethod) { + if (cycleMethod == null) { + return Duration.ofDays(1); + } + if (cycleMethod.equals(MesMdAutoCodeCycleMethodEnum.YEAR.getMethod())) { + return Duration.ofDays(366); + } else if (cycleMethod.equals(MesMdAutoCodeCycleMethodEnum.MONTH.getMethod())) { + return Duration.ofDays(32); + } else if (cycleMethod.equals(MesMdAutoCodeCycleMethodEnum.DAY.getMethod())) { + return Duration.ofDays(2); + } else if (cycleMethod.equals(MesMdAutoCodeCycleMethodEnum.HOUR.getMethod())) { + return Duration.ofHours(2); + } else if (cycleMethod.equals(MesMdAutoCodeCycleMethodEnum.MINUTE.getMethod())) { + return Duration.ofMinutes(2); + } else if (cycleMethod.equals(MesMdAutoCodeCycleMethodEnum.INPUT_CHAR.getMethod())) { + return Duration.ofDays(30); + } else { + throw new IllegalArgumentException("未知的循环方式:" + cycleMethod); + } + } + +}