소스 검색

Merge remote-tracking branch 'origin/master'

liub 4 주 전
부모
커밋
7bf02e5e31

+ 32 - 162
commons/src/main/java/com/jzg/commons/entity/finance/vo/importimcome/ImportContentExt.java

@@ -1,13 +1,12 @@
 package com.jzg.commons.entity.finance.vo.importimcome;
 
-import cn.hutool.core.collection.CollUtil;
+
 import cn.hutool.core.util.StrUtil;
+import com.jzg.commons.entity.finance.po.InsPlyIncome;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.io.Serial;
-import java.io.Serializable;
-import java.util.Objects;
 
 /**
  * Excel 表格字段填充后的完整数据信息
@@ -15,184 +14,55 @@ import java.util.Objects;
  * @date 2026/8/4 9:14
  */
 @Data
-public class ImportContentExt implements Serializable {
+public class ImportContentExt extends ExcelContent4Platform {
     @Serial
     private static final long serialVersionUID = 8609830028190910294L;
 
-    @Schema(description = "车牌号")
-    private String licenseNo;
-
-    @Schema(description = "交强险保单号")
-    private String jqPolicyNo;
-
-    @Schema(description = "商业险保单号")
-    private String syPolicyNo;
-
-    @Schema(description = "非车险保单号")
-    private String jyPolicyNo;
-
-    @Schema(description = "交强险手续费比例")
-    private String jqSuperviseCostsProportion;
-
-    @Schema(description = "交强险跟单费比例")
-    private String jqOtherCostsProportion;
-
-    @Schema(description = "商业险手续费比例")
-    private String sySuperviseCostsProportion;
-
-    @Schema(description = "商业险跟单费比例")
-    private String syOtherCostsProportion;
-
-
-    @Schema(description = "非车险手续费比例")
-    private String jySuperviseCostsProportion;
-
-    @Schema(description = "非车险跟单费比例")
-    private String jyOtherCostsProportion;
-
-
-    @Schema(description = "交强险入口比例")
-    private String jqInletRatio;
-
-    @Schema(description = "商业险入口比例")
-    private String syInletRatio;
-
-    @Schema(description = "非车险入口比例")
-    private String jyInletRatio;
-
-    @Schema(description = "选中类型")
-    // 1 全部数据选中  2 选中部分数据
-    private String selectedType;
-
     @Schema(description = "订单号")
     private String orderNo;
 
-    @Schema(description = "id")
-    private String id;
-
-    @Schema(description = "签单时间")
-    private String signingTime;
-
-    @Schema(description = "协议类型")
-    private String agreementType;
-
-    @Schema(description = "险种名称")
-    private String productName;
-
-    @Schema(description = "被保险人姓名")
-    private String insuredPerson;
+    @Schema(description = "保险机构")
+    private String parternerCompanyId;
 
-    @Schema(description = "公司名称")
-    private String companyName;
+    @Schema(description = "应收订单的ID")
+    private String incomeId;
 
     @Schema(description = "对接人")
     private String contactPerson;
 
-    @Schema(description = "对接人手机号")
-    private String contactPersonPhone;
-
-    @Schema(description = "错误信息")
-    private String errorMessage;
-
-    @Schema(description = "协议Id")
-    private String agreementId;
-
-    @Schema(description = "协议名称")
-    private String agreementName;
-
-    @Schema(description = "租户代码")
-    private String systemCode;
-
-    @Schema(description = "保险机构")
-    private String partnerCompanyId;
-
-    @Schema(description = "交强保费")
-    private String jqPremium;
-
-    @Schema(description = "商业保费")
-    private String syPremium;
+    @Schema(description = "应收订单")
+    private InsPlyIncome insPlyIncome;
 
-    @Schema(description = "驾意保费")
-    private String jyPremium;
+    //  20 表示平台协议  11表示车险手续费 12 表示非车险手续费
+    @Schema(description = "类型")
+    private String type;
 
     public ImportResultVo checkEmpty(){
-        ImportResultVo resultVo = new ImportResultVo();
-        resultVo.setSuccess(false);
-        // 基础必填字段校验
-        if (StrUtil.isBlank(this.getSigningTime())) {
-            resultVo.getMessage().add("签单时间不能为空");
-        }
-        if (StrUtil.isBlank(this.getOrderNo())) {
-            resultVo.getMessage().add("订单号不能为空");
-        }
-        if (StrUtil.isBlank(this.getLicenseNo())) {
-            resultVo.getMessage().add("车牌号不能为空");
-        }
-        if (StrUtil.isBlank(this.getProductName())) {
-            resultVo.getMessage().add("险种名称不能为空");
+        ImportResultVo vo = new ImportResultVo();
+        if(StrUtil.isEmpty(this.orderNo)){
+            vo.addMessage(String.format("订单不存在,车牌号是[%s]",this.getLicenseNo()));
+            return vo;
         }
-//        if (StrUtil.isBlank(this.getInsuredPerson())) {
-//            resultVo.getMessage().add("被保险人姓名不能为空");
-//        }
-        if (StrUtil.isBlank(this.getAgreementType())) {
-            resultVo.getMessage().add("协议类型不能为空");
+        if (StrUtil.isEmpty(this.incomeId)) {
+            vo.addMessage(String.format("订单没有进入应收,车牌号是[%s]",this.getLicenseNo()));
+            return vo;
         }
-//        if (StrUtil.isBlank(this.getContactPerson())) {
-//            resultVo.getMessage().add("对接人不能为空");
-//        }
-//        if (StrUtil.isBlank(this.getAgreementType())) {
-//            resultVo.getMessage().add("对接人手机号不能为空");
-//        }
-
-        // 交强险:有保单号 → 手续费、跟单费必填
-//        if (StrUtil.isNotBlank(this.getJqPolicyNo())
-//                || StrUtil.isNotBlank(this.getJqSuperviseCostsProportion())
-//                || StrUtil.isNotBlank(this.getJqOtherCostsProportion())) {
-//            if (StrUtil.isBlank(this.getJqPolicyNo())) {
-//                resultVo.getMessage().add("交强险保单号不能为空");
-//            }
-//            if (StrUtil.isBlank(this.getJqSuperviseCostsProportion())) {
-//                resultVo.getMessage().add("交强险手续费比例不能为空");
-//            }
-//            if (StrUtil.isBlank(this.getJqOtherCostsProportion())) {
-//                resultVo.getMessage().add("交强险跟单费比例不能为空");
-//            }
-//        }
-
-        // 商业险:有保单号 → 手续费、跟单费必填
-//        if (StrUtil.isNotBlank(this.getSyPolicyNo())
-//                || StrUtil.isNotBlank(this.getSySuperviseCostsProportion())
-//                || StrUtil.isNotBlank(this.getSyOtherCostsProportion())) {
-//            if (StrUtil.isBlank(this.getJqPolicyNo())) {
-//                resultVo.getMessage().add("商业险保单号不能为空");
-//            }
-//            if (StrUtil.isBlank(this.getSySuperviseCostsProportion())) {
-//                resultVo.getMessage().add("商业险手续费比例不能为空");
-//            }
-//            if (StrUtil.isBlank(this.getSyOtherCostsProportion())) {
-//                resultVo.getMessage().add("商业险跟单费比例不能为空");
-//            }
-//        }
-
-        // 非车险:有保单号 → 手续费、跟单费必填
-        if (StrUtil.isNotBlank(this.getJyPolicyNo())
-                || StrUtil.isNotBlank(this.getJySuperviseCostsProportion())
-                || StrUtil.isNotBlank(this.getJyOtherCostsProportion())) {
-            if (StrUtil.isBlank(this.getJqPolicyNo())) {
-                resultVo.getMessage().add("非车险保单号不能为空");
-            }
-            if (StrUtil.isBlank(this.getJySuperviseCostsProportion())) {
-                resultVo.getMessage().add("非车险手续费比例不能为空");
-            }
-            if (StrUtil.isBlank(this.getJyOtherCostsProportion())) {
-                resultVo.getMessage().add("非车险跟单费比例不能为空");
-            }
+        if(this.insPlyIncome == null){
+            vo.addMessage(String.format("根据订单号没有匹配到应收数据. 车牌号是[%s],订单号是[%s]",this.getLicenseNo(),this.getOrderNo()));
+            return vo;
         }
 
-        if(CollUtil.isEmpty(resultVo.getMessage())){
-            resultVo.setSuccess(true);
+        // TODO 校验手续费比例等信息表格里面的和数据库 ins_ply_income 里面是否一致
+        if("11".equals(this.type)){
+
+        }else if("20".equals(this.type)){
+
+        }else if ("12".equals(this.type)) {
+
+        }else{
+
         }
-        return resultVo;
+        return vo;
     }
 
 }

+ 5 - 0
commons/src/main/java/com/jzg/commons/entity/quote/vo/aggregated/QuoteEchoVo.java

@@ -27,6 +27,7 @@ import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import org.springframework.beans.BeanUtils;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import java.io.Serial;
 import java.math.BigDecimal;
@@ -299,9 +300,13 @@ public class QuoteEchoVo extends QuoteVo {
 
     @Schema(description = "是否是疑问订单")
     private boolean isProblem;
+
     @Schema(description = "疑问订单原因")
     private String problemReason;
+
     @Schema(description = "设为疑问订单的时间")
+    @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
     private LocalDateTime problemTime;
 
     @Schema(description = "权益信息")

+ 21 - 0
commons/src/main/java/com/jzg/commons/entity/vo/CostExternalListVo.java

@@ -14,6 +14,14 @@ public class CostExternalListVo {
 
     private String id;
 
+    @Schema(description = "加投比例")
+    private String addThrow;
+
+    @Schema(description = "内部协议id")
+    private String ptlAgreementId;
+
+    @Schema(description = "跟单比例")
+    private String keepPointRatio;
 
     @Schema(description = "协议代码")
     private String agreementCode;
@@ -76,9 +84,22 @@ public class CostExternalListVo {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private String auditTime;
 
+    @Schema(description = "修改时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private String updateTime;
+
     @Schema(description = "审核人")
     private String auditPerson;
 
+    @Schema(description = "修改人")
+    private String updateBy;
+
+    @Schema(description = "是否有效")
+    private String isDelete;
+
+    @Schema(description = "所属机构编码")
+    private String systemCode;
+
     @Schema(description = "审核描述")
     private String reviewDescription;
 

+ 1 - 1
commons/src/main/java/com/jzg/commons/util/SchemaDescriptionParser.java

@@ -113,6 +113,6 @@ public class SchemaDescriptionParser {
     // --- 测试主函数 ---
     public static void main(String[] args) {
         Map<String, String> result = SchemaDescriptionParser.getSchemaMap();
-        //result.forEach((k, v) -> System.out.println(k + " = " + v));
+        result.forEach((k, v) -> System.out.println(k + " = " + v));
     }
 }

+ 4 - 4
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/component/HuaTaiCrawlerCacheComponent.java

@@ -39,7 +39,7 @@ public class HuaTaiCrawlerCacheComponent {
         authorizationMap.put(COOKIE, cookie);
         RMap<Object, Object> map = redissonClient.getMap(HUATAI_COOKIE);
         map.putAll(authorizationMap);
-        map.expire(Duration.ofHours(3L));
+        map.expire(Duration.ofDays(30L));
     }
 
     public void cacheGsInfo(String gsinfo) {
@@ -48,7 +48,7 @@ public class HuaTaiCrawlerCacheComponent {
         authorizationMap.put(GSINFO, gsinfo);
         RMap<Object, Object> map = redissonClient.getMap(HUATAI_GSINFO);
         map.putAll(authorizationMap);
-        map.expire(Duration.ofHours(3L));
+        map.expire(Duration.ofDays(30L));
     }
 
     public void cacheComCode(String comcode) {
@@ -57,7 +57,7 @@ public class HuaTaiCrawlerCacheComponent {
         authorizationMap.put(COMCODE, comcode);
         RMap<Object, Object> map = redissonClient.getMap(HUATAI_COMCODE);
         map.putAll(authorizationMap);
-        map.expire(Duration.ofHours(3L));
+        map.expire(Duration.ofDays(30L));
     }
 
     public void cacheYingXiangUploaded(String yx) {
@@ -66,7 +66,7 @@ public class HuaTaiCrawlerCacheComponent {
         authorizationMap.put(YINGXIANG_UPLOADED, yx);
         RMap<Object, Object> map = redissonClient.getMap(HUATAI_YINGXIANG_UPLOADED);
         map.putAll(authorizationMap);
-        map.expire(Duration.ofHours(3L));
+        map.expire(Duration.ofDays(30L));
     }
 
     public String getCookie() {

+ 3 - 1
tenant/insurance/quotation-summary/src/main/resources/application-dev.yaml

@@ -227,7 +227,9 @@ zijin:
 
   crawler:
     baseUrl: https://kscd.zking.com
-    cookie-path: https://test.baoxianzhanggui.com/ck-api/ck
+    cookie-path: http://39.98.41.104:8888/zjbx/ck
+    # Python外放接口的Cookie更新地址,生成ck的JS算法有时效性,需主动调用此接口刷新Cookie
+    update-ck-path: http://39.98.41.104:8888/zjbx/update
 
 #    # 为接入方提供获取token服务
 #    accessTokenUrl: https://open.zking.com/api/v1/public/token/getAccessToken

+ 70 - 60
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/component/ZiJinCrawlerRequestComponent.java

@@ -9,7 +9,6 @@ import com.jzg.quotation.zijin.crawler.entity.response.*;
 import com.jzg.quotation.zijin.crawler.enums.RequestUrl;
 import com.jzg.quotation.zijin.crawler.properties.ZiJinCrawlerProperties;
 import com.jzg.quotation.zijin.crawler.util.DESEncryption;
-import lombok.Data;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.jetbrains.annotations.NotNull;
@@ -49,6 +48,16 @@ public class ZiJinCrawlerRequestComponent {
     // 用于调用Python外放接口获取Cookie
     private final RestTemplate restTemplate = new RestTemplate();
 
+
+    /**
+     * Cookie缓存过期时间戳(毫秒),超过此时间需重新调用Python更新接口刷新Cookie
+     */
+    private volatile long cookieExpireTime;
+    /**
+     * Cookie缓存有效期:10分钟(生成ck的JS算法具有时效性,超过10分钟需主动调用更新接口刷新)
+     */
+    private static final long COOKIE_TTL_MS = 10 * 60 * 1000;
+
     /**
      * 获取验证码
      *
@@ -116,7 +125,6 @@ public class ZiJinCrawlerRequestComponent {
     public ZiJinCrawlerCheckCaptchaResponse checkCaptchaAndGetToken(ZiJinCrawlerCheckCaptchaRequest ziJinCrawlerCheckCaptchaRequest, String token) throws IOException {
         log.info("ziJinCrawlerCheckCaptchaRequest请求参数的值:{}", JSON.toJSONString(ziJinCrawlerCheckCaptchaRequest));
         HttpHeaders httpHeaders = setHttpHeaders();
-        // 注意:不要手动设置Content-Length,由底层WebClient根据body自动计算,否则会被WAF判定为异常请求(412)
         // 需要单独设置这个
         httpHeaders.set("Authorization", token);
         httpHeaders.set("loginToken", token);
@@ -514,40 +522,57 @@ public class ZiJinCrawlerRequestComponent {
 
 
     /**
-     * Python外放接口返回的Cookie信息
-     * 用于动态设置请求头中的Cookie、x-csrf-token、User-Agent等,避免硬编码导致WAF校验失败
+     * 默认User-Agent,与Python端curl-cffi的impersonate=chrome131保持一致
      */
-    @Data
-    public static class CookieInfo {
-        /** 完整的Cookie字符串,包含WAF挑战Cookie和csrfToken */
-        private String cookie;
-        /** CSRF Token值,用于x-csrf-token请求头 */
-        private String csrfToken;
-        /** User-Agent字符串,需与获取Cookie时Python使用的UA保持一致以通过WAF指纹校验 */
-        private String ua;
+    private static final String DEFAULT_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36";
+
+    /**
+     * 调用Python外放接口更新Cookie
+     * 由于生成ck的JS算法具有时效性,需主动调用此接口让Python重新执行JS挑战刷新Cookie
+     *
+     * @throws IOException 如果调用更新接口时发生错误
+     */
+    public void updateCookie() throws IOException {
+        String updateUrl = ziJinCrawlerProperties.getUpdateCkPath();
+        if (updateUrl == null || updateUrl.trim().isEmpty()) {
+            throw new IOException("紫金crawler.update-ck-path未配置");
+        }
+        try {
+            log.info("调用Python更新Cookie接口: {}", updateUrl);
+            ResponseEntity<String> response = restTemplate.getForEntity(updateUrl, String.class);
+            String body = response.getBody();
+            log.info("更新Cookie接口响应: {}", body);
+        } catch (Exception e) {
+            log.error("调用Python更新Cookie接口失败: {}", e.getMessage(), e);
+            throw new IOException("更新Cookie失败: " + e.getMessage(), e);
+        }
     }
 
     /**
-     * 调用Python外放接口获取Cookie及关联信息
-     * 返回包含cookie、csrfToken、ua的完整信息对象,用于动态构建请求头
+     * 获取Cookie字符串(带缓存)
+     * <p>
+     * 由于生成ck的JS算法具有时效性,Cookie缓存10分钟后自动过期。
+     * 过期时会先调用Python更新接口刷新Cookie,再重新获取。
      * <p>
      * Python接口返回示例:
      * <pre>{@code
      * {
-     *     "ok": true,
-     *     "cookie": "c7IBxtKJpAH2O=...; c7IBxtKJpAH2P=...; csrfToken=uZvxgMXq-TPNbLU8jJhSOpxmaynt9YmmuxH0",
-     *     "pLen": 343,
-     *     "csrfToken": "uZvxgMXq-TPNbLU8jJhSOpxmaynt9YmmuxH0",
-     *     "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
-     *     "impersonate": "chrome131",
-     *     "elapsed_ms": 3801
+     *     "c7IBxtKJpAH2P": "aqEdSy_6gjpocI0...",
+     *     "c7IBxtKJpAH2O": "qaAIGG3xrOsNPZx..."
      * }
      * }</pre>
      *
-     * @return CookieInfo Cookie信息对象
+     * @return String Cookie字符串,格式: "key1=value1; key2=value2"
      * @throws IOException 如果获取Cookie时发生错误
      */
-    public CookieInfo getCookieInfo() throws IOException {
+    public String getCookie() throws IOException {
+        // 检查缓存是否有效
+        long now = System.currentTimeMillis();
+        if (now < cookieExpireTime) {
+            log.info("紫金Cookie JS算法剩余有效时间: {}ms", (cookieExpireTime - now));
+            updateCookie();
+        }
+        // 调用Python接口获取刷新后的Cookie
         String cookieUrl = ziJinCrawlerProperties.getCookiePath();
         if (cookieUrl == null || cookieUrl.trim().isEmpty()) {
             throw new IOException("紫金crawler.cookie-path未配置");
@@ -559,23 +584,25 @@ public class ZiJinCrawlerRequestComponent {
                 throw new IOException("获取Cookie失败: Python接口返回空内容");
             }
             log.info("获取Cookie响应:{}", body);
-            // 解析JSON响应,提取cookie、csrfToken、ua字段
+            // Python返回Cookie键值对Map,遍历拼接为标准Cookie格式
             com.alibaba.fastjson2.JSONObject jsonObject = JSON.parseObject(body);
-            if (!jsonObject.getBooleanValue("ok")) {
-                throw new IOException("获取Cookie失败: Python接口返回ok=false");
-            }
-            CookieInfo cookieInfo = new CookieInfo();
-            cookieInfo.setCookie(jsonObject.getString("cookie"));
-            cookieInfo.setCsrfToken(jsonObject.getString("csrfToken"));
-            cookieInfo.setUa(jsonObject.getString("ua"));
-            if (cookieInfo.getCookie() == null || cookieInfo.getCookie().trim().isEmpty()) {
-                throw new IOException("获取Cookie失败: 响应中cookie字段为空");
+            StringBuilder cookieBuilder = new StringBuilder();
+            for (String key : jsonObject.keySet()) {
+                String value = jsonObject.getString(key);
+                if (value != null && !value.trim().isEmpty()) {
+                    if (cookieBuilder.length() > 0) {
+                        cookieBuilder.append("; ");
+                    }
+                    cookieBuilder.append(key).append("=").append(value);
+                }
             }
-            if (cookieInfo.getCsrfToken() == null || cookieInfo.getCsrfToken().trim().isEmpty()) {
-                throw new IOException("获取Cookie失败: 响应中csrfToken字段为空");
+            String cookie = cookieBuilder.toString();
+            if (cookie.trim().isEmpty()) {
+                throw new IOException("获取Cookie失败: 拼接的Cookie字符串为空");
             }
-            log.info("紫金Cookie获取成功,耗时: {}ms", jsonObject.getString("elapsed_ms"));
-            return cookieInfo;
+            cookieExpireTime = System.currentTimeMillis() + COOKIE_TTL_MS;
+            log.info("紫金Cookie获取并缓存成功,有效期: {}分钟", COOKIE_TTL_MS / 60000);
+            return cookie;
         } catch (IOException e) {
             throw e;
         } catch (Exception e) {
@@ -584,17 +611,6 @@ public class ZiJinCrawlerRequestComponent {
         }
     }
 
-    /**
-     * 获取Cookie字符串
-     * 通过调用Python外放接口获取Cookie,返回完整的Cookie字符串(包含WAF挑战Cookie和csrfToken)
-     *
-     * @return String Cookie字符串
-     * @throws IOException 如果获取Cookie时发生错误
-     */
-    public String getCookie() throws IOException {
-        return getCookieInfo().getCookie();
-    }
-
     /**
      * 从User-Agent字符串中解析Chrome主版本号
      * 例如: "Mozilla/5.0 ... Chrome/131.0.0.0 Safari/537.36" → "131"
@@ -637,10 +653,9 @@ public class ZiJinCrawlerRequestComponent {
     @NotNull
     private HttpHeaders setHttpHeaders(String token) throws IOException {
         HttpHeaders headers = new HttpHeaders();
-        // 动态获取Cookie信息(包含WAF挑战Cookie、csrfToken、ua),避免硬编码导致WAF校验失败
-        CookieInfo cookieInfo = getCookieInfo();
-        // Cookie字符串已包含csrfToken,直接使用Python返回的完整Cookie
-        headers.set("Cookie", cookieInfo.getCookie());
+        // 通过Python外放接口获取WAF挑战Cookie,拼接为标准Cookie格式
+        String cookie = getCookie();
+        headers.set("Cookie", "csrfToken=yKKI5-FlPLoNFbMVKORknSef;" + cookie);
         headers.set("Accept", "application/json, text/plain, */*, application/problem+json");
         // headers.set("Accept-Encoding", "gzip, deflate, br, zstd");
         headers.set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
@@ -655,19 +670,14 @@ public class ZiJinCrawlerRequestComponent {
         headers.set("Sec-Fetch-Mode", "cors");
         headers.set("Sec-Fetch-Site", "same-origin");
         headers.set("Tokentype", "DEFULT");
-        // User-Agent需与Python获取Cookie时使用的UA保持一致,否则WAF指纹校验会失败
-        String ua = cookieInfo.getUa();
-        if (ua == null || ua.trim().isEmpty()) {
-            ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
-        }
-        headers.set("User-Agent", ua);
+        headers.set("User-Agent", DEFAULT_UA);
         // 从UA中解析Chrome版本号,构造与UA一致的sec-ch-ua头,避免版本号不匹配
-        String chromeVersion = extractChromeVersion(ua);
+        String chromeVersion = extractChromeVersion(DEFAULT_UA);
         headers.set("sec-ch-ua", "\"Google Chrome\";v=\"" + chromeVersion + "\", \"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"" + chromeVersion + "\"");
         headers.set("sec-ch-ua-mobile", "?0");
         headers.set("sec-ch-ua-platform", "\"Windows\"");
         // x-csrf-token使用Python返回的动态值,不再硬编码
-        headers.set("x-csrf-token", cookieInfo.getCsrfToken());
+        headers.set("x-csrf-token", "yKKI5-FlPLoNFbMVKORknSef");
         headers.set("content-type", "application/json");
         if (StringUtils.hasText(token)) {
             headers.set("Authorization", token);

+ 6 - 0
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/properties/ZiJinCrawlerProperties.java

@@ -21,4 +21,10 @@ public class ZiJinCrawlerProperties {
      */
     private String cookiePath;
 
+    /**
+     * Python外放接口的Cookie更新地址
+     * 由于生成ck的JS算法有时效性,需主动调用此接口让Python重新执行JS挑战刷新Cookie
+     */
+    private String updateCkPath;
+
 }

+ 13 - 12
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerRequestImpl.java

@@ -160,23 +160,24 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
                 }
             }
 
-            // 4.0 处理报价失败
+            // 处理报价失败
             if (!ResponseCode.R_0000.getCode().equals(ziJinCrawlerQuotationResponse.getRtnCode())) {
                 ziJinCrawlerOrderService.save(quoteVo, ziJinCrawlerQuotationResponse, null, null, ziJinCrawlerQuotationRequest.getOrderId(), false);
                 return ZiJinCrawlerQuoteResultsVoBuild.buildQuoteFailResultsVo(ziJinCrawlerQuotationResponse);
-            } else {
-                // 报价成功
-                // 保存报价信息
-                ZiJinCrawlerSaveQuoteInfoRequest ziJinCrawlerSaveQuoteInfoRequest = ziJinCrawlerSaveQuoteInfoRequestBuild.buildSaveQuoteInfoRequest(quoteVo, ziJinCrawlerGetOrderNoResponse.getOrderNo(), ziJinCrawlerQuotationRequest, ziJinCrawlerQuotationResponse);
-                ZiJinCrawlerSaveQuoteInfoResponse ziJinCrawlerSaveQuoteInfoResponse = ziJinCrawlerRequestComponent.saveQuoteInformation(ziJinCrawlerSaveQuoteInfoRequest, headers);
+            }
 
-                // 保存投保单
-                ZiJinCrawlerSaveProposalRequest ziJinCrawlerSaveProposalRequest = new ZiJinCrawlerSaveProposalRequest(ziJinCrawlerGetOrderNoResponse.getOrderNo(), ziJinCrawlerQuotationResponse.getBasePart().getProposalCheckNo());
-                ZiJinCrawlerSaveProposalResponse ziJinCrawlerSaveProposalResponse = ziJinCrawlerRequestComponent.saveProposal(ziJinCrawlerSaveProposalRequest, headers);
+            // 报价成功
+            // 保存报价信息
+            ZiJinCrawlerSaveQuoteInfoRequest ziJinCrawlerSaveQuoteInfoRequest = ziJinCrawlerSaveQuoteInfoRequestBuild.buildSaveQuoteInfoRequest(quoteVo, ziJinCrawlerGetOrderNoResponse.getOrderNo(), ziJinCrawlerQuotationRequest, ziJinCrawlerQuotationResponse);
+            ZiJinCrawlerSaveQuoteInfoResponse ziJinCrawlerSaveQuoteInfoResponse = ziJinCrawlerRequestComponent.saveQuoteInformation(ziJinCrawlerSaveQuoteInfoRequest, headers);
+
+            // 保存投保单
+            ZiJinCrawlerSaveProposalRequest ziJinCrawlerSaveProposalRequest = new ZiJinCrawlerSaveProposalRequest(ziJinCrawlerGetOrderNoResponse.getOrderNo(), ziJinCrawlerQuotationResponse.getBasePart().getProposalCheckNo());
+            ZiJinCrawlerSaveProposalResponse ziJinCrawlerSaveProposalResponse = ziJinCrawlerRequestComponent.saveProposal(ziJinCrawlerSaveProposalRequest, headers);
+
+            ziJinCrawlerOrderService.save(quoteVo, ziJinCrawlerQuotationResponse, ziJinCrawlerSaveProposalResponse, ziJinCrawlerSaveQuoteInfoResponse.getOrderNo(), ziJinCrawlerQuotationRequest.getOrderId(), true);
+            return ZiJinCrawlerQuoteResultsVoBuild.buildQuoteResultsVo(quoteVo, ziJinCrawlerQuotationResponse, ziJinCrawlerSaveProposalResponse);
 
-                ziJinCrawlerOrderService.save(quoteVo, ziJinCrawlerQuotationResponse, ziJinCrawlerSaveProposalResponse, ziJinCrawlerSaveQuoteInfoResponse.getOrderNo(), ziJinCrawlerQuotationRequest.getOrderId(), true);
-                return ZiJinCrawlerQuoteResultsVoBuild.buildQuoteResultsVo(quoteVo, ziJinCrawlerQuotationResponse, ziJinCrawlerSaveProposalResponse);
-            }
         } catch (Exception e) {
             e.printStackTrace();
             throw new RuntimeException(e);

+ 5 - 49
tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java

@@ -2561,7 +2561,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             } else {
                 existPolicyNoSet.add(policyNo);
             }
-            existCompanyIdSet.add(vo.getCompanyName());
+            existCompanyIdSet.add(vo.getParternerCompanyId());
         }
 
         // 导入只能一个保司
@@ -2570,27 +2570,6 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             throw new SystemException("导入数据不能包含多个保险公司");
         }
 
-        // 处理数据
-        for (ImportContentExt vo : datas) {
-            // 1. 空数据校验
-            ImportResultVo resultVo = vo.checkEmpty();
-            if (!resultVo.isSuccess()) {
-                vo.setErrorMessage(resultVo.convert2Str());
-                failedExcel.add(vo);
-                continue;
-            }
-
-            // 2. Excel内部保单号重复
-            if (repeatPolicyNoSet.contains(vo.getJqPolicyNo())) {
-                vo.setErrorMessage("保单号重复");
-                failedExcel.add(vo);
-                continue;
-            }
-            ImportContentExt errVO = importIncomeService.spliceData(vo, insertExcel, updateExcel);
-            if(errVO != null){
-                failedExcel.add(errVO);
-            }
-        }
 
         // 执行批量更新
         ImportUpdateExcelResultVo importExcelResultVo = importIncomeService.getDataManipulationResult(updateExcel, insertExcel,failedExcel);
@@ -2609,21 +2588,15 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
      */
     private List<ImportContentExt> parseAndFillContent(MultipartFile file, String type) {
         log.info("解析Excel内容并填充缺失的字段. type=[{}]", type);
-
         if("11".equals(type)){
             List<ExcelContent4PrivateSuperviseCar> excelContents2 = importIncomeService.parseImportExcel4PrivateCar(file);
             return importIncomeService.fillExcelContent4All(excelContents2);
         } if("12".equals(type)){
             List<ExcelContent4PrivateSuperviseNoCar> excelContents3 = importIncomeService.parseImportExcel4PrivateNoCar(file);
             return importIncomeService.fillExcelContent4All(excelContents3);
-//        } if("20".equals(type)){
-//            List<ExcelContent4Platform> excelContents = importIncomeService.parseImportExcel4Platform(file);
-//            return importIncomeService.fillExcelContent4All(excelContents);
         }else{
             List<ExcelContent4Platform> excelContents = importIncomeService.parseImportExcel4Platform(file);
             return importIncomeService.fillExcelContent4All(excelContents);
-//            log.info("解析Excel内容并填充缺失的字段.类型不支持 type=[{}]", type);
-//            return Collections.emptyList();
         }
     }
 
@@ -6230,27 +6203,10 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
      */
     @Override
     public Page<ReceiverSettlementReportDto> receiverSettlementReportWithSettlemetnDate(Page page, SettlementReportQueryVo vo) {
-        log.info("平台协议应收-结算报表-对接人结算报表查询。結算时间不为空 settlementReportQueryVo=[{}]", JSONUtil.toJsonStr(vo));
-        Page<InsPlyIncomeInvoiceSettlement> pageRes = insPlyIncomeInvoiceSettlementMapper.querySettlementBySettlementDate(page,vo);
-        List<InsPlyIncomeInvoiceSettlement> records = pageRes.getRecords();
-        Map<String, List<InsPlyIncomeInvoiceSettlement>> res =  records.stream()
-                .collect(Collectors.groupingBy(InsPlyIncomeInvoiceSettlement::getContactPerson));
-        Page<ReceiverSettlementReportDto> pagDto = new Page<>(page.getPages(), page.getSize());
-        List<ReceiverSettlementReportDto> dtos = new ArrayList<>();
-        for (String s : res.keySet()) {
-            ReceiverSettlementReportDto dto = new ReceiverSettlementReportDto();
-            dto.setReceiver(s);
-            List<InsPlyIncomeInvoiceSettlement> settlements = res.get(s);
-            BigDecimal diffAmount = settlements.stream().map(InsPlyIncomeInvoiceSettlement::getSettlementPaymentDifference).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
-            BigDecimal actualReceivedAmount = settlements.stream().map(InsPlyIncomeInvoiceSettlement::getActualReceivedAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
-            dto.setSettledAmount(actualReceivedAmount.toString());
-            dto.setUnSettledAmount(BigDecimal.ZERO.toString());
-            dto.setTotalReceivable(BigDecimalUtil.add(diffAmount, actualReceivedAmount).toString());
-            dto.setTotalPaymentDifference(diffAmount);
-            dtos.add(dto);
-        }
-        pagDto.setRecords(dtos);
-        return pagDto;
+        // 改为复用全量查询方法,从 ins_ply_income 出发,保持数据口径一致
+        // 时间范围通过 vo.startTime / vo.endTime 由 getReceiverSettlementReport SQL 中的 ipii.invoice_time 过滤
+        log.info("平台协议应收-结算报表-对接人结算报表查询(按时间范围)。settlementReportQueryVo=[{}]", JSONUtil.toJsonStr(vo));
+        return this.receiverSettlementReport(page, vo);
     }
 
     /**

+ 24 - 119
tenant/organization/src/main/java/com/jzg/organization/service/impl/importincome/ImportIncomeServiceImpl.java

@@ -5,21 +5,12 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.excel.EasyExcel;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.jzg.commons.constants.ProductsType;
-import com.jzg.commons.core.base.BaseController;
-import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.finance.po.InsPlyIncome;
 import com.jzg.commons.entity.finance.vo.importimcome.*;
 import com.jzg.commons.entity.orders.po.InsOrdersPolicy;
-import com.jzg.commons.entity.quote.vo.orders.InsOrdersVo;
-import com.jzg.commons.entity.vo.AgreementVo;
-import com.jzg.commons.entity.vo.InsFeeOrdersVo;
-import com.jzg.commons.util.idgen.IdGenerate;
-import com.jzg.organization.client.InsOrdersClient;
 import com.jzg.organization.excel.listener.InvoiceReceivbleExcel4AllListener;
 import com.jzg.organization.mapper.InsOrdersPolicyMapper;
 import com.jzg.organization.mapper.InsPlyIncomeMapper;
-import com.jzg.organization.mapper.PtlAgreementMapper;
 import com.jzg.organization.service.impl.ExportBaseServiceImpl;
 import com.jzg.organization.service.importincome.ImportIncomeService;
 import org.slf4j.Logger;
@@ -30,8 +21,6 @@ import org.springframework.web.multipart.MultipartFile;
 
 import java.io.InputStream;
 import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -45,13 +34,9 @@ public class ImportIncomeServiceImpl implements ImportIncomeService {
     @Autowired
     private ExportBaseServiceImpl exportBaseService;
     @Autowired
-    private BaseController baseController;
-    @Autowired
-    private InsOrdersClient insOrdersClient;
-    @Autowired
     private InsOrdersPolicyMapper insOrdersPolicyMapper;
     @Autowired
-    private PtlAgreementMapper ptlAgreementMapper;
+    private InsPlyIncomeMapper insPlyIncomeMapper;
 
     private static final Logger log = LoggerFactory.getLogger(ImportIncomeServiceImpl.class);
 
@@ -107,89 +92,6 @@ public class ImportIncomeServiceImpl implements ImportIncomeService {
         return importExcelResultVo;
     }
 
-    /**
-     * 对表格中的内容进行扩展
-     *
-     * @param excelContents
-     * @author lipf
-     * @date 2026/8/4 9:22
-     */
-    @Override
-    public List<ImportContentExt> fillExcelContent4Private(List<ExcelContent4PrivateSuperviseNoCar> excelContents) {
-        log.info("为私有订单填充数据:excelContents.size=[{}]", CollUtil.size(excelContents));
-        return List.of();
-    }
-
-    /**
-     * 批量处理数据
-     * @param updateExcel 要修改的数据
-     * @param insertExcel 要新增的数据
-     */
-    @Override
-    public ImportContentExt spliceData(ImportContentExt vo,
-                                        List<InsPlyIncome> insertExcel,
-                                        List<InsPlyIncome> updateExcel) {
-
-        // 查询数据库中是否已存在该保单号
-        InsPlyIncome existIncome = baseMapper.selectOne(new LambdaQueryWrapper<InsPlyIncome>()
-                .eq(InsPlyIncome::getJqPolicyNo, vo.getJqPolicyNo()));
-
-        // 封装修改数据
-        InsPlyIncome insPlyIncome = new InsPlyIncome();
-        BeanUtil.copyProperties(vo,insPlyIncome);
-        insPlyIncome.setId(IdGenerate.nextId());
-        insPlyIncome.setLicenseNo(vo.getLicenseNo());
-        insPlyIncome.setJqPolicyNo(vo.getJqPolicyNo());
-        insPlyIncome.setJqSuperviseCostsProportion(vo.getJqSuperviseCostsProportion());
-        insPlyIncome.setJqOtherCostsProportion(vo.getJqOtherCostsProportion());
-        insPlyIncome.setSyPolicyNo(vo.getSyPolicyNo());
-        insPlyIncome.setSySuperviseCostsProportion(vo.getSySuperviseCostsProportion());
-        insPlyIncome.setSyOtherCostsProportion(vo.getSyOtherCostsProportion());
-        insPlyIncome.setJyPolicyNo(vo.getJyPolicyNo());
-        insPlyIncome.setJySuperviseCostsProportion(vo.getJySuperviseCostsProportion());
-        insPlyIncome.setJyOtherCostsProportion(vo.getJyOtherCostsProportion());
-        // 签单时间
-        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-        insPlyIncome.setSigningTime(LocalDateTime.parse(vo.getSigningTime(), formatter));
-//        // 协议编号
-//        insPlyIncome.setAgreementId(ptlAgreement.getId());
-//        insPlyIncome.setAgreementName(ptlAgreement.getAgreementName());
-//        insPlyIncome.setAgreementType(ptlAgreement.getAgreementType().toString());
-//        insPlyIncome.setSystemCode(ptlAgreement.getSystemCode());
-        // 险种编号
-        insPlyIncome.setProductId(ProductsType.getCodeByDesc(vo.getProductName()));
-        // 险种名称
-        insPlyIncome.setProductName(vo.getProductName());
-        // 被保险人姓名
-        insPlyIncome.setInsuredPerson(vo.getInsuredPerson());
-        // 对接人信息
-        insPlyIncome.setContactPerson(vo.getContactPerson());
-        insPlyIncome.setContactPersonPhone(vo.getContactPersonPhone());
-        // 数据库不存在 → 直接失败
-        if (Objects.isNull(existIncome)) {
-            // 加入修改列表
-            // 机构id
-            insPlyIncome.setDeptId(baseController.getUserDeptId());
-            insPlyIncome.setOrderNo(vo.getOrderNo());
-            insertExcel.add(insPlyIncome);
-        }else{
-            // 数据库已存在 → 继续后续校验
-            // 判断已开票 / 已结算
-            String settlementFlag = "1";
-            if (settlementFlag.equals(existIncome.getSuperviseSettlement()) || settlementFlag.equals(existIncome.getOtherSettlement())
-                    || settlementFlag.equals(existIncome.getJySuperviseSettlement()) || settlementFlag.equals(existIncome.getJyOtherSettlement())
-                    || settlementFlag.equals(existIncome.getPlatformSuperviseSettlement()) || settlementFlag.equals(existIncome.getPlatformOtherSettlement())) {
-                vo.setErrorMessage("应收数据已结算");
-                return vo;
-            }
-            insPlyIncome.setId(existIncome.getId());
-            // 加入修改列表
-            updateExcel.add(insPlyIncome);
-        }
-        return null;
-    }
-
-
     /**
      * 对表格中的内容进行扩展
      * <p>
@@ -244,28 +146,31 @@ public class ImportIncomeServiceImpl implements ImportIncomeService {
             }
             log.info("处理订单号是[{}]的订单",orderNO);
             ext.setOrderNo(orderNO);
-            HttpResult<InsOrdersVo> insOrdersVoHttpResult = insOrdersClient.selectById(orderNO);
-            InsOrdersVo data = insOrdersVoHttpResult.getData();
-            if (data!= null){
-                BeanUtil.copyProperties(data,ext);
-                if(data.getSigningTime() != null){
-                    ext.setSigningTime(data.getSigningTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
-                }
-                String agreementId = data.getAgreementId();
-                if(StrUtil.isNotEmpty(agreementId)){
-                    AgreementVo agreementVo = ptlAgreementMapper.queryById(agreementId);
-                    if(agreementVo != null){
-                        ext.setPartnerCompanyId(agreementVo.getPartnerCompanyId());
-                    }
-                }
-                InsFeeOrdersVo feeOrdersVo = data.getFeeOrdersVo();
-                if(BeanUtil.isEmpty(feeOrdersVo)){
-                    ext.setJqPremium(feeOrdersVo.getJqPremium());
-                    ext.setSyPremium(feeOrdersVo.getSyPremium());
-                    ext.setJyPremium(feeOrdersVo.getJyPremium());
-                }
 
+            LambdaQueryWrapper<InsPlyIncome> wrapper = new LambdaQueryWrapper();
+            wrapper.eq(InsPlyIncome::getOrderNo,orderNO);
+            List<InsPlyIncome> insPlyIncomes = insPlyIncomeMapper.selectList(wrapper);
+            if(CollUtil.isEmpty(insPlyIncomes)){
+                log.info("订单号为[{}]的数据没有进入应收",orderNO);
+                continue;
             }
+            InsPlyIncome insPlyIncome = insPlyIncomes.get(0);
+
+            ext.setIncomeId(insPlyIncome.getId());
+            ext.setContactPerson(insPlyIncome.getContactPerson());
+            ext.setParternerCompanyId(insPlyIncome.getPartnerCompanyId());
+
+
+            // 校验 手续费等比例是否一致
+            String jqSuperviseCostsProportion = insPlyIncome.getJqSuperviseCostsProportion();
+            String sySuperviseCostsProportion = insPlyIncome.getSySuperviseCostsProportion();
+            String jySuperviseCostsProportion = insPlyIncome.getJySuperviseCostsProportion();
+            String jqOtherCostsProportion = insPlyIncome.getJqOtherCostsProportion();
+            String syOtherCostsProportion = insPlyIncome.getSyOtherCostsProportion();
+            String jyOtherCostsProportion = insPlyIncome.getJyOtherCostsProportion();
+
+
+
             res.add(ext);
         }
         return res;

+ 0 - 17
tenant/organization/src/main/java/com/jzg/organization/service/importincome/ImportIncomeService.java

@@ -24,23 +24,6 @@ public interface ImportIncomeService {
      */
     <T extends InsuranceData> List<ImportContentExt> fillExcelContent4All(List<T> excelContents);
 
-    /**
-     * 对表格中的内容进行扩展
-     *
-     * @author lipf
-     * @date 2026/8/4 9:22
-     */
-    public List<ImportContentExt> fillExcelContent4Private(List<ExcelContent4PrivateSuperviseNoCar> excelContents);
-
-    /**
-     * 批量处理数据
-     * @param updateExcel
-     * @param insertExcel
-     */
-    public ImportContentExt spliceData(ImportContentExt vo,
-                                       List<InsPlyIncome> insertExcel,
-                                       List<InsPlyIncome> updateExcel);
-
     /**
      * <p>
      * 1. 获取保司名称

+ 25 - 5
tenant/organization/src/main/resources/mapper/PtlAgreementCostExternalMapper.xml

@@ -32,6 +32,7 @@
 
     <resultMap id="ExternalListVoMap" type="com.jzg.commons.entity.vo.CostExternalListVo">
         <result column="id" property="id" />
+        <result column="ptl_agreement_id" property="ptlAgreementId" />
         <result column="agreement_code" property="agreementCode" />
         <result column="agreement_abbreviation" property="agreementAbbreviation" />
         <result column="product_name" property="productName" />
@@ -40,15 +41,23 @@
         <result column="is_inquiry" property="isInquiry" />
         <result column="effective_time" property="effectiveTime" />
         <result column="failure_time" property="failureTime" />
-        <result column="effective" property="effective" />
+        <result column="audit_method" property="auditMethod" />
         <result column="audit_status" property="auditStatus" />
         <result column="is_enabled" property="isEnabled" />
+        <result column="review_description" property="reviewDescription" />
         <result column="contact_person" property="contactPerson" />
         <result column="contact_mobile" property="contactMobile" />
-        <result column="audit_method" property="auditMethod" />
+        <result column="audit_person" property="auditPerson" />
+        <result column="audit_time" property="auditTime" />
         <result column="priority_level" property="priorityLevel" />
+        <result column="add_throw" property="addThrow" />
+        <result column="keep_point_ratio" property="keepPointRatio" />
         <result column="create_time" property="createTime" />
         <result column="create_by" property="createBy" />
+        <result column="update_time" property="updateTime" />
+        <result column="update_by" property="updateBy" />
+        <result column="is_delete" property="isDelete" />
+        <result column="system_code" property="systemCode" />
         <collection property="costExternalTypeAdds" column="id" ofType="com.jzg.commons.entity.vo.CostExternalTypeVo" select="selectCostExternalTypeVo" />
     </resultMap>
 
@@ -121,19 +130,30 @@
     <select id="pageList" resultMap="ExternalListVoMap">
         SELECT
         ce.id,
+        ce.ptl_agreement_id,
         ce.product_name,
         ce.product_id,
-        ce.cost_describe,
-        ce.is_inquiry,
         ce.effective_time,
         ce.failure_time,
+        ce.audit_method,
         ce.audit_status,
         ce.is_enabled,
+        ce.review_description,
+        ce.is_inquiry,
+        ce.cost_describe,
         ce.contact_person,
         ce.contact_mobile,
-        ce.audit_method,
+        ce.audit_person,
+        ce.audit_time,
         ce.create_time,
         ce.create_by,
+        ce.update_time,
+        ce.update_by,
+        ce.is_delete,
+        ce.system_code,
+        ce.priority_level,
+        ce.add_throw,
+        ce.keep_point_ratio,
         pa.agreement_code,
         pa.agreement_abbreviation
         FROM