- 在 WmsAttendanceScheduleMapper 中新增关联查询和批量插入方法 - 实现员工和班次信息的关联查询功能 - 添加分页查询排班列表的详细信息展示 - 扩展 WmsAttendanceScheduleVo 数据传输对象 - 完善排班详情查询和列表查询的服务层逻辑 - 集成员工姓名、部门、岗位及班次时间等详细信息 - 优化批量插入排班数据的功能实现
316 lines
12 KiB
Java
316 lines
12 KiB
Java
package com.klp.service.impl;
|
||
|
||
import cn.hutool.core.bean.BeanUtil;
|
||
import com.klp.common.core.page.TableDataInfo;
|
||
import com.klp.common.core.domain.PageQuery;
|
||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||
import com.klp.common.utils.StringUtils;
|
||
import com.klp.domain.vo.WmsAttendanceShiftRuleVo;
|
||
import com.klp.domain.vo.WmsAttendanceShiftVo;
|
||
import lombok.RequiredArgsConstructor;
|
||
import org.springframework.stereotype.Service;
|
||
import org.springframework.transaction.annotation.Transactional;
|
||
import com.klp.domain.bo.WmsAttendanceScheduleBo;
|
||
import com.klp.domain.bo.GenerateScheduleBo;
|
||
import com.klp.domain.vo.WmsAttendanceScheduleVo;
|
||
import com.klp.domain.WmsAttendanceSchedule;
|
||
import com.klp.domain.WmsAttendanceShiftRule;
|
||
import com.klp.domain.WmsAttendanceShift;
|
||
import com.klp.mapper.WmsAttendanceScheduleMapper;
|
||
import com.klp.service.IWmsAttendanceScheduleService;
|
||
import com.klp.service.IWmsAttendanceShiftRuleService;
|
||
import com.klp.service.IWmsAttendanceShiftService;
|
||
|
||
import java.time.LocalDate;
|
||
import java.time.temporal.ChronoUnit;
|
||
import java.util.ArrayList;
|
||
import java.util.Date;
|
||
import java.util.List;
|
||
|
||
import java.util.Collection;
|
||
import java.util.Map;
|
||
|
||
/**
|
||
* 排班(谁在哪天上班)Service业务层处理
|
||
*
|
||
* @author klp
|
||
* @date 2026-05-08
|
||
*/
|
||
@RequiredArgsConstructor
|
||
@Service
|
||
public class WmsAttendanceScheduleServiceImpl implements IWmsAttendanceScheduleService {
|
||
|
||
private final WmsAttendanceScheduleMapper baseMapper;
|
||
private final IWmsAttendanceShiftRuleService shiftRuleService;
|
||
private final IWmsAttendanceShiftService shiftService;
|
||
|
||
/**
|
||
* 查询排班(谁在哪天上班)
|
||
*/
|
||
@Override
|
||
public WmsAttendanceScheduleVo queryById(Long scheduleId){
|
||
WmsAttendanceSchedule schedule = baseMapper.selectById(scheduleId);
|
||
if (schedule == null) {
|
||
return null;
|
||
}
|
||
|
||
// 使用关联查询获取详细信息
|
||
List<WmsAttendanceScheduleVo> list = baseMapper.selectScheduleWithDetails(
|
||
schedule.getUserId(), schedule.getWorkDate(), schedule.getShiftId());
|
||
|
||
return list.isEmpty() ? null : list.get(0);
|
||
}
|
||
|
||
/**
|
||
* 查询排班(谁在哪天上班)列表
|
||
*/
|
||
@Override
|
||
public TableDataInfo<WmsAttendanceScheduleVo> queryPageList(WmsAttendanceScheduleBo bo, PageQuery pageQuery) {
|
||
Page<WmsAttendanceScheduleVo> page = pageQuery.<WmsAttendanceScheduleVo>build();
|
||
List<WmsAttendanceScheduleVo> list = baseMapper.selectScheduleWithDetailsPage(
|
||
bo.getUserId(), bo.getWorkDate(), bo.getShiftId(), bo.getShiftName(), bo.getShiftGroup());
|
||
|
||
// 手动分页处理
|
||
int total = list.size();
|
||
int startNum = (int) ((page.getCurrent() - 1) * page.getSize());
|
||
int endNum = Math.min(startNum + (int) page.getSize(), total);
|
||
|
||
List<WmsAttendanceScheduleVo> pageList = new ArrayList<>();
|
||
if (startNum < total) {
|
||
pageList = list.subList(startNum, endNum);
|
||
}
|
||
|
||
Page<WmsAttendanceScheduleVo> result = new Page<>(page.getCurrent(), page.getSize(), total);
|
||
result.setRecords(pageList);
|
||
return TableDataInfo.build(result);
|
||
}
|
||
|
||
/**
|
||
* 查询排班(谁在哪天上班)列表
|
||
*/
|
||
@Override
|
||
public List<WmsAttendanceScheduleVo> queryList(WmsAttendanceScheduleBo bo) {
|
||
return baseMapper.selectScheduleWithDetails(bo.getUserId(), bo.getWorkDate(), bo.getShiftId());
|
||
}
|
||
|
||
/**
|
||
* 新增排班(谁在哪天上班)
|
||
*/
|
||
@Override
|
||
public Boolean insertByBo(WmsAttendanceScheduleBo bo) {
|
||
WmsAttendanceSchedule add = BeanUtil.toBean(bo, WmsAttendanceSchedule.class);
|
||
validEntityBeforeSave(add);
|
||
boolean flag = baseMapper.insert(add) > 0;
|
||
if (flag) {
|
||
bo.setScheduleId(add.getScheduleId());
|
||
}
|
||
return flag;
|
||
}
|
||
|
||
/**
|
||
* 修改排班(谁在哪天上班)
|
||
*/
|
||
@Override
|
||
public Boolean updateByBo(WmsAttendanceScheduleBo bo) {
|
||
WmsAttendanceSchedule update = BeanUtil.toBean(bo, WmsAttendanceSchedule.class);
|
||
validEntityBeforeSave(update);
|
||
return baseMapper.updateById(update) > 0;
|
||
}
|
||
|
||
/**
|
||
* 保存前的数据校验
|
||
*/
|
||
private void validEntityBeforeSave(WmsAttendanceSchedule entity){
|
||
//TODO 做一些数据校验,如唯一约束
|
||
}
|
||
|
||
/**
|
||
* 批量删除排班(谁在哪天上班)
|
||
*/
|
||
@Override
|
||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||
if(isValid){
|
||
//TODO 做一些业务上的校验,判断是否需要校验
|
||
}
|
||
return baseMapper.deleteBatchIds(ids) > 0;
|
||
}
|
||
|
||
/**
|
||
* 生成排班
|
||
*/
|
||
@Override
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public void generateSchedule(GenerateScheduleBo bo) {
|
||
LocalDate startDate = bo.getStartDate().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate();
|
||
LocalDate endDate = bo.getEndDate().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate();
|
||
|
||
if (startDate.isAfter(endDate)) {
|
||
throw new RuntimeException("开始时间不能大于结束时间");
|
||
}
|
||
|
||
if (bo.getRuleId() == null) {
|
||
// 正常排班,不倒班
|
||
generateNormalSchedule(bo, startDate, endDate);
|
||
} else {
|
||
// 倒班排班
|
||
generateShiftSchedule(bo, startDate, endDate);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 生成正常排班
|
||
*/
|
||
private void generateNormalSchedule(GenerateScheduleBo bo, LocalDate startDate, LocalDate endDate) {
|
||
List<WmsAttendanceSchedule> schedules = new ArrayList<>();
|
||
|
||
// 获取班次信息
|
||
WmsAttendanceShiftVo shift = shiftService.queryById(bo.getShiftId());
|
||
if (shift == null) {
|
||
throw new RuntimeException("班次不存在");
|
||
}
|
||
|
||
LocalDate currentDate = startDate;
|
||
while (!currentDate.isAfter(endDate)) {
|
||
// 检查是否已存在排班
|
||
if (!isScheduleExists(bo.getUserId(), currentDate)) {
|
||
WmsAttendanceSchedule schedule = new WmsAttendanceSchedule();
|
||
schedule.setUserId(bo.getUserId());
|
||
schedule.setWorkDate(java.sql.Date.valueOf(currentDate));
|
||
schedule.setShiftId(bo.getShiftId());
|
||
schedule.setShiftName(shift.getShiftName());
|
||
schedules.add(schedule);
|
||
}
|
||
currentDate = currentDate.plusDays(1);
|
||
}
|
||
|
||
// 批量插入
|
||
if (!schedules.isEmpty()) {
|
||
boolean ok = baseMapper.insertBatch(schedules);
|
||
if (!ok) {
|
||
throw new RuntimeException("排班插入失败");
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 生成倒班排班
|
||
*/
|
||
private void generateShiftSchedule(GenerateScheduleBo bo, LocalDate startDate, LocalDate endDate) {
|
||
// 获取倒班规则
|
||
WmsAttendanceShiftRuleVo rule = shiftRuleService.queryById(bo.getRuleId());
|
||
if (rule == null) {
|
||
throw new RuntimeException("倒班规则不存在");
|
||
}
|
||
|
||
// 验证班次匹配
|
||
if (!bo.getShiftId().equals(rule.getShiftA()) && !bo.getShiftId().equals(rule.getShiftB())) {
|
||
throw new RuntimeException("班次ID与倒班规则不匹配");
|
||
}
|
||
|
||
// 获取班次信息
|
||
WmsAttendanceShiftVo shiftA = shiftService.queryById(rule.getShiftA());
|
||
WmsAttendanceShiftVo shiftB = shiftService.queryById(rule.getShiftB());
|
||
WmsAttendanceShiftVo changeShiftB = rule.getChangeShiftBId() != null ?
|
||
shiftService.queryById(rule.getChangeShiftBId()) : null;
|
||
WmsAttendanceShiftVo changeShiftA = rule.getChangeShiftAId() != null ?
|
||
shiftService.queryById(rule.getChangeShiftAId()) : null;
|
||
|
||
if (shiftA == null || shiftB == null) {
|
||
throw new RuntimeException("倒班规则中的班次不存在");
|
||
}
|
||
|
||
List<WmsAttendanceSchedule> schedules = new ArrayList<>();
|
||
LocalDate currentDate = startDate;
|
||
long daysFromStart = 0;
|
||
|
||
// 确定初始班次
|
||
boolean isCurrentShiftA = bo.getShiftId().equals(rule.getShiftA());
|
||
|
||
while (!currentDate.isAfter(endDate)) {
|
||
if (!isScheduleExists(bo.getUserId(), currentDate)) {
|
||
WmsAttendanceSchedule schedule = new WmsAttendanceSchedule();
|
||
schedule.setUserId(bo.getUserId());
|
||
schedule.setWorkDate(java.sql.Date.valueOf(currentDate));
|
||
|
||
// 判断是否为倒班日
|
||
long cycleDays = rule.getCycleDays() != null ? rule.getCycleDays() : 10;
|
||
boolean isChangeDay = (daysFromStart + 1) % cycleDays == 0;
|
||
|
||
if (isChangeDay) {
|
||
// 倒班日
|
||
if (isCurrentShiftA) {
|
||
// 白班转夜班
|
||
if (changeShiftB != null) {
|
||
schedule.setShiftId(rule.getChangeShiftBId());
|
||
schedule.setShiftName(changeShiftB.getShiftName());
|
||
} else {
|
||
schedule.setShiftId(rule.getShiftB());
|
||
schedule.setShiftName(shiftB.getShiftName());
|
||
}
|
||
// 下一天也使用倒班班次(工作18小时)
|
||
LocalDate nextDay = currentDate.plusDays(1);
|
||
if (!nextDay.isAfter(endDate) && !isScheduleExists(bo.getUserId(), nextDay)) {
|
||
WmsAttendanceSchedule nextSchedule = new WmsAttendanceSchedule();
|
||
nextSchedule.setUserId(bo.getUserId());
|
||
nextSchedule.setWorkDate(java.sql.Date.valueOf(nextDay));
|
||
if (changeShiftB != null) {
|
||
nextSchedule.setShiftId(rule.getChangeShiftBId());
|
||
nextSchedule.setShiftName(changeShiftB.getShiftName());
|
||
} else {
|
||
nextSchedule.setShiftId(rule.getShiftB());
|
||
nextSchedule.setShiftName(shiftB.getShiftName());
|
||
}
|
||
schedules.add(nextSchedule);
|
||
}
|
||
isCurrentShiftA = false;
|
||
currentDate = currentDate.plusDays(1); // 跳过下一天,因为已经处理了
|
||
daysFromStart++;
|
||
} else {
|
||
// 夜班转白班
|
||
if (changeShiftA != null) {
|
||
schedule.setShiftId(rule.getChangeShiftAId());
|
||
schedule.setShiftName(changeShiftA.getShiftName());
|
||
} else {
|
||
schedule.setShiftId(rule.getShiftA());
|
||
schedule.setShiftName(shiftA.getShiftName());
|
||
}
|
||
isCurrentShiftA = true;
|
||
}
|
||
} else {
|
||
// 普通日
|
||
if (isCurrentShiftA) {
|
||
schedule.setShiftId(rule.getShiftA());
|
||
schedule.setShiftName(shiftA.getShiftName());
|
||
} else {
|
||
schedule.setShiftId(rule.getShiftB());
|
||
schedule.setShiftName(shiftB.getShiftName());
|
||
}
|
||
}
|
||
|
||
schedules.add(schedule);
|
||
}
|
||
currentDate = currentDate.plusDays(1);
|
||
daysFromStart++;
|
||
}
|
||
|
||
// 批量插入
|
||
if (!schedules.isEmpty()) {
|
||
for (WmsAttendanceSchedule schedule : schedules) {
|
||
baseMapper.insert(schedule);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 检查排班是否已存在
|
||
*/
|
||
private boolean isScheduleExists(Long userId, LocalDate workDate) {
|
||
LambdaQueryWrapper<WmsAttendanceSchedule> wrapper = Wrappers.lambdaQuery();
|
||
wrapper.eq(WmsAttendanceSchedule::getUserId, userId)
|
||
.eq(WmsAttendanceSchedule::getWorkDate, java.sql.Date.valueOf(workDate));
|
||
return baseMapper.selectCount(wrapper) > 0;
|
||
}
|
||
}
|