Files
klp-oa/klp-wms/src/main/java/com/klp/service/impl/WmsAttendanceScheduleServiceImpl.java
Joshi cd3cfd6198 feat(wms): 添加排班管理的查询功能
- 在 WmsAttendanceScheduleMapper 中新增关联查询和批量插入方法
- 实现员工和班次信息的关联查询功能
- 添加分页查询排班列表的详细信息展示
- 扩展 WmsAttendanceScheduleVo 数据传输对象
- 完善排班详情查询和列表查询的服务层逻辑
- 集成员工姓名、部门、岗位及班次时间等详细信息
- 优化批量插入排班数据的功能实现
2026-05-09 14:08:38 +08:00

316 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}