package nju.seec.helper.service.impl; import nju.seec.helper.dao.ChooseDAO; import nju.seec.helper.dao.CourseDAO; import nju.seec.helper.dao.UserDAO; import nju.seec.helper.dto.course.ChooseDTO; import nju.seec.helper.dto.course.CourseDTO; import nju.seec.helper.dto.user.LoginUser; import nju.seec.helper.entity.Choose; import nju.seec.helper.entity.Course; import nju.seec.helper.service.CourseService; import nju.seec.helper.service.util.AuthUtils; import nju.seec.helper.service.util.StringUtils; import nju.seec.helper.util.EncryptUtils; import nju.seec.helper.util.enums.ExceptionType; import nju.seec.helper.util.exception.HelperException; import nju.seec.helper.vo.CourseVO; import nju.seec.helper.vo.UserVO; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.persistence.criteria.JoinType; import java.util.Set; /** * @author cst */ @Service public class CourseServiceImpl implements CourseService { private final UserDAO userDAO; private final CourseDAO courseDAO; private final ChooseDAO chooseDAO; public CourseServiceImpl(UserDAO userDAO, CourseDAO courseDAO, ChooseDAO chooseDAO) { this.userDAO = userDAO; this.courseDAO = courseDAO; this.chooseDAO = chooseDAO; } @Transactional(rollbackFor = Exception.class) @Override public CourseVO createCourse(LoginUser teacher, CourseDTO courseDTO) { // 检查 checkSameCourseName(0L, teacher.getId(), courseDTO.getName()); Course course = new Course() .setTeacher(userDAO.findUserById(teacher.getId())) .setName(courseDTO.getName()) .setBio(courseDTO.getBio()) .setCode(EncryptUtils.encode(courseDTO.getCode())); course = courseDAO.save(course); return new CourseVO(course); } @Transactional(rollbackFor = Exception.class) @Override public CourseVO modifyCourse(LoginUser user, Long courseId, CourseDTO courseDTO) { Course course = courseDAO.findCourseById(courseId); // 检查 AuthUtils.checkDataAuth(user.getId(), course.getTeacher().getId(), "您无权修改该课程"); checkSameCourseName(course.getId(), user.getId(), courseDTO.getName()); course.setName(courseDTO.getName()) .setBio(courseDTO.getBio()) .setCode(EncryptUtils.encode(courseDTO.getCode())); course = courseDAO.save(course); return new CourseVO(course); } @Transactional(rollbackFor = Exception.class) @Override public void removeCourse(LoginUser user, Long courseId) { Course course = courseDAO.findCourseById(courseId); AuthUtils.checkDataAuth(user.getId(), course.getTeacher().getId(), "您无权删除该课程"); course.setDeleteAt(System.currentTimeMillis()); courseDAO.save(course); } @Transactional(rollbackFor = Exception.class) @Override public void chooseCourse(LoginUser student, Long courseId, ChooseDTO chooseDTO) { Long studentId = student.getId(); if (chooseDAO.existsByStudentIdAndCourseId(studentId, courseId)) { throw HelperException.of(ExceptionType.CONFLICT, "您已选课"); } if (!courseDAO.existsByIdAndCode(courseId, EncryptUtils.encode(chooseDTO.getCode()))) { throw HelperException.of(ExceptionType.NOT_FOUND, "选课码错误"); } Choose choose = new Choose() .setCourseId(courseId) .setStudentId(studentId); chooseDAO.save(choose); } @Transactional(rollbackFor = Exception.class) @Override public void quitCourse(LoginUser user, Long courseId) { chooseDAO.deleteByStudentIdAndCourseId(user.getId(), courseId); } @Transactional(readOnly = true) @Override public Page getCourses(String key, Pageable pageable) { return findByKey(key, pageable).map(CourseVO::new); } @Transactional(readOnly = true) @Override public Page getCourses(LoginUser user, String key, Pageable pageable) { switch (user.getType()) { case TEACHER: return teacherGetCourses(user.getId(), key, pageable); case STUDENT: return studentGetCourses(user.getId(), key, pageable); default: return Page.empty(); } } private Page teacherGetCourses(Long teacherId, String key, Pageable pageable) { return findByTeacherIdAndKey(teacherId, key, pageable).map(CourseVO::new); } private Page studentGetCourses(Long studentId, String key, Pageable pageable) { return findByIdsAndKey(chooseDAO.findCourseIdsByStudentId(studentId), key, pageable).map(CourseVO::new); } @Transactional(readOnly = true) @Override public String getCourseCode(LoginUser user, Long courseId) { Course course = courseDAO.findCourseById(courseId); AuthUtils.checkDataAuth(user.getId(), course.getTeacher().getId(), "您无权获取该课程选课码"); return EncryptUtils.decode(course.getCode()); } @Transactional(readOnly = true) @Override public CourseVO getOneCourse(Long courseId) { return new CourseVO(courseDAO.findCourseById(courseId)); } @Transactional(readOnly = true) @Override public Page getChooseStudents(LoginUser user, Long courseId, String key, Pageable pageable) { Course course = courseDAO.findCourseById(courseId); AuthUtils.checkDataAuth(user.getId(), course.getTeacher().getId(), "您无权获取该课程的选课名单"); return userDAO.findByIdIn(chooseDAO.findStudentIdsByCourseId(courseId), pageable).map(UserVO::new); } @Override public boolean existsCourseResourcesGetAuth(LoginUser user, Long courseId) { switch (user.getType()) { case TEACHER: return courseDAO.findCourseById(courseId).getTeacher().getId().equals(user.getId()); case STUDENT: return chooseDAO.existsByStudentIdAndCourseId(user.getId(), courseId); default: return false; } } private void checkSameCourseName(Long courseId, Long teacherId, String name) { long exists = courseDAO.count((Specification) (root, query, cb) -> cb.and(cb.notEqual(root.get("id"), courseId) , cb.equal(root.get("teacher").get("id"), teacherId) , cb.equal(root.get("deleteAt"), 0L) , cb.equal(root.get("name"), name) )); if (exists > 0) { throw HelperException.of(ExceptionType.CONFLICT, "该课程名已使用"); } } private Page findByTeacherIdAndKey(Long teacherId, String key, Pageable pageable) { return courseDAO.findAll( (Specification) (root, query, cb) -> cb.and( cb.equal(root.get("teacher").get("id"), teacherId) , cb.equal(root.get("deleteAt"), 0L) // , cb.like(root.get("name"), StringUtils.keyPattern(key)) ), pageable); } private Page findByKey(String key, Pageable pageable) { final String keyPattern = StringUtils.keyPattern(key); return courseDAO.findAll( (Specification) (root, query, cb) -> cb.and( cb.equal(root.get("deleteAt"), 0L) , cb.or(cb.like(root.get("name"), keyPattern), cb.like(root.join("teacher", JoinType.LEFT).get("name"), keyPattern)) ), pageable); } private Page findByIdsAndKey(Set courseIds, String key, Pageable pageable) { final String keyPattern = StringUtils.keyPattern(key); return courseDAO.findAll( (Specification) (root, query, cb) -> cb.and( root.get("id").in(courseIds) , cb.equal(root.get("deleteAt"), 0L) , cb.or(cb.like(root.get("name"), keyPattern), cb.like(root.join("teacher", JoinType.LEFT).get("name"), keyPattern)) ), pageable); } }