cnas-personnel/src/main/java/com/ruoyi/personnel/service/impl/PersonTrainingServiceImpl.java
@@ -33,6 +33,7 @@
import com.ruoyi.personnel.pojo.PersonTraining;
import com.ruoyi.personnel.pojo.PersonTrainingDetailed;
import com.ruoyi.personnel.pojo.PersonTrainingDetailedFile;
import com.ruoyi.personnel.pojo.PersonTrainingRecord;
import com.ruoyi.personnel.service.PersonTrainingDetailedService;
import com.ruoyi.personnel.service.PersonTrainingService;
import com.ruoyi.system.mapper.UserMapper;
@@ -57,6 +58,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
 * <p>
@@ -98,50 +100,32 @@
    @Override
    public void personTrainingImport(MultipartFile file, PersonTraining training) {
        if (file == null || file.isEmpty()) {
            throw new ErrorException("请选择导入文件");
        }
        if (training == null || StringUtils.isBlank(training.getPlanYear())) {
            throw new ErrorException("请选择计划年份");
        }
        if (training.getReviewerId() == null) {
            throw new ErrorException("请选择审核人");
        }
        String originalFilename = file.getOriginalFilename();
        if (StringUtils.isBlank(originalFilename)) {
            throw new ErrorException("文件名不能为空");
        }
        Integer userId = SecurityUtils.getUserId().intValue();
        // 年度计划父级新增数据
        PersonTraining personSupervisePlan = new PersonTraining();
        String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf("."));
        String fileName = originalFilename.contains(".")
                ? originalFilename.substring(0, originalFilename.lastIndexOf("."))
                : originalFilename;
        personSupervisePlan.setFileName(fileName);
        personSupervisePlan.setPlanYear(training.getPlanYear());
        personSupervisePlan.setCompilerId(userId);
        personSupervisePlan.setReviewerId(training.getReviewerId());
        personSupervisePlan.setCompilationDate(LocalDateTime.now());
        baseMapper.insert(personSupervisePlan);
        User user = userMapper.selectById(userId);
        // 消息发送
        InformationNotification info = new InformationNotification();
        // 发送人
        info.setCreateUser(user.getName());
        info.setMessageType("6");
        info.setTheme("CNAS培训计划审核通知");
        info.setContent("您有一条培训计划待审核");
        info.setSenderId(userId);
        // 接收人
        info.setConsigneeId(training.getApproverId());
        info.setJumpPath(MenuJumpPathConstants.PERSONNEL);
        informationNotificationService.addInformationNotification(info);
        // 发送企业微信通知
        threadPoolTaskExecutor.execute(() -> {
            // 查询接收人
            User personnel = userMapper.selectById(training.getApproverId());
            String message = "";
            message += "CNAS培训计划审核通知";
            message += "\n请去资源管理-人员-培训计划填写";
            message += "\n" + fileName + "的培训计划待审核";
            //发送企业微信消息通知(接收人不存在或发送失败不影响导入流程)
            if (personnel == null || StringUtils.isBlank(personnel.getAccount())) {
                return;
            }
            try {
                WxCpUtils.inform(personnel.getAccount(), message, null);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        // 年度计划详情 新增
        try {
@@ -149,65 +133,138 @@
            personSupervisePlanDetailsListener.setPlanId(personSupervisePlan.getId());
            EasyExcel.read(file.getInputStream(), PersonTrainingDetailedUpload.class, personSupervisePlanDetailsListener).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
            throw new ErrorException("读取导入文件失败,请检查文件格式");
        }
        User user = userMapper.selectById(userId);
        // 消息发送(接收人为选定的审核人)
        InformationNotification info = new InformationNotification();
        info.setCreateUser(user != null ? user.getName() : "");
        info.setMessageType("6");
        info.setTheme("CNAS培训计划审核通知");
        info.setContent("您有一条培训计划待审核");
        info.setSenderId(userId);
        info.setConsigneeId(training.getReviewerId());
        info.setJumpPath(MenuJumpPathConstants.PERSONNEL);
        informationNotificationService.addInformationNotification(info);
        // 发送企业微信通知(接收人不存在或发送失败不影响导入流程)
        threadPoolTaskExecutor.execute(() -> {
            User personnel = userMapper.selectById(training.getReviewerId());
            if (personnel == null || StringUtils.isBlank(personnel.getAccount())) {
                return;
            }
            String message = "";
            message += "CNAS培训计划审核通知";
            message += "\n请去资源管理-人员-培训计划填写";
            message += "\n" + fileName + "的培训计划待审核";
            try {
                WxCpUtils.inform(personnel.getAccount(), message, null);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
    @Override
    public void personTrainingDelete(Integer id) {
        personTrainingDetailedService.remove(Wrappers.<PersonTrainingDetailed>lambdaQuery()
        if (id == null) {
            throw new ErrorException("缺少计划id");
        }
        List<PersonTrainingDetailed> details = personTrainingDetailedService.list(Wrappers.<PersonTrainingDetailed>lambdaQuery()
                .eq(PersonTrainingDetailed::getPlanId, id));
        if (!details.isEmpty()) {
            List<Integer> detailIds = details.stream().map(PersonTrainingDetailed::getId).collect(Collectors.toList());
            // 连同明细下的培训记录、附件一起删除,避免留下孤儿数据
            personTrainingRecordMapper.delete(Wrappers.<PersonTrainingRecord>lambdaQuery()
                    .in(PersonTrainingRecord::getCourseId, detailIds));
            personTrainingDetailedFileMapper.delete(Wrappers.<PersonTrainingDetailedFile>lambdaQuery()
                    .in(PersonTrainingDetailedFile::getTrainingDetailedId, detailIds));
            personTrainingDetailedService.remove(Wrappers.<PersonTrainingDetailed>lambdaQuery()
                    .eq(PersonTrainingDetailed::getPlanId, id));
        }
        baseMapper.deleteById(id);
    }
    @Override
    public void reviewAnnualPersonnelTraining(PersonTraining training) {
        PersonTraining personTraining = new PersonTraining();
        personTraining.setId(training.getId());
        personTraining.setApproverId(training.getApproverId());// 添加批准人
        personTraining.setAuditDate(LocalDateTime.now());
        personTraining.setAuditRemarks(training.getAuditRemarks());
        personTraining.setReviewerStatus(training.getReviewerStatus());
        if (training == null || training.getId() == null) {
            throw new ErrorException("缺少计划id");
        }
        if (!Integer.valueOf(1).equals(training.getReviewerStatus()) && !Integer.valueOf(2).equals(training.getReviewerStatus())) {
            throw new ErrorException("审核结果不正确");
        }
        PersonTraining old = baseMapper.selectById(training.getId());
        if (old == null) {
            throw new ErrorException("培训计划不存在或已被删除");
        }
        if (Integer.valueOf(1).equals(old.getReviewerStatus())) {
            throw new ErrorException("该计划已审核通过,请勿重复审核");
        }
        boolean passed = Integer.valueOf(1).equals(training.getReviewerStatus());
        if (passed && training.getApproverId() == null) {
            throw new ErrorException("请选择批准人");
        }
        // 消息发送
        baseMapper.update(null, Wrappers.<PersonTraining>lambdaUpdate()
                .eq(PersonTraining::getId, training.getId())
                .set(PersonTraining::getApproverId, passed ? training.getApproverId() : null)
                .set(PersonTraining::getAuditDate, LocalDateTime.now())
                .set(PersonTraining::getAuditRemarks, training.getAuditRemarks())
                .set(PersonTraining::getReviewerStatus, training.getReviewerStatus()));
        // 只有审核通过才通知批准人
        if (!passed) {
            return;
        }
        Integer userId = SecurityUtils.getUserId().intValue();
        User user = userMapper.selectById(userId);
        InformationNotification info = new InformationNotification();
        // 发送人
        info.setCreateUser(user.getName());
        info.setCreateUser(user != null ? user.getName() : "");
        info.setMessageType("6");
        info.setTheme("CNAS培训计划审核通知");
        info.setContent("您有一条培训计划待批准");
        info.setSenderId(userId);
        // 接收人
        info.setConsigneeId(training.getApproverId());
        info.setJumpPath(MenuJumpPathConstants.PERSONNEL);
        informationNotificationService.addInformationNotification(info);
        // 发送企业微信通知
        threadPoolTaskExecutor.execute(() -> {
            // 查询接收人
            User personnel = userMapper.selectById(training.getApproverId());
            if (personnel == null || StringUtils.isBlank(personnel.getAccount())) {
                return;
            }
            String message = "";
            message += "CNAS培训计划批准通知";
            message += "\n请去资源管理-人员-培训计划填写";
            message += "\n" + old.getFileName() + "的培训计划待批准";
            //发送企业微信消息通知
            try {
                WxCpUtils.inform(personnel.getAccount(), message, null);
            } catch (Exception e) {
                throw new RuntimeException(e);
                e.printStackTrace();
            }
        });
        baseMapper.updateById(personTraining);
    }
    @Override
    public void approveAnnualPersonnelTraining(PersonTraining training) {
        if (training == null || training.getId() == null) {
            throw new ErrorException("缺少计划id");
        }
        if (!Integer.valueOf(1).equals(training.getApprovalStatus()) && !Integer.valueOf(2).equals(training.getApprovalStatus())) {
            throw new ErrorException("批准结果不正确");
        }
        PersonTraining old = baseMapper.selectById(training.getId());
        if (old == null) {
            throw new ErrorException("培训计划不存在或已被删除");
        }
        if (!Integer.valueOf(1).equals(old.getReviewerStatus())) {
            throw new ErrorException("该计划尚未审核通过,不能批准");
        }
        if (Integer.valueOf(1).equals(old.getApprovalStatus())) {
            throw new ErrorException("该计划已批准,请勿重复操作");
        }
        LambdaUpdateWrapper<PersonTraining> wrapper = Wrappers.<PersonTraining>lambdaUpdate()
                .eq(PersonTraining::getId, training.getId())
                .set(PersonTraining::getApprovalDate, LocalDateTime.now())
@@ -224,30 +281,48 @@
    @Override
    public void exportPersonTraining(Integer id, HttpServletResponse response) {
        if (id == null) {
            throw new ErrorException("缺少计划id");
        }
        // 查询详情
        PersonTraining personTraining = baseMapper.selectById(id);
        //获取提交人的签名地址
        String writeUrl = userMapper.selectById(personTraining.getCompilerId()).getSignatureUrl();
        if (ObjectUtils.isEmpty(writeUrl) || writeUrl.equals("")) {
            throw new ErrorException("找不到检验人的签名");
        if (personTraining == null) {
            throw new ErrorException("培训计划不存在或已被删除");
        }
        //获取复核人的签名地址
        //获取编制人的签名地址
        User compiler = userMapper.selectById(personTraining.getCompilerId());
        String writeUrl = compiler != null ? compiler.getSignatureUrl() : null;
        if (StringUtils.isBlank(writeUrl)) {
            throw new ErrorException("编制人未上传签名,暂无法导出");
        }
        if (!new File(imgUrl + "/" + writeUrl).exists()) {
            throw new ErrorException("编制人的签名图片不存在,请重新上传签名");
        }
        //获取审核人的签名地址
        String examineUrl = null;
        if (personTraining.getReviewerId() != null) {
            examineUrl = userMapper.selectById(personTraining.getReviewerId()).getSignatureUrl();
            User reviewer = userMapper.selectById(personTraining.getReviewerId());
            examineUrl = reviewer != null ? reviewer.getSignatureUrl() : null;
            if (StringUtils.isBlank(examineUrl)) {
                throw new ErrorException("找不到复核人的签名");
                throw new ErrorException("审核人未上传签名,暂无法导出");
            }
            if (!new File(imgUrl + "/" + examineUrl).exists()) {
                throw new ErrorException("审核人的签名图片不存在,请重新上传签名");
            }
        }
        //获取批准人的签名地址
        String ratifyUrl = null;
        if (personTraining.getApproverId() != null) {
            ratifyUrl = userMapper.selectById(personTraining.getApproverId()).getSignatureUrl();
            User approver = userMapper.selectById(personTraining.getApproverId());
            ratifyUrl = approver != null ? approver.getSignatureUrl() : null;
            if (StringUtils.isBlank(ratifyUrl)) {
                throw new ErrorException("找不到复核人的签名");
                throw new ErrorException("批准人未上传签名,暂无法导出");
            }
            if (!new File(imgUrl + "/" + ratifyUrl).exists()) {
                throw new ErrorException("批准人的签名图片不存在,请重新上传签名");
            }
        }
@@ -307,8 +382,14 @@
     */
    @Override
    public void exportPersonTrainingRecord(Integer id, HttpServletResponse response) {
        if (id == null) {
            throw new ErrorException("缺少培训明细id");
        }
        // 查询人员培训明细
        PersonTrainingDetailedDto detailedDto = personTrainingDetailedMapper.selectTrainingDetail(id);
        if (detailedDto == null) {
            throw new ErrorException("培训记录不存在或已被删除");
        }
        // 生成培训老师签名(未配置签名时用透明图片兜底,模板里的图片占位不能为 null)
        detailedDto.setTrainingLecturerRender(UserUtils.orTransparentPicture(