|
@@ -0,0 +1,373 @@
|
|
|
+package com.qmth.exam.reserve.service.impl;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.qmth.boot.core.exception.StatusException;
|
|
|
+import com.qmth.exam.reserve.bean.applytask.CurrentApplyTaskVO;
|
|
|
+import com.qmth.exam.reserve.bean.examsite.ExamSiteCacheBean;
|
|
|
+import com.qmth.exam.reserve.bean.login.LoginUser;
|
|
|
+import com.qmth.exam.reserve.bean.org.OrgInfo;
|
|
|
+import com.qmth.exam.reserve.bean.timeperiod.TimePeriodExamSiteBean;
|
|
|
+import com.qmth.exam.reserve.bean.timeperiod.TimePeriodExamSiteInfo;
|
|
|
+import com.qmth.exam.reserve.bean.timeperiod.TimePeriodExamSiteReq;
|
|
|
+import com.qmth.exam.reserve.bean.timeperiod.TimePeriodExamSiteVo;
|
|
|
+import com.qmth.exam.reserve.cache.impl.ApplyTaskCacheService;
|
|
|
+import com.qmth.exam.reserve.cache.impl.ExamSiteCacheService;
|
|
|
+import com.qmth.exam.reserve.cache.impl.OrgCacheService;
|
|
|
+import com.qmth.exam.reserve.dao.TimePeriodExamRoomDao;
|
|
|
+import com.qmth.exam.reserve.entity.ExamRoomEntity;
|
|
|
+import com.qmth.exam.reserve.entity.TimePeriodEntity;
|
|
|
+import com.qmth.exam.reserve.entity.TimePeriodExamRoomEntity;
|
|
|
+import com.qmth.exam.reserve.enums.Role;
|
|
|
+import com.qmth.exam.reserve.service.ExamRoomService;
|
|
|
+import com.qmth.exam.reserve.service.TimePeriodExamRoomService;
|
|
|
+import com.qmth.exam.reserve.service.TimePeriodService;
|
|
|
+import com.qmth.exam.reserve.util.DateUtil;
|
|
|
+import com.qmth.exam.reserve.util.UnionUtil;
|
|
|
+import org.apache.commons.collections4.CollectionUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Isolation;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class TimePeriodExamRoomServiceImpl extends ServiceImpl<TimePeriodExamRoomDao, TimePeriodExamRoomEntity> implements TimePeriodExamRoomService {
|
|
|
+
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(TimePeriodExamRoomServiceImpl.class);
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ApplyTaskCacheService applyTaskCacheService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private OrgCacheService orgCacheService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TimePeriodService timePeriodService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ExamSiteCacheService examSiteCacheService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ExamRoomService examRoomService;
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<TimePeriodExamSiteVo> ListDetail(LoginUser loginUser, Long examRoomId) {
|
|
|
+ //获取当前机构
|
|
|
+ OrgInfo org = orgCacheService.currentOrg();
|
|
|
+ if (org == null) {
|
|
|
+ log.warn("[考场排班设置列表]未找到当前机构");
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+
|
|
|
+ //判断考场是否存在
|
|
|
+ ExamRoomEntity examRoom = examRoomService.getById(examRoomId);
|
|
|
+ if (examRoom == null) {
|
|
|
+ log.warn("[考场排班设置列表]未找到考场:{}", examRoomId);
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+
|
|
|
+ //教学点管理员权限限制
|
|
|
+ ExamSiteCacheBean examSite = examSiteCacheService.getExamSiteById(examRoom.getExamSiteId());
|
|
|
+ if (examSite == null) {
|
|
|
+ log.warn("[考场排班设置列表]考场:{}未找到所属考点", examRoomId);
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ if (loginUser.getRole().equals(Role.TEACHING) && !loginUser.getCategoryId().equals(examSite.getCategoryId())) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取当前任务
|
|
|
+ CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(org.getOrgId());
|
|
|
+ if (curApplyTask == null) {
|
|
|
+ log.warn("[考场排班设置列表]机构:{},当前未有启用的任务", org.getOrgId());
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 所有的预约日期
|
|
|
+ List<String> dateList = timePeriodService.listTimePeriodDate(curApplyTask.getTaskId());
|
|
|
+ if (CollectionUtils.isEmpty(dateList)) {
|
|
|
+ log.warn("[考场排班设置列表]当前任务:{}未设置预约日期", curApplyTask.getTaskId());
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+
|
|
|
+ //教学点管理员设置的所有的考点时段
|
|
|
+ List<TimePeriodExamSiteBean> timePeriodExamRoomList = timePeriodService.listTimePeriodByExamRoomId(curApplyTask.getTaskId(), examRoomId);
|
|
|
+ //学校管理员设置的所有预约时段
|
|
|
+ List<TimePeriodExamSiteBean> timePeriodList = timePeriodService.listTimePeriodByTask(curApplyTask.getTaskId());
|
|
|
+ List<TimePeriodExamSiteBean> resultList;
|
|
|
+ if (CollectionUtils.isEmpty(timePeriodExamRoomList)) {
|
|
|
+ resultList = timePeriodList;
|
|
|
+ } else {
|
|
|
+ //取并集
|
|
|
+ resultList = UnionUtil.unionByAttribute(timePeriodExamRoomList, timePeriodList, TimePeriodExamSiteBean::getTimePeriodId);
|
|
|
+ }
|
|
|
+
|
|
|
+ //按日期封装
|
|
|
+ List<TimePeriodExamSiteVo> list = new ArrayList<>();
|
|
|
+ for (String date : dateList) {
|
|
|
+ TimePeriodExamSiteVo timePeriodVo = new TimePeriodExamSiteVo();
|
|
|
+ timePeriodVo.setDateStr(getDateStr(date));
|
|
|
+ timePeriodVo.setTimePeriodList(filterTimePeriod(date, resultList, curApplyTask.getAllowApplyCancelDays()));
|
|
|
+ list.add(timePeriodVo);
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getDateStr(String date) {
|
|
|
+ if (StringUtils.isEmpty(date)) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ String[] dateArr = date.split("-");
|
|
|
+ if (dateArr.length != 3) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ return dateArr[1] + "月" + dateArr[2] + "日";
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private List<TimePeriodExamSiteInfo> filterTimePeriod(String date, List<TimePeriodExamSiteBean> timePeriodList, Integer canCancelDay) {
|
|
|
+ // 参数校验
|
|
|
+ if (timePeriodList == null || date == null || canCancelDay == null || canCancelDay < 0) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ List<TimePeriodExamSiteInfo> resultList = new ArrayList<>();
|
|
|
+
|
|
|
+ // 过滤符合条件的时间段
|
|
|
+ List<TimePeriodExamSiteBean> filteredTimePeriodList = timePeriodList.stream()
|
|
|
+ .filter(item -> DateUtil.getShortDateByLongTime(item.getStartTime()).equals(date))
|
|
|
+ .sorted(Comparator.comparing(TimePeriodExamSiteBean::getStartTime))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 计算可取消时间范围
|
|
|
+ Long longToday = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(new Date()) + " 00:00:00");
|
|
|
+ Date today = new Date(longToday);
|
|
|
+ Date otherDay = DateUtil.addValues(today, Calendar.DAY_OF_MONTH, canCancelDay);
|
|
|
+ long longOtherDay = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(otherDay) + " 23:59:59");
|
|
|
+
|
|
|
+ // 当前时间
|
|
|
+ long now = System.currentTimeMillis();
|
|
|
+
|
|
|
+ for (TimePeriodExamSiteBean time : filteredTimePeriodList) {
|
|
|
+ // 检查时间是否有效
|
|
|
+ if (time.getStartTime() == null || time.getEndTime() == null) {
|
|
|
+ continue; // 跳过无效时间段
|
|
|
+ }
|
|
|
+
|
|
|
+ TimePeriodExamSiteInfo bean = new TimePeriodExamSiteInfo();
|
|
|
+ bean.setId(time.getId());
|
|
|
+ bean.setTimePeriodId(time.getTimePeriodId());
|
|
|
+ bean.setEnable(time.getEnable());
|
|
|
+ bean.setTimePeriodStr(DateUtil.getStartToEndTime(time.getStartTime(), time.getEndTime()));
|
|
|
+
|
|
|
+ // 判断是否可编辑
|
|
|
+ boolean isEditable = isTimeEditable(now, time.getEndTime(), longOtherDay, time.getStartTime());
|
|
|
+ bean.setEditable(isEditable);
|
|
|
+
|
|
|
+ resultList.add(bean);
|
|
|
+ }
|
|
|
+
|
|
|
+ return resultList;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isTimeEditable(long now, long endTime, long longOtherDay, long startTime) {
|
|
|
+ return !(endTime < now || startTime < longOtherDay);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional(isolation = Isolation.READ_COMMITTED)
|
|
|
+ @Override
|
|
|
+ public void save(Long userId, Long examRoomId, List<TimePeriodExamSiteReq> timePeriodExamRoomList) {
|
|
|
+ if (CollectionUtils.isEmpty(timePeriodExamRoomList)) {
|
|
|
+ log.warn("[考场排班设置]时间段列表为空");
|
|
|
+ throw new StatusException("保存失败,时间段列表为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 获取当前机构
|
|
|
+ OrgInfo org = orgCacheService.currentOrg();
|
|
|
+ if (org == null) {
|
|
|
+ log.warn("[考场排班设置]未找到当前机构");
|
|
|
+ throw new StatusException("保存失败,未找到当前机构");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取当前任务
|
|
|
+ CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(org.getOrgId());
|
|
|
+ if (curApplyTask == null) {
|
|
|
+ log.warn("[考场排班设置]机构:{},当前未有启用的任务", org.getOrgId());
|
|
|
+ throw new StatusException("保存失败,未有启用的任务");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验考场信息
|
|
|
+ ExamRoomEntity examRoom = examRoomService.getById(examRoomId);
|
|
|
+ if (examRoom == null) {
|
|
|
+ log.warn("[考场排班设置]未找到考场:{}", examRoomId);
|
|
|
+ throw new StatusException("保存失败,未找到考场");
|
|
|
+ }
|
|
|
+ if (!examRoom.getEnable()) {
|
|
|
+ log.warn("[考场排班设置]考场已被禁用:{}", examRoomId);
|
|
|
+ throw new StatusException("保存失败,考场已被禁用");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验考点信息
|
|
|
+ ExamSiteCacheBean examSiteCacheBean = examSiteCacheService.getExamSiteById(examRoom.getExamSiteId());
|
|
|
+ if (examSiteCacheBean == null) {
|
|
|
+ log.warn("[考场排班设置]未找到考点:{}", examRoom.getExamSiteId());
|
|
|
+ throw new StatusException("保存失败,未找到考点");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取考场对应的所有时段
|
|
|
+ List<TimePeriodExamSiteBean> timePeriodList = timePeriodService.listTimePeriodByExamRoomId(curApplyTask.getTaskId(), examRoomId);
|
|
|
+
|
|
|
+ // 时段Map
|
|
|
+ Map<Long, TimePeriodExamSiteBean> timePeriodMap = timePeriodList.stream()
|
|
|
+ .collect(Collectors.toMap(TimePeriodExamSiteBean::getId, tp -> tp));
|
|
|
+
|
|
|
+ List<TimePeriodExamRoomEntity> timePeriodExamRoomEntityList = new ArrayList<>(timePeriodExamRoomList.size());
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(timePeriodList)) {
|
|
|
+ //是否可编辑判断
|
|
|
+ List<Long> listTimePeriodIds = timePeriodExamRoomList.stream()
|
|
|
+ .filter(item -> !item.getEnable())
|
|
|
+ .map(TimePeriodExamSiteReq::getTimePeriodId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ canEdit(listTimePeriodIds, curApplyTask);
|
|
|
+ handleFirstTimeSave(userId, examRoomId, timePeriodExamRoomList, timePeriodExamRoomEntityList, examRoom);
|
|
|
+ } else {
|
|
|
+ handleUpdateOrSave(userId, examRoomId, timePeriodExamRoomList, timePeriodExamRoomEntityList, timePeriodMap, examRoom, curApplyTask);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("[考场排班设置]保存失败,原因:{}", e.getMessage(), e);
|
|
|
+ throw new StatusException(e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验是否可编辑
|
|
|
+ private void canEdit(List<Long> timePeriodExamRoomList, CurrentApplyTaskVO curApplyTask) {
|
|
|
+ if (CollectionUtils.isNotEmpty(timePeriodExamRoomList)) {
|
|
|
+ Long longToday = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(new Date()) + " 00:00:00");
|
|
|
+ Date today = new Date(longToday);
|
|
|
+ Date otherDay = DateUtil.addValues(today, Calendar.DAY_OF_MONTH, curApplyTask.getAllowApplyCancelDays());
|
|
|
+ long longOtherDay = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(otherDay) + " 23:59:59");
|
|
|
+ // 当前时间
|
|
|
+ long now = System.currentTimeMillis();
|
|
|
+ List<TimePeriodEntity> timePeriodEntities = timePeriodService.listByIds(timePeriodExamRoomList);
|
|
|
+ Map<Long, TimePeriodEntity> timePeriodEntityMap = timePeriodEntities.stream()
|
|
|
+ .collect(Collectors.toMap(TimePeriodEntity::getId, tpe -> tpe));
|
|
|
+
|
|
|
+ for (Long timePeriodId : timePeriodExamRoomList) {
|
|
|
+ TimePeriodEntity timePeriod = timePeriodEntityMap.get(timePeriodId);
|
|
|
+ if (!isTimeEditable(now, timePeriod.getEndTime(), longOtherDay, timePeriod.getStartTime())) {
|
|
|
+ throw new StatusException("保存失败," + DateUtil.getShortDateByLongTime(timePeriod.getStartTime()) + "可编辑时间范围已过");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void handleFirstTimeSave(Long userId, Long examRoomId, List<TimePeriodExamSiteReq> timePeriodExamRoomList,
|
|
|
+ List<TimePeriodExamRoomEntity> timePeriodExamRoomEntityList, ExamRoomEntity examRoom) {
|
|
|
+ timePeriodExamRoomList.forEach(item -> {
|
|
|
+ TimePeriodExamRoomEntity entity = createTimePeriodExamRoomEntity(item, examRoomId, userId);
|
|
|
+ timePeriodExamRoomEntityList.add(entity);
|
|
|
+ });
|
|
|
+
|
|
|
+ saveBatch(timePeriodExamRoomEntityList);
|
|
|
+ //刷新缓存
|
|
|
+ refreshDisableTimePeriodCache(timePeriodExamRoomEntityList, examRoom);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void handleUpdateOrSave(Long userId, Long examRoomId, List<TimePeriodExamSiteReq> timePeriodExamRoomList,
|
|
|
+ List<TimePeriodExamRoomEntity> timePeriodExamRoomEntityList,
|
|
|
+ Map<Long, TimePeriodExamSiteBean> timePeriodMap, ExamRoomEntity examRoom, CurrentApplyTaskVO curApplyTask) {
|
|
|
+ List<TimePeriodExamRoomEntity> toBeSaveList = new ArrayList<>();
|
|
|
+ List<TimePeriodExamRoomEntity> toBeUpdateList = new ArrayList<>();
|
|
|
+
|
|
|
+ timePeriodExamRoomList.forEach(item -> {
|
|
|
+ TimePeriodExamRoomEntity entity = createTimePeriodExamRoomEntity(item, examRoomId, userId);
|
|
|
+ timePeriodExamRoomEntityList.add(entity);
|
|
|
+
|
|
|
+ if (item.getId() == null) {
|
|
|
+ toBeSaveList.add(entity);
|
|
|
+ } else {
|
|
|
+ toBeUpdateList.add(entity);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ List<Long> resultList = new ArrayList<>();
|
|
|
+ for(TimePeriodExamRoomEntity item : toBeSaveList) {
|
|
|
+ resultList.add(item.getTimePeriodId());
|
|
|
+ }
|
|
|
+ for (TimePeriodExamRoomEntity item : toBeUpdateList) {
|
|
|
+ TimePeriodExamSiteBean timePeriod = timePeriodMap.get(item.getId());
|
|
|
+ if(timePeriod != null && !timePeriod.getEnable().equals(item.getEnable())) {
|
|
|
+ resultList.add(item.getTimePeriodId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ canEdit(resultList, curApplyTask);
|
|
|
+
|
|
|
+ saveOrUpdateBatch(timePeriodExamRoomEntityList);
|
|
|
+
|
|
|
+ //新增的记录,刷新缓存,只考虑禁用的情况
|
|
|
+ refreshDisableTimePeriodCache(toBeSaveList, examRoom);
|
|
|
+ //更新的记录,刷新缓存
|
|
|
+ refreshUpdatedTimePeriodCache(toBeUpdateList, timePeriodMap, examRoom);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private TimePeriodExamRoomEntity createTimePeriodExamRoomEntity(TimePeriodExamSiteReq item, Long examRoomId, Long userId) {
|
|
|
+ TimePeriodExamRoomEntity entity = new TimePeriodExamRoomEntity();
|
|
|
+ BeanUtils.copyProperties(item, entity);
|
|
|
+ entity.setExamRoomId(examRoomId);
|
|
|
+ entity.setOperateId(userId);
|
|
|
+ return entity;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void refreshDisableTimePeriodCache(List<TimePeriodExamRoomEntity> disableList, ExamRoomEntity examRoom) {
|
|
|
+ disableList.stream()
|
|
|
+ .filter(item -> !item.getEnable())
|
|
|
+ .forEach(item -> {
|
|
|
+ // TODO 更新容量缓存,缺失 timePeriodId 参数
|
|
|
+ /* applyTaskCacheService.refreshApplyAvailableCountCache(
|
|
|
+ examRoom.getExamSiteId(),
|
|
|
+ examRoom.getCapacity(),
|
|
|
+ 0
|
|
|
+ );*/
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private void refreshUpdatedTimePeriodCache(List<TimePeriodExamRoomEntity> updateList,
|
|
|
+ Map<Long, TimePeriodExamSiteBean> timePeriodMap,
|
|
|
+ ExamRoomEntity examRoom) {
|
|
|
+ updateList.forEach(item -> {
|
|
|
+ TimePeriodExamSiteBean timePeriod = timePeriodMap.get(item.getId());
|
|
|
+ //由启用变为禁用,缓存容量=-考场的容量
|
|
|
+ if (timePeriod != null && Boolean.TRUE.equals(timePeriod.getEnable()) && !item.getEnable()) {
|
|
|
+ // TODO 更新容量缓存,缺失 timePeriodId 参数
|
|
|
+ /* applyTaskCacheService.refreshApplyAvailableCountCache(
|
|
|
+ examRoom.getExamSiteId(),
|
|
|
+ examRoom.getCapacity(),
|
|
|
+ 0
|
|
|
+ );*/
|
|
|
+ }
|
|
|
+
|
|
|
+ //由禁用变为启用,缓存容量=+考场的容量
|
|
|
+ if (timePeriod != null && Boolean.FALSE.equals(timePeriod.getEnable()) && item.getEnable()) {
|
|
|
+ // TODO 更新容量缓存,缺失 timePeriodId 参数
|
|
|
+ /*applyTaskCacheService.refreshApplyAvailableCountCache(
|
|
|
+ examRoom.getExamSiteId(),
|
|
|
+ 0,
|
|
|
+ examRoom.getCapacity()
|
|
|
+ );*/
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+}
|