package com.keao.edu.user.service.impl; import com.keao.edu.auth.api.entity.SysUser; import com.keao.edu.common.dal.BaseDAO; import com.keao.edu.common.enums.MessageTypeEnum; import com.keao.edu.common.exception.BizException; import com.keao.edu.common.page.PageInfo; import com.keao.edu.common.service.SysMessageService; import com.keao.edu.common.service.impl.BaseServiceImpl; import com.keao.edu.common.tenant.TenantContextHolder; import com.keao.edu.thirdparty.message.provider.YimeiSmsPlugin; import com.keao.edu.user.api.enums.ExamModeEnum; import com.keao.edu.user.dao.*; import com.keao.edu.user.dto.ExamRoomExamTimeDto; import com.keao.edu.user.dto.ExaminationBasicDto; import com.keao.edu.user.entity.*; import com.keao.edu.user.enums.ExamStatusEnum; import com.keao.edu.user.page.ExaminationQueryInfo; import com.keao.edu.user.service.ExamOrganizationRelationService; import com.keao.edu.user.service.ExaminationBasicService; import com.keao.edu.user.service.OrganizationService; import com.keao.edu.user.service.StudentExamResultService; import com.keao.edu.util.collection.MapUtil; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.time.LocalDate; import java.util.*; import java.util.stream.Collectors; @Service public class ExaminationBasicServiceImpl extends BaseServiceImpl implements ExaminationBasicService { @Autowired private ExaminationBasicDao examinationBasicDao; @Autowired private ExamOrganizationRelationService examOrganizationRelationService; @Autowired private ExamOrganizationRelationDao examOrganizationRelationDao; @Autowired private MusicTheoryDao musicTheoryDao; @Autowired private ExamMusicTheoryDao examMusicTheoryDao; @Autowired private ExamLocationDao examLocationDao; @Autowired private SysUserDao sysUserDao; @Autowired private OrganizationService organizationService; @Autowired private ExamLifecycleLogDao examLifecycleLogDao; @Autowired private SysMessageService sysMessageService; @Autowired private StudentExamResultService studentExamResultService; @Autowired private ExamRoomDao examRoomDao; @Autowired private TenantInfoDao tenantInfoDao; @Override public BaseDAO getDAO() { return examinationBasicDao; } @Override @Transactional(rollbackFor = Exception.class) public ExaminationBasic addExaminationBasic(ExaminationBasic examinationBasic) { if (StringUtils.isBlank(examinationBasic.getName())) { throw new BizException("请填写项目名称"); } if (Objects.isNull(examinationBasic.getExamMode())) { throw new BizException("请选择考试类型"); } if (ExamModeEnum.OFFLINE.equals(examinationBasic.getExamMode()) && StringUtils.isBlank(examinationBasic.getExamLocationIdList())) { throw new BizException("请指定考试地点"); } if (Objects.isNull(examinationBasic.getEnrollStartTime()) || Objects.isNull(examinationBasic.getEnrollEndTime())) { throw new BizException("请指定报名开始与结束时间"); } if(examinationBasic.getEnrollStartTime().compareTo(examinationBasic.getEnrollEndTime())>=0){ throw new BizException("报名时间异常"); } if(ExamModeEnum.ONLINE.equals(examinationBasic.getExamMode())){ examinationBasic.setExamLocationIdList(null); } if(StringUtils.isNotBlank(examinationBasic.getExamLocationIdList())){ List organIds = Arrays.stream(examinationBasic.getExamLocationIdList().split(",")).map(e -> Integer.valueOf(e)).collect(Collectors.toList()); Map organNameMap = this.getMap("exam_location", "id_", "name_", organIds, Integer.class, String.class); examinationBasic.setExamLocationNameList(StringUtils.join(organNameMap.values(),",")); } examinationBasic.setTenantId(TenantContextHolder.getTenantId()); examinationBasic.setEnrollStartTime(DateUtils.setSeconds(examinationBasic.getEnrollStartTime(), 0)); examinationBasic.setEnrollEndTime(DateUtils.setSeconds(examinationBasic.getEnrollEndTime(), 0)); examinationBasic.setExpectExamStartTime(DateUtils.setSeconds(examinationBasic.getExpectExamStartTime(), 0)); examinationBasic.setExpectExamEndTime(DateUtils.setSeconds(examinationBasic.getExpectExamEndTime(), 0)); List musicTheories = musicTheoryDao.getWithTenant(Integer.valueOf(examinationBasic.getTenantId())); if (CollectionUtils.isEmpty(musicTheories)) { throw new BizException("请设置乐理"); } examinationBasic.setStatus(ExamStatusEnum.SETTING); examinationBasicDao.insert(examinationBasic); examOrganizationRelationService.addExamOrganizations(examinationBasic.getId(),examinationBasic.getOrganId().toString()); List examMusicTheories = new ArrayList<>(); for (MusicTheory musicTheory : musicTheories) { ExamMusicTheory emt = new ExamMusicTheory(); emt.setExaminationBasicId(examinationBasic.getId()); emt.setTenantId(examinationBasic.getTenantId()); emt.setLevel(musicTheory.getLevel()); emt.setFee(musicTheory.getFee()); examMusicTheories.add(emt); } examMusicTheoryDao.batchInsert(examMusicTheories); examLifecycleLogDao.insert(new ExamLifecycleLog(examinationBasic.getId().intValue(), "创建项目", examinationBasic.getCreatorId())); return examinationBasic; } @Override public void updateExamStatus() { List exams = examinationBasicDao.getNeedUpdateStatusExams(); if (CollectionUtils.isEmpty(exams)) { return; } Date now = new Date(); for (ExaminationBasic exam : exams) { if (exam.getStatus().getOrder()= 0 && now.compareTo(exam.getEnrollEndTime()) <= 0) { exam.setStatus(ExamStatusEnum.APPLYING); examLifecycleLogDao.insert(new ExamLifecycleLog(exam.getId().intValue(), "报名已开启", null, "定时任务自动更新")); continue; }else if (exam.getStatus().getOrder()= 0) { exam.setStatus(ExamStatusEnum.APPLIED); examLifecycleLogDao.insert(new ExamLifecycleLog(exam.getId().intValue(), "报名已结束", null,"定时任务自动更新")); examOrganizationRelationService.examRegistCutOffPush(exam.getId()); continue; } if(Objects.nonNull(exam.getActualExamStartTime()) &&exam.getStatus().equals(ExamStatusEnum.APPLIED) &&now.compareTo(exam.getActualExamStartTime()) >= 0){ exam.setStatus(ExamStatusEnum.EXAM_ING); } if (Objects.nonNull(exam.getActualExamEndTime()) &&exam.getStatus().equals(ExamStatusEnum.EXAM_ING) &&now.compareTo(exam.getActualExamEndTime()) >= 0) { exam.setStatus(ExamStatusEnum.EXAM_END); } } examinationBasicDao.batchUpdate(exams); } @Override public void examEndRemind() { LocalDate today = LocalDate.now(); List endExams = examinationBasicDao.getEndExamsWithDayAndStatus(today.plusDays(-1).toString()); if(CollectionUtils.isEmpty(endExams)){ return; } Set tenantIds = endExams.stream().map(e->Integer.valueOf(e.getTenantId())).collect(Collectors.toSet()); List tenants = tenantInfoDao.getTenants(new ArrayList<>(tenantIds)); List phones = tenants.stream().map(TenantInfo::getContactPhone).collect(Collectors.toList()); Map idTenantMap = tenants.stream().collect(Collectors.toMap(TenantInfo::getId, e -> e)); List tenantUsers = sysUserDao.getWithPones(phones); Map phoneUserMap = tenantUsers.stream().collect(Collectors.toMap(SysUser::getPhone, t -> t)); for (ExaminationBasic endExam : endExams) { TenantInfo tenantInfo = idTenantMap.get(Integer.valueOf(endExam.getTenantId())); if(Objects.isNull(tenantInfo)){ continue; } SysUser sysUser = phoneUserMap.get(tenantInfo.getContactPhone()); if(Objects.isNull(sysUser)){ continue; } Map userPhoneMap = new HashMap<>(); userPhoneMap.put(sysUser.getId(), sysUser.getPhone()); sysMessageService.batchSendMessage(MessageTypeEnum.EXAM_END_REMIND, userPhoneMap, null, 0, null, YimeiSmsPlugin.PLUGIN_NAME, tenantInfo.getName(), endExam.getName()); } } @Override @Transactional(rollbackFor = Exception.class) public void updateExamBasicStatus(Long examId, ExamStatusEnum statusEnum, Integer operatorId) { if(Objects.isNull(examId)){ throw new BizException("请指定考级项目"); } ExaminationBasic existsExam = examinationBasicDao.get(examId); if(Objects.isNull(existsExam)){ throw new BizException("考级项目不存在"); } if(ExamStatusEnum.RESULT_CONFIRM.equals(existsExam.getStatus())){ throw new BizException("考级项目结果已确认"); } if(ExamStatusEnum.DELETE.equals(statusEnum)&&!ExamStatusEnum.SETTING.equals(existsExam.getStatus())){ throw new BizException("此状态不支持删除"); } if(ExamStatusEnum.DELETE.equals(statusEnum)){ examLifecycleLogDao.insert(new ExamLifecycleLog(existsExam.getId().intValue(), "删除考级项目", operatorId)); }else if(ExamStatusEnum.RESULT_CONFIRM.equals(statusEnum)){ if(ExamStatusEnum.EXAM_END.equals(existsExam.getStatus())){ throw new BizException("考试未结束"); } examLifecycleLogDao.insert(new ExamLifecycleLog(existsExam.getId().intValue(), "确认考试结果", operatorId)); studentExamResultService.examResultConfirmPush(examId); }else if(ExamStatusEnum.CLOSE.equals(statusEnum)){ examLifecycleLogDao.insert(new ExamLifecycleLog(existsExam.getId().intValue(), "关闭考级项目", operatorId)); examOrganizationRelationService.examStatusChangePush(examId, statusEnum); } if(ExamStatusEnum.CLOSE.equals(existsExam.getStatus())){ examLifecycleLogDao.insert(new ExamLifecycleLog(existsExam.getId().intValue(), "开启考级项目", operatorId)); } if(ExamStatusEnum.NOT_START.equals(existsExam.getStatus())&&ExamStatusEnum.APPLYING.equals(statusEnum)){ existsExam.setEnrollStartTime(new Date()); examLifecycleLogDao.insert(new ExamLifecycleLog(existsExam.getId().intValue(), "报名已开启", operatorId)); } if(ExamStatusEnum.APPLYING.equals(existsExam.getStatus())&&ExamStatusEnum.APPLIED.equals(statusEnum)){ existsExam.setEnrollEndTime(new Date()); examLifecycleLogDao.insert(new ExamLifecycleLog(existsExam.getId().intValue(), "关闭报名连接", operatorId)); examOrganizationRelationService.examStatusChangePush(examId, statusEnum); } existsExam.setStatus(statusEnum); examinationBasicDao.update(existsExam); } @Override public PageInfo findExaminationBasics(ExaminationQueryInfo queryInfo) { PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows()); Map params = new HashMap(); MapUtil.populateMap(params, queryInfo); List dataList = new ArrayList<>(); int count = examinationBasicDao.countExaminationBasics(params); if (count > 0) { pageInfo.setTotal(count); params.put("offset", pageInfo.getOffset()); dataList = examinationBasicDao.findExaminationBasics(params); List examIds = dataList.stream().map(ExaminationBasicDto::getId).collect(Collectors.toList()); List examOrgans = new ArrayList<>(); if (!CollectionUtils.isEmpty(examIds)) { List childOrganIds = organizationService.getChildOrganIds(queryInfo.getOrganId(), true); examOrgans = examOrganizationRelationDao.getWithExamsAndOrgans(examIds, childOrganIds); } Map> examOrgansMap = new HashMap<>(); if (!CollectionUtils.isEmpty(examOrgans)) { examOrgansMap = examOrgans.stream().collect(Collectors.groupingBy(ExamOrganizationRelation::getExaminationBasicId)); } for (ExaminationBasicDto examinationBasicDto : dataList) { List examOrganizationRelations = examOrgansMap.get(examinationBasicDto.getId().intValue()); if (CollectionUtils.isEmpty(examOrganizationRelations)) { continue; } Integer totalRegistrationStudentNum = examOrganizationRelations.stream().mapToInt(ExamOrganizationRelation::getSelfRegistrationStudentNum).sum(); BigDecimal totalPaymentAmount = examOrganizationRelations.stream().map(ExamOrganizationRelation::getSelfPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add); examinationBasicDto.setTotalRegistrationStudentNum(totalRegistrationStudentNum); examinationBasicDto.setTotalPaymentAmount(totalPaymentAmount); } } pageInfo.setRows(dataList); return pageInfo; } @Override @Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED) public ExaminationBasicDto getExaminationBasic(Integer examId) { if (Objects.isNull(examId)) { throw new BizException("请指定考级项目"); } ExaminationBasicDto examinationBasic = examinationBasicDao.getExaminationBasic(examId); if (Objects.isNull(examinationBasic)) { throw new BizException("指定的考级项目不存在"); } List examOrganizationRelations = examOrganizationRelationDao.getWithExam(examId); if (!CollectionUtils.isEmpty(examOrganizationRelations)) { Integer totalRegistrationStudentNum = examOrganizationRelations.stream().mapToInt(ExamOrganizationRelation::getTotalRegistrationStudentNum).sum(); BigDecimal totalPaymentAmount = examOrganizationRelations.stream().map(ExamOrganizationRelation::getTotalPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add); examinationBasic.setTotalRegistrationStudentNum(totalRegistrationStudentNum); examinationBasic.setTotalPaymentAmount(totalPaymentAmount); examinationBasic.setOrganNum(examOrganizationRelations.size()); } if(Objects.nonNull(examinationBasic.getCreatorId())){ SysUser sysUser = sysUserDao.get(examinationBasic.getCreatorId()); examinationBasic.setCreatorName(sysUser.getRealName()); } return examinationBasic; } @Override @Transactional(rollbackFor = Exception.class) public void updateExam(ExaminationBasic examinationBasic,Integer operatorId) { if(Objects.isNull(examinationBasic.getId())){ throw new BizException("请指定考级项目"); } ExaminationBasic existsExam = examinationBasicDao.get(examinationBasic.getId().longValue()); if(Objects.isNull(existsExam)){ throw new BizException("考级项目不存在"); } if(ExamStatusEnum.RESULT_CONFIRM.equals(existsExam.getStatus())){ throw new BizException("考级项目结果已确认"); } if(ExamStatusEnum.CLOSE.equals(existsExam.getStatus())){ throw new BizException("考级项目已关闭"); } if(ExamModeEnum.ONLINE.equals(examinationBasic.getExamMode())){ examinationBasic.setExamLocationIdList(null); } if(StringUtils.isNotBlank(examinationBasic.getExamLocationIdList())){ List organIds = Arrays.stream(examinationBasic.getExamLocationIdList().split(",")).map(e -> Integer.valueOf(e)).collect(Collectors.toList()); Map organNameMap = this.getMap("exam_location", "id_", "name_", organIds, Integer.class, String.class); examinationBasic.setExamLocationNameList(StringUtils.join(organNameMap.values(),",")); } boolean examRegistIsChange=false; if(Objects.nonNull(examinationBasic.getEnrollStartTime()) &&examinationBasic.getEnrollStartTime().compareTo(existsExam.getEnrollStartTime())!=0){ if(ExamStatusEnum.EXAM_ING.equals(existsExam.getStatus())|| ExamStatusEnum.EXAM_END.equals(existsExam.getStatus())){ throw new BizException("无法修改"); } examLifecycleLogDao.insert(new ExamLifecycleLog(existsExam.getId().intValue(), "修改报名时间", operatorId)); examRegistIsChange=true; } if(Objects.nonNull(examinationBasic.getEnrollEndTime()) &&examinationBasic.getEnrollEndTime().compareTo(existsExam.getEnrollEndTime())!=0){ if(ExamStatusEnum.EXAM_ING.equals(existsExam.getStatus())|| ExamStatusEnum.EXAM_END.equals(existsExam.getStatus())){ throw new BizException("无法修改"); } ExamRoomExamTimeDto examRoomExamTime = examRoomDao.getExamRoomExamTime(examinationBasic.getId()); if(Objects.nonNull(examRoomExamTime)&&examinationBasic.getEnrollEndTime().compareTo(examRoomExamTime.getExamStartTime())>0){ throw new BizException("报名结束时间不得在考试开始时间之后"); } examLifecycleLogDao.insert(new ExamLifecycleLog(existsExam.getId().intValue(), "修改报名时间", operatorId)); examRegistIsChange=true; } if(Objects.nonNull(examinationBasic.getEnrollStartTime())&&Objects.nonNull(examinationBasic.getEnrollEndTime())&&!ExamStatusEnum.SETTING.equals(existsExam.getStatus())){ if(examinationBasic.getEnrollStartTime().compareTo(examinationBasic.getEnrollEndTime())>=0){ throw new BizException("参数错误"); } Date now=new Date(); if(examinationBasic.getEnrollStartTime().compareTo(now)>0){ examinationBasic.setStatus(ExamStatusEnum.NOT_START); }else if(examinationBasic.getEnrollEndTime().compareTo(now)<0){ examinationBasic.setStatus(ExamStatusEnum.APPLIED); }else{ examinationBasic.setStatus(ExamStatusEnum.APPLYING); } } examinationBasic.setActualExamStartTime(existsExam.getActualExamStartTime()); examinationBasic.setActualExamEndTime(existsExam.getActualExamEndTime()); examinationBasicDao.update(examinationBasic); if(examRegistIsChange){ examOrganizationRelationService.examDateChangePush(examinationBasic.getId()); } } @Override public void closeExam(Integer organId, Integer examId, String reason) { if (Objects.isNull(examId)) { throw new BizException("请指定考级项目"); } ExaminationBasic examinationBasic = examinationBasicDao.get(examId.longValue()); if (Objects.isNull(examinationBasic)) { throw new BizException("考级项目不存在"); } List childOrganIds = organizationService.getChildOrganIds(organId, true); if(Objects.nonNull(childOrganIds)&&!childOrganIds.contains(examinationBasic.getOrganId())){ throw new BizException("删除失败"); } if (StringUtils.isBlank(reason)) { reason = "后台手动关闭"; } examinationBasic.setMemo(reason); examinationBasic.setStatus(ExamStatusEnum.CLOSE); examinationBasicDao.update(examinationBasic); examOrganizationRelationService.examStatusChangePush(examId.longValue(), ExamStatusEnum.CLOSE); } @Override public ExaminationBasic getInfo(Integer examId) { ExaminationBasic examinationBasic = examinationBasicDao.get(examId.longValue()); if (examinationBasic == null) { throw new BizException("考试项目不存在,请核对"); } if (!StringUtils.isBlank(examinationBasic.getExamLocationIdList())) { List examLocations = examLocationDao.getExamLocationByIds(examinationBasic.getExamLocationIdList()); examinationBasic.setExamLocations(examLocations); } return examinationBasic; } }