diff --git a/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseScheduleSessionService.java b/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseScheduleSessionService.java index d34b6a4e..791e175e 100644 --- a/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseScheduleSessionService.java +++ b/web/src/main/java/com/ibeetl/jlw/service/TeacherOpenCourseScheduleSessionService.java @@ -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 CoreBaseServicequeryByCondition(PageQuery query){ @@ -354,7 +360,7 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService dateTimes = DateUtil.rangeToList(startTime, endTime, DateField.DAY_OF_YEAR); // 开课星期,排序。数据直观一些 List 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 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> sessionClassTagMap = tocss.getSessionClassList(); @@ -496,8 +520,17 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService sessionClassList = teacherOpenCourseScheduleSessionClassService.getValuesByQuery(query); + + // 这里不带status = 1,全量查询吧,查询上课的教室列表 + TeacherOpenCourseScheduleSessionClassQuery tocQuery = new TeacherOpenCourseScheduleSessionClassQuery(); + tocQuery.setOrgId(teacherOrgId); + final List sessionClassListByTOC = Collections + .unmodifiableList(CollectionUtil.emptyIfNull(teacherOpenCourseScheduleSessionClassService.getValuesByQuery(tocQuery))); + + // 一个Key对应多个Value的封装Map MultiValueMapAdapter multiValueMapAdapter = new MultiValueMapAdapter( sessionClassList.stream().collect(groupingBy(TeacherOpenCourseScheduleSessionClass::getTeacherOpenCourseScheduleSessionClassId))); @@ -512,7 +545,7 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService { + sessionTagConsumerHandler(tagList, (o, index, isSecondLast) -> { // 判断时间区间的交集 List containsList = rangeContains( new DateRange(o.getFirstStartTime(), o.getFirstEndTime(), HOUR_OF_DAY), @@ -527,10 +560,10 @@ public class TeacherOpenCourseScheduleSessionService extends CoreBaseService { + 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 { + 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 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 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 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 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 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 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 tagList, Consumer consumer) { + private void sessionTagConsumerHandler(List tagList, Consumer3 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