yangdamao 2 년 전
부모
커밋
1f60273290
34개의 변경된 파일883개의 추가작업 그리고 102개의 파일을 삭제
  1. 20 7
      zhongzheng-admin-data/src/main/java/com/zhongzheng/controller/ExamSubscribeController.java
  2. 2 2
      zhongzheng-admin-data/src/main/java/com/zhongzheng/controller/UserSubscribeController.java
  3. 5 0
      zhongzheng-admin-data/src/main/resources/application-dev.yml
  4. 5 1
      zhongzheng-admin/src/main/resources/application-dev.yml
  5. 96 8
      zhongzheng-common/src/main/java/com/zhongzheng/common/utils/DateUtils.java
  6. 30 21
      zhongzheng-common/src/main/java/com/zhongzheng/common/utils/http/HttpUtils.java
  7. 2 1
      zhongzheng-framework/src/main/java/com/zhongzheng/framework/config/SecurityConfig.java
  8. 19 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/bo/BatchCancelSubscribeBo.java
  9. 6 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/bo/BatchSubscribeBo.java
  10. 7 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/bo/CdUserExamSubscribeQueryBo.java
  11. 1 2
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/bo/CdUserSubscribeBo.java
  12. 3 2
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/bo/CdUserSubscribeUpdateBo.java
  13. 51 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/bo/ExamApplySubscribeRequstBo.java
  14. 41 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/domain/CdExamConfig.java
  15. 42 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/domain/CdExamErrorLog.java
  16. 2 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/domain/CdExamSubscribe.java
  17. 0 2
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/domain/CdUserSubscribe.java
  18. 7 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/mapper/CdExamConfigMapper.java
  19. 7 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/mapper/CdExamErrorLogMapper.java
  20. 3 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/mapper/CdExamSubscribeMapper.java
  21. 7 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/ICdExamConfigService.java
  22. 7 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/ICdExamErrorLogService.java
  23. 8 4
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/ICdExamRoomService.java
  24. 2 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/ICdExamSubscribeService.java
  25. 4 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/impl/CdCdExamSubscribeServiceImpl.java
  26. 15 11
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/impl/CdCdUserSubscribeServiceImpl.java
  27. 403 34
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/impl/CdExamRoomServiceImpl.java
  28. 15 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/impl/ICdExamConfigServiceImpl.java
  29. 15 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/impl/ICdExamErrorLogServiceImpl.java
  30. 0 3
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/vo/CdExamRoomVo.java
  31. 4 4
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/vo/CdUserExamSubscribeVo.java
  32. 31 0
      zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/vo/UserExamDetailVo.java
  33. 23 0
      zhongzheng-system/src/main/resources/mapper/modules/cd/exam/DataWxTpClickMapper.xml
  34. 0 0
      zhongzheng-system/src/main/resources/mapper/modules/data/CdExamSubscribeMapper.xml

+ 20 - 7
zhongzheng-admin-data/src/main/java/com/zhongzheng/controller/ExamSubscribeController.java

@@ -3,13 +3,11 @@ package com.zhongzheng.controller;
 import com.zhongzheng.common.core.controller.BaseController;
 import com.zhongzheng.common.core.domain.AjaxResult;
 import com.zhongzheng.common.core.page.TableDataInfo;
-import com.zhongzheng.modules.middleground.record.bo.CdExamRoomBo;
-import com.zhongzheng.modules.middleground.record.bo.CdExamRoomQuery;
-import com.zhongzheng.modules.middleground.record.bo.CdExamRoomUpdateBo;
-import com.zhongzheng.modules.middleground.record.bo.CdUserExamSubscribeQueryBo;
+import com.zhongzheng.modules.middleground.record.bo.*;
 import com.zhongzheng.modules.middleground.record.service.ICdExamRoomService;
 import com.zhongzheng.modules.middleground.record.vo.CdExamRoomVo;
 import com.zhongzheng.modules.middleground.record.vo.CdUserExamSubscribeVo;
+import com.zhongzheng.modules.middleground.record.vo.UserExamDetailVo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.RequiredArgsConstructor;
@@ -25,7 +23,7 @@ import java.util.List;
 @Api(value = "考场预约接口", tags = {"考场预约控制器"})
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 @RestController
-@RequestMapping("/exam")
+@RequestMapping("/cd/exam")
 public class ExamSubscribeController extends BaseController {
 
     private final ICdExamRoomService examSubscribeService;
@@ -55,13 +53,28 @@ public class ExamSubscribeController extends BaseController {
         return AjaxResult.success(voList);
     }
 
+    @ApiOperation("考试详情")
+    @GetMapping("/detail/{id}")
+    public AjaxResult<List<UserExamDetailVo>> getExamDetail(@PathVariable("id") Long id) {
+        List<UserExamDetailVo> voList = examSubscribeService.getExamDetail(id);
+        return AjaxResult.success(voList);
+    }
+
     @ApiOperation("批量预约考试")
     @PostMapping("/batch/subscribe")
-    public AjaxResult<Void> batchSubscribe(CdUserExamSubscribeQueryBo bo) {
+    public AjaxResult<Void> batchSubscribe(@RequestBody BatchSubscribeBo bo) {
+        examSubscribeService.batchSubscribe(bo);
+        return AjaxResult.success();
+    }
+
+    @ApiOperation("批量取消预约考试")
+    @PostMapping("/batch/cancel/subscribe")
+    public AjaxResult<Void> batchCancelSubscribe(@RequestBody BatchCancelSubscribeBo bo) {
+        examSubscribeService.batchCancelSubscribe(bo);
         return AjaxResult.success();
     }
 
-    @ApiOperation("可预约学员列表")
+    @ApiOperation("学员列表")
     @GetMapping("/subscribe/list")
     public TableDataInfo<CdUserExamSubscribeVo> getExamSubscribeList(CdUserExamSubscribeQueryBo bo) {
         startPage();

+ 2 - 2
zhongzheng-admin-data/src/main/java/com/zhongzheng/controller/UserSubscribeController.java

@@ -21,10 +21,10 @@ import org.springframework.web.bind.annotation.RestController;
 @Api(value = "用户预约控制器", tags = {"用户预约控制器"})
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 @RestController
-@RequestMapping("/subscribe")
+@RequestMapping("/cd/subscribe")
 public class UserSubscribeController extends BaseController {
 
-    private ICdUserSubscribeService userSubscribeService;
+    private final ICdUserSubscribeService userSubscribeService;
 
     @ApiOperation("新增用户预约记录")
     @PostMapping("/save")

+ 5 - 0
zhongzheng-admin-data/src/main/resources/application-dev.yml

@@ -143,3 +143,8 @@ officialPush:
 
 distributionOldPay:
     host: http://gdxypx.xy.com/System/BussinessApi/AddRedPackData
+
+exam:
+    subscribe: http://192.168.1.222:5030/common/apply/subscribe
+    cancelSubscribe: http://192.168.1.222:5030/common/apply/subscribe/cancel
+

+ 5 - 1
zhongzheng-admin/src/main/resources/application-dev.yml

@@ -142,4 +142,8 @@ officialPush:
 
 
 distributionOldPay:
-    host: http://gdxypx.xy.com/System/BussinessApi/AddRedPackData
+    host: http://gdxypx.xy.com/System/BussinessApi/AddRedPackData\
+
+exam:
+    subscribe: http://192.168.1.222:5030/common/apply/subscribe
+    cancelSubscribe: http://192.168.1.222:5030/common/apply/subscribe/cancel

+ 96 - 8
zhongzheng-common/src/main/java/com/zhongzheng/common/utils/DateUtils.java

@@ -1,18 +1,18 @@
 package com.zhongzheng.common.utils;
 
+import cn.hutool.core.lang.Validator;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.time.DateFormatUtils;
+
 import java.lang.management.ManagementFactory;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.time.DayOfWeek;
+import java.time.Instant;
 import java.time.LocalDateTime;
+import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-import cn.hutool.core.lang.Validator;
-import org.apache.commons.lang3.RandomStringUtils;
-import org.apache.commons.lang3.time.DateFormatUtils;
+import java.util.*;
 
 /**
  * 时间工具类
@@ -371,4 +371,92 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
         return hh*60*60+mi*60+ss;
     }
 
+    /**
+     * 指定时间往前或往后推n天
+     *
+     * @param dateTime 指定时间
+     * @param x 指定天数
+     * @return
+     */
+    public static Long getDayBefore(Long dateTime, int x) {
+        Calendar c = Calendar.getInstance();
+        Date date = new Date(dateTime*1000);
+        c.setTime(date);
+        int day = c.get(Calendar.DATE);
+        c.set(Calendar.DATE, day - x);    //往前推几天
+        //c.set(Calendar.DATE, day + x);  往后推几天
+        return c.getTime().getTime()/1000;
+    }
+
+    /**
+     * 指定时间往前或往后推n天
+     *
+     * @param dateTime 指定时间
+     * @param x 指定天数
+     * @return
+     */
+    public static Long getDayAfter(Long dateTime, int x) {
+        Calendar c = Calendar.getInstance();
+        Date date = new Date(dateTime*1000);
+        c.setTime(date);
+        int day = c.get(Calendar.DATE);
+//        c.set(Calendar.DATE, day - x);    //往前推几天
+        c.set(Calendar.DATE, day + x);  //往后推几天
+        return c.getTime().getTime()/1000;
+    }
+
+    public static Date timeToDate(Long times){
+        long t = times.longValue();
+        t = t * 1000;
+        return new Date(t);
+    }
+
+    static List<String> holiday =new ArrayList<>();
+    static List<String> extraWorkDay =new ArrayList<>();
+
+    /**
+     *  初始化节假日
+     */
+    public static void initHoliday(){
+        holiday.add("2023-06-22");
+        holiday.add("2023-06-23");
+        holiday.add("2023-09-29");
+        holiday.add("2023-09-30");
+        holiday.add("2023-10-01");
+        holiday.add("2023-10-02");
+        holiday.add("2023-10-03");
+        holiday.add("2023-10-04");
+        holiday.add("2023-10-05");
+        holiday.add("2023-10-06");
+    }
+    /**
+     *  初始化额外加班日
+     */
+    public static void initExtraWorkDay(){
+        extraWorkDay.add("2023-06-25");
+        extraWorkDay.add("2023-10-07");
+        extraWorkDay.add("2023-10-08");
+    }
+
+    public static Boolean isWorkingDay(long time) {
+        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneOffset.of("+8"));
+        String formatTime = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+        initHoliday();
+        initExtraWorkDay();
+        //是否加班日
+        if(extraWorkDay.contains(formatTime)){
+            return true;
+        }
+        //是否节假日
+        if(holiday.contains(formatTime)){
+            return false;
+        }
+        //如果是1-5表示周一到周五  是工作日
+        DayOfWeek week = dateTime.getDayOfWeek();
+        if(week==DayOfWeek.SATURDAY||week==DayOfWeek.SUNDAY){
+            return false;
+        }
+        return true;
+
+    }
 }

+ 30 - 21
zhongzheng-common/src/main/java/com/zhongzheng/common/utils/http/HttpUtils.java

@@ -1,23 +1,7 @@
 package com.zhongzheng.common.utils.http;
 
-import java.io.*;
-import java.net.*;
-import java.security.cert.X509Certificate;
-import java.util.*;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
-
-import cn.hutool.http.HttpUtil;
-import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
-import org.apache.http.Consts;
-import org.apache.http.Header;
 import cn.hutool.core.lang.Validator;
+import com.alibaba.fastjson.JSONObject;
 import org.apache.http.*;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.config.RequestConfig;
@@ -25,8 +9,6 @@ import org.apache.http.client.entity.UrlEncodedFormEntity;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.client.methods.HttpUriRequest;
-import org.apache.http.client.params.AllClientPNames;
-import org.apache.http.entity.ContentType;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClientBuilder;
@@ -35,8 +17,12 @@ import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.EntityUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.http.HttpEntity;
-import sun.misc.BASE64Encoder;
+
+import javax.net.ssl.*;
+import java.io.*;
+import java.net.*;
+import java.security.cert.X509Certificate;
+import java.util.*;
 
 
 /**
@@ -249,6 +235,29 @@ public class HttpUtils
         return null;
     }
 
+
+    public static String sendPostJsonHeaderAsync(String url, String json, Map<String, String> headersMap)
+    {
+        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5*1000).setConnectTimeout(5*1000).build();
+        HttpClient client =  HttpClients.createDefault();
+        HttpPost post = new HttpPost(url);
+        post.setConfig(requestConfig);
+        try {
+            //此处应设定参数的编码格式,不然中文会变乱码
+            StringEntity s = new StringEntity(json, "UTF-8");
+            s.setContentEncoding("UTF-8");
+            s.setContentType("application/json");
+            post.setEntity(s);
+            post.addHeader("content-type", "application/json");
+            headersMap.forEach(post::setHeader);
+            client.execute(post);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
+        return null;
+    }
+
     /**
      * 向指定 URL 发送POST方法的请求
      *

+ 2 - 1
zhongzheng-framework/src/main/java/com/zhongzheng/framework/config/SecurityConfig.java

@@ -137,7 +137,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                 .antMatchers("/common/decompression").anonymous()
                 .antMatchers("/common/del/file").anonymous()
                 .antMatchers("/common/merge/file").anonymous()
-                .antMatchers("/exam/*").anonymous()
+                .antMatchers("/cd/exam/**").anonymous()
+                .antMatchers("/cd/subscribe/**").anonymous()
                 .antMatchers("/common/delete/file").anonymous()
                 .antMatchers("/course/handouts/**").anonymous()
                 .antMatchers("/common/get/goods").anonymous()

+ 19 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/bo/BatchCancelSubscribeBo.java

@@ -0,0 +1,19 @@
+package com.zhongzheng.modules.middleground.record.bo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author yangdamao
+ * @date 2023年07月19日 16:19
+ */
+@Data
+public class BatchCancelSubscribeBo implements Serializable {
+
+    @ApiModelProperty("学员预约ID")
+    private List<Long> userSubscribeIds;
+
+}

+ 6 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/bo/BatchSubscribeBo.java

@@ -1,8 +1,10 @@
 package com.zhongzheng.modules.middleground.record.bo;
 
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.util.List;
 
 /**
  * @author yangdamao
@@ -11,5 +13,9 @@ import java.io.Serializable;
 @Data
 public class BatchSubscribeBo implements Serializable {
 
+    @ApiModelProperty("学员预约ID")
+    private List<Long> userSubscribeIds;
 
+    @ApiModelProperty("考试ID")
+    private Long examId;
 }

+ 7 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/bo/CdUserExamSubscribeQueryBo.java

@@ -15,6 +15,13 @@ public class CdUserExamSubscribeQueryBo implements Serializable {
     @ApiModelProperty("用户名称")
     private String userName;
 
+    @ApiModelProperty("公司名称")
+    private String companyName;
+
+    @ApiModelProperty("专业")
+    private String major;
+
+
     @ApiModelProperty("预约状态:1正常 2取消 3过期 4未约")
     private Integer subscribeStatus;
 

+ 1 - 2
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/bo/CdUserSubscribeBo.java

@@ -48,11 +48,10 @@ public class CdUserSubscribeBo implements Serializable {
     @ApiModelProperty("机构Id")
     private Long tenantId;
     @ApiModelProperty("数据来源:1新系统 2旧系统")
-    private Long dataFrom;
+    private Integer dataFrom;
     @ApiModelProperty("类型:1七大员新考")
     private Integer type;
     /** 公司名称 */
     @ApiModelProperty("公司名称")
     private String companyName;
-
 }

+ 3 - 2
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/bo/CdUserSubscribeUpdateBo.java

@@ -18,6 +18,8 @@ public class CdUserSubscribeUpdateBo implements Serializable {
     /** 用户身份证 */
     @ApiModelProperty("用户身份证")
     private String userCard;
+    @ApiModelProperty("专业")
+    private String major;
     /** 考试次数 */
     @ApiModelProperty("考试次数")
     private Integer examNum;
@@ -34,8 +36,7 @@ public class CdUserSubscribeUpdateBo implements Serializable {
     @ApiModelProperty("机构Id")
     private Long tenantId;
     @ApiModelProperty("数据来源:1新系统 2旧系统")
-    private Long dataFrom;
+    private Integer dataFrom;
     @ApiModelProperty("类型:1七大员新考")
     private Integer type;
-
 }

+ 51 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/bo/ExamApplySubscribeRequstBo.java

@@ -0,0 +1,51 @@
+package com.zhongzheng.modules.middleground.record.bo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+/**
+ * @author yangdamao
+ * @date 2023年06月20日 11:22
+ */
+@Data
+public class ExamApplySubscribeRequstBo implements Serializable {
+
+    @ApiModelProperty("考生身份证号")
+    private String idCard;
+
+    @ApiModelProperty("联系方式")
+    private String telphone;
+
+    @ApiModelProperty("标识ID")
+    private Long signId;
+
+    @ApiModelProperty("学员类型:1非补考 2补考")
+    private Integer studentType;
+
+    @ApiModelProperty("专业名称")
+    private String majorName;
+
+    @ApiModelProperty("考试日期")
+    private Long applyTime;
+
+    @ApiModelProperty("考试开始时间段")
+    private String applyStartTime;
+
+    @ApiModelProperty("考试结束时间段")
+    private String applyEndTime;
+
+    @ApiModelProperty("机构ID")
+    private Long tenantId;
+
+    @ApiModelProperty("当前时间戳")
+    @NotBlank(message = "当前时间戳不能为空")
+    private Long stamp;
+
+    @ApiModelProperty("签名")
+    @NotBlank(message = "签名不能为空")
+    private String sign;
+
+}

+ 41 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/domain/CdExamConfig.java

@@ -0,0 +1,41 @@
+package com.zhongzheng.modules.middleground.record.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @author yangdamao
+ * @date 2023年07月11日 16:53
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("cd_exam_config")
+public class CdExamConfig implements Serializable {
+
+    @TableId(value = "id")
+    private Long id;
+    /** 配置key */
+    private String configKey;
+    /** 配置value */
+    private String configValue;
+    /** 添加时间 */
+    @TableField(fill = FieldFill.INSERT)
+    private Long createTime;
+    /** 修改时间 */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateTime;
+    /** 0 失效 1启用 */
+    private Integer status;
+    /** 机构Id */
+    private Long tenantId;
+    /** 类型:1七大员新考 */
+    private Integer type;
+}

+ 42 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/domain/CdExamErrorLog.java

@@ -0,0 +1,42 @@
+package com.zhongzheng.modules.middleground.record.domain;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * @author yangdamao
+ * @date 2023年07月21日 11:43
+ */
+@Data
+@NoArgsConstructor
+@Accessors(chain = true)
+@TableName("cd_exam_error_log")
+public class CdExamErrorLog implements Serializable {
+
+
+    @TableId(value = "id")
+    private Long id;
+    /** 类型:1预约考试 */
+    private Integer type;
+    /** 备注 */
+    private String remark;
+    /** 错误日志 */
+    private String errorLog;
+    /** 添加时间 */
+    @TableField(fill = FieldFill.INSERT)
+    private Long createTime;
+    /** 修改时间 */
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateTime;
+    /** 机构Id */
+    private Long tenantId;
+
+
+}

+ 2 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/domain/CdExamSubscribe.java

@@ -25,6 +25,8 @@ public class CdExamSubscribe implements Serializable {
     private Long id;
     /** 考试ID */
     private Long examId;
+    /** 学员预约ID */
+    private Long userSubscribeId;
     /** 用户ID */
     private Long userId;
     /** 用户姓名 */

+ 0 - 2
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/domain/CdUserSubscribe.java

@@ -50,8 +50,6 @@ public class CdUserSubscribe implements Serializable {
     private Long updateTime;
     /** 0 失效 1启用 */
     private Integer status;
-    /** 机构名称 */
-    private String tenantName;
     /** 数据来源:1新系统 2旧系统 */
     private Integer dataFrom;
     /** 机构Id */

+ 7 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/mapper/CdExamConfigMapper.java

@@ -0,0 +1,7 @@
+package com.zhongzheng.modules.middleground.record.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhongzheng.modules.middleground.record.domain.CdExamConfig;
+
+public interface CdExamConfigMapper extends BaseMapper<CdExamConfig> {
+}

+ 7 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/mapper/CdExamErrorLogMapper.java

@@ -0,0 +1,7 @@
+package com.zhongzheng.modules.middleground.record.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zhongzheng.modules.middleground.record.domain.CdExamErrorLog;
+
+public interface CdExamErrorLogMapper extends BaseMapper<CdExamErrorLog> {
+}

+ 3 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/mapper/CdExamSubscribeMapper.java

@@ -2,6 +2,9 @@ package com.zhongzheng.modules.middleground.record.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.zhongzheng.modules.middleground.record.domain.CdExamSubscribe;
+import org.apache.ibatis.annotations.Param;
 
 public interface CdExamSubscribeMapper extends BaseMapper<CdExamSubscribe> {
+
+    Long getReplenishNum(@Param("userId") Long userId,@Param("examMajor") String examMajor,@Param("tenantId") Long tenantId);
 }

+ 7 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/ICdExamConfigService.java

@@ -0,0 +1,7 @@
+package com.zhongzheng.modules.middleground.record.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhongzheng.modules.middleground.record.domain.CdExamConfig;
+
+public interface ICdExamConfigService extends IService<CdExamConfig> {
+}

+ 7 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/ICdExamErrorLogService.java

@@ -0,0 +1,7 @@
+package com.zhongzheng.modules.middleground.record.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhongzheng.modules.middleground.record.domain.CdExamErrorLog;
+
+public interface ICdExamErrorLogService extends IService<CdExamErrorLog> {
+}

+ 8 - 4
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/ICdExamRoomService.java

@@ -1,13 +1,11 @@
 package com.zhongzheng.modules.middleground.record.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.zhongzheng.modules.middleground.record.bo.CdExamRoomBo;
-import com.zhongzheng.modules.middleground.record.bo.CdExamRoomQuery;
-import com.zhongzheng.modules.middleground.record.bo.CdExamRoomUpdateBo;
-import com.zhongzheng.modules.middleground.record.bo.CdUserExamSubscribeQueryBo;
+import com.zhongzheng.modules.middleground.record.bo.*;
 import com.zhongzheng.modules.middleground.record.domain.CdExamRoom;
 import com.zhongzheng.modules.middleground.record.vo.CdExamRoomVo;
 import com.zhongzheng.modules.middleground.record.vo.CdUserExamSubscribeVo;
+import com.zhongzheng.modules.middleground.record.vo.UserExamDetailVo;
 
 import java.util.List;
 
@@ -22,4 +20,10 @@ public interface ICdExamRoomService extends IService<CdExamRoom> {
     boolean deleteExamRoom(CdExamRoomUpdateBo bo);
 
     List<CdUserExamSubscribeVo> getExamSubscribeList(CdUserExamSubscribeQueryBo bo);
+
+    void batchSubscribe(BatchSubscribeBo bo);
+
+    void batchCancelSubscribe(BatchCancelSubscribeBo bo);
+
+    List<UserExamDetailVo> getExamDetail(Long id);
 }

+ 2 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/ICdExamSubscribeService.java

@@ -4,4 +4,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.zhongzheng.modules.middleground.record.domain.CdExamSubscribe;
 
 public interface ICdExamSubscribeService extends IService<CdExamSubscribe> {
+
+    Long getReplenishNum(Long userId, String examMajor,Long tenantId);
 }

+ 4 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/impl/CdCdExamSubscribeServiceImpl.java

@@ -12,4 +12,8 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class CdCdExamSubscribeServiceImpl extends ServiceImpl<CdExamSubscribeMapper, CdExamSubscribe> implements ICdExamSubscribeService {
+    @Override
+    public Long getReplenishNum(Long userId, String examMajor,Long tenantId) {
+        return baseMapper.getReplenishNum(userId, examMajor,tenantId);
+    }
 }

+ 15 - 11
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/impl/CdCdUserSubscribeServiceImpl.java

@@ -3,7 +3,6 @@ package com.zhongzheng.modules.middleground.record.service.impl;
 import cn.hutool.core.bean.BeanUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
-import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zhongzheng.common.exception.CustomException;
 import com.zhongzheng.modules.middleground.record.bo.CdUserSubscribeBo;
@@ -30,18 +29,18 @@ public class CdCdUserSubscribeServiceImpl extends ServiceImpl<CdUserSubscribeMap
     public boolean saveUserSubscribe(CdUserSubscribeBo bo) {
         CdUserSubscribe cdUserSubscribe = BeanUtil.toBean(bo, CdUserSubscribe.class);
         //机构信息
-        cdUserSubscribe.setTenantId(getNewTenantId(bo.getTenantId()));
+        cdUserSubscribe.setTenantId(getNewTenantId(bo.getTenantId(),bo.getDataFrom()));
         return save(cdUserSubscribe);
     }
 
     @Override
     public boolean updateUserSubscribe(CdUserSubscribeUpdateBo bo) {
         CdUserSubscribe cdUserSubscribe = getOne(new LambdaQueryWrapper<CdUserSubscribe>()
-                .eq(ObjectUtils.isNotNull(bo.getUserId()), CdUserSubscribe::getUserId, bo.getUserId())
-                .eq(StringUtils.isNotBlank(bo.getUserCard()), CdUserSubscribe::getUserCard, bo.getUserCard())
-                .eq(CdUserSubscribe::getTenantId, getNewTenantId(bo.getTenantId()))
+                .eq( CdUserSubscribe::getUserId, bo.getUserId())
+                .eq( CdUserSubscribe::getUserCard, bo.getUserCard())
+                .eq( CdUserSubscribe::getMajor, bo.getMajor())
+                .eq(CdUserSubscribe::getTenantId, getNewTenantId(bo.getTenantId(),bo.getDataFrom()))
                 .eq(CdUserSubscribe::getDataFrom, bo.getDataFrom())
-                .eq(CdUserSubscribe::getType,bo.getType())
                 .last("limit 1"));
         if (ObjectUtils.isNull(cdUserSubscribe)){
             throw new CustomException("用户信息不匹配,请检查!");
@@ -69,11 +68,16 @@ public class CdCdUserSubscribeServiceImpl extends ServiceImpl<CdUserSubscribeMap
      * @param tenantId
      * @return java.lang.Long
      */
-    private Long getNewTenantId(Long tenantId){
-        DataTenant tenant = dataTenantService.getOne(new LambdaQueryWrapper<DataTenant>()
-                .eq(DataTenant::getNewId, tenantId)
-                .or().eq(DataTenant::getOldId, tenantId)
-                .last("limit 1"));
+    private Long getNewTenantId(Long tenantId,Integer dataFrom){
+        LambdaQueryWrapper<DataTenant> queryWrapper = new LambdaQueryWrapper<>();
+        if (dataFrom == 1){
+            //新系统
+            queryWrapper.eq(DataTenant::getNewId,tenantId);
+        }else {
+            //旧系统
+            queryWrapper.eq(DataTenant::getOldId,tenantId);
+        }
+        DataTenant tenant = dataTenantService.getOne(queryWrapper);
         if (ObjectUtils.isNull(tenant)){
             throw new CustomException("机构信息不匹配,请检查!");
         }

+ 403 - 34
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/impl/CdExamRoomServiceImpl.java

@@ -1,33 +1,33 @@
 package com.zhongzheng.modules.middleground.record.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zhongzheng.common.exception.CustomException;
+import com.zhongzheng.common.utils.DateUtils;
 import com.zhongzheng.common.utils.ServletUtils;
-import com.zhongzheng.modules.middleground.record.bo.CdExamRoomBo;
-import com.zhongzheng.modules.middleground.record.bo.CdExamRoomQuery;
-import com.zhongzheng.modules.middleground.record.bo.CdExamRoomUpdateBo;
-import com.zhongzheng.modules.middleground.record.bo.CdUserExamSubscribeQueryBo;
-import com.zhongzheng.modules.middleground.record.domain.CdExamRoom;
-import com.zhongzheng.modules.middleground.record.domain.CdExamSite;
+import com.zhongzheng.common.utils.ToolsUtils;
+import com.zhongzheng.common.utils.http.HttpUtils;
+import com.zhongzheng.modules.middleground.record.bo.*;
+import com.zhongzheng.modules.middleground.record.domain.*;
 import com.zhongzheng.modules.middleground.record.mapper.CdExamRoomMapper;
-import com.zhongzheng.modules.middleground.record.service.ICdExamRoomService;
-import com.zhongzheng.modules.middleground.record.service.ICdExamSiteService;
+import com.zhongzheng.modules.middleground.record.service.*;
 import com.zhongzheng.modules.middleground.record.vo.CdExamRoomDetailVo;
 import com.zhongzheng.modules.middleground.record.vo.CdExamRoomVo;
 import com.zhongzheng.modules.middleground.record.vo.CdUserExamSubscribeVo;
+import com.zhongzheng.modules.middleground.record.vo.UserExamDetailVo;
 import com.zhongzheng.modules.middleground.tenant.domain.DataTenant;
 import com.zhongzheng.modules.middleground.tenant.service.IDataTenantService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
@@ -35,10 +35,21 @@ public class CdExamRoomServiceImpl extends ServiceImpl<CdExamRoomMapper, CdExamR
 
     @Autowired
     private IDataTenantService dataTenantService;
-
     @Autowired
     private ICdExamSiteService examSiteService;
+    @Autowired
+    private ICdUserSubscribeService cdUserSubscribeService;
+    @Autowired
+    private ICdExamSubscribeService cdExamSubscribeService;
+    @Autowired
+    private ICdExamConfigService cdExamConfigService;
+    @Autowired
+    private ICdExamErrorLogService cdExamErrorLogService;
 
+    @Value("${exam.subscribe}")
+    private String EXAM_SUBSCRIBE_PATH;
+    @Value("${exam.cancelSubscribe}")
+    private String EXAM_SUBSCRIBE_CANCEL_PATH;
 
     @Override
     public boolean saveExamRoom(CdExamRoomBo bo) {
@@ -52,7 +63,7 @@ public class CdExamRoomServiceImpl extends ServiceImpl<CdExamRoomMapper, CdExamR
                 CdExamSite site = new CdExamSite();
                 site.setCode(ServletUtils.getEncoded("DD"));
                 site.setSiteAddress(bo.getExamSite());
-                site.setTenantId(getNewTenantId(bo.getTenantId()));
+                site.setTenantId(getNewTenantId(bo.getTenantId(),bo.getDataFrom()));
                 examSiteService.save(site);
                 siteId = site.getSiteId();
             }else {
@@ -62,7 +73,7 @@ public class CdExamRoomServiceImpl extends ServiceImpl<CdExamRoomMapper, CdExamR
 
         //查询考场是否存在
         CdExamRoom cdExamRoom = getOne(new LambdaQueryWrapper<CdExamRoom>()
-                .eq(CdExamRoom::getTenantId, getNewTenantId(bo.getTenantId()))
+                .eq(CdExamRoom::getTenantId, getNewTenantId(bo.getTenantId(),bo.getDataFrom()))
                 .eq(CdExamRoom::getExamTime, bo.getExamTime())
                 .eq(CdExamRoom::getExamStartTime, bo.getExamStartTime())
                 .eq(ObjectUtils.isNotNull(siteId), CdExamRoom::getExamSiteId, siteId)
@@ -88,7 +99,7 @@ public class CdExamRoomServiceImpl extends ServiceImpl<CdExamRoomMapper, CdExamR
             entity.setOldSignId(bo.getSignId());
         }
         entity.setStatus(1);
-        entity.setTenantId(getNewTenantId(bo.getTenantId()));
+        entity.setTenantId(getNewTenantId(bo.getTenantId(),bo.getDataFrom()));
         if (ObjectUtils.isNull(siteId)){
             //获取默认的
             CdExamSite site = examSiteService.getOne(new LambdaQueryWrapper<CdExamSite>().eq(CdExamSite::getSign, 1).last("limit 1"));
@@ -105,19 +116,18 @@ public class CdExamRoomServiceImpl extends ServiceImpl<CdExamRoomMapper, CdExamR
     public List<CdExamRoomVo> getExamRoomList(CdExamRoomQuery bo) {
         List<CdExamRoomVo> result = new ArrayList<>();
         List<CdExamRoom> cdExamRoomList = list(new LambdaQueryWrapper<CdExamRoom>()
-                .eq(ObjectUtils.isNotNull(bo.getTenantId()), CdExamRoom::getTenantId, getNewTenantId(bo.getTenantId()))
+                .eq(ObjectUtils.isNotNull(bo.getTenantId()), CdExamRoom::getTenantId, bo.getTenantId())
                 .eq(ObjectUtils.isNotNull(bo.getApplyTime()), CdExamRoom::getExamTime, bo.getApplyTime())
                 .eq(CdExamRoom::getType,1)
+                .eq(CdExamRoom::getStatus,1)
                 .eq(ObjectUtils.isNotNull(bo.getApplyStartTime()), CdExamRoom::getExamStartTime, bo.getApplyStartTime())
                 .eq(ObjectUtils.isNotNull(bo.getApplyEndTime()), CdExamRoom::getExamEndTime, bo.getApplyEndTime()));
         if (CollectionUtils.isEmpty(cdExamRoomList)) {
             return result;
         }
-        String tenantName = getNewTenant(bo.getTenantId()).getTenantName();
         Map<Long, List<CdExamRoom>> map = cdExamRoomList.stream().collect(Collectors.groupingBy(CdExamRoom::getExamTime));
         map.forEach((k, v) -> {
             CdExamRoomVo cdExamRoomVo = new CdExamRoomVo();
-            cdExamRoomVo.setTenantName(tenantName);
             cdExamRoomVo.setExamTime(k);
 
             List<CdExamRoomDetailVo> voList = v.stream().map(item -> {
@@ -143,7 +153,7 @@ public class CdExamRoomServiceImpl extends ServiceImpl<CdExamRoomMapper, CdExamR
     public boolean updateExamRoom(CdExamRoomUpdateBo bo) {
         //查询考场是否存在
         LambdaQueryWrapper<CdExamRoom> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(CdExamRoom::getTenantId,getNewTenantId(bo.getTenantId()));
+        wrapper.eq(CdExamRoom::getTenantId,getNewTenantId(bo.getTenantId(),bo.getDataFrom()));
         if (bo.getDataFrom() == 1) {
             wrapper.eq(CdExamRoom::getNewSignId,bo.getSignId());
         } else {
@@ -180,7 +190,7 @@ public class CdExamRoomServiceImpl extends ServiceImpl<CdExamRoomMapper, CdExamR
                 CdExamSite site = new CdExamSite();
                 site.setCode(ServletUtils.getEncoded("DD"));
                 site.setSiteAddress(bo.getExamSite());
-                site.setTenantId(getNewTenantId(bo.getTenantId()));
+                site.setTenantId(getNewTenantId(bo.getTenantId(),bo.getDataFrom()));
                 examSiteService.save(site);
                 cdExamRoom.setExamSiteId(site.getSiteId());
             }else {
@@ -194,7 +204,7 @@ public class CdExamRoomServiceImpl extends ServiceImpl<CdExamRoomMapper, CdExamR
     public boolean deleteExamRoom(CdExamRoomUpdateBo bo) {
         //查询考场是否存在
         LambdaQueryWrapper<CdExamRoom> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(CdExamRoom::getTenantId,getNewTenantId(bo.getTenantId()));
+        wrapper.eq(CdExamRoom::getTenantId,getNewTenantId(bo.getTenantId(),bo.getDataFrom()));
         if (bo.getDataFrom() == 1) {
             wrapper.eq(CdExamRoom::getNewSignId,bo.getSignId());
         } else {
@@ -205,7 +215,8 @@ public class CdExamRoomServiceImpl extends ServiceImpl<CdExamRoomMapper, CdExamR
         if (ObjectUtils.isNull(cdExamRoom)) {
             throw new CustomException("考场信息获取有误!");
         }
-        return removeById(cdExamRoom);
+        cdExamRoom.setStatus(0);
+        return updateById(cdExamRoom);
     }
 
     /**
@@ -217,9 +228,336 @@ public class CdExamRoomServiceImpl extends ServiceImpl<CdExamRoomMapper, CdExamR
      */
     @Override
     public List<CdUserExamSubscribeVo> getExamSubscribeList(CdUserExamSubscribeQueryBo bo) {
+        List<CdUserSubscribe> userSubscribe = cdUserSubscribeService.list(new LambdaQueryWrapper<CdUserSubscribe>()
+                .eq(StringUtils.isNotBlank(bo.getMajor()), CdUserSubscribe::getMajor, bo.getMajor())
+                .like(StringUtils.isNotBlank(bo.getUserName()), CdUserSubscribe::getUserName, bo.getUserName())
+                .like(StringUtils.isNotBlank(bo.getCompanyName()), CdUserSubscribe::getCompanyName, bo.getCompanyName()));
+        if (CollectionUtils.isEmpty(userSubscribe)){
+            return new ArrayList<>();
+        }
+        //考试信息
+        List<CdUserExamSubscribeVo> list = userSubscribe.stream().map(item -> {
+            CdUserExamSubscribeVo examSubscribeVo = BeanUtil.toBean(item, CdUserExamSubscribeVo.class);
+            CdExamSubscribe cdExamSubscribe = cdExamSubscribeService
+                    .getOne(new LambdaQueryWrapper<CdExamSubscribe>()
+                    .eq(CdExamSubscribe::getUserSubscribeId, item.getId())
+                    .eq(CdExamSubscribe::getStatus, 1)
+                    .orderByDesc(CdExamSubscribe::getCreateTime)
+                    .last("limit 1"));
+            if (ObjectUtils.isNotNull(cdExamSubscribe)){
+                switch (cdExamSubscribe.getSubscribeStatus()){
+                    case 1://正常
+                        //考试时间
+                        examSubscribeVo.setSubscribeStatus(1);
+                        CdExamRoom examRoom = getById(cdExamSubscribe.getExamId());
+                        String content = DateUtils.timestampToDateFormat(examRoom.getExamTime(), "yyyy年MM月dd号");
+                        String format = String.format("%s(%s-%s)", content, examRoom.getExamStartTime(), examRoom.getExamEndTime());
+                        examSubscribeVo.setExamTime(format);
+                        examSubscribeVo.setExamStatus(cdExamSubscribe.getExamStatus());
+                        if (ObjectUtils.isNotNull(cdExamSubscribe.getPerformance())){
+                            examSubscribeVo.setPerformance(cdExamSubscribe.getPerformance());
+                            examSubscribeVo.setExamStatus(cdExamSubscribe.getResult());
+                            examSubscribeVo.setExamType(cdExamSubscribe.getType());
+                        }
+                        if (ObjectUtils.isNotNull(cdExamSubscribe.getCertificateCode())){
+                            examSubscribeVo.setCertificateCode(cdExamSubscribe.getCertificateCode());
+                            examSubscribeVo.setPerformanceTime(cdExamSubscribe.getPerformanceTime());
+                        }
+                        break;
+                    case 2://取消
+                        examSubscribeVo.setSubscribeStatus(2);
+                        break;
+                    case 3://过期
+                        examSubscribeVo.setSubscribeStatus(3);
+                        break;
+                    default :
+                         break;
+                }
+                //补考次数
+                Long num = cdExamSubscribeService.getReplenishNum(cdExamSubscribe.getUserId(),cdExamSubscribe.getExamMajor(),cdExamSubscribe.getTenantId());
+                examSubscribeVo.setReplenishNum(num);
+            }
+            return examSubscribeVo;
+        }).collect(Collectors.toList());
+        return list;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void batchSubscribe(BatchSubscribeBo bo) {
+        //预约校验
+        subscribeVerify(bo);
+        List<CdExamSubscribe>  resultList = new ArrayList<>();
+        for (Long userSubscribeId : bo.getUserSubscribeIds()) {
+            //创建预约信息
+            CdExamSubscribe subscribe = new CdExamSubscribe();
+            subscribe.setExamId(bo.getExamId());
+            CdUserSubscribe userSubscribe = cdUserSubscribeService.getById(userSubscribeId);
+            subscribe.setUserSubscribeId(userSubscribe.getId());
+            subscribe.setExamMajor(userSubscribe.getMajor());
+            subscribe.setUserId(userSubscribe.getUserId());
+            subscribe.setUserName(userSubscribe.getUserName());
+            subscribe.setUserCard(userSubscribe.getUserCard());
+            subscribe.setUserPhone(userSubscribe.getUserPhone());
+            subscribe.setSubscribeStatus(1);
+            subscribe.setDataFrom(userSubscribe.getDataFrom());
+            subscribe.setTenantId(userSubscribe.getTenantId());
+            subscribe.setType(userSubscribe.getType());
+
+            //是否是新考
+            int count = cdExamSubscribeService.count(new LambdaQueryWrapper<CdExamSubscribe>()
+                    .eq(CdExamSubscribe::getUserId, userSubscribe.getUserId())
+                    .eq(CdExamSubscribe::getExamMajor, userSubscribe.getMajor())
+                    .eq(CdExamSubscribe::getSubscribeStatus, 1)
+                    .eq(CdExamSubscribe::getStatus, 1)
+                    .eq(CdExamSubscribe::getTenantId, userSubscribe.getTenantId()));
+            if (count > 0){
+                subscribe.setExamType(2);//补考
+            }else {
+                subscribe.setExamType(1);//新考
+            }
+            resultList.add(subscribe);
+        }
+        cdExamSubscribeService.saveBatch(resultList);
+
+        //todo 新旧系统学员预约处理
+        Map<Integer, List<CdExamSubscribe>> collect = resultList.stream().collect(Collectors.groupingBy(CdExamSubscribe::getDataFrom));
+        collect.forEach((k,v) -> {
+            switch (k){
+                case 1://新系统
+                    v.forEach(item -> {
+                        ExamApplySubscribeRequstBo requstBo = new ExamApplySubscribeRequstBo();
+                        Long nowTime = DateUtils.getNowTime();
+                        String sign = ToolsUtils.EncoderByMd5(nowTime.toString() + "pubilc2022");
+                        requstBo.setSign(sign);
+                        requstBo.setStamp(nowTime);
+                        requstBo.setTenantId(getNewTenant(item.getTenantId(),item.getDataFrom()).getNewId());
+                        //用户信息
+                        requstBo.setIdCard(item.getUserCard());
+                        requstBo.setTelphone(item.getUserPhone());
+                        CdExamRoom examRoom = getById(item.getExamId());
+                        requstBo.setSignId(examRoom.getNewSignId());
+                        requstBo.setStudentType(item.getExamType());
+                        requstBo.setApplyTime(examRoom.getExamTime());
+                        requstBo.setApplyStartTime(examRoom.getExamStartTime());
+                        requstBo.setApplyEndTime(examRoom.getExamEndTime());
+                        requstBo.setMajorName(item.getExamMajor());
+                        String param = JSONObject.toJSONString(bo);
+                        Map<String, String> headersMap = new HashMap<>();
+                        headersMap.put("TenantId", ServletUtils.getRequest().getHeader("TenantId"));
+                        try {
+                            HttpUtils.sendPostJsonHeaderAsync(EXAM_SUBSCRIBE_PATH, param,headersMap);
+                        }catch (Exception e){
+                            //预约错误记录日志
+                            CdExamErrorLog log = new CdExamErrorLog();
+                            log.setTenantId(item.getTenantId());
+                            log.setRemark(String.format("学员:%s,身份证:%s,预约专业:%s,预约表数据ID:%s",item.getUserName(),item.getUserCard(),item.getExamMajor(),item.getId()));
+                            log.setErrorLog(e.getMessage());
+                            log.setType(1);//预约考试错误
+                            cdExamErrorLogService.save(log);
+                        }
+                    });
+                    break;
+                case 2://旧系统
+                    break;
+                default :
+                    break;
+            }
+        });
+    }
+
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void batchCancelSubscribe(BatchCancelSubscribeBo bo) {
+        List<CdExamSubscribe> subscribeList = new ArrayList<>();
+        bo.getUserSubscribeIds().forEach(id -> {
+            CdExamSubscribe subscribe = cdExamSubscribeService
+                    .getOne(new LambdaQueryWrapper<CdExamSubscribe>()
+                    .eq(CdExamSubscribe::getUserSubscribeId, id)
+                    .eq(CdExamSubscribe::getSubscribeStatus, 1)
+                    .eq(CdExamSubscribe::getStatus, 1)
+                    .last("limit 1"));
+            CdUserSubscribe userSubscribe = cdUserSubscribeService.getById(id);
+            if (ObjectUtils.isNull(subscribe)){
+                throw new CustomException(String.format("【%s】学员预约数据不存在,请检查!",userSubscribe.getUserName()));
+            }
+
+            CdExamRoom cdExamRoom = getById(subscribe.getExamId());
+            Long time = cdExamRoom.getExamTime();
+            String before = getExamConfig("exam_before", 1,  cdExamRoom.getTenantId());
+            Long applyBeforeTime = getApplyBeforeTime(time, Integer.valueOf(before));
+            if (DateUtils.getNowTime() >= applyBeforeTime){
+                throw new CustomException(String.format("【%s】学员预约的考试场次距开考少于7个工作日,不能取消预约!",userSubscribe.getUserName()));
+            }
+            subscribe.setSubscribeStatus(0);//取消预约
+            subscribeList.add(subscribe);
+        });
+        cdExamSubscribeService.updateBatchById(subscribeList);
+
+        //todo 新旧系统取消预约处理
+        Map<Integer, List<CdExamSubscribe>> map = subscribeList.stream().collect(Collectors.groupingBy(CdExamSubscribe::getDataFrom));
+        map.forEach((k,v) -> {
+            switch (k){
+                case 1://新系统
+                    v.forEach(item -> {
+                        ExamApplySubscribeRequstBo requstBo = new ExamApplySubscribeRequstBo();
+                        Long nowTime = DateUtils.getNowTime();
+                        String sign = ToolsUtils.EncoderByMd5(nowTime.toString() + "pubilc2022");
+                        requstBo.setSign(sign);
+                        requstBo.setStamp(nowTime);
+                        requstBo.setTenantId(getNewTenant(item.getTenantId(),item.getDataFrom()).getNewId());
+                        //用户信息
+                        requstBo.setIdCard(item.getUserCard());
+                        requstBo.setTelphone(item.getUserPhone());
+                        CdExamRoom examRoom = getById(item.getExamId());
+                        requstBo.setSignId(examRoom.getNewSignId());
+                        requstBo.setStudentType(item.getExamType());
+                        requstBo.setApplyTime(examRoom.getExamTime());
+                        requstBo.setApplyStartTime(examRoom.getExamStartTime());
+                        requstBo.setApplyEndTime(examRoom.getExamEndTime());
+                        requstBo.setMajorName(item.getExamMajor());
+                        String param = JSONObject.toJSONString(bo);
+                        Map<String, String> headersMap = new HashMap<>();
+                        headersMap.put("TenantId", ServletUtils.getRequest().getHeader("TenantId"));
+                        try {
+                            HttpUtils.sendPostJsonHeaderAsync(EXAM_SUBSCRIBE_CANCEL_PATH, param,headersMap);
+                        }catch (Exception e){
+                            //预约错误记录日志
+                            CdExamErrorLog log = new CdExamErrorLog();
+                            log.setTenantId(item.getTenantId());
+                            log.setRemark(String.format("学员:%s,身份证:%s,预约专业:%s,预约表数据ID:%s",item.getUserName(),item.getUserCard(),item.getExamMajor(),item.getId()));
+                            log.setErrorLog(e.getMessage());
+                            log.setType(1);//预约考试错误
+                            cdExamErrorLogService.save(log);
+                        }
+                    });
+                    break;
+                case 2://旧系统
+                    break;
+                default :
+                    break;
+            }
+        });
+    }
+
+    @Override
+    public List<UserExamDetailVo> getExamDetail(Long id) {
+        CdUserSubscribe subscribe = cdUserSubscribeService.getById(id);
+        List<CdExamSubscribe> list = cdExamSubscribeService
+                .list(new LambdaQueryWrapper<CdExamSubscribe>()
+                .eq(CdExamSubscribe::getUserId, subscribe.getUserId())
+                .eq(CdExamSubscribe::getExamMajor, subscribe.getMajor())
+                .eq(CdExamSubscribe::getSubscribeStatus, 1)
+                .eq(CdExamSubscribe::getStatus, 1));
+        if (CollectionUtils.isEmpty(list)){
+            return new ArrayList<>();
+        }
+       return list.stream().map(item -> {
+            UserExamDetailVo userExamDetailVo = new UserExamDetailVo();
+            userExamDetailVo.setUserId(item.getUserId());
+            userExamDetailVo.setExamType(item.getExamType());
+            CdExamRoom exam = getById(item.getExamId());
+            userExamDetailVo.setExamTime(exam.getExamTime());
+            userExamDetailVo.setPerformance(item.getPerformance());
+            if (item.getExamStatus() == 1){
+                userExamDetailVo.setExamStatus(item.getResult());
+            }else {
+                userExamDetailVo.setExamStatus(item.getExamStatus());
+            }
+            return userExamDetailVo;
+        }).collect(Collectors.toList());
+    }
+
+    //预约校验
+    private void subscribeVerify(BatchSubscribeBo bo) {
+        CdExamRoom courseRoom = getById(bo.getExamId());
+        Long tenantId = courseRoom.getTenantId();
+        Long time = courseRoom.getExamTime();
+        //考试前7个工作日停止预约
+        String before = getExamConfig("exam_before", 1,tenantId);
+        Long applyBeforeTime = getApplyBeforeTime(time, Integer.valueOf(before));
+        if (DateUtils.getNowTime() >= applyBeforeTime){
+            throw new CustomException("该考试场次已停止预约,请选择其他场次!");
+        }
 
+        for (Long userSubscribeId : bo.getUserSubscribeIds()) {
+            CdExamSubscribe subscribe = cdExamSubscribeService.getOne(new LambdaQueryWrapper<CdExamSubscribe>()
+                    .eq(CdExamSubscribe::getUserSubscribeId, userSubscribeId)
+                    .eq(CdExamSubscribe::getStatus, 1)
+                    .eq(CdExamSubscribe::getSubscribeStatus, 1)
+                    .orderByDesc(CdExamSubscribe::getCreateTime)
+                    .last("limit 1"));
+            if (ObjectUtils.isNull(subscribe)){
+                continue;
+            }
+            CdUserSubscribe userSubscribe = cdUserSubscribeService.getById(userSubscribeId);
+            if (subscribe.getExamStatus() == 0){
+                //考试成绩没出
+                throw new CustomException(String.format("%s【%s】已经预约了该专业考试,无需重复预约",userSubscribe.getUserName(),userSubscribe.getUserCard()));
+            }
+
+            //查询考试情况
+            if (subscribe.getResult() == 1){
+                //成绩已通过
+                throw new CustomException(String.format("%s【%s】已经通过该专业考试,无需重复预约",userSubscribe.getUserName(),userSubscribe.getUserCard()));
+            }
+
+            //过20个工作日才能在预约
+            CdExamRoom exam = getById(subscribe.getExamId());
+            Long examTime = exam.getExamTime(); // 考试时间
+            String after = getExamConfig("exam_after", 1, tenantId);
+            Long applyEndTime = getApplyAfterTime(examTime, Integer.valueOf(after));
+            if (DateUtils.getNowTime() <= applyEndTime){
+                throw new CustomException(String.format("%s【%s】请等待15个工作日后再预约!",userSubscribe.getUserName(),userSubscribe.getUserCard()));
+            }
+
+        }
+    }
+
+
+    private Long getApplyAfterTime(Long millisecond, Integer day) {
+        for (Integer i = 0; i < day; i++) {
+            Long dayAfter = DateUtils.getDayAfter(millisecond, 1);
+            Calendar calendar = Calendar.getInstance();
+            calendar.setTime(DateUtils.timeToDate(dayAfter));
+            int index = calendar.get(Calendar.DAY_OF_WEEK) - 1;
+            String[] weeks = new String[]{"星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
+
+            if (weeks[index].equals("星期六") || weeks[index].equals("星期天")) {
+                day += 1;
+
+            }
+            //判断当前是否为工作日
+            if (!DateUtils.isWorkingDay(dayAfter)) {
+                day += 1;
+            }
+            millisecond = dayAfter;
+        }
+
+        return millisecond;
+    }
+
+    private Long getApplyBeforeTime(Long millisecond, Integer day) {
+        for (Integer i = 0; i < day; i++) {
+            Long dayAfter = DateUtils.getDayBefore(millisecond, 1);
+            Calendar calendar = Calendar.getInstance();
+            calendar.setTime(DateUtils.timeToDate(dayAfter));
+            int index = calendar.get(Calendar.DAY_OF_WEEK) - 1;
+            String[] weeks = new String[]{"星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
 
-        return null;
+            if (weeks[index].equals("星期六") || weeks[index].equals("星期天")) {
+                day += 1;
+
+            }
+            //判断当前是否为工作日
+            if (!DateUtils.isWorkingDay(dayAfter)) {
+                day += 1;
+            }
+            millisecond = dayAfter;
+        }
+
+        return millisecond;
     }
 
 
@@ -230,11 +568,16 @@ public class CdExamRoomServiceImpl extends ServiceImpl<CdExamRoomMapper, CdExamR
      * @param tenantId
      * @return java.lang.Long
      */
-    private Long getNewTenantId(Long tenantId){
-        DataTenant tenant = dataTenantService.getOne(new LambdaQueryWrapper<DataTenant>()
-                .eq(DataTenant::getNewId, tenantId)
-                .or().eq(DataTenant::getOldId, tenantId)
-                .last("limit 1"));
+    private Long getNewTenantId(Long tenantId,Integer dataFrom){
+        LambdaQueryWrapper<DataTenant> queryWrapper = new LambdaQueryWrapper<>();
+        if (dataFrom == 1){
+            //新系统
+            queryWrapper.eq(DataTenant::getNewId,tenantId);
+        }else {
+            //旧系统
+            queryWrapper.eq(DataTenant::getOldId,tenantId);
+        }
+        DataTenant tenant = dataTenantService.getOne(queryWrapper);
         if (ObjectUtils.isNull(tenant)){
             throw new CustomException("机构信息不匹配,请检查!");
         }
@@ -242,22 +585,48 @@ public class CdExamRoomServiceImpl extends ServiceImpl<CdExamRoomMapper, CdExamR
     }
 
     /**
-     * 获取机构信息
+     * 获取机构ID
      * @author change
      * @date 2023/7/17 10:13
      * @param tenantId
      * @return java.lang.Long
      */
-    private DataTenant getNewTenant(Long tenantId){
-        DataTenant tenant = dataTenantService.getOne(new LambdaQueryWrapper<DataTenant>()
-                .eq(DataTenant::getNewId, tenantId)
-                .or().eq(DataTenant::getOldId, tenantId)
-                .last("limit 1"));
+    private DataTenant getNewTenant(Long tenantId,Integer dataFrom){
+        LambdaQueryWrapper<DataTenant> queryWrapper = new LambdaQueryWrapper<>();
+        if (dataFrom == 1){
+            //新系统
+            queryWrapper.eq(DataTenant::getNewId,tenantId);
+        }else {
+            //旧系统
+            queryWrapper.eq(DataTenant::getOldId,tenantId);
+        }
+        DataTenant tenant = dataTenantService.getOne(queryWrapper);
         if (ObjectUtils.isNull(tenant)){
             throw new CustomException("机构信息不匹配,请检查!");
         }
         return tenant;
     }
 
+    /**
+     * 获取考试配置项
+     * @author change
+     * @date 2023/7/21 10:15
+     * @param key
+     * @param type
+     * @return java.lang.String
+     */
+    private String getExamConfig(String key,Integer type,Long tenantId){
+        CdExamConfig config = cdExamConfigService
+                .getOne(new LambdaQueryWrapper<CdExamConfig>()
+                .eq(CdExamConfig::getConfigKey, key)
+                .eq(CdExamConfig::getType, type)
+                .eq(CdExamConfig::getTenantId, tenantId)
+                .last("limit 1"));
+
+        if (ObjectUtils.isNull(config)){
+            throw new CustomException("考试配置项读取失败!");
+        }
+        return config.getConfigValue();
+    }
 
 }

+ 15 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/impl/ICdExamConfigServiceImpl.java

@@ -0,0 +1,15 @@
+package com.zhongzheng.modules.middleground.record.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhongzheng.modules.middleground.record.domain.CdExamConfig;
+import com.zhongzheng.modules.middleground.record.mapper.CdExamConfigMapper;
+import com.zhongzheng.modules.middleground.record.service.ICdExamConfigService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author yangdamao
+ * @date 2023年07月21日 10:13
+ */
+@Service
+public class ICdExamConfigServiceImpl extends ServiceImpl<CdExamConfigMapper, CdExamConfig> implements ICdExamConfigService {
+}

+ 15 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/service/impl/ICdExamErrorLogServiceImpl.java

@@ -0,0 +1,15 @@
+package com.zhongzheng.modules.middleground.record.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhongzheng.modules.middleground.record.domain.CdExamErrorLog;
+import com.zhongzheng.modules.middleground.record.mapper.CdExamErrorLogMapper;
+import com.zhongzheng.modules.middleground.record.service.ICdExamErrorLogService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author yangdamao
+ * @date 2023年07月21日 10:13
+ */
+@Service
+public class ICdExamErrorLogServiceImpl extends ServiceImpl<CdExamErrorLogMapper, CdExamErrorLog> implements ICdExamErrorLogService {
+}

+ 0 - 3
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/vo/CdExamRoomVo.java

@@ -16,9 +16,6 @@ public class CdExamRoomVo implements Serializable {
     @ApiModelProperty("机构ID")
     private String tenantId;
 
-    @ApiModelProperty("机构名称")
-    private String tenantName;
-
     @ApiModelProperty("考试日期")
     private Long examTime;
 

+ 4 - 4
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/vo/CdUserExamSubscribeVo.java

@@ -30,15 +30,15 @@ public class CdUserExamSubscribeVo implements Serializable {
     @ApiModelProperty("预约状态:1正常 2取消 3过期 4未约")
     private Integer subscribeStatus;
     @ApiModelProperty("考试时间")
-    private Long examTime;
-    @ApiModelProperty("考试状态")
-    private Long examStatus;
+    private String examTime;
+    @ApiModelProperty("考试状态:1通过 0不通过 2缺考 3作弊 4替考")
+    private Integer examStatus;
     @ApiModelProperty("成绩")
     private BigDecimal performance;
     @ApiModelProperty("类型:1新考 2补考")
     private Integer examType;
     @ApiModelProperty("补考次数")
-    private Integer examNum;
+    private Long replenishNum;
 
     @ApiModelProperty("可预约次数")
     private Integer subscribeNum;

+ 31 - 0
zhongzheng-system/src/main/java/com/zhongzheng/modules/middleground/record/vo/UserExamDetailVo.java

@@ -0,0 +1,31 @@
+package com.zhongzheng.modules.middleground.record.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @author yangdamao
+ * @date 2023年07月20日 16:30
+ */
+@Data
+public class UserExamDetailVo implements Serializable {
+
+    @ApiModelProperty("用户ID")
+    private Long userId;
+
+    @ApiModelProperty("考试时间")
+    private Long examTime;
+
+    @ApiModelProperty("考试状态:1通过 0不通过 2缺考 3作弊 4替考")
+    private Integer examStatus;
+
+    @ApiModelProperty("成绩")
+    private BigDecimal performance;
+
+    @ApiModelProperty("类型:1新考 2补考")
+    private Integer examType;
+
+}

+ 23 - 0
zhongzheng-system/src/main/resources/mapper/modules/cd/exam/DataWxTpClickMapper.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zhongzheng.modules.middleground.record.mapper.CdExamSubscribeMapper">
+
+    <select id="getReplenishNum" parameterType="map" resultType="java.lang.Long">
+        SELECT
+            COUNT( ces.id )
+        FROM
+            cd_exam_subscribe ces
+                LEFT JOIN cd_exam_room cer ON ces.exam_id = cer.exam_id
+        WHERE
+            ces.user_id = #{userId}
+          AND ces.exam_major = #{examMajor}
+          AND ces.subscribe_status = 1
+          AND ces.`status` = 1
+          AND ces.tenant_id = #{tenantId}
+          AND NOW() > cer.exam_time
+    </select>
+
+
+</mapper>

+ 0 - 0
zhongzheng-system/src/main/resources/mapper/modules/data/DataWxTpClickMapper.xml → zhongzheng-system/src/main/resources/mapper/modules/data/CdExamSubscribeMapper.xml