Просмотр исходного кода

Merge branch 'master' into wrq_dev

wangrq 3 месяцев назад
Родитель
Сommit
e7fb8a5346
31 измененных файлов с 456 добавлено и 174 удалено
  1. 4 1
      authentication/src/main/java/com/jzg/config/JzgAuthenticationProvider.java
  2. 17 0
      commons/src/main/java/com/jzg/commons/entity/dto/PtlAgreementCostEnd.java
  3. 20 0
      commons/src/main/java/com/jzg/commons/entity/finance/vo/InvoiceRecordResult.java
  4. 9 0
      commons/src/main/java/com/jzg/commons/entity/po/InsFeeOrders.java
  5. 3 0
      commons/src/main/java/com/jzg/commons/entity/po/SysUserJzgInfo.java
  6. 9 2
      commons/src/main/java/com/jzg/commons/util/BuildDescUtils.java
  7. 17 2
      commons/src/main/java/com/jzg/commons/util/MinioUtils.java
  8. 6 6
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/client/OrgClient.java
  9. 1 3
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/component/RequestComponent.java
  10. 36 23
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/DateUtil.java
  11. 73 14
      tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/component/HengBangCrawlerRequestComponent.java
  12. 27 14
      tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/entity/request/HbCrawlerCalculationRequest.java
  13. 1 20
      tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/service/Impl/HengBangCrawlerRequestImpl.java
  14. 0 0
      tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/utils/HengBangAESUtil.java
  15. 21 1
      tenant/insurance/quotation-huanong/src/main/java/com/jzg/quotation/huanong/crawler/service/impl/HuaNongCrawlerRequestImpl.java
  16. 28 8
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/service/Impl/HuaTaiCrawlerRequestImpl.java
  17. 4 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/aspect/QuoteVerificationAspect.java
  18. 8 2
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeAuditServiceImpl.java
  19. 3 1
      tenant/insurance/quotation-summary/src/main/resources/mapper/InsFeeAuditMapper.xml
  20. 38 44
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/impl/TaiShanCrawlerQuoteProcessServiceImpl.java
  21. 7 0
      tenant/organization/src/main/java/com/jzg/organization/controller/ReceivableController.java
  22. 5 0
      tenant/organization/src/main/java/com/jzg/organization/mapper/ReceivableMapper.java
  23. 2 0
      tenant/organization/src/main/java/com/jzg/organization/service/SysUserJzgInfoService.java
  24. 27 21
      tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java
  25. 5 1
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysDistributionSettingServiceImpl.java
  26. 3 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserAccountServiceImpl.java
  27. 8 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserJzgInfoServiceImpl.java
  28. 2 2
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserServiceImpl.java
  29. 1 1
      tenant/organization/src/main/resources/mapper/PtlAgreementUndwrtRulesMapper.xml
  30. 71 6
      tenant/organization/src/main/resources/mapper/ReceivableMapper.xml
  31. 0 1
      tenant/organization/src/main/resources/mapper/SysDistributionSettingMapper.xml

+ 4 - 1
authentication/src/main/java/com/jzg/config/JzgAuthenticationProvider.java

@@ -406,7 +406,10 @@ public class JzgAuthenticationProvider implements AuthenticationProvider {
                 log.info("租户登录异常:用户不存在。 userId=[{}]",userId);
                 throw new SystemException("业务员不存在");
             }
-            SysUserJzgInfo sysUserJzgInfo = sysUserJzgInfos.get(0);
+            SysUserJzgInfo sysUserJzgInfo = sysUserJzgInfos.stream()
+                    .filter(x -> Objects.equals(x.getSystemCode(), system))
+                    .findFirst()
+                    .orElse(null);
             // 租户系统才会校验这个, 后台管理系统,没有租户的概念
             if(this.isTenantLogin(system)){
                 if (sysUserJzgInfo.cannotLogin()) {

+ 17 - 0
commons/src/main/java/com/jzg/commons/entity/dto/PtlAgreementCostEnd.java

@@ -93,6 +93,9 @@ public class PtlAgreementCostEnd {
         @Schema(description = "属性编码")
         private String attrCode;
 
+        @Schema(description = "属性类型")
+        private String attrType;
+
         @Schema(description = "左操作数")
         private String min;
 
@@ -105,6 +108,20 @@ public class PtlAgreementCostEnd {
         @Schema(description = "操作符")
         private String operator;
 
+        @Schema(description = "费用规则字典")
+        private List<PtlAgreementCostRulesDictLabalDto> dictLabal;
+
+    }
+
+    @Data
+    @Schema(description = "费用规则字典")
+    public static class PtlAgreementCostRulesDictLabalDto {
+
+        @Schema(description = "编码")
+        private String code;
+
+        @Schema(description = "编码")
+        private String name;
     }
 
     @Data

+ 20 - 0
commons/src/main/java/com/jzg/commons/entity/finance/vo/InvoiceRecordResult.java

@@ -128,4 +128,24 @@ public class InvoiceRecordResult extends PageRequest {
      * 开票日期
      */
     private String createTime;
+
+    /**
+     * 跟单费的年份
+     */
+    private String year;
+
+    /**
+     * 跟单费的月份
+     */
+    private String month;
+
+    /**
+     * 分支公司id
+     */
+    private String partnerCompanyId;
+
+    /**
+     * 分支公司名称
+     */
+    private String partnerCompanyName;
 }

+ 9 - 0
commons/src/main/java/com/jzg/commons/entity/po/InsFeeOrders.java

@@ -222,18 +222,27 @@ public class InsFeeOrders {
     @Schema(description = "一级分销员id")
     private String firstDistributorId;
 
+    @Schema(description = "一级分销比例")
+    private BigDecimal firstDistributionRatio;
+
     @Schema(description = "二级分销费")
     private BigDecimal secondDistributionFee;
 
     @Schema(description = "二级分销员id")
     private String secondDistributorId;
 
+    @Schema(description = "二级分销比例")
+    private BigDecimal secondDistributionRatio;
+
     @Schema(description = "三级分销费")
     private BigDecimal thirdDistributionFee;
 
     @Schema(description = "三级分销员id")
     private String thirdDistributorId;
 
+    @Schema(description = "三级分销比例")
+    private BigDecimal thirdDistributionRatio;
+
     @Schema(description = "车牌号")
     @TableField(exist = false)
     private String licenseNo;

+ 3 - 0
commons/src/main/java/com/jzg/commons/entity/po/SysUserJzgInfo.java

@@ -147,6 +147,9 @@ public class SysUserJzgInfo extends BaseModel implements Serializable {
     @Schema(description = "邮政编码")
     private String postalCode;
 
+    @TableField(value = "email")
+    private String email;
+
     @TableField(value = "blood_type")
     @Schema(description = "血型")
     private String bloodType;

+ 9 - 2
commons/src/main/java/com/jzg/commons/util/BuildDescUtils.java

@@ -21,7 +21,7 @@ public class BuildDescUtils {
 
         for (PtlAgreementUndwrtRulesAttr link : linkList) {
             PtlAgreementUndwrtRulesAttr ptlAgreementUndwrtRulesAttr = attrMap.get(link.getAttrCode());
-
+            ptlAgreementUndwrtRulesAttr.setDictLabal(link.getDictLabal());
             if (ptlAgreementUndwrtRulesAttr == null) {
                 continue;
             }
@@ -36,7 +36,14 @@ public class BuildDescUtils {
                 if(link.getMinArray() != null && link.getMinArray().length > 0){
                     desc.append(ptlAgreementUndwrtRulesAttr.getAttrName()).append("包含");
                     for (int k=0 ; k<link.getMinArray().length; k++){
-                        PtlAgreementUndwrtRulesDictLabal ptlAgreementUndwrtRulesDictLabal = ptlAgreementUndwrtRulesAttr.getDictLabal().stream().filter(x -> Arrays.asList(link.getMinArray()).contains(x.getCode())).findFirst().orElse(null);
+                        PtlAgreementUndwrtRulesDictLabal ptlAgreementUndwrtRulesDictLabal = null;
+                        for (PtlAgreementUndwrtRulesDictLabal x : ptlAgreementUndwrtRulesAttr.getDictLabal()) {
+                            if (Arrays.asList(link.getMinArray()).contains("select".equals(attrType) ? x.getName() : x.getCode())) {
+                                ptlAgreementUndwrtRulesDictLabal = x;
+                                link.getMinArray()[k] = null;
+                                break;
+                            }
+                        }
                         desc.append(null != ptlAgreementUndwrtRulesDictLabal ? ptlAgreementUndwrtRulesDictLabal.getName() : "").append(",");
                     }
 

+ 17 - 2
commons/src/main/java/com/jzg/commons/util/MinioUtils.java

@@ -12,6 +12,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.compress.utils.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
 import org.springframework.stereotype.Component;
@@ -43,6 +44,14 @@ public class MinioUtils {
         log.info("MinioClient has been initialized: {}", minioClient);
     }
 
+
+    private static String minioPublicUrl;
+
+    @Value("${minio.url:https://minio.baoxianzhanggui.com}")
+    public void setMinioPublicUrl(String minioPublicUrl) {
+        MinioUtils.minioPublicUrl = minioPublicUrl;
+    }
+
     public static MinioClient getMinioClient() {
         return MinioUtils.minioClient;
     }
@@ -399,9 +408,15 @@ public class MinioUtils {
      */
     @SneakyThrows(Exception.class)
     public static String getPresignedObjectUrl(String bucketName, String objectName) {
+//        try {
+//            GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).method(Method.GET).build();
+//            return minioClient.getPresignedObjectUrl(args);
+//        } catch (Exception e) {
+//            return null;
+//        }
+        // 重新调整方法  minio 设置公开权限
         try {
-            GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).method(Method.GET).build();
-            return minioClient.getPresignedObjectUrl(args);
+            return minioPublicUrl + "/" + bucketName + "/" + objectName;
         } catch (Exception e) {
             return null;
         }

+ 6 - 6
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/client/OrgClient.java

@@ -122,36 +122,36 @@ public interface OrgClient {
     /**
      * 获取租户分销设置
      */
-    @PostMapping(value = "/sysDistributionSetting/getSettingBySystemCode")
+    @GetMapping(value = "/sysDistributionSetting/getSettingBySystemCode")
     HttpResult<SysDistributionSetting> getSettingBySystemCode();
 
     /**
      * 获取机构
      */
     @GetMapping(value = "/dept/deptGet")
-    HttpResult<SysDeptVo> deptGet(String id);
+    HttpResult<SysDeptVo> deptGet(@RequestParam String id);
 
     /**
      * 获取租户用户
      */
     @GetMapping(value = "userInfo/getUserInfoByMobile")
-    HttpResult<SysUserJzgInfo> getUserInfoByMobile(String mobile);
+    HttpResult<SysUserJzgInfo> getUserInfoByMobile(@RequestParam String mobile);
 
     /**
      * 获取上级推荐人
      */
     @GetMapping(value = "esmUserReferrer/getReferrer")
-    HttpResult<EsmUserReferrer> getReferrer(String id);
+    HttpResult<EsmUserReferrer> getReferrer(@RequestParam String id);
 
 
     /**
      * 获取租户用户
      */
     @GetMapping(value = "userInfo/getUserInfo")
-    HttpResult<SysUserJzgInfo> getUserInfo(String id);
+    HttpResult<SysUserJzgInfo> getUserInfo(@RequestParam String id);
 
     @GetMapping(value = "userInfo/getUserInfoById")
-    HttpResult<SysUserJzgInfo> getUserInfoById(String id);
+    HttpResult<SysUserJzgInfo> getUserInfoById(@RequestParam String id);
 
     @PostMapping(value = "receivable/restockInsPlyIncome")
     void restockInsPlyIncome(@RequestBody InsOrderAdjust insOrderAdjust);

+ 1 - 3
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/component/RequestComponent.java

@@ -32,8 +32,6 @@ import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
-import java.util.Map;
-import java.util.Optional;
 import java.time.Duration;
 import java.util.Map;
 import java.util.Optional;
@@ -393,7 +391,7 @@ public class RequestComponent {
     public <Response> ResponseEntity<Response> post(String url, String body, Class<Response> responseClass, HttpHeaders headers) {
         body = Optional.ofNullable(body).orElse("");
         log.info("URL的值:{},body的值:{}", url, body);
-        WebClient webClient = selectNoSSLWebClient();
+//        WebClient webClient = selectNoSSLWebClientWithProxy("127.0.0.1", 9001);
         try {
             // 创建一个不带Accept-Encoding的请求头,避免服务器返回压缩数据
             HttpHeaders requestHeaders = new HttpHeaders();

+ 36 - 23
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/DateUtil.java

@@ -418,47 +418,60 @@ public class DateUtil {
 
     private static final DateTimeFormatter INPUT_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
     private static final DateTimeFormatter OUTPUT_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+    private static final ZoneId ASIA_SHANGHAI = ZoneId.of("Asia/Shanghai");
 
     /**
-     * 获取投保日期的下一天0点(北京时间)并转为UTC ISO8601格式
-     * 驾意险起保日期默认为投保日期的下一天的0点
+     * 获取北京时间下一天0点对应的UTC时间字符串
+     * 驾意险起保日期默认为投保日期的下一天的0点(北京时间)
      */
     public static String getNextDayMidnightUtc() {
-        LocalDate tomorrow = LocalDate.now().plusDays(1);
+        LocalDate tomorrow = LocalDate.now(ASIA_SHANGHAI).plusDays(1);
         String beijingTime = tomorrow.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00:00:00";
         return toUtcDateTime(beijingTime);
     }
 
     /**
-     * 获取指定UTC日期时间的下一天0点(北京时间)并转为UTC ISO8601格式
-     * 驾意险不支持即时起保,需调整起保日期为主险投保日期的下一日0时
+     * 判断一个UTC时间是否对应北京时间的0点(用于驾意险起保时间判断)
      *
-     * @param utcDateTime 主险起保UTC时间(ISO8601格式,如 2026-07-04T16:00:00.000Z)
-     * @return 下一天北京时间0点对应的UTC ISO8601格式
+     * @param utcTime UTC时间字符串(ISO8601格式,如 2026-06-25T16:00:00.000Z 即北京06-26 00:00:00)
+     * @return true=北京时间0点
      */
-    public static String getNextDayMidnightUtc(String utcDateTime) {
-        ZonedDateTime utcZoned = ZonedDateTime.parse(utcDateTime, DateTimeFormatter.ISO_DATE_TIME);
-        ZonedDateTime beijingZoned = utcZoned.withZoneSameInstant(ZoneId.of("Asia/Shanghai"));
-        LocalDate nextDay = beijingZoned.toLocalDate().plusDays(1);
-        String beijingTime = nextDay.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00:00:00";
+    public static boolean isBeijingMidnight(String utcTime) {
+        ZonedDateTime utcZdt = ZonedDateTime.parse(utcTime, DateTimeFormatter.ISO_DATE_TIME);
+        ZonedDateTime bjZdt = utcZdt.withZoneSameInstant(ASIA_SHANGHAI);
+        return "00:00:00".equals(bjZdt.toLocalTime().toString());
+    }
+
+    /**
+     * 获取驾意险起保时间对应的UTC时间字符串
+     * 驾意险不支持即时起保:
+     * - 调用方需先通过 isBeijingMidnight 判断,已是0点则直接复用原值,无需调用此方法
+     * - 若北京时间不是0点,则调整为下一日北京时间0点,再转为UTC
+     *
+     * @param utcTime 主险起保时间(ISO8601 UTC格式,如 2026-07-04T08:00:00.000Z 即北京16:00)
+     * @return UTC时间字符串
+     */
+    public static String getNextDayMidnightUtc(String utcTime) {
+        ZonedDateTime utcZdt = ZonedDateTime.parse(utcTime, DateTimeFormatter.ISO_DATE_TIME);
+        ZonedDateTime bjZdt = utcZdt.withZoneSameInstant(ASIA_SHANGHAI);
+        LocalDate targetDate = bjZdt.toLocalDate();
+        // 非0点则顺延至下一日0点
+        if (!"00:00:00".equals(bjZdt.toLocalTime().toString())) {
+            targetDate = targetDate.plusDays(1);
+        }
+        String beijingTime = targetDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00:00:00";
         return toUtcDateTime(beijingTime);
     }
 
     /**
-     * 将北京时间(yyyy-MM-dd HH:mm:ss)转换为UTC时间(ISO8601格式)
+     * 将北京时间字符串(yyyy-MM-dd HH:mm:ss)转为实际UTC时间(yyyy-MM-dd'T'HH:mm:ss.SSS'Z')
+     * 如 "2026-06-25 16:00:00"(北京)→ "2026-06-25T08:00:00.000Z"(UTC)
      */
     public static String toUtcDateTime(String beijingTime) {
-        // 解析输入的北京时间
         LocalDateTime localDateTime = LocalDateTime.parse(beijingTime, INPUT_FORMAT);
-
-        // 指定时区为中国北京时间
-        ZonedDateTime beijingZoned = localDateTime.atZone(ZoneId.of("Asia/Shanghai"));
-
-        // 转为UTC时区
-        ZonedDateTime utcZoned = beijingZoned.withZoneSameInstant(ZoneId.of("UTC"));
-
-        // 格式化为ISO8601字符串
-        return utcZoned.format(OUTPUT_FORMAT);
+        ZonedDateTime bjZdt = localDateTime.atZone(ASIA_SHANGHAI);
+        ZonedDateTime utcZdt = bjZdt.withZoneSameInstant(ZoneOffset.UTC);
+        return utcZdt.format(OUTPUT_FORMAT);
     }
 
     public static void main(String[] args) throws ParseException {

+ 73 - 14
tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/component/HengBangCrawlerRequestComponent.java

@@ -2,6 +2,8 @@ package com.jzg.quotation.hengbang.crawler.component;
 
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.annotation.JsonInclude;
@@ -10,6 +12,7 @@ import com.jzg.commons.exception.SystemException;
 import com.jzg.quotation.commons.component.RequestComponent;
 import com.jzg.quotation.commons.constant.CacheConstant;
 import com.jzg.quotation.commons.service.ExteriorUtilsRequest;
+import com.jzg.quotation.commons.utils.DateUtil;
 import com.jzg.quotation.commons.utils.RequestObjectConversion;
 import com.jzg.quotation.hengbang.crawler.constant.RequestConstant;
 import com.jzg.quotation.hengbang.crawler.constant.enums.RequestUrl;
@@ -39,6 +42,8 @@ import javax.crypto.spec.SecretKeySpec;
 import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 /**
@@ -302,24 +307,78 @@ public class HengBangCrawlerRequestComponent {
             String json = mapper.writeValueAsString(calculationRequest);
             log.info("提交报价数据请求参数: {}", json);
             req.setHbEncD(HengBangAESUtil.encryptStr(json));
-            HbCrawlerSaleInfoResponse response = requestComponent.toStringPost(RequestUrl.CALCULATION.getRequestUrl(hbCrawlerProperties.getBaseUrl()), req, RequestUrl.CALCULATION.getRequestDescription(), HbCrawlerSaleInfoResponse.class, headers);
-            System.out.println(HengBangAESUtil.decryptStr(response.getHbEncD()));
+
+            String requestJson = mapper.writeValueAsString(req);
+            String url = RequestUrl.CALCULATION.getRequestUrl(hbCrawlerProperties.getBaseUrl());
+            log.info("恒邦calculation请求URL: {}, 请求体: {}", url, requestJson);
+
+            // 使用Hutool发送HTTP POST请求
+            HttpResponse httpResponse = HttpRequest.post(url)
+                    .header(headers)
+                    .body(requestJson)
+                    .timeout(60000)
+                    .execute();
+
+            String responseBody = httpResponse.body();
+            int status = httpResponse.getStatus();
+            log.info("恒邦calculation响应状态码: {}, 响应体(前500字符): {}", status,
+                    responseBody != null && responseBody.length() > 500 ? responseBody.substring(0, 500) : responseBody);
+
+            // 处理非2xx响应
+            if (!httpResponse.isOk()) {
+                if (status == 500) {
+                    JSONObject resObj = JSONObject.parseObject(responseBody);
+                    String detail = resObj.getString("detail");
+                    if (StrUtil.isNotBlank(detail) && detail.contains("重复投保")) {
+                        String time = extractDuplicateEndTime(detail);
+                        if (time != null) {
+                            calculationRequest.setBegintimeCi(DateUtil.toUtcDateTime(time));
+                            calculationRequest.setBegintimeBi(DateUtil.toUtcDateTime(time));
+                        }
+                        return getCalculationResult(calculationRequest, headers);
+                    }
+                    return StrUtil.isNotBlank(detail) ? detail : responseBody;
+                } else if (status == 400) {
+                    JSONObject resObj = JSONObject.parseObject(responseBody);
+                    String title = resObj.getString("title");
+                    return StrUtil.isNotBlank(title) ? title : responseBody;
+                }
+                log.error("恒邦calculation接口返回非2xx: {}, 响应: {}", status, responseBody);
+            }
+
+            // Jackson解析响应
+            HbCrawlerSaleInfoResponse response = mapper.readValue(responseBody, HbCrawlerSaleInfoResponse.class);
+            if (response.getHbEncD() == null) {
+                throw new SystemException("恒邦calculation接口返回数据缺少hbEncD字段,原始响应: " + responseBody);
+            }
             String resJson = HengBangAESUtil.decryptStr(response.getHbEncD());
+            log.info("恒邦calculation解密后响应: {}", resJson);
             return resJson;
-        } catch (WebClientResponseException e) {
-            log.error("恒邦calculation接口调用失败[{}]: {}", e.getStatusCode(), e.getResponseBodyAsString());
-            final JSONObject jsonObject = JSONObject.parseObject(e.getResponseBodyAsString());
-            if (jsonObject.getInteger("status") == 500) {
-                String detail = jsonObject.getString("detail");
-                return StrUtil.isNotBlank(detail) ? detail : e.getResponseBodyAsString();
-            } else if (jsonObject.getInteger("status") == 400) {
-                return jsonObject.getString("title");
-            } else {
-                throw new SystemException(e.getMessage());
-            }
+        } catch (SystemException e) {
+            throw e;
         } catch (Exception e) {
-            throw new SystemException(e.getMessage());
+            log.error("恒邦calculation接口调用异常", e);
+            throw new SystemException("恒邦报价第二步异常: " + e.getMessage());
+        }
+    }
+
+
+    // 重复投保提取时间
+    private static final Pattern DUPLICATE_END_TIME_PATTERN = Pattern.compile("终保日期 (\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2})");
+
+    /**
+     * 提取系统自动分配的起保时间
+     *
+     * @param calculationResult 核心提示
+     * @return 提取到的时间字符串,未提取到返回 null
+     */
+    public String extractDuplicateEndTime(String calculationResult) {
+        Matcher matcher = DUPLICATE_END_TIME_PATTERN.matcher(calculationResult);
+        if (matcher.find()) {
+            String shortEndTime = matcher.group(1); // 提取到 2025-12-14 16:00
+            return shortEndTime + ":00"; // 补全秒数为 2025-12-14 16:00:00
         }
+        return null;
     }
 
     /**

+ 27 - 14
tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/entity/request/HbCrawlerCalculationRequest.java

@@ -1,7 +1,7 @@
 package com.jzg.quotation.hengbang.crawler.entity.request;
 
 import cn.hutool.core.collection.CollUtil;
-import com.alibaba.excel.util.StringUtils;
+import cn.hutool.core.util.StrUtil;
 import com.jzg.commons.entity.quote.vo.AccidentalDrivingVo;
 import com.jzg.commons.entity.quote.vo.KindInfoVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
@@ -88,16 +88,25 @@ public class HbCrawlerCalculationRequest extends HbBaseRequest {
         }
         if (CollUtil.isNotEmpty(kindInfoVoList)) {
             this.epersonliabilityList = getEpersonliabilityList(kindInfoVoList, depreciationPrice);
-            this.begintimeBi = DateUtil.toUtcDateTime(quoteVo.getBiRiskInfoVo().getStartDate());
+            // 防 NPE:BiRiskInfoVo 或 startDate 为空时跳过 begintimeBi 赋值
+            if (Objects.nonNull(quoteVo.getBiRiskInfoVo()) && Objects.nonNull(quoteVo.getBiRiskInfoVo().getStartDate())) {
+                this.begintimeBi = DateUtil.toUtcDateTime(quoteVo.getBiRiskInfoVo().getStartDate());
+            }
             this.risktype = "2";
         } else {
             this.epersonliabilityList = new ArrayList<>();
         }
-        // 驾意险不支持即时起保,起保日期为主险投保日期的下一日0时(北京时间)
+        // 驾意险不支持即时起保,若传入时间不是0点则自动改为下一日0点(北京时间),再转为UTC
         if ("2".equals(this.risktype) && this.begintimeBi != null) {
-            this.begintimeAccident = DateUtil.getNextDayMidnightUtc(this.begintimeBi);
+            // 商业险起始时间已是北京时间0点,驾意险直接复用,无需取下一日0时
+            this.begintimeAccident = DateUtil.isBeijingMidnight(this.begintimeBi)
+                    ? this.begintimeBi
+                    : DateUtil.getNextDayMidnightUtc(this.begintimeBi);
         } else if ("1".equals(this.risktype) && this.begintimeCi != null) {
-            this.begintimeAccident = DateUtil.getNextDayMidnightUtc(this.begintimeCi);
+            // 交强险起始时间已是北京时间0点,驾意险直接复用,无需取下一日0时
+            this.begintimeAccident = DateUtil.isBeijingMidnight(this.begintimeCi)
+                    ? this.begintimeCi
+                    : DateUtil.getNextDayMidnightUtc(this.begintimeCi);
         } else {
             this.begintimeAccident = DateUtil.getNextDayMidnightUtc();
         }
@@ -123,6 +132,9 @@ public class HbCrawlerCalculationRequest extends HbBaseRequest {
     public List<EpersonliabilityDTO> getEpersonliabilityList(List<KindInfoVo> kindInfoVoList, String depreciationPrice) {
         List<EpersonliabilityDTO> epersonliabilityDTOList = new ArrayList<>();
         for (KindInfoVo kindInfoVo : kindInfoVoList) {
+            if (StrUtil.isBlank(kindInfoVo.getAmount())) {
+                throw new RuntimeException(kindInfoVo.getPlatformKindName() + "保险保额为空,请检查数据!");
+            }
             EpersonliabilityDTO epersonliabilityDTO = new EpersonliabilityDTO();
             epersonliabilityDTO.setKindcode(kindInfoVo.getKindCode());
             epersonliabilityDTO.setLiabname(kindInfoVo.getKindName());
@@ -194,9 +206,9 @@ public class HbCrawlerCalculationRequest extends HbBaseRequest {
     public static AccidentInsuranceDTO convertToAccidentInsuranceDTO(RiskInfoVo biRiskInfoVo, AccidentalDrivingVo vo) {
         AccidentInsuranceDTO dto = new AccidentInsuranceDTO();
         dto.setNonriskcode(vo.getProductCode().split("_")[1]);
-        dto.setProgramcode(vo.getProductCode());
-        dto.setProgramname("1119险种5座非营运客车保额525000保费99.9(山西)");
         dto.setCompanycode("0107");
+        dto.setProgramcode(vo.getProductCode());
+        dto.setProgramname(vo.getProductName());
         dto.setIfdefault(true);
         dto.setBuynum(vo.getQuantity());
         List<GgriskprogramdetailsDTO> detailsList = getGgriskprogramdetailsList(vo.getProductCode().split("_")[1], vo.getProductCode());
@@ -331,6 +343,9 @@ public class HbCrawlerCalculationRequest extends HbBaseRequest {
     private String clauseType;
     private List<String> ecarChargingPosts;
     private List<String> carInsureDevices;
+    // 正确请求中 begintimeAccident/endtimeAccident 紧跟 carInsureDevices(位于 drivingtype 之前)
+    private String begintimeAccident;
+    private String endtimeAccident;
     private String effectfLag;
     private String drivingtype;
     private String relationCarOwner = "a";
@@ -347,8 +362,6 @@ public class HbCrawlerCalculationRequest extends HbBaseRequest {
     private String taxonomyCode;
     private String epolicyFlag;
     private String accidentEpolicyFlag;
-    private String begintimeAccident;
-    private String endtimeAccident;
     private HbCrawlerRecordResponse transferVehicle;
 
     @Data
@@ -425,19 +438,19 @@ public class HbCrawlerCalculationRequest extends HbBaseRequest {
         @Serial
         private static final long serialVersionUID = -9183755801236888529L;
 
-        private String createtime;
+        private String programcode;
         private String paramname;
         private String paramvalue;
-        private String programcode;
+        private String createtime;
         private String updatetime;
         private String validind;
 
         public GgriskprogramparamlDTO(String createtime, String paramname, String paramvalue, String programcode, String updatetime, String validind) {
-            this.createtime = createtime;
-            this.updatetime = updatetime;
+            this.programcode = programcode;
             this.paramname = paramname;
             this.paramvalue = paramvalue;
-            this.programcode = programcode;
+            this.createtime = createtime;
+            this.updatetime = updatetime;
             this.validind = validind;
         }
     }

+ 1 - 20
tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/service/Impl/HengBangCrawlerRequestImpl.java

@@ -53,8 +53,6 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 /**
  * @description: 恒邦财险 爬虫请求
@@ -173,7 +171,7 @@ public class HengBangCrawlerRequestImpl implements HengBangCrawlerRequest {
         }
 
         if (errorMsg.contains("重复投保")) {
-            String time = extractDuplicateEndTime(errorMsg);
+            String time = hbCrawlerRequestComponent.extractDuplicateEndTime(errorMsg);
             if (time != null) {
                 calculationRequest.setBegintimeCi(DateUtil.toUtcDateTime(time));
                 calculationRequest.setBegintimeBi(DateUtil.toUtcDateTime(time));
@@ -243,23 +241,6 @@ public class HengBangCrawlerRequestImpl implements HengBangCrawlerRequest {
         calculationRequest.setAccidentEpolicyFlag(accidentList.isEmpty() ? "" : "Y");
     }
 
-    // 重复投保提取时间
-    private static final Pattern DUPLICATE_END_TIME_PATTERN = Pattern.compile("终保日期 (\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2})");
-
-    /**
-     * 提取系统自动分配的起保时间
-     *
-     * @param calculationResult 核心提示
-     * @return 提取到的时间字符串,未提取到返回 null
-     */
-    private String extractDuplicateEndTime(String calculationResult) {
-        Matcher matcher = DUPLICATE_END_TIME_PATTERN.matcher(calculationResult);
-        if (matcher.find()) {
-            String shortEndTime = matcher.group(1); // 提取到 2025-12-14 16:00
-            return shortEndTime + ":00"; // 补全秒数为 2025-12-14 16:00:00
-        }
-        return null;
-    }
 
     /**
      * 获取当前时间2小时以后的时间

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/utils/HengBangAESUtil.java


+ 21 - 1
tenant/insurance/quotation-huanong/src/main/java/com/jzg/quotation/huanong/crawler/service/impl/HuaNongCrawlerRequestImpl.java

@@ -44,6 +44,8 @@ import org.springframework.http.HttpHeaders;
 import java.time.Duration;
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 @QuoteCrawlerService(InsuranceCode.INSURANCE_HNIC)
 @RequiredArgsConstructor
@@ -362,10 +364,28 @@ public class HuaNongCrawlerRequestImpl implements HuaNongCrawlerRequest {
             if (contract.getPlatFormMessage() == null) {
                 continue;
             }
-            String ciEnd = contract.getPlatFormMessage().getCiReinsureEndDate();
+            // 匹配终保日期后面的时间字符串
             String ciMsg = contract.getPlatFormMessage().getCiReinsureMessage();
+            String ciEnd = contract.getPlatFormMessage().getCiReinsureEndDate();
+            Pattern pattern = Pattern.compile("终保日期\\s*(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2})");
+            Matcher matcher = pattern.matcher(ciMsg);
+            if (matcher.find()) {
+                String fullDateTime = matcher.group(1);
+                if(!fullDateTime.isEmpty()){
+                    ciEnd = fullDateTime;
+                }
+
+            }
             String biEnd = contract.getPlatFormMessage().getBiReinsureEndDate();
             String biMsg = contract.getPlatFormMessage().getBiReinsureMessage();
+            matcher = pattern.matcher(biMsg);
+            if (matcher.find()) {
+                String fullDateTime = matcher.group(1);
+                if(!fullDateTime.isEmpty()){
+                    biEnd = fullDateTime;
+                }
+
+            }
 
             if (StringUtils.hasText(ciEnd)) ciReinsureEndDate = ciEnd;
             if (StringUtils.hasText(ciMsg)) ciReinsureMessage = ciMsg;

+ 28 - 8
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/service/Impl/HuaTaiCrawlerRequestImpl.java

@@ -1,10 +1,13 @@
 package com.jzg.quotation.huatai.crawler.service.Impl;
 
 import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.json.JsonReadFeature;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
 import com.jzg.commons.constants.ProductsType;
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
 import com.jzg.commons.entity.po.jyxSetting;
@@ -238,17 +241,19 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
     // ====================== 报价主流程 ======================
     @Override
     public QuoteResultsVo quote(QuoteVo quoteVo) throws Exception {
+        // 构造登录参数
         AttributionInformationVo attr = quoteVo.getOrder().getAttributionInformationVo();
         LoginDTO dto = buildLoginDTO(attr);
+        // 获取登录相关信息
         Map<String, Object> mmap = login(dto);
-        //归属信息
+        // 归属信息
         Map<String, Object> gsInfo = parseToMap(mmap.get("gsInfo").toString());
         log.info("gsInfo: {}", JSONObject.toJSONString(mmap));
 
         String cookie = extractCookie(mmap);
         CarInfoVo car = quoteVo.getCarInfoVo();
 
-        //带重试的获取报价编号、车型型号
+        // 带重试的获取报价编号、车型型号
         Map<String, Object> xbResult = retry(() -> {
             try { return xbQuery(dto.getUsername(), cookie, car); }
             catch (Exception e) { refreshLogin(dto); throw new Exception(e); }
@@ -256,14 +261,14 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
 
         String quotationNo = str(xbResult, "quotationNo");
         String modelcodexh = str(xbResult, "modelcodexh");
-        //报价前预处理-保存车辆信息、过滤车型等处理
+        // 报价前预处理-保存车辆信息、过滤车型等处理
         PreResult pre = prepareQuote(attr, mmap, car, modelcodexh, cookie, quotationNo);
-        //报价
+        // 报价
         CoreResult core = executeQuote(quoteVo, quotationNo, dto, cookie, pre, gsInfo, attr);
         if (!core.success()) throw new SystemException("报价失败");
-        //保存订单到MongoDB
+        // 保存订单到MongoDB
         saveOrder(quoteVo, core);
-        //组装费用
+        // 组装费用
         return HuaTaiCrawlerQuoteResultsVoBuild.buildQuoteResultsVo(quoteVo, core.data(), core.fcPrice());
     }
 
@@ -836,12 +841,27 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
 
         Map<String, Object> map = new HashMap<>();
         try {
-            map = MAPPER.readValue(res, Map.class);
+            // 忽略未知字段
+            MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+            // 空字符串转null
+            MAPPER.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
+            // 允许单引号、宽松JSON格式(第三方不规范返回必备)
+            MAPPER.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
+            MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
+            // 允许换行符、回车符存在于字符串值中
+            // MAPPER.configure(JsonParser.Feature.ALLOW_UNESCAPED_CONTROL_CHARS, true);
+
+            ObjectReader reader = MAPPER.readerFor(Map.class)
+                    .with(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS)
+                    .with(JsonReadFeature.ALLOW_SINGLE_QUOTES)
+                    .with(JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES);
+
+            map = reader.readValue(res);
         } catch (JsonProcessingException e) {
             throw new SystemException("核保失败, {}", convertResponseMsg(res));
         }
 
-        if (!"1,2,3,4".contains(order.getCiCategory()) || "Y".equals(str(map, "isOver")) || "Y".equals(str(map, "isOver1"))
+        if (!"1,2,3,4,Y1,Y2,Y3".contains(order.getCiCategory()) || "Y".equals(str(map, "isOver")) || "Y".equals(str(map, "isOver1"))
                 || "重新计算保费".equals(str(map, "MSG")) || (res.contains("下发修改意见") && !res.contains("isPassHB")) || res.contains("转人工意见")) {
             throw new SystemException("核保失败-------" + convertResponseMsg(res));
         }

+ 4 - 1
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/aspect/QuoteVerificationAspect.java

@@ -600,7 +600,7 @@ public class QuoteVerificationAspect {
                         }
                         break;
                     case "3":
-                        String level1Id = calculateLevel1Distribution(insFeeOrders, totalPremium, currentUser.getUserId(), sysDistributionSetting);
+                        String level1Id = calculateLevel1Distribution(insFeeOrders, totalPremium, currentUser.getId(), sysDistributionSetting);
                         if (level1Id != null) {
                             String level2Id = calculateLevel2Distribution(insFeeOrders, totalPremium, level1Id, sysDistributionSetting);
                             if (level2Id != null) {
@@ -627,6 +627,7 @@ public class QuoteVerificationAspect {
                 String distributorId = referrer.getReferrerId();
                 insFeeOrders.setFirstDistributorId(distributorId);
                 insFeeOrders.setFirstDistributionFee(totalPremium.multiply(setting.getCommissionRatioLevel1()));
+                insFeeOrders.setFirstDistributionRatio(setting.getCommissionRatioLevel1());
                 return distributorId;
             }
         }
@@ -647,6 +648,7 @@ public class QuoteVerificationAspect {
                 String distributorId = referrer.getReferrerId();
                 insFeeOrders.setSecondDistributorId(distributorId);
                 insFeeOrders.setSecondDistributionFee(totalPremium.multiply(setting.getCommissionRatioLevel2()));
+                insFeeOrders.setSecondDistributionRatio(setting.getCommissionRatioLevel2());
                 return distributorId;
             }
         }
@@ -666,6 +668,7 @@ public class QuoteVerificationAspect {
                     && "1".equals(referrerInfoResult.getData().getIsDistribution())) {
                 insFeeOrders.setThirdDistributorId(referrer.getReferrerId());
                 insFeeOrders.setThirdDistributionFee(totalPremium.multiply(setting.getCommissionRatioLevel3()));
+                insFeeOrders.setThirdDistributionRatio(setting.getCommissionRatioLevel3());
             }
         }
     }

+ 8 - 2
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeAuditServiceImpl.java

@@ -167,7 +167,7 @@ public class InsFeeAuditServiceImpl extends ServiceImpl<InsFeeAuditMapper, InsFe
         return page;
     }
 
-    public List<FeeAuditVo> queryList(FeeAuditParam param) {
+      public List<FeeAuditVo> queryList(FeeAuditParam param) {
         log.info("订单审核-任务中心,查询待审核任务。 param=[{}]", JSONUtil.toJsonStr(param));
         // 获取选中的保险公司条件
         String companyId = param.getCompanyId();
@@ -883,7 +883,13 @@ public class InsFeeAuditServiceImpl extends ServiceImpl<InsFeeAuditMapper, InsFe
      */
     @Override
     public String exportAuditList(FeeAuditParam param) {
-        List<FeeAuditVo> result = queryList(param);
+        param.getPage().setPages(1);
+        param.getPage().setSize(Integer.MAX_VALUE);
+        param.setPages(1);
+        param.setSize(Integer.MAX_VALUE);
+        Page<FeeAuditVo> feeAuditVoPage = this.queryPage(param);
+        List<FeeAuditVo> result = feeAuditVoPage.getRecords();
+        log.info("审核记录导出。导出[{}]条记录。param=[{}]",CollUtil.size(result), JSONUtil.toJsonStr(param));
         for (FeeAuditVo feeAuditVo : result) {
             feeAuditVo.setTotalPayablePremium(feeAuditVo.getTotalPayablePremium().setScale(2, RoundingMode.HALF_UP));
             feeAuditVo.setJyPayablePremium(feeAuditVo.getJyPayablePremium().setScale(2, RoundingMode.HALF_UP));

+ 3 - 1
tenant/insurance/quotation-summary/src/main/resources/mapper/InsFeeAuditMapper.xml

@@ -67,7 +67,8 @@
         ELSE ''
         END AS isProblem,
         io.order_source,
-        ioci.vin_no
+        ioci.vin_no,
+        ifo.*
         FROM ins_fee_audit ifa
         LEFT JOIN ins_orders io on ifa.order_no = io.id AND io.is_delete=0
         LEFT JOIN ins_orders_car_info ioci on io.id = ioci.order_no AND ioci.is_delete=0
@@ -79,6 +80,7 @@
         LEFT JOIN sys_user sua on sua.id = pa.custodian_id AND sua.is_delete=0
         LEFT JOIN ins_orders_costs ioc on ioc.order_no = io.id AND ioc.is_delete=0
         LEFT JOIN ins_orders_external_policy ioep on ioep.order_no = io.id AND ioep.is_delete=0
+        LEFT JOIN ins_fee_orders ifo on ifo.order_no  = ifa.order_no  and ifo.is_delete = 0
         <where>
             and ifa.is_delete=0 and ifa.system_code = #{param.systemCode}
             <if test="param.vinNo != null and param.vinNo !=''">

+ 38 - 44
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/impl/TaiShanCrawlerQuoteProcessServiceImpl.java

@@ -117,16 +117,28 @@ public class TaiShanCrawlerQuoteProcessServiceImpl implements TaiShanCrawlerQuot
                 TaiShanExternalSendCodeResponse externalResponse = JSON.parseObject(externalResponseBody, TaiShanExternalSendCodeResponse.class);
                 log.info("externalSendCodeResponse参数的值:{}", JSON.toJSONString(externalResponse));
 
-                // 从外部响应中获取数据并缓存
-                TaiShanExternalSendCodeResponse.DataDTO externalData = externalResponse.getData();
-                Map<String, Object> tokenMap = new HashMap<>();
-                tokenMap.put("token", externalData.getToken());
-                tokenMap.put("secretKey", externalData.getSecretKey());
-                tokenMap.put("pointJson", externalData.getPointJson());
-                log.info("TaiShan-tokenMap参数的值(从外部接口获取):{}", JSON.toJSONString(tokenMap));
-                taiShanCrawlerCacheComponent.cacheToken(username, tokenMap);
-
-                getCaptchaResponse.setIdentifyId(externalData.getToken());
+                if(externalResponse != null){
+                    if (externalResponse.getCode() != null && externalResponse.getCode().equals(200)) {
+                        TaiShanExternalSendCodeResponse.DataDTO externalData = externalResponse.getData();
+                        if (externalData != null && StringUtils.isNotBlank(externalData.getToken())) {
+                            Map<String, Object> tokenMap = new HashMap<>();
+                            tokenMap.put("token", externalData.getToken());
+                            tokenMap.put("secretKey", externalData.getSecretKey());
+                            tokenMap.put("pointJson", externalData.getPointJson());
+                            log.info("TaiShan-tokenMap参数的值(从外部接口获取):{}", JSON.toJSONString(tokenMap));
+                            taiShanCrawlerCacheComponent.cacheToken(username, tokenMap);
+
+                            getCaptchaResponse.setIdentifyId(externalData.getToken());
+                        } else {
+                            log.warn("外部发送验证码接口响应数据为空或token缺失");
+                        }
+                    } else {
+                        log.warn("外部发送验证码接口调用失败,code={}, message={}",
+                                externalResponse.getCode(), externalResponse.getMessage());
+                    }
+                } else {
+                    log.warn("外部发送验证码接口返回空响应");
+                }
             }
         }
 
@@ -152,14 +164,24 @@ public class TaiShanCrawlerQuoteProcessServiceImpl implements TaiShanCrawlerQuot
         TaiShanExternalSendCodeResponse externalResponse = JSON.parseObject(externalResponseBody, TaiShanExternalSendCodeResponse.class);
         log.info("externalSendCodeResponse参数的值:{}", JSON.toJSONString(externalResponse));
 
-//        if (externalResponse == null || externalResponse.getCode() != 200) {
-//            String message = externalResponse != null ? externalResponse.getMessage() : "未知错误";
-//            log.warn("外部发送验证码接口调用失败,错误信息:{}", message);
-//            throw new RuntimeException("外部发送验证码失败:" + message);
-//        }
+        if (externalResponse == null) {
+            log.warn("外部发送验证码接口返回空响应");
+            throw new RuntimeException("外部发送验证码失败:响应为空");
+        }
+
+        if (externalResponse.getCode() == null || !externalResponse.getCode().equals("200")) {
+            String message = externalResponse.getMessage() != null ? externalResponse.getMessage() : "未知错误";
+            log.warn("外部发送验证码接口调用失败,错误信息:{}", message);
+            throw new RuntimeException("外部发送验证码失败:" + message);
+        }
 
-        // 从外部响应中获取数据并缓存
         TaiShanExternalSendCodeResponse.DataDTO externalData = externalResponse.getData();
+        if (externalData == null) {
+            log.warn("外部发送验证码接口响应数据为空");
+            throw new RuntimeException("外部发送验证码失败:响应数据为空");
+        }
+
+        // 从外部响应中获取数据并缓存
         Map<String, Object> tokenMap = new HashMap<>();
         tokenMap.put("token", externalData.getToken());
         tokenMap.put("secretKey", externalData.getSecretKey());
@@ -203,34 +225,6 @@ public class TaiShanCrawlerQuoteProcessServiceImpl implements TaiShanCrawlerQuot
             token = (String) tokenMap.get("token");
         }
         return StringUtils.hasText(token);
-
-
-//        log.info("TaiShan-detectLoginRequest参数的值:{}", JSON.toJSONString(detectLoginRequest));
-//        String username = detectLoginRequest.getUsername();
-//        String password = detectLoginRequest.getPassword();
-//        LoginBase loginBase = new LoginBase();
-//        loginBase.setUsername(username);
-//        loginBase.setPassword(password);
-//        log.info("TaiShan-loginBase参数的值:{}", JSON.toJSONString(loginBase));
-//
-//        HttpHeaders httpHeaders = new HttpHeaders();
-//        getVerifyHeader(httpHeaders);
-//
-//        sendCode(username, password);
-//
-//        Map<String, Object> tokenMap = taiShanCrawlerCacheComponent.getToken(username);
-//        log.info("TaiShan-tokenMap参数的值:{}", JSON.toJSONString(tokenMap));
-
-
-//        TaiShanCrawlerLoginRequest loginRequest = new TaiShanCrawlerLoginRequest(loginBase,tokenMap);
-//        TaiShanCrawlerLoginResponse loginResponse = taiShanCrawlerRequestComponent.login(loginRequest, httpHeaders);
-//        log.info("TaiShan-loginResponse参数的值:{}", JSON.toJSONString(loginResponse));
-//        if(loginResponse.getCode().equals("200")){
-//            String authorization = loginResponse.getResult().getIdToken();
-//            //缓存登录的信息
-//            taiShanCrawlerCacheComponent.cacheAuthorization(loginBase.getUsername(), authorization);
-//        }
-//        return true;
     }
 
 

+ 7 - 0
tenant/organization/src/main/java/com/jzg/organization/controller/ReceivableController.java

@@ -487,6 +487,13 @@ public class ReceivableController {
     @PostMapping("/exportPlatFormReceivable")
     @Operation(summary = "导出平台协议数据")
     public HttpResult exportPlatFormReceivable(@RequestBody ReceivableQueryVo receivableQueryVo) throws IOException {
+        if (StrUtil.isBlank(receivableQueryVo.getQueryType())){
+            receivableQueryVo.setQueryType("1");
+        }
+        // 协议类型 1 平台协议  2 私有协议
+        if (StrUtil.isBlank(receivableQueryVo.getAgreementType())){
+            receivableQueryVo.setAgreementType("1");
+        }
         return HttpResult.ok(receivableService.exportPlatFormReceivable(receivableQueryVo));
     }
 

+ 5 - 0
tenant/organization/src/main/java/com/jzg/organization/mapper/ReceivableMapper.java

@@ -214,6 +214,11 @@ public interface ReceivableMapper extends BaseMapper<InsPlyIncome> {
      */
     Page<InvoiceRecordResult> getInvoiceRecordList(Page page, @Param("invoiceRecordQueryVo") InvoiceRecordQueryVo invoiceRecordQueryVo);
 
+    /**
+     * 获取开票记录
+     */
+    Page<InvoiceRecordResult> getFollowInvoiceRecordList(Page page, @Param("invoiceRecordQueryVo") InvoiceRecordQueryVo invoiceRecordQueryVo);
+
     List<CompanySuperviseSettlementReportDto> selectAllCompanyReports(@Param("queryVo") SettlementReportQueryVo queryVo);
 
     /**

+ 2 - 0
tenant/organization/src/main/java/com/jzg/organization/service/SysUserJzgInfoService.java

@@ -20,6 +20,8 @@ public interface SysUserJzgInfoService extends IService<SysUserJzgInfo> {
      */
     List<SysUserJzgInfo> getUserInfoByIdentity(String identity,String userId);
 
+    SysUserJzgInfo getByUserIdOrId(String id);
+
     /**
      * 通过userId查询用户信息
      * @param userId 用户序号

+ 27 - 21
tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java

@@ -573,13 +573,14 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         queryWrapper.lambda().eq(InsPlyFollowInvoiceLink::getIsDelete, 0);
         List<InsPlyFollowInvoiceLink> insPlyFollowInvoiceLinks = insPlyFollowInvoiceLinkMapper.selectList(queryWrapper);
 
-        if (CollUtil.isNotEmpty(insPlyFollowInvoiceLinks)){
-            List<String> ids = insPlyFollowInvoiceLinks.stream().map(InsPlyFollowInvoiceLink::getId).toList();
-            List<String> followIds = insPlyFollowInvoiceLinks.stream().map(InsPlyFollowInvoiceLink::getFollowId).toList();
-            insPlyFollowInvoiceLinkMapper.deleteByIds(ids);
-            return insFeeFollowOrderMapper.deleteByIds(followIds) > 0;
+        if (CollUtil.isEmpty(insPlyFollowInvoiceLinks)){
+            return false;
         }
-        return Boolean.FALSE;
+        List<String> ids = insPlyFollowInvoiceLinks.stream().map(InsPlyFollowInvoiceLink::getId).toList();
+        List<String> followIds = insPlyFollowInvoiceLinks.stream().map(InsPlyFollowInvoiceLink::getFollowId).toList();
+        insPlyFollowInvoiceLinkMapper.deleteByIds(ids);
+        insFeeFollowOrderMapper.deleteByIds(followIds);
+        return insPlyIncomeInvoiceMapper.deleteById(invoiceId) > 0;
     }
 
     @Override
@@ -1631,20 +1632,20 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
                         .set(InsPlyIncomeInvoice::getStatus,"0").eq(InsPlyIncomeInvoice::getId,invoiceId));
 
         // 查询中间表:使用 QueryWrapper,增加逻辑删除过滤
-        LambdaQueryWrapper<InsPlyFollowInvoiceLink> linkQueryWrapper = new LambdaQueryWrapper<>();
-        linkQueryWrapper.eq(InsPlyFollowInvoiceLink::getInvoiceId, invoiceId);
-        linkQueryWrapper.eq(InsPlyFollowInvoiceLink::getIsDelete, SETTLE_STATUS_RESET);
-        List<InsPlyFollowInvoiceLink> linkList = insPlyFollowInvoiceLinkMapper.selectList(linkQueryWrapper);
-
-        if (CollUtil.isNotEmpty(linkList)){
-            // 删除中间表
-            List<String> followLinkIds = linkList.stream().map(InsPlyFollowInvoiceLink::getId).collect(Collectors.toList());
-            insPlyFollowInvoiceLinkMapper.deleteByIds(followLinkIds);
-
-            // 删除跟单表
-            List<String> followIds = linkList.stream().map(InsPlyFollowInvoiceLink::getFollowId).collect(Collectors.toList());
-            insFeeFollowOrderMapper.deleteByIds(followIds);
-        }
+//        LambdaQueryWrapper<InsPlyFollowInvoiceLink> linkQueryWrapper = new LambdaQueryWrapper<>();
+//        linkQueryWrapper.eq(InsPlyFollowInvoiceLink::getInvoiceId, invoiceId);
+//        linkQueryWrapper.eq(InsPlyFollowInvoiceLink::getIsDelete, SETTLE_STATUS_RESET);
+//        List<InsPlyFollowInvoiceLink> linkList = insPlyFollowInvoiceLinkMapper.selectList(linkQueryWrapper);
+
+//        if (CollUtil.isNotEmpty(linkList)){
+//            // 删除中间表
+//            List<String> followLinkIds = linkList.stream().map(InsPlyFollowInvoiceLink::getId).collect(Collectors.toList());
+//            insPlyFollowInvoiceLinkMapper.deleteByIds(followLinkIds);
+//
+//            // 删除跟单表
+//            List<String> followIds = linkList.stream().map(InsPlyFollowInvoiceLink::getFollowId).collect(Collectors.toList());
+//            insFeeFollowOrderMapper.deleteByIds(followIds);
+//        }
         return insPlyIncomeInvoiceSettlementMapper.deleteById(id) > 0;
     }
 
@@ -3212,7 +3213,12 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             invoiceRecordQueryVo.setSettlementStatus(null);
         }
         invoiceRecordQueryVo.setSystemCode(baseController.getSystemCode());
-        Page<InvoiceRecordResult> invoiceRecordList = baseMapper.getInvoiceRecordList(invoiceRecordQueryVo.getPage(), invoiceRecordQueryVo);
+        Page<InvoiceRecordResult> invoiceRecordList = null;
+        if ("2".equals(invoiceRecordQueryVo.getInvoiceType())){
+            invoiceRecordList = baseMapper.getFollowInvoiceRecordList(invoiceRecordQueryVo.getPage(), invoiceRecordQueryVo);
+        }else if ("1".equals(invoiceRecordQueryVo.getInvoiceType())){
+            invoiceRecordList = baseMapper.getInvoiceRecordList(invoiceRecordQueryVo.getPage(), invoiceRecordQueryVo);
+        }
         List<InvoiceRecordResult> records = invoiceRecordList.getRecords();
         if(CollUtil.isNotEmpty(records)){
             Map<String, String> allCompanyHierarchyPaths = esmInsCompanyClient.getAllCompanyHierarchyPaths();

+ 5 - 1
tenant/organization/src/main/java/com/jzg/organization/service/impl/SysDistributionSettingServiceImpl.java

@@ -28,6 +28,7 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -191,6 +192,7 @@ public class SysDistributionSettingServiceImpl extends ServiceImpl<SysDistributi
             // 审核通过 改为分销员身份
             sysDistributionAudit.setAuditApprovalTime(LocalDateTime.now());
             sysUserJzgInfo.setIsDistribution("1");
+            sysUserJzgInfo.setDistributionTime(LocalDateTime.now());
             sysUserJzgInfoMapper.updateById(sysUserJzgInfo);
             // 添加分销推荐关系
             SysUserJzgInfo inviter = sysUserJzgInfoMapper.selectById(sysUserJzgInfo.getReferrerId());
@@ -321,7 +323,9 @@ public class SysDistributionSettingServiceImpl extends ServiceImpl<SysDistributi
                 pendingAmount = pendingAmount.add(fee);
             }
         }
-        resultVo.setAuditApprovalTime(sysDistributionAudit.getAuditApprovalTime() != null ? sysDistributionAudit.getAuditApprovalTime() : null);
+        if(Objects.nonNull(sysDistributionAudit)) {
+            resultVo.setAuditApprovalTime(sysDistributionAudit.getAuditApprovalTime() != null ? sysDistributionAudit.getAuditApprovalTime() : null);
+        }
         resultVo.setTotalAmount(totalFee); // 累计佣金
         resultVo.setPendingAmount(pendingAmount); // 待结算佣金
         resultVo.setTotalPremium(totalPremium); // 累计保费

+ 3 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserAccountServiceImpl.java

@@ -102,6 +102,9 @@ public class SysUserAccountServiceImpl extends ServiceImpl<SysUserAccountMapper,
         // 获取个人中心信息
         String mobile = baseController.getUserName();
         String systemCode = baseController.getSystemCode();
+        if (systemCode == null) {
+            systemCode = baseController.getAppSystemCode();
+        }
         String userId  = baseController.getUserId();
         log.info("查询用户的钱包信息:mobile=[{}], systemCode=[{}],userId=[{}]", mobile, systemCode, userId);
         SysUser sysUser = sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getMobile, mobile));

+ 8 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserJzgInfoServiceImpl.java

@@ -38,6 +38,14 @@ public class SysUserJzgInfoServiceImpl extends ServiceImpl<SysUserJzgInfoMapper,
         return baseMapper.getUserInfoByIdentity(identity, userId);
     }
 
+    @Override
+    public SysUserJzgInfo getByUserIdOrId(String id) {
+        return baseMapper.selectOne(new LambdaQueryWrapper<SysUserJzgInfo>()
+                .eq(SysUserJzgInfo::getUserId,id)
+                .or()
+                .eq(SysUserJzgInfo::getId,id));
+    }
+
     @Override
     public SysUserJzgInfo getUserByUserId(String userId) {
         return baseMapper.getUserJzgInfoByUserId(userId);

+ 2 - 2
tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserServiceImpl.java

@@ -218,7 +218,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
             }
             log.info("查看成员下的业务员信息:成员的序号:jzgInfoId=[{}]", jzgInfoId);
             // modify by lipf 查询成员下业务员的时候,不进行分页
-            page.setSize(Long.MAX_VALUE);
+//            page.setSize(Long.MAX_VALUE);
             userInfoList = sysUserJzgInfoMapper.queryYwy(page, sysUserInfoListVo, systemCode, jzgInfoId
             );
         }else if("1".equals(sysUserInfoListVo.getIsMember())){
@@ -1041,7 +1041,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
      */
     @Override
     public HttpResult<SysUserJzgInfo> getUserInfoByUserId(String id) {
-        SysUserJzgInfo sysUserJzgInfo = sysUserJzgInfoService.getUserByUserId(id);
+        SysUserJzgInfo sysUserJzgInfo = sysUserJzgInfoService.getByUserIdOrId(id);
         log.info("根据id=[{}]查询用户信息sysUserJzgInfo=[{}]",id, JSONUtil.toJsonStr(sysUserJzgInfo));
         if (sysUserJzgInfo == null) {
             throw new SystemException("该用户不存在");

+ 1 - 1
tenant/organization/src/main/resources/mapper/PtlAgreementUndwrtRulesMapper.xml

@@ -18,7 +18,7 @@
     </resultMap>
 
     <sql id="Base_Column_List">
-        paur.id,paur.agreement_id,paur.rule_description,paur.parent_id,
+        paur.id,paur.agreement_id,paur.rule_description,paur.parent_id,paur.input_description,
         paur.order_num,paur.create_by,paur.create_time,
         paur.update_by,paur.update_time,paur.is_delete
     </sql>

+ 71 - 6
tenant/organization/src/main/resources/mapper/ReceivableMapper.xml

@@ -334,12 +334,6 @@
                 #{id}
             </foreach>
         </if>
-        <if test="receivableQueryVo.queryType != null and receivableQueryVo.queryType == 1">
-            AND ipi.supervise_settlement = 0
-        </if>
-        <if test="receivableQueryVo.queryType!= null and receivableQueryVo.queryType == 2">
-            AND ipi.other_settlement = 0
-        </if>
         <if test="receivableQueryVo.queryType!= null and (receivableQueryVo.queryType == 3 or receivableQueryVo.queryType == 4)">
             AND ipi.jy_premium != 0
             AND ipi.jy_supervise_settlement = 0
@@ -1378,6 +1372,77 @@
         ORDER BY ipii.create_time DESC
     </select>
 
+    <select id="getFollowInvoiceRecordList" resultType="com.jzg.commons.entity.finance.vo.InvoiceRecordResult">
+        SELECT
+        ipii.id,
+        ipii.company_id,
+        ipii.invoice_no,
+        ipii.invoice_type,
+        ipii.invoice_risk_type,
+        CASE
+        WHEN ipii.invoice_party = '1' THEN
+        '我方开票' ELSE '保司开票'
+        END as invoice_party,
+        ipii.overinflated_amount,
+        ipii.receivable_supervise_premium,
+        ipii.tax_point,
+        ipii.create_time,
+        ipii.create_by,
+        ipii.update_time,
+        ipii.update_by,
+        eic.name as company_name,
+        eic.name_simple as companyNameSimple,
+        sum( ipiis.actual_received_amount ) AS actual_received_amount,
+        ipii.status,
+        ipii.payment_reason,
+        GROUP_CONCAT(DISTINCT iffo.year SEPARATOR ',') AS year,
+        GROUP_CONCAT(DISTINCT iffo.month SEPARATOR ',') AS month,
+        iffo.partner_company_id,
+        ( select cp.name from  esm_ins_company cp  where cp.id = iffo.partner_company_id) as partner_company_name
+        FROM
+        ins_ply_income_invoice ipii
+        LEFT JOIN ins_ply_follow_invoice_link ipfii ON ipii.id = ipfii.invoice_id  AND ipfii.is_delete = 0
+        LEFT JOIN ins_fee_follow_order iffo ON iffo.id = ipfii.follow_id  AND iffo.is_delete = 0
+        LEFT JOIN ins_ply_income_invoice_settlement ipiis ON ipii.id = ipiis.invoice_id AND ipiis.is_delete = 0
+        LEFT JOIN esm_ins_company eic on eic.id = ipii.company_id AND eic.is_delete = 0
+        <where>
+            ipii.is_delete = 0
+            AND ipii.system_code = #{invoiceRecordQueryVo.systemCode}
+            <if test="invoiceRecordQueryVo.invoiceType != null and invoiceRecordQueryVo.invoiceType != ''">
+                AND ipii.invoice_type = #{invoiceRecordQueryVo.invoiceType}
+            </if>
+            <if test="invoiceRecordQueryVo.accountsReceivable != null and invoiceRecordQueryVo.accountsReceivable != ''">
+                AND ipii.invoice_risk_type = #{invoiceRecordQueryVo.accountsReceivable}
+            </if>
+            <if test="invoiceRecordQueryVo.recordId != null and invoiceRecordQueryVo.recordId != ''">
+                AND ipii.id = #{invoiceRecordQueryVo.recordId}
+            </if>
+            <if test="invoiceRecordQueryVo.companyId != null and invoiceRecordQueryVo.companyId != ''">
+                AND ipii.company_id = #{invoiceRecordQueryVo.companyId}
+            </if>
+            <if test="invoiceRecordQueryVo.invoiceParty != null and invoiceRecordQueryVo.invoiceParty != ''">
+                AND ipii.invoice_party = #{invoiceRecordQueryVo.invoiceParty}
+            </if>
+            <if test="invoiceRecordQueryVo.companyNameSimple != null and invoiceRecordQueryVo.companyNameSimple != ''">
+                AND eic.id = #{invoiceRecordQueryVo.companyNameSimple}
+            </if>
+        </where>
+        <if test="invoiceRecordQueryVo.settlementStatus != null and invoiceRecordQueryVo.settlementStatus != ''">
+            HAVING CASE
+            WHEN ipii.receivable_supervise_premium = SUM(ipiis.actual_received_amount) THEN '1'
+            ELSE '0'
+            END = #{invoiceRecordQueryVo.settlementStatus}
+        </if>
+        GROUP BY
+        ipii.id,
+        ipii.receivable_supervise_premium,
+        ipii.invoice_type,
+        ipii.company_id,
+        ipii.invoice_party,
+        iffo.partner_company_id
+        ORDER BY ipii.create_time DESC
+    </select>
+
     <!-- 基础结果集映射 -->
     <resultMap id="BaseResultMap" type="com.jzg.commons.entity.finance.dto.CompanySuperviseSettlementReportDto">
         <result column="company_id" property="companyId"/>

+ 0 - 1
tenant/organization/src/main/resources/mapper/SysDistributionSettingMapper.xml

@@ -240,7 +240,6 @@
             and sda.audit_status = '1'
             AND suji3.id IS NOT NULL
         </if>
-        ORDER BY eur1.id DESC
     </select>
 
     <select id="getDistributionOrder" resultType="com.jzg.commons.entity.vo.DistributionOrder">

Некоторые файлы не были показаны из-за большого количества измененных файлов