|
@@ -1,22 +1,81 @@
|
|
|
package com.qmth.exam.reserve.service.impl;
|
|
|
|
|
|
+import java.io.InputStream;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+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;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import com.qmth.boot.core.collection.PageResult;
|
|
|
+import com.qmth.boot.core.exception.StatusException;
|
|
|
+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.exam.reserve.bean.login.LoginUser;
|
|
|
+import com.qmth.exam.reserve.bean.stdapply.AgentAndTimeVO;
|
|
|
import com.qmth.exam.reserve.bean.stdapply.StdApplyReq;
|
|
|
import com.qmth.exam.reserve.bean.stdapply.StdApplyVO;
|
|
|
+import com.qmth.exam.reserve.bean.stdapply.StdImportVO;
|
|
|
+import com.qmth.exam.reserve.dao.ApplyTaskDao;
|
|
|
+import com.qmth.exam.reserve.dao.OperateLogDao;
|
|
|
import com.qmth.exam.reserve.dao.StudentApplyDao;
|
|
|
+import com.qmth.exam.reserve.dao.TimePeriodDao;
|
|
|
+import com.qmth.exam.reserve.entity.ApplyTaskEntity;
|
|
|
+import com.qmth.exam.reserve.entity.CategoryEntity;
|
|
|
+import com.qmth.exam.reserve.entity.ExamSiteEntity;
|
|
|
+import com.qmth.exam.reserve.entity.OperateLogEntity;
|
|
|
import com.qmth.exam.reserve.entity.StudentApplyEntity;
|
|
|
+import com.qmth.exam.reserve.entity.StudentEntity;
|
|
|
+import com.qmth.exam.reserve.entity.TimePeriodEntity;
|
|
|
+import com.qmth.exam.reserve.enums.CategoryLevel;
|
|
|
+import com.qmth.exam.reserve.enums.EventType;
|
|
|
+import com.qmth.exam.reserve.service.CategoryService;
|
|
|
+import com.qmth.exam.reserve.service.ExamSiteService;
|
|
|
import com.qmth.exam.reserve.service.StudentApplyService;
|
|
|
+import com.qmth.exam.reserve.service.StudentService;
|
|
|
+import com.qmth.exam.reserve.util.DateUtil;
|
|
|
+import com.qmth.exam.reserve.util.JsonHelper;
|
|
|
import com.qmth.exam.reserve.util.PageUtil;
|
|
|
|
|
|
@Service
|
|
|
public class StudentApplyServiceImp extends ServiceImpl<StudentApplyDao, StudentApplyEntity>
|
|
|
implements StudentApplyService {
|
|
|
|
|
|
+ private static final String[] EXCEL_HEADER = new String[] { "学号", "姓名", "证件号", "所属教学点", "预约考点1", "预约时段1", "预约考点2",
|
|
|
+ "预约时段2", "预约考点3", "预约时段3", "预约考点4", "预约时段4" };
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TimePeriodDao timePeriodDao;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ApplyTaskDao applyTaskDao;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private OperateLogDao operateLogDao;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CategoryService categoryService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private StudentService studentService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ExamSiteService examSiteService;
|
|
|
+
|
|
|
@Override
|
|
|
public PageResult<StdApplyVO> page(StdApplyReq req) {
|
|
|
IPage<StdApplyVO> iPage = this.baseMapper.page(new Page<StdApplyVO>(req.getPageNumber(), req.getPageSize()),
|
|
@@ -24,8 +83,311 @@ public class StudentApplyServiceImp extends ServiceImpl<StudentApplyDao, Student
|
|
|
return PageUtil.of(iPage);
|
|
|
}
|
|
|
|
|
|
- public static void main(String[] args) {
|
|
|
- System.out.println(System.currentTimeMillis());
|
|
|
+ @Transactional
|
|
|
+ @Override
|
|
|
+ public void cancel(LoginUser user, Long id) {
|
|
|
+ // 时间判断
|
|
|
+ StudentApplyEntity studentApply = this.baseMapper.selectById(id);
|
|
|
+ if (studentApply == null || studentApply.getTimePeriodId() == null)
|
|
|
+ throw new StatusException("考生没有预约,无法取消!");
|
|
|
+ TimePeriodEntity timePeroid = this.timePeriodDao.selectById(studentApply.getTimePeriodId());
|
|
|
+ if (timePeroid == null)
|
|
|
+ throw new StatusException("考试时段不存在,请检查考试时段数据!");
|
|
|
+ LambdaQueryWrapper<ApplyTaskEntity> wrapper = new LambdaQueryWrapper<ApplyTaskEntity>()
|
|
|
+ .eq(ApplyTaskEntity::getEnable, Boolean.TRUE);
|
|
|
+ ApplyTaskEntity task = applyTaskDao.selectOne(wrapper);
|
|
|
+ Date applyDate = DateUtil.parse(DateUtil.getShortDateByLongTime(timePeroid.getStartTime()), "yyyy-MM-dd");
|
|
|
+ Date canCancelDay = DateUtil.addValues(applyDate, 5, -task.getAllowApplyCancelDays());
|
|
|
+ if (new Date().after(canCancelDay))
|
|
|
+ throw new StatusException("可取消时间已过,无法取消!");
|
|
|
+ studentApply.setCancel(Boolean.TRUE);
|
|
|
+ this.baseMapper.updateById(studentApply);
|
|
|
+ // TODO redis更新:该时段redis已预约的数量减1
|
|
|
+
|
|
|
+ // 写入日志
|
|
|
+ OperateLogEntity log = new OperateLogEntity();
|
|
|
+ log.setCreateTime(System.currentTimeMillis());
|
|
|
+ log.setUpdateTime(System.currentTimeMillis());
|
|
|
+ log.setOperateId(user.getId());
|
|
|
+ log.setEventType(EventType.CANCEL.toString());
|
|
|
+ log.setContent(JsonHelper.toJson(studentApply));
|
|
|
+ operateLogDao.insert(log);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ @Override
|
|
|
+ public List<Map<String, Object>> importPreExam(LoginUser user, Long teachingId, InputStream inputStream) {
|
|
|
+ checkInTime();
|
|
|
+ List<DataMap> lineList = null;
|
|
|
+ ExcelReader reader = ExcelReader.create(ExcelType.XLSX, inputStream, 0);
|
|
|
+ try {
|
|
|
+ lineList = reader.getDataMapList();
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new StatusException("Excel 解析失败");
|
|
|
+ }
|
|
|
+ if (!Arrays.equals(EXCEL_HEADER, reader.getColumnNames())) {
|
|
|
+ throw new StatusException("Excel表头错误");
|
|
|
+ }
|
|
|
+ if (CollectionUtils.isEmpty(lineList)) {
|
|
|
+ throw new StatusException("Excel无内容");
|
|
|
+ }
|
|
|
+ List<Map<String, Object>> failRecords = new ArrayList<Map<String, Object>>();
|
|
|
+ Map<String, Long> teachingCache = getTeachingCache();
|
|
|
+ Map<String, Long> agentCache = getAgentCache(teachingId);
|
|
|
+ Map<String, Long> timeCache = getTimePeriodCache();
|
|
|
+ List<StdImportVO> applyList = new ArrayList<>();
|
|
|
+ AgentAndTimeVO agentTime = new AgentAndTimeVO();
|
|
|
+ for (int i = 0; i < lineList.size(); i++) {
|
|
|
+ List<AgentAndTimeVO> agentTimeList = new ArrayList<>();
|
|
|
+ DataMap line = lineList.get(i);
|
|
|
+ StdImportVO apply = new StdImportVO();
|
|
|
+ StringBuilder msg = new StringBuilder();
|
|
|
+ String studentCode = trimAndNullIfBlank(line.get(EXCEL_HEADER[0]));
|
|
|
+ if (StringUtils.isBlank(studentCode)) {
|
|
|
+ msg.append(" 学号不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ String name = trimAndNullIfBlank(line.get(EXCEL_HEADER[1]));
|
|
|
+ if (StringUtils.isBlank(name)) {
|
|
|
+ msg.append(" 姓名不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ String identityNumber = trimAndNullIfBlank(line.get(EXCEL_HEADER[2]));
|
|
|
+ if (StringUtils.isBlank(identityNumber)) {
|
|
|
+ msg.append(" 证件号不能为空");
|
|
|
+ }
|
|
|
+ StudentEntity student = null;
|
|
|
+ try {
|
|
|
+ student = checkStd(studentCode, name, identityNumber);
|
|
|
+ apply.setStudentId(student.getId());
|
|
|
+ } catch (StatusException e) {
|
|
|
+ msg.append(" " + e.getMessage());
|
|
|
+ failRecords.add(newError(i + 1, msg.toString()));
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ String teachingName = trimAndNullIfBlank(line.get(EXCEL_HEADER[3]));
|
|
|
+ if (StringUtils.isBlank(teachingName)) {
|
|
|
+ msg.append(" 所属教学点不能为空");
|
|
|
+ }
|
|
|
+ Long categoryId = teachingCache.get(teachingName);
|
|
|
+ if (categoryId == null) {
|
|
|
+ msg.append(" 所属教学点不存在");
|
|
|
+ }
|
|
|
+ if (!student.getCategoryId().equals(categoryId)) {
|
|
|
+ msg.append(" 考生所属教学点和库中的考生教学点不匹配");
|
|
|
+ }
|
|
|
+
|
|
|
+ String agentName1 = trimAndNullIfBlank(line.get(EXCEL_HEADER[4]));
|
|
|
+ if (StringUtils.isBlank(agentName1)) {
|
|
|
+ msg.append(" 预约考点1不能为空");
|
|
|
+ }
|
|
|
+ agentTime = new AgentAndTimeVO();
|
|
|
+ Long agentId = agentCache.get(agentName1);
|
|
|
+ if (agentId == null) {
|
|
|
+ msg.append(" 预约考点1不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ String timePeriod1 = trimAndNullIfBlank(line.get(EXCEL_HEADER[5]));
|
|
|
+ if (StringUtils.isBlank(timePeriod1)) {
|
|
|
+ msg.append(" 预约时段1不能为空");
|
|
|
+ }
|
|
|
+ Long timePeriodId = null;
|
|
|
+ try {
|
|
|
+ timePeriodId = checkTimePeriod(timePeriod1, timeCache);
|
|
|
+ agentTime.setAgentId(agentId);
|
|
|
+ agentTime.setTimePeriodId(timePeriodId);
|
|
|
+ agentTimeList.add(agentTime);
|
|
|
+ } catch (StatusException e) {
|
|
|
+ msg.append(" " + e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ String agentName2 = trimAndNullIfBlank(line.get(EXCEL_HEADER[6]));
|
|
|
+ String timePeriod2 = trimAndNullIfBlank(line.get(EXCEL_HEADER[7]));
|
|
|
+ if (StringUtils.isBlank(agentName2) && StringUtils.isBlank(timePeriod2)) {
|
|
|
+ apply.setAgentTimeList(agentTimeList);
|
|
|
+ applyList.add(apply);
|
|
|
+ if (msg.length() > 0)
|
|
|
+ failRecords.add(newError(i + 1, msg.toString()));
|
|
|
+ continue;
|
|
|
+ } else {
|
|
|
+ agentId = agentCache.get(agentName2);
|
|
|
+ if (agentId == null)
|
|
|
+ msg.append(" 预约考点2不存在");
|
|
|
+ try {
|
|
|
+ timePeriodId = checkTimePeriod(timePeriod2, timeCache);
|
|
|
+ agentTime = new AgentAndTimeVO();
|
|
|
+ agentTime.setAgentId(agentId);
|
|
|
+ agentTime.setTimePeriodId(timePeriodId);
|
|
|
+ agentTimeList.add(agentTime);
|
|
|
+ } catch (StatusException e) {
|
|
|
+ msg.append(" " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ String agentName3 = trimAndNullIfBlank(line.get(EXCEL_HEADER[8]));
|
|
|
+ String timePeriod3 = trimAndNullIfBlank(line.get(EXCEL_HEADER[9]));
|
|
|
+ if (StringUtils.isBlank(agentName3) && StringUtils.isBlank(timePeriod3)) {
|
|
|
+ apply.setAgentTimeList(agentTimeList);
|
|
|
+ applyList.add(apply);
|
|
|
+ if (msg.length() > 0)
|
|
|
+ failRecords.add(newError(i + 1, msg.toString()));
|
|
|
+ continue;
|
|
|
+ } else {
|
|
|
+ agentId = agentCache.get(agentName3);
|
|
|
+ if (agentId == null)
|
|
|
+ msg.append(" 预约考点3不存在");
|
|
|
+ try {
|
|
|
+ timePeriodId = checkTimePeriod(timePeriod3, timeCache);
|
|
|
+ agentTime = new AgentAndTimeVO();
|
|
|
+ agentTime.setAgentId(agentId);
|
|
|
+ agentTime.setTimePeriodId(timePeriodId);
|
|
|
+ agentTimeList.add(agentTime);
|
|
|
+ } catch (StatusException e) {
|
|
|
+ msg.append(" " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ String agentName4 = trimAndNullIfBlank(line.get(EXCEL_HEADER[10]));
|
|
|
+ String timePeriod4 = trimAndNullIfBlank(line.get(EXCEL_HEADER[11]));
|
|
|
+ if (StringUtils.isBlank(agentName4) && StringUtils.isBlank(timePeriod4)) {
|
|
|
+ apply.setAgentTimeList(agentTimeList);
|
|
|
+ applyList.add(apply);
|
|
|
+ if (msg.length() > 0)
|
|
|
+ failRecords.add(newError(i + 1, msg.toString()));
|
|
|
+ continue;
|
|
|
+ } else {
|
|
|
+ agentId = agentCache.get(agentName4);
|
|
|
+ if (agentId == null)
|
|
|
+ msg.append(" 预约考点4不存在");
|
|
|
+ try {
|
|
|
+ timePeriodId = checkTimePeriod(timePeriod4, timeCache);
|
|
|
+ agentTime = new AgentAndTimeVO();
|
|
|
+ agentTime.setAgentId(agentId);
|
|
|
+ agentTime.setTimePeriodId(timePeriodId);
|
|
|
+ agentTimeList.add(agentTime);
|
|
|
+ apply.setAgentTimeList(agentTimeList);
|
|
|
+ applyList.add(apply);
|
|
|
+ } catch (StatusException e) {
|
|
|
+ msg.append(" " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CollectionUtils.isNotEmpty(failRecords)) {
|
|
|
+ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
|
|
+ return failRecords;
|
|
|
+ }
|
|
|
+ for (int i = 0; i < applyList.size(); i++) {
|
|
|
+ StdImportVO vo = applyList.get(i);
|
|
|
+ try {
|
|
|
+ saveStdApply(vo);
|
|
|
+ } catch (StatusException e) {
|
|
|
+ failRecords.add(newError(i + 1, e.getMessage()));
|
|
|
+ } catch (Exception e) {
|
|
|
+ failRecords.add(newError(i + 1, " 系统异常"));
|
|
|
+ log.error("导入异常", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (CollectionUtils.isNotEmpty(failRecords)) {
|
|
|
+ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
|
|
+ }
|
|
|
+ // TODO 更新redis
|
|
|
+ return failRecords;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void checkInTime() {
|
|
|
+ LambdaQueryWrapper<ApplyTaskEntity> wrapper = new LambdaQueryWrapper<ApplyTaskEntity>()
|
|
|
+ .eq(ApplyTaskEntity::getEnable, Boolean.TRUE);
|
|
|
+ ApplyTaskEntity task = applyTaskDao.selectOne(wrapper);
|
|
|
+ Date start = DateUtil.parse(DateUtil.getLongDateByLongTime(task.getOpenApplyStartTime()), null);
|
|
|
+ // DateUtil.isBetwwen(start, end)
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveStdApply(StdImportVO vo) {
|
|
|
+ List<AgentAndTimeVO> agentTimeList = vo.getAgentTimeList();
|
|
|
+ LambdaQueryWrapper<StudentApplyEntity> lm = new LambdaQueryWrapper<>();
|
|
|
+ lm.eq(StudentApplyEntity::getStudentId, vo.getStudentId());
|
|
|
+ this.baseMapper.delete(lm);
|
|
|
+ for (AgentAndTimeVO agentTime : agentTimeList) {
|
|
|
+ StudentApplyEntity entity = new StudentApplyEntity();
|
|
|
+ entity.setStudentId(vo.getStudentId());
|
|
|
+ entity.setCreateTime(System.currentTimeMillis());
|
|
|
+ entity.setUpdateTime(System.currentTimeMillis());
|
|
|
+ entity.setExamSiteId(agentTime.getAgentId());
|
|
|
+ entity.setTimePeriodId(agentTime.getTimePeriodId());
|
|
|
+ entity.setCancel(Boolean.FALSE);
|
|
|
+ this.baseMapper.insert(entity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Long checkTimePeriod(String timePeriod, Map<String, Long> timeCache) {
|
|
|
+ if (timePeriod.split(" ").length != 2) {
|
|
|
+ throw new StatusException(" 预约时段格式不正确");
|
|
|
+ }
|
|
|
+ String[] arr = timePeriod.split("-");
|
|
|
+ String startTime = arr[0] + ":00";
|
|
|
+ String endTime = startTime.substring(0, startTime.indexOf("日") + 1) + " " + arr[1] + ":00";
|
|
|
+ Long startTimeLong = DateUtil.getLongTimeByZHDate(startTime);
|
|
|
+ Long endTimeLong = DateUtil.getLongTimeByZHDate(endTime);
|
|
|
+ if (timeCache.get(startTimeLong + "-" + endTimeLong) == null) {
|
|
|
+ throw new StatusException(" 预约时段不存在");
|
|
|
+ }
|
|
|
+ return timeCache.get(startTimeLong + "-" + endTimeLong);
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Long> getTimePeriodCache() {
|
|
|
+ Map<String, Long> map = new HashMap<>();
|
|
|
+ LambdaQueryWrapper<TimePeriodEntity> lm = new LambdaQueryWrapper<>();
|
|
|
+ List<TimePeriodEntity> timeList = timePeriodDao.selectList(lm);
|
|
|
+ for (TimePeriodEntity time : timeList) {
|
|
|
+ map.put(time.getStartTime() + "-" + time.getEndTime(), time.getId());
|
|
|
+ }
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Long> getTeachingCache() {
|
|
|
+ LambdaQueryWrapper<CategoryEntity> lm = new LambdaQueryWrapper<>();
|
|
|
+ lm.eq(CategoryEntity::getEnable, Boolean.TRUE);
|
|
|
+ lm.eq(CategoryEntity::getLevel, CategoryLevel.TEACHING.getValue());
|
|
|
+ List<CategoryEntity> categoryList = categoryService.list(lm);
|
|
|
+ return categoryList.stream().collect(Collectors.toMap(CategoryEntity::getName, CategoryEntity::getId));
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Long> getAgentCache(Long categoryId) {
|
|
|
+ LambdaQueryWrapper<ExamSiteEntity> lm = new LambdaQueryWrapper<>();
|
|
|
+ lm.eq(ExamSiteEntity::getEnable, Boolean.TRUE);
|
|
|
+ lm.eq(ExamSiteEntity::getCategoryId, categoryId);
|
|
|
+ List<ExamSiteEntity> categoryList = examSiteService.list(lm);
|
|
|
+ return categoryList.stream().collect(Collectors.toMap(ExamSiteEntity::getName, ExamSiteEntity::getId));
|
|
|
+ }
|
|
|
+
|
|
|
+ private StudentEntity checkStd(String studentCode, String name, String identityNumber) {
|
|
|
+ LambdaQueryWrapper<StudentEntity> lm = new LambdaQueryWrapper<>();
|
|
|
+ lm.eq(StudentEntity::getStudentCode, studentCode);
|
|
|
+ lm.eq(StudentEntity::getName, name);
|
|
|
+ lm.eq(StudentEntity::getIdentityNumber, identityNumber);
|
|
|
+ StudentEntity student = studentService.getOne(lm);
|
|
|
+ if (student == null) {
|
|
|
+ throw new StatusException(" 考生信息填写错误");
|
|
|
+ }
|
|
|
+ return student;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> newError(int lineNum, String msg) {
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("lineNum", lineNum);
|
|
|
+ map.put("msg", msg);
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String trimAndNullIfBlank(String s) {
|
|
|
+ if (StringUtils.isBlank(s)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return s.trim();
|
|
|
}
|
|
|
|
|
|
}
|