|
@@ -3,10 +3,8 @@ package com.qmth.exam.reserve.service.impl;
|
|
|
import java.io.File;
|
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
-import java.time.Instant;
|
|
|
import java.time.LocalDate;
|
|
|
import java.time.ZoneId;
|
|
|
-import java.time.temporal.ChronoUnit;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Calendar;
|
|
@@ -15,10 +13,8 @@ import java.util.Comparator;
|
|
|
import java.util.Date;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.Iterator;
|
|
|
-import java.util.LinkedHashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
-import java.util.Map.Entry;
|
|
|
import java.util.concurrent.locks.Lock;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
@@ -29,7 +25,6 @@ import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
-import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
@@ -43,6 +38,8 @@ import com.qmth.boot.tools.excel.ExcelReader;
|
|
|
import com.qmth.boot.tools.excel.enums.ExcelType;
|
|
|
import com.qmth.boot.tools.excel.model.DataMap;
|
|
|
import com.qmth.boot.tools.io.ZipWriter;
|
|
|
+import com.qmth.exam.reserve.bean.Constants;
|
|
|
+import com.qmth.exam.reserve.bean.apply.ApplyRecordCacheBean;
|
|
|
import com.qmth.exam.reserve.bean.login.LoginUser;
|
|
|
import com.qmth.exam.reserve.bean.stdapply.AgentAndTimeVO;
|
|
|
import com.qmth.exam.reserve.bean.stdapply.MaterialTitleInfo;
|
|
@@ -130,21 +127,51 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
public void cancel(LoginUser user, Long id) {
|
|
|
// 时间判断
|
|
|
StudentApplyEntity studentApply = this.baseMapper.selectById(id);
|
|
|
- if (studentApply == null || studentApply.getTimePeriodId() == null)
|
|
|
+ if (studentApply == null || studentApply.getTimePeriodId() == null) {
|
|
|
throw new StatusException("考生没有预约,无法取消!");
|
|
|
- TimePeriodEntity timePeroid = timePeriodService.getById(studentApply.getTimePeriodId());
|
|
|
- if (timePeroid == null)
|
|
|
+ }
|
|
|
+ TimePeriodEntity timePeriod = timePeriodService.getById(studentApply.getTimePeriodId());
|
|
|
+ if (timePeriod == null) {
|
|
|
throw new StatusException("考试时段不存在,请检查考试时段数据!");
|
|
|
+ }
|
|
|
ApplyTaskEntity task = getApplyTask();
|
|
|
- Date applyDate = DateUtils.truncate(new Date(timePeroid.getStartTime()), Calendar.DATE);
|
|
|
+ Date applyDate = DateUtils.truncate(new Date(timePeriod.getStartTime()), Calendar.DATE);
|
|
|
Date canCancelDay = DateUtil.addValues(applyDate, Calendar.DAY_OF_MONTH, -task.getAllowApplyCancelDays());
|
|
|
- if (new Date().after(canCancelDay))
|
|
|
+ if (new Date().after(canCancelDay)) {
|
|
|
throw new StatusException("可取消时间已过,无法取消!");
|
|
|
- studentApply.setCancel(Boolean.TRUE);
|
|
|
- this.baseMapper.updateById(studentApply);
|
|
|
+ }
|
|
|
|
|
|
- // redis更新:该时段redis已预约的数量减1
|
|
|
- cacheService.decreaseApplyFinishCount(studentApply.getExamSiteId(), studentApply.getTimePeriodId());
|
|
|
+ String studentApplyLockKey = String.format(CacheConstants.LOCK_STUDENT_APPLY, studentApply.getStudentId());
|
|
|
+ Lock studentApplyLock = concurrentService.getLock(studentApplyLockKey);
|
|
|
+ try {
|
|
|
+ if (!studentApplyLock.tryLock()) {
|
|
|
+ log.warn("获取锁失败,同一个考生不允许同时操作预约!lockKey:{}", studentApplyLockKey);
|
|
|
+ throw new StatusException(Constants.SYSTEM_BUSY);
|
|
|
+ }
|
|
|
+ if (studentApplyLock.tryLock()) {
|
|
|
+ studentApply.setCancel(Boolean.TRUE);
|
|
|
+ this.baseMapper.updateById(studentApply);
|
|
|
+
|
|
|
+ ApplyRecordCacheBean bean = new ApplyRecordCacheBean();
|
|
|
+ bean.setStudentId(studentApply.getStudentId());
|
|
|
+ bean.setExamSiteId(studentApply.getExamSiteId());
|
|
|
+ bean.setTimePeriodId(studentApply.getTimePeriodId());
|
|
|
+ bean.setCancel(Boolean.TRUE);
|
|
|
+ bean.setOperateId(user.getId());
|
|
|
+ bean.setOperateTime(System.currentTimeMillis());
|
|
|
+ cacheService.saveStudentApplyRecord(bean);
|
|
|
+ cacheService.pushStudentApplyRecordQueue(bean);
|
|
|
+ cacheService.decreaseApplyFinishCount(studentApply.getExamSiteId(), studentApply.getTimePeriodId());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new StatusException("取消预约失败,请稍后再试!", e);
|
|
|
+ } finally {
|
|
|
+ try {
|
|
|
+ studentApplyLock.unlock();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn(e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
operateLogService.insertOperateLog(user.getId(), EventType.CANCEL_APPLY, JsonHelper.toJson(studentApply));
|
|
|
}
|
|
@@ -153,7 +180,6 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
@Override
|
|
|
public List<Map<String, Object>> importPreExam(Long userId, Long teachingId, Integer level,
|
|
|
InputStream inputStream) {
|
|
|
- /* checkInOpenTime(); */
|
|
|
List<DataMap> lineList = null;
|
|
|
ExcelReader reader = ExcelReader.create(ExcelType.XLSX, inputStream, 0);
|
|
|
try {
|
|
@@ -321,16 +347,12 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
|
|
|
checkStudentApplyTime(applyList, getApplyTask().getAllowApplyCancelDays(), failRecords);
|
|
|
if (CollectionUtils.isNotEmpty(failRecords)) {
|
|
|
- TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
|
|
+ // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
|
|
return failRecords;
|
|
|
}
|
|
|
checkAvailableTimePeriod(applyList);
|
|
|
- List<AgentAndTimeVO> toBeUpdateAgentTimeList = new ArrayList<>();
|
|
|
for (int i = 0; i < applyList.size(); i++) {
|
|
|
StudentImportVO vo = applyList.get(i);
|
|
|
- if (!vo.getAgentTimeList().isEmpty()) {
|
|
|
- toBeUpdateAgentTimeList.addAll(vo.getAgentTimeList());
|
|
|
- }
|
|
|
try {
|
|
|
saveStdApply(i, vo, userId, failRecords);
|
|
|
} catch (StatusException e) {
|
|
@@ -340,12 +362,10 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
}
|
|
|
|
|
|
if (CollectionUtils.isNotEmpty(failRecords)) {
|
|
|
- TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
|
|
+ // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
|
|
return failRecords;
|
|
|
}
|
|
|
|
|
|
- // 导入预考后,更新redis
|
|
|
- updateRedisCount(toBeUpdateAgentTimeList);
|
|
|
return failRecords;
|
|
|
|
|
|
}
|
|
@@ -355,23 +375,29 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
StudentImportVO vo = applyList.get(i);
|
|
|
List<AgentAndTimeVO> agentTimeList = vo.getAgentTimeList();
|
|
|
List<StudentApplyEntity> haveApplyList = listStudentApply(vo.getStudentId(), Boolean.FALSE);
|
|
|
+ int studentApplyFinishCount = cacheService.getStudentApplyFinishCount(vo.getStudentId());
|
|
|
+ if (studentApplyFinishCount == 0) {
|
|
|
+ studentApplyFinishCount = haveApplyList.size();
|
|
|
+ }
|
|
|
Collections.sort(agentTimeList, Comparator.comparing(AgentAndTimeVO::getStartTime));
|
|
|
- // 考生已经预约,不做处理,跳过
|
|
|
List<AgentAndTimeVO> tobeInsertTimeList = new ArrayList<>();
|
|
|
- if (haveApplyList.size() >= agentTimeList.size()) {
|
|
|
- vo.setAgentTimeList(tobeInsertTimeList);
|
|
|
+
|
|
|
+ // 考生已经完成预约-不做处理
|
|
|
+ if (studentApplyFinishCount == vo.getApplyNumber().intValue()) {
|
|
|
continue;
|
|
|
}
|
|
|
+
|
|
|
// 只预约了部分
|
|
|
- if (haveApplyList.size() > 0 && haveApplyList.size() < agentTimeList.size()) {
|
|
|
+ if (studentApplyFinishCount > 0 && studentApplyFinishCount < vo.getApplyNumber()) {
|
|
|
List<AgentAndTimeVO> availableList = listAvailableTime(haveApplyList, agentTimeList);
|
|
|
// 需要填充的次数
|
|
|
- for (int j = 0; j < agentTimeList.size() - haveApplyList.size(); j++) {
|
|
|
+ for (int j = 0; j < availableList.size(); j++) {
|
|
|
tobeInsertTimeList.add(availableList.get(j));
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
// 未预约
|
|
|
- if (haveApplyList.size() == 0) {
|
|
|
+ if (studentApplyFinishCount == 0) {
|
|
|
tobeInsertTimeList = agentTimeList;
|
|
|
}
|
|
|
vo.setAgentTimeList(tobeInsertTimeList);
|
|
@@ -420,12 +446,6 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void updateRedisCount(List<AgentAndTimeVO> toBeUpdateAgentTimeList) {
|
|
|
- for (AgentAndTimeVO time : toBeUpdateAgentTimeList) {
|
|
|
- cacheService.increaseApplyFinishCount(time.getAgentId(), time.getTimePeriodId());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
private ApplyTaskEntity getApplyTask() {
|
|
|
LambdaQueryWrapper<ApplyTaskEntity> wrapper = new LambdaQueryWrapper<ApplyTaskEntity>()
|
|
|
.eq(ApplyTaskEntity::getEnable, Boolean.TRUE);
|
|
@@ -439,20 +459,57 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
List<Map<String, Object>> failRecords) {
|
|
|
List<StudentApplyEntity> ApplyList = new ArrayList<>();
|
|
|
List<AgentAndTimeVO> agentTimeList = vo.getAgentTimeList();
|
|
|
- for (AgentAndTimeVO agentTime : agentTimeList) {
|
|
|
- StudentApplyEntity entity = new StudentApplyEntity();
|
|
|
- entity.setStudentId(vo.getStudentId());
|
|
|
- entity.setExamSiteId(agentTime.getAgentId());
|
|
|
- entity.setTimePeriodId(agentTime.getTimePeriodId());
|
|
|
- entity.setCancel(Boolean.FALSE);
|
|
|
- entity.setOperateId(userId);
|
|
|
- int haveApplyCount = countApplyFinishForExamSiteAndTimePeriod(agentTime.getAgentId(),
|
|
|
- agentTime.getTimePeriodId());
|
|
|
- ExamSiteEntity examSite = examSiteService.getById(agentTime.getAgentId());
|
|
|
- if (haveApplyCount >= examSite.getCapacity().intValue()) {
|
|
|
- failRecords.add(newError(row + 1, " 考点【" + examSite.getName() + "】的容量已满"));
|
|
|
+ String studentApplyLockKey = String.format(CacheConstants.LOCK_STUDENT_APPLY, vo.getStudentId());
|
|
|
+ Lock studentApplyLock = concurrentService.getLock(studentApplyLockKey);
|
|
|
+ try {
|
|
|
+ if (!studentApplyLock.tryLock()) {
|
|
|
+ log.warn("获取锁失败,考生在同时操作预约!lockKey:{}", studentApplyLockKey);
|
|
|
} else {
|
|
|
- this.baseMapper.insert(entity);
|
|
|
+ for (AgentAndTimeVO agentTime : agentTimeList) {
|
|
|
+ // 已经预约的容量和考点的容量从redis中获取
|
|
|
+ int haveApplyCount = cacheService.getApplyFinishCount(agentTime.getAgentId(),
|
|
|
+ agentTime.getTimePeriodId());
|
|
|
+ int examSiteCount = cacheService.getApplyTotalCount(agentTime.getAgentId());
|
|
|
+ if (haveApplyCount >= examSiteCount) {
|
|
|
+ ExamSiteEntity examSite = examSiteService.getById(agentTime.getAgentId());
|
|
|
+ failRecords.add(newError(row + 1, " 考点【" + examSite.getName() + "】的容量已满"));
|
|
|
+ } else {
|
|
|
+ StudentApplyEntity entity = new StudentApplyEntity();
|
|
|
+ entity.setStudentId(vo.getStudentId());
|
|
|
+ entity.setExamSiteId(agentTime.getAgentId());
|
|
|
+ entity.setTimePeriodId(agentTime.getTimePeriodId());
|
|
|
+ entity.setCancel(Boolean.FALSE);
|
|
|
+ entity.setOperateId(userId);
|
|
|
+
|
|
|
+ StudentApplyEntity existStudentApply = findStudentApply(entity);
|
|
|
+ if (existStudentApply != null) {
|
|
|
+ existStudentApply.setCancel(Boolean.FALSE);
|
|
|
+ baseMapper.updateById(existStudentApply);
|
|
|
+ } else {
|
|
|
+ baseMapper.insert(entity);
|
|
|
+ }
|
|
|
+
|
|
|
+ ApplyRecordCacheBean bean = new ApplyRecordCacheBean();
|
|
|
+ bean.setStudentId(vo.getStudentId());
|
|
|
+ bean.setExamSiteId(agentTime.getAgentId());
|
|
|
+ bean.setTimePeriodId(agentTime.getTimePeriodId());
|
|
|
+ bean.setCancel(Boolean.FALSE);
|
|
|
+ bean.setOperateId(userId);
|
|
|
+ bean.setOperateTime(System.currentTimeMillis());
|
|
|
+ cacheService.saveStudentApplyRecord(bean);
|
|
|
+ cacheService.pushStudentApplyRecordQueue(bean);
|
|
|
+ cacheService.increaseApplyFinishCount(agentTime.getAgentId(), agentTime.getTimePeriodId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("导入预考失败,错误原因:", e.getMessage());
|
|
|
+ throw new StatusException("导入预考失败,请稍后再试!", e);
|
|
|
+ } finally {
|
|
|
+ try {
|
|
|
+ studentApplyLock.unlock();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn(e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
return ApplyList;
|
|
@@ -527,10 +584,9 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
|
|
|
@Transactional
|
|
|
@Override
|
|
|
- public void autoAssign(Long taskId) {
|
|
|
+ public void autoAssign(Long taskId, Long userId) {
|
|
|
checkAfterOpenTime();
|
|
|
Lock lock = concurrentService.getLock(CacheConstants.LOCK_AUTO_APPLY);
|
|
|
- List<StudentApplyEntity> updateToRedisList = new ArrayList<>();
|
|
|
try {
|
|
|
if (!lock.tryLock()) {
|
|
|
log.warn("获取锁失败,不允许同时执行自动分配!lockKey:{}", CacheConstants.LOCK_AUTO_APPLY);
|
|
@@ -538,23 +594,26 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
}
|
|
|
// 1、未完成预约的考生
|
|
|
List<StudentEntity> studentList = studentService.listNoFinishStudent(taskId, Boolean.FALSE);
|
|
|
- Map<Long, List<StudentEntity>> map = studentList.stream()
|
|
|
+ Map<Long, List<StudentEntity>> noFinishApplyMap = studentList.stream()
|
|
|
.collect(Collectors.groupingBy(StudentEntity::getCategoryId));
|
|
|
// 2、考位是否充足
|
|
|
List<TimePeriodEntity> timeList = listTimePeroid(taskId);
|
|
|
- checkTeachingCapacity(map, timeList, taskId);
|
|
|
+ checkTeachingCapacity(noFinishApplyMap, timeList, taskId);
|
|
|
// 3、按照教学点安排考位。规则:不能和已预约的时间上有冲突
|
|
|
- for (Long key : map.keySet()) {
|
|
|
+ for (Long key : noFinishApplyMap.keySet()) {
|
|
|
List<ExamSiteEntity> siteList = listExamSite(key, null);
|
|
|
- List<StudentEntity> teachingStudentList = map.get(key);
|
|
|
+ List<StudentEntity> teachingStudentList = noFinishApplyMap.get(key);
|
|
|
for (ExamSiteEntity site : siteList) {
|
|
|
for (TimePeriodEntity time : timeList) {
|
|
|
// 该时段已预约的考生
|
|
|
- Integer haveApplyNum = getHaveApplyNum(site.getId(), time.getId());
|
|
|
+ Integer haveApplyNum = cacheService.getApplyFinishCount(site.getId(), time.getId());
|
|
|
+ if (haveApplyNum == null || haveApplyNum == 0) {
|
|
|
+ haveApplyNum = getHaveApplyNum(site.getId(), time.getId());
|
|
|
+ }
|
|
|
// 剩余的考位
|
|
|
Integer remainNum = site.getCapacity() - haveApplyNum;
|
|
|
- updateToRedisList
|
|
|
- .addAll(assignStudentApply(site.getId(), time.getId(), teachingStudentList, remainNum));
|
|
|
+
|
|
|
+ assignStudentApply(userId, site.getId(), time.getId(), teachingStudentList, remainNum);
|
|
|
}
|
|
|
}
|
|
|
// 4、判断是否还有剩余考生未完成预约,提醒考位不够
|
|
@@ -565,51 +624,94 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
log.error(e.getMessage());
|
|
|
throw new StatusException(e.getMessage());
|
|
|
} finally {
|
|
|
- lock.unlock();
|
|
|
- }
|
|
|
- // 更新缓存
|
|
|
- for (StudentApplyEntity apply : updateToRedisList) {
|
|
|
- cacheService.increaseApplyFinishCount(apply.getExamSiteId(), apply.getTimePeriodId());
|
|
|
+ try {
|
|
|
+ lock.unlock();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn(e.getMessage());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- private List<StudentApplyEntity> assignStudentApply(Long siteId, Long timeId,
|
|
|
+ private List<StudentApplyEntity> assignStudentApply(Long userId, Long siteId, Long timeId,
|
|
|
List<StudentEntity> teachingStudentList, Integer remainNum) {
|
|
|
List<StudentApplyEntity> insertApplyList = new ArrayList<>();
|
|
|
int num = 0;
|
|
|
+ String studentApplyLockKey = null;
|
|
|
+ Lock studentApplyLock = null;
|
|
|
for (Iterator<StudentEntity> iterator = teachingStudentList.iterator(); iterator.hasNext();) {
|
|
|
StudentEntity student = iterator.next();
|
|
|
- String studentApplyLockKey = String.format(CacheConstants.LOCK_STUDENT_APPLY, student.getId());
|
|
|
- Lock studentApplyLock = concurrentService.getLock(studentApplyLockKey);
|
|
|
if (num >= remainNum)
|
|
|
break;
|
|
|
- List<StudentApplyEntity> studentApplyList = listStudentApply(student.getId(), Boolean.FALSE);
|
|
|
- int toApplyNum = student.getApplyNumber() - studentApplyList.size();
|
|
|
- if (toApplyNum > 0 && !haveApplySameTimePeriod(siteId, timeId, student.getId())) {
|
|
|
- StudentApplyEntity studentApply = new StudentApplyEntity();
|
|
|
- studentApply.setStudentId(student.getId());
|
|
|
- studentApply.setExamSiteId(siteId);
|
|
|
- studentApply.setCancel(Boolean.FALSE);
|
|
|
- studentApply.setTimePeriodId(timeId);
|
|
|
- if (studentApplyLock.tryLock()) {
|
|
|
- baseMapper.insert(studentApply);
|
|
|
- insertApplyList.add(studentApply);
|
|
|
- studentApplyLock.unlock();
|
|
|
+ studentApplyLockKey = String.format(CacheConstants.LOCK_STUDENT_APPLY, student.getId());
|
|
|
+ studentApplyLock = concurrentService.getLock(studentApplyLockKey);
|
|
|
+ try {
|
|
|
+ if (!studentApplyLock.tryLock()) {
|
|
|
+ log.warn("获取锁失败,考生在同时操作预约!lockKey:{}", studentApplyLockKey);
|
|
|
+ iterator.remove();
|
|
|
} else {
|
|
|
- log.warn("获取锁失败,不允许同一个考生同时操作预约!lockKey:{}", studentApplyLockKey);
|
|
|
+ List<StudentApplyEntity> studentApplyList = listStudentApply(student.getId(), Boolean.FALSE);
|
|
|
+ int toApplyNum = student.getApplyNumber() - studentApplyList.size();
|
|
|
+ if (toApplyNum > 0 && !haveApplySameTimePeriod(siteId, timeId, student.getId())) {
|
|
|
+ StudentApplyEntity studentApply = new StudentApplyEntity();
|
|
|
+ studentApply.setStudentId(student.getId());
|
|
|
+ studentApply.setExamSiteId(siteId);
|
|
|
+ studentApply.setCancel(Boolean.FALSE);
|
|
|
+ studentApply.setTimePeriodId(timeId);
|
|
|
+
|
|
|
+ StudentApplyEntity existStudentApply = findStudentApply(studentApply);
|
|
|
+ if (existStudentApply != null) {
|
|
|
+ existStudentApply.setCancel(Boolean.FALSE);
|
|
|
+ baseMapper.updateById(existStudentApply);
|
|
|
+ } else {
|
|
|
+ baseMapper.insert(studentApply);
|
|
|
+ }
|
|
|
+ insertApplyList.add(studentApply);
|
|
|
+
|
|
|
+ studentApplyLock.unlock();
|
|
|
+ num++;
|
|
|
+ if (student.getApplyNumber() - (studentApplyList.size() + 1) == 0) {
|
|
|
+ iterator.remove();
|
|
|
+ student.setApplyFinished(true);
|
|
|
+ this.studentService.updateById(student);
|
|
|
+ }
|
|
|
+
|
|
|
+ ApplyRecordCacheBean bean = new ApplyRecordCacheBean();
|
|
|
+ bean.setStudentId(studentApply.getStudentId());
|
|
|
+ bean.setExamSiteId(studentApply.getExamSiteId());
|
|
|
+ bean.setTimePeriodId(studentApply.getTimePeriodId());
|
|
|
+ bean.setCancel(Boolean.FALSE);
|
|
|
+ bean.setOperateId(userId);
|
|
|
+ bean.setOperateTime(System.currentTimeMillis());
|
|
|
+ cacheService.saveStudentApplyRecord(bean);
|
|
|
+ cacheService.pushStudentApplyRecordQueue(bean);
|
|
|
+ cacheService.increaseApplyFinishCount(studentApply.getExamSiteId(),
|
|
|
+ studentApply.getTimePeriodId());
|
|
|
+ }
|
|
|
}
|
|
|
- num++;
|
|
|
- if (student.getApplyNumber() - (studentApplyList.size() + 1) == 0) {
|
|
|
- iterator.remove();
|
|
|
- student.setApplyFinished(true);
|
|
|
- this.studentService.updateById(student);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("自动安排预约失败,错误信息:" + e.getMessage());
|
|
|
+ throw new StatusException("自动安排预约失败,请稍后再试!");
|
|
|
+ } finally {
|
|
|
+ try {
|
|
|
+ studentApplyLock.unlock();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn(e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
return insertApplyList;
|
|
|
}
|
|
|
|
|
|
+ private StudentApplyEntity findStudentApply(StudentApplyEntity studentApply) {
|
|
|
+ LambdaQueryWrapper<StudentApplyEntity> lm = new LambdaQueryWrapper<>();
|
|
|
+ lm.eq(StudentApplyEntity::getExamSiteId, studentApply.getExamSiteId());
|
|
|
+ lm.eq(StudentApplyEntity::getTimePeriodId, studentApply.getTimePeriodId());
|
|
|
+ lm.eq(StudentApplyEntity::getStudentId, studentApply.getStudentId());
|
|
|
+ return baseMapper.selectOne(lm);
|
|
|
+ }
|
|
|
+
|
|
|
private boolean haveApplySameTimePeriod(Long siteId, Long timeId, Long studentId) {
|
|
|
LambdaQueryWrapper<StudentApplyEntity> wrapper = new LambdaQueryWrapper<>();
|
|
|
wrapper.eq(StudentApplyEntity::getExamSiteId, siteId);
|
|
@@ -625,8 +727,7 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
wrapper.eq(StudentApplyEntity::getExamSiteId, siteId);
|
|
|
wrapper.eq(StudentApplyEntity::getTimePeriodId, timeId);
|
|
|
wrapper.eq(StudentApplyEntity::getCancel, Boolean.FALSE);
|
|
|
- List<StudentApplyEntity> haveAplyList = baseMapper.selectList(wrapper);
|
|
|
- return haveAplyList == null ? 0 : haveAplyList.size();
|
|
|
+ return baseMapper.selectCount(wrapper);
|
|
|
}
|
|
|
|
|
|
private void checkAfterOpenTime() {
|
|
@@ -646,8 +747,14 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
Integer total = siteList.stream().collect(Collectors.summingInt(ExamSiteEntity::getCapacity))
|
|
|
* timeList.size();
|
|
|
// 已经预约的数量
|
|
|
- Integer haveApplyNum = this.getBaseMapper().getHaveApplyCount(
|
|
|
- siteList.stream().map(site -> site.getId()).collect(Collectors.toList()), Boolean.FALSE);
|
|
|
+ Integer haveApplyNum = 0;
|
|
|
+ for (ExamSiteEntity site : siteList) {
|
|
|
+ haveApplyNum += cacheService.getApplyTotalCount(site.getId());
|
|
|
+ }
|
|
|
+ if (haveApplyNum == 0) {
|
|
|
+ haveApplyNum = getBaseMapper().getHaveApplyCount(
|
|
|
+ siteList.stream().map(site -> site.getId()).collect(Collectors.toList()), Boolean.FALSE);
|
|
|
+ }
|
|
|
// 未预约的数量
|
|
|
Integer noApplyNum = getNoApplyNum(map.get(key));
|
|
|
if (noApplyNum > total - haveApplyNum) {
|
|
@@ -664,8 +771,9 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
if (student.getApplyNumber().intValue() == 1) {
|
|
|
noApplyNum++;
|
|
|
} else if (student.getApplyNumber().intValue() > 1) {
|
|
|
- noApplyNum = noApplyNum
|
|
|
- + (student.getApplyNumber() - listStudentApply(student.getId(), Boolean.FALSE).size());
|
|
|
+ // listStudentApply(student.getId(), Boolean.FALSE).size()
|
|
|
+ int haveApplyNum = cacheService.getStudentApplyFinishCount(student.getId());
|
|
|
+ noApplyNum = noApplyNum + (student.getApplyNumber() - haveApplyNum);
|
|
|
}
|
|
|
}
|
|
|
return noApplyNum;
|
|
@@ -904,46 +1012,43 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
|
if (taskId != null) {
|
|
|
task = applyTaskService.getById(taskId);
|
|
|
} else {
|
|
|
- task = getApplyTask();
|
|
|
+ LambdaQueryWrapper<ApplyTaskEntity> wrapper = new LambdaQueryWrapper<ApplyTaskEntity>()
|
|
|
+ .eq(ApplyTaskEntity::getEnable, Boolean.TRUE);
|
|
|
+ task = applyTaskService.getOne(wrapper);
|
|
|
}
|
|
|
+ if (task == null) {
|
|
|
+ log.warn("当前没有开启的任务");
|
|
|
+ return signInList;
|
|
|
+ }
|
|
|
+
|
|
|
List<TimePeriodEntity> timePeriodList = listTimePeroid(task.getId());
|
|
|
if (timePeriodList.isEmpty()) {
|
|
|
- throw new StatusException("未配置考试时段");
|
|
|
+ log.warn("未配置考试时段");
|
|
|
+ return signInList;
|
|
|
}
|
|
|
- TimePeriodEntity time = timePeriodList.get(0);
|
|
|
- List<TimePeriodEntity> noCancelTimePeroidList = listNoCancelApplyTimePeroid(timePeriodList,
|
|
|
- task.getAllowApplyCancelDays());
|
|
|
- if (noCancelTimePeroidList.isEmpty()) {
|
|
|
- throw new StatusException("未到可以取消预约的时间");
|
|
|
+ Long startTime = timePeriodList.get(0).getStartTime();
|
|
|
+ Long endTime = timePeriodList.get(timePeriodList.size() - 1).getEndTime();
|
|
|
+
|
|
|
+ String todayStr = DateUtil.formatShortSplitDateString(new Date());
|
|
|
+ Long longToday = DateUtil.getLongTimeByDate(todayStr + " 00:00:00");
|
|
|
+ Date today = new Date(longToday);
|
|
|
+ if (longToday >= startTime && longToday <= endTime) {
|
|
|
+ SignInVO vo = new SignInVO();
|
|
|
+ vo.setExamDate(longToday);
|
|
|
+ signInList.add(vo);
|
|
|
}
|
|
|
- LinkedHashMap<LocalDate, LocalDate> map = groupTimestampsByDay(noCancelTimePeroidList);
|
|
|
- long between = ChronoUnit.DAYS.between(LocalDate.now(), map.entrySet().iterator().next().getKey());
|
|
|
- for (long i = 0; i < between; i++) {
|
|
|
- LocalDate day = LocalDate.now().plusDays(i);
|
|
|
- long epochMilli = day.plusDays(1).atStartOfDay(ZoneId.systemDefault()).minusSeconds(1).toInstant()
|
|
|
- .toEpochMilli();
|
|
|
- // 判断是否在考试时段内
|
|
|
- if (epochMilli >= time.getStartTime()) {
|
|
|
- map.put(day, day);
|
|
|
+
|
|
|
+ for (int i = 1; i <= task.getAllowApplyCancelDays().intValue(); i++) {
|
|
|
+ Date otherDay = DateUtil.addValues(today, Calendar.DAY_OF_MONTH, i);
|
|
|
+ Long longOtherDay = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(otherDay) + " 00:00:00");
|
|
|
+ if (longOtherDay >= startTime && longOtherDay <= endTime) {
|
|
|
+ SignInVO vo = new SignInVO();
|
|
|
+ vo.setExamDate(longToday);
|
|
|
+ signInList.add(vo);
|
|
|
}
|
|
|
}
|
|
|
- for (Entry<LocalDate, LocalDate> entry : map.entrySet()) {
|
|
|
- SignInVO signIn = new SignInVO();
|
|
|
- signIn.setExamDate(entry.getKey().atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli());
|
|
|
- signInList.add(signIn);
|
|
|
- }
|
|
|
Collections.sort(signInList, Comparator.comparing(SignInVO::getExamDate));
|
|
|
return signInList;
|
|
|
}
|
|
|
|
|
|
- private LinkedHashMap<LocalDate, LocalDate> groupTimestampsByDay(List<TimePeriodEntity> timeList) {
|
|
|
- LinkedHashMap<LocalDate, LocalDate> map = new LinkedHashMap<>();
|
|
|
- for (TimePeriodEntity time : timeList) {
|
|
|
- Instant instant = Instant.ofEpochMilli(time.getStartTime());
|
|
|
- LocalDate date = instant.atZone(ZoneId.systemDefault()).toLocalDate();
|
|
|
- map.putIfAbsent(date, date);
|
|
|
- }
|
|
|
- return map;
|
|
|
- }
|
|
|
-
|
|
|
}
|