排课规则验证

beetlsql3-dev
Mlxa0324 2 years ago
parent 4b4be97375
commit 52c2bab232

@ -4,7 +4,9 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.*;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.func.Consumer3;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.jlw.util.ToolUtils;
import cn.jlw.validate.ValidateConfig;
@ -24,6 +26,7 @@ import com.ibeetl.jlw.dao.*;
import com.ibeetl.jlw.entity.*;
import com.ibeetl.jlw.web.query.TeacherOpenCourseScheduleSessionClassQuery;
import com.ibeetl.jlw.web.query.TeacherOpenCourseScheduleSessionQuery;
import com.ibeetl.jlw.web.query.TeacherOpenCourseScheduleSessionSnapQuery;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
@ -42,13 +45,14 @@ import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import static cn.hutool.core.collection.CollUtil.join;
import static cn.hutool.core.date.DateField.HOUR_OF_DAY;
import static cn.hutool.core.date.DateField.MINUTE;
import static cn.hutool.core.date.DatePattern.NORM_DATE_PATTERN;
import static cn.hutool.core.date.DateUtil.*;
import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
import static com.ibeetl.admin.core.util.BeanUtil.copyToListSupportExtMap;
import static com.ibeetl.admin.core.util.DateUtil.weekNumberInList;
import static com.ibeetl.admin.core.util.user.CacheUserUtil.getUser;
@ -78,6 +82,8 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService<Tea
TeacherOpenCourseScheduleSessionTagDao teacherOpenCourseScheduleSessionTagDao;
@Autowired
TeacherOpenCourseScheduleSessionClassService teacherOpenCourseScheduleSessionClassService;
@Autowired
TeacherService teacherService;
@Master
public PageQuery<TeacherOpenCourseScheduleSession>queryByCondition(PageQuery query){
@ -354,7 +360,7 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService<Tea
// 构建的入库实体
TeacherOpenCourseScheduleSession tocss = insertByOptionResult.getScheduleSession();
// 验证排课规则
validateScheduleOptions(options);
// validateScheduleOptions(options, dateTimes);
// 入库
teacherOpenCourseScheduleSessionDao.insert(tocss);
// 获取插入数据库后返回的主键ID
@ -442,12 +448,17 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService<Tea
DateTime startTime = parseDate(options.getStartTime());
// 结束时间向前偏移一天
DateTime endTime = offsetDay(DateUtil.offsetWeek(startTime, options.getWeekNum()), -1);
// 取开始和结束之间的区间
// 取开始和结束之间的区间,单位(天)
List<DateTime> dateTimes = DateUtil.rangeToList(startTime, endTime, DateField.DAY_OF_YEAR);
// 开课星期,排序。数据直观一些
List<Object> sortWeekDetail = options.getWeekDetail().stream().sorted().collect(Collectors.toList());
final Long teacherId = options.getTeacherId();
Teacher teacher = CollectionUtil.getFirst(teacherService.getByIds(teacherId.toString()));
final Long teacherOrgId = (teacher != null ? teacher.getOrgId() : null);
final Long teacherUserId = (teacher != null ? teacher.getUserId() : null);
// 课表主表保存
TeacherOpenCourseScheduleSession tocss = new TeacherOpenCourseScheduleSession();
tocss.setTeacherOpenCourseScheduleSessionAddTime(DateUtil.beginOfHour(DateUtil.date()));
@ -462,8 +473,8 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService<Tea
tocss.setTeacherOpenCourseScheduleSessionEndDate(endTime.toDateStr());
tocss.setTeacherOpenCourseScheduleSessionWeekNum(options.getWeekNum());
tocss.setTeacherOpenCourseScheduleSessionStatusWeekDetail(join(sortWeekDetail, ","));
tocss.setOrgId(options.getOrgId());
tocss.setUserId(options.getUserId());
tocss.setOrgId(defaultIfNull(teacherOrgId, options.getOrgId()));
tocss.setUserId(defaultIfNull(teacherUserId, options.getUserId()));
// 返回结果暂存
InsertByOptionResult insertByOptionResult = new InsertByOptionResult();
@ -487,7 +498,20 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService<Tea
* @Author: lx
* @Date: 2023/2/16 0:16
*/
public void validateScheduleOptions(@NotNull(message = "排课配置不能为空!") TeacherOpenCourseScheduleSessionOptions tocss) {
public void validateScheduleOptions(@NotNull(message = "排课配置不能为空!") TeacherOpenCourseScheduleSessionOptions tocss, List<DateTime> dateTimes) {
// 通过教师获取org_id过滤院校之间的数据用于加快查询速度
final Long teacherId = tocss.getTeacherId();
Teacher teacher = CollectionUtil.getFirst(teacherService.getByIds(teacherId.toString()));
final Long teacherOrgId = (teacher != null ? teacher.getOrgId() : null);
final Long teacherUserId = (teacher != null ? teacher.getUserId() : null);
// 开课ID
final Long teacherOpenCourseId = tocss.getTeacherOpenCourseId();
// 上午或者下午,每节课的时间间隔
final int intervalTimeMinutes = 30;
// 这里的TeacherOpenCourseScheduleSessionTag 是前端传递过来的对象,全量数据
Map<Long, List<TeacherOpenCourseScheduleSessionTag>> sessionClassTagMap = tocss.getSessionClassList();
@ -496,8 +520,17 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService<Tea
// 这里不带status = 1全量查询吧查询上课的教室列表
TeacherOpenCourseScheduleSessionClassQuery query = new TeacherOpenCourseScheduleSessionClassQuery();
query.setTeacherOpenCourseScheduleSessionClassIdPlural(join(sessionClassIds, ","));
query.setOrgId(teacherOrgId);
List<TeacherOpenCourseScheduleSessionClass> sessionClassList = teacherOpenCourseScheduleSessionClassService.getValuesByQuery(query);
// 这里不带status = 1全量查询吧查询上课的教室列表
TeacherOpenCourseScheduleSessionClassQuery tocQuery = new TeacherOpenCourseScheduleSessionClassQuery();
tocQuery.setOrgId(teacherOrgId);
final List<TeacherOpenCourseScheduleSessionClass> sessionClassListByTOC = Collections
.unmodifiableList(CollectionUtil.emptyIfNull(teacherOpenCourseScheduleSessionClassService.getValuesByQuery(tocQuery)));
// 一个Key对应多个Value的封装Map
MultiValueMapAdapter<Long, TeacherOpenCourseScheduleSessionClass> multiValueMapAdapter = new MultiValueMapAdapter(
sessionClassList.stream().collect(groupingBy(TeacherOpenCourseScheduleSessionClass::getTeacherOpenCourseScheduleSessionClassId)));
@ -512,7 +545,7 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService<Tea
parseTimeToday(o2.getTeacherOpenCourseScheduleSessionTagStartTime())));
// 判断时间是否有重叠部分
sessionTagConsumerHandler(tagList, (o) -> {
sessionTagConsumerHandler(tagList, (o, index, isSecondLast) -> {
// 判断时间区间的交集
List<DateTime> containsList = rangeContains(
new DateRange(o.getFirstStartTime(), o.getFirstEndTime(), HOUR_OF_DAY),
@ -527,10 +560,10 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService<Tea
return isIn(parseTimeToday("00:01"), parseTimeToday("13:00"), endDate);
}).collect(Collectors.toList());
sessionTagConsumerHandler(AMTagList, (o) -> {
sessionTagConsumerHandler(AMTagList, (o, index, isSecondLast) -> {
// 上午6点到12点之间的每节课之间间隔不允许超过30分钟来判断是否有断课
long betweenMinutes = o.getFirstEndTime().between(o.getSecondStartTime(), DateUnit.MINUTE);
Assert.isTrue(betweenMinutes < 30,
Assert.isTrue(betweenMinutes < intervalTimeMinutes,
"无法正常排课,课次名称:[{}],{}] 不是连续的课次上午每节课间隔不超过30分钟", o.getFirstTagName(), o.getSecondTagName());
});
@ -540,18 +573,116 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService<Tea
return isIn(parseTimeToday("13:01"), parseTimeToday("23:59"), endDate);
}).collect(Collectors.toList());
sessionTagConsumerHandler(PMTagList, (o) -> {
sessionTagConsumerHandler(PMTagList, (o, index, isSecondLast) -> {
// 上午6点到12点之间的每节课之间间隔不允许超过30分钟来判断是否有断课
long betweenMinutes = o.getFirstEndTime().between(o.getSecondStartTime(), DateUnit.MINUTE);
Assert.isTrue(betweenMinutes < 30,
Assert.isTrue(betweenMinutes < intervalTimeMinutes,
"无法正常排课,课次名称:[{}],{}] 不是连续的课次下午每节课间隔不超过30分钟", o.getFirstTagName(), o.getSecondTagName());
});
// 检查重复:重复提示:
// 同一个教室,同一个时段,不能安排两次课;
// TODO 排课重复检查
sessionTagConsumerHandler(tagList, (o, index, isSecondLast) -> {
// 快照表没存教室ID所以需要实时的查询教室的全名称
final String sessionClassFullName = defaultIfNull(
teacherOpenCourseScheduleSessionClassService.getSessionClassFullName(sessionClassId, sessionClassListByTOC), "");
// 查看已经安排了的课表,判断同一个教室同一个时间段,不能重复
TeacherOpenCourseScheduleSessionSnapQuery sessionSnapQuery = new TeacherOpenCourseScheduleSessionSnapQuery();
sessionSnapQuery.setTeacherOpenCourseId(teacherOpenCourseId);
sessionSnapQuery.setTeacherOpenCourseScheduleSessionSnapStatus(1);
sessionSnapQuery.setTeacherOpenCourseScheduleSessionClassName(sessionClassFullName);
//查询正常状态下的排课快照列表
List<TeacherOpenCourseScheduleSessionSnap> normalStatusSessionSnapList =
teacherOpenCourseScheduleSessionSnapDao.getValuesByQuery(sessionSnapQuery);
// 数据库中保存的时间区间
final DateRange dr = new DateRange(o.getSecondStartTime(), o.getFirstEndTime(), MINUTE);
// 题目快照构建出来的时间区间集合
normalStatusSessionSnapList.stream()
.filter(item -> StrUtil.isNotBlank(sessionClassFullName)
&& sessionClassFullName.equals(item.getTeacherOpenCourseScheduleSessionClassName()))
.forEach(item -> {
// yyyy-MM-dd HH:mm 时间格式
String startDateTime = item.getTeacherOpenCourseScheduleSessionDayTime() + " " + item.getTeacherOpenCourseScheduleSessionTagStartTime();
String endDateTime = item.getTeacherOpenCourseScheduleSessionDayTime() + " " + item.getTeacherOpenCourseScheduleSessionTagEndTime();
// 判断时间区间的交集
List<DateTime> containsList = rangeContains(new DateRange(parse(startDateTime), parse(endDateTime), MINUTE), dr);
Assert.notEmpty(
containsList, "无法正常排课,教室名称:{},课次名称:[{}],{}] 时间有重叠部分!",
sessionClassFullName, o.getFirstTagName(), o.getSecondTagName());
});
});
// 同一个老师,不能安排在不同课程的同一个时段上课;
sessionTagConsumerHandler(tagList, (o, index, isSecondLast) -> {
// 查看已经安排了的课表,判断同一个教室同一个时间段,不能重复
TeacherOpenCourseScheduleSessionSnapQuery sessionSnapQuery = new TeacherOpenCourseScheduleSessionSnapQuery();
sessionSnapQuery.setTeacherOpenCourseId(teacherOpenCourseId);
sessionSnapQuery.setTeacherOpenCourseScheduleSessionSnapStatus(1);
sessionSnapQuery.setUserId(teacherUserId);
//查询正常状态下的排课快照列表,教师的所有排课
List<TeacherOpenCourseScheduleSessionSnap> normalStatusSessionSnapList =
teacherOpenCourseScheduleSessionSnapDao.getValuesByQuery(sessionSnapQuery);
// 数据库中保存的时间区间
final DateRange dr = new DateRange(o.getSecondStartTime(), o.getFirstEndTime(), MINUTE);
// 题目快照构建出来的时间区间集合
normalStatusSessionSnapList.stream().forEach(item -> {
// yyyy-MM-dd HH:mm 时间格式
String startDateTime = item.getTeacherOpenCourseScheduleSessionDayTime() + " " + item.getTeacherOpenCourseScheduleSessionTagStartTime();
String endDateTime = item.getTeacherOpenCourseScheduleSessionDayTime() + " " + item.getTeacherOpenCourseScheduleSessionTagEndTime();
// 判断时间区间的交集
List<DateTime> containsList = rangeContains(new DateRange(parse(startDateTime), parse(endDateTime), MINUTE), dr);
Assert.notEmpty(containsList, "无法正常排课,教师名称:{},课次名称:[{}],{}] 时间有重叠部分!",
teacher.getTeacherName(), o.getFirstTagName(), o.getSecondTagName());
});
});
// 同一个班级,不能安排不同教室同一个时间上课
// TODO 排课重复检查
sessionTagConsumerHandler(tagList, (o, index, isSecondLast) -> {
// 查看已经安排了的课表,判断同一个教室同一个时间段,不能重复
TeacherOpenCourseScheduleSessionSnapQuery sessionSnapQuery = new TeacherOpenCourseScheduleSessionSnapQuery();
sessionSnapQuery.setTeacherOpenCourseId(teacherOpenCourseId);
sessionSnapQuery.setTeacherOpenCourseScheduleSessionSnapStatus(1);
sessionSnapQuery.setUserId(teacherUserId);
//查询正常状态下的排课快照列表,教师的所有排课
List<TeacherOpenCourseScheduleSessionSnap> normalStatusSessionSnapList =
teacherOpenCourseScheduleSessionSnapDao.getValuesByQuery(sessionSnapQuery);
// 数据库中保存的时间区间
final DateRange dr = new DateRange(o.getSecondStartTime(), o.getFirstEndTime(), MINUTE);
// 题目快照构建出来的时间区间集合
normalStatusSessionSnapList.stream().forEach(item -> {
// yyyy-MM-dd HH:mm 时间格式
String startDateTime = item.getTeacherOpenCourseScheduleSessionDayTime() + " " + item.getTeacherOpenCourseScheduleSessionTagStartTime();
String endDateTime = item.getTeacherOpenCourseScheduleSessionDayTime() + " " + item.getTeacherOpenCourseScheduleSessionTagEndTime();
// 判断时间区间的交集
List<DateTime> containsList = rangeContains(new DateRange(parse(startDateTime), parse(endDateTime), MINUTE), dr);
Assert.notEmpty(containsList, "无法正常排课,教师名称:{},课次名称:[{}],{}] 时间有重叠部分!",
teacher.getTeacherName(), o.getFirstTagName(), o.getSecondTagName());
});
});
});
}
@ -564,7 +695,12 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService<Tea
* @Author: lx
* @Date: 2023/2/16 1:42
*/
private void sessionTagConsumerHandler(List<TeacherOpenCourseScheduleSessionTag> tagList, Consumer<SessionTagTemp> consumer) {
private void sessionTagConsumerHandler(List<TeacherOpenCourseScheduleSessionTag> tagList, Consumer3<SessionTagTemp, Integer, Boolean> consumer) {
// 如果只查询到条数据的话,那么直接跳过,不进行验证
if (tagList == null || tagList.size() <= 1) {
return;
}
// 循环遍历,构建消费
for (int i = 0; i < tagList.size() - 1; i++) {
@ -588,7 +724,9 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService<Tea
.secondStartTime(secondStartTime)
.secondEndTime(secondEndTime)
.build();
consumer.accept(stt);
// 构建的实体,索引,当前索引是否是倒数第二个元素
consumer.accept(stt, i, i == tagList.size() - 2);
}
}

Loading…
Cancel
Save