123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- 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.baomidou.mybatisplus.core.metadata.IPage;
- 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.core.fss.store.FileStore;
- import com.qmth.exam.reserve.bean.Constants;
- import com.qmth.exam.reserve.bean.applytask.CurrentApplyTaskVO;
- import com.qmth.exam.reserve.bean.login.LoginUser;
- import com.qmth.exam.reserve.bean.org.OrgInfo;
- import com.qmth.exam.reserve.bean.stdapply.CategoryVO;
- import com.qmth.exam.reserve.bean.student.StudentInfo;
- import com.qmth.exam.reserve.bean.student.StudentReq;
- import com.qmth.exam.reserve.bean.student.StudentVO;
- import com.qmth.exam.reserve.bean.student.WechatBindReq;
- import com.qmth.exam.reserve.cache.impl.ApplyTaskCacheService;
- import com.qmth.exam.reserve.cache.impl.CategoryCacheService;
- import com.qmth.exam.reserve.cache.impl.OrgCacheService;
- import com.qmth.exam.reserve.config.SysProperty;
- import com.qmth.exam.reserve.dao.StudentDao;
- import com.qmth.exam.reserve.entity.ApplyTaskEntity;
- import com.qmth.exam.reserve.entity.StudentApplyEntity;
- import com.qmth.exam.reserve.entity.StudentCourseEntity;
- import com.qmth.exam.reserve.entity.StudentEntity;
- import com.qmth.exam.reserve.enums.AsyncTaskType;
- import com.qmth.exam.reserve.enums.EventType;
- import com.qmth.exam.reserve.enums.FileUploadType;
- import com.qmth.exam.reserve.enums.Role;
- import com.qmth.exam.reserve.service.*;
- import com.qmth.exam.reserve.template.execute.StudentPhotoUploadService;
- import com.qmth.exam.reserve.util.FileUtil;
- import com.qmth.exam.reserve.util.PageUtil;
- import org.apache.commons.codec.digest.DigestUtils;
- import org.apache.commons.collections4.CollectionUtils;
- import org.apache.commons.compress.utils.FileNameUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.slf4j.Logger;
- 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.web.multipart.MultipartFile;
- import java.io.File;
- import java.io.IOException;
- import java.util.Arrays;
- import java.util.List;
- import java.util.Map;
- import java.util.StringJoiner;
- import java.util.stream.Collectors;
- @Service
- public class StudentServiceImpl extends ServiceImpl<StudentDao, StudentEntity> implements StudentService {
- private static final Logger log = LoggerFactory.getLogger(StudentServiceImpl.class);
- @Autowired
- private CategoryCacheService categoryCacheService;
- @Autowired
- private StudentApplyService studentApplyService;
- @Autowired
- private OperateLogService operateLogService;
- @Autowired
- private ApplyTaskService applyTaskService;
- @Autowired
- private FileStore fileStore;
- @Autowired
- private AsyncTaskService asyncTaskService;
- @Autowired
- private StudentPhotoUploadService studentPhotoUploadService;
- @Autowired
- private ApplyTaskCacheService applyTaskCacheService;
- @Autowired
- private SysProperty sysProperty;
- @Autowired
- private StudentCourseService studentCourseService;
- @Autowired
- private OrgCacheService orgCacheService;
- @Override
- public StudentEntity findByStudentCode(Long applyTaskId, String studentCode) {
- if (StringUtils.isEmpty(studentCode)) {
- throw new StatusException("学号不能为空");
- }
- if (applyTaskId == null) {
- throw new StatusException("预约任务ID不能为空");
- }
- LambdaQueryWrapper<StudentEntity> wrapper = new LambdaQueryWrapper<>();
- wrapper.eq(StudentEntity::getStudentCode, studentCode);
- wrapper.eq(StudentEntity::getApplyTaskId, applyTaskId);
- return baseMapper.selectOne(wrapper);
- }
- @Override
- public StudentEntity findByOpenIdAndUid(String openId, String uid) {
- if (StringUtils.isEmpty(openId)) {
- throw new StatusException("微信OID不能为空");
- }
- LambdaQueryWrapper<StudentEntity> wrapper = new LambdaQueryWrapper<>();
- wrapper.eq(StudentEntity::getOpenId, openId);
- if (StringUtils.isNotEmpty(uid)) {
- wrapper.eq(StudentEntity::getUid, uid);
- }
- return baseMapper.selectOne(wrapper);
- }
- @Override
- public int findStudentApplyNumberById(Long studentId) {
- // 只查询applyNumber等少量字段
- LambdaQueryWrapper<StudentEntity> wrapper = new LambdaQueryWrapper<>();
- wrapper.select(StudentEntity::getApplyNumber);
- wrapper.eq(StudentEntity::getId, studentId);
- StudentEntity stu = this.getOne(wrapper);
- if (stu == null) {
- log.warn("学生信息不存在!studentId:{}", studentId);
- throw new StatusException("学生信息不存在");
- }
- return stu.getApplyNumber();
- }
- @Override
- public StudentEntity findLessInfoByStudentId(Long studentId) {
- // 只查询id、name等少量字段
- LambdaQueryWrapper<StudentEntity> wrapper = new LambdaQueryWrapper<>();
- wrapper.select(StudentEntity::getId, StudentEntity::getName);
- wrapper.eq(StudentEntity::getId, studentId);
- return this.getOne(wrapper);
- }
- @Override
- public StudentInfo findInfoByStudentId(Long studentId) {
- StudentInfo info = baseMapper.findInfoById(studentId);
- if (info == null) {
- throw new StatusException("学生信息不存在");
- }
- return info;
- }
- @Transactional
- @Override
- public void bindingWechat(WechatBindReq req) {
- StudentEntity stu = baseMapper.selectById(req.getStudentId());
- if (stu == null) {
- throw new StatusException("学生信息不存在");
- }
- if (StringUtils.isNotEmpty(stu.getOpenId())) {
- throw new StatusException("微信账号已绑定");
- }
- if (StringUtils.isEmpty(req.getOpenId())) {
- throw new StatusException("微信OID不能为空");
- }
- LambdaUpdateWrapper<StudentEntity> updateWrapper = new LambdaUpdateWrapper<>();
- updateWrapper.set(StudentEntity::getOpenId, req.getOpenId());
- updateWrapper.set(StudentEntity::getUid, req.getUid());
- updateWrapper.eq(StudentEntity::getId, req.getStudentId());
- this.update(updateWrapper);
- log.info("[WECHAT_BINDING] studentId:{} openId:{} uid:{}", req.getStudentId(), req.getOpenId(), req.getUid());
- }
- @Transactional
- @Override
- public void unbindWechatByStudentId(Long studentId) {
- StudentEntity stu = baseMapper.selectById(studentId);
- if (stu == null) {
- throw new StatusException("学生信息不存在");
- }
- if (StringUtils.isEmpty(stu.getOpenId())) {
- return;
- }
- LambdaUpdateWrapper<StudentEntity> updateWrapper = new LambdaUpdateWrapper<>();
- updateWrapper.set(StudentEntity::getOpenId, null);
- updateWrapper.set(StudentEntity::getUid, null);
- updateWrapper.eq(StudentEntity::getId, studentId);
- this.update(updateWrapper);
- log.info("[WECHAT_UNBIND] studentId:{} openId:{} uid:{}", stu.getId(), stu.getOpenId(), stu.getUid());
- }
- @Override
- public List<StudentEntity> listNoFinishStudent(Long taskId, Boolean cancel) {
- return this.baseMapper.listNoFinishStudent(taskId, cancel);
- }
- @Override
- public List<CategoryVO> listNoFinishCategory(Long taskId, Boolean cancel) {
- return baseMapper.listNoFinishCategory(taskId, cancel);
- }
- @Override
- public PageResult<StudentVO> pageStudent(StudentReq req) {
- if (req.getTaskId() == null) {
- OrgInfo org = orgCacheService.currentOrg();
- CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(org.getOrgId());
- if (curApplyTask == null) {
- return new PageResult<>();
- } else {
- req.setTaskId(curApplyTask.getTaskId());
- }
- }
- IPage<StudentVO> iPage = baseMapper.pageStudent(new Page<>(req.getPageNumber(), req.getPageSize()), req);
- List<StudentVO> recordList = iPage.getRecords();
- for (StudentVO student : recordList) {
- //添加图片访问前缀
- student.setPhotoPath(sysProperty.getServer() + File.separator + student.getPhotoPath());
- }
- return PageUtil.of(iPage);
- }
- @Override
- @Transactional
- public void delete(Long[] studentCourseIds, LoginUser loginUser) {
- // 考生科目ID
- for(Long studentCourseId : studentCourseIds) {
- StudentCourseEntity studentCourseEntity = studentCourseService.getById(studentCourseId);
- if(studentCourseEntity == null) {
- throw new StatusException("考生科目不存在");
- }
- Long studentId = studentCourseEntity.getStudentId();
- List<StudentApplyEntity> studentApplyList = getStudentApplyList(studentId);
- if (CollectionUtils.isNotEmpty(studentApplyList)) {
- log.warn("[考生删除] 删除失败,存在预约信息,student_id:{}", studentId);
- throw new StatusException("考生存在预约信息,无法删除");
- }
- StudentEntity studentEntity = this.getById(studentId);
- if (studentEntity == null) {
- log.warn("[考生删除] 考生不存在,student_id:{}", studentId);
- throw new StatusException("考生不存在,无法删除");
- }
- //教学点管理员
- if (loginUser.getRole().equals(Role.TEACHING)) {
- Long studentCategoryId = studentEntity.getCategoryId();
- Long loginUserCategoryId = loginUser.getCategoryId();
- if (!studentCategoryId.equals(loginUserCategoryId)) {
- log.warn("[考生删除] student_id:{}, 所在教学点{},登录用户的教学点:{} ", studentId, studentCategoryId, loginUserCategoryId);
- throw new StatusException("不能删除其他教学点的考生科目信息");
- }
- }
- // 删除科目信息
- studentCourseService.removeById(studentCourseId);
- // 考生是否还有科目,没有科目,删除考生
- LambdaQueryWrapper<StudentCourseEntity> wrapper = new LambdaQueryWrapper<>();
- wrapper.eq(StudentCourseEntity::getStudentId, studentId);
- List<StudentCourseEntity> studentCourseList = studentCourseService.list(wrapper);
- if (CollectionUtils.isEmpty(studentCourseList)) {
- //删除考生信息
- this.removeById(studentId);
- } else {
- //更新考生的预约次数
- this.updateStudentApplyNumber(studentId);
- }
- // 清空缓存
- applyTaskCacheService.clearStudentApplyNumberCache(studentId);
- //写入日志
- operateLogService.insertOperateLog(loginUser.getId(), EventType.DELETE_STUDENT, String.join("-", studentId.toString(), studentCourseId.toString()));
- }
- }
- private List<StudentApplyEntity> getStudentApplyList(Long studentId) {
- LambdaQueryWrapper<StudentApplyEntity> wrapper = new LambdaQueryWrapper<>();
- wrapper.eq(StudentApplyEntity::getStudentId, studentId);
- wrapper.eq(StudentApplyEntity::getCancel, Boolean.FALSE);
- return studentApplyService.list(wrapper);
- }
- @Override
- public void modifyApplyNumber(Long studentId, Long operateId, Integer applyNumber) {
- if (applyNumber == null || applyNumber <= 0) {
- throw new StatusException("考生的预约次数必须大于0");
- }
- List<StudentApplyEntity> studentApplyList = getStudentApplyList(studentId);
- if (CollectionUtils.isNotEmpty(studentApplyList) && applyNumber < studentApplyList.size()) {
- throw new StatusException("考生已预约了" + studentApplyList.size() + "次,不能小于已经预约的次数");
- }
- LambdaUpdateWrapper<StudentEntity> updateWrapper = new LambdaUpdateWrapper<>();
- updateWrapper.eq(StudentEntity::getId, studentId);
- updateWrapper.set(StudentEntity::getApplyNumber, applyNumber);
- this.update(updateWrapper);
- //写入日志
- operateLogService.insertOperateLog(operateId, EventType.MODIFY_APPLY_NUMBER, studentId + "->" + applyNumber);
- }
- @Override
- public void uploadStudentPhotoAsync(Long operateId, MultipartFile file) throws IOException {
- ApplyTaskEntity applyTask = applyTaskService.findApplyTask();
- if (applyTask == null) {
- throw new StatusException("未开启预约任务,无法导入");
- }
- File tempFile = FileUtil.getFileTemp(".zip");
- if (tempFile != null) {
- file.transferTo(tempFile);
- }
- //写入异步任务
- Map<String, Object> taskMap = asyncTaskService.saveAsyncTask(AsyncTaskType.UPLOAD_STUDENT_PHOTO, operateId);
- taskMap.computeIfAbsent("taskId", v -> applyTask.getId());
- taskMap.computeIfAbsent("operateId", v -> operateId);
- try {
- studentPhotoUploadService.uploadTask(taskMap, tempFile);
- } catch (Exception e) {
- throw new StatusException(e.getMessage());
- }
- }
- @Override
- public void updateStudentApplyNumber(Long studentId) {
- baseMapper.updateStudentApplyNumber(studentId);
- }
- @Override
- public void uploadStudentPhoto(Long operateId, MultipartFile file) {
- //文件大小限制
- if (file.getSize() > Constants.FILE_SIZE_LIMIT) {
- throw new StatusException("上传的考生照片大小不能超过500KB");
- }
- OrgInfo org = orgCacheService.currentOrg();
- CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(org.getOrgId());
- if (curApplyTask == null) {
- throw new StatusException("未开启预约任务,无法导入");
- }
- //照片必须以考生的身份证命名
- String identityNumber = FileNameUtils.getBaseName(file.getOriginalFilename());
- LambdaQueryWrapper<StudentEntity> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.eq(StudentEntity::getIdentityNumber, identityNumber);
- queryWrapper.eq(StudentEntity::getApplyTaskId, curApplyTask.getTaskId());
- List<StudentEntity> studentList = this.list(queryWrapper);
- if (CollectionUtils.isEmpty(studentList)) {
- throw new StatusException("考生照片必须以考生的身份证命名");
- }
- StringJoiner stringJoiner = FileUtil.getDirName(false);
- String path = stringJoiner.toString().replaceAll("\\\\", "/");
- try {
- fileStore.write(path + file.getOriginalFilename(), file.getInputStream(), DigestUtils.md5Hex(file.getInputStream()));
- } catch (Exception e) {
- log.error("[上传考生头像],上传失败:{}", e.getMessage());
- throw new StatusException("考生头像上传失败,请稍后重试");
- }
- //更新考生照片路径
- List<Long> studentIds = studentList.stream().map(StudentEntity::getId).collect(Collectors.toList());
- LambdaUpdateWrapper<StudentEntity> updateWrapper = new LambdaUpdateWrapper<>();
- updateWrapper.set(StudentEntity::getPhotoPath, path + file.getOriginalFilename());
- updateWrapper.in(StudentEntity::getId, studentIds);
- this.update(null, updateWrapper);
- }
- }
|