123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696 |
- 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<StudentApplyEntity> 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<StudentApplyEntity> 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<Long, TimePeriodEntity> getTimePeriods(Set<Long> timePeriodIds) {
- LambdaQueryWrapper<TimePeriodEntity> wrapper = new LambdaQueryWrapper<>();
- wrapper.select(TimePeriodEntity::getId, TimePeriodEntity::getStartTime, TimePeriodEntity::getEndTime);
- wrapper.in(TimePeriodEntity::getId, timePeriodIds);
- List<TimePeriodEntity> timePeriods = timePeriodService.list(wrapper);
- Map<Long, TimePeriodEntity> maps = new HashMap<>();
- for (TimePeriodEntity timePeriod : timePeriods) {
- maps.put(timePeriod.getId(), timePeriod);
- }
- return maps;
- }
- @Override
- public List<ApplyVO> getStudentApplyList(LoginUser student, Boolean cancel) {
- CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(student.getOrgId());
- if (curApplyTask == null) {
- return new ArrayList<>();
- }
- StudentApplyDao baseMapper = (StudentApplyDao) studentApplyService.getBaseMapper();
- List<ApplyVO> 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<ApplyVO> getStudentApplyListFromCache(LoginUser student, Boolean cancel) {
- CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(student.getOrgId());
- if (curApplyTask == null) {
- return new ArrayList<>();
- }
- Map<String, ApplyRecordCacheBean> 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<Long> timePeriodIds = maps.values().stream().map(ApplyRecordCacheBean::getTimePeriodId).collect(Collectors.toSet());
- Map<Long, TimePeriodEntity> timePeriods = this.getTimePeriods(timePeriodIds);
- // 考前N天,禁止考生自主取消预约
- Date allowDate = DateUtil.changeDateAndTimeEnd(new Date(), curApplyTask.getAllowApplyCancelDays());
- List<ApplyVO> 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<ApplyVO> getStudentApplyListForCurrent(LoginUser student) {
- // 默认过滤掉“已取消预约”的记录
- // List<ApplyVO> list = this.getStudentApplyList(student, false);
- List<ApplyVO> list = this.getStudentApplyListFromCache(student, false);
- Date now = new Date();
- List<ApplyVO> 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<CourseVO> courses = studentCourseService.getStudentCourses(studentId);
- info.setCourses(courses);
- return info;
- }
- @Override
- public List<String> getApplyDateList(LoginUser student, Long examSiteId) {
- if (examSiteId == null) {
- throw new StatusException("考点ID不能为空");
- }
- // 日期格式:yyyyMMdd
- List<String> 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<ExamSiteTimePeriodInfo> timePeriods = timePeriodExamSiteService.findExamSiteTimePeriods(periodQuery);
- if (CollectionUtils.isEmpty(timePeriods)) {
- return dateList;
- }
- // 考前N天,禁止考生自主预约
- Date allowDate = DateUtil.changeDateAndTimeEnd(new Date(), curApplyTask.getAllowApplyDays());
- Set<String> 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<ExamSiteTimePeriodInfo> timePeriods = timePeriodExamSiteService.findExamSiteTimePeriods(periodQuery);
- // 获取某考生的 所有的“预约记录”
- // Map<String, ApplyRecordCacheBean> maps = applyTaskCacheService.getStudentApplyRecordsFromDB(student.getId());
- Map<String, ApplyRecordCacheBean> 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<TimePeriodInfo> 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;
- }
- }
|