Merge branch '0.8.X' of http://49.232.154.205:10100/DeXun/klp-oa into 0.8.X
This commit is contained in:
@@ -19,6 +19,7 @@ import com.klp.common.enums.BusinessType;
|
||||
import com.klp.common.utils.poi.ExcelUtil;
|
||||
import com.klp.domain.vo.WmsAttendanceScheduleVo;
|
||||
import com.klp.domain.bo.WmsAttendanceScheduleBo;
|
||||
import com.klp.domain.bo.GenerateScheduleBo;
|
||||
import com.klp.service.IWmsAttendanceScheduleService;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
|
||||
@@ -96,4 +97,14 @@ public class WmsAttendanceScheduleController extends BaseController {
|
||||
@PathVariable Long[] scheduleIds) {
|
||||
return toAjax(iWmsAttendanceScheduleService.deleteWithValidByIds(Arrays.asList(scheduleIds), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成排班
|
||||
*/
|
||||
@Log(title = "生成排班", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/generate")
|
||||
public R<Void> generateSchedule(@Validated @RequestBody GenerateScheduleBo bo) {
|
||||
iWmsAttendanceScheduleService.generateSchedule(bo);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,14 @@ public class WmsAttendanceShiftRule extends BaseEntity {
|
||||
* 班次B(通常夜班ID)
|
||||
*/
|
||||
private Long shiftB;
|
||||
/**
|
||||
* 倒班日(白班转夜班)使用的班次ID
|
||||
*/
|
||||
private Long changeShiftBId;
|
||||
/**
|
||||
* 倒班日(夜班转白班)使用的班次ID
|
||||
*/
|
||||
private Long changeShiftAId;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.klp.domain.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import javax.validation.constraints.*;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 生成排班请求对象
|
||||
*
|
||||
* @author klp
|
||||
* @date 2026-05-09
|
||||
*/
|
||||
@Data
|
||||
public class GenerateScheduleBo {
|
||||
|
||||
/**
|
||||
* 员工ID
|
||||
*/
|
||||
@NotNull(message = "员工ID不能为空")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 班次ID
|
||||
*/
|
||||
@NotNull(message = "班次ID不能为空")
|
||||
private Long shiftId;
|
||||
|
||||
/**
|
||||
* 倒班规则ID(可为空,为空则不倒班)
|
||||
*/
|
||||
private Long ruleId;
|
||||
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
@NotNull(message = "开始时间不能为空")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date startDate;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
@NotNull(message = "结束时间不能为空")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date endDate;
|
||||
|
||||
}
|
||||
@@ -47,6 +47,16 @@ public class WmsAttendanceShiftRuleBo extends BaseEntity {
|
||||
*/
|
||||
private Long shiftB;
|
||||
|
||||
/**
|
||||
* 倒班日(白班转夜班)使用的班次ID
|
||||
*/
|
||||
private Long changeShiftBId;
|
||||
|
||||
/**
|
||||
* 倒班日(夜班转白班)使用的班次ID
|
||||
*/
|
||||
private Long changeShiftAId;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
|
||||
@@ -60,6 +60,18 @@ public class WmsAttendanceShiftRuleVo {
|
||||
@ExcelDictFormat(readConverterExp = "通=常夜班ID")
|
||||
private Long shiftB;
|
||||
|
||||
/**
|
||||
* 倒班日(白班转夜班)使用的班次ID
|
||||
*/
|
||||
@ExcelProperty(value = "倒班日白转夜班次ID")
|
||||
private Long changeShiftBId;
|
||||
|
||||
/**
|
||||
* 倒班日(夜班转白班)使用的班次ID
|
||||
*/
|
||||
@ExcelProperty(value = "倒班日夜转白班次ID")
|
||||
private Long changeShiftAId;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.klp.service;
|
||||
import com.klp.domain.WmsAttendanceSchedule;
|
||||
import com.klp.domain.vo.WmsAttendanceScheduleVo;
|
||||
import com.klp.domain.bo.WmsAttendanceScheduleBo;
|
||||
import com.klp.domain.bo.GenerateScheduleBo;
|
||||
import com.klp.common.core.page.TableDataInfo;
|
||||
import com.klp.common.core.domain.PageQuery;
|
||||
|
||||
@@ -46,4 +47,9 @@ public interface IWmsAttendanceScheduleService {
|
||||
* 校验并批量删除排班(谁在哪天上班)信息
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 生成排班
|
||||
*/
|
||||
void generateSchedule(GenerateScheduleBo bo);
|
||||
}
|
||||
|
||||
@@ -7,17 +7,30 @@ 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.Map;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 排班(谁在哪天上班)Service业务层处理
|
||||
@@ -30,6 +43,8 @@ import java.util.Collection;
|
||||
public class WmsAttendanceScheduleServiceImpl implements IWmsAttendanceScheduleService {
|
||||
|
||||
private final WmsAttendanceScheduleMapper baseMapper;
|
||||
private final IWmsAttendanceShiftRuleService shiftRuleService;
|
||||
private final IWmsAttendanceShiftService shiftService;
|
||||
|
||||
/**
|
||||
* 查询排班(谁在哪天上班)
|
||||
@@ -110,4 +125,180 @@ public class WmsAttendanceScheduleServiceImpl implements IWmsAttendanceScheduleS
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,8 @@ public class WmsAttendanceShiftRuleServiceImpl implements IWmsAttendanceShiftRul
|
||||
lqw.eq(bo.getCycleDays() != null, WmsAttendanceShiftRule::getCycleDays, bo.getCycleDays());
|
||||
lqw.eq(bo.getShiftA() != null, WmsAttendanceShiftRule::getShiftA, bo.getShiftA());
|
||||
lqw.eq(bo.getShiftB() != null, WmsAttendanceShiftRule::getShiftB, bo.getShiftB());
|
||||
lqw.eq(bo.getChangeShiftBId() != null, WmsAttendanceShiftRule::getChangeShiftBId, bo.getChangeShiftBId());
|
||||
lqw.eq(bo.getChangeShiftAId() != null, WmsAttendanceShiftRule::getChangeShiftAId, bo.getChangeShiftAId());
|
||||
return lqw;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
<result property="cycleDays" column="cycle_days"/>
|
||||
<result property="shiftA" column="shift_a"/>
|
||||
<result property="shiftB" column="shift_b"/>
|
||||
<result property="changeShiftBId" column="change_shift_b_id"/>
|
||||
<result property="changeShiftAId" column="change_shift_a_id"/>
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="delFlag" column="del_flag"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
|
||||
Reference in New Issue
Block a user