package com.qmth.exam.reserve.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.qmth.boot.core.concurrent.service.ConcurrentService; import com.qmth.boot.core.exception.StatusException; import com.qmth.exam.reserve.bean.Constants; import com.qmth.exam.reserve.bean.RichTextBean; import com.qmth.exam.reserve.bean.apply.*; import com.qmth.exam.reserve.bean.applytask.CurrentApplyTaskVO; import com.qmth.exam.reserve.bean.category.CategoryCacheBean; import com.qmth.exam.reserve.bean.course.CourseVO; import com.qmth.exam.reserve.bean.examsite.ExamSiteCacheBean; import com.qmth.exam.reserve.bean.login.LoginUser; import com.qmth.exam.reserve.cache.CacheConstants; import com.qmth.exam.reserve.cache.impl.ApplyTaskCacheService; import com.qmth.exam.reserve.cache.impl.CategoryCacheService; import com.qmth.exam.reserve.cache.impl.ExamSiteCacheService; import com.qmth.exam.reserve.dao.StudentApplyDao; import com.qmth.exam.reserve.entity.ApplyTaskEntity; import com.qmth.exam.reserve.entity.ExamSiteEntity; import com.qmth.exam.reserve.entity.StudentApplyEntity; import com.qmth.exam.reserve.entity.TimePeriodEntity; import com.qmth.exam.reserve.enums.ApplyStatus; import com.qmth.exam.reserve.service.*; import com.qmth.exam.reserve.util.DateUtil; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.FastDateFormat; import org.redisson.api.RLock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.text.ParseException; import java.util.*; import java.util.stream.Collectors; @Service public class ExamReserveServiceImpl implements ExamReserveService { private static final Logger log = LoggerFactory.getLogger(ExamReserveServiceImpl.class); @Autowired private ApplyTaskCacheService applyTaskCacheService; @Autowired private ApplyTaskService applyTaskService; @Autowired private ExamSiteService examSiteService; @Autowired private ExamSiteCacheService examSiteCacheService; @Autowired private TimePeriodService timePeriodService; @Autowired private TimePeriodExamSiteService timePeriodExamSiteService; @Autowired private StudentApplyService studentApplyService; @Autowired private StudentCourseService studentCourseService; @Autowired private CategoryCacheService categoryCacheService; @Autowired private ConcurrentService concurrentService; @Autowired private SystemPropertyService systemPropertyService; @Override public void saveStudentApply(LoginUser student, Long examSiteId, Long timePeriodId) { if (examSiteId == null) { throw new StatusException("考点ID不能为空"); } if (timePeriodId == null) { throw new StatusException("预约时段ID不能为空"); } CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(student.getOrgId()); if (curApplyTask == null) { log.warn("预约失败,尚未开启预约任务!stuApplyTaskId:{}", student.getApplyTaskId()); throw new StatusException("尚未开启预约任务"); } if (curApplyTask.getSelfApplyStartTime() > System.currentTimeMillis()) { log.warn("预约失败,未到预约时间!selfApplyStartTime:{}", curApplyTask.getSelfApplyStartTime()); throw new StatusException("未到预约时间"); } if (curApplyTask.getOpenApplyEndTime() < System.currentTimeMillis()) { log.warn("预约失败,预约时间已结束!openApplyEndTime:{}", curApplyTask.getOpenApplyEndTime()); throw new StatusException("预约时间已结束"); } if (!curApplyTask.getTaskId().equals(student.getApplyTaskId())) { log.warn("预约失败,当前预约任务与学生的不匹配!curApplyTaskId:{} stuApplyTaskId:{}", curApplyTask.getTaskId(), student.getApplyTaskId()); throw new StatusException("当前预约任务与学生的不匹配"); } // 自主预约全局开关 boolean globalOpen = systemPropertyService.existPropValue(curApplyTask.getOrgId(), Constants.APPLY_SWITCH, Constants.APPLY_SWITCH_OPEN); if (!globalOpen) { throw new StatusException("当前无法自主预约,请联系教学点老师进行操作"); } CategoryCacheBean category = categoryCacheService.getCategoryById(student.getCategoryId()); if (category == null || !category.getSelfApplyEnable()) { log.warn("预约失败,当前教学点尚未开启考生自主预约!categoryId:{}", student.getCategoryId()); throw new StatusException("当前教学点尚未开启考生自主预约"); } ExamSiteTimePeriodInfo timePeriod = timePeriodExamSiteService.findOneExamSiteTimePeriod(curApplyTask.getTaskId(), examSiteId, timePeriodId); if (timePeriod == null || !timePeriod.getEnable()) { log.warn("预约失败,当前预约时段不存在或未启用!timePeriodId:{}", timePeriodId); throw new StatusException("当前预约时段不存在或未启用"); } // 考前N天,禁止考生自主预约 Date allowDate = DateUtil.changeDateAndTimeEnd(new Date(), curApplyTask.getAllowApplyDays()); Date curDate = new Date(timePeriod.getStartTime()); if (curDate.before(allowDate)) { // 跳过过期时段,“当前时段开始时间”在“允许预约时间”之前,则禁止预约 log.warn("预约失败,当前预约时段已禁止预约!allowApplyDays:{} timePeriodStart:{}", curApplyTask.getAllowApplyDays(), timePeriod.getStartTime()); throw new StatusException("当前预约时段已禁止预约"); } if (concurrentService.isLocked(CacheConstants.LOCK_AUTO_APPLY)) { // 系统自动预约“任务执行期间”不允许预约 log.warn("系统自动预约中,不允许考生操作预约!lockKey:{}", CacheConstants.LOCK_AUTO_APPLY); throw new StatusException(Constants.SYSTEM_BUSY); } String capacityLockKey = String.format(CacheConstants.LOCK_EXAM_SITE_CAPACITY, examSiteId); if (concurrentService.isLocked(capacityLockKey)) { log.warn("考点剩余可约数量更新中,不允许考生操作预约!lockKey:{}", capacityLockKey); throw new StatusException(Constants.SYSTEM_BUSY); } // 考生预约操作锁 String studentApplyLockKey = String.format(CacheConstants.LOCK_STUDENT_APPLY, student.getId()); RLock studentApplyLock = (RLock) concurrentService.getLock(studentApplyLockKey); try { if (!studentApplyLock.tryLock()) { log.warn("获取锁失败,同一个考生不允许同时操作预约!lockKey:{}", studentApplyLockKey); throw new StatusException(Constants.SYSTEM_BUSY); } log.info("获取锁成功!lockKey:{}", studentApplyLockKey); // 考生剩余预约次数 = 允许预约次数 - 已完成预约次数 int studentApplyNumber = applyTaskCacheService.getStudentApplyNumber(student.getId()); int studentApplyFinishCount = applyTaskCacheService.getStudentApplyFinishCount(student.getId()); int unApplyNumber = studentApplyNumber - studentApplyFinishCount; if (unApplyNumber < 1) { String msg = "当前学生无剩余可约时段次数,已完成预约" + studentApplyNumber + "次"; log.warn(msg); throw new StatusException(msg); } ApplyRecordCacheBean existApply = applyTaskCacheService.getStudentApplyRecord(student.getId(), examSiteId, timePeriodId); if (existApply != null && !existApply.getCancel()) { log.warn("当前时段已预约,请勿重复预约!examSiteId:{} timePeriodId:{}", examSiteId, timePeriodId); throw new StatusException("当前时段已预约,请勿重复预约"); } // 某考点某时段的“剩余可约数量” 累减1(抢占1个数量) boolean takeSuccess = applyTaskCacheService.decreaseApplyAvailableCount(examSiteId, timePeriodId); if (!takeSuccess) { log.warn("预约失败,当前预约时段已约满!examSiteId:{} timePeriodId:{}", examSiteId, timePeriodId); throw new StatusException("当前预约时段已约满"); } try { if (existApply != null) { // 存在历史“已取消”的预约记录,则恢复预约 existApply.setCancel(false); existApply.setOperateId(student.getId()); existApply.setOperateTime(System.currentTimeMillis()); existApply.setBizId(applyTaskCacheService.increaseBizId()); // 推送至预约队列 boolean pushSuccess = applyTaskCacheService.pushStudentApplyRecordQueue(existApply); if (!pushSuccess) { throw new StatusException("预约消息推送失败,请稍后再试!"); } // 保存至预约缓存 applyTaskCacheService.saveStudentApplyRecord(existApply); } else { // 不存在则新增预约记录 ApplyRecordCacheBean newApply = new ApplyRecordCacheBean(); newApply.setStudentId(student.getId()); newApply.setExamSiteId(examSiteId); newApply.setTimePeriodId(timePeriodId); newApply.setCancel(false); newApply.setOperateId(student.getId()); newApply.setOperateTime(System.currentTimeMillis()); newApply.setBizId(applyTaskCacheService.increaseBizId()); // 推送至预约队列 boolean pushSuccess = applyTaskCacheService.pushStudentApplyRecordQueue(newApply); if (!pushSuccess) { throw new StatusException("预约消息推送失败,请稍后再试!"); } // 保存至预约缓存 applyTaskCacheService.saveStudentApplyRecord(newApply); } log.warn("预约成功!studentId:{} examSiteId:{} timePeriodId:{}", student.getId(), examSiteId, timePeriodId); } catch (Exception e) { // 异常时,归还1个被占数量 applyTaskCacheService.increaseApplyAvailableCount(examSiteId, timePeriodId); log.error("预约异常!examSiteId:{} timePeriodId:{} err:{}", examSiteId, timePeriodId, e.getMessage()); throw new StatusException("预约失败,请稍后再试!", e); } } finally { try { // 解锁前检查当前线程是否持有该锁 if (studentApplyLock.isLocked() && studentApplyLock.isHeldByCurrentThread()) { studentApplyLock.unlock(); log.info("解锁成功!lockKey:{}", studentApplyLockKey); } } catch (Exception e) { log.warn("解锁失败!lockKey:{} err:{}", studentApplyLockKey, e.getMessage()); } } } @Override public void cancelStudentApply(LoginUser student, Long examSiteId, Long timePeriodId) { if (examSiteId == null) { throw new StatusException("考点ID不能为空"); } if (timePeriodId == null) { throw new StatusException("预约时段ID不能为空"); } CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(student.getOrgId()); if (curApplyTask == null) { log.warn("取消预约失败,尚未开启预约任务!stuApplyTaskId:{}", student.getApplyTaskId()); return; } if (!curApplyTask.getTaskId().equals(student.getApplyTaskId())) { log.warn("取消预约失败,当前预约任务与学生的不匹配!curApplyTaskId:{} stuApplyTaskId:{}", curApplyTask.getTaskId(), student.getApplyTaskId()); return; } // 自主预约全局开关 boolean globalOpen = systemPropertyService.existPropValue(curApplyTask.getOrgId(), Constants.APPLY_SWITCH, Constants.APPLY_SWITCH_OPEN); if (!globalOpen) { throw new StatusException("当前无法自主取消,请联系教学点老师进行操作"); } TimePeriodEntity timePeriod = timePeriodService.getById(timePeriodId); if (timePeriod == null) { log.warn("取消预约失败,预约时段不存在!examSiteId:{} timePeriodId:{}", examSiteId, timePeriodId); return; } // 考前N天,禁止考生自主取消预约 Date allowDate = DateUtil.changeDateAndTimeEnd(new Date(), curApplyTask.getAllowApplyCancelDays()); Date curDate = new Date(timePeriod.getStartTime()); if (curDate.before(allowDate)) { // “当前时段开始时间”在“允许取消时间”之前,禁止取消预约 log.warn("取消预约失败,当前预约记录已禁止取消预约!allowApplyCancelDays:{} timePeriodStart:{}", curApplyTask.getAllowApplyCancelDays(), timePeriod.getStartTime()); throw new StatusException("当前预约记录已禁止取消预约"); } if (concurrentService.isLocked(CacheConstants.LOCK_AUTO_APPLY)) { // 系统自动预约“任务执行期间”不允许取消预约 log.warn("系统自动预约中,不允许考生操作预约!lockKey:{}", CacheConstants.LOCK_AUTO_APPLY); throw new StatusException(Constants.SYSTEM_BUSY); } String capacityLockKey = String.format(CacheConstants.LOCK_EXAM_SITE_CAPACITY, examSiteId); if (concurrentService.isLocked(capacityLockKey)) { log.warn("考点剩余可约数量更新中,不允许考生操作预约!lockKey:{}", capacityLockKey); throw new StatusException(Constants.SYSTEM_BUSY); } // 考生预约操作锁 String studentApplyLockKey = String.format(CacheConstants.LOCK_STUDENT_APPLY, student.getId()); RLock studentApplyLock = (RLock) concurrentService.getLock(studentApplyLockKey); try { if (!studentApplyLock.tryLock()) { log.warn("获取锁失败,同一个考生不允许同时操作预约!lockKey:{}", studentApplyLockKey); throw new StatusException(Constants.SYSTEM_BUSY); } log.info("获取锁成功!lockKey:{}", studentApplyLockKey); // StudentApplyEntity existApply = applyTaskCacheService.getStudentApplyRecordFormDB(student.getId(), examSiteId, timePeriodId); ApplyRecordCacheBean existApply = applyTaskCacheService.getStudentApplyRecord(student.getId(), examSiteId, timePeriodId); if (existApply == null) { log.warn("取消预约失败,预约记录不存在!examSiteId:{} timePeriodId:{}", examSiteId, timePeriodId); return; } if (existApply.getCancel()) { log.warn("当前时段已取消,忽略重复取消!examSiteId:{} timePeriodId:{}", examSiteId, timePeriodId); return; } existApply.setCancel(true); existApply.setOperateId(student.getId()); existApply.setOperateTime(System.currentTimeMillis()); existApply.setBizId(applyTaskCacheService.increaseBizId()); // 推送至预约队列 boolean pushSuccess = applyTaskCacheService.pushStudentApplyRecordQueue(existApply); if (!pushSuccess) { throw new StatusException("预约消息推送失败,请稍后再试!"); } // 保存至预约缓存 applyTaskCacheService.saveStudentApplyRecord(existApply); // 某考点某时段的“剩余可约数量” 累加1(归还1个被占数量) applyTaskCacheService.increaseApplyAvailableCount(examSiteId, timePeriodId); log.warn("取消预约成功!studentId:{} examSiteId:{} timePeriodId:{}", student.getId(), examSiteId, timePeriodId); } finally { try { // 解锁前检查当前线程是否持有该锁 if (studentApplyLock.isLocked() && studentApplyLock.isHeldByCurrentThread()) { studentApplyLock.unlock(); log.info("解锁成功!lockKey:{}", studentApplyLockKey); } } catch (Exception e) { log.warn("解锁失败!lockKey:{} err:{}", studentApplyLockKey, e.getMessage()); } } } public void updateStudentApplyForCancel(Long applyId, boolean cancel, Long operateId) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.set(StudentApplyEntity::getCancel, cancel); updateWrapper.set(StudentApplyEntity::getOperateId, operateId); updateWrapper.set(StudentApplyEntity::getUpdateTime, System.currentTimeMillis()); updateWrapper.eq(StudentApplyEntity::getId, applyId); studentApplyService.update(updateWrapper); } public void addStudentApply(ApplyRecordCacheBean bean) { StudentApplyEntity newApply = new StudentApplyEntity(); newApply.setStudentId(bean.getStudentId()); newApply.setExamSiteId(bean.getExamSiteId()); newApply.setTimePeriodId(bean.getTimePeriodId()); newApply.setOperateId(bean.getStudentId()); newApply.setCancel(bean.getCancel()); studentApplyService.save(newApply); } private boolean hasTicketNumber(Long studentId, Long examSiteId, Long timePeriodId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.select(StudentApplyEntity::getTicketNumber);//只查询ticketNumber等字段 wrapper.eq(StudentApplyEntity::getExamSiteId, examSiteId); wrapper.eq(StudentApplyEntity::getTimePeriodId, timePeriodId); wrapper.eq(StudentApplyEntity::getStudentId, studentId); StudentApplyEntity e = studentApplyService.getOne(wrapper); return e != null && StringUtils.isNotEmpty(e.getTicketNumber()); } private Map getTimePeriods(Set timePeriodIds) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.select(TimePeriodEntity::getId, TimePeriodEntity::getStartTime, TimePeriodEntity::getEndTime); wrapper.in(TimePeriodEntity::getId, timePeriodIds); List timePeriods = timePeriodService.list(wrapper); Map maps = new HashMap<>(); for (TimePeriodEntity timePeriod : timePeriods) { maps.put(timePeriod.getId(), timePeriod); } return maps; } @Override public List getStudentApplyList(LoginUser student, Boolean cancel) { CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(student.getOrgId()); if (curApplyTask == null) { return new ArrayList<>(); } StudentApplyDao baseMapper = (StudentApplyDao) studentApplyService.getBaseMapper(); List list = baseMapper.getStudentApplyList(student.getId(), cancel); if (CollectionUtils.isEmpty(list)) { return new ArrayList<>(); } // 自主预约全局开关 boolean globalOpen = systemPropertyService.existPropValue(curApplyTask.getOrgId(), Constants.APPLY_SWITCH, Constants.APPLY_SWITCH_OPEN); // 考前N天,禁止考生自主取消预约 Date allowDate = DateUtil.changeDateAndTimeEnd(new Date(), curApplyTask.getAllowApplyCancelDays()); for (ApplyVO vo : list) { vo.setShowTicket(false); vo.setAllowCancel(false); if (!vo.getCancel()) { if (StringUtils.isNotEmpty(vo.getTicketNumber())) { // 准考证号已生成,则可查看 vo.setShowTicket(true); } } Date curDate = new Date(vo.getTimePeriodStart()); if (curDate.after(allowDate) && globalOpen) { // “当前时段开始时间”在“允许取消时间”之后,可以取消预约 vo.setAllowCancel(true); } } Collections.sort(list); return list; } @Override public List getStudentApplyListFromCache(LoginUser student, Boolean cancel) { CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(student.getOrgId()); if (curApplyTask == null) { return new ArrayList<>(); } Map maps = applyTaskCacheService.getStudentApplyRecords(student.getId()); if (MapUtils.isEmpty(maps)) { return new ArrayList<>(); } // 自主预约全局开关 boolean globalOpen = systemPropertyService.existPropValue(curApplyTask.getOrgId(), Constants.APPLY_SWITCH, Constants.APPLY_SWITCH_OPEN); Set timePeriodIds = maps.values().stream().map(ApplyRecordCacheBean::getTimePeriodId).collect(Collectors.toSet()); Map timePeriods = this.getTimePeriods(timePeriodIds); // 考前N天,禁止考生自主取消预约 Date allowDate = DateUtil.changeDateAndTimeEnd(new Date(), curApplyTask.getAllowApplyCancelDays()); List list = new ArrayList<>(); for (ApplyRecordCacheBean bean : maps.values()) { if (cancel != null && cancel != bean.getCancel()) { // 按“取消预约”状态过滤 continue; } ApplyVO vo = new ApplyVO(); vo.setShowTicket(false); vo.setAllowCancel(false); vo.setCancel(bean.getCancel()); TimePeriodEntity timePeriod = timePeriods.get(bean.getTimePeriodId()); vo.setTimePeriodId(bean.getTimePeriodId()); if (timePeriod != null) { vo.setTimePeriodStart(timePeriod.getStartTime()); vo.setTimePeriodEnd(timePeriod.getEndTime()); Date curDate = new Date(vo.getTimePeriodStart()); if (curDate.after(allowDate) && globalOpen) { // “当前时段开始时间”在“允许取消时间”之后,可以取消预约 vo.setAllowCancel(true); } } ExamSiteCacheBean examSite = examSiteCacheService.getExamSiteById(bean.getExamSiteId()); vo.setExamSiteId(bean.getExamSiteId()); if (examSite != null) { vo.setExamSiteName(examSite.getExamSiteName()); vo.setExamSiteAddress(examSite.getExamSiteAddress()); vo.setCategoryId(examSite.getCategoryId()); vo.setCategoryName(examSite.getCategoryName()); } if (!vo.getCancel()) { // 准考证号已生成,则可查看 vo.setShowTicket(this.hasTicketNumber(bean.getStudentId(), bean.getExamSiteId(), bean.getTimePeriodId())); } list.add(vo); } Collections.sort(list); return list; } @Override public List getStudentApplyListForCurrent(LoginUser student) { // 默认过滤掉“已取消预约”的记录 // List list = this.getStudentApplyList(student, false); List list = this.getStudentApplyListFromCache(student, false); Date now = new Date(); List newList = new ArrayList<>(); for (ApplyVO vo : list) { Date curDate = new Date(vo.getTimePeriodEnd()); if (curDate.before(now)) { // “当前时段结束时间”在“当前时间”之前,则过滤掉 continue; } newList.add(vo); } return newList; } @Override public TicketInfo getApplyTicket(Long studentId, Long examSiteId, Long timePeriodId) { if (examSiteId == null) { throw new StatusException("考点ID不能为空"); } if (timePeriodId == null) { throw new StatusException("预约时段ID不能为空"); } StudentApplyDao baseMapper = (StudentApplyDao) studentApplyService.getBaseMapper(); TicketInfo info = baseMapper.getStudentApplyTicket(studentId, examSiteId, timePeriodId); if (info == null || info.getCancel()) { throw new StatusException("准考证信息不存在"); } if (StringUtils.isEmpty(info.getTicketNumber())) { throw new StatusException("准考证信息尚未生成"); } List courses = studentCourseService.getStudentCourses(studentId); info.setCourses(courses); return info; } @Override public List getApplyDateList(LoginUser student, Long examSiteId) { if (examSiteId == null) { throw new StatusException("考点ID不能为空"); } // 日期格式:yyyyMMdd List dateList = new ArrayList<>(); CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(student.getOrgId()); if (curApplyTask == null) { return dateList; } ExamSiteTimePeriodQuery periodQuery = new ExamSiteTimePeriodQuery(); periodQuery.setApplyTaskId(curApplyTask.getTaskId()); periodQuery.setExamSiteId(examSiteId); List timePeriods = timePeriodExamSiteService.findExamSiteTimePeriods(periodQuery); if (CollectionUtils.isEmpty(timePeriods)) { return dateList; } // 考前N天,禁止考生自主预约 Date allowDate = DateUtil.changeDateAndTimeEnd(new Date(), curApplyTask.getAllowApplyDays()); Set dates = new HashSet<>(); FastDateFormat fdf = FastDateFormat.getInstance("yyyyMMdd"); for (ExamSiteTimePeriodInfo timePeriod : timePeriods) { if (!timePeriod.getEnable()) { // 跳过未启用的时段 continue; } Date curDate = new Date(timePeriod.getStartTime()); if (curDate.before(allowDate)) { // 跳过过期时段,“当前时段开始时间”在“允许预约时间”之前,则禁止预约 continue; } dates.add(fdf.format(curDate)); } dateList.addAll(dates); Collections.sort(dateList); return dateList; } @Override public ApplyTimePeriodResult getApplyTimePeriodList(LoginUser student, Long examSiteId, String date) { if (examSiteId == null) { throw new StatusException("考点ID不能为空"); } if (StringUtils.isEmpty(date)) { throw new StatusException("预约日期不能为空"); } Date timeBegin, timeEnd; try { FastDateFormat fdf = FastDateFormat.getInstance("yyyyMMddHHmmss"); timeBegin = fdf.parse(date + "000000"); timeEnd = fdf.parse(date + "235959"); } catch (ParseException e) { log.error(e.getMessage(), e); throw new StatusException("预约日期值的格式不正确"); } CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(student.getOrgId()); if (curApplyTask == null) { throw new StatusException("尚未开启预约任务"); } if (curApplyTask.getSelfApplyStartTime() > System.currentTimeMillis()) { log.warn("未到预约时间!selfApplyStartTime:{}", curApplyTask.getSelfApplyStartTime()); throw new StatusException("未到预约时间"); } ExamSiteTimePeriodQuery periodQuery = new ExamSiteTimePeriodQuery(); periodQuery.setApplyTaskId(curApplyTask.getTaskId()); periodQuery.setExamSiteId(examSiteId); periodQuery.setTimeBegin(timeBegin.getTime()); periodQuery.setTimeEnd(timeEnd.getTime()); List timePeriods = timePeriodExamSiteService.findExamSiteTimePeriods(periodQuery); // 获取某考生的 所有的“预约记录” // Map maps = applyTaskCacheService.getStudentApplyRecordsFromDB(student.getId()); Map maps = applyTaskCacheService.getStudentApplyRecords(student.getId()); int studentApplyFinishCount = 0; for (ApplyRecordCacheBean bean : maps.values()) { if (!bean.getCancel()) { studentApplyFinishCount++; } } // 考生剩余预约次数 = 允许预约次数 - 已完成预约次数 int studentApplyNumber = applyTaskCacheService.getStudentApplyNumber(student.getId()); int unApplyNumber = studentApplyNumber - studentApplyFinishCount; List periodList = new ArrayList<>(); if (CollectionUtils.isNotEmpty(timePeriods)) { for (ExamSiteTimePeriodInfo timePeriod : timePeriods) { TimePeriodInfo info = new TimePeriodInfo(); info.setTimePeriodId(timePeriod.getTimePeriodId()); info.setTimePeriodStart(timePeriod.getStartTime()); info.setTimePeriodEnd(timePeriod.getEndTime()); info.setEnable(timePeriod.getEnable()); int availableCount = applyTaskCacheService.getApplyAvailableCount(examSiteId, timePeriod.getTimePeriodId()); info.setAvailableCount(availableCount); if (availableCount < 1) { info.setStatus(ApplyStatus.FULL); } else { info.setStatus(ApplyStatus.AVAILABLE); } String hashKey = String.format("%s_%s", examSiteId, timePeriod.getTimePeriodId()); ApplyRecordCacheBean existApply = maps.get(hashKey); if (existApply != null && !existApply.getCancel()) { info.setStatus(ApplyStatus.FINISHED); } periodList.add(info); } } ApplyTimePeriodResult result = new ApplyTimePeriodResult(); result.setUnApplyNumber(Math.max(unApplyNumber, 0)); result.setPeriodList(periodList); return result; } @Override public RichTextBean getExamNotice(Long applyTaskId) { if (applyTaskId == null) { throw new StatusException("预约任务ID不能为空"); } ApplyTaskEntity applyTask = applyTaskService.getById(applyTaskId); if (applyTask == null) { throw new StatusException("考试须知信息不存在"); } RichTextBean bean = new RichTextBean(); bean.setContent(applyTask.getNotice()); return bean; } @Override public RichTextBean getExamSiteGuide(Long examSiteId) { if (examSiteId == null) { throw new StatusException("考点ID不能为空"); } ExamSiteEntity examSite = examSiteService.getById(examSiteId); if (examSite == null) { throw new StatusException("考场引导信息不存在"); } RichTextBean bean = new RichTextBean(); bean.setContent(examSite.getGuide()); return bean; } }