Эх сурвалжийг харах

Merge remote-tracking branch 'origin/dev_v3.4.2' into dev_v3.4.2

wangliang 7 сар өмнө
parent
commit
dc19431b42

+ 0 - 3
distributed-print-business/src/main/java/com/qmth/distributed/print/business/bean/dto/ExamTaskPaperExportDto.java

@@ -78,9 +78,6 @@ public class ExamTaskPaperExportDto implements Serializable {
         this.courseName = examTaskDetailDto.getCourseName();
         this.courseCode = examTaskDetailDto.getCourseCode();
         this.paperNumber = examTaskDetailDto.getPaperNumber();
-        this.paperType = examTaskDetailDto.getPaperType();
-        this.exposedPaperType = examTaskDetailDto.getExposedPaperType();
-        this.unexposedPaperType = examTaskDetailDto.getUnexposedPaperType();
     }
 
     public String getExposedPaperType() {

+ 50 - 59
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/DownloadServiceImpl.java

@@ -86,16 +86,13 @@ public class DownloadServiceImpl implements DownloadService {
     @Override
     public void paperDownload(HttpServletResponse response, Long id) {
         ExamTask examTask = examTaskService.getByIdIncludeCourse(id);
-        QueryWrapper<ExamTaskDetail> queryWrapper = new QueryWrapper<>();
-        queryWrapper.lambda().eq(ExamTaskDetail::getExamTaskId, id);
-        ExamTaskDetail examTaskDetail = examTaskDetailMapper.selectOne(queryWrapper);
-        if (examTaskDetail == null) {
-            throw ExceptionResultEnum.ERROR.exception("数据异常");
+        List<ExamTaskDetail> examTaskDetailList = examTaskDetailService.listByExamTaskId(id);
+        if (CollectionUtils.isEmpty(examTaskDetailList)) {
+            throw ExceptionResultEnum.ERROR.exception("未找到试卷");
         }
-        // 只下载未曝光试卷
-        String unexposedPaperType = examTaskDetail.getUnexposedPaperType();
-        if (StringUtils.isBlank(unexposedPaperType)) {
-            throw ExceptionResultEnum.ERROR.exception("没有未曝光试卷,无法下载");
+        List<ExamTaskDetail> examTaskDetails = examTaskDetailList.stream().filter(m -> m.getExposed() == null || !m.getExposed()).collect(Collectors.toList());
+        if (CollectionUtils.isEmpty(examTaskDetails)) {
+            throw ExceptionResultEnum.ERROR.exception("没有未曝光试卷");
         }
 
         // 收集处理试卷和题卡
@@ -106,62 +103,56 @@ public class DownloadServiceImpl implements DownloadService {
             fileTemp = SystemConstant.getFileTempVar(SystemConstant.ZIP_PREFIX);
             rootPath = fileTemp.getParent() + File.separator + System.currentTimeMillis();
             List<File> fileList = new ArrayList<>();
-            List<String> unexposedPaperTypes = Arrays.asList(unexposedPaperType.split(","));
-            List<PaperInfoVo> paperInfoDtoList = ExamTaskUtil.parsePaperAttachmentPath(examTaskDetail.getPaperAttachmentIds());
-            if (CollectionUtils.isEmpty(paperInfoDtoList)) {
-                throw ExceptionResultEnum.ERROR.exception("试卷信息不存在");
-            }
-
-            for (PaperInfoVo paperInfo : paperInfoDtoList) {
-                String paperType = paperInfo.getName();
-                if (!unexposedPaperTypes.contains(paperType)) {
-                    continue;
-                }
-
-                // 试卷附件id
-                String attachmentId = paperInfo.getAttachmentId();
-                if (StringUtils.isNotBlank(attachmentId)) {
-                    // 试卷
-                    BasicAttachment attachment = basicAttachmentMapper.selectById(attachmentId);
-                    if (attachment == null) {
-                        throw ExceptionResultEnum.ERROR.exception("附件数据异常");
+            for (ExamTaskDetail examTaskDetail : examTaskDetails) {
+                List<PaperInfoVo> paperInfoDtoList = ExamTaskUtil.parsePaperAttachmentPath(examTaskDetail.getPaperAttachmentIds());
+                for (PaperInfoVo paperInfo : paperInfoDtoList) {
+                    String paperType = paperInfo.getName();
+                    // 试卷附件id
+                    String attachmentId = paperInfo.getAttachmentId();
+                    if (StringUtils.isNotBlank(attachmentId)) {
+                        // 试卷
+                        BasicAttachment attachment = basicAttachmentMapper.selectById(attachmentId);
+                        if (attachment == null) {
+                            throw ExceptionResultEnum.ERROR.exception("附件数据异常");
+                        }
+                        String paperPath = rootPath + File.separator + examTask.getCourseName().replaceAll(" ", "") + SystemConstant.HYPHEN + examTask.getCourseCode() + File.separator + examTask.getPaperNumber();
+                        String fileName = "卷" + examTaskDetail.getSerialNumber() + SystemConstant.HYPHEN + "试卷" + SystemConstant.HYPHEN + attachment.getName() + SystemConstant.HYPHEN + paperType + attachment.getType();
+                        fileList.add(attachmentCommonService.downloadFile(paperPath, fileName, attachment));
                     }
-                    String paperPath = rootPath + File.separator + examTask.getCourseName().replaceAll(" ", "") + SystemConstant.HYPHEN + examTask.getCourseCode() + File.separator + examTask.getPaperNumber();
-                    String fileName = "试卷" + "_" + attachment.getName() + "_" + paperType + attachment.getType();
-                    fileList.add(attachmentCommonService.downloadFile(paperPath, fileName, attachment));
-                }
 
-                // 题卡id
-                String cardId = paperInfo.getCardId();
-                // 题卡
-                if (StringUtils.isNotBlank(cardId)) {
-                    ExamCard examCard = examCardMapper.selectById(cardId);
-
-                    String cardPath = rootPath + File.separator + examTask.getCourseName().replaceAll(" ", "") + SystemConstant.HYPHEN + examTask.getCourseCode() + File.separator + examTask.getPaperNumber();
-                    String cardHtmlPath = cardPath + File.separator + "题卡" + "_" + examTask.getCourseName() + "_" + paperType + SystemConstant.HTML_PREFIX;
-                    String cardPdfPath = cardPath + File.separator + "题卡" + "_" + examTask.getCourseName() + "_" + paperType + SystemConstant.PDF_PREFIX;
-
-                    // html
-                    File htmlFile = new File(cardHtmlPath);
-                    if (!htmlFile.exists()) {
-                        htmlFile.getParentFile().mkdirs();
-                        htmlFile.createNewFile();
-                    }
-                    String htmlContent = createPdfUtil.replaceBlankHtmlContent(examCard.getHtmlContent(), examCard.getCourseId());
-                    // 生成html文件
-                    FileCopyUtils.copy(htmlContent.getBytes(StandardCharsets.UTF_8), htmlFile);
-                    fileList.add(htmlFile);
-                    // 转pdf文件
-                    File pdfFile = new File(cardPdfPath);
-                    if (!pdfFile.exists()) {
-                        pdfFile.getParentFile().mkdirs();
-                        pdfFile.createNewFile();
+                    // 题卡id
+                    String cardId = paperInfo.getCardId();
+                    // 题卡
+                    if (StringUtils.isNotBlank(cardId)) {
+                        ExamCard examCard = examCardMapper.selectById(cardId);
+
+                        String cardPath = rootPath + File.separator + examTask.getCourseName().replaceAll(" ", "") + SystemConstant.HYPHEN + examTask.getCourseCode() + File.separator + examTask.getPaperNumber();
+                        String cardHtmlPath = cardPath + File.separator + "卷" + examTaskDetail.getSerialNumber() + SystemConstant.HYPHEN + "题卡" + SystemConstant.HYPHEN + examTask.getCourseName() + SystemConstant.HYPHEN + paperType + SystemConstant.HTML_PREFIX;
+                        String cardPdfPath = cardPath + File.separator + "卷" + examTaskDetail.getSerialNumber() + SystemConstant.HYPHEN + "题卡" + SystemConstant.HYPHEN + examTask.getCourseName() + SystemConstant.HYPHEN + paperType + SystemConstant.PDF_PREFIX;
+
+                        // html
+                        File htmlFile = new File(cardHtmlPath);
+                        if (!htmlFile.exists()) {
+                            htmlFile.getParentFile().mkdirs();
+                            htmlFile.createNewFile();
+                        }
+                        String htmlContent = createPdfUtil.replaceBlankHtmlContent(examCard.getHtmlContent(), examCard.getCourseId());
+                        // 生成html文件
+                        FileCopyUtils.copy(htmlContent.getBytes(StandardCharsets.UTF_8), htmlFile);
+                        fileList.add(htmlFile);
+                        // 转pdf文件
+                        File pdfFile = new File(cardPdfPath);
+                        if (!pdfFile.exists()) {
+                            pdfFile.getParentFile().mkdirs();
+                            pdfFile.createNewFile();
+                        }
+                        HtmlToPdfUtil.convert(cardHtmlPath, cardPdfPath, PageSizeEnum.A3);
+                        fileList.add(pdfFile);
                     }
-                    HtmlToPdfUtil.convert(cardHtmlPath, cardPdfPath, PageSizeEnum.A3);
-                    fileList.add(pdfFile);
                 }
             }
 
+
             if (fileList.size() == 0) {
                 throw ExceptionResultEnum.ERROR.exception("没有可导出文件");
             }

+ 9 - 6
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ExamTaskServiceImpl.java

@@ -1335,11 +1335,14 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
 
                 if (StringUtils.isNotBlank(paperInfoVoList.get(0).getUuid())) {
                     // 删除临时数据
-                    QueryWrapper<ExamTaskPaperData> deleteWrapper = new QueryWrapper<>();
-                    deleteWrapper.lambda().eq(ExamTaskPaperData::getExamId, examTask.getExamId())
-                            .eq(ExamTaskPaperData::getPaperNumber, paperInfoVoList.get(0).getUuid())
-                            .notIn(ExamTaskPaperData::getPaperId, paperInfoVoList.stream().filter(m -> m.getPaperId() != null).map(PaperInfoVo::getPaperId).collect(Collectors.toList()));
-                    examTaskPaperDataService.remove(deleteWrapper);
+                    List<Long> paperIdList = paperInfoVoList.stream().filter(m -> m.getPaperId() != null).map(PaperInfoVo::getPaperId).collect(Collectors.toList());
+                    if(CollectionUtils.isNotEmpty(paperIdList)) {
+                        QueryWrapper<ExamTaskPaperData> deleteWrapper = new QueryWrapper<>();
+                        deleteWrapper.lambda().eq(ExamTaskPaperData::getExamId, examTask.getExamId())
+                                .eq(ExamTaskPaperData::getPaperNumber, paperInfoVoList.get(0).getUuid())
+                                .notIn(ExamTaskPaperData::getPaperId, paperIdList);
+                        examTaskPaperDataService.remove(deleteWrapper);
+                    }
                 }
             }
 
@@ -1436,7 +1439,7 @@ public class ExamTaskServiceImpl extends ServiceImpl<ExamTaskMapper, ExamTask> i
                         if (basicStudentIdUserMap.containsKey(i)) {
                             BasicExamStudent basicExamStudent = basicExamStudentService.getById(i);
                             if (basicExamStudent != null) {
-//                                throw ExceptionResultEnum.ERROR.exception("教学班[" + basicExamStudent.getTeachClassName() + "]内有考生已被[" + basicStudentIdUserMap.get(i) + "]选择");
+                                throw ExceptionResultEnum.ERROR.exception("教学班[" + basicExamStudent.getTeachClassName() + "]内有考生已被[" + basicStudentIdUserMap.get(i) + "]选择");
                             }
                         }
                     });

+ 70 - 59
distributed-print-business/src/main/java/com/qmth/distributed/print/business/templete/service/impl/DownloadLogicServiceImpl.java

@@ -545,28 +545,34 @@ public class DownloadLogicServiceImpl implements DownloadLogicService {
             List<ExamTaskPaperExportDto> examTaskPaperExportDtoList = new ArrayList<>();
             for (ExamTaskDetailDto examTaskDetailDto : examTaskDetailDtoList) {
                 ExamTaskPaperExportDto examTaskPaperExportDto = new ExamTaskPaperExportDto(examTaskDetailDto);
-                examTaskPaperExportDtoList.add(examTaskPaperExportDto);
-                List<PaperInfoVo> paperInfoVoList = ExamTaskUtil.parsePaperAttachmentPath(examTaskDetailDto.getPaperAttachmentIds());
+                List<ExamTaskDetail> examTaskDetailList = examTaskDetailService.listByExamTaskId(examTaskDetailDto.getId());
+                if (CollectionUtils.isEmpty(examTaskDetailList)) {
+                    examTaskPaperExportDto.setResult("未找到试卷,下载失败");
+                    continue;
+                }
+                examTaskPaperExportDto.setPaperType(examTaskDetailList.stream().map(m -> String.valueOf(m.getSerialNumber())).collect(Collectors.joining(",")));
+                examTaskPaperExportDto.setExposedPaperType(examTaskDetailList.stream().filter(m -> m.getExposed()).map(m -> String.valueOf(m.getSerialNumber())).collect(Collectors.joining(",")));
+                examTaskPaperExportDto.setUnexposedPaperType(examTaskDetailList.stream().filter(m -> !m.getExposed()).map(m -> String.valueOf(m.getSerialNumber())).collect(Collectors.joining(",")));
+
+                List<ExamTaskDetail> examTaskDetails = examTaskDetailList.stream().collect(Collectors.toList());
                 // 选择曝光卷型
                 if (PaperFileDownloadExposureStatusEnum.EXPOSED_PAPER.equals(paperFileDownloadExposureStatus)) {
-                    if (StringUtils.isBlank(examTaskDetailDto.getExposedPaperType())) {
+                    examTaskDetails = examTaskDetailList.stream().filter(m -> m.getExposed()).collect(Collectors.toList());
+                    if (CollectionUtils.isEmpty(examTaskDetails)) {
                         examTaskPaperExportDto.setResult("没有曝光卷型,下载失败");
                         continue;
-                    } else {
-                        paperInfoVoList = ExamTaskUtil.parsePaperAttachmentPath(examTaskDetailDto.getPaperAttachmentIds(), examTaskDetailDto.getExposedPaperType());
                     }
                 }
                 // 选择未曝光卷型
                 if (PaperFileDownloadExposureStatusEnum.UNEXPOSED_PAPER.equals(paperFileDownloadExposureStatus)) {
+                    examTaskDetails = examTaskDetailList.stream().filter(m -> !m.getExposed()).collect(Collectors.toList());
                     if (StringUtils.isBlank(examTaskDetailDto.getUnexposedPaperType())) {
                         examTaskPaperExportDto.setResult("没有未曝光卷型,下载失败");
                         continue;
-                    } else {
-                        paperInfoVoList = ExamTaskUtil.parsePaperAttachmentPath(examTaskDetailDto.getPaperAttachmentIds(), examTaskDetailDto.getUnexposedPaperType());
                     }
                 }
 
-                if (CollectionUtils.isEmpty(paperInfoVoList)) {
+                if (CollectionUtils.isEmpty(examTaskDetails)) {
                     examTaskPaperExportDto.setResult("所选试卷状态未查询到上传的试卷信息,下载失败");
                     continue;
                 }
@@ -583,63 +589,68 @@ public class DownloadLogicServiceImpl implements DownloadLogicService {
 
                 // 目录规则(课程名称(课程代码)/试卷编号)
                 String secondPath = examTaskDetailDto.getCourseName() + SystemConstant.HYPHEN + examTaskDetailDto.getCourseCode() + File.separator + examTaskDetailDto.getPaperNumber();
-                for (PaperInfoVo paperInfoVo : paperInfoVoList) {
-                    // 下载试卷
-                    if (downloadPaper) {
-                        // 不管什么命名规则,默认都加上卷型前缀
-                        String paperFileNamePath = "试卷" + SystemConstant.HYPHEN + paperInfoVo.getName() + SystemConstant.HYPHEN + fileNamePath;
-                        // 原文件名
-                        if (namedByOriginalFile) {
-                            paperFileNamePath = paperFileNamePath + SystemConstant.HYPHEN + paperInfoVo.getFilename();
-                        } else {
-                            paperFileNamePath = paperFileNamePath + "." + FilenameUtils.getExtension(paperInfoVo.getFilename());
-                        }
-                        Long attachmentId = Long.valueOf(paperInfoVo.getAttachmentId());
-                        if (Objects.nonNull(attachmentId)) {
-                            BasicAttachment attachment = basicAttachmentService.getById(attachmentId);
-                            if (Objects.nonNull(attachment)) {
-                                String fileName = trimWhiteSpace(zipLocalRootPath + File.separator + secondPath + File.separator + spliceFileName(paperFileNamePath, SystemConstant.PDF_PREFIX));
-                                fileUploadService.downloadFile(attachment, fileName);
+                for (ExamTaskDetail examTaskDetail : examTaskDetails) {
+                    List<PaperInfoVo> paperInfoVoList = JSON.parseArray(examTaskDetail.getPaperAttachmentIds(), PaperInfoVo.class);
+                    for (PaperInfoVo paperInfoVo : paperInfoVoList) {
+                        // 下载试卷
+                        if (downloadPaper) {
+                            // 不管什么命名规则,默认都加上卷型前缀
+                            String paperFileNamePath = "卷" + examTaskDetail.getSerialNumber() + SystemConstant.HYPHEN + "试卷" + SystemConstant.HYPHEN + paperInfoVo.getName() + SystemConstant.HYPHEN + fileNamePath;
+                            // 原文件名
+                            if (namedByOriginalFile) {
+                                paperFileNamePath = paperFileNamePath + SystemConstant.HYPHEN + paperInfoVo.getFilename();
+                            } else {
+                                paperFileNamePath = paperFileNamePath + "." + FilenameUtils.getExtension(paperInfoVo.getFilename());
+                            }
+                            Long attachmentId = Long.valueOf(paperInfoVo.getAttachmentId());
+                            if (Objects.nonNull(attachmentId)) {
+                                BasicAttachment attachment = basicAttachmentService.getById(attachmentId);
+                                if (Objects.nonNull(attachment)) {
+                                    String fileName = trimWhiteSpace(zipLocalRootPath + File.separator + secondPath + File.separator + spliceFileName(paperFileNamePath, SystemConstant.PDF_PREFIX));
+                                    fileUploadService.downloadFile(attachment, fileName);
+                                }
                             }
                         }
-                    }
-                    // 下载题卡
-                    if (downloadCard) {
-                        Long cardId = Long.valueOf(paperInfoVo.getCardId());
-                        ExamCard examCard = examCardService.getById(cardId);
-                        Optional.ofNullable(examCard).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("课程[" + examTaskDetailDto.getCourseName() + "(" + examTaskDetailDto.getCourseCode() + ")]、试卷编号[" + examTaskDetailDto.getPaperNumber() + "]命题任务未找到卷型[" + paperInfoVo.getName() + "]题卡"));
-
-                        String cardHtmlPath = zipLocalRootPath + File.separator + secondPath + File.separator + "题卡" + SystemConstant.HYPHEN + paperInfoVo.getName() + SystemConstant.HYPHEN + fileNamePath;
-                        String cardPdfPath = zipLocalRootPath + File.separator + secondPath + File.separator + "题卡" + SystemConstant.HYPHEN + paperInfoVo.getName() + SystemConstant.HYPHEN + fileNamePath;
-                        // 原文件名
-                        if (namedByOriginalFile) {
-                            cardHtmlPath = trimWhiteSpace(cardHtmlPath + SystemConstant.HYPHEN + examCard.getTitle() + SystemConstant.HTML_PREFIX);
-                            cardPdfPath = trimWhiteSpace(cardPdfPath + SystemConstant.HYPHEN + examCard.getTitle() + SystemConstant.PDF_PREFIX);
-                        } else {
-                            cardHtmlPath = trimWhiteSpace(cardHtmlPath + SystemConstant.HTML_PREFIX);
-                            cardPdfPath = trimWhiteSpace(cardPdfPath + SystemConstant.PDF_PREFIX);
-                        }
+                        // 下载题卡
+                        if (downloadCard) {
+                            Long cardId = Long.valueOf(paperInfoVo.getCardId());
+                            ExamCard examCard = examCardService.getById(cardId);
+                            Optional.ofNullable(examCard).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("课程[" + examTaskDetailDto.getCourseName() + "(" + examTaskDetailDto.getCourseCode() + ")]、试卷编号[" + examTaskDetailDto.getPaperNumber() + "]命题任务未找到卷型[" + paperInfoVo.getName() + "]题卡"));
+
+                            String cardHtmlPath = zipLocalRootPath + File.separator + secondPath + File.separator + "卷" + examTaskDetail.getSerialNumber() + SystemConstant.HYPHEN + "题卡" + SystemConstant.HYPHEN + paperInfoVo.getName() + SystemConstant.HYPHEN + fileNamePath;
+                            String cardPdfPath = zipLocalRootPath + File.separator + secondPath + File.separator + "卷" + examTaskDetail.getSerialNumber() + SystemConstant.HYPHEN + "题卡" + SystemConstant.HYPHEN + paperInfoVo.getName() + SystemConstant.HYPHEN + fileNamePath;
+                            // 原文件名
+                            if (namedByOriginalFile) {
+                                cardHtmlPath = trimWhiteSpace(cardHtmlPath + SystemConstant.HYPHEN + examCard.getTitle() + SystemConstant.HTML_PREFIX);
+                                cardPdfPath = trimWhiteSpace(cardPdfPath + SystemConstant.HYPHEN + examCard.getTitle() + SystemConstant.PDF_PREFIX);
+                            } else {
+                                cardHtmlPath = trimWhiteSpace(cardHtmlPath + SystemConstant.HTML_PREFIX);
+                                cardPdfPath = trimWhiteSpace(cardPdfPath + SystemConstant.PDF_PREFIX);
+                            }
 
-                        // html
-                        File localFile = new File(cardHtmlPath);
-                        if (!localFile.exists()) {
-                            localFile.getParentFile().mkdirs();
-                            localFile.createNewFile();
-                        }
-                        // 通用题卡
-                        String htmlContent = createPdfUtil.replaceBlankHtmlContent(examCard.getHtmlContent(), examCard.getCourseId());
-                        // 生成html文件
-                        FileCopyUtils.copy(htmlContent.getBytes(StandardCharsets.UTF_8), localFile);
-                        // 转pdf文件
-                        File file = new File(cardPdfPath);
-                        if (!file.exists()) {
-                            file.getParentFile().mkdirs();
-                            file.createNewFile();
+                            // html
+                            File localFile = new File(cardHtmlPath);
+                            if (!localFile.exists()) {
+                                localFile.getParentFile().mkdirs();
+                                localFile.createNewFile();
+                            }
+                            // 通用题卡
+                            String htmlContent = createPdfUtil.replaceBlankHtmlContent(examCard.getHtmlContent(), examCard.getCourseId());
+                            // 生成html文件
+                            FileCopyUtils.copy(htmlContent.getBytes(StandardCharsets.UTF_8), localFile);
+                            // 转pdf文件
+                            File file = new File(cardPdfPath);
+                            if (!file.exists()) {
+                                file.getParentFile().mkdirs();
+                                file.createNewFile();
+                            }
+                            HtmlToPdfUtil.convert(cardHtmlPath, cardPdfPath, PageSizeEnum.A3);
                         }
-                        HtmlToPdfUtil.convert(cardHtmlPath, cardPdfPath, PageSizeEnum.A3);
+                        examTaskPaperExportDto.setResult("下载成功");
                     }
-                    examTaskPaperExportDto.setResult("下载成功");
                 }
+
+                examTaskPaperExportDtoList.add(examTaskPaperExportDto);
             }
 
             // 导出文件excel

+ 1 - 8
distributed-print-business/src/main/resources/mapper/ExamTaskMapper.xml

@@ -1073,17 +1073,10 @@
             bc.code courseCode,
             bc.name courseName,
             a.paper_number paperNumber,
-            b.enable,
-            b.paper_type paperType,
-            IFNULL(b.exposed_paper_type,'') exposedPaperType,
-            IFNULL(b.unexposed_paper_type,'') unexposedPaperType,
-            so.name orgName,
-            b.paper_attachment_ids paperAttachmentIds
+            so.name orgName
         FROM
             exam_task a
                 LEFT JOIN
-            exam_task_detail b ON a.id = b.exam_task_id
-                LEFT JOIN
             basic_course bc ON a.course_id = bc.id
                 LEFT JOIN
             basic_card_rule e ON a.card_rule_id = e.id