|
@@ -12,6 +12,7 @@ import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
+import java.util.Map.Entry;
|
|
import java.util.concurrent.locks.Lock;
|
|
import java.util.concurrent.locks.Lock;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
@@ -43,7 +44,7 @@ import com.qmth.exam.reserve.bean.stdapply.StudentApplyReq;
|
|
import com.qmth.exam.reserve.bean.stdapply.StudentApplyVO;
|
|
import com.qmth.exam.reserve.bean.stdapply.StudentApplyVO;
|
|
import com.qmth.exam.reserve.bean.stdapply.StudentImportVO;
|
|
import com.qmth.exam.reserve.bean.stdapply.StudentImportVO;
|
|
import com.qmth.exam.reserve.cache.CacheConstants;
|
|
import com.qmth.exam.reserve.cache.CacheConstants;
|
|
-import com.qmth.exam.reserve.cache.RedisClient;
|
|
|
|
|
|
+import com.qmth.exam.reserve.cache.impl.ApplyTaskCacheService;
|
|
import com.qmth.exam.reserve.dao.StudentApplyDao;
|
|
import com.qmth.exam.reserve.dao.StudentApplyDao;
|
|
import com.qmth.exam.reserve.entity.ApplyTaskEntity;
|
|
import com.qmth.exam.reserve.entity.ApplyTaskEntity;
|
|
import com.qmth.exam.reserve.entity.CategoryEntity;
|
|
import com.qmth.exam.reserve.entity.CategoryEntity;
|
|
@@ -76,8 +77,6 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
private static final String[] EXCEL_HEADER = new String[] { "学号", "姓名", "证件号", "所属教学点", "预约考点1", "预约时段1", "预约考点2",
|
|
private static final String[] EXCEL_HEADER = new String[] { "学号", "姓名", "证件号", "所属教学点", "预约考点1", "预约时段1", "预约考点2",
|
|
"预约时段2", "预约考点3", "预约时段3", "预约考点4", "预约时段4" };
|
|
"预约时段2", "预约考点3", "预约时段3", "预约考点4", "预约时段4" };
|
|
|
|
|
|
- private final long TIMEOUT = 60;
|
|
|
|
-
|
|
|
|
@Autowired
|
|
@Autowired
|
|
private TimePeriodService timePeriodService;
|
|
private TimePeriodService timePeriodService;
|
|
|
|
|
|
@@ -96,9 +95,6 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
@Autowired
|
|
@Autowired
|
|
private OperateLogService operateLogService;
|
|
private OperateLogService operateLogService;
|
|
|
|
|
|
- @Autowired
|
|
|
|
- private RedisClient redisClient;
|
|
|
|
-
|
|
|
|
@Autowired
|
|
@Autowired
|
|
private ExamRoomService examRoomService;
|
|
private ExamRoomService examRoomService;
|
|
|
|
|
|
@@ -108,6 +104,9 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
@Autowired
|
|
@Autowired
|
|
private ConcurrentService concurrentService;
|
|
private ConcurrentService concurrentService;
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
+ private ApplyTaskCacheService cacheService;
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public PageResult<StudentApplyVO> page(StudentApplyReq req) {
|
|
public PageResult<StudentApplyVO> page(StudentApplyReq req) {
|
|
IPage<StudentApplyVO> iPage = this.baseMapper
|
|
IPage<StudentApplyVO> iPage = this.baseMapper
|
|
@@ -133,14 +132,15 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
studentApply.setCancel(Boolean.TRUE);
|
|
studentApply.setCancel(Boolean.TRUE);
|
|
this.baseMapper.updateById(studentApply);
|
|
this.baseMapper.updateById(studentApply);
|
|
|
|
|
|
- // TODO redis更新:该时段redis已预约的数量加1
|
|
|
|
|
|
+ // redis更新:该时段redis已预约的数量减1
|
|
|
|
+ cacheService.decreaseApplyFinishCount(studentApply.getExamSiteId(), studentApply.getTimePeriodId());
|
|
|
|
|
|
operateLogService.insertOperateLog(user.getId(), EventType.CANCEL_APPLY, JsonHelper.toJson(studentApply));
|
|
operateLogService.insertOperateLog(user.getId(), EventType.CANCEL_APPLY, JsonHelper.toJson(studentApply));
|
|
}
|
|
}
|
|
|
|
|
|
@Transactional
|
|
@Transactional
|
|
@Override
|
|
@Override
|
|
- public List<Map<String, Object>> importPreExam(LoginUser user, Long teachingId, Integer level,
|
|
|
|
|
|
+ public List<Map<String, Object>> importPreExam(Long userId, Long teachingId, Integer level,
|
|
InputStream inputStream) {
|
|
InputStream inputStream) {
|
|
checkInOpenTime();
|
|
checkInOpenTime();
|
|
List<DataMap> lineList = null;
|
|
List<DataMap> lineList = null;
|
|
@@ -307,10 +307,17 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
|
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
|
return failRecords;
|
|
return failRecords;
|
|
}
|
|
}
|
|
|
|
+ // 判断容量是否充足
|
|
|
|
+ checkCapactiy(teachingId, applyList);
|
|
|
|
+ List<StudentApplyEntity> deleteApplyList = new ArrayList<>();
|
|
|
|
+ List<AgentAndTimeVO> toBeUpdateAgentTimeList = new ArrayList<>();
|
|
for (int i = 0; i < applyList.size(); i++) {
|
|
for (int i = 0; i < applyList.size(); i++) {
|
|
StudentImportVO vo = applyList.get(i);
|
|
StudentImportVO vo = applyList.get(i);
|
|
|
|
+ toBeUpdateAgentTimeList.addAll(vo.getAgentTimeList());
|
|
try {
|
|
try {
|
|
- saveStdApply(user.getId(), vo);
|
|
|
|
|
|
+ List<StudentApplyEntity> deleteApply = saveStdApply(userId, vo);
|
|
|
|
+ if (!deleteApply.isEmpty())
|
|
|
|
+ deleteApplyList.addAll(deleteApply);
|
|
} catch (StatusException e) {
|
|
} catch (StatusException e) {
|
|
failRecords.add(newError(i + 1, " 系统异常"));
|
|
failRecords.add(newError(i + 1, " 系统异常"));
|
|
log.error("导入异常", e);
|
|
log.error("导入异常", e);
|
|
@@ -320,27 +327,44 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
|
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
|
return failRecords;
|
|
return failRecords;
|
|
}
|
|
}
|
|
- if (CollectionUtils.isEmpty(failRecords)) {
|
|
|
|
- checkStudentApplyFinish(applyList);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // TODO 导入预考后,更新redis
|
|
|
|
|
|
|
|
|
|
+ // 导入预考后,更新redis
|
|
|
|
+ updateRedisCount(deleteApplyList, toBeUpdateAgentTimeList);
|
|
return failRecords;
|
|
return failRecords;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- private void checkStudentApplyFinish(List<StudentImportVO> applyList) {
|
|
|
|
- List<StudentEntity> toBeUpdateList = new ArrayList<>();
|
|
|
|
- for (StudentImportVO importVO : applyList) {
|
|
|
|
- StudentEntity student = studentService.getById(importVO.getStudentId());
|
|
|
|
- List<StudentApplyEntity> haveApplyList = listStudentApply(importVO.getStudentId(), Boolean.FALSE);
|
|
|
|
- if (student.getApplyNumber().intValue() == haveApplyList.size()) {
|
|
|
|
- // 更新考生的完成状态
|
|
|
|
- student.setApplyFinished(Boolean.TRUE);
|
|
|
|
- toBeUpdateList.add(student);
|
|
|
|
|
|
+ private void checkCapactiy(Long teachingId, List<StudentImportVO> applyList) {
|
|
|
|
+ ExamSiteEntity site = null;
|
|
|
|
+ List<AgentAndTimeVO> agentTimelist = new ArrayList<>();
|
|
|
|
+ for (StudentImportVO vo : applyList) {
|
|
|
|
+ agentTimelist.addAll(vo.getAgentTimeList());
|
|
|
|
+ }
|
|
|
|
+ Map<Long, Map<Long, List<AgentAndTimeVO>>> agentTimeMap = agentTimelist.stream().collect(Collectors
|
|
|
|
+ .groupingBy(AgentAndTimeVO::getAgentId, Collectors.groupingBy(AgentAndTimeVO::getTimePeriodId)));
|
|
|
|
+ for (Entry<Long, Map<Long, List<AgentAndTimeVO>>> examSiteEntry : agentTimeMap.entrySet()) {
|
|
|
|
+ site = examSiteService.getById(examSiteEntry.getKey());
|
|
|
|
+ Map<Long, List<AgentAndTimeVO>> examSiteMap = examSiteEntry.getValue();
|
|
|
|
+ for (Entry<Long, List<AgentAndTimeVO>> timeEntry : examSiteMap.entrySet()) {
|
|
|
|
+ List<AgentAndTimeVO> agentTimeList = timeEntry.getValue();
|
|
|
|
+ if (site.getCapacity() == null || agentTimeList.size() > site.getCapacity().intValue()) {
|
|
|
|
+ TimePeriodEntity timePeriod = timePeriodService.getById(timeEntry.getKey());
|
|
|
|
+ Long startTime = timePeriod.getStartTime();
|
|
|
|
+ Long endTime = timePeriod.getEndTime();
|
|
|
|
+ throw new StatusException("考点【" + site.getName() + "】,时段:"
|
|
|
|
+ + DateUtil.getStartAndEndTime(startTime, endTime) + "容量不足");
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- studentService.saveOrUpdateBatch(toBeUpdateList);
|
|
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void updateRedisCount(List<StudentApplyEntity> deleteApplyList,
|
|
|
|
+ List<AgentAndTimeVO> toBeUpdateAgentTimeList) {
|
|
|
|
+ for (StudentApplyEntity apply : deleteApplyList) {
|
|
|
|
+ cacheService.decreaseApplyFinishCount(apply.getExamSiteId(), apply.getTimePeriodId());
|
|
|
|
+ }
|
|
|
|
+ for (AgentAndTimeVO time : toBeUpdateAgentTimeList) {
|
|
|
|
+ cacheService.increaseApplyFinishCount(time.getAgentId(), time.getTimePeriodId());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -362,12 +386,18 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
return task;
|
|
return task;
|
|
}
|
|
}
|
|
|
|
|
|
- private void saveStdApply(Long userId, StudentImportVO vo) {
|
|
|
|
|
|
+ private List<StudentApplyEntity> saveStdApply(Long userId, StudentImportVO vo) {
|
|
|
|
+ List<StudentApplyEntity> ApplyList = new ArrayList<>();
|
|
List<AgentAndTimeVO> agentTimeList = vo.getAgentTimeList();
|
|
List<AgentAndTimeVO> agentTimeList = vo.getAgentTimeList();
|
|
LambdaQueryWrapper<StudentApplyEntity> lm = new LambdaQueryWrapper<>();
|
|
LambdaQueryWrapper<StudentApplyEntity> lm = new LambdaQueryWrapper<>();
|
|
lm.eq(StudentApplyEntity::getStudentId, vo.getStudentId());
|
|
lm.eq(StudentApplyEntity::getStudentId, vo.getStudentId());
|
|
- LogStdApply(userId, this.baseMapper.selectList(lm));
|
|
|
|
- this.baseMapper.delete(lm);
|
|
|
|
|
|
+ lm.eq(StudentApplyEntity::getCancel, Boolean.FALSE);
|
|
|
|
+ List<StudentApplyEntity> existStudentApplyList = this.baseMapper.selectList(lm);
|
|
|
|
+ if (!existStudentApplyList.isEmpty()) {
|
|
|
|
+ logStdApply(userId, existStudentApplyList);
|
|
|
|
+ this.baseMapper.delete(lm);
|
|
|
|
+ ApplyList.addAll(existStudentApplyList);
|
|
|
|
+ }
|
|
for (AgentAndTimeVO agentTime : agentTimeList) {
|
|
for (AgentAndTimeVO agentTime : agentTimeList) {
|
|
StudentApplyEntity entity = new StudentApplyEntity();
|
|
StudentApplyEntity entity = new StudentApplyEntity();
|
|
entity.setStudentId(vo.getStudentId());
|
|
entity.setStudentId(vo.getStudentId());
|
|
@@ -376,9 +406,10 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
entity.setCancel(Boolean.FALSE);
|
|
entity.setCancel(Boolean.FALSE);
|
|
this.baseMapper.insert(entity);
|
|
this.baseMapper.insert(entity);
|
|
}
|
|
}
|
|
|
|
+ return ApplyList;
|
|
}
|
|
}
|
|
|
|
|
|
- private void LogStdApply(Long userId, List<StudentApplyEntity> existList) {
|
|
|
|
|
|
+ private void logStdApply(Long userId, List<StudentApplyEntity> existList) {
|
|
if (!existList.isEmpty()) {
|
|
if (!existList.isEmpty()) {
|
|
for (StudentApplyEntity studentApply : existList) {
|
|
for (StudentApplyEntity studentApply : existList) {
|
|
this.operateLogService.insertOperateLog(userId, EventType.DELETE_APPLY,
|
|
this.operateLogService.insertOperateLog(userId, EventType.DELETE_APPLY,
|
|
@@ -458,17 +489,13 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
public void autoAssign(Long taskId) {
|
|
public void autoAssign(Long taskId) {
|
|
checkAfterOpenTime();
|
|
checkAfterOpenTime();
|
|
Lock lock = concurrentService.getLock(CacheConstants.LOCK_AUTO_APPLY);
|
|
Lock lock = concurrentService.getLock(CacheConstants.LOCK_AUTO_APPLY);
|
|
|
|
+ List<StudentApplyEntity> updateToRedisList = new ArrayList<>();
|
|
try {
|
|
try {
|
|
if (!lock.tryLock()) {
|
|
if (!lock.tryLock()) {
|
|
log.warn("获取锁失败,不允许同时执行自动分配!lockKey:{}", CacheConstants.LOCK_AUTO_APPLY);
|
|
log.warn("获取锁失败,不允许同时执行自动分配!lockKey:{}", CacheConstants.LOCK_AUTO_APPLY);
|
|
throw new StatusException("其他老师正在执行自动分配,请不要重复执行!");
|
|
throw new StatusException("其他老师正在执行自动分配,请不要重复执行!");
|
|
}
|
|
}
|
|
// 1、未完成预约的考生
|
|
// 1、未完成预约的考生
|
|
- /*
|
|
|
|
- * LambdaQueryWrapper<StudentEntity> lm = new LambdaQueryWrapper<>();
|
|
|
|
- * lm.eq(StudentEntity::getApplyFinished, Boolean.FALSE); List<StudentEntity>
|
|
|
|
- * studentList = studentService.list(lm);
|
|
|
|
- */
|
|
|
|
List<StudentEntity> studentList = studentService.listNoFinishStudent(taskId, Boolean.FALSE);
|
|
List<StudentEntity> studentList = studentService.listNoFinishStudent(taskId, Boolean.FALSE);
|
|
Map<Long, List<StudentEntity>> map = studentList.stream()
|
|
Map<Long, List<StudentEntity>> map = studentList.stream()
|
|
.collect(Collectors.groupingBy(StudentEntity::getCategoryId));
|
|
.collect(Collectors.groupingBy(StudentEntity::getCategoryId));
|
|
@@ -485,7 +512,8 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
Integer haveApplyNum = getHaveApplyNum(site.getId(), time.getId());
|
|
Integer haveApplyNum = getHaveApplyNum(site.getId(), time.getId());
|
|
// 剩余的考位
|
|
// 剩余的考位
|
|
Integer remainNum = site.getCapacity() - haveApplyNum;
|
|
Integer remainNum = site.getCapacity() - haveApplyNum;
|
|
- assignStudentApply(site.getId(), time.getId(), teachingStudentList, remainNum);
|
|
|
|
|
|
+ updateToRedisList
|
|
|
|
+ .addAll(assignStudentApply(site.getId(), time.getId(), teachingStudentList, remainNum));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// 4、判断是否还有剩余考生未完成预约,提醒考位不够
|
|
// 4、判断是否还有剩余考生未完成预约,提醒考位不够
|
|
@@ -498,11 +526,16 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
} finally {
|
|
} finally {
|
|
lock.unlock();
|
|
lock.unlock();
|
|
}
|
|
}
|
|
|
|
+ // 更新缓存
|
|
|
|
+ for (StudentApplyEntity apply : updateToRedisList) {
|
|
|
|
+ cacheService.increaseApplyFinishCount(apply.getExamSiteId(), apply.getTimePeriodId());
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- private void assignStudentApply(Long siteId, Long timeId, List<StudentEntity> teachingStudentList,
|
|
|
|
- Integer remainNum) {
|
|
|
|
|
|
+ private List<StudentApplyEntity> assignStudentApply(Long siteId, Long timeId,
|
|
|
|
+ List<StudentEntity> teachingStudentList, Integer remainNum) {
|
|
|
|
+ List<StudentApplyEntity> insertApplyList = new ArrayList<>();
|
|
int num = 0;
|
|
int num = 0;
|
|
for (Iterator<StudentEntity> iterator = teachingStudentList.iterator(); iterator.hasNext();) {
|
|
for (Iterator<StudentEntity> iterator = teachingStudentList.iterator(); iterator.hasNext();) {
|
|
StudentEntity student = iterator.next();
|
|
StudentEntity student = iterator.next();
|
|
@@ -520,6 +553,7 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
studentApply.setTimePeriodId(timeId);
|
|
studentApply.setTimePeriodId(timeId);
|
|
if (studentApplyLock.tryLock()) {
|
|
if (studentApplyLock.tryLock()) {
|
|
baseMapper.insert(studentApply);
|
|
baseMapper.insert(studentApply);
|
|
|
|
+ insertApplyList.add(studentApply);
|
|
} else {
|
|
} else {
|
|
log.warn("获取锁失败,不允许同一个考生同时操作预约!lockKey:{}", studentApplyLockKey);
|
|
log.warn("获取锁失败,不允许同一个考生同时操作预约!lockKey:{}", studentApplyLockKey);
|
|
}
|
|
}
|
|
@@ -531,6 +565,7 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ return insertApplyList;
|
|
}
|
|
}
|
|
|
|
|
|
private boolean haveApplySameTimePeriod(Long siteId, Long timeId, Long studentId) {
|
|
private boolean haveApplySameTimePeriod(Long siteId, Long timeId, Long studentId) {
|
|
@@ -628,10 +663,6 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
log.info("没有开启预约任务");
|
|
log.info("没有开启预约任务");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- // boolean isSuccess = redisClient.tryLock(
|
|
|
|
- // CacheConstants.LOCK_ARRANGE_EXAM + DateUtil.formatShortDateString(new
|
|
|
|
- // Date()), FastUUID.get(), TIMEOUT,
|
|
|
|
- // TimeUnit.MINUTES);
|
|
|
|
String autoLayoutLockKey = String.format(CacheConstants.LOCK_ARRANGE_EXAM,
|
|
String autoLayoutLockKey = String.format(CacheConstants.LOCK_ARRANGE_EXAM,
|
|
DateUtil.formatShortDateString(new Date()));
|
|
DateUtil.formatShortDateString(new Date()));
|
|
Lock autoLayoutLock = concurrentService.getLock(autoLayoutLockKey);
|
|
Lock autoLayoutLock = concurrentService.getLock(autoLayoutLockKey);
|
|
@@ -669,8 +700,6 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
log.error(e.getMessage());
|
|
log.error(e.getMessage());
|
|
e.printStackTrace();
|
|
e.printStackTrace();
|
|
} finally {
|
|
} finally {
|
|
- // redisClient.delete(CacheConstants.LOCK_ARRANGE_EXAM +
|
|
|
|
- // DateUtil.formatShortDateString(new Date()));
|
|
|
|
autoLayoutLock.unlock();
|
|
autoLayoutLock.unlock();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -813,7 +842,7 @@ public class StudentApplyServiceImpl extends ServiceImpl<StudentApplyDao, Studen
|
|
*/
|
|
*/
|
|
@Override
|
|
@Override
|
|
public int countApplyFinishForExamSiteAndTimePeriod(Long examSiteId, Long timePeriodId) {
|
|
public int countApplyFinishForExamSiteAndTimePeriod(Long examSiteId, Long timePeriodId) {
|
|
- Integer value = baseMapper.countApplyFinishForExamSiteAndTimePeriod(examSiteId,timePeriodId);
|
|
|
|
|
|
+ Integer value = baseMapper.countApplyFinishForExamSiteAndTimePeriod(examSiteId, timePeriodId);
|
|
return value != null ? value : 0;
|
|
return value != null ? value : 0;
|
|
}
|
|
}
|
|
|
|
|