Commit 1aab8aef43d4d0baa23c5535b0a466e640079767

Authored by YunaiV
1 parent 9014ff1f

feat(mes): 完善排班日历功能,新增假期过滤及班组排班记录查询逻辑

Showing 15 changed files with 325 additions and 292 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/MesCalCalendarController.java
1 1 package cn.iocoder.yudao.module.mes.controller.admin.cal.calendar;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.date.DatePattern;
3 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 6 import cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo.MesCalCalendarListReqVO;
5 7 import cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo.MesCalCalendarRespVO;
6   -import cn.iocoder.yudao.module.mes.service.cal.calendar.MesCalCalendarService;
  8 +import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftListReqVO;
  9 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO;
  10 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO;
  11 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO;
  12 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO;
  13 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamMemberDO;
  14 +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO;
  15 +import cn.iocoder.yudao.module.mes.service.cal.holiday.MesCalHolidayService;
  16 +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService;
  17 +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService;
  18 +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamMemberService;
  19 +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamService;
  20 +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamShiftService;
7 21 import io.swagger.v3.oas.annotations.Operation;
8 22 import io.swagger.v3.oas.annotations.tags.Tag;
9 23 import jakarta.annotation.Resource;
... ... @@ -14,9 +28,13 @@ import org.springframework.web.bind.annotation.GetMapping;
14 28 import org.springframework.web.bind.annotation.RequestMapping;
15 29 import org.springframework.web.bind.annotation.RestController;
16 30  
17   -import java.util.List;
  31 +import java.time.LocalDate;
  32 +import java.time.LocalDateTime;
  33 +import java.util.*;
  34 +import java.util.stream.Collectors;
18 35  
19 36 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  37 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
20 38  
21 39 @Tag(name = "管理后台 - MES 排班日历")
22 40 @RestController
... ... @@ -25,14 +43,185 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
25 43 public class MesCalCalendarController {
26 44  
27 45 @Resource
28   - private MesCalCalendarService calendarService;
  46 + private MesCalTeamShiftService teamShiftService;
  47 + @Resource
  48 + private MesCalTeamService teamService;
  49 + @Resource
  50 + private MesCalPlanShiftService planShiftService;
  51 + @Resource
  52 + private MesCalPlanService planService;
  53 + @Resource
  54 + private MesCalTeamMemberService teamMemberService;
  55 + @Resource
  56 + private MesCalHolidayService holidayService;
29 57  
30 58 @GetMapping("/list")
31 59 @Operation(summary = "查询排班日历")
32 60 @PreAuthorize("@ss.hasPermission('mes:cal-team-shift:query')")
33 61 public CommonResult<List<MesCalCalendarRespVO>> getCalendarList(@Valid MesCalCalendarListReqVO reqVO) {
34   - List<MesCalCalendarRespVO> list = calendarService.getCalendarList(reqVO);
35   - return success(list);
  62 + // 1.1 根据查询类型获取班组排班记录
  63 + List<MesCalTeamShiftDO> teamShifts = getTeamShifts(reqVO);
  64 + if (CollUtil.isEmpty(teamShifts)) {
  65 + return success(Collections.emptyList());
  66 + }
  67 + // 1.2 查询假期列表,构建假期日期集合
  68 + // TODO @AI:是不是按照指定日期查询下,避免加载所有!
  69 + Set<String> holidaySet = buildHolidaySet();
  70 + // 1.3 批量查询关联数据:班组、班次、排班计划
  71 + Map<Long, MesCalTeamDO> teamMap = teamService.getTeamMap(
  72 + convertSet(teamShifts, MesCalTeamShiftDO::getTeamId));
  73 + Map<Long, MesCalPlanShiftDO> shiftMap = planShiftService.getPlanShiftMap(
  74 + convertSet(teamShifts, MesCalTeamShiftDO::getShiftId));
  75 + Map<Long, MesCalPlanDO> planMap = planService.getPlanMap(
  76 + convertSet(teamShifts, MesCalTeamShiftDO::getPlanId));
  77 +
  78 + // 2. 按 day 分组聚合,过滤假期
  79 + // TODO @AI:使用 MapUtils 里的方法;
  80 + Map<String, List<MesCalTeamShiftDO>> dayGroupMap = teamShifts.stream()
  81 + .collect(Collectors.groupingBy(
  82 + ts -> ts.getDay().toLocalDate().format(DatePattern.NORM_DATE_FORMATTER),
  83 + LinkedHashMap::new,
  84 + Collectors.toList()
  85 + ));
  86 + List<MesCalCalendarRespVO> result = new ArrayList<>();
  87 + for (Map.Entry<String, List<MesCalTeamShiftDO>> entry : dayGroupMap.entrySet()) {
  88 + String dayStr = entry.getKey();
  89 + // 4.1 过滤假期
  90 + if (holidaySet.contains(dayStr)) {
  91 + continue;
  92 + }
  93 + List<MesCalTeamShiftDO> dayShifts = entry.getValue();
  94 + dayShifts.sort(Comparator.comparing(ts -> ts.getSort() != null ? ts.getSort() : 0)); // 按 sort 升序排列
  95 + // 4.2 获取轮班方式(取第一条记录关联的排班计划)
  96 + Integer shiftType = null;
  97 + MesCalTeamShiftDO first = dayShifts.get(0);
  98 + if (first.getPlanId() != null) {
  99 + MesCalPlanDO plan = planMap.get(first.getPlanId());
  100 + if (plan != null) {
  101 + shiftType = plan.getShiftType();
  102 + }
  103 + }
  104 + // 4.3 构建班组排班项列表
  105 + // TODO @AI:convertList?
  106 + List<MesCalCalendarRespVO.TeamShiftItem> items = dayShifts.stream()
  107 + .map(ts -> buildTeamShiftItem(ts, teamMap, shiftMap))
  108 + .collect(Collectors.toList());
  109 +
  110 + // 4.4 构建日历项,添加到结果列表
  111 + // TODO @AI:先构建出一个对象,在 add 到 result 里;
  112 + result.add(MesCalCalendarRespVO.builder()
  113 + .day(LocalDate.parse(dayStr, DatePattern.NORM_DATE_FORMATTER).atStartOfDay())
  114 + .shiftType(shiftType)
  115 + .teamShifts(items)
  116 + .build());
  117 + }
  118 + return success(result);
  119 + }
  120 +
  121 + /**
  122 + * 根据查询类型获取班组排班记录
  123 + */
  124 + @SuppressWarnings("EnhancedSwitchMigration")
  125 + private List<MesCalTeamShiftDO> getTeamShifts(MesCalCalendarListReqVO reqVO) {
  126 + LocalDateTime startDay = reqVO.getStartDay();
  127 + LocalDateTime endDay = reqVO.getEndDay();
  128 + switch (reqVO.getQueryType()) {
  129 + case MesCalCalendarListReqVO.QUERY_TYPE_TYPE:
  130 + return getTeamShiftsByCalendarType(reqVO.getCalendarType(), startDay, endDay);
  131 + case MesCalCalendarListReqVO.QUERY_TYPE_TEAM:
  132 + return getTeamShiftsByTeamId(reqVO.getTeamId(), startDay, endDay);
  133 + case MesCalCalendarListReqVO.QUERY_TYPE_USER:
  134 + return getTeamShiftsByUserId(reqVO.getUserId(), startDay, endDay);
  135 + default:
  136 + return Collections.emptyList();
  137 + }
  138 + }
  139 +
  140 + /**
  141 + * 构建单条 TeamShiftItem
  142 + */
  143 + private MesCalCalendarRespVO.TeamShiftItem buildTeamShiftItem(MesCalTeamShiftDO ts,
  144 + Map<Long, MesCalTeamDO> teamMap,
  145 + Map<Long, MesCalPlanShiftDO> shiftMap) {
  146 + MesCalTeamDO team = teamMap.get(ts.getTeamId());
  147 + MesCalPlanShiftDO shift = shiftMap.get(ts.getShiftId());
  148 + return MesCalCalendarRespVO.TeamShiftItem.builder()
  149 + .teamId(ts.getTeamId()).teamName(team != null ? team.getName() : null)
  150 + .shiftId(ts.getShiftId()).shiftName(shift != null ? shift.getName() : null)
  151 + .sort(ts.getSort()).build();
  152 + }
  153 +
  154 + /**
  155 + * 按班组类型查询排班记录
  156 + */
  157 + private List<MesCalTeamShiftDO> getTeamShiftsByCalendarType(Integer calendarType,
  158 + LocalDateTime startDay, LocalDateTime endDay) {
  159 + if (calendarType == null) {
  160 + return Collections.emptyList();
  161 + }
  162 + // 1. 查询指定类型的所有班组
  163 + List<MesCalTeamDO> teams = teamService.getTeamList().stream()
  164 + .filter(t -> calendarType.equals(t.getCalendarType()))
  165 + .collect(Collectors.toList());
  166 + if (CollUtil.isEmpty(teams)) {
  167 + return Collections.emptyList();
  168 + }
  169 + // 2. 查询这些班组在日期范围内的排班记录
  170 + List<MesCalTeamShiftDO> result = new ArrayList<>(teams.size());
  171 + for (MesCalTeamDO team : teams) {
  172 + MesCalTeamShiftListReqVO reqVO = new MesCalTeamShiftListReqVO()
  173 + .setTeamId(team.getId()).setStartDay(startDay).setEndDay(endDay);
  174 + result.addAll(teamShiftService.getTeamShiftList(reqVO));
  175 + }
  176 + return result;
  177 + }
  178 +
  179 + /**
  180 + * 按班组编号查询排班记录
  181 + */
  182 + private List<MesCalTeamShiftDO> getTeamShiftsByTeamId(Long teamId, LocalDateTime startDay, LocalDateTime endDay) {
  183 + if (teamId == null) {
  184 + return Collections.emptyList();
  185 + }
  186 + MesCalTeamShiftListReqVO reqVO = new MesCalTeamShiftListReqVO()
  187 + .setTeamId(teamId).setStartDay(startDay).setEndDay(endDay);
  188 + return teamShiftService.getTeamShiftList(reqVO);
  189 + }
  190 +
  191 + /**
  192 + * 按用户编号查询排班记录(先查用户所属班组,再查班组排班)
  193 + */
  194 + private List<MesCalTeamShiftDO> getTeamShiftsByUserId(Long userId,
  195 + LocalDateTime startDay, LocalDateTime endDay) {
  196 + if (userId == null) {
  197 + return Collections.emptyList();
  198 + }
  199 + // 1. 查询用户所属的班组(一个用户只属于一个班组)
  200 + MesCalTeamMemberDO member = teamMemberService.getTeamMemberByUserId(userId);
  201 + if (member == null) {
  202 + return Collections.emptyList();
  203 + }
  204 + // 2. 查询该班组在日期范围内的排班记录
  205 + MesCalTeamShiftListReqVO reqVO = new MesCalTeamShiftListReqVO()
  206 + .setTeamId(member.getTeamId()).setStartDay(startDay).setEndDay(endDay);
  207 + return teamShiftService.getTeamShiftList(reqVO);
  208 + }
  209 +
  210 + /**
  211 + * 构建假期日期集合(yyyy-MM-dd 格式)
  212 + */
  213 + private Set<String> buildHolidaySet() {
  214 + List<MesCalHolidayDO> holidays = holidayService.getHolidayList();
  215 + Set<String> holidaySet = new HashSet<>();
  216 + for (MesCalHolidayDO holiday : holidays) {
  217 + // type=2 表示节假日
  218 + // todo @AI:需要搞个枚举类;另外 holiday 那的字段,也要处理下;
  219 + if (holiday.getType() != null && holiday.getType() == 2) {
  220 + LocalDate day = holiday.getDay().toLocalDate();
  221 + holidaySet.add(day.format(DatePattern.NORM_DATE_FORMATTER));
  222 + }
  223 + }
  224 + return holidaySet;
36 225 }
37 226  
38 227 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarListReqVO.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import jakarta.validation.constraints.NotEmpty;
  5 +import jakarta.validation.constraints.NotNull;
5 6 import lombok.Data;
6 7 import org.springframework.format.annotation.DateTimeFormat;
7 8  
... ... @@ -17,11 +18,13 @@ public class MesCalCalendarListReqVO {
17 18 public static final String QUERY_TYPE_TEAM = "TEAM";
18 19 public static final String QUERY_TYPE_USER = "USER";
19 20  
20   - @Schema(description = "开始日期")
  21 + @Schema(description = "开始日期", requiredMode = Schema.RequiredMode.REQUIRED)
  22 + @NotNull(message = "开始日期不能为空")
21 23 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
22 24 private LocalDateTime startDay;
23 25  
24   - @Schema(description = "结束日期")
  26 + @Schema(description = "结束日期", requiredMode = Schema.RequiredMode.REQUIRED)
  27 + @NotNull(message = "结束日期不能为空")
25 28 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
26 29 private LocalDateTime endDay;
27 30  
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/calendar/vo/MesCalCalendarRespVO.java
... ... @@ -6,7 +6,7 @@ import lombok.Builder;
6 6 import lombok.Data;
7 7 import lombok.NoArgsConstructor;
8 8  
9   -import java.time.LocalDate;
  9 +import java.time.LocalDateTime;
10 10 import java.util.List;
11 11  
12 12 @Schema(description = "管理后台 - MES 排班日历 Response VO")
... ... @@ -16,9 +16,8 @@ import java.util.List;
16 16 @AllArgsConstructor
17 17 public class MesCalCalendarRespVO {
18 18  
19   - // TODO @AI: private LocalDateTime day; 合适点,和 holiday 保持统一;
20   - @Schema(description = "日期,格式 yyyy-MM-dd", requiredMode = Schema.RequiredMode.REQUIRED, example = "2025-01-15")
21   - private String day;
  19 + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2025-01-15 00:00:00")
  20 + private LocalDateTime day;
22 21  
23 22 @Schema(description = "轮班方式", example = "2")
24 23 private Integer shiftType; // 对应 MesCalShiftTypeEnum 枚举值
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/calendar/MesCalCalendarService.java deleted
1   -package cn.iocoder.yudao.module.mes.service.cal.calendar;
2   -
3   -import cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo.MesCalCalendarListReqVO;
4   -import cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo.MesCalCalendarRespVO;
5   -
6   -import java.util.List;
7   -
8   -/**
9   - * MES 排班日历 Service 接口
10   - *
11   - * @author 芋道源码
12   - */
13   -public interface MesCalCalendarService {
14   -
15   - /**
16   - * 查询排班日历列表
17   - *
18   - * @param reqVO 查询条件
19   - * @return 排班日历列表
20   - */
21   - List<MesCalCalendarRespVO> getCalendarList(MesCalCalendarListReqVO reqVO);
22   -
23   -}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/calendar/MesCalCalendarServiceImpl.java deleted
1   -package cn.iocoder.yudao.module.mes.service.cal.calendar;
2   -
3   -import cn.hutool.core.collection.CollUtil;
4   -import cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo.MesCalCalendarListReqVO;
5   -import cn.iocoder.yudao.module.mes.controller.admin.cal.calendar.vo.MesCalCalendarRespVO;
6   -import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftListReqVO;
7   -import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO;
8   -import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO;
9   -import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO;
10   -import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO;
11   -import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamMemberDO;
12   -import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO;
13   -import cn.iocoder.yudao.module.mes.dal.mysql.cal.holiday.MesCalHolidayMapper;
14   -import cn.iocoder.yudao.module.mes.dal.mysql.cal.plan.MesCalPlanMapper;
15   -import cn.iocoder.yudao.module.mes.dal.mysql.cal.team.MesCalTeamMapper;
16   -import cn.iocoder.yudao.module.mes.dal.mysql.cal.team.MesCalTeamMemberMapper;
17   -import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService;
18   -import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamShiftService;
19   -import jakarta.annotation.Resource;
20   -import org.springframework.stereotype.Service;
21   -import org.springframework.validation.annotation.Validated;
22   -
23   -import java.time.LocalDate;
24   -import java.time.LocalDateTime;
25   -import java.time.format.DateTimeFormatter;
26   -import java.util.*;
27   -import java.util.stream.Collectors;
28   -
29   -/**
30   - * MES 排班日历 Service 实现类
31   - *
32   - * @author 芋道源码
33   - */
34   -@Service
35   -@Validated
36   -public class MesCalCalendarServiceImpl implements MesCalCalendarService {
37   -
38   - // TODO @AI:看看能不能用 hutool 里,已经枚举好的;
39   - private static final DateTimeFormatter DAY_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
40   -
41   - @Resource
42   - private MesCalTeamShiftService teamShiftService;
43   - @Resource
44   - private MesCalPlanShiftService planShiftService;
45   - @Resource
46   - private MesCalTeamMapper teamMapper;
47   - @Resource
48   - private MesCalTeamMemberMapper teamMemberMapper;
49   - @Resource
50   - private MesCalPlanMapper planMapper;
51   - @Resource
52   - private MesCalHolidayMapper holidayMapper;
53   -
54   - @Override
55   - public List<MesCalCalendarRespVO> getCalendarList(MesCalCalendarListReqVO reqVO) {
56   - // 1. 计算月份范围
57   - // TODO @AI:参数非空,通过 validator 在 MesCalCalendarListReqVO 里;
58   - LocalDateTime startDay = reqVO.getStartDay();
59   - LocalDateTime endDay = reqVO.getEndDay();
60   - if (startDay == null || endDay == null) {
61   - return Collections.emptyList();
62   - }
63   -
64   - // 2. 根据查询类型查询班组排班记录
65   - // TODO @AI:抽个小方法去返回;
66   - List<MesCalTeamShiftDO> teamShifts;
67   - switch (reqVO.getQueryType()) {
68   - case MesCalCalendarListReqVO.QUERY_TYPE_TYPE:
69   - teamShifts = getTeamShiftsByCalendarType(reqVO.getCalendarType(), startDay, endDay);
70   - break;
71   - case MesCalCalendarListReqVO.QUERY_TYPE_TEAM:
72   - teamShifts = getTeamShiftsByTeamId(reqVO.getTeamId(), startDay, endDay);
73   - break;
74   - case MesCalCalendarListReqVO.QUERY_TYPE_USER:
75   - teamShifts = getTeamShiftsByUserId(reqVO.getUserId(), startDay, endDay);
76   - break;
77   - default:
78   - return Collections.emptyList();
79   - }
80   - if (CollUtil.isEmpty(teamShifts)) {
81   - return Collections.emptyList();
82   - }
83   -
84   - // 3. 查询假期列表,构建假期日期集合
85   - Set<String> holidaySet = buildHolidaySet();
86   -
87   - // 4. 批量查询关联数据:班组名称、班次名称
88   - // TODO @AI:需要通过 teamService 去查询,并且要 getTeamMap 的方式;不要 Map<Long, String> 这种;
89   - Set<Long> teamIds = teamShifts.stream().map(MesCalTeamShiftDO::getTeamId).collect(Collectors.toSet());
90   - Map<Long, String> teamNameMap = teamMapper.selectBatchIds(teamIds).stream()
91   - .collect(Collectors.toMap(MesCalTeamDO::getId, MesCalTeamDO::getName));
92   -
93   - // TODO @AI:使用 planShiftService 的 getPlanShiftMap 方法,批量查询并返回 Map<Long, MesCalPlanShiftDO>;不要 for 循环去查询;
94   - Set<Long> shiftIds = teamShifts.stream().map(MesCalTeamShiftDO::getShiftId).collect(Collectors.toSet());
95   - Map<Long, MesCalPlanShiftDO> shiftMap = new HashMap<>();
96   - if (CollUtil.isNotEmpty(shiftIds)) {
97   - for (Long shiftId : shiftIds) {
98   - MesCalPlanShiftDO shift = planShiftService.getPlanShift(shiftId);
99   - if (shift != null) {
100   - shiftMap.put(shiftId, shift);
101   - }
102   - }
103   - }
104   -
105   - // 查询 plan 用于获取 shiftType
106   - // TODO @AI:使用 planService 的 getPlanMap 方法,批量查询并返回 Map<Long, MesCalPlanDO>;不要 for 循环去查询;
107   - Set<Long> planIds = teamShifts.stream().map(MesCalTeamShiftDO::getPlanId)
108   - .filter(Objects::nonNull).collect(Collectors.toSet());
109   - Map<Long, MesCalPlanDO> planMap = new HashMap<>();
110   - if (CollUtil.isNotEmpty(planIds)) {
111   - planMap.putAll(planMapper.selectBatchIds(planIds).stream()
112   - .collect(Collectors.toMap(MesCalPlanDO::getId, p -> p)));
113   - }
114   -
115   - // 5. 按 day 分组聚合,过滤假期
116   - Map<String, List<MesCalTeamShiftDO>> dayGroupMap = teamShifts.stream()
117   - .collect(Collectors.groupingBy(
118   - ts -> ts.getDay().toLocalDate().format(DAY_FORMATTER),
119   - LinkedHashMap::new,
120   - Collectors.toList()
121   - ));
122   -
123   - List<MesCalCalendarRespVO> result = new ArrayList<>();
124   - for (Map.Entry<String, List<MesCalTeamShiftDO>> entry : dayGroupMap.entrySet()) {
125   - String dayStr = entry.getKey();
126   - // 过滤假期
127   - if (holidaySet.contains(dayStr)) {
128   - continue;
129   - }
130   - List<MesCalTeamShiftDO> dayShifts = entry.getValue();
131   - // 排序
132   - dayShifts.sort(Comparator.comparing(ts -> ts.getSort() != null ? ts.getSort() : 0));
133   -
134   - // 获取 shiftType(取第一条记录的 planId 对应的 plan)
135   - Integer shiftType = null;
136   - MesCalTeamShiftDO first = dayShifts.get(0);
137   - if (first.getPlanId() != null) {
138   - MesCalPlanDO plan = planMap.get(first.getPlanId());
139   - if (plan != null) {
140   - shiftType = plan.getShiftType();
141   - }
142   - }
143   -
144   - // TODO @AI:看看怎么进一步简化;
145   - List<MesCalCalendarRespVO.TeamShiftItem> items = dayShifts.stream()
146   - .map(ts -> {
147   - MesCalPlanShiftDO shift = shiftMap.get(ts.getShiftId());
148   - return MesCalCalendarRespVO.TeamShiftItem.builder()
149   - .teamId(ts.getTeamId())
150   - .teamName(teamNameMap.get(ts.getTeamId()))
151   - .shiftId(ts.getShiftId())
152   - .shiftName(shift != null ? shift.getName() : null)
153   - .sort(ts.getSort())
154   - .build();
155   - })
156   - .collect(Collectors.toList());
157   -
158   - result.add(MesCalCalendarRespVO.builder()
159   - .day(LocalDate.parse(dayStr, DAY_FORMATTER))
160   - .shiftType(shiftType)
161   - .teamShifts(items)
162   - .build());
163   - }
164   - return result;
165   - }
166   -
167   - /**
168   - * 按班组类型查询排班记录
169   - */
170   - private List<MesCalTeamShiftDO> getTeamShiftsByCalendarType(Integer calendarType,
171   - LocalDateTime startDay, LocalDateTime endDay) {
172   - if (calendarType == null) {
173   - return Collections.emptyList();
174   - }
175   - // 1. 查询指定类型的所有班组
176   - List<MesCalTeamDO> teams = teamMapper.selectList(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<MesCalTeamDO>()
177   - .eq(MesCalTeamDO::getCalendarType, calendarType));
178   - if (CollUtil.isEmpty(teams)) {
179   - return Collections.emptyList();
180   - }
181   - // 2. 查询这些班组在日期范围内的排班记录
182   - List<MesCalTeamShiftDO> result = new ArrayList<>();
183   - for (MesCalTeamDO team : teams) {
184   - MesCalTeamShiftListReqVO reqVO = new MesCalTeamShiftListReqVO();
185   - reqVO.setTeamId(team.getId());
186   - reqVO.setStartDay(startDay);
187   - reqVO.setEndDay(endDay);
188   - result.addAll(teamShiftService.getTeamShiftList(reqVO));
189   - }
190   - return result;
191   - }
192   -
193   - /**
194   - * 按班组编号查询排班记录
195   - */
196   - private List<MesCalTeamShiftDO> getTeamShiftsByTeamId(Long teamId,
197   - LocalDateTime startDay, LocalDateTime endDay) {
198   - if (teamId == null) {
199   - return Collections.emptyList();
200   - }
201   - MesCalTeamShiftListReqVO reqVO = new MesCalTeamShiftListReqVO();
202   - reqVO.setTeamId(teamId);
203   - reqVO.setStartDay(startDay);
204   - reqVO.setEndDay(endDay);
205   - return teamShiftService.getTeamShiftList(reqVO);
206   - }
207   -
208   - /**
209   - * 按用户编号查询排班记录(先查用户所属班组,再查班组排班)
210   - */
211   - private List<MesCalTeamShiftDO> getTeamShiftsByUserId(Long userId,
212   - LocalDateTime startDay, LocalDateTime endDay) {
213   - if (userId == null) {
214   - return Collections.emptyList();
215   - }
216   - // 1. 查询用户所属的班组
217   - List<MesCalTeamMemberDO> members = teamMemberMapper.selectList(
218   - new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<MesCalTeamMemberDO>()
219   - .eq(MesCalTeamMemberDO::getUserId, userId));
220   - if (CollUtil.isEmpty(members)) {
221   - return Collections.emptyList();
222   - }
223   - // 2. 查询这些班组在日期范围内的排班记录
224   - List<MesCalTeamShiftDO> result = new ArrayList<>();
225   - for (MesCalTeamMemberDO member : members) {
226   - MesCalTeamShiftListReqVO reqVO = new MesCalTeamShiftListReqVO();
227   - reqVO.setTeamId(member.getTeamId());
228   - reqVO.setStartDay(startDay);
229   - reqVO.setEndDay(endDay);
230   - result.addAll(teamShiftService.getTeamShiftList(reqVO));
231   - }
232   - return result;
233   - }
234   -
235   - /**
236   - * 构建假期日期集合
237   - */
238   - private Set<String> buildHolidaySet() {
239   - List<MesCalHolidayDO> holidays = holidayMapper.selectList();
240   - Set<String> holidaySet = new HashSet<>();
241   - for (MesCalHolidayDO holiday : holidays) {
242   - // type=2 表示节假日
243   - if (holiday.getType() != null && holiday.getType() == 2) {
244   - LocalDate day = holiday.getDay().toLocalDate();
245   - holidaySet.add(day.format(DAY_FORMATTER));
246   - }
247   - }
248   - return holidaySet;
249   - }
250   -
251   -}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanService.java
... ... @@ -6,6 +6,12 @@ import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanSaveRe
6 6 import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO;
7 7 import jakarta.validation.Valid;
8 8  
  9 +import java.util.Collection;
  10 +import java.util.List;
  11 +import java.util.Map;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  14 +
9 15 /**
10 16 * MES 排班计划 Service 接口
11 17 *
... ... @@ -59,6 +65,24 @@ public interface MesCalPlanService {
59 65 MesCalPlanDO getPlan(Long id);
60 66  
61 67 /**
  68 + * 获得排班计划列表
  69 + *
  70 + * @param ids 排班计划编号集合
  71 + * @return 排班计划列表
  72 + */
  73 + List<MesCalPlanDO> getPlanList(Collection<Long> ids);
  74 +
  75 + /**
  76 + * 获得排班计划 Map
  77 + *
  78 + * @param ids 排班计划编号集合
  79 + * @return 排班计划 Map,key 为编号
  80 + */
  81 + default Map<Long, MesCalPlanDO> getPlanMap(Collection<Long> ids) {
  82 + return convertMap(getPlanList(ids), MesCalPlanDO::getId);
  83 + }
  84 +
  85 + /**
62 86 * 获得排班计划分页
63 87 *
64 88 * @param pageReqVO 分页查询
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.cal.plan;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 6 import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanPageReqVO;
... ... @@ -16,6 +17,10 @@ import org.springframework.stereotype.Service;
16 17 import org.springframework.transaction.annotation.Transactional;
17 18 import org.springframework.validation.annotation.Validated;
18 19  
  20 +import java.util.Collection;
  21 +import java.util.Collections;
  22 +import java.util.List;
  23 +
19 24 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
20 25 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
21 26  
... ... @@ -91,8 +96,7 @@ public class MesCalPlanServiceImpl implements MesCalPlanService {
91 96 planMapper.updateById(updateObj);
92 97  
93 98 // 3. 生成班组排班记录
94   - // TODO @AI:方法名,不要缩写;
95   - teamShiftService.genRecords(id);
  99 + teamShiftService.generateTeamShiftRecords(id);
96 100 }
97 101  
98 102 @Override
... ... @@ -114,6 +118,14 @@ public class MesCalPlanServiceImpl implements MesCalPlanService {
114 118 }
115 119  
116 120 @Override
  121 + public List<MesCalPlanDO> getPlanList(Collection<Long> ids) {
  122 + if (CollUtil.isEmpty(ids)) {
  123 + return Collections.emptyList();
  124 + }
  125 + return planMapper.selectByIds(ids);
  126 + }
  127 +
  128 + @Override
117 129 public PageResult<MesCalPlanDO> getPlanPage(MesCalPlanPageReqVO pageReqVO) {
118 130 return planMapper.selectPage(pageReqVO);
119 131 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanShiftService.java
... ... @@ -6,7 +6,11 @@ import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.shift.MesCalPlan
6 6 import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO;
7 7 import jakarta.validation.Valid;
8 8  
  9 +import java.util.Collection;
9 10 import java.util.List;
  11 +import java.util.Map;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
10 14  
11 15 /**
12 16 * MES 计划班次 Service 接口
... ... @@ -78,6 +82,24 @@ public interface MesCalPlanShiftService {
78 82 void addDefaultPlanShift(Long planId, Integer shiftType);
79 83  
80 84 /**
  85 + * 获得计划班次列表
  86 + *
  87 + * @param ids 班次编号集合
  88 + * @return 班次列表
  89 + */
  90 + List<MesCalPlanShiftDO> getPlanShiftList(Collection<Long> ids);
  91 +
  92 + /**
  93 + * 获得计划班次 Map
  94 + *
  95 + * @param ids 班次编号集合
  96 + * @return 班次 Map,key 为编号
  97 + */
  98 + default Map<Long, MesCalPlanShiftDO> getPlanShiftMap(Collection<Long> ids) {
  99 + return convertMap(getPlanShiftList(ids), MesCalPlanShiftDO::getId);
  100 + }
  101 +
  102 + /**
81 103 * 根据排班计划编号删除所有班次
82 104 *
83 105 * @param planId 排班计划编号
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanShiftServiceImpl.java
... ... @@ -15,6 +15,10 @@ import org.springframework.context.annotation.Lazy;
15 15 import org.springframework.stereotype.Service;
16 16 import org.springframework.validation.annotation.Validated;
17 17  
  18 +import cn.hutool.core.collection.CollUtil;
  19 +
  20 +import java.util.Collection;
  21 +import java.util.Collections;
18 22 import java.util.List;
19 23  
20 24 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
... ... @@ -132,6 +136,14 @@ public class MesCalPlanShiftServiceImpl implements MesCalPlanShiftService {
132 136 }
133 137  
134 138 @Override
  139 + public List<MesCalPlanShiftDO> getPlanShiftList(Collection<Long> ids) {
  140 + if (CollUtil.isEmpty(ids)) {
  141 + return Collections.emptyList();
  142 + }
  143 + return planShiftMapper.selectByIds(ids);
  144 + }
  145 +
  146 + @Override
135 147 public void deletePlanShiftByPlanId(Long planId) {
136 148 planShiftMapper.deleteByPlanId(planId);
137 149 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamMemberService.java
... ... @@ -64,6 +64,14 @@ public interface MesCalTeamMemberService {
64 64 List<MesCalTeamMemberDO> getTeamMemberListByTeamIds(Collection<Long> teamIds);
65 65  
66 66 /**
  67 + * 根据用户编号获得班组成员
  68 + *
  69 + * @param userId 用户编号
  70 + * @return 班组成员,不存在则返回 null
  71 + */
  72 + MesCalTeamMemberDO getTeamMemberByUserId(Long userId);
  73 +
  74 + /**
67 75 * 根据班组编号删除所有成员
68 76 *
69 77 * @param teamId 班组编号
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamMemberServiceImpl.java
... ... @@ -74,6 +74,11 @@ public class MesCalTeamMemberServiceImpl implements MesCalTeamMemberService {
74 74 }
75 75  
76 76 @Override
  77 + public MesCalTeamMemberDO getTeamMemberByUserId(Long userId) {
  78 + return teamMemberMapper.selectByUserId(userId);
  79 + }
  80 +
  81 + @Override
77 82 public void deleteByTeamId(Long teamId) {
78 83 teamMemberMapper.deleteByTeamId(teamId);
79 84 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamService.java
... ... @@ -6,7 +6,11 @@ import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.MesCalTeamSaveRe
6 6 import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO;
7 7 import jakarta.validation.Valid;
8 8  
  9 +import java.util.Collection;
9 10 import java.util.List;
  11 +import java.util.Map;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
10 14  
11 15 /**
12 16 * MES 班组 Service 接口
... ... @@ -61,6 +65,24 @@ public interface MesCalTeamService {
61 65 List<MesCalTeamDO> getTeamList();
62 66  
63 67 /**
  68 + * 获得班组列表
  69 + *
  70 + * @param ids 班组编号集合
  71 + * @return 班组列表
  72 + */
  73 + List<MesCalTeamDO> getTeamList(Collection<Long> ids);
  74 +
  75 + /**
  76 + * 获得班组 Map
  77 + *
  78 + * @param ids 班组编号集合
  79 + * @return 班组 Map,key 为编号
  80 + */
  81 + default Map<Long, MesCalTeamDO> getTeamMap(Collection<Long> ids) {
  82 + return convertMap(getTeamList(ids), MesCalTeamDO::getId);
  83 + }
  84 +
  85 + /**
64 86 * 校验班组存在
65 87 *
66 88 * @param id 编号
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.cal.team;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjUtil;
3 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 7 import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.MesCalTeamPageReqVO;
... ... @@ -12,6 +14,8 @@ import org.springframework.stereotype.Service;
12 14 import org.springframework.transaction.annotation.Transactional;
13 15 import org.springframework.validation.annotation.Validated;
14 16  
  17 +import java.util.Collection;
  18 +import java.util.Collections;
15 19 import java.util.List;
16 20  
17 21 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
... ... @@ -83,6 +87,14 @@ public class MesCalTeamServiceImpl implements MesCalTeamService {
83 87 }
84 88  
85 89 @Override
  90 + public List<MesCalTeamDO> getTeamList(Collection<Long> ids) {
  91 + if (CollUtil.isEmpty(ids)) {
  92 + return Collections.emptyList();
  93 + }
  94 + return teamMapper.selectByIds(ids);
  95 + }
  96 +
  97 + @Override
86 98 public MesCalTeamDO validateTeamExists(Long id) {
87 99 MesCalTeamDO team = teamMapper.selectById(id);
88 100 if (team == null) {
... ... @@ -96,8 +108,7 @@ public class MesCalTeamServiceImpl implements MesCalTeamService {
96 108 if (team == null) {
97 109 return;
98 110 }
99   - // TODO @AI:ObjUtil notEquals
100   - if (id == null || !id.equals(team.getId())) {
  111 + if (ObjUtil.notEqual(id, team.getId())) {
101 112 throw exception(CAL_TEAM_CODE_DUPLICATE);
102 113 }
103 114 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftService.java
... ... @@ -12,13 +12,12 @@ import java.util.List;
12 12 */
13 13 public interface MesCalTeamShiftService {
14 14  
15   - // TODO @AI:方法名,优化下;
16 15 /**
17 16 * 根据排班计划生成班组排班记录
18 17 *
19 18 * @param planId 排班计划编号
20 19 */
21   - void genRecords(Long planId);
  20 + void generateTeamShiftRecords(Long planId);
22 21  
23 22 /**
24 23 * 获得班组排班列表
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java
... ... @@ -45,9 +45,10 @@ public class MesCalTeamShiftServiceImpl implements MesCalTeamShiftService {
45 45 @Lazy
46 46 private MesCalPlanTeamService planTeamService;
47 47  
  48 + // TODO @芋艿:这块逻辑,可能要想下;
48 49 @Async
49 50 @Override
50   - public void genRecords(Long planId) {
  51 + public void generateTeamShiftRecords(Long planId) {
51 52 // 1.1 查询排班计划
52 53 MesCalPlanDO plan = planService.getPlan(planId);
53 54 // 1.2 查询计划中的班次列表
... ...