Commit 215f58813401103cdf6a6bfa0c27e68815fa8e8b

Authored by YunaiV
1 parent 203c6393

feat(mes-cal): 新增排班计划(cal_plan)、计划班次(cal_shift)、计划班组(cal_plan_team)模块

迁移 ktg-mes 排班计划核心三表到 yudao-module-mes,实现创建计划→自动生成班次→分配班组→确认计划的完整业务流。

- 新增 cal_plan 排班计划 CRUD + 导出,含编码唯一校验、草稿/确认状态管理
- 新增 cal_shift 计划班次 CRUD + 导出,含按轮班方式自动生成默认班次、班次数量上限校验
- 新增 cal_plan_team 计划班组关联增删查,复用 plan 权限
- 新增 CalConstants 常量类、枚举类(ShiftType/ShiftMethod/PlanStatus)
- 新增错误码(shift 上限校验、plan 编码重复、状态校验、班组数量匹配)
- 删除计划时级联删除关联班次和班组
Showing 21 changed files with 1437 additions and 0 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan;
  2 +
  3 +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  8 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  9 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanPageReqVO;
  10 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanRespVO;
  11 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanSaveReqVO;
  12 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.MesCalPlanDO;
  13 +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService;
  14 +import io.swagger.v3.oas.annotations.Operation;
  15 +import io.swagger.v3.oas.annotations.Parameter;
  16 +import io.swagger.v3.oas.annotations.tags.Tag;
  17 +import jakarta.annotation.Resource;
  18 +import jakarta.servlet.http.HttpServletResponse;
  19 +import jakarta.validation.Valid;
  20 +import org.springframework.security.access.prepost.PreAuthorize;
  21 +import org.springframework.validation.annotation.Validated;
  22 +import org.springframework.web.bind.annotation.*;
  23 +
  24 +import java.io.IOException;
  25 +import java.util.List;
  26 +
  27 +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
  28 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  29 +
  30 +@Tag(name = "管理后台 - MES 排班计划")
  31 +@RestController
  32 +@RequestMapping("/mes/cal/plan")
  33 +@Validated
  34 +public class MesCalPlanController {
  35 +
  36 + @Resource
  37 + private MesCalPlanService planService;
  38 +
  39 + @PostMapping("/create")
  40 + @Operation(summary = "创建排班计划")
  41 + @PreAuthorize("@ss.hasPermission('mes:cal-plan:create')")
  42 + public CommonResult<Long> createPlan(@Valid @RequestBody MesCalPlanSaveReqVO createReqVO) {
  43 + return success(planService.createPlan(createReqVO));
  44 + }
  45 +
  46 + @PutMapping("/update")
  47 + @Operation(summary = "更新排班计划")
  48 + @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')")
  49 + public CommonResult<Boolean> updatePlan(@Valid @RequestBody MesCalPlanSaveReqVO updateReqVO) {
  50 + planService.updatePlan(updateReqVO);
  51 + return success(true);
  52 + }
  53 +
  54 + @DeleteMapping("/delete")
  55 + @Operation(summary = "删除排班计划")
  56 + @Parameter(name = "id", description = "编号", required = true)
  57 + @PreAuthorize("@ss.hasPermission('mes:cal-plan:delete')")
  58 + public CommonResult<Boolean> deletePlan(@RequestParam("id") Long id) {
  59 + planService.deletePlan(id);
  60 + return success(true);
  61 + }
  62 +
  63 + @GetMapping("/get")
  64 + @Operation(summary = "获得排班计划")
  65 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  66 + @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')")
  67 + public CommonResult<MesCalPlanRespVO> getPlan(@RequestParam("id") Long id) {
  68 + MesCalPlanDO plan = planService.getPlan(id);
  69 + return success(BeanUtils.toBean(plan, MesCalPlanRespVO.class));
  70 + }
  71 +
  72 + @GetMapping("/page")
  73 + @Operation(summary = "获得排班计划分页")
  74 + @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')")
  75 + public CommonResult<PageResult<MesCalPlanRespVO>> getPlanPage(@Valid MesCalPlanPageReqVO pageReqVO) {
  76 + PageResult<MesCalPlanDO> pageResult = planService.getPlanPage(pageReqVO);
  77 + return success(BeanUtils.toBean(pageResult, MesCalPlanRespVO.class));
  78 + }
  79 +
  80 + @GetMapping("/export-excel")
  81 + @Operation(summary = "导出排班计划 Excel")
  82 + @PreAuthorize("@ss.hasPermission('mes:cal-plan:export')")
  83 + @ApiAccessLog(operateType = EXPORT)
  84 + public void exportPlanExcel(@Valid MesCalPlanPageReqVO pageReqVO,
  85 + HttpServletResponse response) throws IOException {
  86 + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
  87 + List<MesCalPlanDO> list = planService.getPlanPage(pageReqVO).getList();
  88 + // 导出 Excel
  89 + ExcelUtils.write(response, "排班计划.xls", "数据", MesCalPlanRespVO.class,
  90 + BeanUtils.toBean(list, MesCalPlanRespVO.class));
  91 + }
  92 +
  93 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalPlanTeamController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team.MesCalPlanTeamRespVO;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team.MesCalPlanTeamSaveReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.MesCalPlanTeamDO;
  8 +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanTeamService;
  9 +import io.swagger.v3.oas.annotations.Operation;
  10 +import io.swagger.v3.oas.annotations.Parameter;
  11 +import io.swagger.v3.oas.annotations.tags.Tag;
  12 +import jakarta.annotation.Resource;
  13 +import jakarta.validation.Valid;
  14 +import org.springframework.security.access.prepost.PreAuthorize;
  15 +import org.springframework.validation.annotation.Validated;
  16 +import org.springframework.web.bind.annotation.*;
  17 +
  18 +import java.util.List;
  19 +
  20 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  21 +
  22 +@Tag(name = "管理后台 - MES 计划班组关联")
  23 +@RestController
  24 +@RequestMapping("/mes/cal/plan-team")
  25 +@Validated
  26 +public class MesCalPlanTeamController {
  27 +
  28 + @Resource
  29 + private MesCalPlanTeamService planTeamService;
  30 +
  31 + @PostMapping("/create")
  32 + @Operation(summary = "创建计划班组关联")
  33 + @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')")
  34 + public CommonResult<Long> createPlanTeam(@Valid @RequestBody MesCalPlanTeamSaveReqVO createReqVO) {
  35 + return success(planTeamService.createPlanTeam(createReqVO));
  36 + }
  37 +
  38 + @DeleteMapping("/delete")
  39 + @Operation(summary = "删除计划班组关联")
  40 + @Parameter(name = "id", description = "编号", required = true)
  41 + @PreAuthorize("@ss.hasPermission('mes:cal-plan:update')")
  42 + public CommonResult<Boolean> deletePlanTeam(@RequestParam("id") Long id) {
  43 + planTeamService.deletePlanTeam(id);
  44 + return success(true);
  45 + }
  46 +
  47 + @GetMapping("/list-by-plan")
  48 + @Operation(summary = "获得指定排班计划的班组列表")
  49 + @Parameter(name = "planId", description = "排班计划编号", required = true)
  50 + @PreAuthorize("@ss.hasPermission('mes:cal-plan:query')")
  51 + public CommonResult<List<MesCalPlanTeamRespVO>> getPlanTeamListByPlan(@RequestParam("planId") Long planId) {
  52 + List<MesCalPlanTeamDO> list = planTeamService.getPlanTeamListByPlanId(planId);
  53 + // TODO @芋艿:拼装班组编码/名称,等 cal_team 迁移后对接
  54 + return success(BeanUtils.toBean(list, MesCalPlanTeamRespVO.class));
  55 + }
  56 +
  57 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/MesCalShiftController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan;
  2 +
  3 +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  8 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  9 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalShiftPageReqVO;
  10 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalShiftRespVO;
  11 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalShiftSaveReqVO;
  12 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.MesCalShiftDO;
  13 +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalShiftService;
  14 +import io.swagger.v3.oas.annotations.Operation;
  15 +import io.swagger.v3.oas.annotations.Parameter;
  16 +import io.swagger.v3.oas.annotations.tags.Tag;
  17 +import jakarta.annotation.Resource;
  18 +import jakarta.servlet.http.HttpServletResponse;
  19 +import jakarta.validation.Valid;
  20 +import org.springframework.security.access.prepost.PreAuthorize;
  21 +import org.springframework.validation.annotation.Validated;
  22 +import org.springframework.web.bind.annotation.*;
  23 +
  24 +import java.io.IOException;
  25 +import java.util.List;
  26 +
  27 +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
  28 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  29 +
  30 +// TODO @AI:它是不是改成 MesCalPlanShiftController 更好?毕竟它是排班计划的班次,而不是单纯的班次
  31 +@Tag(name = "管理后台 - MES 计划班次")
  32 +@RestController
  33 +@RequestMapping("/mes/cal/shift")
  34 +@Validated
  35 +public class MesCalShiftController {
  36 +
  37 + @Resource
  38 + private MesCalShiftService shiftService;
  39 +
  40 + @PostMapping("/create")
  41 + @Operation(summary = "创建计划班次")
  42 + @PreAuthorize("@ss.hasPermission('mes:cal-shift:create')")
  43 + public CommonResult<Long> createShift(@Valid @RequestBody MesCalShiftSaveReqVO createReqVO) {
  44 + return success(shiftService.createShift(createReqVO));
  45 + }
  46 +
  47 + @PutMapping("/update")
  48 + @Operation(summary = "更新计划班次")
  49 + @PreAuthorize("@ss.hasPermission('mes:cal-shift:update')")
  50 + public CommonResult<Boolean> updateShift(@Valid @RequestBody MesCalShiftSaveReqVO updateReqVO) {
  51 + shiftService.updateShift(updateReqVO);
  52 + return success(true);
  53 + }
  54 +
  55 + @DeleteMapping("/delete")
  56 + @Operation(summary = "删除计划班次")
  57 + @Parameter(name = "id", description = "编号", required = true)
  58 + @PreAuthorize("@ss.hasPermission('mes:cal-shift:delete')")
  59 + public CommonResult<Boolean> deleteShift(@RequestParam("id") Long id) {
  60 + shiftService.deleteShift(id);
  61 + return success(true);
  62 + }
  63 +
  64 + @GetMapping("/get")
  65 + @Operation(summary = "获得计划班次")
  66 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  67 + @PreAuthorize("@ss.hasPermission('mes:cal-shift:query')")
  68 + public CommonResult<MesCalShiftRespVO> getShift(@RequestParam("id") Long id) {
  69 + MesCalShiftDO shift = shiftService.getShift(id);
  70 + return success(BeanUtils.toBean(shift, MesCalShiftRespVO.class));
  71 + }
  72 +
  73 + @GetMapping("/page")
  74 + @Operation(summary = "获得计划班次分页")
  75 + @PreAuthorize("@ss.hasPermission('mes:cal-shift:query')")
  76 + public CommonResult<PageResult<MesCalShiftRespVO>> getShiftPage(@Valid MesCalShiftPageReqVO pageReqVO) {
  77 + PageResult<MesCalShiftDO> pageResult = shiftService.getShiftPage(pageReqVO);
  78 + return success(BeanUtils.toBean(pageResult, MesCalShiftRespVO.class));
  79 + }
  80 +
  81 + @GetMapping("/list-by-plan")
  82 + @Operation(summary = "获得指定排班计划的班次列表")
  83 + @Parameter(name = "planId", description = "排班计划编号", required = true)
  84 + @PreAuthorize("@ss.hasPermission('mes:cal-shift:query')")
  85 + public CommonResult<List<MesCalShiftRespVO>> getShiftListByPlan(@RequestParam("planId") Long planId) {
  86 + List<MesCalShiftDO> list = shiftService.getShiftListByPlanId(planId);
  87 + return success(BeanUtils.toBean(list, MesCalShiftRespVO.class));
  88 + }
  89 +
  90 + @GetMapping("/export-excel")
  91 + @Operation(summary = "导出计划班次 Excel")
  92 + @PreAuthorize("@ss.hasPermission('mes:cal-shift:export')")
  93 + @ApiAccessLog(operateType = EXPORT)
  94 + public void exportShiftExcel(@Valid MesCalShiftPageReqVO pageReqVO,
  95 + HttpServletResponse response) throws IOException {
  96 + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
  97 + List<MesCalShiftDO> list = shiftService.getShiftPage(pageReqVO).getList();
  98 + // 导出 Excel
  99 + ExcelUtils.write(response, "计划班次.xls", "数据", MesCalShiftRespVO.class,
  100 + BeanUtils.toBean(list, MesCalShiftRespVO.class));
  101 + }
  102 +
  103 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +@Schema(description = "管理后台 - MES 排班计划分页 Request VO")
  10 +@Data
  11 +@EqualsAndHashCode(callSuper = true)
  12 +@ToString(callSuper = true)
  13 +public class MesCalPlanPageReqVO extends PageParam {
  14 +
  15 + @Schema(description = "计划编码", example = "PLAN001")
  16 + private String code;
  17 +
  18 + @Schema(description = "计划名称", example = "2024年排班")
  19 + private String name;
  20 +
  21 + @Schema(description = "轮班方式", example = "1")
  22 + private Integer shiftType;
  23 +
  24 + @Schema(description = "状态", example = "0")
  25 + private Integer status;
  26 +
  27 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo;
  2 +
  3 +import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
  4 +import cn.idev.excel.annotation.ExcelProperty;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import lombok.Data;
  7 +
  8 +import java.time.LocalDateTime;
  9 +
  10 +@Schema(description = "管理后台 - MES 排班计划 Response VO")
  11 +@Data
  12 +@ExcelIgnoreUnannotated
  13 +public class MesCalPlanRespVO {
  14 +
  15 + @Schema(description = "计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  16 + @ExcelProperty("计划编号")
  17 + private Long id;
  18 +
  19 + @Schema(description = "计划编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PLAN001")
  20 + @ExcelProperty("计划编码")
  21 + private String code;
  22 +
  23 + @Schema(description = "计划名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024年排班计划")
  24 + @ExcelProperty("计划名称")
  25 + private String name;
  26 +
  27 + @Schema(description = "班组类型", example = "1")
  28 + @ExcelProperty("班组类型")
  29 + private Integer calendarType;
  30 +
  31 + @Schema(description = "开始日期", requiredMode = Schema.RequiredMode.REQUIRED)
  32 + @ExcelProperty("开始日期")
  33 + private LocalDateTime startDate;
  34 +
  35 + @Schema(description = "结束日期", requiredMode = Schema.RequiredMode.REQUIRED)
  36 + @ExcelProperty("结束日期")
  37 + private LocalDateTime endDate;
  38 +
  39 + @Schema(description = "轮班方式", example = "1")
  40 + @ExcelProperty("轮班方式")
  41 + private Integer shiftType;
  42 +
  43 + @Schema(description = "倒班方式", example = "1")
  44 + @ExcelProperty("倒班方式")
  45 + private Integer shiftMethod;
  46 +
  47 + @Schema(description = "倒班天数", example = "7")
  48 + @ExcelProperty("倒班天数")
  49 + private Integer shiftCount;
  50 +
  51 + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
  52 + @ExcelProperty("状态")
  53 + private Integer status;
  54 +
  55 + @Schema(description = "备注")
  56 + @ExcelProperty("备注")
  57 + private String remark;
  58 +
  59 + @Schema(description = "预留字段1")
  60 + private String attribute1;
  61 +
  62 + @Schema(description = "预留字段2")
  63 + private String attribute2;
  64 +
  65 + @Schema(description = "预留字段3")
  66 + private Integer attribute3;
  67 +
  68 + @Schema(description = "预留字段4")
  69 + private Integer attribute4;
  70 +
  71 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  72 + @ExcelProperty("创建时间")
  73 + private LocalDateTime createTime;
  74 +
  75 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanSaveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotEmpty;
  5 +import jakarta.validation.constraints.NotNull;
  6 +import lombok.Data;
  7 +
  8 +import java.time.LocalDateTime;
  9 +
  10 +@Schema(description = "管理后台 - MES 排班计划新增/修改 Request VO")
  11 +@Data
  12 +public class MesCalPlanSaveReqVO {
  13 +
  14 + @Schema(description = "计划编号", example = "1024")
  15 + private Long id;
  16 +
  17 + @Schema(description = "计划编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "PLAN001")
  18 + @NotEmpty(message = "计划编码不能为空")
  19 + private String code;
  20 +
  21 + @Schema(description = "计划名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024年排班计划")
  22 + @NotEmpty(message = "计划名称不能为空")
  23 + private String name;
  24 +
  25 + @Schema(description = "班组类型", example = "1")
  26 + private Integer calendarType;
  27 +
  28 + @Schema(description = "开始日期", requiredMode = Schema.RequiredMode.REQUIRED)
  29 + @NotNull(message = "开始日期不能为空")
  30 + private LocalDateTime startDate;
  31 +
  32 + @Schema(description = "结束日期", requiredMode = Schema.RequiredMode.REQUIRED)
  33 + @NotNull(message = "结束日期不能为空")
  34 + private LocalDateTime endDate;
  35 +
  36 + @Schema(description = "轮班方式", example = "1")
  37 + private Integer shiftType;
  38 +
  39 + @Schema(description = "倒班方式", example = "1")
  40 + private Integer shiftMethod;
  41 +
  42 + @Schema(description = "倒班天数", example = "7")
  43 + private Integer shiftCount;
  44 +
  45 + @Schema(description = "状态", example = "0")
  46 + private Integer status;
  47 +
  48 + @Schema(description = "备注")
  49 + private String remark;
  50 +
  51 + @Schema(description = "预留字段1")
  52 + private String attribute1;
  53 +
  54 + @Schema(description = "预留字段2")
  55 + private String attribute2;
  56 +
  57 + @Schema(description = "预留字段3")
  58 + private Integer attribute3;
  59 +
  60 + @Schema(description = "预留字段4")
  61 + private Integer attribute4;
  62 +
  63 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalShiftPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +@Schema(description = "管理后台 - MES 计划班次分页 Request VO")
  10 +@Data
  11 +@EqualsAndHashCode(callSuper = true)
  12 +@ToString(callSuper = true)
  13 +public class MesCalShiftPageReqVO extends PageParam {
  14 +
  15 + @Schema(description = "排班计划编号", example = "1")
  16 + private Long planId;
  17 +
  18 + @Schema(description = "班次名称", example = "白班")
  19 + private String name;
  20 +
  21 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalShiftRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift;
  2 +
  3 +import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
  4 +import cn.idev.excel.annotation.ExcelProperty;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
  6 +import lombok.Data;
  7 +
  8 +import java.time.LocalDateTime;
  9 +
  10 +@Schema(description = "管理后台 - MES 计划班次 Response VO")
  11 +@Data
  12 +@ExcelIgnoreUnannotated
  13 +public class MesCalShiftRespVO {
  14 +
  15 + @Schema(description = "班次编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  16 + @ExcelProperty("班次编号")
  17 + private Long id;
  18 +
  19 + @Schema(description = "排班计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  20 + @ExcelProperty("排班计划编号")
  21 + private Long planId;
  22 +
  23 + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  24 + @ExcelProperty("显示顺序")
  25 + private Integer sort;
  26 +
  27 + @Schema(description = "班次名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "白班")
  28 + @ExcelProperty("班次名称")
  29 + private String name;
  30 +
  31 + @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "08:00")
  32 + @ExcelProperty("开始时间")
  33 + private String startTime;
  34 +
  35 + @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "17:00")
  36 + @ExcelProperty("结束时间")
  37 + private String endTime;
  38 +
  39 + @Schema(description = "备注")
  40 + @ExcelProperty("备注")
  41 + private String remark;
  42 +
  43 + @Schema(description = "预留字段1")
  44 + private String attribute1;
  45 +
  46 + @Schema(description = "预留字段2")
  47 + private String attribute2;
  48 +
  49 + @Schema(description = "预留字段3")
  50 + private Integer attribute3;
  51 +
  52 + @Schema(description = "预留字段4")
  53 + private Integer attribute4;
  54 +
  55 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  56 + @ExcelProperty("创建时间")
  57 + private LocalDateTime createTime;
  58 +
  59 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/shift/MesCalShiftSaveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotEmpty;
  5 +import jakarta.validation.constraints.NotNull;
  6 +import lombok.Data;
  7 +
  8 +@Schema(description = "管理后台 - MES 计划班次新增/修改 Request VO")
  9 +@Data
  10 +public class MesCalShiftSaveReqVO {
  11 +
  12 + @Schema(description = "班次编号", example = "1024")
  13 + private Long id;
  14 +
  15 + @Schema(description = "排班计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  16 + @NotNull(message = "排班计划不能为空")
  17 + private Long planId;
  18 +
  19 + @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  20 + @NotNull(message = "显示顺序不能为空")
  21 + private Integer sort;
  22 +
  23 + @Schema(description = "班次名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "白班")
  24 + @NotEmpty(message = "班次名称不能为空")
  25 + private String name;
  26 +
  27 + @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "08:00")
  28 + @NotEmpty(message = "开始时间不能为空")
  29 + private String startTime;
  30 +
  31 + @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "17:00")
  32 + @NotEmpty(message = "结束时间不能为空")
  33 + private String endTime;
  34 +
  35 + @Schema(description = "备注")
  36 + private String remark;
  37 +
  38 + @Schema(description = "预留字段1")
  39 + private String attribute1;
  40 +
  41 + @Schema(description = "预留字段2")
  42 + private String attribute2;
  43 +
  44 + @Schema(description = "预留字段3")
  45 + private Integer attribute3;
  46 +
  47 + @Schema(description = "预留字段4")
  48 + private Integer attribute4;
  49 +
  50 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +
  8 +@Schema(description = "管理后台 - MES 计划班组关联 Response VO")
  9 +@Data
  10 +public class MesCalPlanTeamRespVO {
  11 +
  12 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  13 + private Long id;
  14 +
  15 + @Schema(description = "排班计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  16 + private Long planId;
  17 +
  18 + @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + private Long teamId;
  20 +
  21 + // TODO @芋艿:等 cal_team 迁移后,通过 teamId 关联查询填充
  22 + @Schema(description = "班组编码", example = "T001")
  23 + private String teamCode;
  24 +
  25 + // TODO @芋艿:等 cal_team 迁移后,通过 teamId 关联查询填充
  26 + @Schema(description = "班组名称", example = "A组")
  27 + private String teamName;
  28 +
  29 + @Schema(description = "备注")
  30 + private String remark;
  31 +
  32 + @Schema(description = "预留字段1")
  33 + private String attribute1;
  34 +
  35 + @Schema(description = "预留字段2")
  36 + private String attribute2;
  37 +
  38 + @Schema(description = "预留字段3")
  39 + private Integer attribute3;
  40 +
  41 + @Schema(description = "预留字段4")
  42 + private Integer attribute4;
  43 +
  44 + @Schema(description = "创建时间")
  45 + private LocalDateTime createTime;
  46 +
  47 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/team/MesCalPlanTeamSaveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotNull;
  5 +import lombok.Data;
  6 +
  7 +@Schema(description = "管理后台 - MES 计划班组关联新增 Request VO")
  8 +@Data
  9 +public class MesCalPlanTeamSaveReqVO {
  10 +
  11 + @Schema(description = "编号", example = "1024")
  12 + private Long id;
  13 +
  14 + @Schema(description = "排班计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  15 + @NotNull(message = "排班计划不能为空")
  16 + private Long planId;
  17 +
  18 + @Schema(description = "班组编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + @NotNull(message = "班组不能为空")
  20 + private Long teamId;
  21 +
  22 + @Schema(description = "备注")
  23 + private String remark;
  24 +
  25 + @Schema(description = "预留字段1")
  26 + private String attribute1;
  27 +
  28 + @Schema(description = "预留字段2")
  29 + private String attribute2;
  30 +
  31 + @Schema(description = "预留字段3")
  32 + private Integer attribute3;
  33 +
  34 + @Schema(description = "预留字段4")
  35 + private Integer attribute4;
  36 +
  37 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/MesCalPlanDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.cal;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.mes.enums.cal.MesCalPlanStatusEnum;
  5 +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftMethodEnum;
  6 +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum;
  7 +import com.baomidou.mybatisplus.annotation.KeySequence;
  8 +import com.baomidou.mybatisplus.annotation.TableId;
  9 +import com.baomidou.mybatisplus.annotation.TableName;
  10 +import lombok.*;
  11 +
  12 +import java.time.LocalDateTime;
  13 +
  14 +/**
  15 + * MES 排班计划 DO
  16 + *
  17 + * @author 芋道源码
  18 + */
  19 +@TableName("mes_cal_plan")
  20 +@KeySequence("mes_cal_plan_seq")
  21 +@Data
  22 +@EqualsAndHashCode(callSuper = true)
  23 +@ToString(callSuper = true)
  24 +@Builder
  25 +@NoArgsConstructor
  26 +@AllArgsConstructor
  27 +public class MesCalPlanDO extends BaseDO {
  28 +
  29 + /**
  30 + * 计划编号
  31 + */
  32 + @TableId
  33 + private Long id;
  34 + /**
  35 + * 计划编码
  36 + */
  37 + private String code;
  38 + /**
  39 + * 计划名称
  40 + */
  41 + private String name;
  42 + // TODO @AI:增加一个枚举值(类),好一点;
  43 + /**
  44 + * 班组类型
  45 + *
  46 + * 枚举 mes_cal_calendar_type(1=分组轮班, 2=固定班组)
  47 + */
  48 + private Integer calendarType;
  49 + /**
  50 + * 开始日期
  51 + */
  52 + private LocalDateTime startDate;
  53 + /**
  54 + * 结束日期
  55 + */
  56 + private LocalDateTime endDate;
  57 + /**
  58 + * 轮班方式
  59 + *
  60 + * 枚举 {@link MesCalShiftTypeEnum}
  61 + */
  62 + private Integer shiftType;
  63 + /**
  64 + * 倒班方式
  65 + *
  66 + * 枚举 {@link MesCalShiftMethodEnum}
  67 + */
  68 + private Integer shiftMethod;
  69 + /**
  70 + * 倒班天数
  71 + */
  72 + private Integer shiftCount;
  73 + /**
  74 + * 状态
  75 + *
  76 + * 枚举 {@link MesCalPlanStatusEnum}
  77 + */
  78 + private Integer status;
  79 + /**
  80 + * 备注
  81 + */
  82 + private String remark;
  83 + /**
  84 + * 预留字段1
  85 + */
  86 + private String attribute1;
  87 + /**
  88 + * 预留字段2
  89 + */
  90 + private String attribute2;
  91 + /**
  92 + * 预留字段3
  93 + */
  94 + private Integer attribute3;
  95 + /**
  96 + * 预留字段4
  97 + */
  98 + private Integer attribute4;
  99 +
  100 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/MesCalPlanTeamDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.cal;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.KeySequence;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.*;
  8 +
  9 +/**
  10 + * MES 计划班组关联 DO
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@TableName("mes_cal_plan_team")
  15 +@KeySequence("mes_cal_plan_team_seq")
  16 +@Data
  17 +@EqualsAndHashCode(callSuper = true)
  18 +@ToString(callSuper = true)
  19 +@Builder
  20 +@NoArgsConstructor
  21 +@AllArgsConstructor
  22 +public class MesCalPlanTeamDO extends BaseDO {
  23 +
  24 + /**
  25 + * 编号
  26 + */
  27 + @TableId
  28 + private Long id;
  29 + /**
  30 + * 排班计划编号
  31 + *
  32 + * 关联 {@link MesCalPlanDO#getId()}
  33 + */
  34 + private Long planId;
  35 + /**
  36 + * 班组编号
  37 + *
  38 + * TODO @芋艿:关联 cal_team 表,等 cal_team 迁移后补充
  39 + */
  40 + private Long teamId;
  41 + /**
  42 + * 备注
  43 + */
  44 + private String remark;
  45 + /**
  46 + * 预留字段1
  47 + */
  48 + private String attribute1;
  49 + /**
  50 + * 预留字段2
  51 + */
  52 + private String attribute2;
  53 + /**
  54 + * 预留字段3
  55 + */
  56 + private Integer attribute3;
  57 + /**
  58 + * 预留字段4
  59 + */
  60 + private Integer attribute4;
  61 +
  62 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/MesCalShiftDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.cal;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.KeySequence;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.*;
  8 +
  9 +/**
  10 + * MES 计划班次 DO
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@TableName("mes_cal_shift")
  15 +@KeySequence("mes_cal_shift_seq")
  16 +@Data
  17 +@EqualsAndHashCode(callSuper = true)
  18 +@ToString(callSuper = true)
  19 +@Builder
  20 +@NoArgsConstructor
  21 +@AllArgsConstructor
  22 +public class MesCalShiftDO extends BaseDO {
  23 +
  24 + /**
  25 + * 班次编号
  26 + */
  27 + @TableId
  28 + private Long id;
  29 + /**
  30 + * 排班计划编号
  31 + *
  32 + * 关联 {@link MesCalPlanDO#getId()}
  33 + */
  34 + private Long planId;
  35 + /**
  36 + * 显示顺序
  37 + */
  38 + private Integer sort;
  39 + /**
  40 + * 班次名称
  41 + */
  42 + private String name;
  43 + /**
  44 + * 开始时间(HH:mm 格式)
  45 + */
  46 + private String startTime;
  47 + /**
  48 + * 结束时间(HH:mm 格式)
  49 + */
  50 + private String endTime;
  51 + /**
  52 + * 备注
  53 + */
  54 + private String remark;
  55 + /**
  56 + * 预留字段1
  57 + */
  58 + private String attribute1;
  59 + /**
  60 + * 预留字段2
  61 + */
  62 + private String attribute2;
  63 + /**
  64 + * 预留字段3
  65 + */
  66 + private Integer attribute3;
  67 + /**
  68 + * 预留字段4
  69 + */
  70 + private Integer attribute4;
  71 +
  72 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/CalConstants.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.enums.cal;
  2 +
  3 +// TODO @AI:参考别的类,生成枚举类
  4 +/**
  5 + * MES 日历排班常量
  6 + *
  7 + * @author 芋道源码
  8 + */
  9 +public interface CalConstants {
  10 +
  11 + /** 白班 */
  12 + String SHIFT_NAME_DAY = "白班";
  13 + /** 夜班 */
  14 + String SHIFT_NAME_NIGHT = "夜班";
  15 + /** 中班 */
  16 + String SHIFT_NAME_MID = "中班";
  17 +
  18 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.cal.plan;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanPageReqVO;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanSaveReqVO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.MesCalPlanDO;
  7 +import jakarta.validation.Valid;
  8 +
  9 +/**
  10 + * MES 排班计划 Service 接口
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +public interface MesCalPlanService {
  15 +
  16 + /**
  17 + * 创建排班计划
  18 + *
  19 + * @param createReqVO 创建信息
  20 + * @return 编号
  21 + */
  22 + Long createPlan(@Valid MesCalPlanSaveReqVO createReqVO);
  23 +
  24 + /**
  25 + * 更新排班计划
  26 + *
  27 + * @param updateReqVO 更新信息
  28 + */
  29 + void updatePlan(@Valid MesCalPlanSaveReqVO updateReqVO);
  30 +
  31 + /**
  32 + * 删除排班计划
  33 + *
  34 + * @param id 编号
  35 + */
  36 + void deletePlan(Long id);
  37 +
  38 + /**
  39 + * 获得排班计划
  40 + *
  41 + * @param id 编号
  42 + * @return 排班计划
  43 + */
  44 + MesCalPlanDO getPlan(Long id);
  45 +
  46 + /**
  47 + * 获得排班计划分页
  48 + *
  49 + * @param pageReqVO 分页查询
  50 + * @return 排班计划分页
  51 + */
  52 + PageResult<MesCalPlanDO> getPlanPage(MesCalPlanPageReqVO pageReqVO);
  53 +
  54 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.cal.plan;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanPageReqVO;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanSaveReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.MesCalPlanDO;
  8 +import cn.iocoder.yudao.module.mes.dal.mysql.cal.plan.MesCalPlanMapper;
  9 +import cn.iocoder.yudao.module.mes.enums.cal.MesCalPlanStatusEnum;
  10 +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum;
  11 +import jakarta.annotation.Resource;
  12 +import org.springframework.context.annotation.Lazy;
  13 +import org.springframework.stereotype.Service;
  14 +import org.springframework.transaction.annotation.Transactional;
  15 +import org.springframework.validation.annotation.Validated;
  16 +
  17 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  18 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
  19 +
  20 +/**
  21 + * MES 排班计划 Service 实现类
  22 + *
  23 + * @author 芋道源码
  24 + */
  25 +@Service
  26 +@Validated
  27 +public class MesCalPlanServiceImpl implements MesCalPlanService {
  28 +
  29 + @Resource
  30 + private MesCalPlanMapper planMapper;
  31 + @Resource
  32 + @Lazy
  33 + private MesCalShiftService shiftService;
  34 + @Resource
  35 + @Lazy
  36 + private MesCalPlanTeamService planTeamService;
  37 +
  38 + @Override
  39 + @Transactional(rollbackFor = Exception.class)
  40 + public Long createPlan(MesCalPlanSaveReqVO createReqVO) {
  41 + // 1. 校验编码唯一
  42 + validatePlanCodeUnique(null, createReqVO.getCode());
  43 +
  44 + // 2. 插入计划
  45 + MesCalPlanDO plan = BeanUtils.toBean(createReqVO, MesCalPlanDO.class);
  46 + plan.setStatus(MesCalPlanStatusEnum.PREPARE.getStatus()); // 默认草稿
  47 + planMapper.insert(plan);
  48 +
  49 + // 3. 自动生成默认班次
  50 + if (plan.getShiftType() != null) {
  51 + shiftService.addDefaultShift(plan.getId(), plan.getShiftType());
  52 + }
  53 + return plan.getId();
  54 + }
  55 +
  56 + @Override
  57 + @Transactional(rollbackFor = Exception.class)
  58 + public void updatePlan(MesCalPlanSaveReqVO updateReqVO) {
  59 + // 1.1 校验存在
  60 + MesCalPlanDO existPlan = validatePlanExists(updateReqVO.getId());
  61 + // 1.2 校验编码唯一
  62 + validatePlanCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
  63 + // 1.3 若 status 变为 CONFIRMED,校验班组数量
  64 + if (MesCalPlanStatusEnum.CONFIRMED.getStatus().equals(updateReqVO.getStatus())
  65 + && !MesCalPlanStatusEnum.CONFIRMED.getStatus().equals(existPlan.getStatus())) {
  66 + validateTeamCountForConfirm(updateReqVO.getId(), updateReqVO.getShiftType());
  67 + }
  68 +
  69 + // 2. 更新
  70 + MesCalPlanDO updateObj = BeanUtils.toBean(updateReqVO, MesCalPlanDO.class);
  71 + planMapper.updateById(updateObj);
  72 +
  73 + // TODO @芋艿:确认时调用 calTeamshiftService.genRecords(planId) 生成排班记录,等 cal_team_shift 迁移后
  74 + }
  75 +
  76 + @Override
  77 + @Transactional(rollbackFor = Exception.class)
  78 + public void deletePlan(Long id) {
  79 + // 1.1 校验存在
  80 + MesCalPlanDO plan = validatePlanExists(id);
  81 + // 1.2 校验状态为草稿
  82 + // TODO @AI:notEquals 更好一点;
  83 + if (!MesCalPlanStatusEnum.PREPARE.getStatus().equals(plan.getStatus())) {
  84 + throw exception(CAL_PLAN_NOT_PREPARE);
  85 + }
  86 +
  87 + // 2.1 级联删除班次 + 班组关联
  88 + shiftService.deleteShiftByPlanId(id);
  89 + planTeamService.deleteByPlanId(id);
  90 + // 2.2 删除计划
  91 + planMapper.deleteById(id);
  92 + }
  93 +
  94 + @Override
  95 + public MesCalPlanDO getPlan(Long id) {
  96 + return planMapper.selectById(id);
  97 + }
  98 +
  99 + @Override
  100 + public PageResult<MesCalPlanDO> getPlanPage(MesCalPlanPageReqVO pageReqVO) {
  101 + return planMapper.selectPage(pageReqVO);
  102 + }
  103 +
  104 + private MesCalPlanDO validatePlanExists(Long id) {
  105 + MesCalPlanDO plan = planMapper.selectById(id);
  106 + if (plan == null) {
  107 + throw exception(CAL_PLAN_NOT_EXISTS);
  108 + }
  109 + return plan;
  110 + }
  111 +
  112 + private void validatePlanCodeUnique(Long id, String code) {
  113 + MesCalPlanDO plan = planMapper.selectByCode(code);
  114 + if (plan == null) {
  115 + return;
  116 + }
  117 + if (id == null || !id.equals(plan.getId())) {
  118 + throw exception(CAL_PLAN_CODE_DUPLICATE);
  119 + }
  120 + }
  121 +
  122 + /**
  123 + * 确认排班计划时,校验班组数量是否与轮班方式匹配
  124 + */
  125 + private void validateTeamCountForConfirm(Long planId, Integer shiftType) {
  126 + Long teamCount = planTeamService.getPlanTeamCountByPlanId(planId);
  127 + // TODO @AI:startTime、endTime 可以放到枚举类里么?List<hutool Pair>;这样就可以判断数量;
  128 + if (MesCalShiftTypeEnum.TWO.getType().equals(shiftType) && teamCount < 2) {
  129 + throw exception(CAL_PLAN_TEAM_COUNT_NOT_MATCH);
  130 + } else if (MesCalShiftTypeEnum.THREE.getType().equals(shiftType) && teamCount < 3) {
  131 + throw exception(CAL_PLAN_TEAM_COUNT_NOT_MATCH);
  132 + }
  133 + // TODO @AI:兜底下,其它,则抛出异常参数 IllegalArgumentException,提示不支持的轮班方式;
  134 + }
  135 +
  136 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanTeamService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.cal.plan;
  2 +
  3 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team.MesCalPlanTeamSaveReqVO;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.MesCalPlanTeamDO;
  5 +import jakarta.validation.Valid;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * MES 计划班组关联 Service 接口
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +public interface MesCalPlanTeamService {
  15 +
  16 + /**
  17 + * 创建计划班组关联
  18 + *
  19 + * @param createReqVO 创建信息
  20 + * @return 编号
  21 + */
  22 + Long createPlanTeam(@Valid MesCalPlanTeamSaveReqVO createReqVO);
  23 +
  24 + /**
  25 + * 删除计划班组关联
  26 + *
  27 + * @param id 编号
  28 + */
  29 + void deletePlanTeam(Long id);
  30 +
  31 + /**
  32 + * 获得指定排班计划的班组列表
  33 + *
  34 + * @param planId 排班计划编号
  35 + * @return 班组关联列表
  36 + */
  37 + List<MesCalPlanTeamDO> getPlanTeamListByPlanId(Long planId);
  38 +
  39 + /**
  40 + * 获得指定排班计划的班组数量
  41 + *
  42 + * @param planId 排班计划编号
  43 + * @return 班组数量
  44 + */
  45 + Long getPlanTeamCountByPlanId(Long planId);
  46 +
  47 + /**
  48 + * 根据排班计划编号删除所有班组关联
  49 + *
  50 + * @param planId 排班计划编号
  51 + */
  52 + void deleteByPlanId(Long planId);
  53 +
  54 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanTeamServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.cal.plan;
  2 +
  3 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.team.MesCalPlanTeamSaveReqVO;
  5 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.MesCalPlanTeamDO;
  6 +import cn.iocoder.yudao.module.mes.dal.mysql.cal.plan.MesCalPlanTeamMapper;
  7 +import jakarta.annotation.Resource;
  8 +import org.springframework.stereotype.Service;
  9 +import org.springframework.validation.annotation.Validated;
  10 +
  11 +import java.util.List;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  14 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
  15 +
  16 +/**
  17 + * MES 计划班组关联 Service 实现类
  18 + *
  19 + * @author 芋道源码
  20 + */
  21 +@Service
  22 +@Validated
  23 +public class MesCalPlanTeamServiceImpl implements MesCalPlanTeamService {
  24 +
  25 + @Resource
  26 + private MesCalPlanTeamMapper planTeamMapper;
  27 +
  28 + @Override
  29 + public Long createPlanTeam(MesCalPlanTeamSaveReqVO createReqVO) {
  30 + // 校验排班计划存在
  31 + validatePlanTeamDuplicate(createReqVO.getPlanId(), createReqVO.getTeamId());
  32 +
  33 + // 插入
  34 + MesCalPlanTeamDO planTeam = BeanUtils.toBean(createReqVO, MesCalPlanTeamDO.class);
  35 + planTeamMapper.insert(planTeam);
  36 + return planTeam.getId();
  37 + }
  38 +
  39 + @Override
  40 + public void deletePlanTeam(Long id) {
  41 + // 校验存在
  42 + validatePlanTeamExists(id);
  43 + // 删除
  44 + planTeamMapper.deleteById(id);
  45 + }
  46 +
  47 + private void validatePlanTeamExists(Long id) {
  48 + if (planTeamMapper.selectById(id) == null) {
  49 + throw exception(CAL_PLAN_TEAM_NOT_EXISTS);
  50 + }
  51 + }
  52 +
  53 + private void validatePlanTeamDuplicate(Long planId, Long teamId) {
  54 + MesCalPlanTeamDO planTeam = planTeamMapper.selectByPlanIdAndTeamId(planId, teamId);
  55 + if (planTeam != null) {
  56 + throw exception(CAL_PLAN_TEAM_DUPLICATE);
  57 + }
  58 + }
  59 +
  60 + @Override
  61 + public List<MesCalPlanTeamDO> getPlanTeamListByPlanId(Long planId) {
  62 + return planTeamMapper.selectListByPlanId(planId);
  63 + }
  64 +
  65 + @Override
  66 + public Long getPlanTeamCountByPlanId(Long planId) {
  67 + return planTeamMapper.selectCountByPlanId(planId);
  68 + }
  69 +
  70 + @Override
  71 + public void deleteByPlanId(Long planId) {
  72 + planTeamMapper.deleteByPlanId(planId);
  73 + }
  74 +
  75 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalShiftService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.cal.plan;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalShiftPageReqVO;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalShiftSaveReqVO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.MesCalShiftDO;
  7 +import jakarta.validation.Valid;
  8 +
  9 +import java.util.List;
  10 +
  11 +/**
  12 + * MES 计划班次 Service 接口
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +public interface MesCalShiftService {
  17 +
  18 + /**
  19 + * 创建计划班次
  20 + *
  21 + * @param createReqVO 创建信息
  22 + * @return 编号
  23 + */
  24 + Long createShift(@Valid MesCalShiftSaveReqVO createReqVO);
  25 +
  26 + /**
  27 + * 更新计划班次
  28 + *
  29 + * @param updateReqVO 更新信息
  30 + */
  31 + void updateShift(@Valid MesCalShiftSaveReqVO updateReqVO);
  32 +
  33 + /**
  34 + * 删除计划班次
  35 + *
  36 + * @param id 编号
  37 + */
  38 + void deleteShift(Long id);
  39 +
  40 + /**
  41 + * 获得计划班次
  42 + *
  43 + * @param id 编号
  44 + * @return 计划班次
  45 + */
  46 + MesCalShiftDO getShift(Long id);
  47 +
  48 + /**
  49 + * 获得计划班次分页
  50 + *
  51 + * @param pageReqVO 分页查询
  52 + * @return 计划班次分页
  53 + */
  54 + PageResult<MesCalShiftDO> getShiftPage(MesCalShiftPageReqVO pageReqVO);
  55 +
  56 + /**
  57 + * 获得指定排班计划的班次列表
  58 + *
  59 + * @param planId 排班计划编号
  60 + * @return 班次列表
  61 + */
  62 + List<MesCalShiftDO> getShiftListByPlanId(Long planId);
  63 +
  64 + /**
  65 + * 获得指定排班计划的班次数量
  66 + *
  67 + * @param planId 排班计划编号
  68 + * @return 班次数量
  69 + */
  70 + Long getShiftCountByPlanId(Long planId);
  71 +
  72 + /**
  73 + * 根据轮班方式添加默认班次
  74 + *
  75 + * @param planId 排班计划编号
  76 + * @param shiftType 轮班方式
  77 + */
  78 + void addDefaultShift(Long planId, Integer shiftType);
  79 +
  80 + /**
  81 + * 根据排班计划编号删除所有班次
  82 + *
  83 + * @param planId 排班计划编号
  84 + */
  85 + void deleteShiftByPlanId(Long planId);
  86 +
  87 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalShiftServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.cal.plan;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalShiftPageReqVO;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalShiftSaveReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.MesCalPlanDO;
  8 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.MesCalShiftDO;
  9 +import cn.iocoder.yudao.module.mes.dal.mysql.cal.plan.MesCalPlanMapper;
  10 +import cn.iocoder.yudao.module.mes.dal.mysql.cal.plan.MesCalShiftMapper;
  11 +import cn.iocoder.yudao.module.mes.enums.cal.CalConstants;
  12 +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum;
  13 +import jakarta.annotation.Resource;
  14 +import org.springframework.stereotype.Service;
  15 +import org.springframework.validation.annotation.Validated;
  16 +
  17 +import java.util.List;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  20 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
  21 +
  22 +/**
  23 + * MES 计划班次 Service 实现类
  24 + *
  25 + * @author 芋道源码
  26 + */
  27 +@Service
  28 +@Validated
  29 +public class MesCalShiftServiceImpl implements MesCalShiftService {
  30 +
  31 + @Resource
  32 + private MesCalShiftMapper shiftMapper;
  33 + @Resource
  34 + private MesCalPlanMapper planMapper;
  35 +
  36 + @Override
  37 + public Long createShift(MesCalShiftSaveReqVO createReqVO) {
  38 + // 校验班次数量限制
  39 + validateShiftCount(createReqVO.getPlanId());
  40 +
  41 + // 插入
  42 + MesCalShiftDO shift = BeanUtils.toBean(createReqVO, MesCalShiftDO.class);
  43 + shiftMapper.insert(shift);
  44 + return shift.getId();
  45 + }
  46 +
  47 + @Override
  48 + public void updateShift(MesCalShiftSaveReqVO updateReqVO) {
  49 + // 校验存在
  50 + validateShiftExists(updateReqVO.getId());
  51 + // 更新
  52 + MesCalShiftDO updateObj = BeanUtils.toBean(updateReqVO, MesCalShiftDO.class);
  53 + shiftMapper.updateById(updateObj);
  54 + }
  55 +
  56 + @Override
  57 + public void deleteShift(Long id) {
  58 + // 校验存在
  59 + validateShiftExists(id);
  60 + // 删除
  61 + shiftMapper.deleteById(id);
  62 + }
  63 +
  64 + private void validateShiftExists(Long id) {
  65 + if (shiftMapper.selectById(id) == null) {
  66 + throw exception(CAL_SHIFT_NOT_EXISTS);
  67 + }
  68 + }
  69 +
  70 + /**
  71 + * 校验班次数量是否超限
  72 + * <p>
  73 + * 通过 planId 查询已有班次数量,根据排班计划的轮班方式校验
  74 + */
  75 + private void validateShiftCount(Long planId) {
  76 + MesCalPlanDO plan = planMapper.selectById(planId);
  77 + if (plan == null) {
  78 + return;
  79 + }
  80 + Long count = shiftMapper.selectCountByPlanId(planId);
  81 + Integer shiftType = plan.getShiftType();
  82 + // TODO @AI:startTime、endTime 可以放到枚举类里么?List<hutool Pair>;这样可以 count 来判断。更简洁;
  83 + if (MesCalShiftTypeEnum.SINGLE.getType().equals(shiftType) && count >= 1) {
  84 + throw exception(CAL_SHIFT_COUNT_EXCEED_SINGLE);
  85 + } else if (MesCalShiftTypeEnum.TWO.getType().equals(shiftType) && count >= 2) {
  86 + throw exception(CAL_SHIFT_COUNT_EXCEED_TWO);
  87 + } else if (MesCalShiftTypeEnum.THREE.getType().equals(shiftType) && count >= 3) {
  88 + throw exception(CAL_SHIFT_COUNT_EXCEED_THREE);
  89 + }
  90 + }
  91 +
  92 + @Override
  93 + public MesCalShiftDO getShift(Long id) {
  94 + return shiftMapper.selectById(id);
  95 + }
  96 +
  97 + @Override
  98 + public PageResult<MesCalShiftDO> getShiftPage(MesCalShiftPageReqVO pageReqVO) {
  99 + return shiftMapper.selectPage(pageReqVO);
  100 + }
  101 +
  102 + @Override
  103 + public List<MesCalShiftDO> getShiftListByPlanId(Long planId) {
  104 + return shiftMapper.selectListByPlanId(planId);
  105 + }
  106 +
  107 + @Override
  108 + public Long getShiftCountByPlanId(Long planId) {
  109 + return shiftMapper.selectCountByPlanId(planId);
  110 + }
  111 +
  112 + @Override
  113 + public void addDefaultShift(Long planId, Integer shiftType) {
  114 + // 根据轮班方式,添加默认班次
  115 + // TODO @AI:startTime、endTime 可以放到枚举类里么?List<hutool Pair>;这样就可以 for 循环;
  116 + if (MesCalShiftTypeEnum.SINGLE.getType().equals(shiftType)) {
  117 + // 单白班:1 个班次
  118 + insertShift(planId, 1, CalConstants.SHIFT_NAME_DAY, "08:00", "17:00");
  119 + } else if (MesCalShiftTypeEnum.TWO.getType().equals(shiftType)) {
  120 + // 两班倒:2 个班次
  121 + insertShift(planId, 1, CalConstants.SHIFT_NAME_DAY, "08:00", "20:00");
  122 + insertShift(planId, 2, CalConstants.SHIFT_NAME_NIGHT, "20:00", "08:00");
  123 + } else if (MesCalShiftTypeEnum.THREE.getType().equals(shiftType)) {
  124 + // 三班倒:3 个班次
  125 + insertShift(planId, 1, CalConstants.SHIFT_NAME_DAY, "08:00", "16:00");
  126 + insertShift(planId, 2, CalConstants.SHIFT_NAME_MID, "16:00", "00:00");
  127 + insertShift(planId, 3, CalConstants.SHIFT_NAME_NIGHT, "00:00", "08:00");
  128 + }
  129 + }
  130 +
  131 + private void insertShift(Long planId, Integer sort, String name, String startTime, String endTime) {
  132 + // TODO @AI:链式 set,想通放在一样;
  133 + MesCalShiftDO shift = new MesCalShiftDO();
  134 + shift.setPlanId(planId);
  135 + shift.setSort(sort);
  136 + shift.setName(name);
  137 + shift.setStartTime(startTime);
  138 + shift.setEndTime(endTime);
  139 + shiftMapper.insert(shift);
  140 + }
  141 +
  142 + @Override
  143 + public void deleteShiftByPlanId(Long planId) {
  144 + shiftMapper.deleteByPlanId(planId);
  145 + }
  146 +
  147 +}
... ...