Ver código fonte

Merge remote-tracking branch 'origin/master'

wanghao 2 meses atrás
pai
commit
beae48e5a2
63 arquivos alterados com 1326 adições e 222 exclusões
  1. 0 2
      commons/src/main/java/com/jzg/commons/config/MyBatisPlusConfig.java
  2. 2 1
      commons/src/main/java/com/jzg/commons/constants/SystemBusPermsConstants.java
  3. 10 1
      commons/src/main/java/com/jzg/commons/entity/account/po/SysUserAccountChangeLog.java
  4. 8 0
      commons/src/main/java/com/jzg/commons/entity/finance/dto/ExportSuperviseSettlementDetailExcelDto.java
  5. 8 0
      commons/src/main/java/com/jzg/commons/entity/finance/dto/ExportSuperviseSettlementExcelDto.java
  6. 4 0
      commons/src/main/java/com/jzg/commons/entity/finance/dto/InsPlyIncomeDto.java
  7. 5 0
      commons/src/main/java/com/jzg/commons/entity/finance/vo/FollowCompanyFeeVO.java
  8. 5 0
      commons/src/main/java/com/jzg/commons/entity/finance/vo/InvoiceRecordQueryVo.java
  9. 3 0
      commons/src/main/java/com/jzg/commons/entity/finance/vo/SettlementReportQueryVo.java
  10. 23 0
      commons/src/main/java/com/jzg/commons/entity/finance/vo/UpdateSettlementStatusVo.java
  11. 10 0
      commons/src/main/java/com/jzg/commons/entity/quote/vo/aggregated/QuoteEchoVo.java
  12. 2 2
      commons/src/main/java/com/jzg/commons/entity/quote/vo/orders/InsOrdersVo.java
  13. 29 0
      commons/src/main/java/com/jzg/commons/entity/report/vo/FeeAuditDetailParam.java
  14. 4 0
      commons/src/main/java/com/jzg/commons/entity/scheme/vo/SchemeResultVo.java
  15. 8 0
      commons/src/main/java/com/jzg/commons/entity/system/po/SysSystemBusPermsLink.java
  16. 8 2
      commons/src/main/java/com/jzg/commons/entity/system/vo/SysSystemBusPermsVo.java
  17. 1 1
      commons/src/main/java/com/jzg/commons/entity/vo/RuleAttrMappingVo.java
  18. 3 0
      commons/src/main/java/com/jzg/commons/entity/vo/SysUserAccountVo.java
  19. 22 0
      commons/src/main/java/com/jzg/commons/util/BigDecimalUtil.java
  20. 5 0
      consoleStatistics/pom.xml
  21. 22 0
      consoleStatistics/src/main/java/com/jzg/console/client/FeeAuditClient.java
  22. 18 0
      consoleStatistics/src/main/java/com/jzg/console/controller/ReportFinanceDataManageController.java
  23. 8 0
      consoleStatistics/src/main/java/com/jzg/console/service/ReportFeeAuditSummaryService.java
  24. 37 2
      consoleStatistics/src/main/java/com/jzg/console/service/impl/ReportFeeAuditSummaryServiceImpl.java
  25. 20 10
      consoleStatistics/src/main/java/com/jzg/console/service/impl/ReportReceivableDataServiceImpl.java
  26. 4 4
      tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/api/entity/request/PremiumCalculationRequest.java
  27. 2 1
      tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/crawler/entity/request/GuoRenCrawlerQueryQuotationRequest.java
  28. 4 1
      tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/service/Impl/HengBangCrawlerRequestImpl.java
  29. 13 0
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/build/HuaTaiCrawlerQuoteResultsVoBuild.java
  30. 4 4
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/component/HuaTaiCrawlerCacheComponent.java
  31. 32 17
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/service/Impl/HuaTaiCrawlerRequestImpl.java
  32. 25 3
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/OrderOperationLogAspect.java
  33. 6 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/aspect/QuoteVerificationAspect.java
  34. 13 3
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/InsFeeOrderController.java
  35. 3 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeAuditServiceImpl.java
  36. 3 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeOrdersServiceImpl.java
  37. 12 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrdersServiceImpl.java
  38. 7 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrdersTrackServiceImpl.java
  39. 1 0
      tenant/insurance/quotation-summary/src/main/resources/mapper/InsOrdersMapper.xml
  40. 45 0
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/cache/RedisCacheUtil.java
  41. 5 0
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/client/HttpURL.java
  42. 35 0
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/api/CarCheckUploadFileSubmitParam.java
  43. 53 0
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/api/CarCheckUploadFileVerifyImgParam.java
  44. 5 0
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/api/TKEntranceFor000086Result.java
  45. 35 5
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/service/TKHttpAPIService.java
  46. 383 32
      tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/service/impl/TKQuotationBaseServiceImpl.java
  47. 5 1
      tenant/insurance/quotation-taiping/src/main/java/com/jzg/quotation/taiping/crawler/entity/request/TaiPingCrawlerPremiumCalculateRequest.java
  48. 104 69
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/impl/TaiShanCrawlerRequestImpl.java
  49. 5 1
      tenant/insurance/quotation-yongcheng/src/main/java/com/jzg/quotation/yongcheng/api/entity/request/AuditRequest.java
  50. 12 0
      tenant/insurance/quotation-yongcheng/src/main/java/com/jzg/quotation/yongcheng/api/service/impl/YongChengApiRequestImpl.java
  51. 22 5
      tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/entity/request/ZhongAnCrawlerQuoteRequest.java
  52. 9 0
      tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/entity/Request/ZmCrawlerQuotedPriceRequest.java
  53. 1 1
      tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/service/Impl/ZhongMeiCrawlerRequestImpl.java
  54. 9 3
      tenant/organization/src/main/java/com/jzg/organization/controller/ReceivableController.java
  55. 2 0
      tenant/organization/src/main/java/com/jzg/organization/controller/UserAccountController.java
  56. 2 2
      tenant/organization/src/main/java/com/jzg/organization/mapper/SysUserAccountIncomeLogMapper.java
  57. 2 2
      tenant/organization/src/main/java/com/jzg/organization/service/ReceivableService.java
  58. 99 31
      tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java
  59. 21 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysAmountAuditingServiceImpl.java
  60. 36 8
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserAccountServiceImpl.java
  61. 4 0
      tenant/organization/src/main/resources/mapper/InsFeeFollowOrderMapper.xml
  62. 17 1
      tenant/organization/src/main/resources/mapper/PtlSchemeMapper.xml
  63. 21 4
      tenant/organization/src/main/resources/mapper/ReceivableMapper.xml

+ 0 - 2
commons/src/main/java/com/jzg/commons/config/MyBatisPlusConfig.java

@@ -1,7 +1,5 @@
 package com.jzg.commons.config;
 
-
-import cn.hutool.json.JSONNull;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
 import com.baomidou.mybatisplus.extension.handlers.Fastjson2TypeHandler;

+ 2 - 1
commons/src/main/java/com/jzg/commons/constants/SystemBusPermsConstants.java

@@ -15,7 +15,8 @@ public enum SystemBusPermsConstants {
     SALESMAN_AUDIT_DEPT(3,"salesmanAuditDept","业务员审核机构"),
     SALESMAN_WITHDRAW_ACCOUNT_AUDIT_DEPT(4,"salesmanWithdrawAccountAuditDept","业务员提现账号审核机构"),
     SALESMAN_WITHDRAW_PAYMENT_AUDIT_DEPT(5,"salesmanWithdrawPaymentAuditDept","业务员提现申请付款审核机构"),
-    AccountLinking(6,"accountLinking","账号互通");
+    AccountLinking(6,"accountLinking","账号互通"),
+    CLIENT_TYPE(6,"clientType","PC端还是APP端可用"),;
 
     private Integer id;
     private String code;

+ 10 - 1
commons/src/main/java/com/jzg/commons/entity/account/po/SysUserAccountChangeLog.java

@@ -71,7 +71,7 @@ public class SysUserAccountChangeLog extends BaseModel {
     }
 
     /**
-     * 操作类型 1 保单费用 2 保单提成 3. 提现
+     * 操作类型 1 保单费用 2 保单提成 3. 提现 4. 提现驳回
      */
     @ExcelIgnore
     @Schema(description = "操作类型")
@@ -87,6 +87,7 @@ public class SysUserAccountChangeLog extends BaseModel {
         operTypeMap.put(1,"保单费用");
         operTypeMap.put(2,"保单提成");
         operTypeMap.put(3,"提现");
+        operTypeMap.put(4,"提现驳回");
     }
 
     public String getOperTypeName(){
@@ -97,6 +98,14 @@ public class SysUserAccountChangeLog extends BaseModel {
     @Schema(description = "关联订单ID")
     private String relatedOrderId;
 
+    @ExcelIgnore
+    @Schema(description = "状态10有效20无效")
+    private String status;
+
+    @ExcelIgnore
+    @Schema(description = "费用审核关联id(sys_amount_auditing表的id)")
+    private String relatedAmountAuditingId;
+
 
     @ExcelIgnore
     @Schema(description = "转出银行卡的序号")

+ 8 - 0
commons/src/main/java/com/jzg/commons/entity/finance/dto/ExportSuperviseSettlementDetailExcelDto.java

@@ -49,6 +49,14 @@ public class ExportSuperviseSettlementDetailExcelDto {
     @ExcelProperty(value = "应收手续费")
     private String receivableSuperviseCosts;
 
+    @Schema(description = "车险手续费")
+    @ExcelProperty(value = "车险手续费")
+    private String superviseCostPremiums4Car;
+
+    @Schema(description = "非车手续费")
+    @ExcelProperty(value = "非车手续费")
+    private String jySuperviseCostsPremiums;
+
     @Schema(description = "交强保单号")
     @ExcelProperty(value = "交强保单号")
     private String jqPolicyNo;

+ 8 - 0
commons/src/main/java/com/jzg/commons/entity/finance/dto/ExportSuperviseSettlementExcelDto.java

@@ -44,6 +44,14 @@ public class ExportSuperviseSettlementExcelDto {
     @ExcelProperty(value = "应收项")
     private String invoiceType;
 
+    @Schema(description = "应收项(10车险20非车险)")
+    @ExcelProperty(value = "应收项(10车险20非车险)")
+    private String invoiceRiskType;
+
+    @Schema(description = "应收项(10车险20非车险)")
+    @ExcelProperty(value = "应收项(10车险20非车险)")
+    private String invoiceRiskTypeName;
+
     // 应收项转义
     @Schema(description = "应收项")
     @ExcelProperty(value = "应收项")

+ 4 - 0
commons/src/main/java/com/jzg/commons/entity/finance/dto/InsPlyIncomeDto.java

@@ -316,6 +316,10 @@ public class InsPlyIncomeDto extends BaseModel {
     @Schema(description = "订单关联的发票信息")
     private String invoiceId;
 
+    @TableField(exist = false)
+    @Schema(description = "1-手续费, 2-跟单费, 3-驾意险手续费, 4-驾意险跟单费, 5-平台应收-车险, 6-平台应收-非车险")
+    private String invoiceType;
+
     @TableField(exist = false)
     @Schema(description = "地区归属")
     private String companyNameSimple;

+ 5 - 0
commons/src/main/java/com/jzg/commons/entity/finance/vo/FollowCompanyFeeVO.java

@@ -69,4 +69,9 @@ public class FollowCompanyFeeVO {
      */
     private String followId;
 
+    /**
+     * 开票类型  1、手续费  2、跟单费  3、驾意险手续费 4、驾意险跟单费 5、平台应收-车险 6、平台应收-非车险
+     */
+    private String invoiceType;
+
 }

+ 5 - 0
commons/src/main/java/com/jzg/commons/entity/finance/vo/InvoiceRecordQueryVo.java

@@ -61,6 +61,11 @@ public class InvoiceRecordQueryVo extends PageRequest {
      */
     private String companyNameSimple;
 
+    /**
+     * 保险公司分支id
+     */
+    private String partnerCompanyId;
+
     /**
      * 租户代码
      */

+ 3 - 0
commons/src/main/java/com/jzg/commons/entity/finance/vo/SettlementReportQueryVo.java

@@ -52,6 +52,9 @@ public class SettlementReportQueryVo extends PageRequest {
     @Schema(description = "开票类型 1 手续费  2 跟单费  3 驾意险手续费 4 驾意险跟单费")
     private List<String> invoiceTypes;
 
+    @Schema(description = "开票类型 1 手续费  2 跟单费  3 驾意险手续费 4 驾意险跟单费")
+    private String invoiceType;
+
     @Schema(description = "上级公司id")
     private String parentId;
 

+ 23 - 0
commons/src/main/java/com/jzg/commons/entity/finance/vo/UpdateSettlementStatusVo.java

@@ -0,0 +1,23 @@
+package com.jzg.commons.entity.finance.vo;
+
+import com.jzg.commons.core.base.PageRequest;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author quchen
+ * @date 2025/7/31 17:59
+ */
+
+@Data
+public class UpdateSettlementStatusVo extends PageRequest {
+
+    @Schema(description = "开票id")
+    private String invoiceId;
+
+    @Schema(description = "回款原因")
+    private String settlementPaymentReason;
+
+}

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

@@ -56,6 +56,9 @@ public class QuoteEchoVo extends QuoteVo {
     private static class OrderBaseVo extends OrderBase{
         @Serial
         private static final long serialVersionUID = -9184896455541993138L;
+
+        private Integer entryStatus;
+
         private String orderStatus;
         private String companyName;
         private String productsName;
@@ -279,6 +282,12 @@ public class QuoteEchoVo extends QuoteVo {
     @Schema(description = "订单批改信息")
     private InsOrderAdjustVo insOrderAdjustVo;
 
+    @Schema(description = "权益是否可用")
+    private String ownerRights;
+
+    @Schema(description = "权益可用范围")
+    private String clientType;
+
     @Schema(description = "权益信息")
     private InsOrderRightsInfoVo insOrderRightsInfoVo;
 
@@ -335,6 +344,7 @@ public class QuoteEchoVo extends QuoteVo {
         this.getOrder().setQuoteTime(insOrdersVo.getCreateTime());
         this.getOrder().setSigningTime(insOrdersVo.getPayTime());
         this.getOrder().setOrderType(insOrdersVo.getOrderType());
+        this.getOrder().setEntryStatus(insOrdersVo.getEntryStatus());
         this.setCiSpecialInfoVo(insOrdersVo.getSpecialInfoVo().stream().filter(companyClauseVo -> companyClauseVo.getRiskCode().equals("0507")).collect(Collectors.toList()));
         this.setBiSpecialInfoVo(insOrdersVo.getSpecialInfoVo().stream().filter(companyClauseVo -> companyClauseVo.getRiskCode().equals("0510")).collect(Collectors.toList()));
         Salesman salesman = new Salesman();

+ 2 - 2
commons/src/main/java/com/jzg/commons/entity/quote/vo/orders/InsOrdersVo.java

@@ -49,10 +49,10 @@ public class InsOrdersVo extends QuoteVo {
     private String agreementId;
 
     @Schema(description = "审核状态")
-    private byte auditStatus;
+    private Integer auditStatus;
 
     @Schema(description = "录入状态 1 车险录入 2 待客录单 3 外部订单")
-    private byte entryStatus;
+    private Integer entryStatus;
 
 
     @Schema(description = "审核内容")

+ 29 - 0
commons/src/main/java/com/jzg/commons/entity/report/vo/FeeAuditDetailParam.java

@@ -0,0 +1,29 @@
+package com.jzg.commons.entity.report.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jzg.commons.core.base.PageRequest;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+/**
+ * 费用审核明细列表请求参数:按保险公司查看所有状态的审核明细
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(description = "费用审核明细列表请求参数")
+public class FeeAuditDetailParam extends PageRequest {
+
+    @Schema(description = "保险公司ID")
+    private String companyId;
+
+    @Schema(description = "审核开始时间")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate auditTimeStart;
+
+    @Schema(description = "审核结束时间")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate auditTimeEnd;
+}

+ 4 - 0
commons/src/main/java/com/jzg/commons/entity/scheme/vo/SchemeResultVo.java

@@ -1,5 +1,6 @@
 package com.jzg.commons.entity.scheme.vo;
 
+import com.jzg.commons.entity.po.jyxSetting;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -107,6 +108,7 @@ public class SchemeResultVo {
          * 产品分类编码
          */
         private String productCategoryName;
+        private String premiumSetting;
         private String alias;
         private String coverage;
         private String sumAmount;
@@ -115,5 +117,7 @@ public class SchemeResultVo {
         private String selectedStatus;
         private Integer minSeatCount;
         private Integer maxSeatCount;
+
+        List<jyxSetting> settingList;
     }
 }

+ 8 - 0
commons/src/main/java/com/jzg/commons/entity/system/po/SysSystemBusPermsLink.java

@@ -82,6 +82,14 @@ public class SysSystemBusPermsLink implements Serializable {
                 links.add(sysSystemBusPermsLink);
             }
         }
+        if (sysSystemBusPermsVo.getClientTypeList() != null && !sysSystemBusPermsVo.getClientTypeList().isEmpty()) {
+            for (String clientTypeId : sysSystemBusPermsVo.getClientTypeList()) {
+                SysSystemBusPermsLink sysSystemBusPermsLink = new SysSystemBusPermsLink();
+                sysSystemBusPermsLink.setBusId(clientTypeId);
+                sysSystemBusPermsLink.setBusCode(SystemBusPermsConstants.CLIENT_TYPE.getCode());
+                links.add(sysSystemBusPermsLink);
+            }
+        }
         return links;
     }
 }

+ 8 - 2
commons/src/main/java/com/jzg/commons/entity/system/vo/SysSystemBusPermsVo.java

@@ -80,9 +80,12 @@ public class SysSystemBusPermsVo implements Serializable {
     @Schema(description = "车主权益1:开启,0:关闭")
     private Integer ownerRights;
 
-    @Schema(description = "PC端还是APP端可用1:PC,2:APP")
+    @Schema(description = "PC端还是APP端可用1:PC,2:APP,3:PC+APP")
     private Integer clientType;
 
+    @Schema(description = "权益PC APP 回显列表")
+    private List<String> clientTypeList = new ArrayList<>();
+
     @Schema(description = "账号互通")
     private Integer accountLinking;
 
@@ -130,7 +133,10 @@ public class SysSystemBusPermsVo implements Serializable {
         this.salesmanWithdrawPaymentAuditDeptList.addAll(links.stream()
                 .filter(link -> link.getBusCode().equals(SystemBusPermsConstants.SALESMAN_WITHDRAW_PAYMENT_AUDIT_DEPT.getCode()))
                 .map(link->link.getBusId()).collect(Collectors.toList()));
-
+        //权益PC APP 回显列表
+        this.clientTypeList.addAll(links.stream()
+                .filter(link -> link.getBusCode().equals(SystemBusPermsConstants.CLIENT_TYPE.getCode()))
+                .map(link->link.getBusId()).collect(Collectors.toList()));
     }
 
 }

+ 1 - 1
commons/src/main/java/com/jzg/commons/entity/vo/RuleAttrMappingVo.java

@@ -191,7 +191,7 @@ public class RuleAttrMappingVo {
                 ruleAttrMappingVoList.add(new RuleAttrMappingVo("DriverLiabilityInsurance", String.valueOf(kind.getAmount())));
             //乘客责任险
             if (KindCode.D4.getCode().equals(kind.getKindCode()))
-                ruleAttrMappingVoList.add(new RuleAttrMappingVo("PassengerLiabilityInsurance", String.valueOf(kind.getUnitAmount())));
+                ruleAttrMappingVoList.add(new RuleAttrMappingVo("PassengerLiabilityInsurance", String.valueOf(kind.getAmount())));
             //车身划痕险
             if (KindCode.L.getCode().equals(kind.getKindCode()))
                 ruleAttrMappingVoList.add(new RuleAttrMappingVo("CarScratchInsurance", String.valueOf(kind.getAmount())));

+ 3 - 0
commons/src/main/java/com/jzg/commons/entity/vo/SysUserAccountVo.java

@@ -43,6 +43,9 @@ public class SysUserAccountVo extends BaseModel {
     @Schema(description = "已付总金额")
     private BigDecimal sumAmountPaid;
 
+    @Schema(description = "支付中金额")
+    private BigDecimal payingAmount;
+
     @Schema(description = "未付总金额")
     private BigDecimal sumAmountUnpaid;
 

+ 22 - 0
commons/src/main/java/com/jzg/commons/util/BigDecimalUtil.java

@@ -6,6 +6,7 @@ import cn.hutool.core.util.StrUtil;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.List;
+import java.util.Objects;
 
 
 /**
@@ -55,6 +56,27 @@ public class BigDecimalUtil {
         return sum;
     }
 
+    /**
+     *
+     * @author lipf
+     * @date 2026/7/1 14:58
+     */
+    public static String add(String ... v1s){
+        if (v1s == null || v1s.length == 0) {
+            return Objects.toString(BigDecimal.ZERO);
+        }
+        BigDecimal sum = BigDecimal.ZERO;
+        BigDecimal temp = BigDecimal.ZERO;
+        for (String v1 : v1s) {
+            if(StrUtil.isNotEmpty(v1)){
+                temp = new BigDecimal(v1);
+            }
+            sum = BigDecimalUtil.add(sum,temp);
+            temp = BigDecimal.ZERO;
+        }
+        return sum.toString();
+    }
+
     /**
      * 提供精确的加法运算
      * @param v1 被加数

+ 5 - 0
consoleStatistics/pom.xml

@@ -64,6 +64,11 @@
             <artifactId>rocketmq-spring-boot-starter</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>com.jzg</groupId>
             <artifactId>rocketmq</artifactId>

+ 22 - 0
consoleStatistics/src/main/java/com/jzg/console/client/FeeAuditClient.java

@@ -0,0 +1,22 @@
+package com.jzg.console.client;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jzg.commons.core.page.HttpResult;
+import com.jzg.commons.entity.dto.FeeAuditParam;
+import com.jzg.commons.entity.orders.vo.FeeAuditVo;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+/**
+ * 调用 quotation-summary 的订单审核接口 Feign 客户端
+ */
+@FeignClient(value = "quotation-summary")
+public interface FeeAuditClient {
+
+    /**
+     * 订单审核列表分页查询
+     */
+    @PostMapping("/feeAudit/auditList")
+    HttpResult<Page<FeeAuditVo>> auditList(@RequestBody FeeAuditParam param);
+}

+ 18 - 0
consoleStatistics/src/main/java/com/jzg/console/controller/ReportFinanceDataManageController.java

@@ -1,11 +1,14 @@
 package com.jzg.console.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jzg.commons.core.base.BaseController;
 import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.report.dto.FeeAuditSummaryVo;
+import com.jzg.commons.entity.report.vo.FeeAuditDetailParam;
 import com.jzg.commons.entity.report.vo.FeeAuditSummaryParam;
 import com.jzg.commons.entity.report.vo.ReportSearchCommonVo;
+import com.jzg.commons.entity.orders.vo.FeeAuditVo;
 import com.jzg.console.service.*;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -361,4 +364,19 @@ public class ReportFinanceDataManageController extends BaseController {
         }
     }
 
+    /**
+     * 费用审核明细列表:根据保险公司ID查询该公司的所有审核明细(不区分审核状态)
+     * @author: jk
+     */
+    @Operation(summary = "费用审核-明细列表", description = "费用审核-明细列表")
+    @PostMapping(value = "/feeAuditDetailPageList")
+    public HttpResult<Page<FeeAuditVo>> feeAuditDetailPageList(@RequestBody FeeAuditDetailParam param) {
+        try {
+            Page<FeeAuditVo> pageList = reportFeeAuditSummaryService.getFeeAuditDetailPage(param);
+            return HttpResult.ok(pageList);
+        } catch (Exception e) {
+            return HttpResult.error(e.getMessage());
+        }
+    }
+
 }

+ 8 - 0
consoleStatistics/src/main/java/com/jzg/console/service/ReportFeeAuditSummaryService.java

@@ -1,8 +1,11 @@
 package com.jzg.console.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jzg.commons.entity.report.dto.FeeAuditSummaryVo;
+import com.jzg.commons.entity.report.vo.FeeAuditDetailParam;
 import com.jzg.commons.entity.report.vo.FeeAuditSummaryParam;
+import com.jzg.commons.entity.orders.vo.FeeAuditVo;
 
 /**
  * 费用审核汇总统计 Service
@@ -13,4 +16,9 @@ public interface ReportFeeAuditSummaryService {
      * 按保险公司分组统计费用审核汇总(逻辑分页)
      */
     IPage<FeeAuditSummaryVo> getFeeAuditSummaryPage(FeeAuditSummaryParam param);
+
+    /**
+     * 按保险公司查询费用审核明细列表(分页)
+     */
+    Page<FeeAuditVo> getFeeAuditDetailPage(FeeAuditDetailParam param);
 }

+ 37 - 2
consoleStatistics/src/main/java/com/jzg/console/service/impl/ReportFeeAuditSummaryServiceImpl.java

@@ -2,13 +2,21 @@ package com.jzg.console.service.impl;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jzg.commons.core.page.HttpResult;
+import com.jzg.commons.entity.dto.FeeAuditParam;
 import com.jzg.commons.entity.report.dto.FeeAuditSummaryVo;
+import com.jzg.commons.entity.report.vo.FeeAuditDetailParam;
 import com.jzg.commons.entity.report.vo.FeeAuditSummaryParam;
+import com.jzg.commons.entity.orders.vo.FeeAuditVo;
+import com.jzg.console.client.FeeAuditClient;
 import com.jzg.console.mapper.ReportFeeAuditSummaryMapper;
 import com.jzg.console.service.ReportFeeAuditSummaryService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.time.LocalTime;
+import java.util.Objects;
+
 /**
  * 费用审核汇总统计 Service 实现
  */
@@ -18,11 +26,38 @@ public class ReportFeeAuditSummaryServiceImpl implements ReportFeeAuditSummarySe
     @Autowired
     private ReportFeeAuditSummaryMapper reportFeeAuditSummaryMapper;
 
+    @Autowired
+    private FeeAuditClient feeAuditClient;
+
     @Override
     public IPage<FeeAuditSummaryVo> getFeeAuditSummaryPage(FeeAuditSummaryParam param) {
-        // 创建分页对象
         Page<FeeAuditSummaryVo> page = new Page<>(param.getPages(), param.getSize());
-        // 执行分组统计查询(逻辑分页:先查出全部再在内存中分页)
         return reportFeeAuditSummaryMapper.getFeeAuditSummaryPage(page, param);
     }
+
+    @Override
+    public Page<FeeAuditVo> getFeeAuditDetailPage(FeeAuditDetailParam param) {
+        // 构建调用 quotation-summary /feeAudit/auditList 的参数
+        FeeAuditParam feeAuditParam = new FeeAuditParam();
+        feeAuditParam.setPages(param.getPages());
+        feeAuditParam.setSize(param.getSize());
+        feeAuditParam.setCompanyId(param.getCompanyId());
+
+        // 转换时间:LocalDate -> LocalDateTime(开始日期的00:00:00,结束日期的23:59:59)
+        if (param.getAuditTimeStart() != null) {
+            feeAuditParam.setAuditTimeStart(param.getAuditTimeStart().atStartOfDay());
+        }
+        if (param.getAuditTimeEnd() != null) {
+            feeAuditParam.setAuditTimeEnd(param.getAuditTimeEnd().atTime(LocalTime.MAX));
+        }
+
+        // 调用远程服务获取审核列表
+        HttpResult<Page<FeeAuditVo>> result = feeAuditClient.auditList(feeAuditParam);
+
+        if (result.isSuccess() && result.getData() != null) {
+            return result.getData();
+        }
+        // 返回空分页避免前端报错
+        return new Page<>(param.getPages(), param.getSize());
+    }
 }

+ 20 - 10
consoleStatistics/src/main/java/com/jzg/console/service/impl/ReportReceivableDataServiceImpl.java

@@ -1,21 +1,19 @@
 package com.jzg.console.service.impl;
 
 
-import com.alibaba.excel.annotation.ExcelIgnore;
-import com.alibaba.excel.annotation.ExcelProperty;
-import com.alibaba.excel.annotation.write.style.ColumnWidth;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jzg.commons.entity.report.dto.*;
 import com.jzg.commons.entity.report.vo.ReportSearchCommonVo;
-import com.jzg.console.service.ReportCostVerificationDataService;
 import com.jzg.console.service.ReportReceivableDataService;
-import io.swagger.v3.oas.annotations.media.Schema;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 
 /**
@@ -26,6 +24,9 @@ import java.util.List;
  */
 @Service
 public class ReportReceivableDataServiceImpl extends ReportBaseServiceImpl implements ReportReceivableDataService {
+
+    private static final Logger log = LoggerFactory.getLogger(ReportReceivableDataServiceImpl.class);
+
     /**
      *  @version
      *  @author: hxl
@@ -34,7 +35,8 @@ public class ReportReceivableDataServiceImpl extends ReportBaseServiceImpl imple
      */
     @Override
     public List<?> getListByParams(ReportSearchCommonVo reportSearchCommonVo){
-        return getList();
+        log.info("数据报表-财务数据-应收. reportSearchCommonVo=[{}]", JSONUtil.toJsonStr(reportSearchCommonVo));
+        return getList(reportSearchCommonVo);
     }
     @Override
     public IPage<?> getPageListByParams(ReportSearchCommonVo reportSearchCommonVo) {
@@ -48,7 +50,7 @@ public class ReportReceivableDataServiceImpl extends ReportBaseServiceImpl imple
      */
     @Override
     public void downloadListByParams(ReportSearchCommonVo reportSearchCommonVo) {
-        List<ReportReceivableDataDto> list = getList();
+        List<ReportReceivableDataDto> list = getList(reportSearchCommonVo);
         upLoadFile(reportSearchCommonVo, ReportReceivableDataDto.class,list,"财务数据-应收-列表导出-"+ reportSearchCommonVo.getUserId());
     }
     /**
@@ -83,8 +85,16 @@ public class ReportReceivableDataServiceImpl extends ReportBaseServiceImpl imple
      *  @Date: 2025/9/24 10:42
      *  @Description:  模拟数据
      */
-    public List<ReportReceivableDataDto>  getList(){
+    public List<ReportReceivableDataDto>  getList(ReportSearchCommonVo param){
+        log.info("数据报表-财务数据-应收。 param=[{}]", JSONUtil.toJsonStr(param));
         List<ReportReceivableDataDto> list =new ArrayList<>();
+        // 和财务沟通过, 开票的时候,一个月的进行开票,不进行跨月开票。
+        List<String> years = param.getYear();
+        String year="";
+        if(CollUtil.isNotEmpty(years)){
+            year = years.get(0);
+        }
+
         ReportReceivableDataDto reportReceivableDataDto = ReportReceivableDataDto.builder()
                 .yearAndMonthTime("2023-10").accountsReceivableMoney(new BigDecimal(100))
                 .uninvoicedMoney(new BigDecimal(100)).invoicedMoney(new BigDecimal(100))

+ 4 - 4
tenant/insurance/quotation-chengtai/src/main/java/com/jzg/quotation/chengtai/api/entity/request/PremiumCalculationRequest.java

@@ -786,11 +786,11 @@ public class PremiumCalculationRequest {
                 }
                 // 绝对免赔
                 else if (kindCode.equals("FA") || kindCode.equals("FB") || kindCode.equals("FD11") || kindCode.equals("FD12")) {
-                    kind.quantity = Integer.valueOf(kindInfoVo.getDeductibleRate());
-                    kind.sumInsured = new BigDecimal(kindInfoVo.getDeductibleRate());
+                    kind.quantity = Integer.valueOf(kindInfoVo.getAmount());
+                    kind.sumInsured = new BigDecimal(kindInfoVo.getAmount());
                 } else if (kindCode.equals("S1") || kindCode.equals("S2") || kindCode.equals("S3") || kindCode.equals("S4")) {
-                    kind.quantity = Integer.valueOf(kindInfoVo.getServiceTimes());
-                    kind.sumInsured = new BigDecimal(kindInfoVo.getServiceTimes());
+                    kind.quantity = Integer.valueOf(kindInfoVo.getAmount());
+                    kind.sumInsured = new BigDecimal(kindInfoVo.getAmount());
                 } else if (KindCodeEnum.KCE_01.getKindCode().equals(kindCode)) {
                     kind.sumInsured = actualValue;
                 } else {

+ 2 - 1
tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/crawler/entity/request/GuoRenCrawlerQueryQuotationRequest.java

@@ -1,5 +1,6 @@
 package com.jzg.quotation.guoren.crawler.entity.request;
 
+import com.alibaba.excel.util.StringUtils;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.jzg.commons.entity.quote.vo.AccidentalDrivingVo;
 import com.jzg.commons.entity.quote.vo.CustomerInfoVo;
@@ -50,7 +51,7 @@ public class GuoRenCrawlerQueryQuotationRequest implements Serializable {
         DataDTO dataDTO = new DataDTO();
         GoodsListDTO goodsListDTO = new GoodsListDTO();
         goodsListDTO.setClassifyCode("A");
-        goodsListDTO.setGoodsCode(accidentalDriving.getParentProductCode());
+        goodsListDTO.setGoodsCode(StringUtils.isBlank(accidentalDriving.getParentProductCode()) ? accidentalDriving.getProductCode() : accidentalDriving.getParentProductCode());
         goodsListDTO.setProdCode(accidentalDriving.getProductCode());
         goodsListDTO.setStartDate(quoteVo.getCiRiskInfoVo() != null
                 ? TimeProcessing.dateTimeToDate(quoteVo.getCiRiskInfoVo().getStartDate()) + " 00:00:00"

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

@@ -197,7 +197,10 @@ public class HengBangCrawlerRequestImpl implements HengBangCrawlerRequest {
                 // 不含交强险标识则为商业险重复投保
                 calculationRequest.setBegintimeBi(utcTime);
             }
-            calculationRequest.setBegintimeAccident(utcTime);
+            // 驾意险不支持即时起保:北京时间0点则直接复用,非0点则自动设为下一日0点
+            calculationRequest.setBegintimeAccident(DateUtil.isBeijingMidnight(utcTime)
+                    ? utcTime
+                    : DateUtil.getNextDayMidnightUtc(utcTime));
 
             resJsonObj = callCalculation(calculationRequest, headers);
             if (resJsonObj == null) {

+ 13 - 0
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/build/HuaTaiCrawlerQuoteResultsVoBuild.java

@@ -14,6 +14,9 @@ import com.jzg.quotation.commons.constant.enums.quote.RenewalEnum;
 import com.jzg.quotation.huatai.api.constant.enums.ContractEnum;
 import com.jzg.quotation.huatai.crawler.entity.Response.HtCrawlerQuoteResponse;
 
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -24,14 +27,24 @@ import java.util.stream.Collectors;
  * @date: 2025/4/22 11:06
  **/
 public class HuaTaiCrawlerQuoteResultsVoBuild {
+    private static final String DATE_FMT = "yyyy-MM-dd HH:mm:ss";
     public static QuoteResultsVo buildQuoteResultsVo(QuoteVo quoteVo, HtCrawlerQuoteResponse.DataDTO quoteResponseData, String niPremium) {
         OrderBase orderBase = quoteVo.getOrder();
         QuoteResultsVo quoteResultsVo = new QuoteResultsVo();
         quoteResultsVo.setOrdersNo(orderBase.getOrdersNo());
         // 交强险
         quoteResultsVo.setCiRiskInfoVo(buildCiRiskInfoVo(quoteResponseData, quoteVo));
+        quoteResultsVo.setCiStartDate(quoteResultsVo.getCiRiskInfoVo().getStartDate());
+        quoteResultsVo.setCiEndDate(quoteResultsVo.getCiRiskInfoVo().getEndDate());
         // 商业险
         quoteResultsVo.setBiRiskInfoVo(buildBiRiskInfoVo(quoteResponseData, quoteVo));
+        if(quoteResultsVo.getBiRiskInfoVo() != null) {
+            quoteResultsVo.setBiStartDate(quoteResultsVo.getBiRiskInfoVo().getStartDate());
+            // quoteResultsVo.setBiEndDate(quoteResultsVo.getBiRiskInfoVo().getEndDate());
+            LocalDateTime dt = LocalDateTime.parse(quoteResultsVo.getBiRiskInfoVo().getStartDate(), DateTimeFormatter.ofPattern(DATE_FMT));
+            dt = dt.plusYears(1).minusDays(1).with(LocalTime.MAX);
+            quoteResultsVo.setBiEndDate(dt.format(DateTimeFormatter.ofPattern(DATE_FMT)));
+        }
         // 商业险种的详细保费
         quoteResultsVo.setKindInfoVo(quoteVo.getKindInfoVo());
         // 商业险险种信息

+ 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(2L));
+        map.expire(Duration.ofHours(3L));
     }
 
     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(2L));
+        map.expire(Duration.ofHours(3L));
     }
 
     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(2L));
+        map.expire(Duration.ofHours(3L));
     }
 
     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(2L));
+        map.expire(Duration.ofHours(3L));
     }
 
     public String getCookie() {

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

@@ -90,6 +90,8 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
     private static final String BASE_URL = "https://cspxp.pc.ehuatai.com";
     private static final int MAX_RETRIES = 3;
     private static final long RETRY_DELAY_MS = 3000;
+    /** 指数退避倍率:每次重试间隔 = RETRY_DELAY_MS * (BACKOFF_FACTOR ^ 重试次数) */
+    private static final int BACKOFF_FACTOR = 2;
     private static final long SHORT_DELAY_MS = 100;
     private static final String RISK_CODE = "1251";
     private static final String XBCOM_CODE = "927";
@@ -121,6 +123,13 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
     private final PlatformClient platformClient;
     private final CookieUtils cookieUtils;
     private static final ObjectMapper MAPPER = new ObjectMapper();
+    static {
+        // 初始化时统一配置所有 Feature,避免运行时多线程并发配置导致不稳定
+        MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        MAPPER.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
+        MAPPER.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
+        MAPPER.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
+    }
 
     // ====================== 登录 ======================
     @Override public void login(LoginBase loginBase) { }
@@ -221,9 +230,13 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
         quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
         // 带重试的获取报价编号、车型型号
         Map<String, Object> xbResult = retry(() -> {
-            try { return xbQuery(dto.getUsername(), cookie, car); }
+            try {
+                String freshCookie = cache.getCookie();
+                String useCookie = StringUtils.hasText(freshCookie) ? freshCookie : cookie;
+                return xbQuery(dto.getUsername(), useCookie, car);
+            }
             catch (Exception e) { refreshLogin(dto); throw new Exception(e); }
-        }, MAX_RETRIES, RETRY_DELAY_MS, "预报价获取登录信息");
+        }, MAX_RETRIES, RETRY_DELAY_MS, BACKOFF_FACTOR, "预报价获取登录信息");
 
         String quotationNo = str(xbResult, "quotationNo");
         String modelcodexh = StringUtils.isBlank(str(xbResult, "modelcodexh")) ? car.getCarModelNo() : str(xbResult, "modelcodexh");
@@ -233,7 +246,7 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
         // 报价前预处理-保存车辆信息、过滤车型等处理
         PreResult pre = null;
         try {
-            pre = prepareQuote(attr, mmap, car, modelcodexh, cookie, quotationNo, xbResult);
+            pre = prepareQuote(attr, mmap, car, modelcodexh, cache.getCookie(), quotationNo, xbResult);
         } catch (Exception e) {
             log.error("报价失败:保存车辆信息、过滤车型异常,{}",e.getMessage());
             throw new SystemException(e.getMessage());
@@ -241,7 +254,7 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
         // 报价
         CoreResult core = null;
         try {
-            core = executeQuote(quoteVo, quotationNo, dto, cookie, pre, gsInfo, attr);
+            core = executeQuote(quoteVo, quotationNo, dto, cache.getCookie(), pre, gsInfo, attr);
         } catch (Exception e) {
             log.error("报价失败,{}",e.getMessage());
             throw new SystemException(e.getMessage());
@@ -335,9 +348,9 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
         //车型查询 -- renewCarInfo
         String carData = executeCarModelCodexhQuery(carDTO, car, cookie, quotationNo);
         // 核心:关闭「未知字段抛出异常」,优先级 > 类注解
-        MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        //MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
         // 可选:兼容空字符串、大小写字段(对接第三方接口常用)
-        MAPPER.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
+        //MAPPER.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
         Map<String, Object> rootMap = MAPPER.readValue(carData, new TypeReference<Map<String, Object>>() {});
         String datalistStr = (String) rootMap.get("datalist");
         String datalist2Str = (String) rootMap.get("datalist2");
@@ -365,6 +378,9 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
 
     private void executeSaveCarQuery(HtCrawlerCarQueryResponse.DataDTO.DataListDTO carDTO,
                                      HtCrawlerCarQueryResponse.DataDTO dataDTO, CarInfoVo car, String cookie) throws JsonProcessingException {
+        if (dataDTO.getDatalist2() == null || dataDTO.getDatalist2().isEmpty()) {
+            throw new SystemException("车辆信息不完整");
+        }
         String aa = URLEncoder.encode(MAPPER.writeValueAsString(carDTO), StandardCharsets.UTF_8);
         String bb = URLEncoder.encode(MAPPER.writeValueAsString(dataDTO.getDatalist2().get(0)), StandardCharsets.UTF_8);
 
@@ -790,10 +806,6 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
         //cookie还在,但服务器已断开连接,需重新连接
         if(res.contains("<html>")) {
             refreshLogin(buildLoginDTO(attr));
-            Map<String, Object> m = login(buildLoginDTO(attr));
-            String cookie = (String) m.get("cookie");
-            req.getHeaders().remove(HtRequestConstant.COOKIE);
-            req.getHeaders().add(HtRequestConstant.COOKIE, cookie);
             return underwriting(vo);
         }
         if (res.contains("起保时间不正确")) {
@@ -803,12 +815,12 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
         Map<String, Object> map = new HashMap<>();
         try {
             // 忽略未知字段
-            MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+            // MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
             // 空字符串转null
-            MAPPER.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
+            // 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_SINGLE_QUOTES, true);
+            // MAPPER.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
             // 允许换行符、回车符存在于字符串值中
             // MAPPER.configure(JsonParser.Feature.ALLOW_UNESCAPED_CONTROL_CHARS, true);
 
@@ -921,7 +933,7 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
     private void doLoginCookie(AttributionInformationVo attr) {
         if (StringUtils.isBlank(req.getCookie())) {
             Map<String, Object> m = login(buildLoginDTO(attr));
-            String cookie = (String) m.get("cookie");
+            String cookie = (String) m.get("cookies");
             req.getHeaders().remove(HtRequestConstant.COOKIE);
             req.getHeaders().add(HtRequestConstant.COOKIE, cookie);
         }
@@ -1333,13 +1345,16 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
     @FunctionalInterface
     public interface RetryableTask<T> { T execute() throws Exception; }
 
-    private <T> T retry(RetryableTask<T> task, int max, long delay, String name) {
+    private <T> T retry(RetryableTask<T> task, int max, long delay, int backoffFactor, String name) {
         for (int i = 0; i < max; i++) {
             try { return task.execute(); }
             catch (Exception e) {
                 log.warn("{} 失败,第 {} 次重试", name, i + 1);
                 if (i + 1 >= max) throw new SystemException(name + " 失败,已重试 " + max + " 次", e.getMessage());
-                sleep(delay);
+                // 指数退避:第1次 baseDelay,第2次 baseDelay*factor,第3次 baseDelay*factor^2 ...
+                long waitMs = delay * (long) Math.pow(Math.max(backoffFactor, 1), i);
+                log.info("{} 等待 {} ms 后重试", name, waitMs);
+                sleep(waitMs);
             }
         }
         throw new SystemException(name + " 失败,已达到最大重试次数");

+ 25 - 3
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/OrderOperationLogAspect.java

@@ -195,6 +195,16 @@ public class OrderOperationLogAspect {
             track.setOptContent(log.description());
             track.setChangeAfter(JSONUtil.toJsonStr(vo));
             track.setResult(JSONUtil.toJsonStr(result));
+            InsOrders insOrders = orderService.getById(orderNo);
+            if(insOrders != null){
+                InsOrdersCarInfo carInfo = carInfoService.getByOrderId(insOrders.getId());
+                track.setLicenseNo(carInfo.getLicenseNo());
+                track.setCompanyId(insOrders.getCompanyId());
+                // track.setResult(result.getMsg());
+            }else{
+                track.setResult("要修改的订单不存在");
+            }
+            track.setStatus(1);
             track.setOrderNo(orderNo);
             traceService.save(track);
 
@@ -209,13 +219,25 @@ public class OrderOperationLogAspect {
      */
     private void saveCostInfo(Object result, OrderOperationLog log, PtlAgreementCostRatioVo vo) {
         InsOrdersTrack track = new InsOrdersTrack();
+        String orderNo = vo.getOrderNo();
         track.setModule(log.module());
         track.setSubModule(log.subModule());
         track.setOptType(log.optType().getCode());
         track.setOptContent(log.description());
-        track.setResult(JSONUtil.toJsonStr(result));
-        track.setChangeAfter(JSONUtil.toJsonStr(vo));
-        track.setOrderNo(vo.getOrderNo());
+        track.setResult(JSONUtil.toJsonStr(vo));
+        InsOrders insOrders = orderService.getById(orderNo);
+        if(insOrders != null){
+            InsOrdersCarInfo carInfo = carInfoService.getByOrderId(insOrders.getId());
+            track.setLicenseNo(carInfo.getLicenseNo());
+            track.setCompanyId(insOrders.getCompanyId());
+            // track.setResult(result.getMsg());
+        }else{
+            track.setResult("要进行费用调整的订单不存在");
+        }
+        track.setStatus(1);
+        track.setChangeBefore("");
+        track.setChangeAfter("费用调整完成");
+        track.setOrderNo(orderNo);
         track.setResult(JSONUtil.toJsonStr(result));
         traceService.save(track);
     }

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

@@ -357,6 +357,7 @@ public class QuoteVerificationAspect {
 
         // modify by lipf ,2026年6月17日15:30:54 是否除以1.06,不再根据平台协议还是私有协议进行判断,而是根据协议的是否含税来进行判断
         BigDecimal taxFactor = insOrdersService.obtainTaxRate(insOrders.getId());
+        log.info("订单[{}]是否属于补录订单.[{}]",Objects.toString(insOrders.getId(),insOrders.getInsOrderNo()), isrecordByLeader);
         // 6. 统一处理各险种的费用计算(应收、应付、各类费用)
         processInsuranceType(
                 insOrdersCosts.getJqPremium(), jqCostType, jqEntranceFeeRatio, jqFollowRatio, taxFactor,
@@ -477,6 +478,11 @@ public class QuoteVerificationAspect {
         if(isrecordByLeader){
             // 如果是代客录单,出口比例减去一个百分比,也就是 0.01 2026年7月11日09:30:09
             exportPercent = BigDecimalUtil.subtract(exportPercent, new BigDecimal("0.01"));
+            // 代客录单-1时,出口不够减的情况直接为0 add by lipf 2026年7月14日09:06:50
+            if(BigDecimal.ZERO.compareTo(exportPercent) >0){
+                log.info("代客录单-1时,出口不够减的情况直接为0。exportPercent=[{}]",exportPercent);
+                exportPercent = new BigDecimal("0");
+            }
         }
 
         // 去税保费金额

+ 13 - 3
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/InsFeeOrderController.java

@@ -1,6 +1,6 @@
 package com.jzg.quotation.summary.controller;
 
-import com.alibaba.fastjson.JSONObject;
+import cn.hutool.json.JSONUtil;
 import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.dto.InsFeeOrdersParam;
 import com.jzg.commons.entity.po.InsFeeOrders;
@@ -8,6 +8,8 @@ import com.jzg.quotation.summary.entity.dto.RightsAmountUpdateDto;
 import com.jzg.quotation.summary.service.InsFeeOrdersService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -25,6 +27,8 @@ public class InsFeeOrderController {
     @Autowired
     private InsFeeOrdersService insFeeOrdersService;
 
+    private static final Logger log = LoggerFactory.getLogger(InsFeeOrderController.class);
+
     /**
      * 订单列表分页
      * @return
@@ -35,10 +39,16 @@ public class InsFeeOrderController {
         return insFeeOrdersService.getInsFeeOrdersList(param);
     }
 
+    /**
+     * 这个接口目前不能用, 后期可能会被废弃
+     *
+     * @author lipf
+     * @date 2026/7/15 16:08
+     */
     @PostMapping("/getInsFeeOrderByUserId")
     @Operation(summary = "订单费用列表通过用户id查询")
-    public List<InsFeeOrders> getInsFeeOrderByUserId(@RequestBody JSONObject param){
-        InsFeeOrdersParam insFeeOrdersParam = param.toJavaObject(InsFeeOrdersParam.class);
+    public List<InsFeeOrders> getInsFeeOrderByUserId(@RequestBody InsFeeOrdersParam insFeeOrdersParam){
+        log.info("订单费用列表通过用户id查询:insFeeOrdersParam=[{}],createTimeStart=[{}],createTimeEnd=[{}]", JSONUtil.toJsonStr(insFeeOrdersParam), insFeeOrdersParam.getCreateTimeStart(), insFeeOrdersParam.getCreateTimeEnd() );
         return insFeeOrdersService.getInsFeeOrderListByUserId(insFeeOrdersParam);
     }
 

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

@@ -494,6 +494,7 @@ public class InsFeeAuditServiceImpl extends ServiceImpl<InsFeeAuditMapper, InsFe
 
             // 更新用户账户
             feeOrders = feeOrdersService.getById(param.getOrderNo());
+            log.info("根据订单查询出的费用信息如下:feeOrders=[{}]", JSONUtil.toJsonStr(feeOrders));
             HttpResult<SysUser> sysUserResult = orgClient.getUserOnlyIdByMobile(orders.getRealQuoteUserId());
             SysUser ywySysUser = sysUserResult.getData();
             HttpResult<SysUserAccount> result = orgClient.accountGet(ywySysUser.getId());
@@ -517,6 +518,7 @@ public class InsFeeAuditServiceImpl extends ServiceImpl<InsFeeAuditMapper, InsFe
             }
             BigDecimal sumAmountUnpaid = userAccount.getSumAmountUnpaid();
             BigDecimal amount = feeOrders.getTotalPayablePremium();
+            log.info("费用审核通过。 amount=[{}].feeOrders=[{}]",amount, JSONUtil.toJsonStr(feeOrders));
             userAccount.setSumAmount(BigDecimalUtil.add(amount,userAccount.getSumAmount()));
             userAccount.setSumAmountUnpaid(BigDecimalUtil.add(amount, sumAmountUnpaid));
             orgClient.saveOrUpdate(userAccount);
@@ -531,6 +533,7 @@ public class InsFeeAuditServiceImpl extends ServiceImpl<InsFeeAuditMapper, InsFe
             exportChangeLog.setIsDelete(0);
             exportChangeLog.setRemark("保单费用");
             exportChangeLog.setAmountBefore(sumAmountUnpaid);
+            log.info("准备调用orgClient保存账号变更明细:exportChangeLog=[{}]", JSONUtil.toJsonStr(exportChangeLog));
             orgClient.addUserAccountChangeLog(exportChangeLog);
 
             // 进入应收表

+ 3 - 1
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeOrdersServiceImpl.java

@@ -449,7 +449,9 @@ public class InsFeeOrdersServiceImpl extends ServiceImpl<InsFeeOrdersMapper, Ins
 
     @Override
     public List<InsFeeOrders> getInsFeeOrderListByUserId(InsFeeOrdersParam param) {
-        return insFeeOrdersMapper.getInsFeeOrderListByUserId(param);
+        List<InsFeeOrders> insFeeOrders = insFeeOrdersMapper.getInsFeeOrderListByUserId(param);
+        log.debug("查询费用信息:param=[{}]insFeeOrders.size=[{}]", JSONUtil.toJsonStr(param), CollUtil.size(insFeeOrders));
+        return insFeeOrders;
     }
 
     @Override

+ 12 - 1
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrdersServiceImpl.java

@@ -42,6 +42,7 @@ import com.jzg.commons.entity.quote.vo.orders.InsOrdersAdd;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersEnd;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersVo;
 import com.jzg.commons.entity.rights.vo.InsOrderRightsInfoVo;
+import com.jzg.commons.entity.system.vo.SysSystemBusPermsVo;
 import com.jzg.commons.entity.vo.*;
 import com.jzg.commons.exception.ServiceException;
 import com.jzg.commons.exception.SystemException;
@@ -52,6 +53,7 @@ import com.jzg.quotation.commons.client.PlatformClient;
 import com.jzg.quotation.commons.utils.BeanCopyUtil;
 import com.jzg.quotation.commons.utils.SnowFlakeUtil;
 import com.jzg.quotation.summary.aop.aspect.QuoteVerificationAspect;
+import com.jzg.quotation.summary.client.EsmInsCompanyClient;
 import com.jzg.quotation.summary.consumer.template.OrderMessageTemplate;
 import com.jzg.quotation.summary.entity.bo.DataValueBo;
 import com.jzg.quotation.summary.entity.vo.*;
@@ -118,6 +120,8 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
 
     private final PlatformClient platformClient;
 
+    private final EsmInsCompanyClient esmInsCompanyClient;
+
     private final BaseController baseController;
 
     private final InsOrderAdjustInfoService orderAdjustInfoService;
@@ -1325,6 +1329,7 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
         log.info("根据orderNo=[{}]查询到的订单明细[{}]", ordersNo, JSONUtil.toJsonStr(insOrdersVo));
         AssertionUtils.isFail(Objects.isNull(insOrdersVo), "订单不存在");
         QuoteEchoVo resultVo = new QuoteEchoVo(insOrdersVo);
+        resultVo.setEntryStatus(insOrdersVo.getEntryStatus());
         //获取保司信息
         String companyId = insOrdersVo.getInsOrders().getCompanyId();
         HttpResult<EsmInsCompany> esmInsCompanyHttpResult = platformClient.findLogoById(companyId);
@@ -1405,7 +1410,13 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
             resultVo.setCostRatio(new PtlAgreementCostRatioVo(insFeeOrders));
             resultVo.setInsFeeOrders(new InsFeeOrdersVo(insFeeOrders));
         }
-        //权益信息
+        // 权益权限
+        HttpResult<SysSystemBusPermsVo> sysSystemBusPermsVoHttpResult = esmInsCompanyClient.getBusPerms(baseController.getSystemCode());
+        if (sysSystemBusPermsVoHttpResult.getCode() == 200) {
+            resultVo.setOwnerRights(String.valueOf(sysSystemBusPermsVoHttpResult.getData().getOwnerRights()));
+            resultVo.setClientType(String.valueOf(sysSystemBusPermsVoHttpResult.getData().getClientType()));
+        }
+        // 权益信息
         InsOrderRightsInfoVo insOrderRightsInfoVo = insOrderRightsInfoService.queryByOrderNo(ordersNo);
         resultVo.setInsOrderRightsInfoVo(insOrderRightsInfoVo);
         log.info("根据订单ordersNo=[{}]获取到订单的详细信息resultVo=[{}]", ordersNo, JSONUtil.toJsonStr(resultVo));

+ 7 - 1
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrdersTrackServiceImpl.java

@@ -1,12 +1,15 @@
 package com.jzg.quotation.summary.service.impl;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.jzg.commons.entity.dto.OrdersTrackParam;
 import com.jzg.commons.entity.orders.po.InsOrdersTrack;
 import com.jzg.commons.entity.vo.OrdersTrackVo;
 import com.jzg.quotation.summary.mapper.InsOrdersTrackMapper;
 import com.jzg.quotation.summary.service.InsOrdersTrackService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -20,8 +23,11 @@ import java.util.List;
 public class InsOrdersTrackServiceImpl extends ServiceImpl<InsOrdersTrackMapper, InsOrdersTrack>
     implements InsOrdersTrackService {
 
+    private static final Logger log = LoggerFactory.getLogger(InsOrdersTrackServiceImpl.class);
+
     @Override
     public List<OrdersTrackVo> list(OrdersTrackParam param) {
+        log.info("查询订单轨迹:param=[{}]", JSONUtil.toJsonStr(param));
         List<OrdersTrackVo> ordersTrackVos = baseMapper.queryList(param);
         return ordersTrackVos;
     }

+ 1 - 0
tenant/insurance/quotation-summary/src/main/resources/mapper/InsOrdersMapper.xml

@@ -764,6 +764,7 @@
 
     <select id="getById" resultMap="InsOrdersVoMap">
         select id,
+        entry_status,
         quote_no,
         agreement_id,
         company_id,

+ 45 - 0
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/cache/RedisCacheUtil.java

@@ -3,6 +3,7 @@ package com.jzg.quotation.taikang.crawler.cache;
 
 import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONObject;
+import com.jzg.commons.entity.quote.vo.aggregated.InsuranceUploadImageVo;
 import com.jzg.quotation.taikang.crawler.model.TKLoginSession;
 import com.jzg.quotation.taikang.crawler.model.api.PreciseInitResult;
 import com.jzg.quotation.taikang.crawler.model.entity.po.TKCrawlerOrder;
@@ -22,6 +23,11 @@ public class RedisCacheUtil {
     private static final String SESSION = "SESSION";
     public static String TAIKANG_ORDER_RESPONSE = "taikang:order:response:";
     public static final long TAIKANG_ORDER_RESPONSE_TIME = 1L;
+    
+    /**
+     * 影像上传参数缓存前缀
+     */
+    public static final String TAIKANG_IMAGE_UPLOAD_PARAM = "taikang:image:upload:param:";
 
     public RedisCacheUtil(RedissonClient redissonClient) {
         this.redissonClient = redissonClient;
@@ -122,4 +128,43 @@ public class RedisCacheUtil {
         return tiJinCrawlerOrder;
     }
 
+    /**
+     * 缓存影像上传参数
+     *
+     * @param ordersNo               订单号
+     * @param insuranceUploadImageVo 影像上传参数
+     */
+    public void setImageUploadParam(String ordersNo, InsuranceUploadImageVo insuranceUploadImageVo) {
+        String response = JSONObject.toJSONString(insuranceUploadImageVo);
+        RBucket<String> bucket = redissonClient.getBucket(TAIKANG_IMAGE_UPLOAD_PARAM + ordersNo);
+        bucket.set(response, Duration.ofHours(2L));
+        log.info("影像上传参数已缓存: ordersNo={}", ordersNo);
+    }
+
+    /**
+     * 获取影像上传参数
+     *
+     * @param ordersNo 订单号
+     * @return 影像上传参数
+     */
+    public InsuranceUploadImageVo getImageUploadParam(String ordersNo) {
+        RBucket<String> bucket = redissonClient.getBucket(TAIKANG_IMAGE_UPLOAD_PARAM + ordersNo);
+        String json = bucket.get();
+        if (json == null) {
+            log.warn("未查询到影像上传参数: ordersNo={}", ordersNo);
+            return null;
+        }
+        return JSON.parseObject(json, InsuranceUploadImageVo.class);
+    }
+
+    /**
+     * 删除影像上传参数缓存
+     *
+     * @param ordersNo 订单号
+     */
+    public void deleteImageUploadParam(String ordersNo) {
+        redissonClient.getBucket(TAIKANG_IMAGE_UPLOAD_PARAM + ordersNo).delete();
+        log.info("影像上传参数缓存已删除: ordersNo={}", ordersNo);
+    }
+
 }

+ 5 - 0
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/client/HttpURL.java

@@ -127,4 +127,9 @@ public interface HttpURL {
      * 上传影像
      */
     String carCheckUploadFile = host + "/carSelfService/carCheck/upload/file";
+    String carCheckUploadFile2 = host + "/carSelfService/carCheck/qualityVerifyImg";
+    /**
+     * 上传影像提交
+     */
+    String carCheckUploadFileSubmit = host + "/carSelfService/carCheck/submit";
 }

+ 35 - 0
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/api/CarCheckUploadFileSubmitParam.java

@@ -0,0 +1,35 @@
+package com.jzg.quotation.taikang.crawler.model.api;
+
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Setter
+@Getter
+@Data
+public class CarCheckUploadFileSubmitParam {
+
+    /**
+     * 上传类型
+     */
+    private String orderType;
+    /**
+     * 表单ID
+     */
+    private String formId;
+    /**
+     * 投保单号
+     */
+    private String fullProposalNo;
+    /**
+     * 渠道编码
+     */
+    private String channelCode;
+    /**
+     * 字段ID列表
+     */
+    private List<String> fieldIds;
+
+}

+ 53 - 0
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/api/CarCheckUploadFileVerifyImgParam.java

@@ -0,0 +1,53 @@
+package com.jzg.quotation.taikang.crawler.model.api;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class CarCheckUploadFileVerifyImgParam {
+
+    /**
+     * 拍摄省份
+     */
+    private String shootProvince;
+
+    /**
+     * 拍摄城市
+     */
+    private String shootCity;
+
+    /**
+     * 类型路径
+     */
+    private String typePath;
+
+    /**
+     * 图片base64编码文件名
+     */
+    private String base64FileName;
+
+    /**
+     * 图片base64编码字符串
+     */
+    private String base64File;
+
+    /**
+     * 上传类型
+     */
+    private Integer uploadType;
+
+    /**
+     * 文件类型(与文件原始名称可能重复,根据业务逻辑确认是否区分)
+     */
+    private String fileType;
+    /**
+     * 投保单号
+     */
+    private String fullProposalNo;
+    /**
+     * 渠道编码
+     */
+    private String channelCode;
+
+}

+ 5 - 0
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/model/api/TKEntranceFor000086Result.java

@@ -65,6 +65,11 @@ public class TKEntranceFor000086Result extends UnknownFieldEntity {
      */
     private String areaCname;
 
+    /**
+     * 意见信息
+     */
+    private String dealOpinion;
+
     /**
      * 内部分发ID
      */

+ 35 - 5
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/service/TKHttpAPIService.java

@@ -1,12 +1,9 @@
 package com.jzg.quotation.taikang.crawler.service;
 
 import cn.hutool.core.bean.BeanUtil;
-
-import com.jzg.commons.entity.quote.vo.CarInfoVo;
-import com.jzg.commons.entity.quote.vo.CustomerInfoVo;
+import com.alibaba.fastjson.JSONObject;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.commons.exception.SystemException;
-
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
 import com.jzg.quotation.taikang.crawler.CodeUtil;
 import com.jzg.quotation.taikang.crawler.JsonUtil;
@@ -16,6 +13,7 @@ import com.jzg.quotation.taikang.crawler.model.api.*;
 import com.jzg.quotation.taikang.crawler.model.entity.*;
 import jakarta.annotation.Resource;
 import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpHeaders;
@@ -24,11 +22,11 @@ import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 
 import java.io.File;
-import java.math.BigDecimal;
 import java.util.*;
 
 @Setter
 @Service
+@Slf4j
 public class TKHttpAPIService {
     private static final Logger logger = LoggerFactory.getLogger(TKHttpAPIService.class);
 
@@ -1169,6 +1167,38 @@ public class TKHttpAPIService {
         client.uploadFileWithParams(HttpURL.carCheckUploadFile, formData, file);
     }
 
+    /**
+     * 上传影像(批量上传,直接发送对象集合)
+     *
+     * @param params 影像上传参数集合
+     */
+    public void qualityVerifyImgBatch(List<CarCheckUploadFileVerifyImgParam> params) {
+        logger.info("批量上传影像,参数数量: {}", params != null ? params.size() : 0);
+        HttpHeaders httpHeaders = new HttpHeaders();
+        httpHeaders.add("Content-Type", "application/json");
+        
+        client.request(HttpURL.carCheckUploadFile2, params, httpHeaders, String.class);
+        log.info("批量上传影像完成");
+    }
+
+    public void carCheckUploadFileSubmit(String token, String fromId, String fullProposalNo, String orderId) {
+        CarCheckUploadFileSubmitParam param = new CarCheckUploadFileSubmitParam();
+        param.setChannelCode("OffWeb");
+        param.setFormId(fromId);
+        ArrayList<String> strings = new ArrayList<>();
+        strings.add("1");
+        param.setFieldIds(strings);
+        param.setFullProposalNo(fullProposalNo);
+        param.setOrderType("1");
+
+        HttpHeaders httpHeaders = new HttpHeaders();
+        httpHeaders.add("tkCarRequestToken", token);
+        httpHeaders.add("carInsurFlowId", "carInsur1778568776607661015");
+        httpHeaders.add("carInsurOrderId", orderId);
+        Object response = client.request(HttpURL.carCheckUploadFileSubmit, param, httpHeaders, Object.class);
+        log.info("上传影像提交完成,响应: {}", JSONObject.toJSONString(response));
+    }
+
     public TKEntranceFor000021Result entranceFor000021(String token, String fromId, String mainOrderId) {
         TKEntranceFor000021Param param = new TKEntranceFor000021Param();
         param.setChannelCode("OffWeb");

+ 383 - 32
tenant/insurance/quotation-taikang/src/main/java/com/jzg/quotation/taikang/crawler/service/impl/TKQuotationBaseServiceImpl.java

@@ -1,5 +1,7 @@
 package com.jzg.quotation.taikang.crawler.service.impl;
 
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.nacos.common.utils.CollectionUtils;
 import com.google.gson.Gson;
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
 import com.jzg.commons.entity.orders.po.InsOrdersCarUserInfo;
@@ -9,6 +11,7 @@ import com.jzg.commons.entity.quote.vo.aggregated.*;
 import com.jzg.commons.entity.quote.vo.base.LoginBase;
 import com.jzg.commons.entity.quote.vo.image.InsuranceImageVo;
 import com.jzg.commons.util.ImageUtil;
+import com.jzg.commons.util.StringUtils;
 import com.jzg.quotation.commons.annotation.QuoteCrawlerService;
 import com.jzg.quotation.commons.constant.InsuranceCode;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
@@ -21,7 +24,6 @@ import com.jzg.quotation.taikang.crawler.model.TKLoginSession;
 import com.jzg.quotation.taikang.crawler.model.api.*;
 import com.jzg.quotation.taikang.crawler.model.entity.TKAreaInfoVo;
 import com.jzg.quotation.taikang.crawler.model.entity.TKInsureInfo;
-import com.jzg.quotation.taikang.crawler.model.entity.TKOrderCheckCarSpecification;
 import com.jzg.quotation.taikang.crawler.model.entity.TKOrderData;
 import com.jzg.quotation.taikang.crawler.model.entity.po.TKCrawlerOrder;
 import com.jzg.quotation.taikang.crawler.repository.TKLoginSessionRepository;
@@ -38,6 +40,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 
 import java.io.File;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 
@@ -216,29 +219,205 @@ public class TKQuotationBaseServiceImpl implements TKQuotationBaseService {
         return underwritingResultsVo;
     }
 
-    private void buildCheckCar(TKEntranceFor000038Result tkEntranceFor000038Result, UnderwritingVo underwritingVo, PreciseInitResult preciseInitResult, UnderwritingResultsVo underwritingResultsVo) {
-        // 需要验车,需要上传影像
-
-        // 验车照片详情列表
-        // List<TKOrderCheckCarSpecification> checkCarSpecification = tkEntranceFor000038Result.getCheckCarSpecification();
-        // // 验车原因
-        // Object checkReason = tkEntranceFor000038Result.getCheckReason();
-        // // 人工审核
-        // List<String> underwriteReason = tkEntranceFor000038Result.getUnderwriteReason();
-        // 验车码
-        // String checkCarCode = httpService.entranceFor000133(session.getToken(), preciseInitResult.getMainOrderId());
-        // 上传视频图像的二维码数据示例:https://car.tk.cn/carTKInsure/#/schema?type=checkcar&fullProposalNo=00671070808142500000004429&orderType=1
-        // 其中 00671070808142500000004429 的商业保险单号
-
-        // todo: 需要找个有验车码的车辆进行测试
-        // InsuranceUploadImageVo insuranceUploadImageVo = new InsuranceUploadImageVo();
-        // insuranceUploadImageVo.setOrder(underwritingVo.getOrder());
-        // insuranceUploadImageVo.setImageVoList();
-        // uploadImage(insuranceUploadImageVo);
-
-        // 核保结果
-        underwritingResultsVo.setUnderwritingResult(tkEntranceFor000038Result.getData().getSpResMsg() + ",原因:" + tkEntranceFor000038Result.getCheckReason());
-        // 核保状态
+    /**
+     * 处理验车上传影像流程
+     * <p>
+     * 当核保返回需要验车上传影像时,执行以下流程:
+     * 1. 获取核保返回的保司订单号
+     * 2. 从 Redis 获取前端提前缓存的影像上传参数
+     * 3. 设置保司订单号并上传影像到保司
+     * 4. 查询订单状态并更新核保结果
+     *
+     * @param tkEntranceFor000038Result 核保结果
+     * @param underwritingVo            核保参数
+     * @param preciseInitResult         精准报价结果
+     * @param underwritingResultsVo     核保结果返回
+     */
+    private void buildCheckCar(TKEntranceFor000038Result tkEntranceFor000038Result, 
+                               UnderwritingVo underwritingVo, 
+                               PreciseInitResult preciseInitResult, 
+                               UnderwritingResultsVo underwritingResultsVo) {
+        log.info("========== 开始处理验车上传影像流程 ==========");
+
+        try {
+            // 1. 获取核保返回的保司订单号
+            String proposalNo = extractProposalNo(tkEntranceFor000038Result, underwritingVo);
+            
+            // 2. 从 Redis 获取缓存的影像上传参数(前端提前上传的)
+            String ordersNo = underwritingVo.getOrder().getOrdersNo();
+            InsuranceUploadImageVo insuranceUploadImageVo = redisCacheUtil.getImageUploadParam(ordersNo);
+
+            // 3. 如果有缓存的影像参数,设置保司订单号并清除缓存
+            if (insuranceUploadImageVo != null) {
+                log.info("从 Redis 获取到缓存的影像上传参数,影像数量: {}", 
+                        insuranceUploadImageVo.getImageVoList() != null ? insuranceUploadImageVo.getImageVoList().size() : 0);
+                
+                // 设置保司订单号(核保成功后已返回)
+                if (proposalNo != null) {
+                    insuranceUploadImageVo.getOrder().setCompanyOrderNo(proposalNo);
+                    log.info("已为缓存的影像上传参数设置保司订单号: {}", proposalNo);
+                }
+                
+                // 删除 Redis 中的缓存(已使用,不再需要)
+                redisCacheUtil.deleteImageUploadParam(ordersNo);
+            }
+
+            // 4. 如果有影像资料,上传到保司并查询订单状态
+            if (hasValidImages(insuranceUploadImageVo)) {
+                // 上传影像
+                log.info("开始上传影像资料...");
+                qualityVerifyImg(insuranceUploadImageVo);
+                log.info("影像资料上传成功");
+
+                // 查询订单状态
+                log.info("开始查询订单状态...");
+                OrderStatusResultVo orderStatusResultVo = queryOrderStatus(underwritingVo);
+                log.info("订单状态查询完成,响应: {}", JSONObject.toJSONString(orderStatusResultVo));
+
+                // 更新核保结果
+                updateUnderwritingResultByOrderStatus(tkEntranceFor000038Result, orderStatusResultVo, underwritingResultsVo);
+                log.info("订单状态查询完成,状态: {}", underwritingResultsVo.getUnderwritingStatus());
+            } else {
+                // 没有影像资料,保持人工处理状态
+                setStaffProcessStatus(tkEntranceFor000038Result, underwritingResultsVo, "未查询到影像资料");
+            }
+
+        } catch (Exception e) {
+            log.error("处理验车上传影像失败", e);
+            // 处理失败时保持人工处理状态
+            underwritingResultsVo.setUnderwritingResult("验车影像上传处理异常:" + e.getMessage());
+            underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.STAFF_PROCESS);
+        }
+
+        log.info("========== 验车上传影像流程处理结束 ==========");
+    }
+
+    /**
+     * 从核保结果中提取保司订单号
+     *
+     * @param tkEntranceFor000038Result 核保结果
+     * @param underwritingVo            核保参数
+     * @return 保司订单号
+     */
+    private String extractProposalNo(TKEntranceFor000038Result tkEntranceFor000038Result, UnderwritingVo underwritingVo) {
+        TKOrderData tkOrderData = tkEntranceFor000038Result.getData();
+        if (tkOrderData == null || tkOrderData.getProposalNo() == null) {
+            return null;
+        }
+        
+        String proposalNo = tkOrderData.getProposalNo();
+        underwritingVo.getOrder().setCompanyOrderNo(proposalNo);
+        log.info("核保返回保司订单号: {}", proposalNo);
+        return proposalNo;
+    }
+
+    /**
+     * 判断是否有有效的影像资料
+     *
+     * @param insuranceUploadImageVo 影像上传参数
+     * @return true 表示有有效影像,false 表示无
+     */
+    private boolean hasValidImages(InsuranceUploadImageVo insuranceUploadImageVo) {
+        return insuranceUploadImageVo != null && CollectionUtils.isNotEmpty(insuranceUploadImageVo.getImageVoList());
+    }
+
+    /**
+     * 查询订单状态
+     *
+     * @param underwritingVo 核保参数
+     * @return 订单状态查询结果
+     */
+    private OrderStatusResultVo queryOrderStatus(UnderwritingVo underwritingVo) {
+        OrderStatusVo orderStatusVo = new OrderStatusVo();
+        orderStatusVo.setOrder(underwritingVo.getOrder());
+        return queryOrderState(orderStatusVo);
+    }
+
+    /**
+     * 根据订单状态查询结果更新核保结果
+     *
+     * @param tkEntranceFor000038Result 核保结果
+     * @param orderStatusResultVo       订单状态查询结果
+     * @param underwritingResultsVo     核保结果返回
+     */
+    private void updateUnderwritingResultByOrderStatus(TKEntranceFor000038Result tkEntranceFor000038Result,
+                                                       OrderStatusResultVo orderStatusResultVo,
+                                                       UnderwritingResultsVo underwritingResultsVo) {
+        if (orderStatusResultVo == null || orderStatusResultVo.getOrderStatus() == null) {
+            return;
+        }
+
+        InsOrderStatusEnum orderStatus = orderStatusResultVo.getOrderStatus();
+        underwritingResultsVo.setUnderwritingStatus(orderStatus);
+
+        // 根据不同状态设置核保结果描述
+        String resultDesc = buildResultDescription(orderStatus, orderStatusResultVo, tkEntranceFor000038Result);
+        underwritingResultsVo.setUnderwritingResult(resultDesc);
+
+        // 设置支付链接(仅待支付状态)
+        if (InsOrderStatusEnum.PAY_PENDING.equals(orderStatus)) {
+            underwritingResultsVo.setPaymentLink(orderStatusResultVo.getPaymentLink());
+        }
+
+        // 更新投保单号(交强险、商业险、驾意险)
+        updateApplyNos(orderStatusResultVo, underwritingResultsVo);
+    }
+
+    /**
+     * 构建核保结果描述
+     *
+     * @param orderStatus               订单状态
+     * @param orderStatusResultVo       订单状态查询结果
+     * @param tkEntranceFor000038Result 核保结果
+     * @return 核保结果描述
+     */
+    private String buildResultDescription(InsOrderStatusEnum orderStatus,
+                                          OrderStatusResultVo orderStatusResultVo,
+                                          TKEntranceFor000038Result tkEntranceFor000038Result) {
+        return switch (orderStatus) {
+            case PAY_PENDING -> "核保成功";
+            case UNDERWRITED -> "已承保";
+            case WAIT_AUDIT -> "待核保";
+            case AUDIT_FAIL -> "核保失败";
+            case STAFF_PROCESS -> "人工审核,原因:" + orderStatusResultVo.getErrorMsg();
+            default -> {
+                TKOrderData data = tkEntranceFor000038Result.getData();
+                yield (data != null ? data.getSpResMsg() : "") + ",原因:" + tkEntranceFor000038Result.getCheckCarData();
+            }
+        };
+    }
+
+    /**
+     * 更新投保单号信息
+     *
+     * @param orderStatusResultVo   订单状态查询结果
+     * @param underwritingResultsVo 核保结果返回
+     */
+    private void updateApplyNos(OrderStatusResultVo orderStatusResultVo, UnderwritingResultsVo underwritingResultsVo) {
+        if (orderStatusResultVo.getJqApplyNo() != null) {
+            underwritingResultsVo.setJqApplyNo(orderStatusResultVo.getJqApplyNo());
+        }
+        if (orderStatusResultVo.getSyApplyNo() != null) {
+            underwritingResultsVo.setSyApplyNo(orderStatusResultVo.getSyApplyNo());
+        }
+        if (orderStatusResultVo.getJyApplyNo() != null) {
+            underwritingResultsVo.setJyApplyNo(orderStatusResultVo.getJyApplyNo());
+        }
+    }
+
+    /**
+     * 设置人工处理状态
+     *
+     * @param tkEntranceFor000038Result 核保结果
+     * @param underwritingResultsVo     核保结果返回
+     * @param reason                    原因描述
+     */
+    private void setStaffProcessStatus(TKEntranceFor000038Result tkEntranceFor000038Result,
+                                       UnderwritingResultsVo underwritingResultsVo,
+                                       String reason) {
+        log.warn("{},保持人工处理状态", reason);
+        TKOrderData data = tkEntranceFor000038Result.getData();
+        underwritingResultsVo.setUnderwritingResult((data != null ? data.getSpResMsg() : "") + ",原因:" + tkEntranceFor000038Result.getCheckCarData());
         underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.STAFF_PROCESS);
     }
 
@@ -255,19 +434,41 @@ public class TKQuotationBaseServiceImpl implements TKQuotationBaseService {
 
     @Override
     public void uploadImage(InsuranceUploadImageVo insuranceUploadImageVo) {
+        // 获取保司订单号(fullProposalNo),核保成功后才会有值
+        String companyOrderNo = insuranceUploadImageVo.getOrder().getCompanyOrderNo();
+
+        // 如果保司订单号为空,说明第一次进行核保,将影像上传参数缓存到 Redis
+        // 泰康只有进行验车时必须要进行影像资料上传,其他情况没有验车资料也可以进行核保
+        if (companyOrderNo == null || companyOrderNo.isEmpty()) {
+            log.info("保司订单号为空,影像上传参数将缓存到 Redis,等待核保完成后再上传: ordersNo={}",
+                    insuranceUploadImageVo.getOrder().getOrdersNo());
+            redisCacheUtil.setImageUploadParam(insuranceUploadImageVo.getOrder().getOrdersNo(), insuranceUploadImageVo);
+            return;
+        }
+
+        // 保司订单号已存在,直接进行影像上传
+        qualityVerifyImg(insuranceUploadImageVo);
+    }
+
+    /**
+     * 执行影像上传操作
+     *
+     * @param insuranceUploadImageVo 影像上传参数
+     */
+    private void doUploadImage(InsuranceUploadImageVo insuranceUploadImageVo) {
         AttributionInformationVo attributionInformationVo = insuranceUploadImageVo.getOrder().getAttributionInformationVo();
         TKLoginSession session = loginSession(attributionInformationVo.getUsername(), attributionInformationVo.getPassword());
         CarCheckUploadFileParam param = new CarCheckUploadFileParam();
-        // 泰康订单
+
+        // 获取泰康订单号
         String orderID = redisCacheUtil.getCache(insuranceUploadImageVo.getOrder().getOrdersNo(), "DD");
-        // 泰康保单号, 现在获取不到,核保成功之后才会返回
-        // String proposalNo = redisCacheUtil.getCache(insuranceUploadImageVo.getOrder().getOrdersNo(), "HB");
 
+        // 设置上传参数
         param.setChannelCode("OffWeb");
         param.setTplatformId(session.getTplatformId());
         param.setOnlyId(orderID);
         param.setOrderID(orderID);
-        param.setFullProposalNo(insuranceUploadImageVo.getOrder().getCompanyOrderNo() == null ? insuranceUploadImageVo.getOrder().getQuoteNo() : insuranceUploadImageVo.getOrder().getCompanyOrderNo());
+        param.setFullProposalNo(insuranceUploadImageVo.getOrder().getCompanyOrderNo());
         param.setLastFullProposalNo(insuranceUploadImageVo.getOrder().getCompanyOrderNo());
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         Date date = new Date();
@@ -329,8 +530,158 @@ public class TKQuotationBaseServiceImpl implements TKQuotationBaseService {
                     }
                 });
             }
-
         });
+    }
+
+    /**
+     * 执行影像上传操作(批量上传)
+     * <p>
+     * 该方法负责将前端上传的影像资料(行驶证、身份证等)批量上传到泰康保司系统。
+     * 流程:
+     * 1. 获取登录会话信息
+     * 2. 从Redis获取泰康订单号
+     * 3. 遍历影像列表,根据影像类型构建上传参数
+     * 4. 调用批量上传接口将所有影像一次性上传
+     * 5. 调用影像提交接口完成上传流程
+     *
+     * @param insuranceUploadImageVo 影像上传参数,包含订单信息和影像列表
+     */
+    private void qualityVerifyImg(InsuranceUploadImageVo insuranceUploadImageVo) {
+        // 1. 获取归属信息(用户名、密码)用于登录保司系统
+        AttributionInformationVo attributionInformationVo = insuranceUploadImageVo.getOrder().getAttributionInformationVo();
+
+        // 2. 获取登录会话信息
+        TKLoginSession session = loginSession(attributionInformationVo.getUsername(), attributionInformationVo.getPassword());
+
+        // 3. 从Redis缓存中获取泰康订单号(DD标识)
+        String orderID = redisCacheUtil.getCache(insuranceUploadImageVo.getOrder().getOrdersNo(), "DD");
+        log.info("影像上传 - 获取泰康订单号: {}", orderID);
+
+        // 4. 获取影像列表
+        List<InsuranceImageVo> imageVoList = insuranceUploadImageVo.getImageVoList();
+        if (CollectionUtils.isEmpty(imageVoList)) {
+            log.warn("影像上传 - 影像列表为空,跳过上传");
+            return;
+        }
+
+        // 5. 构建批量上传参数列表
+        List<CarCheckUploadFileVerifyImgParam> uploadParamsList = buildUploadParams(insuranceUploadImageVo, imageVoList);
+
+        // 6. 如果没有需要上传的参数,直接返回
+        if (CollectionUtils.isEmpty(uploadParamsList)) {
+            log.warn("影像上传 - 未构建到有效的上传参数,跳过上传");
+            return;
+        }
+
+        log.info("影像上传 - 准备批量上传 {} 个影像参数", uploadParamsList.size());
+
+        // 7. 调用批量上传接口,一次性发送所有影像参数
+        httpService.qualityVerifyImgBatch(uploadParamsList);
+
+        // 8. 调用影像提交接口,完成上传流程
+        httpService.carCheckUploadFileSubmit(
+                session.getToken(),
+                session.getTplatformId(),
+                insuranceUploadImageVo.getOrder().getCompanyOrderNo(),
+                orderID
+        );
+
+        log.info("影像上传 - 上传完成,订单号: {}", orderID);
+    }
+
+    /**
+     * 构建影像上传参数列表
+     * <p>
+     * 根据影像类型(行驶证、身份证)构建对应的上传参数对象。
+     * 影像类型编码说明:
+     * - C01: 行驶证正面
+     * - D01: 行驶证反面
+     * - C02: 车主身份证正面
+     * - D02: 车主身份证反面
+     *
+     * @param insuranceUploadImageVo 影像上传参数
+     * @param imageVoList            影像列表
+     * @return 上传参数列表
+     */
+    private List<CarCheckUploadFileVerifyImgParam> buildUploadParams(
+            InsuranceUploadImageVo insuranceUploadImageVo,
+            List<InsuranceImageVo> imageVoList) {
+
+        List<CarCheckUploadFileVerifyImgParam> uploadParamsList = new ArrayList<>();
+
+        // 获取保司订单号(核保成功后返回的ProposalNo)
+        String companyOrderNo = insuranceUploadImageVo.getOrder().getCompanyOrderNo();
+
+        // 遍历影像列表
+        for (InsuranceImageVo imageVo : imageVoList) {
+            String imageCode = imageVo.getImageCode();
+            List<InsuranceImageVo.ImageDTO> imageBase64List = imageVo.getImageBase64List();
+
+            // 如果影像编码或Base64列表为空,跳过当前影像
+            if (StringUtils.isEmpty(imageCode) || CollectionUtils.isEmpty(imageBase64List)) {
+                log.warn("影像上传 - 影像编码为空或Base64列表为空,跳过: imageCode={}", imageCode);
+                continue;
+            }
+
+            // 根据影像编码确定类型路径
+            String typePath = getTypePathByImageCode(imageCode);
+            if (StringUtils.isEmpty(typePath)) {
+                log.warn("影像上传 - 未匹配到影像类型路径,跳过: imageCode={}", imageCode);
+                continue;
+            }
+
+            // 遍历Base64图片列表,为每张图片构建一个上传参数
+            for (InsuranceImageVo.ImageDTO imageDTO : imageBase64List) {
+                CarCheckUploadFileVerifyImgParam param = new CarCheckUploadFileVerifyImgParam();
+
+                // 设置渠道编码(固定值)
+                param.setChannelCode("OffWeb");
+                // 设置保司订单号(核保成功后返回)
+                param.setFullProposalNo(companyOrderNo);
+                // 设置拍摄城市(暂时为空)
+                param.setShootCity("");
+                // 设置拍摄省份(暂时为空)
+                param.setShootProvince("");
+                // 设置上传类型(1表示正常上传)
+                param.setUploadType(1);
+                // 设置类型路径(根据影像类型确定)
+                param.setTypePath(typePath);
+                // 设置Base64编码的图片内容
+                param.setBase64File(imageDTO.getImageBase64Str());
+                // 生成Base64文件名(保司订单号+类型路径+序号)
+                param.setBase64FileName(companyOrderNo + typePath + "0.png");
+                // 生成文件类型标识(包含时间戳确保唯一性)
+                param.setFileType("1fileOrgName" + typePath + System.currentTimeMillis() + "0");
+
+                uploadParamsList.add(param);
+                log.debug("影像上传 - 构建上传参数: imageCode={}, typePath={}", imageCode, typePath);
+            }
+        }
+
+        return uploadParamsList;
+    }
+
+    /**
+     * 根据影像编码获取类型路径
+     * <p>
+     * 影像类型与类型路径的映射关系:
+     * - C01/C02: 行驶证(正面/反面)-> 01-15-01(投保业务-车辆证件-行驶证)
+     * - C02/D02: 身份证(正面/反面)-> 01-14-01(投保业务-证件照-证件照)
+     *
+     * @param imageCode 影像编码
+     * @return 类型路径,未匹配返回null
+     */
+    private String getTypePathByImageCode(String imageCode) {
+        if (imageCode == null) {
+            return null;
+        }
+
+        return switch (imageCode) {
+            case "C01", "D01" -> "01-15-01";  // 行驶证
+            case "C02", "D02" -> "01-14-01";  // 身份证
+            default -> null;
+        };
+    }
 
 
 //        {
@@ -454,9 +805,6 @@ public class TKQuotationBaseServiceImpl implements TKQuotationBaseService {
 //            param.setFileType("1fileOrgName01-12-0117429775996580");
 //        }
 
-
-    }
-
     @Override
     public void queryClauseData(ClauseDataVo clauseDataVo) {
 
@@ -532,6 +880,9 @@ public class TKQuotationBaseServiceImpl implements TKQuotationBaseService {
             orderStatusResultVo.setOrderStatus(InsOrderStatusEnum.UNDERWRITED);
         } else if (orderStatus.equals("X")) {
             orderStatusResultVo.setOrderStatus(InsOrderStatusEnum.ORDER_CLOSE);
+        } else if (orderStatus.equals("A3")) {
+            orderStatusResultVo.setOrderStatus(InsOrderStatusEnum.STAFF_PROCESS);
+            orderStatusResultVo.setErrorMsg(tkEntranceFor000086Result.getCarRuleMessage());
         }
         orderStatusResultVo.setJqPolicyno(tkEntranceFor000086Result.getQuotationNoCI());
         orderStatusResultVo.setSyPolicyno(tkEntranceFor000086Result.getQuotationNoBI());

+ 5 - 1
tenant/insurance/quotation-taiping/src/main/java/com/jzg/quotation/taiping/crawler/entity/request/TaiPingCrawlerPremiumCalculateRequest.java

@@ -1086,7 +1086,11 @@ public class TaiPingCrawlerPremiumCalculateRequest {
             this.carKindCodeShowName = motor.getCiModelClass();
             this.vehicleCategory = carInfoVo.getCarTypeCode();
             this.seatCount = Integer.valueOf(carInfoVo.getSeatCount());
-            this.tonCount = Double.valueOf(carInfoVo.getTonCount());
+            if (carInfoVo.getTonCount() != null) {
+                this.tonCount = Double.valueOf(carInfoVo.getTonCount());
+            } else {
+                this.tonCount = 0.00;
+            }
             this.negotiatedActualValue = actualValue;
             this.useNatureShow = carInfoVo.getCarNatureCode();
             this.attachNature = "01";

+ 104 - 69
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/impl/TaiShanCrawlerRequestImpl.java

@@ -226,7 +226,7 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
                 throw new SystemException(errMsg);
             }
         }else{
-            errMsg = exception != null ? exception.getMsg() : taiShanCrawlerQuotationSaveResponse.getMessage();
+            errMsg = exception != null ? exception.getMsg() : (taiShanCrawlerQuotationResponse.getMessage() != null ? taiShanCrawlerQuotationResponse.getMessage() : "报价接口返回异常");
             throw new SystemException(errMsg);
         }
         return TaiShanCrawlerQuoteResultsVoBuild.buildQuoteResultsVo(quoteVo,
@@ -237,61 +237,81 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
 
     private void resultCoverSave(QuoteVo quoteVo, TaiShanCrawlerQuotationRequest taiShanCrawlerQuotationRequest, TaiShanCrawlerQuotationResponse taiShanCrawlerQuotationResponse) {
 
+        if (taiShanCrawlerQuotationRequest == null || taiShanCrawlerQuotationResponse == null || taiShanCrawlerQuotationResponse.getResult() == null) {
+            log.warn("resultCoverSave: 请求或响应信息不完整,跳过字段覆盖");
+            return;
+        }
+        TaiShanCrawlerQuotationResponse.ResultDTO resultDTO = taiShanCrawlerQuotationResponse.getResult();
+
         // ========== 交强险信息处理 ==========
-        TaiShanCrawlerQuotationRequest.CompulsoryInsurance.CarShipTax carShipTax = taiShanCrawlerQuotationRequest.getCompulsoryInsurance().getCarShipTax();
-        TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO.CarShipTaxDTO carShipTaxRes = taiShanCrawlerQuotationResponse.getResult().getCompulsoryInsurance().getCarShipTax();
-        carShipTax.setTotalTax(carShipTaxRes.getTotalTax());
-        carShipTax.setUnitTaxAmt(carShipTaxRes.getUnitTaxAmt());
-        carShipTax.setAnnualTaxDue(carShipTaxRes.getAnnualTaxDue());
-        carShipTax.setSumTax(carShipTaxRes.getSumTax());
-        carShipTax.setAnnualTaxAmt(carShipTaxRes.getAnnualTaxAmt());
-        carShipTax.setTaxActual(carShipTaxRes.getTaxActual());
-        carShipTax.setTaxUnitTypeCode(carShipTaxRes.getTaxUnitTypeCode());
-        carShipTax.setTaxLocationCode(carShipTaxRes.getTaxLocationCode());
-
-        List<TaiShanCrawlerQuotationRequest.CompulsoryInsurance.ItemKind> itemKinds = taiShanCrawlerQuotationRequest.getCompulsoryInsurance().getItemKinds();
-        List<TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO.ItemKindsDTO> itemKindsRes = taiShanCrawlerQuotationResponse.getResult().getCompulsoryInsurance().getItemKinds();
-        Map<String, TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO.ItemKindsDTO> resMap = itemKindsRes.stream()
-                .collect(Collectors.toMap(
-                        TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO.ItemKindsDTO::getKindCode,
-                        Function.identity(),
-                        (o1, o2) -> o1   // 防止 key 冲突
-                ));
-
-        itemKinds.forEach(itemKind ->{
-            TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO.ItemKindsDTO res = resMap.get(itemKind.getKindCode());
-            if (res != null) {
-                itemKind.setBefPremium(res.getBefPremium());
-                itemKind.setBefAnnPrm(res.getBefAnnPrm());
-                itemKind.setBasePrm(res.getBasePrm());
+        if (taiShanCrawlerQuotationRequest.getCompulsoryInsurance() != null && resultDTO.getCompulsoryInsurance() != null) {
+            TaiShanCrawlerQuotationRequest.CompulsoryInsurance ciReq = taiShanCrawlerQuotationRequest.getCompulsoryInsurance();
+            TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO ciRes = resultDTO.getCompulsoryInsurance();
+
+            if (ciReq.getCarShipTax() != null && ciRes.getCarShipTax() != null) {
+                TaiShanCrawlerQuotationRequest.CompulsoryInsurance.CarShipTax carShipTax = ciReq.getCarShipTax();
+                TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO.CarShipTaxDTO carShipTaxRes = ciRes.getCarShipTax();
+                carShipTax.setTotalTax(carShipTaxRes.getTotalTax());
+                carShipTax.setUnitTaxAmt(carShipTaxRes.getUnitTaxAmt());
+                carShipTax.setAnnualTaxDue(carShipTaxRes.getAnnualTaxDue());
+                carShipTax.setSumTax(carShipTaxRes.getSumTax());
+                carShipTax.setAnnualTaxAmt(carShipTaxRes.getAnnualTaxAmt());
+                carShipTax.setTaxActual(carShipTaxRes.getTaxActual());
+                carShipTax.setTaxUnitTypeCode(carShipTaxRes.getTaxUnitTypeCode());
+                carShipTax.setTaxLocationCode(carShipTaxRes.getTaxLocationCode());
             }
-        });
 
-        TaiShanCrawlerQuotationRequest.CompulsoryInsurance.ProductInfo productInfo = taiShanCrawlerQuotationRequest.getCompulsoryInsurance().getProductInfo();
-        TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO.ProductInfoDTO productInfoRes = taiShanCrawlerQuotationResponse.getResult().getCompulsoryInsurance().getProductInfo();
-        productInfo.setPremium(productInfoRes.getPremium());
-        productInfo.setApId(productInfoRes.getApId());
-        productInfo.setEffective(productInfoRes.getEffective());
-        productInfo.setRiskAmount(productInfoRes.getRiskAmount());
+            if (ciReq.getItemKinds() != null && ciRes.getItemKinds() != null) {
+                List<TaiShanCrawlerQuotationRequest.CompulsoryInsurance.ItemKind> itemKinds = ciReq.getItemKinds();
+                List<TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO.ItemKindsDTO> itemKindsRes = ciRes.getItemKinds();
+                Map<String, TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO.ItemKindsDTO> resMap = itemKindsRes.stream()
+                        .filter(r -> r.getKindCode() != null)
+                        .collect(Collectors.toMap(
+                                TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO.ItemKindsDTO::getKindCode,
+                                Function.identity(),
+                                (o1, o2) -> { log.warn("交强险险种存在重复 kindCode: {},保留第一条", o1.getKindCode()); return o1; }
+                        ));
+
+                itemKinds.forEach(itemKind ->{
+                    if (itemKind.getKindCode() == null) return;
+                    TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO.ItemKindsDTO res = resMap.get(itemKind.getKindCode());
+                    if (res != null) {
+                        itemKind.setBefPremium(res.getBefPremium());
+                        itemKind.setBefAnnPrm(res.getBefAnnPrm());
+                        itemKind.setBasePrm(res.getBasePrm());
+                    }
+                });
+            }
+
+            if (ciReq.getProductInfo() != null && ciRes.getProductInfo() != null) {
+                TaiShanCrawlerQuotationRequest.CompulsoryInsurance.ProductInfo productInfo = ciReq.getProductInfo();
+                TaiShanCrawlerQuotationResponse.ResultDTO.CompulsoryInsuranceDTO.ProductInfoDTO productInfoRes = ciRes.getProductInfo();
+                productInfo.setPremium(productInfoRes.getPremium());
+                productInfo.setApId(productInfoRes.getApId());
+                productInfo.setEffective(productInfoRes.getEffective());
+                productInfo.setRiskAmount(productInfoRes.getRiskAmount());
+            }
+        }
 
         // ========== 商业险信息处理 ==========
         TaiShanCrawlerQuotationRequest.BusinessInsurance businessInsurance = taiShanCrawlerQuotationRequest.getBusinessInsurance();
-        TaiShanCrawlerQuotationResponse.ResultDTO.BusinessInsuranceDTO businessInsuranceRes = taiShanCrawlerQuotationResponse.getResult().getBusinessInsurance();
-        
+        TaiShanCrawlerQuotationResponse.ResultDTO.BusinessInsuranceDTO businessInsuranceRes = resultDTO.getBusinessInsurance();
+
         if (businessInsurance != null && businessInsuranceRes != null) {
-            // 商业险险种信息覆盖
             List<TaiShanCrawlerQuotationRequest.BusinessInsurance.ItemKind> biItemKinds = businessInsurance.getItemKinds();
             List<TaiShanCrawlerQuotationResponse.ResultDTO.BusinessInsuranceDTO.ItemKind> biItemKindsRes = businessInsuranceRes.getItemKinds();
-            
+
             if (biItemKinds != null && biItemKindsRes != null) {
                 Map<String, TaiShanCrawlerQuotationResponse.ResultDTO.BusinessInsuranceDTO.ItemKind> biResMap = biItemKindsRes.stream()
+                        .filter(r -> r.getKindCode() != null)
                         .collect(Collectors.toMap(
                                 TaiShanCrawlerQuotationResponse.ResultDTO.BusinessInsuranceDTO.ItemKind::getKindCode,
                                 Function.identity(),
-                                (o1, o2) -> o1
+                                (o1, o2) -> { log.warn("商业险险种存在重复 kindCode: {},保留第一条", o1.getKindCode()); return o1; }
                         ));
-                
+
                 biItemKinds.forEach(itemKind -> {
+                    if (itemKind.getKindCode() == null) return;
                     TaiShanCrawlerQuotationResponse.ResultDTO.BusinessInsuranceDTO.ItemKind res = biResMap.get(itemKind.getKindCode());
                     if (res != null) {
                         itemKind.setPremium(res.getPremium());
@@ -317,11 +337,11 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
                     }
                 });
             }
-            
+
             // 商业险产品信息覆盖
             TaiShanCrawlerQuotationRequest.BusinessInsurance.ProductInfo biProductInfo = businessInsurance.getProductInfo();
             TaiShanCrawlerQuotationResponse.ResultDTO.BusinessInsuranceDTO.ProductInfoDTO biProductInfoRes = businessInsuranceRes.getProductInfo();
-            
+
             if (biProductInfo != null && biProductInfoRes != null) {
                 biProductInfo.setPremium(biProductInfoRes.getPremium());
                 biProductInfo.setApId(biProductInfoRes.getApId());
@@ -331,34 +351,39 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
         }
 
         // ========== 方案信息处理 ==========
-        TaiShanCrawlerQuotationRequest.ProposalInfo proposalInfo = taiShanCrawlerQuotationRequest.getProposalInfo();
-        TaiShanCrawlerQuotationResponse.ResultDTO.ProposalInfoDTO proposalInfoRes = taiShanCrawlerQuotationResponse.getResult().getProposalInfo();
-        proposalInfo.setTotalPremium(proposalInfoRes.getTotalPremium());
+        if (taiShanCrawlerQuotationRequest.getProposalInfo() != null && resultDTO.getProposalInfo() != null) {
+            TaiShanCrawlerQuotationRequest.ProposalInfo proposalInfo = taiShanCrawlerQuotationRequest.getProposalInfo();
+            TaiShanCrawlerQuotationResponse.ResultDTO.ProposalInfoDTO proposalInfoRes = resultDTO.getProposalInfo();
+            proposalInfo.setTotalPremium(proposalInfoRes.getTotalPremium());
+        }
 
         // ========== 车辆信息处理 ==========
-        TaiShanCrawlerQuotationRequest.VehicleInfo vehicleInfo = taiShanCrawlerQuotationRequest.getVehicleInfo();
-        TaiShanCrawlerQuotationResponse.ResultDTO.VehicleInfoDTO vehicleInfoRes = taiShanCrawlerQuotationResponse.getResult().getVehicleInfo();
-        vehicleInfo.setJqQryCde(vehicleInfoRes.getJqQryCde());
-        vehicleInfo.setSyQryCde(vehicleInfoRes.getSyQryCde());
-        vehicleInfo.setJqCResvTxt20(vehicleInfoRes.getJqCResvTxt20());
-        vehicleInfo.setSyCResvTxt20(vehicleInfoRes.getSyCResvTxt20());
+        if (taiShanCrawlerQuotationRequest.getVehicleInfo() != null && resultDTO.getVehicleInfo() != null) {
+            TaiShanCrawlerQuotationRequest.VehicleInfo vehicleInfo = taiShanCrawlerQuotationRequest.getVehicleInfo();
+            TaiShanCrawlerQuotationResponse.ResultDTO.VehicleInfoDTO vehicleInfoRes = resultDTO.getVehicleInfo();
+            vehicleInfo.setJqQryCde(vehicleInfoRes.getJqQryCde());
+            vehicleInfo.setSyQryCde(vehicleInfoRes.getSyQryCde());
+            vehicleInfo.setJqCResvTxt20(vehicleInfoRes.getJqCResvTxt20());
+            vehicleInfo.setSyCResvTxt20(vehicleInfoRes.getSyCResvTxt20());
+        }
 
         // ========== 系数信息处理 ==========
         RiskInfoVo ciRiskInfoVo = quoteVo.getCiRiskInfoVo();
         RiskInfoVo biRiskInfoVo = quoteVo.getBiRiskInfoVo();
-        TaiShanCrawlerQuotationRequest.CoefficientInfo coefficientInfo = taiShanCrawlerQuotationRequest.getCoefficientInfo();
-        TaiShanCrawlerQuotationResponse.ResultDTO.CoefficientInfoDTO coefficientInfoRes = taiShanCrawlerQuotationResponse.getResult().getCoefficientInfo();
-        
-        if(Objects.nonNull(ciRiskInfoVo) && coefficientInfoRes != null){
-            coefficientInfo.setJqResvNum3(coefficientInfoRes.getJqResvNum3());
-            coefficientInfo.setJqResvNum4(coefficientInfoRes.getJqResvNum4());
-        }
-        if(Objects.nonNull(biRiskInfoVo) && coefficientInfoRes != null){
-//            coefficientInfo.setSyResvNum3(coefficientInfoRes.getSyResvNum3());
-//            coefficientInfo.setSyResvNum4(coefficientInfoRes.getSyResvNum4());
+        if (taiShanCrawlerQuotationRequest.getCoefficientInfo() != null && resultDTO.getCoefficientInfo() != null) {
+            TaiShanCrawlerQuotationRequest.CoefficientInfo coefficientInfo = taiShanCrawlerQuotationRequest.getCoefficientInfo();
+            TaiShanCrawlerQuotationResponse.ResultDTO.CoefficientInfoDTO coefficientInfoRes = resultDTO.getCoefficientInfo();
+
+            if (Objects.nonNull(ciRiskInfoVo)) {
+                coefficientInfo.setJqResvNum3(coefficientInfoRes.getJqResvNum3());
+                coefficientInfo.setJqResvNum4(coefficientInfoRes.getJqResvNum4());
+            }
+            if (Objects.nonNull(biRiskInfoVo)) {
+//                coefficientInfo.setSyResvNum3(coefficientInfoRes.getSyResvNum3());
+//                coefficientInfo.setSyResvNum4(coefficientInfoRes.getSyResvNum4());
+            }
         }
     }
-
     /**
      * 核保
      *
@@ -375,7 +400,9 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
 
         // 获取订单信息
         TaiShanCrawlerOrder taiShanCrawlerOrder = taiShanCrawlerOrderService.getByOrdersNo(underwritingVo.getOrder().getOrdersNo());
-
+        if (taiShanCrawlerOrder == null) {
+            throw new SystemException("未找到订单信息: " + underwritingVo.getOrder().getOrdersNo());
+        }
         // 核保
         TaiShanCrawlerUnderwritingRequest taiShanCrawlerUnderwritingRequest = new TaiShanCrawlerUnderwritingRequest(taiShanCrawlerOrder.getOrderNo());
         TaiShanCrawlerUnderwritingResponse taiShanCrawlerUnderwritingResponse = taiShanCrawlerRequestComponent.underwriting(taiShanCrawlerUnderwritingRequest, headers);
@@ -435,6 +462,9 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
             TaiShanCrawlerConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(TaiShanCrawlerConfigureParameters.class, attributionInformationVo.getConfigInfo());
             HttpHeaders headers = taiShanCrawlerQuoteProcessService.getHeaders(attributionInformationVo.getUsername(), parameters.getComCode());
             TaiShanCrawlerOrder taiShanCrawlerOrder = taiShanCrawlerOrderService.getByOrdersNo(insuranceUploadImageVo.getOrder().getOrdersNo());
+            if (taiShanCrawlerOrder == null) {
+                throw new SystemException("未找到订单信息: " + insuranceUploadImageVo.getOrder().getOrdersNo());
+            }
             // 上传影像文件请求参数
             TaiShanCrawlerImageUploadRequest taiShanCrawlerImageUploadRequest = new TaiShanCrawlerImageUploadRequest();
             taiShanCrawlerImageUploadRequest.setBiProposalNo(taiShanCrawlerOrder.getSyApplyNo());
@@ -513,10 +543,15 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
         TaiShanCrawlerConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(TaiShanCrawlerConfigureParameters.class, attributionInformationVo.getConfigInfo());
         HttpHeaders headers = taiShanCrawlerQuoteProcessService.getHeaders(attributionInformationVo.getUsername(), parameters.getComCode());
         log.info("headers:{}", JSON.toJSONString(headers));
-        TaiShanCrawlerOrder ziJinCrawlerOrder = taiShanCrawlerOrderService.getByOrdersNo(paymentLinkVo.getOrder().getOrdersNo());
-
+        TaiShanCrawlerOrder taiShanCrawlerOrder = taiShanCrawlerOrderService.getByOrdersNo(paymentLinkVo.getOrder().getOrdersNo());
+        if (taiShanCrawlerOrder == null) {
+            PaymentLinkResultsVo emptyResult = new PaymentLinkResultsVo();
+            emptyResult.setPayLinkStatus(false);
+            emptyResult.setErrorMsg("未找到订单信息: " + paymentLinkVo.getOrder().getOrdersNo());
+            return emptyResult;
+        }
         // 获取支付信息
-        TaiShanCrawlerPaymentInfoRequest paymentInfoRequest = new TaiShanCrawlerPaymentInfoRequest(ziJinCrawlerOrder.getOrderNo());
+        TaiShanCrawlerPaymentInfoRequest paymentInfoRequest = new TaiShanCrawlerPaymentInfoRequest(taiShanCrawlerOrder.getOrderNo());
         TaiShanCrawlerPaymentInfoResponse infoResponse = taiShanCrawlerRequestComponent.getPayInfo(paymentInfoRequest, headers);
 
         List<TaiShanCrawlerPaymentInfoResponse.ResultDTO.RiskDTO> risk = infoResponse.getResult().getRisk();
@@ -560,7 +595,7 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
                 log.info("未生成交易单号,先获取 batchNo");
                 // 未生成交易单号,先获取 batchNo
                 TaiShanCrawlerPaymentCardRequest cardRequest = new TaiShanCrawlerPaymentCardRequest(
-                        ziJinCrawlerOrder.getOrderNo(), jqAppNo, jquniqueNo, syAppNo, syUniqueNo);
+                        taiShanCrawlerOrder.getOrderNo(), jqAppNo, jquniqueNo, syAppNo, syUniqueNo);
 
                 TaiShanCrawlerPaymentCardResponse cardResponse = taiShanCrawlerRequestComponent.getPaymentCard(cardRequest, headers);
                 String batchNo = cardResponse.getResult().getBatchNo();
@@ -579,7 +614,7 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
                 log.info("未生成交易单号");
                 // 未生成交易单号
                 TaiShanCrawlerPaymentCardRequest cardRequest = new TaiShanCrawlerPaymentCardRequest(
-                        ziJinCrawlerOrder.getOrderNo(), jqAppNo, jquniqueNo, "", "");
+                        taiShanCrawlerOrder.getOrderNo(), jqAppNo, jquniqueNo, "", "");
 
                 TaiShanCrawlerPaymentCardResponse cardResponse = taiShanCrawlerRequestComponent.getPaymentCard(cardRequest, headers);
                 jqBatchNo = cardResponse.getResult().getBatchNo();
@@ -596,7 +631,7 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
                 log.info("未生成交易单号");
                 // 未生成交易单号
                 TaiShanCrawlerPaymentCardRequest cardRequest = new TaiShanCrawlerPaymentCardRequest(
-                        ziJinCrawlerOrder.getOrderNo(), "", "", syAppNo, syUniqueNo);
+                        taiShanCrawlerOrder.getOrderNo(), "", "", syAppNo, syUniqueNo);
 
                 TaiShanCrawlerPaymentCardResponse cardResponse = taiShanCrawlerRequestComponent.getPaymentCard(cardRequest, headers);
                 syBatchNo = cardResponse.getResult().getBatchNo();

+ 5 - 1
tenant/insurance/quotation-yongcheng/src/main/java/com/jzg/quotation/yongcheng/api/entity/request/AuditRequest.java

@@ -384,6 +384,10 @@ public class AuditRequest {
                 condition.setSyFlag("1");
             }
         });
+        //设置驾意险标志
+        if(underwritingVo.getInsOrdersAccidentalDriving() != null){
+            condition.setYwFlag("1");
+        }
         condition.setCProdNoSY(condition.getSyFlag().equals("1") ? "0364" : "");
         condition.setCProdNoJQ(condition.getJqFlag().equals("1") ? "0326" : "");
         condition.setQuerySequenceNoSy(underwritingVo.getPolicy().getSyApplyNo());
@@ -399,6 +403,7 @@ public class AuditRequest {
         condition.setCPintubeLicenceNo("110");
         condition.setCPintubeTel("110");
         condition.setMaintenanceStaffCode("110");
+        condition.setYwFlag("1");
         //<condition>
 
         Condition.Customer customer = new Condition.Customer();
@@ -463,7 +468,6 @@ public class AuditRequest {
         r.setAuthorityData(configurationProperties.gainAuthorityDataXml());
         r.setCondition(condition);
 
-
         auditRequest.setRequestLabel(r);
 
 

+ 12 - 0
tenant/insurance/quotation-yongcheng/src/main/java/com/jzg/quotation/yongcheng/api/service/impl/YongChengApiRequestImpl.java

@@ -409,6 +409,17 @@ public class YongChengApiRequestImpl implements YongChengApiRequest {
             String cleanStr = ycRequestApiComponents.payCallback(callbackRequest,url);
             CallBackResponse response = CallBackResponse.buildCallBackParam(cleanStr);
             if (response.getResult().equals("0")) {
+                //判断人工处理和核保退回
+                if(orderStatusVo.getInsOrders().getOrderStatus().equals(InsOrderStatusEnum.STAFF_PROCESS.getCode().toString())){
+                    if(response.getJqstatus().equals("9")){
+                        orderStatusResultVo.setOrderStatus(InsOrderStatusEnum.PAY_PENDING);
+                    }else if(response.getJqstatus().equals("0")){
+                        orderStatusResultVo.setOrderStatus(InsOrderStatusEnum.STAFF_PROCESS);
+                    }else if(response.getJqstatus().equals(3)){
+                        orderStatusResultVo.setOrderStatus(InsOrderStatusEnum.AUDIT_FAIL);
+                        orderStatusResultVo.setErrorMsg(response.getJqmessage());
+                    }
+                }
                 if(orderStatusVo.getInsOrders().getOrderStatus().equals(InsOrderStatusEnum.PAY_PENDING.getCode().toString())){
                     orderStatusResultVo = buildCallBackStatus(orderStatusVo, response.getJqstatus());
                     // 获取商业保单号
@@ -425,6 +436,7 @@ public class YongChengApiRequestImpl implements YongChengApiRequest {
                         orderStatusResultVo.setJyApplyNo(response.getYwPolicyAppNo());
                     }
                 }
+
             } else {
                 //失败原因
                 orderStatusResultVo.setOrderStatus(InsOrderStatusEnum.AUDIT_FAIL);

+ 22 - 5
tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/entity/request/ZhongAnCrawlerQuoteRequest.java

@@ -15,7 +15,9 @@ import org.springframework.format.annotation.DateTimeFormat;
 
 import java.io.Serial;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @description: 众安保险 报价 请求参数
@@ -107,21 +109,36 @@ public class ZhongAnCrawlerQuoteRequest{
         }
         this.coverageInfo = JSONObject.toJSONString(coverageInfoDTOS);
         List<NonAutoInfoDto> nonAutoInfoDtos = new ArrayList<>();
+        Map<String, String> codeConvertMap = new HashMap<>();
+        codeConvertMap.put("-1", "1");
+        codeConvertMap.put("-2", "2");
+        codeConvertMap.put("-3", "3");
+        codeConvertMap.put("-4", "4");
+        codeConvertMap.put("-5", "5");
+        codeConvertMap.put("-6", "6");
         // 驾意险
         if (quoteVo.getAccidentalDrivings() != null && quoteVo.getAccidentalDrivings().size() > 0) {
-
             quoteVo.getAccidentalDrivings().forEach(accidentalDriving -> {
+                String code = accidentalDriving.getProductCode();
+                if (codeConvertMap.containsKey(code)) {
+                    accidentalDriving.setProductCode(codeConvertMap.get(code));
+                }
                 NonAutoInfoDto nonAutoInfoDto = new NonAutoInfoDto(accidentalDriving.getParentProductCode(), "1", accidentalDriving.getProductCode());
                 nonAutoInfoDtos.add(nonAutoInfoDto);
             });
-            this.nonAutoInfo = JSONObject.toJSONString(nonAutoInfoDtos);
+            boolean hasKpNhjcb = nonAutoInfoDtos.stream()
+                    .anyMatch(dto -> "kp_nhjcb_v1".equals(dto.getProductCode()));
+            if (!hasKpNhjcb) {
+                NonAutoInfoDto jtywxV24 = new NonAutoInfoDto("kp_nhjcb_v1", "0", null);
+                nonAutoInfoDtos.add(jtywxV24);
+            }
         } else {
-            NonAutoInfoDto jtywxV24 = new NonAutoInfoDto("kp_jtywx_v24", "0", null);
-            NonAutoInfoDto wjsGabV6 = new NonAutoInfoDto("wjs_gab_v6", "0", null);
+            NonAutoInfoDto jtywxV24 = new NonAutoInfoDto("kp_nhjcb_v1", "0", null);
+            NonAutoInfoDto wjsGabV6 = new NonAutoInfoDto("wjs_gab_v10", "0", null);
             nonAutoInfoDtos.add(jtywxV24);
             nonAutoInfoDtos.add(wjsGabV6);
-            this.nonAutoInfo = JSONObject.toJSONString(nonAutoInfoDtos);
         }
+        this.nonAutoInfo = JSONObject.toJSONString(nonAutoInfoDtos);
     }
 
     /**

+ 9 - 0
tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/entity/Request/ZmCrawlerQuotedPriceRequest.java

@@ -27,6 +27,7 @@ import java.io.Serial;
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 
 /**
@@ -1166,6 +1167,14 @@ public class ZmCrawlerQuotedPriceRequest extends BaseRequest {
                     this.totalAdjustRate = "";
                     this.totalPremium = "";
                     this.validDate = riskInfoVo.getStartDate();
+                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                    if (!riskInfoVo.isInstantFlag() && riskInfoVo.getEndDate().endsWith("00:00:00")) {
+                        String endDate = riskInfoVo.getEndDate();
+                        LocalDateTime dateTime = LocalDateTime.parse(endDate, formatter);
+                        LocalDateTime minusOneSec = dateTime.minusSeconds(1);
+                        String newEndDate = minusOneSec.format(formatter);
+                        riskInfoVo.setEndDate(newEndDate);
+                    }
                     this.expiryDate = riskInfoVo.getEndDate();
                     this.argueSolution = "1";
                     if (riskInfoVo.isInstantFlag()) {

+ 1 - 1
tenant/insurance/quotation-zhongmei/src/main/java/com/jzg/quotation/zhongmei/crawler/service/Impl/ZhongMeiCrawlerRequestImpl.java

@@ -147,7 +147,7 @@ public class ZhongMeiCrawlerRequestImpl implements ZhongMeiCrawlerRequest {
                 contract.getContractMain().setValidDate(startTime);
                 contract.getContractMain().setExpiryDate(endTime);
                 // 判断是否是即时起保
-                if (!startTime.endsWith("00:00:00")) {
+                if (!endTime.endsWith("23:59:59")) {
                     contract.getContractMain().setReinsuranceFlag("1");
                 }
                 contract.getCoverage().forEach(coverageDTO -> {

+ 9 - 3
tenant/organization/src/main/java/com/jzg/organization/controller/ReceivableController.java

@@ -641,6 +641,12 @@ public class ReceivableController {
         receivableService.exportPlatformSettlementExcel(page,settlementQueryVo);
     }
 
+    /**
+     * 应收手续费结算明细(车险/非车)
+     *
+     * @author lipf
+     * @date 2026/7/15 14:10
+     */
     @PostMapping("superviseSettlementDetailExcel")
     @Operation(summary = "应收手续费结算明细")
     public HttpResult superviseSettlementDetailExcel(@RequestBody SettlementQueryVo settlementQueryVo) {
@@ -759,13 +765,13 @@ public class ReceivableController {
     /**
      * 设置指定发票为结算完成状态
      *
-     * @param invoiceId 发票序号
+     * @param updateSettlementStatusVo 发票序号
      * @author lipf
      * @date 2026/6/11 9:33
      */
     @PostMapping("updateSettlementStatus")
-    public HttpResult<String> updateSettlementStatus(@RequestParam("id") String invoiceId){
-        int count = receivableService.updateSettlementStatus(invoiceId);
+    public HttpResult<String> updateSettlementStatus(@RequestBody UpdateSettlementStatusVo updateSettlementStatusVo){
+        int count = receivableService.updateSettlementStatus(updateSettlementStatusVo);
         if(count>0){
             return HttpResult.ok("订单被标记为结算完成");
         }else{

+ 2 - 0
tenant/organization/src/main/java/com/jzg/organization/controller/UserAccountController.java

@@ -1,6 +1,7 @@
 package com.jzg.organization.controller;
 
 
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jzg.commons.core.base.BaseController;
 import com.jzg.commons.core.page.HttpResult;
@@ -114,6 +115,7 @@ public class UserAccountController {
     @PostMapping("/addUserAccountChangeLog")
     public HttpResult<String> addUserAccountChangeLog(@RequestBody SysUserAccountChangeLog changeLog){
         try{
+            log.info("添加用户钱包账户记录。 changeLog=[{}]", JSONUtil.toJsonStr(changeLog));
            boolean save = sysUserAccountIncomeLogService.save(changeLog);
             if(save){
                 return HttpResult.ok("保存业务员账号明细成功");

+ 2 - 2
tenant/organization/src/main/java/com/jzg/organization/mapper/SysUserAccountIncomeLogMapper.java

@@ -33,9 +33,9 @@ public interface SysUserAccountIncomeLogMapper extends BaseMapper<SysUserAccount
         left join ins_orders io
             on a.related_order_id = io.id
         left join sys_amount_auditing saa
-        on saa.user_id = a.user_id
+            on saa.id = a.related_amount_auditing_id
         where
-            a.user_id = #{ywyUserId} and a.create_time >= #{beginDate} and a.create_time < #{endDate} and a.is_delete = 0 order by a.create_time desc
+            a.user_id = #{ywyUserId} and a.create_time >= #{beginDate} and a.create_time < #{endDate} and a.is_delete = 0 and a.status = 10 order by a.create_time desc
         """)
     List<SysUserAccountChangeLog> queryYwyIORecs(String ywyUserId, LocalDate beginDate, LocalDate endDate);
 }

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

@@ -492,11 +492,11 @@ public interface ReceivableService extends IService<InsPlyIncome> {
     /**
      * 设置指定发票为结算完成状态
      *
-     * @param invoiceId 发票序号
+     * @param updateSettlementStatusVo 发票序号
      * @author lipf
      * @date 2026/6/11 9:33
      */
-    int updateSettlementStatus(String invoiceId);
+    int updateSettlementStatus(UpdateSettlementStatusVo updateSettlementStatusVo);
 
     /**
      * 平台协议结算

+ 99 - 31
tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java

@@ -768,10 +768,32 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             resultList.addAll(followAggVoList);
         }
 
-        // 3. 查询额外其他费用收入数据,补充到结果集
-        List<InsPlyIncomeDto> incomeDtoList = queryFollowIncomeData(settlementReportQueryVo);
-        if (CollUtil.isEmpty(incomeDtoList)) {
-            return resultList;
+        // 应收项为空时才去补充数据,不为空时不补充数据,补充数据是因为联查了invoice和settlement表,所以没开票和结算的数据会被过滤掉,才需要补充数据
+        List<InsPlyIncomeDto> incomeDtoList = CollUtil.newArrayList();
+        if (StrUtil.isBlank(settlementReportQueryVo.getInvoiceType())){
+            // 3. 查询额外其他费用收入数据,补充到结果集
+            incomeDtoList = queryFollowIncomeData(settlementReportQueryVo);
+            if (CollUtil.isEmpty(incomeDtoList)) {
+                return resultList;
+            }else{
+                // 如果JyPremium不为0,则设置发票类型为4
+                incomeDtoList.stream().forEach(item -> {
+                    if (StrUtil.isNotBlank(item.getJyPremium()) && !NumberUtil.equals(BigDecimal.ZERO, new BigDecimal(item.getJyPremium()))){
+                        item.setInvoiceType(InvoiceTypeEnum.FEE_4.getCode());
+                    }else{
+                        item.setInvoiceType(InvoiceTypeEnum.FEE_2.getCode());
+                    }
+                });
+                List<InsPlyIncomeDto> copyList = CollUtil.newArrayList();
+                // 如果有发票类型为4的,则复制一条4的数据,完全一致,但发票类型为2
+                incomeDtoList.stream().filter(item -> InvoiceTypeEnum.FEE_4.getCode().equals(item.getInvoiceType())).forEach(item -> {
+                    InsPlyIncomeDto incomeDto = new InsPlyIncomeDto();
+                    BeanUtils.copyProperties(item, incomeDto);
+                    incomeDto.setInvoiceType(InvoiceTypeEnum.FEE_2.getCode());
+                    copyList.add(incomeDto);
+                });
+                incomeDtoList.addAll(copyList);
+            }
         }
 
         // 4. 根据筛选条件过滤收入数据(发票、结算时间/状态过滤)
@@ -827,12 +849,14 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             String partnerCompanyId = splitArr[0];
             String year = splitArr[1];
             String month = splitArr[2];
+            String invoiceType = splitArr[3];
             List<FollowCompanyFeeVO> voList = entry.getValue();
 
             FollowCompanyFeeVO vo = new FollowCompanyFeeVO();
             vo.setPartnerCompanyId(partnerCompanyId);
             vo.setYear(year);
             vo.setMonth(month);
+            vo.setInvoiceType(invoiceType);
             vo.setCompanyName(getCompanyName(partnerCompanyId, companyMap));
 
             // 汇总当前分组所有followId、settlementId
@@ -904,10 +928,10 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
     }
 
     /**
-     * 构建分组Key:partnerCompanyId_year_month
+     * 构建分组Key:partnerCompanyId_year_month_invoiceType
      */
     private String buildGroupKey(FollowCompanyFeeVO vo) {
-        return StrUtil.format("{}_{}_{}", vo.getPartnerCompanyId(), vo.getYear(), vo.getMonth());
+        return StrUtil.format("{}_{}_{}_{}", vo.getPartnerCompanyId(), vo.getYear(), vo.getMonth(), vo.getInvoiceType());
     }
 
     /**
@@ -934,7 +958,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
      * 根据发票状态、开票时间、结算时间过滤收入数据
      * 优化:嵌套anyMatch改为HashMapID映射匹配,O(n²) -> O(n)
      */
-    private List<InsPlyIncomeDto> filterIncomeByInvoiceAndSettleCondition(List<InsPlyIncomeDto> incomeList, SettlementReportQueryVo queryVo) {
+    private List<InsPlyIncomeDto>  filterIncomeByInvoiceAndSettleCondition(List<InsPlyIncomeDto> incomeList, SettlementReportQueryVo queryVo) {
         String status = queryVo.getStatus();
         String invoiceStartTime = queryVo.getInvoiceStartTime();
         String invoiceEndTime = queryVo.getInvoiceEndTime();
@@ -1030,8 +1054,8 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
 
         // 收入分组
         Map<String, List<InsPlyIncomeDto>> incomeGroupMap = incomeList.stream()
-                .collect(Collectors.groupingBy(dto -> StrUtil.format("{}_{}_{}",
-                        dto.getPartnerCompanyId(), dto.getSignYear(), dto.getSignMonth())));
+                .collect(Collectors.groupingBy(dto -> StrUtil.format("{}_{}_{}_{}",
+                        dto.getPartnerCompanyId(), dto.getSignYear(), dto.getSignMonth(), dto.getInvoiceType())));
 
         for (Map.Entry<String, List<InsPlyIncomeDto>> entry : incomeGroupMap.entrySet()) {
             String groupKey = entry.getKey();
@@ -1040,15 +1064,27 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             String partnerCompanyId = firstDto.getPartnerCompanyId();
             String signYear = firstDto.getSignYear();
             String signMonth = firstDto.getSignMonth();
-
-            // 安全字符串转BigDecimal,兜底0
-            BigDecimal totalOtherReceivable = dtoList.stream()
-                    .map(dto -> {
-                        BigDecimal jq = safeBigDecimal(dto.getJqOtherCostsPremiums());
-                        BigDecimal sy = safeBigDecimal(dto.getSyOtherCostsPremiums());
-                        return jq.add(sy);
-                    })
-                    .reduce(BigDecimal.ZERO, BigDecimal::add);
+            String invoiceType = firstDto.getInvoiceType();
+
+            BigDecimal totalOtherReceivable = BigDecimal.ZERO;
+            if (InvoiceTypeEnum.FEE_2.getCode().equals(invoiceType)){
+                // 安全字符串转BigDecimal,兜底0
+                totalOtherReceivable = dtoList.stream()
+                        .map(dto -> {
+                            BigDecimal jq = safeBigDecimal(dto.getJqOtherCostsPremiums());
+                            BigDecimal sy = safeBigDecimal(dto.getSyOtherCostsPremiums());
+                            return jq.add(sy);
+                        })
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+            }else{
+                // 安全字符串转BigDecimal,兜底0
+                totalOtherReceivable = dtoList.stream()
+                        .map(dto -> {
+                            BigDecimal jy = safeBigDecimal(dto.getJyOtherCostsPremiums());
+                            return jy;
+                        })
+                        .reduce(BigDecimal.ZERO, BigDecimal::add);
+            }
 
             // 已存在直接跳过,不存在新建VO
             if (!existVoMap.containsKey(groupKey)) {
@@ -1057,6 +1093,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
                 newVo.setYear(signYear);
                 newVo.setMonth(signMonth);
                 newVo.setTotalReceivable(totalOtherReceivable);
+                newVo.setInvoiceType(invoiceType);
                 newVo.setTotalInvoiced(BigDecimal.ZERO);
                 newVo.setTotalUnInvoiced(BigDecimal.ZERO);
                 newVo.setTotalSettlementAmount(BigDecimal.ZERO);
@@ -3437,7 +3474,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
      * @return PtlAgreementCostRatioVo 返回计算后的协议成本比例配置对象,包含各险种的入口比例、手续费比例、跟单费比例等
      */
     private PtlAgreementCostRatioVo calRatio(InsPlyIncome insPlyIncome, BatchModifyVo batchModifyVo) {
-        log.info("batchModifyVo.转换百分比之前的数据=【{}】", JSONUtil.toJsonStr(batchModifyVo));
+        log.info("batchModifyVo.转换百分比之前的数据=[{}]", JSONUtil.toJsonStr(batchModifyVo));
         PtlAgreementCostRatioVo vo = new PtlAgreementCostRatioVo();
         vo.setOrderNo(insPlyIncome.getOrderNo());
 
@@ -3445,7 +3482,8 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
 //        vo.setJqAdditionalRatio(insPlyIncome.getJqAdditionalRatio());
 //        vo.setSyAdditionalRatio(insPlyIncome.getSyAdditionalRatio());
 //        vo.setJyAdditionalRatio(insPlyIncome.getJyAdditionalRatio());
-
+        vo.setJyCommissionRatio(batchModifyVo.getJySuperviseCostsProportion());
+        vo.setJyFollowRatio(batchModifyVo.getJyOtherCostsProportion());
         this.calCommissionAndFollowAndInlet(vo, batchModifyVo, insPlyIncome);
 
         // 出口比例
@@ -4529,8 +4567,15 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
                         .map(InsPlyIncomeInvoiceSettlement::getSettlementPaymentDifference)
                         .filter(Objects::nonNull)
                         .reduce(BigDecimal.ZERO, BigDecimal::add);
+
                 BigDecimal receivableSupervisePremium = action.getReceivableSupervisePremium()  != null ? action.getReceivableSupervisePremium(): BigDecimal.ZERO;
+
 //                BigDecimal overinflatedAmount = action.getOverinflatedAmount() != null? action.getOverinflatedAmount(): BigDecimal.ZERO;
+                // 回款差计算逻辑调整 2026年7月14日09:29:08
+//                BigDecimal settlementPaymentDifference = BigDecimal.ZERO;
+//                if (CollUtil.isNotEmpty(insPlyIncomeInvoiceSettlements) && settlementAmount.compareTo(BigDecimal.ZERO) > 0){
+//                    settlementPaymentDifference = BigDecimalUtil.subtract(settlementAmount,receivableSupervisePremium);
+//                }
                 // 待结算金额 = 开票金额 - 已收金额
                 BigDecimal remainSettlementAmount = receivableSupervisePremium.subtract(BigDecimalUtil.add(settlementAmount, settlementPaymentDifference));
                 // 设置已结算的金额
@@ -4540,9 +4585,10 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
                     // 特殊梳理,当待结算金额计算出来为负数时, 设置为0
                     remainSettlementAmount = BigDecimal.ZERO;
                 }
-                action.setRemainSettlementAmount( remainSettlementAmount);
+                action.setRemainSettlementAmount(remainSettlementAmount);
                 action.setCompanyAllName(allCompanyHierarchyPaths.get(Objects.toString(action.getCompanyId(),"")));
                 action.setSettlementStatus(settlementStatusName);
+
                 // 回款差额
                 action.setSettlementPaymentDifference(settlementPaymentDifference);
 
@@ -4783,6 +4829,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
                 case "6" -> dto.setInvoiceType("平台协议非车险应收");
             }
             dto.setInvoiceTypeName(Constant.invoiceRiskTypeMap.get(Objects.toString(dto.getInvoiceType())));
+            dto.setInvoiceRiskTypeName(Constant.invoiceRiskTypeMap.get(Objects.toString(dto.getInvoiceRiskType())));
             LambdaQueryWrapper<InsPlyIncomeInvoiceSettlementFile> wrapper = new LambdaQueryWrapper<InsPlyIncomeInvoiceSettlementFile>();
             List<InsPlyIncomeInvoiceSettlementFile> insPlyIncomeInvoiceSettlementFiles = insPlyIncomeInvoiceSettlementFileMapper.selectList(wrapper.eq(InsPlyIncomeInvoiceSettlementFile::getSettlementId, dto.getSettlementId()));
             if(CollUtil.isNotEmpty(insPlyIncomeInvoiceSettlementFiles)){
@@ -5322,7 +5369,15 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         // 1. 先将有数据的保险公司进行汇总
         // 累计应收金额, 应收手续费(手续费)
         List<CompanySuperviseSettlementReportDto> allCompaniesIncomeDatas = baseMapper.queryCumulativeAccountsReceivable(systemCode, queryVo);
-        
+        // 结算状态在上面的sql进行过筛选了,后面就不再筛选了
+        queryVo.setStatus(null);
+//        if("20".equals(queryVo.getAccountsReceivable())){
+//            allCompaniesIncomeDatas = allCompaniesIncomeDatas.stream().peek(action->{
+//                // 统计非车的手续费
+//                action.setSuperviseFee(action.getSuperviseFee4Other());
+//            }).toList();
+//        }
+
         // 车险
         if("10".equals(queryVo.getAccountsReceivable())){
             // 默认情况下,superviseFee 得到的就是车险的手续费
@@ -5333,10 +5388,9 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
               action.setSuperviseFee(action.getSuperviseFee4Other());
             }).toList();
         }else if(StrUtil.isEmpty(queryVo.getAccountsReceivable())){
-                // 统计总的手续费
+                // 统计总的手续费(车险+非车险)
             allCompaniesIncomeDatas = allCompaniesIncomeDatas.stream().peek(action->{
-                // 统计非车的手续费
-                action.setSuperviseFee(action.getTotalReceivable());
+                action.setSuperviseFee(BigDecimalUtil.add(action.getSuperviseFee(), action.getSuperviseFee4Other()));
             }).toList();
         }
 
@@ -6067,11 +6121,14 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
      * 3. 记录更新人和更新时间
      * </p>
      *
-     * @param invoiceId 发票序号,用于定位需要更新的发票记录
+     * @param updateSettlementStatusVo 发票序号,用于定位需要更新的发票记录
      * @return int 返回受影响的记录数,通常为1表示更新成功,0表示更新失败或记录不存在
      */
     @Override
-    public int updateSettlementStatus(String invoiceId) {
+    public int updateSettlementStatus(UpdateSettlementStatusVo updateSettlementStatusVo) {
+        String invoiceId = updateSettlementStatusVo.getInvoiceId();
+        String settlementPaymentReason = updateSettlementStatusVo.getSettlementPaymentReason();
+
         String userName = baseController.getUserName();
         String systemCode = baseController.getSystemCode();
         log.info("租户[{}]下的用户[{}]标识发票[{}]为结算完成", systemCode, userName, invoiceId);
@@ -6083,10 +6140,21 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         BigDecimal settlementAmount =  insPlyIncomeInvoiceSettlements.stream().map(action-> BigDecimalUtil.add(action.getSettlementPaymentDifference(), action.getActualReceivedAmount()))
                 .reduce(BigDecimal.ZERO,BigDecimal::add);
         BigDecimal subtract = BigDecimalUtil.subtract(insPlyIncomeInvoice.getReceivableSupervisePremium(), settlementAmount);
-        if(subtract.compareTo(BigDecimal.ZERO) != 0){
-            InsPlyIncomeInvoiceSettlement insPlyIncomeInvoiceSettlement = insPlyIncomeInvoiceSettlements.get(0);
-            insPlyIncomeInvoiceSettlement.setSettlementPaymentDifference(BigDecimalUtil.add(subtract,insPlyIncomeInvoiceSettlement.getSettlementPaymentDifference()));
-            insPlyIncomeInvoiceSettlementMapper.updateById(insPlyIncomeInvoiceSettlement);
+        if (CollUtil.isNotEmpty(insPlyIncomeInvoiceSettlements)){
+            if(subtract.compareTo(BigDecimal.ZERO) != 0){
+                InsPlyIncomeInvoiceSettlement insPlyIncomeInvoiceSettlement = insPlyIncomeInvoiceSettlements.get(0);
+                insPlyIncomeInvoiceSettlement.setSettlementPaymentDifference(BigDecimalUtil.add(subtract,insPlyIncomeInvoiceSettlement.getSettlementPaymentDifference()));
+                insPlyIncomeInvoiceSettlement.setSettlementPaymentReason(settlementPaymentReason);
+                insPlyIncomeInvoiceSettlementMapper.updateById(insPlyIncomeInvoiceSettlement);
+            }
+        }else{
+            InsPlyIncomeInvoiceSettlement insPlyIncomeInvoiceSettlement = new InsPlyIncomeInvoiceSettlement();
+            insPlyIncomeInvoiceSettlement.setInvoiceId(invoiceId);
+            insPlyIncomeInvoiceSettlement.setReceivePaymentDate(new DateTime());
+            insPlyIncomeInvoiceSettlement.setActualReceivedAmount(BigDecimal.ZERO);
+            insPlyIncomeInvoiceSettlement.setSettlementPaymentDifference(BigDecimal.ZERO.subtract(insPlyIncomeInvoice.getReceivableSupervisePremium()));
+            insPlyIncomeInvoiceSettlement.setSettlementPaymentReason(settlementPaymentReason);
+            insPlyIncomeInvoiceSettlementMapper.insert(insPlyIncomeInvoiceSettlement);
         }
         return insPlyIncomeInvoiceMapper.update(null, new LambdaUpdateWrapper<InsPlyIncomeInvoice>()
                 .set(InsPlyIncomeInvoice::getStatus,"1")

+ 21 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/SysAmountAuditingServiceImpl.java

@@ -298,6 +298,7 @@ public class SysAmountAuditingServiceImpl extends ServiceImpl<SysAmountAuditingM
         changeLog.setRemark("提现");
         SysAmountAuditing sysAmountAuditing = baseMapper.selectById(param.getId());
         if(sysAmountAuditing != null){
+            changeLog.setRelatedAmountAuditingId(sysAmountAuditing.getId());
             String bankCardNum = sysAmountAuditing.getBankCardNum();
             List<SysUserJzgInfoBankCard> sysUserJzgInfoBankCards =  sysUserJzgInfoBankCardService.queryBankCardBybankCardNum(bankCardNum,systemCode);
             if(CollUtil.isNotEmpty(sysUserJzgInfoBankCards)){
@@ -348,6 +349,25 @@ public class SysAmountAuditingServiceImpl extends ServiceImpl<SysAmountAuditingM
         audit.setRejectPerson(userName);
         audit.setRejectTime(LocalDateTime.now());
         this.updateById(audit);
+        this.saveChangeLog(audit,param);
+    }
+
+    /**
+     * 提现申请不通过的时候,向changeLog表中插入一条状态为90的数据
+     *
+     * @author lipf
+     * @date 2026/7/15 16:48
+     */
+    private void saveChangeLog(SysAmountAuditing audit, AmountAuditRejectParam param) {
+        log.info("提现申请不通过的时候,向changeLog表中插入一条状态为90的数据。audit=[{}],param=[{}]", JSONUtil.toJsonStr(audit), JSONUtil.toJsonStr(param));
+        SysUserAccountChangeLog log = new SysUserAccountChangeLog();
+        log.setRelatedAmountAuditingId(audit.getId());
+        log.setStatus("90");
+        log.setRemark("提现驳回");
+        log.setSystemCode(audit.getSystemCode());
+        log.setUserId(audit.getUserId());
+        log.setOperType(4);
+        sysUserAccountIncomeLogService.save(log);
     }
 
     @Override
@@ -470,6 +490,7 @@ public class SysAmountAuditingServiceImpl extends ServiceImpl<SysAmountAuditingM
     public String exportYwyIORecs(YwyIOParam ywyIOParam) {
         log.info("导出业务员收支明细:ywyIOParam=[{}]", JSONUtil.toJsonStr(ywyIOParam));
         List<SysUserAccountChangeLog> changeLogs = sysUserAccountIncomeLogService.queryYwyIORecs(ywyIOParam);
+        log.info("导出业务员收支明细:ywyIOParam=[{}].导出[{}]条记录", JSONUtil.toJsonStr(ywyIOParam), CollUtil.size(changeLogs));
         String userName=null;
         if(CollUtil.isNotEmpty(changeLogs)){
             SysUserAccountChangeLog sysUserAccountChangeLog = changeLogs.get(0);

+ 36 - 8
tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserAccountServiceImpl.java

@@ -1,6 +1,7 @@
 package com.jzg.organization.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -94,7 +95,21 @@ public class SysUserAccountServiceImpl extends ServiceImpl<SysUserAccountMapper,
     @Override
     public Page<SysUserAccountVo> accountList(SysUserAccountPageParam param) {
         log.info("查询账户列表(应付概览页面):param=[{}]", JSONUtil.toJsonStr(param));
-        return baseMapper.accountList(param.getPage(), param);
+        Page<SysUserAccountVo> sysUserAccountVoPage = baseMapper.accountList(param.getPage(), param);
+        // 填充支付中的金额 add by lipf 2026年7月15日09:47:03
+        List<SysAmountAuditing> sysAmountAuditings = sysAmountAuditingService.list(new LambdaQueryWrapper<SysAmountAuditing>()
+                .eq(SysAmountAuditing::getAuditingStatus, 0));
+        Map<String, List<SysAmountAuditing>> collect = sysAmountAuditings.stream().collect(Collectors.groupingBy(SysAmountAuditing::getUserId));
+        sysUserAccountVoPage.getRecords().stream().peek(action->{
+            String userId = action.getUserId();
+            List<SysAmountAuditing> sysAmountAuditings1 = collect.get(userId);
+            if(CollUtil.isNotEmpty(sysAmountAuditings1)){
+                action.setPayingAmount(sysAmountAuditings1.get(0).getAmount());
+            }else{
+                action.setPayingAmount(BigDecimal.ZERO);
+            }
+        }).toList();
+        return sysUserAccountVoPage;
     }
 
     @Override
@@ -231,6 +246,7 @@ public class SysUserAccountServiceImpl extends ServiceImpl<SysUserAccountMapper,
 
     @Override
     public List<IncomeAndExpenseVo> getIncomeAndExpense(IncomeAndExpenseParam param) {
+        log.info("查询收支明细记录:param=[{}]", JSONUtil.toJsonStr(param));
         // 获取个人中心信息
         String mobile = baseController.getUserName();
         //String deptId = baseController.getUserDeptId();
@@ -265,25 +281,35 @@ public class SysUserAccountServiceImpl extends ServiceImpl<SysUserAccountMapper,
         
         // 时间筛选(支出记录)
         if (createTimeStart != null && !createTimeStart.isEmpty()) {
+            log.info("createTimeStart=[{}]", createTimeStart);
+            if(StrUtil.length(createTimeStart) < "2026-07-15 23:59:59".length()){
+                createTimeStart += " 00:00:00";
+            }
             auditingWrapper.ge(SysAmountAuditing::getCreateTime,
                     LocalDateTime.parse(createTimeStart, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
         }
         if (createTimeEnd != null && !createTimeEnd.isEmpty()) {
+            log.info("createTimeEnd=[{}]",createTimeEnd);
+            if(StrUtil.length(createTimeEnd) < "2026-07-15 23:59:59".length()){
+                createTimeEnd += " 23:59:59";
+            }
             auditingWrapper.le(SysAmountAuditing::getCreateTime,
                     LocalDateTime.parse(createTimeEnd, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
         }
-        
         List<SysAmountAuditing> sysAmountAuditingList = sysAmountAuditingService.list(auditingWrapper);
+        log.info("查询出审核记录[{}]条记录",CollUtil.size(sysAmountAuditingList));
 
+        Map<String, SysUser> userMap = new HashMap<>();
         // 批量查询用户信息
         Set<String> collect = sysAmountAuditingList.stream().map(SysAmountAuditing::getUserId).collect(Collectors.toSet());
-        QueryWrapper<SysUser> idSet = new QueryWrapper<SysUser>().in("id", collect);
-        List<SysUser> list = sysUserService.list(idSet);
-        Map<String, SysUser> userMap = new HashMap<>();
-        if (CollUtil.isNotEmpty(list)){
-            userMap = list.stream().collect(Collectors.toMap(SysUser::getId, Function.identity()));
+        log.info("collect=[{}]", JSONUtil.toJsonStr(collect));
+        if(CollUtil.isNotEmpty(collect)){
+            QueryWrapper<SysUser> idSet = new QueryWrapper<SysUser>().in("id", collect);
+            List<SysUser> list = sysUserService.list(idSet);
+            if (CollUtil.isNotEmpty(list)){
+                userMap = list.stream().collect(Collectors.toMap(SysUser::getId, Function.identity()));
+            }
         }
-
         // 构建订单收入查询参数(手动设置时间,避免类型转换问题)
         InsFeeOrdersParam feeOrdersParam = new InsFeeOrdersParam();
         feeOrdersParam.setUserId(sysUserJzgInfo.getUserId());
@@ -294,6 +320,7 @@ public class SysUserAccountServiceImpl extends ServiceImpl<SysUserAccountMapper,
             feeOrdersParam.setCreateTimeEnd(LocalDateTime.parse(createTimeEnd, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
         }
         List<InsFeeOrders> insFeeOrdersList = quoteClient.getInsFeeOrderByUserId(feeOrdersParam);
+        log.info("查询费用收入明细:feeOrdersParam=[{}],insFeeOrdersList=[{}]", JSONUtil.toJsonStr(feeOrdersParam), CollUtil.size(insFeeOrdersList));
 
         // 构建分销收入查询参数
         InsFeeOrdersParam feeOrdersParam1 = new InsFeeOrdersParam();
@@ -305,6 +332,7 @@ public class SysUserAccountServiceImpl extends ServiceImpl<SysUserAccountMapper,
             feeOrdersParam1.setCreateTimeEnd(LocalDateTime.parse(createTimeEnd, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
         }
         List<InsFeeOrders> distributionList = quoteClient.getInsFeeOrdersList(feeOrdersParam1);
+        log.info("查询分销记录:feeOrdersParam1=[{}], distributionList=[{}]", JSONUtil.toJsonStr(feeOrdersParam1), CollUtil.size(distributionList));
 
         List<IncomeAndExpenseVo.IncomeAndExpenseList> allRecords = new ArrayList<>();
         // 处理支出记录

+ 4 - 0
tenant/organization/src/main/resources/mapper/InsFeeFollowOrderMapper.xml

@@ -51,6 +51,7 @@
         ffo.id AS followId,
         ffo.year,
         ffo.month,
+        ffo.invoice_type,
         inv.id AS invoiceId,
         sett.id AS settlementId
         FROM ins_fee_follow_order ffo
@@ -91,6 +92,9 @@
             <if test="query.settlementStartTime != null and query.settlementStartTime != '' and query.settlementEndTime != null and query.settlementEndTime != ''">
                 AND sett.create_time BETWEEN #{query.settlementStartTime} AND #{query.settlementEndTime}
             </if>
+            <if test="query.invoiceType != null and query.invoiceType != ''">
+                AND ffo.invoice_type = #{query.invoiceType}
+            </if>
         </where>
     </select>
 

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

@@ -49,12 +49,22 @@
                 <result column="parent_product_name" property="parentProductName"/>
                 <result column="product_category_code" property="productCategoryCode"/>
                 <result column="product_category_name" property="productCategoryName"/>
+                <result column="premium_setting" property="premiumSetting"/>
                 <result column="alias" property="alias"/>
                 <result column="premium" property="premium"/>
                 <result column="quantity" property="quantity"/>
                 <result column="selected_status" property="selectedStatus"/>
                 <result column="min_seat_count" property="minSeatCount"/>
                 <result column="max_seat_count" property="maxSeatCount"/>
+                <collection property="settingList" ofType="com.jzg.commons.entity.po.jyxSetting">
+                    <id column="setting_id" property="id"/>
+                    <result column="seats" property="seats"/>
+                    <result column="setting_coverage" property="coverage"/>
+                    <result column="setting_premium" property="premium"/>
+                    <result column="setting_system_code" property="systemCode"/>
+                    <result column="setting_jyx_config_id" property="jyxConfigId"/>
+                    <result column="setting_product_code" property="productCode"/>
+                </collection>
             </collection>
         </collection>
     </resultMap>
@@ -175,16 +185,22 @@
             jc1.product_name as parent_product_name,
             jc1.product_code as product_category_code,
             jc1.product_name as product_category_name,
+            jc.premium_setting,
             psidi.quantity,
             psidi.selected_status,
             psidi.min_seat_count,
-            psidi.max_seat_count
+            psidi.max_seat_count,
+            js.id as setting_id,
+            js.seats,
+            js.premium as setting_premium,
+            js.product_code as setting_product_code
         FROM
             ptl_scheme ps
                 left JOIN ptl_scheme_info psi ON ps.id = psi.scheme_id AND psi.is_delete = 0
                 left JOIN ptl_scheme_insurance_driving_intention psidi ON psidi.scheme_info_id = psi.id AND psidi.is_delete = 0
                 left JOIN jyx_config jc ON psidi.driving_intention_id = jc.id AND jc.is_delete = 0
                 left JOIN jyx_config jc1 on jc.parent_id = jc1.id AND jc1.is_delete = 0
+                left join  jyx_setting js on js.jyx_config_id = jc.id
         WHERE
             ps.company_id = #{companyId}
           AND ps.product_id = #{productId}

+ 21 - 4
tenant/organization/src/main/resources/mapper/ReceivableMapper.xml

@@ -738,6 +738,7 @@
         GROUP_CONCAT(DISTINCT ipii.company_id SEPARATOR ',') AS company_id,
         GROUP_CONCAT(DISTINCT eic.name SEPARATOR ',') AS company_name,
         GROUP_CONCAT(DISTINCT ipii.invoice_type SEPARATOR ',') AS invoice_type,
+        GROUP_CONCAT(DISTINCT ipii.invoice_risk_type SEPARATOR ',') AS invoice_risk_type,
         GROUP_CONCAT(DISTINCT ipii.invoice_party SEPARATOR ',') AS invoice_party,
         GROUP_CONCAT(DISTINCT ipii.tax_point SEPARATOR ',') AS tax_point,
         GROUP_CONCAT(DISTINCT ipiis.settlement_payment_reason SEPARATOR ',') AS settlement_payment_reason,
@@ -898,6 +899,8 @@
         ipii.invoice_party as invoiceParty,
         ipii.tax_point as taxPoint,
         (COALESCE(ipi.jq_supervise_costs_premiums,0)  + COALESCE(ipi.sy_supervise_costs_premiums,0)  + COALESCE(ipi.jy_supervise_costs_premiums,0) ) as receivableSuperviseCosts,
+        COALESCE(ipi.jq_supervise_costs_premiums, 0) + COALESCE(ipi.sy_supervise_costs_premiums, 0) as superviseCostPremiums4Car,
+        COALESCE(ipi.jy_supervise_costs_premiums, 0) as jy_supervise_costs_premiums,
         ipi.jq_premium as jqPremium,
         ipi.jq_supervise_costs_proportion as jqSuperviseCostsProportion,
         ipi.jq_policy_no as jqPolicyNo,
@@ -1481,7 +1484,7 @@
         eic.name as company_name,
         eic.name_simple as companyNameSimple,
         sum( ipiis.actual_received_amount ) AS actual_received_amount,
-        GROUP_CONCAT(DISTINCT ipiis.settlement_payment_reason SEPARATOR ',') AS settlement_payment_reason,
+        GROUP_CONCAT(DISTINCT ipiis.settlement_payment_reason SEPARATOR ',') AS paymentReason,
         ipii.status,
         ipii.payment_reason
         FROM
@@ -1514,6 +1517,9 @@
             <if test="invoiceRecordQueryVo.companyNameSimple != null and invoiceRecordQueryVo.companyNameSimple != ''">
                 AND eic.id = #{invoiceRecordQueryVo.companyNameSimple}
             </if>
+            <if test="invoiceRecordQueryVo.partnerCompanyId != null and invoiceRecordQueryVo.partnerCompanyId != ''">
+                AND eic.id = #{invoiceRecordQueryVo.partnerCompanyId}
+            </if>
         </where>
         <if test="invoiceRecordQueryVo.settlementStatus != null and invoiceRecordQueryVo.settlementStatus != ''">
             HAVING CASE
@@ -1552,7 +1558,7 @@
         eic.name_simple as companyNameSimple,
         sum( ipiis.actual_received_amount ) AS actual_received_amount,
         ipii.status,
-        ipii.payment_reason,
+        GROUP_CONCAT(DISTINCT ipiis.settlement_payment_reason SEPARATOR ',') as paymentReason,
         GROUP_CONCAT(DISTINCT iffo.year SEPARATOR ',') AS year,
         GROUP_CONCAT(DISTINCT iffo.month SEPARATOR ',') AS month,
         iffo.partner_company_id,
@@ -1593,6 +1599,9 @@
             <if test="invoiceRecordQueryVo.companyNameSimple != null and invoiceRecordQueryVo.companyNameSimple != ''">
                 AND eic.id = #{invoiceRecordQueryVo.companyNameSimple}
             </if>
+            <if test="invoiceRecordQueryVo.partnerCompanyId != null and invoiceRecordQueryVo.partnerCompanyId != ''">
+                AND iffo.partner_company_id = #{invoiceRecordQueryVo.partnerCompanyId}
+            </if>
         </where>
         GROUP BY
         ipii.id,
@@ -1930,8 +1939,8 @@
         ipi.company_id,
         ipi.system_code,
         sum(COALESCE(ipi.jq_receivable_premium, 0)+ COALESCE(ipi.sy_receivable_premium ,0)+coalesce(ipi.jy_receivable_premium ,0 )) as totalReceivable,
-        sum(COALESCE(ipi.jq_other_costs_premiums, 0)+ COALESCE(ipi.sy_other_costs_premiums,0)+coalesce(ipi.jy_other_costs_premiums,0 )) as superviseFee4Other ,
-        sum(COALESCE(ipi.jq_supervise_costs_premiums, 0)+ COALESCE(ipi.sy_supervise_costs_premiums,0)+coalesce(ipi.jy_supervise_costs_premiums,0 )) as superviseFee
+        sum(coalesce(ipi.jy_supervise_costs_premiums, 0)) AS superviseFee4Other,
+        sum(COALESCE(ipi.jq_supervise_costs_premiums, 0) + COALESCE(ipi.sy_supervise_costs_premiums,0) ) AS superviseFee
         from
         ins_ply_income ipi
         left join esm_ins_company eic on eic.id = ipi.company_id AND eic.is_delete = 0
@@ -1941,6 +1950,14 @@
             <if test="vo.agreementType != null and vo.agreementType != ''">
                 AND ipi.agreement_type = #{vo.agreementType}
             </if>
+            <if test="vo.status != null">
+                <if test="vo.status == 1">
+                    AND ipi.settlement_time IS NOT NULL
+                </if>
+                <if test="vo.status == 0">
+                    AND ipi.settlement_time IS NULL
+                </if>
+            </if>
             <if test="vo.signingStartTime != null and vo.signingStartTime != '' and vo.signingEndTime != null and vo.signingEndTime != ''">
                 AND DATE(ipi.signing_time) between #{vo.signingStartTime} and #{vo.signingEndTime}
             </if>