Forráskód Böngészése

Merge remote-tracking branch 'origin/master'

wanghao 4 hónapja
szülő
commit
f351a756e3
49 módosított fájl, 2142 hozzáadás és 449 törlés
  1. 7 0
      commons/src/main/java/com/jzg/commons/entity/finance/dto/ExportSuperviseSettlementExcelDto.java
  2. 8 0
      commons/src/main/java/com/jzg/commons/entity/finance/po/InsPlyIncome.java
  3. 7 0
      commons/src/main/java/com/jzg/commons/entity/finance/po/InsPlyIncomeInvoice.java
  4. 36 0
      commons/src/main/java/com/jzg/commons/entity/finance/vo/InsPlyIncomeInvoiceVO.java
  5. 39 0
      commons/src/main/java/com/jzg/commons/entity/finance/vo/InvoiceAndSettlementVo.java
  6. 1 1
      commons/src/main/java/com/jzg/commons/entity/finance/vo/InvoicingVo.java
  7. 22 0
      commons/src/main/java/com/jzg/commons/entity/finance/vo/PlatformSettlementVo.java
  8. 0 1
      platform/src/main/resources/mapper/PtlAgreementAttributionMapper.xml
  9. 8 1
      tenant/insurance/quotation-ansheng/src/main/java/com/jzg/quotation/ansheng/crawler/build/AnShengCrawlerQuoteResultsVoBuild.java
  10. 1 1
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/build/BoHaiCrawlerQuoteResultsVoBuild.java
  11. 2 2
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/component/BoHaiCrawlerRequestComponent.java
  12. 7 7
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/entity/request/BoHaiCrawlerQuotationRequest2.java
  13. 31 1
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/entity/request/BoHaiCrawlerVehicleConfirmationReqeust1.java
  14. 4 5
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/service/impl/BoHaiCrawlerQuoteProcessServiceImpl.java
  15. 267 94
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/service/impl/BoHaiCrawlerRequestImpl.java
  16. 2 2
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/util/PythonExecutor.java
  17. 3 3
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/util/novel.py
  18. 5 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/entity/DetectLoginRequest.java
  19. 10 2
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/DateTimeUtil.java
  20. 4 3
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsFeeAuditService.java
  21. 2 2
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsOrdersService.java
  22. 6 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeAuditServiceImpl.java
  23. 6 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrdersServiceImpl.java
  24. 0 3
      tenant/insurance/quotation-summary/src/main/resources/application-prod.yaml
  25. 29 29
      tenant/insurance/quotation-summary/src/main/resources/mapper/InsFeeAuditMapper.xml
  26. 1 1
      tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/component/ZhongAnCrawlerCacheComponent.java
  27. 0 3
      tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/component/ZhongAnCrawlerRequestComponent.java
  28. 4 0
      tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/entity/ZhongAnCrawlerConfigureParameters.java
  29. 38 37
      tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/service/Impl/ZhongAnCrawlerRequestImpl.java
  30. 1 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/service/Impl/ZiJinApiRequestImpl.java
  31. 6 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/build/ZiJinCrawlerQuoteResultsVoBuild.java
  32. 21 6
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/component/ZiJinCrawlerRequestComponent.java
  33. 6 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerGetOrderNoRequest.java
  34. 24 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerQuotationRequest.java
  35. 29 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerQuoteProcessServiceImpl.java
  36. 975 167
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerRequestImpl.java
  37. 1 1
      tenant/organization/src/main/java/com/jzg/organization/controller/PtlAgreementCostController.java
  38. 12 0
      tenant/organization/src/main/java/com/jzg/organization/controller/PtlAgreementDispatchController.java
  39. 71 15
      tenant/organization/src/main/java/com/jzg/organization/controller/ReceivableController.java
  40. 1 1
      tenant/organization/src/main/java/com/jzg/organization/controller/SchemeController.java
  41. 7 0
      tenant/organization/src/main/java/com/jzg/organization/mapper/ReceivableMapper.java
  42. 1 1
      tenant/organization/src/main/java/com/jzg/organization/service/PtlAgreementCostService.java
  43. 10 0
      tenant/organization/src/main/java/com/jzg/organization/service/PtlAgreementDispatchService.java
  44. 37 4
      tenant/organization/src/main/java/com/jzg/organization/service/ReceivableService.java
  45. 9 3
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementCostServiceImpl.java
  46. 56 18
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementDispatchServiceImpl.java
  47. 1 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlSchemeServiceImpl.java
  48. 246 33
      tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java
  49. 78 1
      tenant/organization/src/main/resources/mapper/ReceivableMapper.xml

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

@@ -52,6 +52,10 @@ public class ExportSuperviseSettlementExcelDto {
     @ExcelProperty(value = "实收金额")
     private String actualReceivedAmount;
 
+    @Schema(description = "应收金额")
+    @ExcelProperty(value = "应收金额")
+    private String receivableSupervisePremium;
+
     @Schema(description = "收款日期")
     @ExcelProperty(value = "收款日期")
     private String receivePaymentDate;
@@ -74,4 +78,7 @@ public class ExportSuperviseSettlementExcelDto {
     @Schema(description = "附件url")
     private String fileUrl;
 
+    @Schema(description = "订单号")
+    private String orderNo;
+
 }

+ 8 - 0
commons/src/main/java/com/jzg/commons/entity/finance/po/InsPlyIncome.java

@@ -206,6 +206,14 @@ public class InsPlyIncome extends BaseModel {
     @ExcelProperty("驾意跟单位是否已经结算")
     private String jyOtherSettlement;
 
+    @Schema(description = "平台协议车险应收是否已经结算  0 未结算  1 结算")
+    @ExcelProperty("平台协议车险应收是否已经结算")
+    private String platformSuperviseSettlement;
+
+    @Schema(description = "平台协议非车险应收是否已经结算  0 未结算  1 结算")
+    @ExcelProperty("平台协议非车险应收是否已经结算")
+    private String platformOtherSettlement;
+
     @Schema(description = "维护人工号")
     @ExcelProperty("维护人工号")
     private String leaderId;

+ 7 - 0
commons/src/main/java/com/jzg/commons/entity/finance/po/InsPlyIncomeInvoice.java

@@ -6,6 +6,7 @@ import lombok.Data;
 
 import java.io.Serial;
 import java.math.BigDecimal;
+import java.time.LocalDateTime;
 import java.util.Objects;
 
 @Data
@@ -44,6 +45,12 @@ public class InsPlyIncomeInvoice extends BaseModel {
     @Schema(description = "税点")
     private String taxPoint;
 
+    @Schema(description = "开票号/发票号")
+    private String invoiceNo;
+
+    @Schema(description = "开票时间")
+    private LocalDateTime invoiceTime;
+
     @Schema(description = "状态")
     private String status;
 

+ 36 - 0
commons/src/main/java/com/jzg/commons/entity/finance/vo/InsPlyIncomeInvoiceVO.java

@@ -0,0 +1,36 @@
+package com.jzg.commons.entity.finance.vo;
+
+import com.jzg.commons.entity.finance.po.InsPlyIncomeInvoice;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(description = "财务应收开票表")
+public class InsPlyIncomeInvoiceVO extends InsPlyIncomeInvoice {
+
+    @Serial
+    private static final long serialVersionUID = 6982290696670953095L;
+    @Schema(description = "是否能开票")
+    private boolean canInvoice;
+
+    @Schema(description = "不能开票的原因")
+    private String errMsg;
+
+    /**
+     * 发票对应的应收订单的序号
+     * @date 2026/5/26 11:35
+     */
+    private List<String> incomeIds;
+
+    /**
+     * 发票对应的应收订单的序号
+     * @date 2026/5/26 11:35
+     */
+    private List<String> orderNos;
+
+}

+ 39 - 0
commons/src/main/java/com/jzg/commons/entity/finance/vo/InvoiceAndSettlementVo.java

@@ -0,0 +1,39 @@
+package com.jzg.commons.entity.finance.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+
+/**
+ * 结算Vo
+ */
+@Data
+@Schema(description = "结算Vo")
+public class InvoiceAndSettlementVo {
+
+    /**
+     * 开票的相关信息
+     */
+    private InsPlyIncomeInvoiceVO invoiceVO;
+
+    @Schema(description = "开票id")
+    private String invoicingId;
+
+    @Schema(description = "实收金额")
+    private BigDecimal actualReceivedAmount;
+
+    @Schema(description = "收款日期")
+    private String receivePaymentDate;
+
+    @Schema(description = "回款差额")
+    private BigDecimal paymentDifference;
+
+    @Schema(description = "差额原因")
+    private String paymentReason;
+
+    @Schema(description = "附加id")
+    private List<String> attachmentIds;
+}

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

@@ -21,7 +21,7 @@ public class InvoicingVo {
     @Schema(description = "开票的保司id")
     private String companyId;
 
-    // 开票类型 1:手续费 2:跟单费 3:驾意手续费 4::驾意跟单费
+    // 开票类型  1、手续费  2、跟单费  3、驾意险手续费 4、驾意险跟单费 5、平台应收-车险 6、平台应收-非车险
     @Schema(description = "开票类型")
     private String invoiceType;
 

+ 22 - 0
commons/src/main/java/com/jzg/commons/entity/finance/vo/PlatformSettlementVo.java

@@ -0,0 +1,22 @@
+package com.jzg.commons.entity.finance.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+
+/**
+ * 结算Vo
+ */
+@Data
+@Schema(description = "平台结算Vo")
+public class PlatformSettlementVo {
+
+    @Schema(description = "结算Vo")
+    private SettlementVo settlementVo;
+
+    @Schema(description = "开票id")
+    private InvoicingVo invoicingVo;
+}

+ 0 - 1
platform/src/main/resources/mapper/PtlAgreementAttributionMapper.xml

@@ -37,7 +37,6 @@
         <if test="ptlAgreementAttributionQueryVo.username != null and ptlAgreementAttributionQueryVo.username != ''">
             and paa.username like concat('%',#{ptlAgreementAttributionQueryVo.username},'%')
             or paa.user_abbr like concat('%',#{ptlAgreementAttributionQueryVo.username},'%')
-            or eic.name_simple like concat('%',#{ptlAgreementAttributionQueryVo.username},'%')
         </if>
         <if test="ptlAgreementAttributionQueryVo.quoteStatus != null and ptlAgreementAttributionQueryVo.quoteStatus != ''">
             and paa.quote_status = #{ptlAgreementAttributionQueryVo.quoteStatus}

+ 8 - 1
tenant/insurance/quotation-ansheng/src/main/java/com/jzg/quotation/ansheng/crawler/build/AnShengCrawlerQuoteResultsVoBuild.java

@@ -14,6 +14,7 @@ import com.jzg.quotation.ansheng.crawler.entity.response.AnShengCrawlerCalculate
 import com.jzg.quotation.commons.component.ConversionOfQuoteInformation;
 import lombok.extern.slf4j.Slf4j;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 
@@ -62,7 +63,13 @@ public final class AnShengCrawlerQuoteResultsVoBuild {
                 buildKindInfo(quoteResultsVo.getKindInfoVo(), contract.getPolicyCoverages());
             }
         });
-
+        QuoteResultsVo.CostsVo costs = quoteResultsVo.getCosts();
+        BigDecimal bi = costs.getBiPremium() == null ? BigDecimal.ZERO : new BigDecimal(costs.getBiPremium());
+        BigDecimal ci = costs.getCiPremium() == null ? BigDecimal.ZERO : new BigDecimal(costs.getCiPremium());
+        BigDecimal vv = costs.getVvTax() == null ? BigDecimal.ZERO : new BigDecimal(costs.getVvTax());
+        BigDecimal total = bi.add(ci).add(vv);
+        String totalStr = total.toPlainString();
+        costs.setSumPremium(totalStr);
         quoteResultsVo.setScoreVo(buildScoreVo(calculatePremiumApply));
         quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.WAIT_AUDIT);
         return quoteResultsVo;

+ 1 - 1
tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/build/BoHaiCrawlerQuoteResultsVoBuild.java

@@ -125,7 +125,7 @@ public class BoHaiCrawlerQuoteResultsVoBuild {
         // 交易流水号
         quoteResultsVo.setCompanyOrderNo("");
         // 报价失败提示
-        quoteResultsVo.setErrorMessage("报价失败");
+        quoteResultsVo.setErrorMessage(boHaiQuoteResponse.getHead().getReturnMessage());
         //设置报价状态:
         quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
         return quoteResultsVo;

+ 2 - 2
tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/component/BoHaiCrawlerRequestComponent.java

@@ -190,7 +190,7 @@ public class BoHaiCrawlerRequestComponent {
 
                     CrawlerRequestUrlStandard standard = (CrawlerRequestUrlStandard) urlOrStandard;
                     ResponseEntity<String> encryptedResponse = requestComponent.objectPost(
-                            standard.getRequestUrl(boHaiCrawlerProperties.getBaseUrl2()),
+                            standard.getRequestUrl(boHaiCrawlerProperties.getBaseUrl()),
                             boHaiCrawlerEncryptionRequest,
                             String.class,
                             headers
@@ -354,7 +354,7 @@ public class BoHaiCrawlerRequestComponent {
      * @return BoHaiCrawlerCarResponse 车型列表
      */
     public BoHaiCrawlerCarApiResponse car(BoHaiCrawlerCarRequest boHaiCrawlerCarRequest, HttpHeaders headers) {
-        return executeRequest(RequestType.ENCRYPTED, RequestUrl.CAR, boHaiCrawlerCarRequest, BoHaiCrawlerCarApiResponse.class, headers);
+        return executeRequest(RequestType.UNENCRYPTED, RequestUrl.CAR, boHaiCrawlerCarRequest, BoHaiCrawlerCarApiResponse.class, headers);
     }
 
     /**

+ 7 - 7
tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/entity/request/BoHaiCrawlerQuotationRequest2.java

@@ -63,7 +63,7 @@ public class BoHaiCrawlerQuotationRequest2 {
         @JSONField(ordinal = 3)
         private List<Insured> insuredList;
         /** 险种集合(商业险/交强险及其条款) */
-        @JSONField(ordinal = 4)
+        @JSONField(ordinal = 4, serialzeFeatures = {SerializerFeature.NotWriteDefaultValue})
         private List<Risk> riskList;
     }
 
@@ -313,7 +313,7 @@ public class BoHaiCrawlerQuotationRequest2 {
 
         /** 排量/功率(L/kW) */
         @JSONField(ordinal = 25)
-        private Double exhaustScale;
+        private String exhaustScale;
 
         /** 注册日期(初登) */
         @JSONField(ordinal = 26)
@@ -329,9 +329,9 @@ public class BoHaiCrawlerQuotationRequest2 {
 
         /** 使用年限 */
         @JSONField(ordinal = 29)
-        private String useYearsDI;
+        private Integer useYearsDI;
 
-        /** 过户标志 */
+        /** 过户标志 “0" 非过户 */
         @JSONField(ordinal = 30)
         private String chgOwnerFlag;
 
@@ -699,7 +699,7 @@ public class BoHaiCrawlerQuotationRequest2 {
         private String nation;
 
         /** 证件签发机关 */
-        @JSONField(ordinal = 25)
+        @JSONField(ordinal = 25,serialzeFeatures = SerializerFeature.WriteMapNullValue)
         private String identifyIssuer;
 
         /** 证件地址 */
@@ -749,7 +749,7 @@ public class BoHaiCrawlerQuotationRequest2 {
         /**
          * 驾驶人数量
          */
-        @JSONField(ordinal = 37)
+        @JSONField(name = "DInsuredCount", ordinal = 37)
         private String DInsuredCount;
 
         /** 是否指定受益人 */
@@ -1014,7 +1014,7 @@ public class BoHaiCrawlerQuotationRequest2 {
         @JSONField(ordinal = 49)
         private String expPricingAdjustValue;
         /** 不浮动费用率 */
-        @JSONField(ordinal = 50)
+        @JSONField(name = "NoneFluctuateFeeRate", ordinal = 50)
         private String NoneFluctuateFeeRate;
     }
     /**

+ 31 - 1
tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/entity/request/BoHaiCrawlerVehicleConfirmationReqeust1.java

@@ -212,7 +212,7 @@ public class BoHaiCrawlerVehicleConfirmationReqeust1 implements Serializable {
          * 排气量
          */
         @JsonProperty("displacement")
-        private String displacement;
+        private Double displacement;
 
         /**
          * 功率
@@ -345,6 +345,36 @@ public class BoHaiCrawlerVehicleConfirmationReqeust1 implements Serializable {
          */
         @JsonProperty("PrecisePriceComCode")
         private Boolean precisePriceComCode;
+
+        /**
+         * 车主名称
+         */
+        @JsonProperty("ownerName")
+        private String ownerName;
+
+        /**
+         * 车主证件类型
+         */
+        @JsonProperty("ownerCertificateType")
+        private String ownerCertificateType;
+
+        /**
+         * 车主证件号码
+         */
+        @JsonProperty("ownerCertificateNum")
+        private String ownerCertificateNum;
+
+        /**
+         * 证件类型
+         */
+        @JsonProperty("certificateType")
+        private String certificateType;
+
+        /**
+         * 证件号码
+         */
+        @JsonProperty("certificateNo")
+        private String certificateNo;
     }
 
 

+ 4 - 5
tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/service/impl/BoHaiCrawlerQuoteProcessServiceImpl.java

@@ -45,12 +45,12 @@ public class BoHaiCrawlerQuoteProcessServiceImpl implements BoHaiCrawlerQuotePro
     /**
      * Python脚本路径
      */
-    private static final String PYTHON_SCRIPT_PATH = "e:/project/jzg/tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/util/novel.py";
+    private static final String PYTHON_SCRIPT_PATH = "E:/IdeaProjects/jzg/tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/util/novel.py";
 
     /**
      * Python解释器路径
      */
-    private static final String PYTHON_EXECUTABLE_PATH = "E:\\project\\memorize_backend\\venv\\Scripts\\python.exe";
+    private static final String PYTHON_EXECUTABLE_PATH = "C:/Users/Administrator/AppData/Local/Programs/Python/Python312/python.exe";
 
     /**
      * Python脚本执行超时时间(秒)
@@ -133,12 +133,11 @@ public class BoHaiCrawlerQuoteProcessServiceImpl implements BoHaiCrawlerQuotePro
         headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
         return headers;*/
         HttpHeaders httpHeaders = new HttpHeaders();
-        httpHeaders.set("Cookie", "HTTPOnly; skin-color=skin-db; Cookie=!uEW94o2278iwLg21yv2qnldjEk8Kb5RsZkOl0FDX8+Mqxb0EGroyfXXQVmrGlnxevDyUYDwsWh2B5iY=; JSESSIONID=0001TTPD95X9DLJB1il0R_O_NhM:3T0NUMVN3E");
+        httpHeaders.set("Cookie", "HTTPOnly; Cookie=!EGmfBaVL8vRhQVm1yv2qnldjEk8KbwtSAPXA04eIJoNmCDYPGJ9wrhISai6LJc/RzChzLWC1R3fADU8=; JSESSIONID=0003Q7K2MvYVNnSRpylGrMlbm0d:-B0CDG8:1RGHVQ8T50:1Q4PVUSPE8");
 
         // 从Redis获取sessionId
         String sessionId = getOrRefreshSessionId();
-
-        if (StringUtils.hasLength(sessionId)) {
+        if (!StringUtils.hasLength(sessionId)) {
             sessionId = getSessionId();
         }
         httpHeaders.set("sessionId", sessionId);

+ 267 - 94
tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/service/impl/BoHaiCrawlerRequestImpl.java

@@ -4,12 +4,10 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.google.zxing.NotFoundException;
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
-import com.jzg.commons.entity.quote.vo.AttributionInformationVo;
-import com.jzg.commons.entity.quote.vo.CustomerInfoVo;
-import com.jzg.commons.entity.quote.vo.KindInfoVo;
-import com.jzg.commons.entity.quote.vo.QuoteVo;
+import com.jzg.commons.entity.quote.vo.*;
 import com.jzg.commons.entity.quote.vo.aggregated.*;
 import com.jzg.commons.entity.quote.vo.base.LoginBase;
+import com.jzg.commons.util.ObjectUtil;
 import com.jzg.quotation.bohai.api.constant.enums.ResponseCode;
 import com.jzg.quotation.bohai.api.entity.BoHaiConfigureParameters;
 import com.jzg.quotation.bohai.api.entity.request.ElectronicPolicyRequest;
@@ -19,6 +17,7 @@ import com.jzg.quotation.bohai.api.entity.request.StatusDocumentsRequest;
 import com.jzg.quotation.bohai.api.entity.response.ElectronicPolicyResponse;
 import com.jzg.quotation.bohai.api.entity.response.StatusDocumentsResponse;
 import com.jzg.quotation.bohai.api.entity.vo.PersonAreaVo;
+import com.jzg.quotation.bohai.api.util.StringSubStringUtils;
 import com.jzg.quotation.bohai.crawler.component.BoHaiCrawlerCacheComponent;
 import com.jzg.quotation.bohai.crawler.component.BoHaiBuildingAttributionInformation;
 import com.jzg.quotation.bohai.crawler.constant.enums.CertifyType;
@@ -40,14 +39,18 @@ import com.jzg.quotation.bohai.crawler.entity.response.*;
 import com.jzg.quotation.bohai.crawler.service.BoHaiCrawlerOrderService;
 import com.jzg.quotation.bohai.crawler.service.BoHaiCrawlerQuoteProcessService;
 import com.jzg.quotation.bohai.crawler.service.BoHaiCrawlerRequest;
+import com.jzg.quotation.commons.utils.DateTimeUtil;
+import com.jzg.quotation.commons.utils.DateUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.HttpHeaders;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.io.IOException;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 
@@ -83,8 +86,8 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
      * 说明:E:\project\memorize_backend\venv\Scripts\python.exe   这是我本地的python解释器路径,这个需要修改为你本地的路径
      */
     private static final String TOKEN = PythonExecutor.executeAndGetToken(
-            "E:/project/jzg/tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/util/novel.py",
-            "E:\\project\\memorize_backend\\venv\\Scripts\\python.exe", 120);
+            "E:/IdeaProjects/jzg/tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/util/novel.py",
+            "C:/Users/Administrator/AppData/Local/Programs/Python/Python312/python.exe", 120);
 
     /**
      * 登录
@@ -110,37 +113,49 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
     @Override
     public QuoteResultsVo quote(QuoteVo quoteVo) {
         try {
-            // 1.0 获取归属信息和配置参数
-            AttributionInformationVo attributionInformationVo = quoteVo.getOrder().getAttributionInformationVo();
-            HttpHeaders headers = boHaiCrawlerQuoteProcessService.getHeaders(attributionInformationVo.getUsername(), attributionInformationVo.getPassword());
-            String userCode = boHaiCrawlerCacheComponent.getUserCode(attributionInformationVo.getUsername());
-            log.info("userCode:{}", userCode);
-
-            BoHaiCrawlerConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(
-                    BoHaiCrawlerConfigureParameters.class, attributionInformationVo.getConfigInfo());
-            log.info("parameters参数的值:{}", JSON.toJSONString(parameters));
-
-            // 2.0 车辆查询
-            BoHaiCrawlerCarApiResponse carApiResponse = queryCarInfo(quoteVo, parameters, userCode, headers);
-            log.info("[车辆查询]返回参数的值:{}", JSON.toJSONString(carApiResponse));
-            // 车辆确认
-            BoHaiCrawlerVehicleConfirmationResponse2 confirmationResponse = confirmVehicle(quoteVo, carApiResponse, parameters, headers);
-            log.info("[车辆确认]返回参数的值:{}", JSON.toJSONString(confirmationResponse));
-
-            // 3.0 构建报价请求并发起报价
-            BoHaiCrawlerQuotationRequest2 quotationRequest = buildQuotationRequest(quoteVo, carApiResponse, confirmationResponse);
-            log.info("[报价]请求参数的值:{}", JSON.toJSONString(quotationRequest));
-            BoHaiCrawlerQuotationResponse2 boHaiCrawlerQuotationResponse2 = boHaiCrawlerRequestComponent.quotation(quotationRequest, headers);
-            log.info("[报价]返回参数的值:{}", JSON.toJSONString(boHaiCrawlerQuotationResponse2));
-
-            // 4.0 处理报价结果
-            return handleQuotationResponse(quoteVo, boHaiCrawlerQuotationResponse2);
+            // 执行报价流程
+            return executeQuotation(quoteVo);
         } catch (Exception e) {
             log.error("报价异常", e);
             throw new RuntimeException(e);
         }
     }
 
+    /**
+     * 执行报价流程(通用方法,首次报价和重复报价共用)
+     *
+     * @param quoteVo 报价实体
+     * @return QuoteResultsVo
+     */
+    private QuoteResultsVo executeQuotation(QuoteVo quoteVo) {
+        // 1.0 获取归属信息和配置参数
+        AttributionInformationVo attributionInformationVo = quoteVo.getOrder().getAttributionInformationVo();
+        HttpHeaders headers = boHaiCrawlerQuoteProcessService.getHeaders(attributionInformationVo.getUsername(), attributionInformationVo.getPassword());
+        String userCode = boHaiCrawlerCacheComponent.getUserCode(attributionInformationVo.getUsername());
+        log.info("userCode:{}", userCode);
+
+        BoHaiCrawlerConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(
+                BoHaiCrawlerConfigureParameters.class, attributionInformationVo.getConfigInfo());
+        log.info("parameters参数的值:{}", JSON.toJSONString(parameters));
+
+        // 2.0 车辆查询
+        BoHaiCrawlerCarApiResponse carApiResponse = queryCarInfo(quoteVo, parameters, userCode, headers);
+        log.info("[车辆查询]返回参数的值:{}", JSON.toJSONString(carApiResponse));
+        
+        // 车辆确认
+        BoHaiCrawlerVehicleConfirmationResponse2 confirmationResponse = confirmVehicle(quoteVo, carApiResponse, parameters, headers);
+        log.info("[车辆确认]返回参数的值:{}", JSON.toJSONString(confirmationResponse));
+
+        // 3.0 构建报价请求并发起报价
+        BoHaiCrawlerQuotationRequest2 quotationRequest = buildQuotationRequest(quoteVo, carApiResponse, confirmationResponse);
+        log.info("[报价]请求参数的值:{}", JSON.toJSONString(quotationRequest));
+        BoHaiCrawlerQuotationResponse2 boHaiCrawlerQuotationResponse2 = boHaiCrawlerRequestComponent.quotation(quotationRequest, headers);
+        log.info("[报价]返回参数的值:{}", JSON.toJSONString(boHaiCrawlerQuotationResponse2));
+
+        // 4.0 处理报价结果
+        return handleQuotationResponse(quoteVo, boHaiCrawlerQuotationResponse2);
+    }
+
     /**
      * 车辆查询
      *
@@ -175,7 +190,7 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
      *
      * @param quoteVo
      * @param carApiResponse
-     * @param currentValue
+     * @param confirmationResponse
      * @return BoHaiCrawlerQuotationRequest2
      */
     private BoHaiCrawlerQuotationRequest2 buildQuotationRequest(QuoteVo quoteVo, BoHaiCrawlerCarApiResponse carApiResponse, BoHaiCrawlerVehicleConfirmationResponse2 confirmationResponse) {
@@ -206,7 +221,7 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
      *
      * @param quoteVo
      * @param carApiResponse
-     * @param currentValue
+     * @param confirmationResponse
      * @return BoHaiCrawlerQuotationRequest2.BusinessData
      */
     private BoHaiCrawlerQuotationRequest2.BusinessData buildBusinessData(QuoteVo quoteVo, BoHaiCrawlerCarApiResponse carApiResponse, BoHaiCrawlerVehicleConfirmationResponse2 confirmationResponse) {
@@ -254,7 +269,7 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         mainInfo.setUnderUnit("");
         mainInfo.setIdentifyType("006");
         mainInfo.setIdentifyDetail("00001");
-        mainInfo.setIdentifyCode("");
+        mainInfo.setIdentifyCode(null);
         mainInfo.setIdentifyVip("");
         mainInfo.setComputerIp("");
         mainInfo.setMainCarKindBC("0");
@@ -281,7 +296,7 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
      *
      * @param quoteVo
      * @param carApiResponse
-     * @param currentValue
+     * @param confirmationResponse
      * @return BoHaiCrawlerQuotationRequest2.CarInfo
      */
     private BoHaiCrawlerQuotationRequest2.CarInfo buildCarInfo(QuoteVo quoteVo, BoHaiCrawlerCarApiResponse carApiResponse, BoHaiCrawlerVehicleConfirmationResponse2 confirmationResponse) {
@@ -296,11 +311,11 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         item.setPureRange("");
         // 燃油类型:A=汽油
         item.setPmFuelType("A");
-        // 验车状态:4=已验
-        item.setCarCheckStatus("4");
-        item.setActualValue(currentValue);
+        // 验车状态: 1=已验
+        item.setCarCheckStatus("1");
+        item.setActualValue("");//设置有值会出现价格实际价格与系统计算价格不一致问题
         item.setOtherNature7BI("0");
-        item.setNegotiatedValue(currentValue);
+        item.setNegotiatedValue("");//设置有值会出现价格实际价格与系统计算价格不一致问题
         // 新车标志:0=非新车
         item.setNewVehicleFlag("0");
         item.setLicenseNo(quoteVo.getCarInfoVo().getLicenseNo());
@@ -309,7 +324,7 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         item.setVinNo(quoteVo.getCarInfoVo().getVinNo());
         item.setNoLicenseFlag("");
         item.setLicenseColorCode(carApiResponse.getData().getJyCarModelFill().getPlateNoColor());
-        item.setUseNatureCode(quoteVo.getCarInfoVo().getCarNatureCode());
+        item.setUseNatureCode("8A"); // 8A=非营运
         item.setMainCarKindCode("A");
         item.setCarKindCode("A0");
 
@@ -319,12 +334,12 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         // 新车购置价(元)
         item.setPurchasePrice(carApiResponse.getData().getPrpDCarModels().get(0).getPurchasePrice());
         item.setBasePurchasePrice(carApiResponse.getData().getPrpDCarModels().get(0).getPurchasePrice());
-        item.setExhaustScale(Double.parseDouble(carApiResponse.getData().getPrpDCarModels().get(0).getExhaustScale()));
+        item.setExhaustScale(carApiResponse.getData().getPrpDCarModels().get(0).getExhaustScale() == null ? "" : String.valueOf(carApiResponse.getData().getPrpDCarModels().get(0).getExhaustScale()));
         item.setEnrollDate(quoteVo.getCarInfoVo().getRegisterDate());
         item.setUseYearsBI("");
         item.setUseYearsCI(0);
-        item.setUseYearsDI("");
-        item.setChgOwnerFlag(quoteVo.getCarInfoVo().getChgOwnerFlag());
+        item.setUseYearsDI(0);
+        item.setChgOwnerFlag(ObjectUtils.isEmpty(quoteVo.getCarInfoVo().getChgOwnerFlag()) ? "0" : quoteVo.getCarInfoVo().getChgOwnerFlag());
         item.setChgTypeFlag("0");
         //转移登记日期
         item.setChgOwnerDate(quoteVo.getCarInfoVo().getIssueDate());
@@ -340,7 +355,7 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         item.setMakeDate("");
         // 车辆品牌
         item.setVehicleBrand(carApiResponse.getData().getPrpDCarModels().get(0).getCarBrand());
-        item.setCompleteKerbMass(Integer.parseInt(carApiResponse.getData().getPrpDCarModels().get(0).getCompleteKerbMass()));
+        item.setCompleteKerbMass(ObjectUtils.isEmpty(carApiResponse.getData().getPrpDCarModels().get(0).getCompleteKerbMass()) ? 0 :Integer.parseInt(carApiResponse.getData().getPrpDCarModels().get(0).getCompleteKerbMass()));
         item.setLicenseKindCode(quoteVo.getCarInfoVo().getLicenseKindCode());
         item.setLicenseCategory(quoteVo.getCarInfoVo().getCarTypeCode());
         // 商业险续保标志:0=非续保
@@ -440,12 +455,12 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
 
         // 被保险人
         insuredList.add(createInsured2("2", "", quoteVo.getInsuredPersonInfo().getIdentifyNumber(), "01", quoteVo.getInsuredPersonInfo().getName(),
-                "2", "1", "1", "3", "", quoteVo.getInsuredPersonInfo().getMobile(), quoteVo.getInsuredPersonInfo().getAddr(),
+                "1", "1", "1", "3", "", quoteVo.getInsuredPersonInfo().getMobile(), quoteVo.getInsuredPersonInfo().getAddr(),
                 quoteVo.getInsuredPersonInfo().getPostCode(), quoteVo.getInsuredPersonInfo().getPostAddress(), quoteVo.getInsuredPersonInfo().getOrganizationCode(),
                 quoteVo.getInsuredPersonInfo().getAge(), birthDate, "", "01", "008zg", quoteVo.getInsuredPersonInfo().getEmail(), "", "汉", null, quoteVo.getInsuredPersonInfo().getAddr(), null, null, "1", "", "",
                 "0", "", "", "", "1", "1", "0", "", "", "", ""));
         // 车主
-        insuredList.add(createInsured3("3", "", quoteVo.getOwnersInfo().getIdentifyNumber(), "01", quoteVo.getOwnersInfo().getName(), "2", "1", "1", "3", "",
+        insuredList.add(createInsured3("3", "", quoteVo.getOwnersInfo().getIdentifyNumber(), "01", quoteVo.getOwnersInfo().getName(), "3", "1", "1", "1", "",
                 quoteVo.getOwnersInfo().getMobile(), quoteVo.getOwnersInfo().getAddr(), quoteVo.getOwnersInfo().getPostCode(), quoteVo.getOwnersInfo().getPostAddress(), quoteVo.getOwnersInfo().getOrganizationCode(),
                 quoteVo.getOwnersInfo().getAge(), birthDate, "", "", "",
                 "", "", "", "", "", "", "", "", "", "", ""));
@@ -546,7 +561,7 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         insured.setEmail(email);
         insured.setBusinessLicenseType(businessLicenseType);
         insured.setNation(nation);
-        insured.setIdentifyIssuer(null);
+        insured.setIdentifyIssuer(identifyIssuer);
         //证件地址
         insured.setIdentifyAddress(identifyAddress);
         insured.setIdentifyStartDate(identifyStartDate);
@@ -599,7 +614,6 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
      * @param carInsuredRelation
      * @param businessSort
      * @param linkerName
-     * @param isSpecialDInsured
      * @param specialDInsuredName
      * @param specialDInsuredIDType
      * @param specialDInsuredID
@@ -760,7 +774,7 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         insured.setIsIndividualBusi("");
         insured.setEmail(email);
         insured.setBusinessLicenseType(businessLicenseType);
-
+        insured.setIdentifyIssuer(null);
         insured.setNation(nation);
         //证件地址
         insured.setIdentifyAddress(identifyAddress);
@@ -1002,35 +1016,83 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
      */
     private List<BoHaiCrawlerQuotationRequest2.ItemKind> buildSyItemKindList(QuoteVo quoteVo) {
         List<BoHaiCrawlerQuotationRequest2.ItemKind> itemKinds = new java.util.ArrayList<>();
+        // 构建商业险险种
+        buildSyItemKindList(quoteVo, itemKinds);
+        // 构建驾意险险种
+        buildJyItemKindList(quoteVo, itemKinds);
+        return itemKinds;
+    }
 
+    /**
+     * 构建商业险险种列表
+     * @param quoteVo
+     * @param itemKinds
+     */
+    private void buildSyItemKindList(QuoteVo quoteVo, List<BoHaiCrawlerQuotationRequest2.ItemKind> itemKinds) {
         List<KindInfoVo> kindInfoVo = quoteVo.getKindInfoVo();
-        for (int i = 0; i < kindInfoVo.size(); i++) {
-            BoHaiCrawlerQuotationRequest2.ItemKind item = new BoHaiCrawlerQuotationRequest2.ItemKind();
-            item.setItemKindNo((i + 1) + "");
-            item.setKindCode(kindInfoVo.get(i).getKindCode());
-            item.setKindName(kindInfoVo.get(i).getKindName());
-            item.setOperateType("");
-            item.setStartDate(kindInfoVo.get(i).getStartDate());
-            item.setStartHour("0");
-            item.setEndDate(kindInfoVo.get(i).getEndDate());
-            item.setEndHour("24");
-            item.setAmount(kindInfoVo.get(i).getAmount());
-            item.setUnitAmount("");
-            item.setQuantity("");
-            item.setModeCode("");
-            item.setModeName("");
-            item.setShortRateFlag("3");
-            item.setShortRate("");
-            item.setCalculateFlag("Y");
-            item.setRate("");
-            item.setNotDeductibleFlag("0");
-            item.setDeductibleRatio("");
-            item.setDiscount("");
-            item.setAdjustRate("");
-            item.setValue("");
-            itemKinds.add(item);
+        if (kindInfoVo != null) {
+            for (int i = 0; i < kindInfoVo.size(); i++) {
+                BoHaiCrawlerQuotationRequest2.ItemKind item = buildBaseItemKind(i + 1);
+                KindInfoVo kind = kindInfoVo.get(i);
+                item.setKindCode(kind.getKindCode());
+                item.setKindName(kind.getKindName());
+                item.setStartDate(kind.getStartDate());
+                item.setEndDate(kind.getEndDate());
+                item.setAmount(kind.getAmount());
+                itemKinds.add(item);
+            }
         }
-        return itemKinds;
+    }
+
+    /**
+     * 构建交驾意险险种列表
+     * @param quoteVo
+     * @param itemKinds
+     */
+    private void buildJyItemKindList(QuoteVo quoteVo, List<BoHaiCrawlerQuotationRequest2.ItemKind> itemKinds) {
+        List<AccidentalDrivingVo> accidentalDrivings = quoteVo.getAccidentalDrivings();
+        if (!CollectionUtils.isEmpty(accidentalDrivings)) {
+            int startIndex = itemKinds.size() + 1;
+            for (int i = 0; i < accidentalDrivings.size(); i++) {
+                BoHaiCrawlerQuotationRequest2.ItemKind item = buildBaseItemKind(startIndex + i);
+                AccidentalDrivingVo driving = accidentalDrivings.get(i);
+                item.setKindCode("O");
+                item.setKindName(driving.getProductName());
+                item.setStartDate(DateTimeUtil.parseLocalDateToString(quoteVo.getCiRiskInfoVo().getStartDate(), DateTimeUtil.DATE_PATTERN));
+                item.setEndDate(DateTimeUtil.parseLocalDateToString(quoteVo.getCiRiskInfoVo().getEndDate(), DateTimeUtil.DATE_PATTERN));
+                item.setAmount(driving.getSumAmount());
+                item.setUnitAmount("10000.00"); // 这个金额不能为空,暂时按最低保额写死
+                item.setQuantity(String.valueOf(driving.getQuantity()));
+                itemKinds.add(item);
+            }
+        }
+    }
+
+    /**
+     * 构建 商业险险种 and 驾意险险种 通用字段设置
+     *
+     * @param itemKindNo 险种序号
+     * @return BoHaiCrawlerQuotationRequest2.ItemKind
+     */
+    private BoHaiCrawlerQuotationRequest2.ItemKind buildBaseItemKind(int itemKindNo) {
+        BoHaiCrawlerQuotationRequest2.ItemKind item = new BoHaiCrawlerQuotationRequest2.ItemKind();
+        item.setItemKindNo(String.valueOf(itemKindNo));
+        item.setOperateType("");
+        item.setStartHour("0");
+        item.setEndHour("24");
+        item.setUnitAmount("");
+        item.setModeCode("");
+        item.setModeName("");
+        item.setShortRateFlag("3");
+        item.setShortRate("");
+        item.setCalculateFlag("Y");
+        item.setRate("");
+        item.setNotDeductibleFlag("0");
+        item.setDeductibleRatio("");
+        item.setDiscount("");
+        item.setAdjustRate("");
+        item.setValue("");
+        return item;
     }
 
     /**
@@ -1045,17 +1107,17 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         // 农业标志:012001=非农业
         mainInfo.setAgriflag("012001");
         mainInfo.setClassCode("");
-        // 险种代码:0380=商业险
-        mainInfo.setRiskCode("0380");
+        // 险种代码:0380=商业险 0382=交强险+驾意险
+        mainInfo.setRiskCode("0382");
         mainInfo.setContractNo("");
         mainInfo.setDiscount("");
         mainInfo.setCurrency("CNY");
         mainInfo.setLastPolicyNo("");
         // 续保标志:0=非续保,1=续保
         mainInfo.setRenewalFlag("0");
-        mainInfo.setStartDate(quoteVo.getBiRiskInfoVo().getStartDate());
+        mainInfo.setStartDate(quoteVo.getBiRiskInfoVo() != null ? DateTimeUtil.parseLocalDateToString(quoteVo.getBiRiskInfoVo().getStartDate(), DateTimeUtil.DATE_PATTERN) : DateTimeUtil.parseLocalDateToString(quoteVo.getCiRiskInfoVo().getStartDate(), DateTimeUtil.DATE_PATTERN));
         mainInfo.setStartHour("0");
-        mainInfo.setEndDate(quoteVo.getBiRiskInfoVo().getEndDate());
+        mainInfo.setEndDate(quoteVo.getBiRiskInfoVo() != null ? DateTimeUtil.parseLocalDateToString(quoteVo.getBiRiskInfoVo().getEndDate(), DateTimeUtil.DATE_PATTERN) : DateTimeUtil.parseLocalDateToString(quoteVo.getCiRiskInfoVo().getEndDate(), DateTimeUtil.DATE_PATTERN));
         mainInfo.setEndHour("24");
         mainInfo.setImmediatelyActiveFlag("");
         // 生效开始时间
@@ -1067,7 +1129,7 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         mainInfo.setSpecialContractSummary("");
         mainInfo.setNoneFluctuateFlag("");
         // 无赔款优待系数(NCD):1=无优惠
-        mainInfo.setNcdCoefficient("1");
+        mainInfo.setNcdCoefficient("");
         mainInfo.setChannelCoefficient("1.00");
         mainInfo.setUnderwritingCoefficient("");
         mainInfo.setAdjustCoefficient("");
@@ -1079,7 +1141,7 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         mainInfo.setProposalNo("");
         // 客户属性:001=普通客户
         mainInfo.setCustomerProperty("001");
-        mainInfo.setRiskCoefficient("362001");
+        mainInfo.setRiskCoefficient("362001");// 渤海是362000
         mainInfo.setBusinessCoefficient("363000");
         mainInfo.setVehicleCoefficient("000");
         mainInfo.setCustomerCoefficient("364001");
@@ -1098,7 +1160,7 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         mainInfo.setPriceId("");
         mainInfo.setNoTaxAmount("");
         mainInfo.setTaxAmount("");
-        mainInfo.setPricingAdjustValue("");
+        mainInfo.setPricingAdjustValue("1");
         mainInfo.setExpPricingAdjustValue("");
         mainInfo.setNoneFluctuateFeeRate("");
         return mainInfo;
@@ -1107,13 +1169,19 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
     /**
      * 处理报价响应
      *
-     * @param quoteVo                        报价Vo
-     * @param boHaiCrawlerQuotationResponse2 报价响应
+     * @param quoteVo 报价Vo
+     * @param response 报价响应
      * @return QuoteResultsVo
      */
     private QuoteResultsVo handleQuotationResponse(QuoteVo quoteVo, BoHaiCrawlerQuotationResponse2 response) {
         if (ResponseCode.Quotation_Failed.getCode().equals(response.getHead().getReturnCode())) {
             log.info("报价失败");
+            // 检查是否为重复投保
+            String returnMessage = response.getHead().getReturnMessage();
+            if (returnMessage != null && returnMessage.contains("发生重复投保")) {
+                log.info("检测到重复投保,尝试重新报价");
+                return handleRepeatInsurance(quoteVo, response, returnMessage);
+            }
             // 报价失败
             boHaiCrawlerOrderService.save(quoteVo, response, false);
             return BoHaiCrawlerQuoteResultsVoBuild.buildQuoteFailResultsVo(response);
@@ -1124,6 +1192,106 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         return BoHaiCrawlerQuoteResultsVoBuild.buildQuoteResultsVo(quoteVo.getOrder().getOrdersNo(), quoteVo, response);
     }
 
+    /**
+     * 处理重复投保情况
+     *
+     * @param quoteVo 报价Vo
+     * @param response 报价响应
+     * @param returnMessage 返回消息
+     * @return QuoteResultsVo
+     */
+    private QuoteResultsVo handleRepeatInsurance(QuoteVo quoteVo, BoHaiCrawlerQuotationResponse2 response, String returnMessage) {
+        try {
+            log.info("开始处理重复投保情况");
+            
+            // 从错误消息中提取终保日期
+            String endDateStr = extractEndDateFromErrorMessage(returnMessage);
+            if (endDateStr == null || endDateStr.isEmpty()) {
+                log.warn("无法从错误消息中提取终保日期,直接返回失败结果");
+                boHaiCrawlerOrderService.save(quoteVo, response, false);
+                return BoHaiCrawlerQuoteResultsVoBuild.buildQuoteFailResultsVo(response);
+            }
+            
+            log.info("提取到的终保日期: {}", endDateStr);
+            
+            // 计算新的保险期间:从原终保日期开始,到一年后结束
+            String newStartDate = endDateStr + ":00"; // 添加秒部分
+            String newEndDate = DateUtil.getNextYearDateStr(newStartDate);
+            
+            log.info("新的保险期间 - 开始日期: {}, 结束日期: {}", newStartDate, newEndDate);
+            
+            // 更新报价请求中的保险期间
+            updateInsurancePeriod(quoteVo, newStartDate, newEndDate);
+            
+            // 重新执行报价流程
+            return executeQuotation(quoteVo);
+            
+        } catch (Exception e) {
+            log.error("处理重复投保异常", e);
+            // 如果处理重复投保过程中出现异常,返回原始失败结果
+            boHaiCrawlerOrderService.save(quoteVo, response, false);
+            return BoHaiCrawlerQuoteResultsVoBuild.buildQuoteFailResultsVo(response);
+        }
+    }
+
+    /**
+     * 从错误消息中提取终保日期
+     *
+     * @param errorMessage 错误消息
+     * @return 终保日期字符串
+     */
+    private String extractEndDateFromErrorMessage(String errorMessage) {
+        try {
+            // 使用StringSubStringUtils工具类提取终保日期
+            String endDate = StringSubStringUtils.subjectStringContentByTrafficPolicyDTOBenginDate(errorMessage, ":", "终保日期");
+            if (endDate != null && !endDate.isEmpty()) {
+                // 清理日期格式,移除可能的空格
+                return endDate.trim();
+            }
+            
+            // 如果上面的方法没有提取到,尝试另一种格式
+            endDate = StringSubStringUtils.subjectStringContentByBusinessPolicyEndDate(errorMessage, "终保日期:");
+            if (endDate != null && !endDate.isEmpty()) {
+                return endDate.trim();
+            }
+            
+            log.warn("无法从错误消息中提取终保日期: {}", errorMessage);
+            return null;
+        } catch (Exception e) {
+            log.error("提取终保日期异常", e);
+            return null;
+        }
+    }
+
+    /**
+     * 更新报价请求中的保险期间
+     *
+     * @param quoteVo 报价Vo
+     * @param startDate 开始日期
+     * @param endDate 结束日期
+     */
+    private void updateInsurancePeriod(QuoteVo quoteVo, String startDate, String endDate) {
+        try {
+            // 更新交强险的保险期间
+            if (quoteVo.getCiRiskInfoVo() != null) {
+                quoteVo.getCiRiskInfoVo().setStartDate(startDate.substring(0, 10)); // 只取日期部分
+                quoteVo.getCiRiskInfoVo().setEndDate(endDate.substring(0, 10));
+                log.info("已更新交强险保险期间 - 开始日期: {}, 结束日期: {}", 
+                    quoteVo.getCiRiskInfoVo().getStartDate(), quoteVo.getCiRiskInfoVo().getEndDate());
+            }
+            
+            // 更新商业险的保险期间
+            if (quoteVo.getBiRiskInfoVo() != null) {
+                quoteVo.getBiRiskInfoVo().setStartDate(startDate.substring(0, 10));
+                quoteVo.getBiRiskInfoVo().setEndDate(endDate.substring(0, 10));
+                log.info("已更新商业险保险期间 - 开始日期: {}, 结束日期: {}", 
+                    quoteVo.getBiRiskInfoVo().getStartDate(), quoteVo.getBiRiskInfoVo().getEndDate());
+            }
+        } catch (Exception e) {
+            log.error("更新保险期间异常", e);
+        }
+    }
+
     /**
      * 核保
      *
@@ -1508,18 +1676,18 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         bodyDTO.setBasicRateCode("");
         // 登录机构编码,先写死
         bodyDTO.setComCode("14070201");
-        bodyDTO.setEffectiveDate(quoteVo.getCiRiskInfoVo().getStartDate());
-        bodyDTO.setExpireDate(quoteVo.getCiRiskInfoVo().getEndDate());
+        bodyDTO.setEffectiveDate(DateTimeUtil.parseLocalDateToString(quoteVo.getCiRiskInfoVo().getStartDate(), DateTimeUtil.DATE_PATTERN));
+        bodyDTO.setExpireDate(DateTimeUtil.parseLocalDateToString(quoteVo.getCiRiskInfoVo().getEndDate(), DateTimeUtil.DATE_PATTERN));
         bodyDTO.setEndHour("24");
         bodyDTO.setStartHour("0");
-        bodyDTO.setRiskCode(quoteVo.getProductId());
-        bodyDTO.setBusinessNature(quoteVo.getCarInfoVo().getCarNatureCode());
-        bodyDTO.setEngineNo(boHaiCrawlerCarApiResponse.getData().getJyCarModelFill().getEngineNumber());
-        bodyDTO.setVin(boHaiCrawlerCarApiResponse.getData().getJyCarModelFill().getVinCode());
+        bodyDTO.setRiskCode(quoteVo.getOrder().getProductId());// 0380-交强险
+        bodyDTO.setBusinessNature("0");// 传0可以,赋值传参报错,不清楚含义
+        bodyDTO.setEngineNo(ObjectUtils.isEmpty(boHaiCrawlerCarApiResponse.getData().getJyCarModelFill().getEngineNumber()) ? quoteVo.getCarInfoVo().getEngineNo() : boHaiCrawlerCarApiResponse.getData().getJyCarModelFill().getEngineNumber());
+        bodyDTO.setVin(boHaiCrawlerCarApiResponse.getData().getJyCarModelFill().getVinCodeRe());
         bodyDTO.setLicensePlateNo(boHaiCrawlerCarApiResponse.getData().getJyCarModelFill().getPlateNumber());
         //车牌类型
         bodyDTO.setLicensePlateType(quoteVo.getCarInfoVo().getLicenseKindCode());
-        bodyDTO.setFirstRegisterDate(boHaiCrawlerCarApiResponse.getData().getJyCarModelFill().getRegisterDate());
+        bodyDTO.setFirstRegisterDate(ObjectUtils.isEmpty(boHaiCrawlerCarApiResponse.getData().getJyCarModelFill().getRegisterDate()) ? quoteVo.getCarInfoVo().getRegisterDate() : boHaiCrawlerCarApiResponse.getData().getJyCarModelFill().getRegisterDate());
         bodyDTO.setModelCode(boHaiCrawlerCarApiResponse.getData().getPrpDCarModels().get(0).getIndustryCarTypeCode());
         //平台车型代码
         bodyDTO.setPlatFormModelCode(boHaiCrawlerCarApiResponse.getData().getPrpDCarModels().get(0).getIndustryCarTypeCode());
@@ -1532,8 +1700,8 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
 
         //车辆动力参数
         //排量
-        bodyDTO.setExhaustScale(Double.parseDouble(quoteVo.getCarInfoVo().getDisplacement()));
-        bodyDTO.setDisplacement("");
+        bodyDTO.setExhaustScale(ObjectUtils.isEmpty(quoteVo.getCarInfoVo().getDisplacement()) ? 0.0 : Double.parseDouble(quoteVo.getCarInfoVo().getDisplacement()));
+        bodyDTO.setDisplacement(ObjectUtils.isEmpty(quoteVo.getCarInfoVo().getDisplacement()) ? 0.0 : Double.parseDouble(quoteVo.getCarInfoVo().getDisplacement()));
         bodyDTO.setPower(quoteVo.getCarInfoVo().getPowerScale());
         bodyDTO.setModelEnergyType(quoteVo.getCarInfoVo().getEnergyTypeCode());
         bodyDTO.setPureRange("");
@@ -1550,7 +1718,7 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         bodyDTO.setRatedPassengerCapacity(quoteVo.getCarInfoVo().getSeatCount());
         bodyDTO.setLimitLoadPerson(quoteVo.getCarInfoVo().getSeatCount());
         bodyDTO.setTonnage("0.0000");
-        bodyDTO.setLimitLoad(quoteVo.getCarInfoVo().getLimitLoad());
+        bodyDTO.setLimitLoad("0".equals(quoteVo.getCarInfoVo().getLimitLoad()) ? "0.0000" : quoteVo.getCarInfoVo().getLimitLoad());
         bodyDTO.setWholeWeight(quoteVo.getCarInfoVo().getCompleteKerbMass());
 
         //价格与价值信息
@@ -1570,6 +1738,11 @@ public class BoHaiCrawlerRequestImpl implements BoHaiCrawlerRequest {
         bodyDTO.setCarOwnerIdentifyType("01");
         bodyDTO.setSalesChannelRefCode("");
         bodyDTO.setPrecisePriceComCode(true);
+        bodyDTO.setOwnerName("");
+        bodyDTO.setOwnerCertificateType("01");
+        bodyDTO.setOwnerCertificateNum("");
+        bodyDTO.setCertificateType("");
+        bodyDTO.setCertificateNo("");
         boHaiCrawlerVehicleConfirmationReqeust1.setBody(bodyDTO);
         log.info("[车辆确认]请求参数的值:{}", JSON.toJSONString(boHaiCrawlerVehicleConfirmationReqeust1));
         //调用车辆确认接口

+ 2 - 2
tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/util/PythonExecutor.java

@@ -307,8 +307,8 @@ public class PythonExecutor {
         }*/
         // 获取token的值
         String token = PythonExecutor.executeAndGetToken(
-                "e:/project/jzg/tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/util/novel.py",
-                "E:\\project\\memorize_backend\\venv\\Scripts\\python.exe", 120);
+                "E:/IdeaProjects/jzg/tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/util/novel.py",
+                "C:/Users/Administrator/AppData/Local/Programs/Python/Python312/python.exe", 120);
         if (token != null) {
             System.out.println("获取到的token: " + token);
         } else {

+ 3 - 3
tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/util/novel.py

@@ -116,9 +116,10 @@ class BHBX_login():
 # 账号:114050281   密码:Bhcx1234  openId  odviKt0g-CP5NVNnZKiHEStPbRoU
 
 usernamelist = [
-    {"username":"114050281","passward":"Bhcx1234","openId":"odviKt0g-CP5NVNnZKiHEStPbRoU"} # odviKt0g-CP5NVNnZKiHEStPbRoU
+    {"username":"114050281","passward":"Bhcx1234","openId":"odviKt0g-CP5NVNnZKiHEStPbRoU"}, # odviKt0g-CP5NVNnZKiHEStPbRoU
+    {"username":"114050287","passward":"Bhcx1234","openId":"odviKt0g-CP5NVNnZKiHEStPbRIU"}, # odviKt0g-CP5NVNnZKiHEStPbRoU
 ]
-username = "114050281"
+username = "114050287"
 password = ""
 openId = ""
 for item in usernamelist:
@@ -132,4 +133,3 @@ if openId == "":
 bhbx = BHBX_login(username,password,openId)
 print(bhbx.login())
 
-

+ 5 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/entity/DetectLoginRequest.java

@@ -29,4 +29,9 @@ public class DetectLoginRequest {
      * 密码
      */
     private String password;
+
+    /**
+     * 产品id 众安登录用
+     */
+    private String productId;
 }

+ 10 - 2
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/DateTimeUtil.java

@@ -136,8 +136,16 @@ public class DateTimeUtil {
      * @return String 日期
      */
     public static String parseLocalDateToString(String localDateStr, String pattern) {
-        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
-        return LocalDate.parse(localDateStr, dateTimeFormatter).toString();
+        // 判断是否包含时间部分
+        if (localDateStr.contains(" ") || localDateStr.contains(":")) {
+            // 包含时间部分,先解析为LocalDateTime,再提取日期
+            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATETIME_PATTERN);
+            return LocalDateTime.parse(localDateStr, dateTimeFormatter).toLocalDate().toString();
+        } else {
+            // 仅日期部分,直接解析为LocalDate
+            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
+            return LocalDate.parse(localDateStr, dateTimeFormatter).toString();
+        }
     }
 
 

+ 4 - 3
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsFeeAuditService.java

@@ -36,9 +36,10 @@ public interface InsFeeAuditService extends IService<InsFeeAudit> {
     void feeAuditAdd(InsOrders orders);
 
     /**
-     * 订单详情
-     * @param orderNo
-     * @return
+     * 根据订单号查询订单详情
+     *
+     * @param orderNo 订单编号
+     * @return QuoteEchoVo 订单详情
      */
     QuoteEchoVo auditInfo(String orderNo);
 

+ 2 - 2
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsOrdersService.java

@@ -128,8 +128,8 @@ public interface InsOrdersService extends IService<InsOrders> {
     /**
      * 查询订单详情
      *
-     * @param ordersNo
-     * @return
+     * @param ordersNo 订单号
+     * @return QuoteEchoVo 订单详情
      */
     QuoteEchoVo getOrderDetail(String ordersNo);
 

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

@@ -227,6 +227,12 @@ public class InsFeeAuditServiceImpl extends ServiceImpl<InsFeeAuditMapper, InsFe
         this.save(insFeeAudit);
     }
 
+    /**
+     * 根据订单号查询订单详情
+     *
+     * @param orderNo 订单编号
+     * @return QuoteEchoVo 订单详情
+     */
     @Override
     public QuoteEchoVo auditInfo(String orderNo) {
         //险种和订单类型以及业务员对应的管理员

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

@@ -1298,7 +1298,12 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
 
     }
 
-
+    /**
+     * 查询订单详情
+     *
+     * @param ordersNo 订单号
+     * @return QuoteEchoVo 订单详情
+     */
     @Override
     public QuoteEchoVo getOrderDetail(String ordersNo) {
         log.info("获取订单详情.ordersNo=[{}]", ordersNo);

+ 0 - 3
tenant/insurance/quotation-summary/src/main/resources/application-prod.yaml

@@ -233,9 +233,6 @@ zijin:
 #    downLoadDocument: http://open.zking.com/temp/api/v1/insurance/nonAutoMobile/queryPolicy/downLoadDocument
 #    # 对接三方渠道验车链接接口
 #    sendCheckCarLink: http://open.zking.com/api/v1/open/open-aggregate/auth/wanJiaYun/sendCheckCarLink
-zhongAn:
-  id: "1402039"
-  productId: "10676"
 
 
 feign:

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

@@ -27,20 +27,21 @@
     </sql>
     <select id="queryPage" resultType="com.jzg.commons.entity.orders.vo.FeeAuditVo">
         SELECT
-            ifa.order_no as orderNo,
-            io.company_id,
-            io.company_name as companyName,
-            ioci.license_no AS licenseNo,
-            iocui.name as insurName,
-            CASE io.entry_status
-            WHEN 1 THEN '车险出单'
-            WHEN 2 THEN '代客录单'
-            WHEN 3 THEN '补录订单'
-            ELSE ''
-            END AS order_type,
-            suji.name as name,
-            su.mobile as mobile,
-            CASE suji.type_attr
+                qsu.username ,    -- 业务员登录账号
+        ifa.order_no as orderNo,
+        io.company_id,
+        io.company_name as companyName,
+        ioci.license_no AS licenseNo,
+        iocui.name as insurName,
+        CASE io.entry_status
+        WHEN 1 THEN '车险出单'
+        WHEN 2 THEN '代客录单'
+        WHEN 3 THEN '补录订单'
+        ELSE ''
+        END AS order_type,
+        suji.name as name,
+        qsu.mobile as mobile,
+        CASE suji.type_attr
                 WHEN 1 THEN '前线人员'
                 WHEN 2 THEN '后线人员'
                 WHEN 3 THEN '合伙人'
@@ -65,19 +66,18 @@
                 WHEN 1 THEN '是'
                 ELSE ''
                 END AS isProblem,
-            io.order_source
-        FROM ins_fee_audit ifa
-        LEFT JOIN ins_orders as io on ifa.order_no = io.id
-        LEFT JOIN ins_orders_car_info as ioci on io.id = ioci.order_no
-        LEFT JOIN ins_orders_car_user_info as iocui on io.id = iocui.order_no and iocui.policy_person_type = 3
-        LEFT JOIN sys_user qsu on qsu.mobile = io.real_quote_user_id
-        LEFT JOIN sys_user_jzg_info suji ON suji.user_id = qsu.id and suji.system_code = #{param.systemCode}
-        LEFT JOIN sys_user su on su.id = io.real_quote_user_id
-        LEFT JOIN sys_dept sd on suji.dept_id = sd.id
-        LEFT JOIN ptl_agreement pa on io.agreement_id = pa.id
-        LEFT JOIN sys_user sua on sua.id = pa.custodian_id
-        LEFT JOIN ins_orders_costs ioc on ioc.order_no = io.id
-        LEFT JOIN ins_orders_external_policy ioep on ioep.order_no = io.id
+                io.order_source
+                FROM ins_fee_audit ifa
+                LEFT JOIN ins_orders as io on ifa.order_no = io.id
+                LEFT JOIN ins_orders_car_info as ioci on io.id = ioci.order_no
+                LEFT JOIN ins_orders_car_user_info as iocui on io.id = iocui.order_no and iocui.policy_person_type = 3
+                LEFT JOIN sys_user qsu on qsu.mobile = io.real_quote_user_id
+                LEFT JOIN sys_user_jzg_info suji ON suji.user_id = qsu.id and suji.system_code = #{param.systemCode}
+                LEFT JOIN sys_dept sd on suji.dept_id = sd.id
+                LEFT JOIN ptl_agreement pa on io.agreement_id = pa.id
+                LEFT JOIN sys_user sua on sua.id = pa.custodian_id
+                LEFT JOIN ins_orders_costs ioc on ioc.order_no = io.id
+                LEFT JOIN ins_orders_external_policy ioep on ioep.order_no = io.id
         <where>
             <choose>
                 <when test="param.receiveUser != null and param.receiveUser != ''">
@@ -106,7 +106,7 @@
                 and suji.type_attr = #{param.attrType}
             </if>
             <if test="param.salesman != null and param.salesman != ''">
-                and (su.username = #{param.salesman} or su.mobile = #{param.salesman})
+                and (qsu.username = #{param.salesman} or qsu.mobile = #{param.salesman})
             </if>
             <if test="param.orderStatus != null ">
                 and io.order_status = #{param.orderStatus}
@@ -192,7 +192,7 @@
                 END AS attrType,
                io.signing_time as signingTime,
                io.create_time as quotationTime, sua.username as dockingPerson,
-               pa.agreement_abbreviation as agreementName,io.product_name as productName,
+               pa.agreement_abbreviation as agreementName,io.product_id, io.product_name as productName,
                ioc.jq_premium as jqPremium, ioc.sy_premium as syPremium, ioc.jy_premium as jyPremium,
                ioc.sum_premium as sumPremium,sd.name as deptName,ifa.create_time as createTime,
                ifa.create_by as createBy,io.pay_time as payTime, ifa.audit_time as auditTime,

+ 1 - 1
tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/component/ZhongAnCrawlerCacheComponent.java

@@ -137,7 +137,7 @@ public class ZhongAnCrawlerCacheComponent {
             String firstUrl = "http://zhongan.bjhfbx.cn/subao-proxy-customer/api/redirectToCoopUserProductExclusivePage";
             URI uri1 = new URIBuilder(firstUrl)
                     .addParameter("coopUserId", zhongAnId)
-                    .addParameter("productId", "10805")
+                    .addParameter("productId", productId)
                     .addParameter("isOpenByPC", "N")
                     .addParameter("promotionScene", "16")
                     .addParameter("bizContent", "")

+ 0 - 3
tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/component/ZhongAnCrawlerRequestComponent.java

@@ -46,9 +46,6 @@ public class ZhongAnCrawlerRequestComponent {
 
     private final ZhongAnCrawlerCacheComponent zhongAnCrawlerCacheComponent;
 
-    @Value("${zhongAn.id}")
-    private String zhongAnId;
-
     /**
      * 登录
      *

+ 4 - 0
tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/entity/ZhongAnCrawlerConfigureParameters.java

@@ -21,4 +21,8 @@ public class ZhongAnCrawlerConfigureParameters implements ConfigureParameters {
     private String flowId;
 
     private String flag = "0";
+
+    private String username;
+
+    private String productId;
 }

+ 38 - 37
tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/service/Impl/ZhongAnCrawlerRequestImpl.java

@@ -65,12 +65,6 @@ public class ZhongAnCrawlerRequestImpl implements ZhongAnCrawlerRequest {
 
     private final ZhongAnCrawlerCacheComponent zhongAnCrawlerCacheComponent;
 
-    @Value("${zhongAn.id}")
-    private String zhongAnId;
-
-    @Value("${zhongAn.productId}")
-    private String productId;
-
     private final PlatformClient platformClient;
 
     @Autowired
@@ -86,23 +80,23 @@ public class ZhongAnCrawlerRequestImpl implements ZhongAnCrawlerRequest {
     private static final String FLOWID = "flowId";
     private static final String ZHONGAN_COOKIE = "zhongan:cookie:";
 
-    public LoginResult login(String zhongAnId, String productId) {
+    public LoginResult login(ZhongAnCrawlerConfigureParameters parameters) {
         // 先从缓存取
-        Map<Object, Object> cacheMap = redissonClient.getMap(ZHONGAN_COOKIE + zhongAnId);
+        Map<Object, Object> cacheMap = redissonClient.getMap(ZHONGAN_COOKIE + parameters.getUsername());
         if (cacheMap != null && !cacheMap.isEmpty()) {
             String zaLoginCookieKey = (String) cacheMap.get(COOKIE);
             String flowId = (String) cacheMap.get(FLOWID);
 
-            System.out.println("[" + zhongAnId + "] 从 Redisson 缓存读取登录信息");
+            System.out.println("[" + parameters.getUsername() + "] 从 Redisson 缓存读取登录信息");
             return new LoginResult(200, "缓存登录成功", zaLoginCookieKey, flowId);
         }
 
         // 缓存没有 执行登录
-        LoginResult result = zhongAnCrawlerCacheComponent.loginCookieCache(zhongAnId, productId);
+        LoginResult result = zhongAnCrawlerCacheComponent.loginCookieCache( parameters.getUsername(),  parameters.getProductId());
 
         // 登录成功 存缓存
         if (result.getCode() == 200) {
-            zhongAnCrawlerCacheComponent.cacheCookie(result.getZaLoginCookieKey(), result.getFlowId(), zhongAnId);
+            zhongAnCrawlerCacheComponent.cacheCookie(result.getZaLoginCookieKey(), result.getFlowId(),  parameters.getUsername());
         }
 
         return result;
@@ -111,18 +105,18 @@ public class ZhongAnCrawlerRequestImpl implements ZhongAnCrawlerRequest {
     @Override
     public boolean detectLogin(DetectLoginRequest detectLoginRequest) {
         // 先从缓存取
-        Map<Object, Object> cacheMap = redissonClient.getMap(ZHONGAN_COOKIE + zhongAnId);
+        Map<Object, Object> cacheMap = redissonClient.getMap(ZHONGAN_COOKIE + detectLoginRequest.getUsername());
         if (cacheMap != null && !cacheMap.isEmpty()) {
-            System.out.println("[" + zhongAnId + "] 从 Redisson 缓存读取登录信息");
+            System.out.println("[" + detectLoginRequest.getUsername() + "] 从 Redisson 缓存读取登录信息");
             return true;
         }
 
         // 缓存没有 执行登录
-        LoginResult result = zhongAnCrawlerCacheComponent.loginCookieCache(zhongAnId, productId);
+        LoginResult result = zhongAnCrawlerCacheComponent.loginCookieCache(detectLoginRequest.getUsername(), detectLoginRequest.getProductId());
 
         // 登录成功 存缓存
         if (result.getCode() == 200) {
-            zhongAnCrawlerCacheComponent.cacheCookie(result.getZaLoginCookieKey(), result.getFlowId(), zhongAnId);
+            zhongAnCrawlerCacheComponent.cacheCookie(result.getZaLoginCookieKey(), result.getFlowId(), detectLoginRequest.getProductId());
         }
         return result.getCode() == 200;
     }
@@ -136,18 +130,19 @@ public class ZhongAnCrawlerRequestImpl implements ZhongAnCrawlerRequest {
      */
     @Override
     public QuoteResultsVo quote(QuoteVo quoteVo) {
+        AttributionInformationVo attributionInformationVo = quoteVo.getOrder().getAttributionInformationVo();
+        //获取配置信息
+        ZhongAnCrawlerConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(ZhongAnCrawlerConfigureParameters.class, attributionInformationVo.getConfigInfo());
         // 检查登录
-        login(zhongAnId, productId);
+        login(parameters);
+        HttpHeaders headers = zhongAnCrawlerRequestComponent.getHeaders(parameters.getUsername());
+
         zhongAnCrawlerCacheComponent.setCache(quoteVo.getOwnersInfo().getIdentifyNumber(), quoteVo.getOrder().getOrdersNo() + ZhongAnCrawlerCacheComponent.IDENTIFY_NUMBER);
         CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
         zhongAnCrawlerCacheComponent.setCache(carInfoVo.getLicenseNo(), quoteVo.getOrder().getOrdersNo() + ZhongAnCrawlerCacheComponent.LICENSE);
-        AttributionInformationVo attributionInformationVo = quoteVo.getOrder().getAttributionInformationVo();
-        //获取配置信息
-        ZhongAnCrawlerConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(ZhongAnCrawlerConfigureParameters.class, attributionInformationVo.getConfigInfo());
-        HttpHeaders headers = zhongAnCrawlerRequestComponent.getHeaders(zhongAnId);
         String flowId = parameters.getFlowId();
         if (StringUtils.isEmpty(flowId)) {
-            parameters.setFlowId(zhongAnCrawlerCacheComponent.getFlowId(zhongAnId));
+            parameters.setFlowId(zhongAnCrawlerCacheComponent.getFlowId(parameters.getUsername()));
         }
         // 查询归属信息
         ZhongAnCrawlerQueryInitInfoRequest queryInitInfoRequest = new ZhongAnCrawlerQueryInitInfoRequest(parameters.getFlowId());
@@ -323,14 +318,14 @@ public class ZhongAnCrawlerRequestImpl implements ZhongAnCrawlerRequest {
      */
     @Override
     public UnderwritingResultsVo underwriting(UnderwritingVo underwritingVo) throws Exception {
-        // 检查登录
-        login(zhongAnId, productId);
         AttributionInformationVo attributionInformationVo = underwritingVo.getOrder().getAttributionInformationVo();
         ZhongAnCrawlerConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(ZhongAnCrawlerConfigureParameters.class, attributionInformationVo.getConfigInfo());
-        HttpHeaders headers = zhongAnCrawlerRequestComponent.getHeaders(zhongAnId);
+        // 检查登录
+        login(parameters);
+        HttpHeaders headers = zhongAnCrawlerRequestComponent.getHeaders(parameters.getUsername());
         String flowId = parameters.getFlowId();
         if (StringUtils.isEmpty(flowId)) {
-            parameters.setFlowId(zhongAnCrawlerCacheComponent.getFlowId(zhongAnId));
+            parameters.setFlowId(zhongAnCrawlerCacheComponent.getFlowId(parameters.getUsername()));
         }
         ZhongAnCrawlerOrder zhongAnCrawlerOrder = zhongAnCrawlerOrderService.findByOrdersNo(underwritingVo.getOrder().getOrdersNo());
         ZhongAnCrawlerMarkRequest markRequest = new ZhongAnCrawlerMarkRequest(parameters, zhongAnCrawlerOrder.getOrderNo());
@@ -360,12 +355,14 @@ public class ZhongAnCrawlerRequestImpl implements ZhongAnCrawlerRequest {
      */
     @Override
     public PaymentLinkResultsVo getPaymentLink(PaymentLinkVo paymentLinkVo) {
+        //获取配置信息
+        AttributionInformationVo attributionInformationVo = paymentLinkVo.getOrder().getAttributionInformationVo();
+        ZhongAnCrawlerConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(ZhongAnCrawlerConfigureParameters.class, attributionInformationVo.getConfigInfo());
         // 检查登录
-        login(zhongAnId, productId);
+        login(parameters);
         PaymentLinkResultsVo paymentLinkResultsVo = new PaymentLinkResultsVo();
         OrderBase orderBase = paymentLinkVo.getOrder();
-        //获取配置信息
-        HttpHeaders headers = zhongAnCrawlerRequestComponent.getHeaders(zhongAnId);
+        HttpHeaders headers = zhongAnCrawlerRequestComponent.getHeaders(parameters.getUsername());
 
         ZhongAnCrawlerOrder zhongAnCrawlerOrder = zhongAnCrawlerOrderService.findByOrdersNo(orderBase.getOrdersNo());
 
@@ -390,16 +387,17 @@ public class ZhongAnCrawlerRequestImpl implements ZhongAnCrawlerRequest {
      */
     @Override
     public void uploadImage(InsuranceUploadImageVo insuranceUploadImageVo) {
-        // 检查登录
-        login(zhongAnId, productId);
         OrderBase orderBase = insuranceUploadImageVo.getOrder();
         AttributionInformationVo attributionInformationVo = orderBase.getAttributionInformationVo();
         //获取配置信息
         ZhongAnCrawlerConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(ZhongAnCrawlerConfigureParameters.class, attributionInformationVo.getConfigInfo());
-        HttpHeaders headers = zhongAnCrawlerRequestComponent.getHeaders(zhongAnId);
+        // 检查登录
+        login(parameters);
+
+        HttpHeaders headers = zhongAnCrawlerRequestComponent.getHeaders(parameters.getUsername());
         String flowId = parameters.getFlowId();
         if (StringUtils.isEmpty(flowId)) {
-            parameters.setFlowId(zhongAnCrawlerCacheComponent.getFlowId(zhongAnId));
+            parameters.setFlowId(zhongAnCrawlerCacheComponent.getFlowId(parameters.getUsername()));
         }
         ZhongAnCrawlerOrder zhongAnCrawlerOrder = zhongAnCrawlerOrderService.findByOrdersNo(orderBase.getOrdersNo());
         for (InsuranceImageVo insuranceImageVo : insuranceUploadImageVo.getImageVoList()) {
@@ -472,11 +470,14 @@ public class ZhongAnCrawlerRequestImpl implements ZhongAnCrawlerRequest {
      */
     @Override
     public DownloadPolicyResultVo downloadPolicy(DownloadPolicyVo downloadPolicyVo) {
+        AttributionInformationVo attributionInformationVo = downloadPolicyVo.getOrder().getAttributionInformationVo();
+        //获取配置信息
+        ZhongAnCrawlerConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(ZhongAnCrawlerConfigureParameters.class, attributionInformationVo.getConfigInfo());
         // 检查登录
-        login(zhongAnId, productId);
+        login(parameters);
         OrderBase orderBase = downloadPolicyVo.getOrder();
         //获取配置信息
-        HttpHeaders headers = zhongAnCrawlerRequestComponent.getHeaders(zhongAnId);
+        HttpHeaders headers = zhongAnCrawlerRequestComponent.getHeaders(parameters.getUsername());
 
         ZhongAnCrawlerOrder zhongAnCrawlerOrder = zhongAnCrawlerOrderService.findByOrdersNo(orderBase.getOrdersNo());
         String orderNo = zhongAnCrawlerOrder.getOrderNo();
@@ -527,11 +528,11 @@ public class ZhongAnCrawlerRequestImpl implements ZhongAnCrawlerRequest {
         AttributionInformationVo attributionInformationVo = orderStatusVo.getOrder().getAttributionInformationVo();
         //获取配置信息
         ZhongAnCrawlerConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(ZhongAnCrawlerConfigureParameters.class, attributionInformationVo.getConfigInfo());
-        login(zhongAnId, productId);
-        HttpHeaders headers = zhongAnCrawlerRequestComponent.getHeaders(zhongAnId);
+        login(parameters);
+        HttpHeaders headers = zhongAnCrawlerRequestComponent.getHeaders(parameters.getUsername());
         String flowId = parameters.getFlowId();
         if (StringUtils.isEmpty(flowId)) {
-            parameters.setFlowId(zhongAnCrawlerCacheComponent.getFlowId(zhongAnId));
+            parameters.setFlowId(zhongAnCrawlerCacheComponent.getFlowId(parameters.getUsername()));
         }
         ZhongAnCrawlerOrder zhongAnCrawlerOrder = zhongAnCrawlerOrderService.findByOrdersNo(orderStatusVo.getOrder().getOrdersNo());
         // 车牌号

+ 1 - 0
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/service/Impl/ZiJinApiRequestImpl.java

@@ -96,6 +96,7 @@ public class ZiJinApiRequestImpl implements ZiJinApiRequest {
         // 车型查询
         CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
         ModelQueryRequest modelQueryRequest = new ModelQueryRequest(parameters, carInfoVo.getVinNo(), carInfoVo.getBrandName());
+        logger.info("modelQueryRequest:{}", JSON.toJSONString(modelQueryRequest));
         ModelQueryResponse modelQueryResponse = ziJinApiRequestComponent.modelQuery(modelQueryRequest, httpHeaders);
         logger.info("紫金请求/modelQuery车型查询接口,结果为:{}", JSON.toJSONString(modelQueryResponse));
         // 过滤车型

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

@@ -1,11 +1,14 @@
 package com.jzg.quotation.zijin.crawler.build;
 
+import com.alibaba.fastjson.JSON;
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
 import com.jzg.commons.entity.quote.vo.KindInfoVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.commons.entity.quote.vo.RiskInfoVo;
 import com.jzg.commons.entity.quote.vo.aggregated.QuoteResultsVo;
 import com.jzg.quotation.zijin.crawler.entity.response.ZiJinCrawlerQuotationResponse;
+import lombok.extern.slf4j.Slf4j;
+
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -16,6 +19,7 @@ import java.util.stream.Collectors;
  * @author:
  * @date:
  **/
+@Slf4j
 public class ZiJinCrawlerQuoteResultsVoBuild {
 
     /**
@@ -55,6 +59,8 @@ public class ZiJinCrawlerQuoteResultsVoBuild {
         buildPremium(quoteResultsVo, ziJinCrawlerQuotationResponse);
         //设置报价状态:带核保
         quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.WAIT_AUDIT);
+
+        log.info("quoteResultsVo参数的值:{}", JSON.toJSONString(quoteResultsVo));
         return quoteResultsVo;
     }
 

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

@@ -172,7 +172,6 @@ public class ZiJinCrawlerRequestComponent {
         return DESEncryption.decryptStrToObject(daJiaCrawlerBaseResponse.getResult(), ZiJinCrawlerGetSaleInfoResponse.class);
     }
 
-
     /**
      * 查询车辆信息
      *
@@ -222,6 +221,23 @@ public class ZiJinCrawlerRequestComponent {
         return responseEntity.getBody();
     }
 
+    /**
+     * 获取税务登记证号
+     *
+     * @param comCode 保险公司代码
+     * @param headers 请求头
+     * @return ZiJinCrawlerGetTaxRegistryNumberResponse
+     */
+    public ZiJinCrawlerGetTaxRegistryNumberResponse getTaxRegistryNumber(String comCode, HttpHeaders headers) throws IOException {
+        HttpHeaders httpHeaders = setHttpHeaders();
+        String url = RequestUrl.GET_TAX_REGISTRY_NUMBER.getRequestUrl(ziJinCrawlerProperties.getBaseUrl()) + "?comCode=" + comCode;
+        log.info("获取税务登记证号请求URL:{}", url);
+        ResponseEntity<ZiJinCrawlerGetTaxRegistryNumberResponse> responseEntity = requestComponent.post(url, null, ZiJinCrawlerGetTaxRegistryNumberResponse.class, httpHeaders);
+        ZiJinCrawlerGetTaxRegistryNumberResponse response = responseEntity.getBody();
+        log.info("获取税务登记证号响应:{}", JSON.toJSONString(response));
+        return response;
+    }
+
     /**
      * 报价
      *
@@ -241,7 +257,7 @@ public class ZiJinCrawlerRequestComponent {
     /**
      * 保存报价信息
      *
-     * @param ziJinCrawlerSaveQuoteInformationRequest
+     * @param ziJinCrawlerSaveQuoteInfoRequest
      * @param headers
      * @return ZiJinCrawlerSaveQuoteInformationResponse
      */
@@ -417,8 +433,7 @@ public class ZiJinCrawlerRequestComponent {
     /**
      * 下载保单
      *
-     * @param request 下载保单实体
-     * @param headers 请求头
+     * @param ziJinCrawlerDownloadPolicyRequest
      * @return ZiJinCrawlerDownloadResponse
      */
     public ZiJinCrawlerDownloadPolicyResponse electronPolicyIODownload(ZiJinCrawlerDownloadPolicyRequest ziJinCrawlerDownloadPolicyRequest) throws IOException {
@@ -462,7 +477,7 @@ public class ZiJinCrawlerRequestComponent {
         headers.set("Accept", "application/json, text/plain, */*, application/problem+json");
         //headers.set("Accept-Encoding", "gzip, deflate, br, zstd");
         headers.set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
-        headers.set("Authorization", "1B0234C742C12BD632AA5027EB3A501A");
+        headers.set("Authorization", "FD385C99C9B35B64EF84590AACA95380");
         headers.set("Cache-Control", "no-cache");
         headers.set("Connection", "keep-alive");
         headers.set("Content-Length", "23");
@@ -475,7 +490,7 @@ public class ZiJinCrawlerRequestComponent {
         headers.set("Sec-Fetch-Site", "same-origin");
         headers.set("Tokentype", "DEFULT");
         headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36");
-        headers.set("loginToken", "1B0234C742C12BD632AA5027EB3A501A");
+        headers.set("loginToken", "FD385C99C9B35B64EF84590AACA95380");
         headers.set("sec-ch-ua", "\"Google Chrome\";v=\"141\", \"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"141\"");
         headers.set("sec-ch-ua-mobile", "?0");
         headers.set("sec-ch-ua-platform", "\"Windows\"");

+ 6 - 0
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerGetOrderNoRequest.java

@@ -94,4 +94,10 @@ public class ZiJinCrawlerGetOrderNoRequest implements Serializable {
      */
     @JsonProperty("terminalIdType")
     private String terminalIdType;
+
+    /**
+     * IAC车辆代码(行业车型编码)
+     */
+    @JsonProperty("iacVehicleCode")
+    private String iacVehicleCode;
 }

+ 24 - 0
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerQuotationRequest.java

@@ -546,6 +546,30 @@ public class ZiJinCrawlerQuotationRequest implements Serializable {
          */
         @JsonProperty("serviceTimes")
         private String serviceTimes;
+
+        /**
+         * 价值(车损险使用)
+         */
+        @JsonProperty("value")
+        private String value;
+
+        /**
+         * 单位保额
+         */
+        @JsonProperty("unitAmount")
+        private String unitAmount;
+
+        /**
+         * 数量(座位数)
+         */
+        @JsonProperty("quantity")
+        private Integer quantity;
+
+        /**
+         * 绝对免赔率
+         */
+        @JsonProperty("deductibleRate")
+        private Integer deductibleRate;
     }
 
     /**

+ 29 - 0
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerQuoteProcessServiceImpl.java

@@ -136,6 +136,35 @@ public class ZiJinCrawlerQuoteProcessServiceImpl implements ZiJinCrawlerQuotePro
         headers.set("Authorization", authorization);
         headers.set("Content-Type", "application/json");
         headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
+
+
+
+        //获取cookie的值
+//        String cookie = getCookie();
+//        headers.set("Cookie", cookie);
+        // 设置请求头
+        headers.set("Accept", "application/json, text/plain, */*, application/problem+json");
+        //headers.set("Accept-Encoding", "gzip, deflate, br, zstd");
+        headers.set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
+        headers.set("Authorization", "1B0234C742C12BD632AA5027EB3A501A");
+        headers.set("Cache-Control", "no-cache");
+        headers.set("Connection", "keep-alive");
+        headers.set("Content-Length", "23");
+        headers.set("Host", "kscd.zking.com");
+        headers.set("Origin", "https://kscd.zking.com");
+        headers.set("Pragma", "no-cache");
+        headers.set("Referer", "https://kscd.zking.com/app/vehicle/proposal/commonlogin");
+        headers.set("Sec-Fetch-Dest", "empty");
+        headers.set("Sec-Fetch-Mode", "cors");
+        headers.set("Sec-Fetch-Site", "same-origin");
+        headers.set("Tokentype", "DEFULT");
+        //headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36");
+        headers.set("loginToken", "1B0234C742C12BD632AA5027EB3A501A");
+        headers.set("sec-ch-ua", "\"Google Chrome\";v=\"141\", \"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"141\"");
+        headers.set("sec-ch-ua-mobile", "?0");
+        headers.set("sec-ch-ua-platform", "\"Windows\"");
+        headers.set("x-csrf-token", "CrwLEmSfUevAb8PcN7kXff-I");
+
         return headers;
     }
 

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

@@ -7,8 +7,7 @@ import com.google.zxing.NotFoundException;
 import java.util.Arrays;
 
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
-import com.jzg.commons.entity.quote.vo.AttributionInformationVo;
-import com.jzg.commons.entity.quote.vo.QuoteVo;
+import com.jzg.commons.entity.quote.vo.*;
 import com.jzg.commons.entity.quote.vo.aggregated.*;
 import com.jzg.commons.entity.quote.vo.base.LoginBase;
 import com.jzg.quotation.commons.entity.DetectLoginRequest;
@@ -29,9 +28,9 @@ import com.jzg.quotation.zijin.crawler.entity.response.*;
 import com.jzg.quotation.zijin.crawler.service.ZiJinCrawlerRequest;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 import org.jetbrains.annotations.NotNull;
 import org.springframework.http.HttpHeaders;
-import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
 import java.io.IOException;
@@ -88,12 +87,18 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
      */
     @Override
     public QuoteResultsVo quote(QuoteVo quoteVo) {
+        log.info("紫金爬虫");
         log.info("quote入参的值:{}", JSON.toJSONString(quoteVo));
         // 归属信息
         AttributionInformationVo attributionInformationVo = quoteVo.getOrder().getAttributionInformationVo();
         log.info("attributionInformationVo参数的值:{}", JSON.toJSONString(attributionInformationVo));
 
         HttpHeaders headers = ziJinCrawlerQuoteProcessService.getHeaders(attributionInformationVo.getUsername(), attributionInformationVo.getPassword());
+        log.info("headers参数的值:{}", JSON.toJSONString(headers));
+
+        String authorization = "FD385C99C9B35B64EF84590AACA95380";
+        headers.set("Authorization", authorization);
+
         String userCode = ziJinCrawlerCacheComponent.getUserCode(attributionInformationVo.getUsername());
         log.info("userCode:{}", userCode);
 
@@ -104,22 +109,28 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         // 1.2 构建归属信息(机构、套餐、渠道信息)
         //ProposalInfoDTO proposalInfoDTO = boHaiBuildingAttributionInformation.build(parameters, userCode, headers);
         try {
+            String comCode = "2140000601";
+
             // 查询车辆信息
             ZiJinCrawlerCarRequest ziJinCrawlerCarRequest = new ZiJinCrawlerCarRequest();
             ziJinCrawlerCarRequest.setChannelCode("KSCD_PROD");
-            ziJinCrawlerCarRequest.setComCode("2140000601");
+            ziJinCrawlerCarRequest.setComCode(comCode);
             ziJinCrawlerCarRequest.setLicenseNo(quoteVo.getCarInfoVo().getLicenseNo());
             ziJinCrawlerCarRequest.setVin(quoteVo.getCarInfoVo().getVinNo());
             ZiJinCrawlerCarResponse ziJinCrawlerCarResponse = ziJinCrawlerRequestComponent.car(ziJinCrawlerCarRequest, headers);
             log.info("ziJinCrawlerCarResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerCarResponse));
 
             // 车辆和交通查询(获取订单号)
-            ZiJinCrawlerGetOrderNoRequest ziJinCrawlerGetOrderNoRequest = buildGetOrderNoRequest();
+            ZiJinCrawlerGetOrderNoRequest ziJinCrawlerGetOrderNoRequest = buildGetOrderNoRequest(quoteVo, parameters, attributionInformationVo.getConfigInfo(), ziJinCrawlerCarResponse);
+            log.info("ziJinCrawlerGetOrderNoRequest参数的值:{}", JSON.toJSONString(ziJinCrawlerGetOrderNoRequest));
+            String modelCode = ziJinCrawlerGetOrderNoRequest.getModelCode();// 车辆模型代码
+            String iacVehicleCode = ziJinCrawlerGetOrderNoRequest.getIacVehicleCode();//IAC车辆代码(行业车型编码)
             ZiJinCrawlerGetOrderNoResponse ziJinCrawlerGetOrderNoResponse = ziJinCrawlerRequestComponent.getOrderNo(ziJinCrawlerGetOrderNoRequest, headers);
             log.info("ziJinCrawlerGetOrderNoResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerGetOrderNoResponse));
 
             //获取车辆实际价值
             ZiJinCrawlerGetCarActualValueRequest ziJinCrawlerGetCarActualValueRequest = buildGetCarActualValueRequest(quoteVo);
+            log.info("ziJinCrawlerGetCarActualValueRequest参数的值:{}", JSON.toJSONString(ziJinCrawlerGetCarActualValueRequest));
             ZiJinCrawlerGetCarActualValueResponse ziJinCrawlerGetCarActualValueResponse = ziJinCrawlerRequestComponent.getCarActualValue(ziJinCrawlerGetCarActualValueRequest, headers);
             log.info("ziJinCrawlerGetCarActualValueResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerGetCarActualValueResponse));
 
@@ -130,39 +141,48 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
             ziJinCrawlerQuotationRequest.setBaseInfo(baseInfo);
 
             // 设置车主信息
-            ziJinCrawlerQuotationRequest.setCarOwnerInfo(buildCarOwnerInfo());
+            ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo = buildCarOwnerInfo(quoteVo);
+            ziJinCrawlerQuotationRequest.setCarOwnerInfo(carOwnerInfo);
 
-            // 设置保险标志
+            // 设置保险标志(固定"0")
             ziJinCrawlerQuotationRequest.setInsuranceSign("0");
 
             // 设置被保险人列表
-            ziJinCrawlerQuotationRequest.setInsuredList(buildInsuredList());
+            ziJinCrawlerQuotationRequest.setInsuredList(buildInsuredList(quoteVo, carOwnerInfo));
 
-            // 设置订单ID
-            ziJinCrawlerQuotationRequest.setOrderId("8aaa2c189a3d3d79019a48d1745253d1");
-            // 设置订单来源
+            // 设置订单ID - 从getOrderNo接口返回的动态获取
+            ziJinCrawlerQuotationRequest.setOrderId(ziJinCrawlerGetOrderNoResponse.getOrderId());
+            // 设置订单来源(固定"KSCD_PROD")
             ziJinCrawlerQuotationRequest.setOrderOrigin("KSCD_PROD");
-            // 设置需求单校验标志
+            // 设置需求单校验标志(固定"1")
             ziJinCrawlerQuotationRequest.setDemandNoCheckFlag("1");
-            // 设置产品代码
+            // 设置产品代码(固定"CAR20190517"-机动车保险代码)
             ziJinCrawlerQuotationRequest.setProductCode("CAR20190517");
-            // 设置产品名称
+            // 设置产品名称(固定"机动车保险")
             ziJinCrawlerQuotationRequest.setProductName("机动车保险");
 
             // 设置减税信息
-            ziJinCrawlerQuotationRequest.setTaxRelifInfo(buildTaxRelifInfo());
+            //ziJinCrawlerQuotationRequest.setTaxRelifInfo(buildTaxRelifInfo(quoteVo, carOwnerInfo, comCode, headers));
 
             // 设置险种列表
-            ziJinCrawlerQuotationRequest.setItemKindList(buildItemKindList());
+            Double actualValue = null;
+            if (ziJinCrawlerGetCarActualValueResponse != null && StringUtils.hasLength(ziJinCrawlerGetCarActualValueResponse.getActualValue())) {
+                actualValue = Double.parseDouble(ziJinCrawlerGetCarActualValueResponse.getActualValue());
+            }
+            ziJinCrawlerQuotationRequest.setItemKindList(buildItemKindList(quoteVo, actualValue));
 
             // 设置附加保单信息列表
-            ziJinCrawlerQuotationRequest.setCarPolicySubInfoList(buildCarPolicySubInfoList());
+            ziJinCrawlerQuotationRequest.setCarPolicySubInfoList(buildCarPolicySubInfoList(quoteVo));
 
             // 设置车辆信息
-            ziJinCrawlerQuotationRequest.setVehicleInfo(buildVehicleInfo());
+            ziJinCrawlerQuotationRequest.setVehicleInfo(buildVehicleInfo(quoteVo, actualValue, modelCode, iacVehicleCode));
 
             // 设置盈利数据列表
-            ziJinCrawlerQuotationRequest.setProfitDataList(buildProfitDataList());
+            ziJinCrawlerQuotationRequest.setProfitDataList(buildProfitDataList(quoteVo));
+
+
+
+
 
             // 设置税务字段
             ziJinCrawlerQuotationRequest.setTaxFields("identifyNumber,taxpayerIdentifier,taxpayerName,taxRegistryNumber");
@@ -171,6 +191,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
             // 设置车载设备保费列表(空列表)
             ziJinCrawlerQuotationRequest.setCarDevicePremiumDtoList(new ArrayList<>());
 
+            log.info("ziJinCrawlerQuotationRequest参数的值:{}", JSON.toJSONString(ziJinCrawlerQuotationRequest));
             ZiJinCrawlerQuotationResponse ziJinCrawlerQuotationResponse = ziJinCrawlerRequestComponent.quotation(ziJinCrawlerQuotationRequest, headers);
             log.info("ziJinCrawlerQuotationResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerQuotationResponse));
 
@@ -182,7 +203,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
                 //报价成功
                 //保存报价信息
                 ZiJinCrawlerSaveQuoteInfoRequest ziJinCrawlerSaveQuoteInfoRequest = buildSaveQuoteInfoRequest();
-
+                log.info("ziJinCrawlerSaveQuoteInfoRequest参数的值:{}", JSON.toJSONString(ziJinCrawlerSaveQuoteInfoRequest));
                 ZiJinCrawlerSaveQuoteInfoResponse ziJinCrawlerSaveQuoteInfoResponse = ziJinCrawlerRequestComponent.saveQuoteInformation(ziJinCrawlerSaveQuoteInfoRequest, headers);
                 log.info("ziJinCrawlerSaveQuoteInfoResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerSaveQuoteInfoResponse));
 
@@ -190,6 +211,7 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
                 ZiJinCrawlerSaveProposalRequest ziJinCrawlerSaveProposalRequest = new  ZiJinCrawlerSaveProposalRequest();
                 ziJinCrawlerSaveProposalRequest.setOrderNo(ziJinCrawlerGetOrderNoResponse.getOrderNo());
                 ziJinCrawlerSaveProposalRequest.setProposalCheckNo(ziJinCrawlerQuotationResponse.getBasePart().getProposalCheckNo());
+                log.info("ziJinCrawlerSaveProposalRequest参数的值:{}", JSON.toJSONString(ziJinCrawlerSaveProposalRequest));
                 ZiJinCrawlerSaveProposalResponse ziJinCrawlerSaveProposalResponse = ziJinCrawlerRequestComponent.saveProposal(ziJinCrawlerSaveProposalRequest, headers);
                 log.info("ziJinCrawlerSaveProposalResponse参数的值:{}", JSON.toJSONString(ziJinCrawlerSaveProposalResponse));
 
@@ -480,24 +502,130 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
      *
      * @return ZiJinCrawlerGetOrderNoRequest
      */
-    private ZiJinCrawlerGetOrderNoRequest buildGetOrderNoRequest() {
+//    private ZiJinCrawlerGetOrderNoRequest buildGetOrderNoRequest() {
+//        ZiJinCrawlerGetOrderNoRequest request = new ZiJinCrawlerGetOrderNoRequest();
+//        request.setBrandName("荣威CSA6452NEAQ多用途乘用车");
+//        request.setLicenseNo("晋HJW581");
+//        request.setOperatorCode("214000151");
+//        request.setOrderOrigin("KSCD_PROD");
+//        request.setProposalAreaCode("140000");
+//        request.setProposalCityCode("140000");
+//        request.setUserComCode("2140000601");
+//        request.setVinNo("LSJA24U69MS091895");
+//        request.setModelCode("RWD1598SQQ");
+//        request.setProductCode("CAR20190517");
+//        request.setProductName("机动车保险");
+//        request.setTerminalId("KSCD");
+//        request.setTerminalIdType("Vue-PC");
+//        return request;
+//    }
+
+
+    /**
+     * 构建获取订单号请求对象
+     * 参数来源对照Python get_orderid_orderno方法:
+     * brandName -> 车型匹配后的vehicleName
+     * licenseNo -> quoteVo车牌号
+     * operatorCode -> 配置参数userCode
+     * proposalAreaCode -> configInfo中的proposalAreaCode
+     * proposalCityCode -> configInfo中的proposalCityCode
+     * userComCode -> 配置参数comCode
+     * vinNo -> quoteVo车架号
+     * modelCode -> 车型匹配后的vehicleCode
+     *
+     * @param quoteVo 报价实体
+     * @param parameters 配置参数
+     * @param configInfo 归属配置信息
+     * @param carResponse 车辆查询响应
+     * @return ZiJinCrawlerGetOrderNoRequest
+     */
+    private ZiJinCrawlerGetOrderNoRequest buildGetOrderNoRequest(QuoteVo quoteVo, ZiJinCrawlerConfigureParameters parameters,
+                                                                  Map<String, String> configInfo, ZiJinCrawlerCarResponse carResponse) {
         ZiJinCrawlerGetOrderNoRequest request = new ZiJinCrawlerGetOrderNoRequest();
-        request.setBrandName("荣威CSA6452NEAQ多用途乘用车");
-        request.setLicenseNo("晋HJW581");
-        request.setOperatorCode("214000151");
+
+        // 从车辆查询响应中匹配车型,获取brandName和modelCode
+        // 对应Python: brandName = PPcarinfo['vehicleName'], modelCode = PPcarinfo['vehicleCode']
+        String brandName = "";
+        String modelCode = "";
+        String iacVehicleCode = "";
+        if (carResponse != null && carResponse.getVehicleModelInfoList() != null && !carResponse.getVehicleModelInfoList().isEmpty()) {
+            // 按purchasePrice和seatCount匹配车型,与Python逻辑一致
+            String purchasePrice = quoteVo.getCarInfoVo().getPurchasePrice();//新车购置价[元]
+            String seatCount = quoteVo.getCarInfoVo().getSeatCount();//座位数[座]
+            ZiJinCrawlerCarResponse.VehicleModelInfo matchedModel = null; //车辆型号信息类
+            for (ZiJinCrawlerCarResponse.VehicleModelInfo model : carResponse.getVehicleModelInfoList()) {
+                if (purchasePrice != null && model.getPurchasePrice() != null
+                        && Double.parseDouble(model.getPurchasePrice()) == Double.parseDouble(purchasePrice)
+                        && model.getSeat() != null && seatCount != null
+                        && Double.parseDouble(model.getSeat()) >= Double.parseDouble(seatCount)) {
+                    matchedModel = model;
+                    break;
+                }
+            }
+            // 如果没有匹配到,且只有一个车型,则使用该车型(与Python逻辑一致)
+            if (matchedModel == null && carResponse.getVehicleModelInfoList().size() == 1) {
+                ZiJinCrawlerCarResponse.VehicleModelInfo onlyModel = carResponse.getVehicleModelInfoList().get(0);
+                if (onlyModel.getSeat() != null && seatCount != null
+                        && Double.parseDouble(onlyModel.getSeat()) >= Double.parseDouble(seatCount)) {
+                    matchedModel = onlyModel;
+                }
+            }
+            if(matchedModel == null){
+                List<ZiJinCrawlerCarResponse.VehicleModelInfo> vehicleModelInfoList = carResponse.getVehicleModelInfoList();
+                List<String> vehicleNameList =vehicleModelInfoList.stream().map(ZiJinCrawlerCarResponse.VehicleModelInfo::getVehicleName).distinct().collect(Collectors.toList());
+                List<String> vehicleCodeList =vehicleModelInfoList.stream().map(ZiJinCrawlerCarResponse.VehicleModelInfo::getVehicleCode).distinct().collect(Collectors.toList());
+                List<String> iacVehicleCodeList =vehicleModelInfoList.stream().map(ZiJinCrawlerCarResponse.VehicleModelInfo::getIacVehicleCode).distinct().collect(Collectors.toList());
+
+                if(CollectionUtils.isNotEmpty(vehicleNameList)
+                        && CollectionUtils.isNotEmpty(vehicleCodeList)
+                        && CollectionUtils.isNotEmpty(iacVehicleCodeList)
+                        && vehicleNameList.size() == 1
+                        && vehicleCodeList.size() == 1
+                        && iacVehicleCodeList.size() == 1
+                ){
+                    matchedModel = new ZiJinCrawlerCarResponse.VehicleModelInfo();
+                    matchedModel.setVehicleName(vehicleNameList.get(0));
+                    matchedModel.setVehicleCode(vehicleCodeList.get(0));
+                    matchedModel.setIacVehicleCode(iacVehicleCodeList.get(0));
+                }
+            }
+
+            if (matchedModel != null) {
+                brandName = matchedModel.getVehicleName();
+                modelCode = matchedModel.getVehicleCode();
+                iacVehicleCode = matchedModel.getIacVehicleCode();
+            }
+        }
+
+        request.setBrandName(brandName);
+        request.setLicenseNo(quoteVo.getCarInfoVo().getLicenseNo());
+        // operatorCode对应Python: operatorCode = self.baseInfo['handler1Code']
+        request.setOperatorCode(parameters.getUserCode());
         request.setOrderOrigin("KSCD_PROD");
-        request.setProposalAreaCode("140000");
-        request.setProposalCityCode("140000");
-        request.setUserComCode("2140000601");
-        request.setVinNo("LSJA24U69MS091895");
-        request.setModelCode("RWD1598SQQ");
+        // proposalAreaCode对应Python: proposalAreaCode = self.get_areacode(userComCode)
+        request.setProposalAreaCode(configInfo.getOrDefault("proposalAreaCode", ""));
+        // proposalCityCode对应Python: proposalCityCode = proposalAreaCode
+        request.setProposalCityCode(configInfo.getOrDefault("proposalCityCode", configInfo.getOrDefault("proposalAreaCode", "")));
+        // userComCode对应Python: userComCode = self.baseInfo['comCode']
+        request.setUserComCode(parameters.getComCode());
+        request.setVinNo(quoteVo.getCarInfoVo().getVinNo());
+        request.setModelCode(modelCode);
         request.setProductCode("CAR20190517");
         request.setProductName("机动车保险");
         request.setTerminalId("KSCD");
         request.setTerminalIdType("Vue-PC");
+
+        //
+        //request.setBrandName("哈弗CC6460AZ04B多用途乘用车");//品牌名称
+        //request.setModelCode("CC6460AZ04B");//车型代码
+        request.setOperatorCode("214000151");//操作员编号
+        request.setUserComCode("2140000601");//用户公司代码
+        request.setIacVehicleCode(iacVehicleCode);//IAC车辆代码(行业车型编码)
+
         return request;
     }
 
+
     /**
      * 构建获取车辆实际价值请求对象
      *
@@ -566,57 +694,218 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
      *
      * @return ZiJinCrawlerQuotationRequest.CarOwnerInfo
      */
-    private ZiJinCrawlerQuotationRequest.CarOwnerInfo buildCarOwnerInfo() {
+//    private ZiJinCrawlerQuotationRequest.CarOwnerInfo buildCarOwnerInfo() {
+//        ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo = new ZiJinCrawlerQuotationRequest.CarOwnerInfo();
+//        carOwnerInfo.setCarOwner("王婧");//车主姓名
+//        carOwnerInfo.setOwnerIdentifyNumber("14092519990322002X");//车主证件号码
+//        carOwnerInfo.setOwnerIdentifyType("01");//车主证件类型(01-身份证)
+//        carOwnerInfo.setVehicleOwnerNature("1");//车主性质(1-个人)
+//        return carOwnerInfo;
+//    }
+
+
+    /**
+     * 构建车主信息对象
+     * 参数来源对照Python get_owner_info方法:
+     * carOwner -> quoteVo车主姓名
+     * ownerIdentifyNumber -> quoteVo车主证件号码
+     * ownerIdentifyType -> 根据证件类型映射(01-身份证)
+     * vehicleOwnerNature -> 根据人员类型映射(1-个人, 5-企业)
+     * ownerAddress -> quoteVo车主地址
+     *
+     * @param quoteVo 报价实体
+     * @return ZiJinCrawlerQuotationRequest.CarOwnerInfo
+     */
+    private ZiJinCrawlerQuotationRequest.CarOwnerInfo buildCarOwnerInfo(QuoteVo quoteVo) {
         ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo = new ZiJinCrawlerQuotationRequest.CarOwnerInfo();
-        carOwnerInfo.setCarOwner("王婧");
-        carOwnerInfo.setOwnerIdentifyNumber("14092519990322002X");
-        carOwnerInfo.setOwnerIdentifyType("01");
-        carOwnerInfo.setVehicleOwnerNature("1");
+        
+        CustomerInfoVo ownersInfo = quoteVo.getOwnersInfo();
+        if (ownersInfo != null) {
+            carOwnerInfo.setCarOwner(ownersInfo.getName());//车主姓名
+            carOwnerInfo.setOwnerIdentifyNumber(ownersInfo.getIdentifyNumber());//车主证件号码
+            
+            // 根据证件类型映射车主性质和证件类型代码
+            String identifyType = ownersInfo.getIdentifyType();
+            String personType = ownersInfo.getPersonType();
+            
+            // 证件类型映射,参考Python get_owner_i方法
+            // 个人类型(1) -> vehicleOwnerNature="1"
+            // 企业类型(2) -> vehicleOwnerNature="5"
+            if ("2".equals(personType)) {
+                // 企业
+                carOwnerInfo.setVehicleOwnerNature("5");
+                // 企业证件类型映射
+                carOwnerInfo.setOwnerIdentifyType(mapEnterpriseIdentifyType(identifyType));
+            } else {
+                // 个人(默认)
+                carOwnerInfo.setVehicleOwnerNature("1");
+                carOwnerInfo.setOwnerIdentifyType("01");//01-身份证
+            }
+        }
+        
         return carOwnerInfo;
     }
 
+
+    /**
+     * 企业证件类型映射
+     * 参考Python get_owner_i方法中的IDType映射
+     *
+     * @param identifyType 证件类型
+     * @return 映射后的证件类型代码
+     */
+    private String mapEnterpriseIdentifyType(String identifyType) {
+        if (identifyType == null) {
+            return "11";//默认工商注册号码
+        }
+        // 证件类型映射:工商注册号码->11, 统一社会信用代码->73, 组织机构代码->71
+        switch (identifyType) {
+            case "11": //工商注册号码
+            case "2":  //企业类型默认
+                return "11";
+            case "73": //统一社会信用代码
+                return "73";
+            case "71": //组织机构代码
+                return "71";
+            default:
+                return "11";//默认工商注册号码
+        }
+    }
+
+//    /**
+//     * 构建被保险人列表
+//     *
+//     * @return List<ZiJinCrawlerQuotationRequest.InsuredList>
+//     */
+//    private List<ZiJinCrawlerQuotationRequest.InsuredList> buildInsuredList() {
+//        List<ZiJinCrawlerQuotationRequest.InsuredList> insuredList = new ArrayList<>();
+//
+//        // 第一个被保险人
+//        ZiJinCrawlerQuotationRequest.InsuredList insured1 = new ZiJinCrawlerQuotationRequest.InsuredList();
+//        insured1.setInsuredName("王婧");
+//        insured1.setInsuredNature("3");
+//        insured1.setIdentifyType("01");
+//        insured1.setIdentifyNumber("14092519990322002X");
+//        insured1.setSex("2");
+//        insured1.setInsuredType("1");
+//        insured1.setMobile("18840186946");
+//        insured1.setPostCode("030053");
+//        insured1.setInsuredFlag(2);
+//        insuredList.add(insured1);
+//
+//        // 第二个被保险人
+//        ZiJinCrawlerQuotationRequest.InsuredList insured2 = new ZiJinCrawlerQuotationRequest.InsuredList();
+//        insured2.setInsuredName("王婧");
+//        insured2.setInsuredNature("3");
+//        insured2.setIdentifyType("01");
+//        insured2.setIdentifyNumber("14092519990322002X");
+//        insured2.setSex("2");
+//        insured2.setInsuredType("1");
+//        insured2.setMobile("18840186946");
+//        insured2.setPostCode("030053");
+//        insured2.setInsuredFlag(1);
+//        insuredList.add(insured2);
+//        return insuredList;
+//    }
+
+    /**
+     * 构建被保险人列表
+     *
+     * @return List<ZiJinCrawlerQuotationRequest.InsuredList>
+     */
     /**
      * 构建被保险人列表
+     * 参数来源对照Python get_insuredList_info方法:
+     * insuredList包含两个对象:投保人(insuredFlag=2)和被保人(insuredFlag=1)
      *
+     * @param quoteVo 报价实体
+     * @param carOwnerInfo 车主信息(用于判断与车主关系)
      * @return List<ZiJinCrawlerQuotationRequest.InsuredList>
      */
-    private List<ZiJinCrawlerQuotationRequest.InsuredList> buildInsuredList() {
+    private List<ZiJinCrawlerQuotationRequest.InsuredList> buildInsuredList(QuoteVo quoteVo, 
+            ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo) {
         List<ZiJinCrawlerQuotationRequest.InsuredList> insuredList = new ArrayList<>();
 
-        // 第一个被保险人
-        ZiJinCrawlerQuotationRequest.InsuredList insured1 = new ZiJinCrawlerQuotationRequest.InsuredList();
-        insured1.setInsuredName("王婧");
-        insured1.setInsuredNature("3");
-        insured1.setIdentifyType("01");
-        insured1.setIdentifyNumber("14092519990322002X");
-        insured1.setSex("2");
-        insured1.setInsuredType("1");
-        insured1.setMobile("18840186946");
-        insured1.setPostCode("030053");
-        insured1.setInsuredFlag(2);
-        insuredList.add(insured1);
-
-        // 第二个被保险人
-        ZiJinCrawlerQuotationRequest.InsuredList insured2 = new ZiJinCrawlerQuotationRequest.InsuredList();
-        insured2.setInsuredName("王婧");
-        insured2.setInsuredNature("3");
-        insured2.setIdentifyType("01");
-        insured2.setIdentifyNumber("14092519990322002X");
-        insured2.setSex("2");
-        insured2.setInsuredType("1");
-        insured2.setMobile("18840186946");
-        insured2.setPostCode("030053");
-        insured2.setInsuredFlag(1);
-        insuredList.add(insured2);
+        CustomerInfoVo policyHolderInfo = quoteVo.getPolicyHolderInfo();//投保人
+        CustomerInfoVo insuredPersonInfo = quoteVo.getInsuredPersonInfo();//被保人
+        
+        // 获取车主性质,用于判断投保人/被保人类型
+        String vehicleOwnerNature = carOwnerInfo != null ? carOwnerInfo.getVehicleOwnerNature() : "1";
+        
+        // 1. 构建投保人信息 (insuredFlag=2)
+        if (policyHolderInfo != null) {
+            ZiJinCrawlerQuotationRequest.InsuredList policyHolder = new ZiJinCrawlerQuotationRequest.InsuredList();
+            buildInsuredItem(policyHolder, policyHolderInfo, 2, vehicleOwnerNature, 
+                    carOwnerInfo != null ? carOwnerInfo.getOwnerIdentifyNumber() : null);
+            insuredList.add(policyHolder);
+        }
+
+        // 2. 构建被保人信息 (insuredFlag=1)
+        if (insuredPersonInfo != null) {
+            ZiJinCrawlerQuotationRequest.InsuredList insuredPerson = new ZiJinCrawlerQuotationRequest.InsuredList();
+            buildInsuredItem(insuredPerson, insuredPersonInfo, 1, vehicleOwnerNature, 
+                    carOwnerInfo != null ? carOwnerInfo.getOwnerIdentifyNumber() : null);
+            insuredList.add(insuredPerson);
+        }
+
         return insuredList;
     }
 
+    /**
+     * 构建单个被保险人对象
+     *
+     * @param insuredItem 被保险人对象
+     * @param customerInfo 客户信息
+     * @param insuredFlag 被保险人标志(1-被保人, 2-投保人)
+     * @param vehicleOwnerNature 车主性质(1-个人, 5-企业)
+     * @param ownerIdentifyNumber 车主证件号码(用于判断与车主关系)
+     */
+    private void buildInsuredItem(ZiJinCrawlerQuotationRequest.InsuredList insuredItem, 
+            CustomerInfoVo customerInfo, int insuredFlag, String vehicleOwnerNature, 
+            String ownerIdentifyNumber) {
+        insuredItem.setInsuredName(customerInfo.getName());
+        insuredItem.setIdentifyNumber(customerInfo.getIdentifyNumber());
+        
+        // 证件类型映射
+        String identifyType = customerInfo.getIdentifyType();
+        String personType = customerInfo.getPersonType();
+        if ("2".equals(personType)) {
+            // 企业
+            insuredItem.setIdentifyType(mapEnterpriseIdentifyType(identifyType));
+        } else {
+            // 个人(默认)
+            insuredItem.setIdentifyType("01");//01-身份证
+        }
+        
+        // 性别映射
+        String gender = customerInfo.getGender();
+        insuredItem.setSex("男".equals(gender) ? "1" : "2");
+        
+        // 根据车主性质设置投保人/被保人类型
+        // 个人车主("1"): 投保人/被保人都是自然人
+        // 企业车主("5"): 投保人是法人,被保人是自然人
+        if ("5".equals(vehicleOwnerNature) && insuredFlag == 2) {
+            // 企业车主的投保人
+            insuredItem.setInsuredNature("4");//4-法人或其他组织
+            insuredItem.setInsuredType("2");
+        } else {
+            // 个人车主或被保人
+            insuredItem.setInsuredNature("3");//3-自然人
+            insuredItem.setInsuredType("1");
+        }
+        
+        insuredItem.setMobile(customerInfo.getMobile());
+        insuredItem.setPostCode(StringUtils.hasLength(customerInfo.getPostCode()) ? 
+                customerInfo.getPostCode() : "030000");
+        insuredItem.setInsuredFlag(insuredFlag);
+    }
+
     /**
      * 构建减税信息对象
      *
      * @return ZiJinCrawlerQuotationRequest.TaxRelifInfo
      */
-    private ZiJinCrawlerQuotationRequest.TaxRelifInfo buildTaxRelifInfo() {
+    private ZiJinCrawlerQuotationRequest.TaxRelifInfo buildTaxRelifInfo2() {
         ZiJinCrawlerQuotationRequest.TaxRelifInfo taxRelifInfo = new ZiJinCrawlerQuotationRequest.TaxRelifInfo();
         taxRelifInfo.setTaxRelifFlag("1");
         taxRelifInfo.setTaxpayerName("王婧");
@@ -627,167 +916,686 @@ public class ZiJinCrawlerRequestImpl implements ZiJinCrawlerRequest {
         return taxRelifInfo;
     }
 
+
+    /**
+     * 构建减税信息对象
+     *
+     * @param quoteVo 报价实体
+     * @param carOwnerInfo 车主信息
+     * @param comCode 保险公司代码
+     * @param headers 请求头
+     * @return ZiJinCrawlerQuotationRequest.TaxRelifInfo
+     */
+    private ZiJinCrawlerQuotationRequest.TaxRelifInfo buildTaxRelifInfo(QuoteVo quoteVo, 
+            ZiJinCrawlerQuotationRequest.CarOwnerInfo carOwnerInfo, String comCode, HttpHeaders headers) {
+        ZiJinCrawlerQuotationRequest.TaxRelifInfo taxRelifInfo = new ZiJinCrawlerQuotationRequest.TaxRelifInfo();
+        
+        // 只有投保交强险时才构建完整的税务信息
+        // 交强险riskCode为"0507"
+        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
+        
+        // 获取税务登记证号
+        String taxRegistryNumber = "";
+        try {
+            ZiJinCrawlerGetTaxRegistryNumberResponse taxResponse = ziJinCrawlerRequestComponent.getTaxRegistryNumber(comCode, headers);
+            if (taxResponse != null && StringUtils.hasLength(taxResponse.getData())) {
+                taxRegistryNumber = taxResponse.getData();
+            }
+        } catch (Exception e) {
+            log.error("获取税务登记证号失败: {}", e.getMessage());
+        }
+        
+        // 设置税务信息
+        taxRelifInfo.setTaxRelifFlag("1");// 1 正常缴税 2 免税 3 减税 4 已完税 5 不征
+        
+        if (carOwnerInfo != null) {
+            taxRelifInfo.setTaxpayerName(carOwnerInfo.getCarOwner());//纳税人姓名
+            taxRelifInfo.setTaxpayerIdentifier(carOwnerInfo.getOwnerIdentifyType());//纳税人标识(证件类型)
+            taxRelifInfo.setIdentifyNumber(carOwnerInfo.getOwnerIdentifyNumber());//证件号码
+        }
+        
+        taxRelifInfo.setTaxRegistryNumber(taxRegistryNumber);//税务登记证号
+        
+        // 整备质量(公斤转吨)
+        if (carInfoVo != null && StringUtils.hasLength(carInfoVo.getCompleteKerbMass())) {
+            String completeKerbMassTon = carInfoVo.completeKerbMassToTonCount();
+            taxRelifInfo.setCompleteKerbMass(completeKerbMassTon);
+        }
+        
+        return taxRelifInfo;
+    }
+
+
     /**
      * 构建险种列表
+     * 根据交强险和商业险的险种信息动态构建险种列表
      *
+     * @param quoteVo 报价实体
+     * @param actualValue 车辆实际价值
      * @return List<ZiJinCrawlerQuotationRequest.ItemKindList>
      */
-    private List<ZiJinCrawlerQuotationRequest.ItemKindList> buildItemKindList() {
+    private List<ZiJinCrawlerQuotationRequest.ItemKindList> buildItemKindList(QuoteVo quoteVo, Double actualValue) {
         List<ZiJinCrawlerQuotationRequest.ItemKindList> itemKindList = new ArrayList<>();
+        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
+        List<KindInfoVo> kindInfoVoList = quoteVo.getKindInfoVo();
+        
+        // 获取座位数
+        int seatCount = 5;
+        if (carInfoVo != null && StringUtils.hasLength(carInfoVo.getSeatCount())) {
+            seatCount = Integer.parseInt(carInfoVo.getSeatCount());
+        }
 
-        // 交通事故强制责任险
-        ZiJinCrawlerQuotationRequest.ItemKindList itemKind1 = new ZiJinCrawlerQuotationRequest.ItemKindList();
-        itemKind1.setAmount("200000");
-        itemKind1.setKindCode("BZ");
-        itemKind1.setKindName("交通事故强制责任险");
-        itemKind1.setRiskCode("0590");
-        itemKind1.setBenchMarkPremium("950.0000");
-        itemKind1.setBasePremium("950.0000");
-        itemKindList.add(itemKind1);
-
-        // 机动车第三者责任保险
-        ZiJinCrawlerQuotationRequest.ItemKindList itemKind2 = new ZiJinCrawlerQuotationRequest.ItemKindList();
-        itemKind2.setAmount(2000000);
-        itemKind2.setKindCode("B");
-        itemKind2.setKindName("机动车第三者责任保险");
-        itemKind2.setRiskCode("050A");
-        itemKind2.setBenchMarkPremium("687.7600");
-        itemKind2.setBasePremium("515.8200");
-        itemKindList.add(itemKind2);
-
-        // 附加医保外用药责任险
-        ZiJinCrawlerQuotationRequest.ItemKindList itemKind3 = new ZiJinCrawlerQuotationRequest.ItemKindList();
-        itemKind3.setAmount("20000");
-        itemKind3.setKindCode("S1");
-        itemKind3.setKindName("附加医保外用药责任险(机动车第三者责任保险)");
-        itemKind3.setRiskCode("050A");
-        itemKind3.setBenchMarkPremium("28.3100");
-        itemKind3.setBasePremium("21.2300");
-        itemKindList.add(itemKind3);
+        // 1. 检查是否有交强险(riskCode='0507')
+        if (quoteVo.getCiRiskInfoVo() != null && "0507".equals(quoteVo.getCiRiskInfoVo().getRiskCode())) {
+            ZiJinCrawlerQuotationRequest.ItemKindList ciItem = new ZiJinCrawlerQuotationRequest.ItemKindList();
+            ciItem.setAmount("200000");
+            ciItem.setKindCode("BZ");
+            ciItem.setKindName("交通事故强制责任险");
+            ciItem.setRiskCode("0590");
+            itemKindList.add(ciItem);
+        }
+
+        // 2. 检查是否有商业险(riskCode='0510')
+        if (quoteVo.getBiRiskInfoVo() != null && "0510".equals(quoteVo.getBiRiskInfoVo().getRiskCode())) {
+            // 根据商业险险种列表构建
+            if (kindInfoVoList != null && !kindInfoVoList.isEmpty()) {
+                for (KindInfoVo kindItem : kindInfoVoList) {
+                    String zgKindCode = kindItem.getKindCode();
+                    ZiJinCrawlerQuotationRequest.ItemKindList zjItem = buildZiJinKindItem(zgKindCode, kindItem, seatCount, actualValue);
+                    if (zjItem != null) {
+                        itemKindList.add(zjItem);
+                    }
+                }
+            }
+        }
 
-        // 道路救援服务特约条款
-        ZiJinCrawlerQuotationRequest.ItemKindList itemKind4 = new ZiJinCrawlerQuotationRequest.ItemKindList();
-        itemKind4.setKindCode("T1");
-        itemKind4.setKindName("道路救援服务特约条款");
-        itemKind4.setRiskCode("050A");
-        itemKind4.setServiceTimes("2");
-        itemKind4.setBenchMarkPremium("0.0000");
-        itemKind4.setBasePremium("0.0000");
-        itemKindList.add(itemKind4);
         return itemKindList;
     }
 
+    /**
+     * 根据平台险种代码构建紫金险种对象
+     *
+     * @param zgKindCode 平台险种代码
+     * @param kindItem 平台险种信息
+     * @param seatCount 座位数
+     * @param actualValue 车辆实际价值
+     * @return ZiJinCrawlerQuotationRequest.ItemKindList
+     */
+    private ZiJinCrawlerQuotationRequest.ItemKindList buildZiJinKindItem(String zgKindCode, KindInfoVo kindItem, 
+            int seatCount, Double actualValue) {
+        ZiJinCrawlerQuotationRequest.ItemKindList item = new ZiJinCrawlerQuotationRequest.ItemKindList();
+        
+        switch (zgKindCode) {
+            case "A": // 机动车损失保险
+                item.setKindCode("A");
+                item.setKindName("机动车损失保险");
+                item.setRiskCode("050A");
+                item.setAmount(actualValue != null ? actualValue.longValue() : 0);
+                item.setValue("0");
+                break;
+                
+            case "B": // 机动车第三者责任保险
+                item.setKindCode("B");
+                item.setKindName("机动车第三者责任保险");
+                item.setRiskCode("050A");
+                if (StringUtils.hasLength(kindItem.getAmount())) {
+                    item.setAmount(Long.parseLong(kindItem.getAmount()));
+                }
+                break;
+                
+            case "D3": // 机动车车上人员责任保险(司机)
+                item.setKindCode("D3");
+                item.setKindName("机动车车上人员责任保险(司机)");
+                item.setRiskCode("050A");
+                if (StringUtils.hasLength(kindItem.getAmount())) {
+                    item.setAmount(Long.parseLong(kindItem.getAmount()));
+                    item.setUnitAmount(kindItem.getAmount());
+                }
+                item.setQuantity(1);
+                break;
+                
+            case "D4": // 机动车车上人员责任保险(乘客)
+                item.setKindCode("D4");
+                item.setKindName("机动车车上人员责任保险(乘客)");
+                item.setRiskCode("050A");
+                if (StringUtils.hasLength(kindItem.getAmount())) {
+                    long perSeatAmount = Long.parseLong(kindItem.getAmount());
+                    int passengerCount = seatCount - 1;
+                    item.setAmount(perSeatAmount * passengerCount);
+                    item.setUnitAmount(kindItem.getAmount());
+                    item.setQuantity(passengerCount);
+                }
+                break;
+                
+            case "L": // 附加车身划痕损失险
+                item.setKindCode("L");
+                item.setKindName("附加车身划痕损失险");
+                item.setRiskCode("050A");
+                item.setAmount(kindItem.getAmount());
+                break;
+                
+            case "BD": // 附加法定节假日限额翻倍险
+                item.setKindCode("B2");
+                item.setKindName("附加法定节假日限额翻倍险");
+                item.setRiskCode("050A");
+                if (StringUtils.hasLength(kindItem.getAmount())) {
+                    item.setAmount(Long.parseLong(kindItem.getAmount()));
+                }
+                break;
+                
+            case "SY_FJ_YBW1": // 附加医保外用药责任险(机动车第三者责任保险)
+                item.setKindCode("S1");
+                item.setKindName("附加医保外用药责任险(机动车第三者责任保险)");
+                item.setRiskCode("050A");
+                item.setAmount(kindItem.getAmount());
+                break;
+                
+            case "SY_FJ_YBW3": // 附加医保外用药责任险(司机)
+                item.setKindCode("S2");
+                item.setKindName("附加医保外用药责任险(机动车车上人员责任保险(司机))");
+                item.setRiskCode("050A");
+                if (StringUtils.hasLength(kindItem.getAmount())) {
+                    item.setAmount(Long.parseLong(kindItem.getAmount()));
+                }
+                break;
+                
+            case "SY_FJ_YBW2": // 附加医保外用药责任险(乘客)
+                item.setKindCode("S3");
+                item.setKindName("附加医保外用药责任险(机动车车上人员责任保险(乘客))");
+                item.setRiskCode("050A");
+                if (StringUtils.hasLength(kindItem.getAmount())) {
+                    long perSeatAmount = Long.parseLong(kindItem.getAmount());
+                    int passengerCount = seatCount - 1;
+                    item.setAmount(perSeatAmount * passengerCount);
+                    item.setUnitAmount(kindItem.getAmount());
+                    item.setQuantity(passengerCount);
+                }
+                break;
+                
+            case "TY1": // 道路救援服务特约条款
+                item.setKindCode("T1");
+                item.setKindName("道路救援服务特约条款");
+                item.setRiskCode("050A");
+                item.setServiceTimes(StringUtils.hasLength(kindItem.getServiceTimes()) ? 
+                        kindItem.getServiceTimes() : kindItem.getAmount());
+                break;
+                
+            case "TY2": // 车辆安全检测特约条款
+                item.setKindCode("T2");
+                item.setKindName("车辆安全检测特约条款");
+                item.setRiskCode("050A");
+                item.setServiceTimes(StringUtils.hasLength(kindItem.getServiceTimes()) ? 
+                        kindItem.getServiceTimes() : kindItem.getAmount());
+                break;
+                
+            case "TY3": // 代为驾驶服务特约条款
+                item.setKindCode("T3");
+                item.setKindName("代为驾驶服务特约条款");
+                item.setRiskCode("050A");
+                item.setServiceTimes(StringUtils.hasLength(kindItem.getServiceTimes()) ? 
+                        kindItem.getServiceTimes() : kindItem.getAmount());
+                break;
+                
+            case "TY4": // 代为送检服务特约条款
+                item.setKindCode("T4");
+                item.setKindName("代为送检服务特约条款");
+                item.setRiskCode("050A");
+                item.setServiceTimes(StringUtils.hasLength(kindItem.getServiceTimes()) ? 
+                        kindItem.getServiceTimes() : kindItem.getAmount());
+                break;
+                
+            case "MJ1": // 附加绝对免赔率特约险(车损险)
+                item.setKindCode("FA");
+                item.setKindName("附加绝对免赔率特约险(机动车损失保险)");
+                item.setRiskCode("050A");
+                item.setAmount(0);
+                if (StringUtils.hasLength(kindItem.getDeductibleRate())) {
+                    // 提取数字部分
+                    String deductibleRate = kindItem.getDeductibleRate().replaceAll("[^0-9]", "");
+                    item.setDeductibleRate(Integer.parseInt(deductibleRate));
+                }
+                break;
+                
+            case "MJ2": // 附加绝对免赔率特约条款(三者险)
+                item.setKindCode("FB");
+                item.setKindName("附加绝对免赔率特约险(机动车第三者责任保险)");
+                item.setRiskCode("050A");
+                item.setAmount(0);
+                if (StringUtils.hasLength(kindItem.getDeductibleRate())) {
+                    String deductibleRate = kindItem.getDeductibleRate().replaceAll("[^0-9]", "");
+                    item.setDeductibleRate(Integer.parseInt(deductibleRate));
+                }
+                break;
+                
+            case "MJ3": // 附加绝对免赔率特约险(司机)
+                item.setKindCode("FD3");
+                item.setKindName("附加绝对免赔率特约险(机动车车上人员责任保险(司机))");
+                item.setRiskCode("050A");
+                item.setAmount(0);
+                if (StringUtils.hasLength(kindItem.getDeductibleRate())) {
+                    String deductibleRate = kindItem.getDeductibleRate().replaceAll("[^0-9]", "");
+                    item.setDeductibleRate(Integer.parseInt(deductibleRate));
+                }
+                break;
+                
+            case "MJ4": // 附加绝对免赔率特约险(乘客)
+                item.setKindCode("FD4");
+                item.setKindName("附加绝对免赔率特约险(机动车车上人员责任保险(乘客))");
+                item.setRiskCode("050A");
+                item.setAmount(0);
+                if (StringUtils.hasLength(kindItem.getDeductibleRate())) {
+                    String deductibleRate = kindItem.getDeductibleRate().replaceAll("[^0-9]", "");
+                    item.setDeductibleRate(Integer.parseInt(deductibleRate));
+                }
+                break;
+                
+            default:
+                // 未知险种代码,返回null
+                return null;
+        }
+        
+        return item;
+    }
+
     /**
      * 构建附加保单信息列表
      *
      * @return List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList>
      */
-    private List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList> buildCarPolicySubInfoList() {
-        List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList> carPolicySubInfoList = new ArrayList<>();
+//    private List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList> buildCarPolicySubInfoList() {
+//        List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList> carPolicySubInfoList = new ArrayList<>();
+//
+//        ZiJinCrawlerQuotationRequest.CarPolicySubInfoList carPolicySubInfo1 = new ZiJinCrawlerQuotationRequest.CarPolicySubInfoList();
+//        carPolicySubInfo1.setPlanName("山西9座以内非营业客车驾乘险10万档:36元/座-10万+1万+30元/天");
+//        carPolicySubInfo1.setInsureGradeNo("214000737028");
+//        carPolicySubInfo1.setIsUseInsured("1");
+//        carPolicySubInfo1.setQuantity("1");
+//        carPolicySubInfo1.setRiskCode("0737");
+//        carPolicySubInfo1.setRiskName("驾乘人员人身意外伤害保险");
+//        carPolicySubInfo1.setSumAmount(577000);
+//        carPolicySubInfo1.setSumPremium(180);
+//        carPolicySubInfo1.setActualPremium("180.00");
+//        carPolicySubInfo1.setProductCode("ZKICATM_GRDL_Plan");
+//        carPolicySubInfoList.add(carPolicySubInfo1);
+//        return carPolicySubInfoList;
+//    }
+
 
-        ZiJinCrawlerQuotationRequest.CarPolicySubInfoList carPolicySubInfo1 = new ZiJinCrawlerQuotationRequest.CarPolicySubInfoList();
-        carPolicySubInfo1.setPlanName("山西9座以内非营业客车驾乘险10万档:36元/座-10万+1万+30元/天");
-        carPolicySubInfo1.setInsureGradeNo("214000737028");
-        carPolicySubInfo1.setIsUseInsured("1");
-        carPolicySubInfo1.setQuantity("1");
-        carPolicySubInfo1.setRiskCode("0737");
-        carPolicySubInfo1.setRiskName("驾乘人员人身意外伤害保险");
-        carPolicySubInfo1.setSumAmount(577000);
-        carPolicySubInfo1.setSumPremium(180);
-        carPolicySubInfo1.setActualPremium("180.00");
-        carPolicySubInfo1.setProductCode("ZKICATM_GRDL_Plan");
-        carPolicySubInfoList.add(carPolicySubInfo1);
+    /**
+     * 构建附加保单信息列表
+     *
+     * @return List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList>
+     */
+    /**
+     * 构建附加保单信息列表(驾乘险)
+     * 参数来源对照Python get_fcx_main方法:
+     * 根据驾乘险列表动态构建附加保单信息
+     * 目前只支持 rideRiskCode == "0733"(紫金驾驶人意外伤害保险)
+     *
+     * @param quoteVo 报价实体
+     * @return List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList>
+     */
+    private List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList> buildCarPolicySubInfoList(QuoteVo quoteVo) {
+        List<ZiJinCrawlerQuotationRequest.CarPolicySubInfoList> carPolicySubInfoList = new ArrayList<>();
+        
+        List<AccidentalDrivingVo> accidentalDrivings = quoteVo.getAccidentalDrivings();
+        if (accidentalDrivings == null || accidentalDrivings.isEmpty()) {
+            return carPolicySubInfoList;
+        }
+        
+        for (AccidentalDrivingVo drivingInsurance : accidentalDrivings) {
+            String rideRiskCode = drivingInsurance.getRiskCode();
+            
+            // 目前只支持 rideRiskCode == "0733"(紫金驾驶人意外伤害保险)
+            if ("0733".equals(rideRiskCode)) {
+                ZiJinCrawlerQuotationRequest.CarPolicySubInfoList subInfo = buildRideRisk0733(drivingInsurance);
+                if (subInfo != null) {
+                    carPolicySubInfoList.add(subInfo);
+                }
+            }
+            // 其他风险代码暂未配置,Python中会抛出异常
+            // 这里暂时跳过,不抛出异常
+        }
+        
         return carPolicySubInfoList;
     }
 
+    /**
+     * 构建紫金驾驶人意外伤害保险(riskCode=0733)信息
+     *
+     * @param drivingInsurance 驾乘险信息
+     * @return ZiJinCrawlerQuotationRequest.CarPolicySubInfoList
+     */
+    private ZiJinCrawlerQuotationRequest.CarPolicySubInfoList buildRideRisk0733(AccidentalDrivingVo drivingInsurance) {
+        ZiJinCrawlerQuotationRequest.CarPolicySubInfoList subInfo = new ZiJinCrawlerQuotationRequest.CarPolicySubInfoList();
+        
+        // 默认值
+        subInfo.setPlanName("全国家用驾驶人意外险50万档:160元-50万+5万+150元/天");
+        subInfo.setInsureGradeNo("200000733009");
+        subInfo.setIsUseInsured("1");
+        subInfo.setQuantity("1");
+        subInfo.setRiskCode("0733");
+        subInfo.setRiskName("紫金驾驶人意外伤害保险");
+        subInfo.setSumAmount(577000);
+        subInfo.setSumPremium(160);
+        subInfo.setProductCode("ZKICATM_Driver_Plan_Common");
+        
+        // 根据 planId(这里用 productCode 代替)匹配具体计划
+        String planId = drivingInsurance.getProductCode();
+        if (StringUtils.hasLength(planId)) {
+            switch (planId) {
+                case "214000733008":
+                    subInfo.setPlanName("山西驾驶20座(不含)以下非营业型客车(不包括摩托车、拖拉机、农用运输车、电瓶车)2.5万档:25元/车-2.5万+2500元");
+                    subInfo.setInsureGradeNo("214000733008");
+                    subInfo.setSumAmount(27500);
+                    subInfo.setSumPremium(25);
+                    break;
+                case "200000733007":
+                    subInfo.setPlanName("全国家用驾驶人意外险30万档:120元-30万+3万+100元/天");
+                    subInfo.setInsureGradeNo("200000733007");
+                    subInfo.setSumAmount(348000);
+                    subInfo.setSumPremium(120);
+                    break;
+                case "200000733009":
+                    // 默认值就是这个计划,无需修改
+                    break;
+                case "214000733004":
+                    subInfo.setPlanName("太原驾驶人意外险5万档:50元-5万+0.5万");
+                    subInfo.setInsureGradeNo("214000733004");
+                    subInfo.setSumAmount(55000);
+                    subInfo.setSumPremium(2607);
+                    break;
+                // 其他计划可以继续添加
+                default:
+                    // 使用默认值
+                    break;
+            }
+        }
+        
+        // 设置实际保费
+        if (subInfo.getSumPremium() != null) {
+            subInfo.setActualPremium(String.format("%.2f", subInfo.getSumPremium().doubleValue()));
+        }
+        
+        return subInfo;
+    }
+
+
+    /**
+     * 构建车辆信息对象
+     *
+     * @return ZiJinCrawlerQuotationRequest.VehicleInfo
+     */
+//    private ZiJinCrawlerQuotationRequest.VehicleInfo buildVehicleInfo() {
+//        ZiJinCrawlerQuotationRequest.VehicleInfo vehicleInfo = new ZiJinCrawlerQuotationRequest.VehicleInfo();
+//
+//        // 基础车辆信息
+//        vehicleInfo.setActualValue(73905.6);
+//        vehicleInfo.setAgreeActualValue(73905.6);
+//        vehicleInfo.setBrandName("荣威CSA6452NEAQ多用途乘用车");
+//        vehicleInfo.setCarKindCode("A0");
+//        vehicleInfo.setCarKindDetailId("KA");
+//        vehicleInfo.setCarLoanFlag("1");
+//        vehicleInfo.setCertificateDate("2021-11-01");
+//        vehicleInfo.setChgOwnerFlag("1");
+//        vehicleInfo.setCompletekerbmass(1539);
+//        vehicleInfo.setEcdemicVehicleFlag("0");
+//        vehicleInfo.setEngineNo("DNSM9070392");
+//
+//        // 日期相关
+//        vehicleInfo.setEnrollDate("2021-11-01");
+//        vehicleInfo.setUpdateEnrollDate("2021-11-01");
+//        vehicleInfo.setIssueDate("2025-10-16");
+//        vehicleInfo.setMakeDate("2025-10-16");
+//        vehicleInfo.setMakeDateJQ("2025-10-16");
+//
+//        // 车辆技术参数
+//        vehicleInfo.setExhaustCapacity(1490);
+//        vehicleInfo.setFuelType("0");
+//        vehicleInfo.setFuelTypeJY("D1");
+//        vehicleInfo.setNewEnergyFlag("0");
+//        vehicleInfo.setPower("133");
+//        vehicleInfo.setModelEnergyType("D1");
+//
+//        // 牌照和车辆识别
+//        vehicleInfo.setLicenseColorCode("01");
+//        vehicleInfo.setLicenseKindCode("02");
+//        vehicleInfo.setLicenseNo("晋HJW581");
+//        vehicleInfo.setLoanVehicleFlag("0");
+//        vehicleInfo.setModelCode("RWD1598SQQ");
+//        vehicleInfo.setNoLicenseFlag("1");
+//        vehicleInfo.setVehicleId("1");
+//        vehicleInfo.setVinNo("LSJA24U69MS091895");
+//
+//        // 车辆分类和用途
+//        vehicleInfo.setSeatCount(5);
+//        vehicleInfo.setUseNatureCode("85");
+//        vehicleInfo.setOriCarKindName("K33");
+//        vehicleInfo.setPlatVehicleCode("CRWARJUC0001");
+//        vehicleInfo.setVehicleStyleUniqueId("800004584");
+//
+//        // 价格和商业信息
+//        vehicleInfo.setPurchasePrice("103800");
+//        vehicleInfo.setSale4SFlag("0");
+//        vehicleInfo.setOriPurchasePrice("103800");
+//        vehicleInfo.setIsInvokeJingYou("1");
+//
+//        // 型号名称
+//        vehicleInfo.setPrintVehicleModelName("荣威CSA6452NEAQ多用途乘用车");
+//        vehicleInfo.setAliasName("荣威RX5 PLUS 330TGI 1.5T TST国潮智臻版");
+//        vehicleInfo.setOriBrandName("荣威CSA6452NEAQ多用途乘用车");
+//        vehicleInfo.setOriModelName("荣威CSA6452NEAQ多用途乘用车");
+//        vehicleInfo.setPrintModelName("荣威CSA6452NEAQ多用途乘用车");
+//
+//        return vehicleInfo;
+//    }
+
+
     /**
      * 构建车辆信息对象
      *
      * @return ZiJinCrawlerQuotationRequest.VehicleInfo
      */
-    private ZiJinCrawlerQuotationRequest.VehicleInfo buildVehicleInfo() {
+    /**
+     * 构建车辆信息对象
+     * 参数来源对照Python get_car_info_main方法:
+     * - carInfoVo: 车辆基本信息
+     * - actualValue: 车辆实际价值(从API获取)
+     *
+     * @param quoteVo      报价实体
+     * @param actualValue  车辆实际价值
+     * @return VehicleInfo
+     */
+    private ZiJinCrawlerQuotationRequest.VehicleInfo buildVehicleInfo(QuoteVo quoteVo, Double actualValue, String modelCode, String iacVehicleCode) {
+        log.info("quoteVo参数的值:{}", JSON.toJSONString(quoteVo));
         ZiJinCrawlerQuotationRequest.VehicleInfo vehicleInfo = new ZiJinCrawlerQuotationRequest.VehicleInfo();
+        CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
+
+        if (carInfoVo == null) {
+            return vehicleInfo;
+        }
 
         // 基础车辆信息
-        vehicleInfo.setActualValue(73905.6);
-        vehicleInfo.setAgreeActualValue(73905.6);
-        vehicleInfo.setBrandName("荣威CSA6452NEAQ多用途乘用车");
-        vehicleInfo.setCarKindCode("A0");
-        vehicleInfo.setCarKindDetailId("KA");
-        vehicleInfo.setCarLoanFlag("1");
-        vehicleInfo.setCertificateDate("2021-11-01");
-        vehicleInfo.setChgOwnerFlag("1");
-        vehicleInfo.setCompletekerbmass(1539);
+        if (actualValue != null) {
+            vehicleInfo.setActualValue(actualValue);
+            vehicleInfo.setAgreeActualValue(actualValue);
+        }
+        vehicleInfo.setBrandName(carInfoVo.getBrandName());
+        
+        // 车辆种类代码转换(A0->客车, A1->货车等)
+        String carKindCode = carInfoVo.getCarKindCode();
+        if (StringUtils.hasLength(carKindCode)) {
+            vehicleInfo.setCarKindCode(carKindCode);
+        }
+        
+        vehicleInfo.setCarKindDetailId(carInfoVo.getCarKindDetailIdCode());
+        
+        // 交强险过户标志
+        vehicleInfo.setCarLoanFlag(carInfoVo.isTransfer() ? "1" : "0");
+        
+        // 购车发票日期(使用注册日期)
+        vehicleInfo.setCertificateDate(carInfoVo.getRegisterDate());
+        
+        // 商业险过户标志
+        vehicleInfo.setChgOwnerFlag(carInfoVo.isTransferBi() ? "1" : "0");
+        
+        // 整备质量
+        if (StringUtils.hasLength(carInfoVo.getCompleteKerbMass())) {
+            vehicleInfo.setCompletekerbmass(Integer.parseInt(carInfoVo.getCompleteKerbMass()));
+        }
+        
+        // 外地车标志(默认0)
         vehicleInfo.setEcdemicVehicleFlag("0");
-        vehicleInfo.setEngineNo("DNSM9070392");
+        
+        vehicleInfo.setEngineNo(carInfoVo.getEngineNo());
 
         // 日期相关
-        vehicleInfo.setEnrollDate("2021-11-01");
-        vehicleInfo.setUpdateEnrollDate("2021-11-01");
-        vehicleInfo.setIssueDate("2025-10-16");
-        vehicleInfo.setMakeDate("2025-10-16");
-        vehicleInfo.setMakeDateJQ("2025-10-16");
+        vehicleInfo.setEnrollDate(carInfoVo.getRegisterDate());
+        vehicleInfo.setUpdateEnrollDate(carInfoVo.getRegisterDate());
+        vehicleInfo.setIssueDate(carInfoVo.getIssueDate());
+        
+        // 过户日期处理
+        if (carInfoVo.isTransferBi()) {
+            vehicleInfo.setMakeDate(carInfoVo.getRegisterDate());
+        }
+        if (carInfoVo.isTransfer()) {
+            vehicleInfo.setMakeDateJQ(carInfoVo.getRegisterDate());
+        }
 
         // 车辆技术参数
-        vehicleInfo.setExhaustCapacity(1490);
-        vehicleInfo.setFuelType("0");
-        vehicleInfo.setFuelTypeJY("D1");
-        vehicleInfo.setNewEnergyFlag("0");
-        vehicleInfo.setPower("133");
-        vehicleInfo.setModelEnergyType("D1");
+        if (StringUtils.hasLength(carInfoVo.getDisplacement())) {
+            // displacement是升(L),需要转换为毫升(ml)
+            double displacement = Double.parseDouble(carInfoVo.getDisplacement());
+            vehicleInfo.setExhaustCapacity((int) (displacement * 1000));
+        }
+        
+        // 能源类型
+        vehicleInfo.setFuelType(carInfoVo.getEnergyTypeCode());
+        vehicleInfo.setFuelTypeJY(carInfoVo.getModelEnergyType());
+        
+        // 新能源标志
+        vehicleInfo.setNewEnergyFlag(carInfoVo.isNewEnergyMark() ? "1" : "0");
+        
+        vehicleInfo.setPower(carInfoVo.getPowerScale());
+        vehicleInfo.setModelEnergyType(carInfoVo.getModelEnergyType());
 
         // 牌照和车辆识别
-        vehicleInfo.setLicenseColorCode("01");
-        vehicleInfo.setLicenseKindCode("02");
-        vehicleInfo.setLicenseNo("晋HJW581");
-        vehicleInfo.setLoanVehicleFlag("0");
-        vehicleInfo.setModelCode("RWD1598SQQ");
-        vehicleInfo.setNoLicenseFlag("1");
+        vehicleInfo.setLicenseColorCode(StringUtils.hasLength(carInfoVo.getLicenseColorCode()) ? carInfoVo.getLicenseColorCode() : "01");
+        vehicleInfo.setLicenseKindCode(StringUtils.hasLength(carInfoVo.getLicenseKindCode()) ? carInfoVo.getLicenseKindCode() : "02");
+        vehicleInfo.setLicenseNo(carInfoVo.getLicenseNo());
+        
+        // 贷款车标志
+        vehicleInfo.setLoanVehicleFlag(carInfoVo.isLoanStatus() ? "1" : "0");
+        
+        // 车型代码
+        vehicleInfo.setModelCode(modelCode);
+        
+        // 是否新车未上牌
+        vehicleInfo.setNoLicenseFlag("0".equals(carInfoVo.getIsRegistered()) ? "0" : "1");
+        
         vehicleInfo.setVehicleId("1");
-        vehicleInfo.setVinNo("LSJA24U69MS091895");
+        vehicleInfo.setVinNo(carInfoVo.getVinNo());
 
         // 车辆分类和用途
-        vehicleInfo.setSeatCount(5);
-        vehicleInfo.setUseNatureCode("85");
-        vehicleInfo.setOriCarKindName("K33");
-        vehicleInfo.setPlatVehicleCode("CRWARJUC0001");
-        vehicleInfo.setVehicleStyleUniqueId("800004584");
+        if (StringUtils.hasLength(carInfoVo.getSeatCount())) {
+            vehicleInfo.setSeatCount(Integer.parseInt(carInfoVo.getSeatCount()));
+        }
+        
+        // 使用性质代码
+        vehicleInfo.setUseNatureCode(carInfoVo.getCarNatureCode());
+        vehicleInfo.setOriCarKindName(carInfoVo.getCarTypeCode());
+        
+        // 平台车辆代码
+        vehicleInfo.setPlatVehicleCode(iacVehicleCode);
+        
+        // 车型唯一ID
+        vehicleInfo.setVehicleStyleUniqueId("");
 
         // 价格和商业信息
-        vehicleInfo.setPurchasePrice("103800");
+        vehicleInfo.setPurchasePrice(carInfoVo.getPurchasePrice());
         vehicleInfo.setSale4SFlag("0");
-        vehicleInfo.setOriPurchasePrice("103800");
+        vehicleInfo.setOriPurchasePrice(carInfoVo.getPurchasePrice());
         vehicleInfo.setIsInvokeJingYou("1");
 
         // 型号名称
-        vehicleInfo.setPrintVehicleModelName("荣威CSA6452NEAQ多用途乘用车");
-        vehicleInfo.setAliasName("荣威RX5 PLUS 330TGI 1.5T TST国潮智臻版");
-        vehicleInfo.setOriBrandName("荣威CSA6452NEAQ多用途乘用车");
-        vehicleInfo.setOriModelName("荣威CSA6452NEAQ多用途乘用车");
-        vehicleInfo.setPrintModelName("荣威CSA6452NEAQ多用途乘用车");
+        vehicleInfo.setPrintVehicleModelName(carInfoVo.getBrandName());
+        vehicleInfo.setAliasName(carInfoVo.getBrandName());
+        vehicleInfo.setOriBrandName(carInfoVo.getBrandName());
+        vehicleInfo.setOriModelName(carInfoVo.getBrandName());
+        vehicleInfo.setPrintModelName(carInfoVo.getBrandName());
 
         return vehicleInfo;
     }
 
+
+    /**
+     * 构建盈利数据列表
+     *
+     * @return List<ZiJinCrawlerQuotationRequest.ProfitDataList>
+     */
+//    private List<ZiJinCrawlerQuotationRequest.ProfitDataList> buildProfitDataList() {
+//        List<ZiJinCrawlerQuotationRequest.ProfitDataList> profitDataList = new ArrayList<>();
+//
+//        // 第一个盈利数据项
+//        ZiJinCrawlerQuotationRequest.ProfitDataList profitData1 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
+//        profitData1.setProfitCode("C31");
+//        profitData1.setProfitRate("1.05");
+//        profitDataList.add(profitData1);
+//
+//        // 第二个盈利数据项
+//        ZiJinCrawlerQuotationRequest.ProfitDataList profitData2 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
+//        profitData2.setProfitCode("C32");
+//        profitData2.setProfitRate("1.000000");
+//        profitDataList.add(profitData2);
+//        return profitDataList;
+//    }
+
+
+    /**
+     * 构建盈利数据列表
+     *
+     * @return List<ZiJinCrawlerQuotationRequest.ProfitDataList>
+     */
     /**
      * 构建盈利数据列表
+     * 参数来源对照Python代码:
+     * - coefficient: 自主定价系数,从 otherInfo 获取
+     * 只有当 coefficient 不为空且大于0时,才构建盈利数据列表
      *
+     * @param quoteVo 报价实体
      * @return List<ZiJinCrawlerQuotationRequest.ProfitDataList>
      */
-    private List<ZiJinCrawlerQuotationRequest.ProfitDataList> buildProfitDataList() {
+    private List<ZiJinCrawlerQuotationRequest.ProfitDataList> buildProfitDataList(QuoteVo quoteVo) {
         List<ZiJinCrawlerQuotationRequest.ProfitDataList> profitDataList = new ArrayList<>();
 
-        // 第一个盈利数据项
-        ZiJinCrawlerQuotationRequest.ProfitDataList profitData1 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
-        profitData1.setProfitCode("C31");
-        profitData1.setProfitRate("1.05");
-        profitDataList.add(profitData1);
-
-        // 第二个盈利数据项
-        ZiJinCrawlerQuotationRequest.ProfitDataList profitData2 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
-        profitData2.setProfitCode("C32");
-        profitData2.setProfitRate("1.000000");
-        profitDataList.add(profitData2);
+        // 获取自主定价系数
+        String coefficient = null;
+        if (quoteVo.getOtherInfo() != null) {
+            coefficient = quoteVo.getOtherInfo().getCoefficient();
+        }
+
+        // 只有当 coefficient 不为空且大于0时,才构建盈利数据列表
+        if (StringUtils.hasLength(coefficient)) {
+            try {
+                double coefficientValue = Double.parseDouble(coefficient);
+                if (coefficientValue > 0) {
+                    // 第一个盈利数据项 - 自主定价系数
+                    ZiJinCrawlerQuotationRequest.ProfitDataList profitData1 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
+                    profitData1.setProfitCode("C31");
+                    profitData1.setProfitRate(coefficient);
+                    profitDataList.add(profitData1);
+
+                    // 第二个盈利数据项 - 固定值
+                    ZiJinCrawlerQuotationRequest.ProfitDataList profitData2 = new ZiJinCrawlerQuotationRequest.ProfitDataList();
+                    profitData2.setProfitCode("C32");
+                    profitData2.setProfitRate("1.000000");
+                    profitDataList.add(profitData2);
+                }
+            } catch (NumberFormatException e) {
+                // coefficient 不是有效数字,不构建盈利数据列表
+            }
+        }
+
         return profitDataList;
     }
 

+ 1 - 1
tenant/organization/src/main/java/com/jzg/organization/controller/PtlAgreementCostController.java

@@ -38,7 +38,7 @@ public class PtlAgreementCostController {
     @OperatorTrajectory(moduleName = "报价配置/费用管理/新增费用",OperationDict = OperationTypeEnum.IN_AGREEMENT,mapperClass = PtlAgreementCostMapper.class,entityClass = PtlAgreemenCostAdd.class)
     @Operation(summary = "协议费用管理新增")
     @PostMapping("save")
-    public HttpResult add(@RequestBody @Valid PtlAgreemenCostAdd ptlAgreemenCostAdd){
+    public HttpResult<String> add(@RequestBody @Valid PtlAgreemenCostAdd ptlAgreemenCostAdd){
         return ptlAgreementCostService.save(ptlAgreemenCostAdd);
     }
 

+ 12 - 0
tenant/organization/src/main/java/com/jzg/organization/controller/PtlAgreementDispatchController.java

@@ -88,4 +88,16 @@ public class PtlAgreementDispatchController {
     public HttpResult updateDispatchName(String dispatchId,String name){
         return ptlAgreementDispatchService.updateDispatchName(dispatchId, name) ? HttpResult.ok("修改调度名称成功") : HttpResult.error("修改调度名称失败");
     }
+
+    /**
+     * 删除后置处理动作
+     *
+     * @param afterActionId ptl_agreement_dispatch_after_action表的序号
+     * @author lipf
+     * @date 2026/5/26 15:22
+     */
+    @DeleteMapping("/deleteAfterActionById/{afterActionId}")
+    public HttpResult<String> deleteAfterActionById(@PathVariable("afterActionId") String afterActionId){
+        return ptlAgreementDispatchService.deleteAfterActionById(afterActionId);
+    }
 }

+ 71 - 15
tenant/organization/src/main/java/com/jzg/organization/controller/ReceivableController.java

@@ -7,10 +7,7 @@ import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.finance.dto.CompanySuperviseSettlementReportDto;
 import com.jzg.commons.entity.finance.dto.ExportSuperviseSettlementExcelDto;
 import com.jzg.commons.entity.finance.dto.ReceiverSettlementReportDto;
-import com.jzg.commons.entity.finance.po.InsPlyIncome;
-import com.jzg.commons.entity.finance.po.InsPlyIncomeInvoiceSettlement;
-import com.jzg.commons.entity.finance.po.InsPlyIncomeOrder;
-import com.jzg.commons.entity.finance.po.InsPlyIncomeVO;
+import com.jzg.commons.entity.finance.po.*;
 import com.jzg.commons.entity.finance.vo.*;
 import com.jzg.commons.entity.orders.po.InsOrderAdjust;
 import com.jzg.commons.request.RequestSingleParam;
@@ -25,6 +22,7 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -149,24 +147,18 @@ public class ReceivableController {
 
     @PostMapping("commissionInvoicing")
     @Operation(summary = "手续费开票")
-    public HttpResult commissionInvoicing(@RequestBody InvoicingVo invoicingVo){
-        // 设置手续费开票
-        //invoicingVo.setInvoiceType("1");
-//        boolean invoicingCheck = receivableService.invoicingCheck(invoicingVo);
-//        if(!invoicingCheck){
-//            return HttpResult.error("有订单占用");
-//        }
+    public HttpResult<InvoiceingResult> commissionInvoicing(@RequestBody InsPlyIncomeInvoiceVO invoicingVo){
         InvoiceingResult result = receivableService.addInvoicing(invoicingVo);
         if (Objects.nonNull(result)){
-            return HttpResult.ok("开票成功",result);
+            return HttpResult.ok("开票成功,发票号是" + result.getInvoiceId() ,result);
         }
         return HttpResult.error("开票失败");
     }
 
     @PostMapping("otherInvoicing")
     @Operation(summary = "跟单费开票")
-    public HttpResult otherInvoicing(@RequestBody InvoicingVo invoicingVo){
-        // 设置跟单费开票
+    public HttpResult<InvoiceingResult> otherInvoicing(@RequestBody InsPlyIncomeInvoiceVO invoicingVo){
+        // 开票类型  1、手续费  2、跟单费  3、驾意险手续费 4、驾意险跟单费 5、平台应收-车险 6、平台应收-非车险
         invoicingVo.setInvoiceType("2");
         InvoiceingResult result = receivableService.addInvoicing(invoicingVo);
         if (Objects.nonNull(result)){
@@ -178,6 +170,9 @@ public class ReceivableController {
     @PostMapping("invoicingCheck")
     @Operation(summary = "开票检测")
     public HttpResult<String> invoicingCheck(@RequestBody InvoicingVo invoicingVo) {
+//        if(1 == 1){
+//            return HttpResult.ok("无占用");
+//        }
         boolean result = receivableService.invoicingCheck(invoicingVo);
         if(result){
             return HttpResult.ok("无占用");
@@ -187,6 +182,23 @@ public class ReceivableController {
         }
     }
 
+    /**
+     * 开票前计算应收金额等信息
+     *
+     * @param invoicingVo 获取订单编号等信息
+     * @author lipf
+     * @date 2026/5/26 10:45
+     */
+    @Operation(summary = "开票前计算应收金额等信息")
+    @PostMapping("/calBeforeInvoice")
+    public HttpResult<InsPlyIncomeInvoice> calBeforeInvoice(@RequestBody InvoicingVo invoicingVo){
+        InsPlyIncomeInvoiceVO insPlyIncomeInvoice = receivableService.calBeforeInvoice(invoicingVo);
+        if(!insPlyIncomeInvoice.isCanInvoice()){
+            return HttpResult.error(500,insPlyIncomeInvoice,insPlyIncomeInvoice.getErrMsg());
+        }
+        return HttpResult.ok(insPlyIncomeInvoice);
+    }
+
     @PostMapping("getReceivableCompany")
     @Operation(summary = "获取保险公司")
     public HttpResult getReceivableCompany(@RequestBody InvoicingVo invoicingVo){
@@ -194,7 +206,7 @@ public class ReceivableController {
     }
 
     @PostMapping("settlement")
-    @Operation(summary = "结算")
+    @Operation(summary = "私有协议结算")
     public HttpResult<String> settlement(@RequestBody SettlementVo settlementVo){
         try{
             boolean settlement = receivableService.settlement(settlementVo);
@@ -204,6 +216,36 @@ public class ReceivableController {
             return HttpResult.error(e.getMessage());
         }
     }
+    /**
+     * 开票并结算
+     *
+     * @author lipf
+     * @date 2026/5/26 11:57
+     */
+    @PostMapping("invoiceAndSettlement")
+    @Operation(summary = "开票并结算")
+    public HttpResult<String> invoiceAndSettlement(@RequestBody InvoiceAndSettlementVo settlementVo){
+        return receivableService.invoiceAndSettlement(settlementVo);
+    }
+
+    @PostMapping("platformSettlement")
+    @Operation(summary = "平台协议结算")
+    public HttpResult<String> platformSettlement(@RequestBody PlatformSettlementVo platformSettlementVo){
+        try{
+            boolean settlement = receivableService.platformSettlement(platformSettlementVo);
+            return settlement ? HttpResult.ok("结算成功") : HttpResult.error("结算失败");
+        }catch (Exception e){
+            log.error("结算失败",e);
+            return HttpResult.error(e.getMessage());
+        }
+    }
+
+    @PostMapping("getPlatformSettlementReceivableAmount")
+    @Operation(summary = "获取平台协议结算的应收金额")
+    public HttpResult<BigDecimal> getPlatformSettlementReceivableAmount(@RequestBody InvoicingVo invoicingVo){
+        BigDecimal receivableAmount = receivableService.getReceivableAmount(invoicingVo);
+        return HttpResult.ok(receivableAmount);
+    }
 
     @PostMapping("settlementList")
     @Operation(summary = "结算明细")
@@ -307,6 +349,13 @@ public class ReceivableController {
         return HttpResult.ok(receivableService.superviseSettlementExcel(page,settlementQueryVo));
     }
 
+    @PostMapping("platformSettlementExcel")
+    @Operation(summary = "平台协议结算记录")
+    public HttpResult<Page<ExportSuperviseSettlementExcelDto>> platformSettlementExcel(@RequestBody SettlementQueryVo settlementQueryVo) {
+        Page page = settlementQueryVo.getPage();
+        return HttpResult.ok(receivableService.platformSettlementExcel(page,settlementQueryVo));
+    }
+
 
     @PostMapping("exportSuperviseSettlementExcel")
     @Operation(summary = "导出应收手续费结算记录excel文件")
@@ -315,6 +364,13 @@ public class ReceivableController {
         receivableService.exportSuperviseSettlementExcel(page,settlementQueryVo);
     }
 
+    @PostMapping("exportPlatformSettlementExcel")
+    @Operation(summary = "导出平台结算记录excel文件")
+    public void exportPlatformSettlementExcel(@RequestBody SettlementQueryVo settlementQueryVo) throws IOException {
+        Page page = new Page<>(1,1000000);
+        receivableService.exportPlatformSettlementExcel(page,settlementQueryVo);
+    }
+
     @PostMapping("superviseSettlementDetailExcel")
     @Operation(summary = "应收手续费结算明细")
     public HttpResult superviseSettlementDetailExcel(@RequestBody SettlementQueryVo settlementQueryVo) {

+ 1 - 1
tenant/organization/src/main/java/com/jzg/organization/controller/SchemeController.java

@@ -42,7 +42,7 @@ public class SchemeController {
 
     @Operation(summary = "获取方案")
     @GetMapping("/getScheme")
-    public HttpResult getScheme(String id){
+    public HttpResult<PtlSchemeQueryVo> getScheme(String id){
         PtlSchemeQueryVo schemeList = ptlSchemeService.getScheme(id);
         return HttpResult.ok(schemeList);
     }

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

@@ -80,6 +80,13 @@ public interface ReceivableMapper extends BaseMapper<InsPlyIncome> {
      */
     Page<ExportSuperviseSettlementExcelDto> superviseSettlementExcelDtos(Page page,@Param("settlementQueryVo") SettlementQueryVo settlementQueryVo);
 
+    /**
+     * 获取平台结算记录列表
+     * @param settlementQueryVo
+     * @return
+     */
+    Page<ExportSuperviseSettlementExcelDto> platformSettlementExcelDtos(Page page,@Param("settlementQueryVo") SettlementQueryVo settlementQueryVo);
+
     /**
      * 获取应收结算记录明细列表
      * @param settlementQueryVo

+ 1 - 1
tenant/organization/src/main/java/com/jzg/organization/service/PtlAgreementCostService.java

@@ -19,7 +19,7 @@ public interface PtlAgreementCostService extends IService<PtlAgreementCost> {
      * @author lipf
      * @date 2026/4/13 14:16
      */
-    HttpResult save(PtlAgreemenCostAdd ptlAgreemenCostAdd);
+    HttpResult<String> save(PtlAgreemenCostAdd ptlAgreemenCostAdd);
 
 
     /**

+ 10 - 0
tenant/organization/src/main/java/com/jzg/organization/service/PtlAgreementDispatchService.java

@@ -1,6 +1,7 @@
 package com.jzg.organization.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.agreement.dispatch.dto.PtlAgreementDispatch;
 import com.jzg.commons.entity.agreement.dispatch.dto.PtlAgreementDispatchAfterAction;
 import com.jzg.commons.entity.agreement.dispatch.vo.PtlAgreementDispatchQuery;
@@ -62,4 +63,13 @@ public interface PtlAgreementDispatchService extends IService<PtlAgreementDispat
      * @return
      */
     public boolean updateDispatchName(String dispatchId,String name);
+
+    /**
+     * 删除后置处理动作
+     *
+     * @param afterActionId ptl_agreement_dispatch_after_action表的序号
+     * @author lipf
+     * @date 2026/5/26 15:22
+     */
+    HttpResult<String> deleteAfterActionById(String afterActionId);
 }

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

@@ -4,9 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.finance.dto.*;
-import com.jzg.commons.entity.finance.po.InsPlyIncome;
-import com.jzg.commons.entity.finance.po.InsPlyIncomeInvoiceSettlement;
-import com.jzg.commons.entity.finance.po.InsPlyIncomeOrder;
+import com.jzg.commons.entity.finance.po.*;
 import com.jzg.commons.entity.finance.vo.*;
 import com.jzg.commons.entity.orders.po.InsOrderAdjust;
 import com.jzg.commons.entity.po.EsmInsCompany;
@@ -76,7 +74,7 @@ public interface ReceivableService extends IService<InsPlyIncome> {
     /**
      * 添加开票
      */
-    InvoiceingResult addInvoicing(InvoicingVo invoicingVo);
+    InvoiceingResult addInvoicing(InsPlyIncomeInvoiceVO invoicingVo);
 
     /**
      * 获取票据的实收金额
@@ -205,11 +203,23 @@ public interface ReceivableService extends IService<InsPlyIncome> {
      */
     Page<ExportSuperviseSettlementExcelDto> superviseSettlementExcel(Page page, SettlementQueryVo settlementQueryVo);
 
+    /**
+     * 平台协议结算记录
+     * @param settlementQueryVo
+     * @return
+     */
+    Page<ExportSuperviseSettlementExcelDto> platformSettlementExcel(Page page, SettlementQueryVo settlementQueryVo);
+
     /**
      * 导出应收手续费结算记录excel
      */
     void exportSuperviseSettlementExcel(Page page,SettlementQueryVo settlementQueryVo) throws IOException;
 
+    /**
+     * 导出平台结算记录excel
+     */
+    void exportPlatformSettlementExcel(Page page,SettlementQueryVo settlementQueryVo) throws IOException;
+
     /**
      * 导出平台协议Excel模板
      */
@@ -321,4 +331,27 @@ public interface ReceivableService extends IService<InsPlyIncome> {
      */
     HttpResult<String> deleteIncomesByIds(List<Long> ids, String userName);
 
+    /**
+     * 开票前计算应收金额等信息
+     *
+     * @param invoicingVo 获取订单编号等信息
+     * @author lipf
+     * @date 2026/5/26 10:45
+     */
+    InsPlyIncomeInvoiceVO calBeforeInvoice(InvoicingVo invoicingVo);
+
+    /**
+     * 开票并结算
+     *
+     * @param settlementVo 开票信息和结算信息
+     * @author lipf
+     * @date 2026/5/26 11:44
+     */
+    HttpResult<String> invoiceAndSettlement(InvoiceAndSettlementVo settlementVo);
+    /**
+     * 平台结算
+     * @param platformSettlementVo
+     * @return
+     */
+    boolean platformSettlement(PlatformSettlementVo platformSettlementVo);
 }

+ 9 - 3
tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementCostServiceImpl.java

@@ -35,7 +35,6 @@ import com.jzg.organization.state.listener.CostStateListener;
 import io.seata.spring.annotation.GlobalTransactional;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
-import org.redisson.api.IdGenerator;
 import org.redisson.api.RList;
 import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -48,7 +47,6 @@ import org.springframework.util.CollectionUtils;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -99,8 +97,12 @@ public class PtlAgreementCostServiceImpl extends ServiceImpl<PtlAgreementCostMap
      */
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public HttpResult save(PtlAgreemenCostAdd ptlAgreemenCostAdd) {
+    public HttpResult<String> save(PtlAgreemenCostAdd ptlAgreemenCostAdd) {
         log.info("报价配置/费用管理/新增费用. ptlAgreemenCostAdd=[{}]", JSONUtil.toJsonStr(ptlAgreemenCostAdd));
+//        if(StrUtil.isEmpty(ptlAgreemenCostAdd.getPtlAgreementId()) || StrUtil.isEmpty(ptlAgreemenCostAdd.getPtlAgreementCode())){
+//            log.info("新增费用的时候,需要指定关联的协议信息。ptlAgreemenCostAdd=[{}]", JSONUtil.toJsonStr(ptlAgreemenCostAdd));
+//            return HttpResult.error("新增费用的时候,需要指定关联的协议信息");
+//        }
         List<CostAdd> costAddList = ptlAgreemenCostAdd.getCostAddList();
         if (costAddList.isEmpty()) {
             log.info("费用管理:保存数据不能为空");
@@ -111,6 +113,10 @@ public class PtlAgreementCostServiceImpl extends ServiceImpl<PtlAgreementCostMap
                 if (ListUtils.hasDuplicates(ptlAgreementCostAdd.getRuleConditions())){
                     throw new SystemException("添加数据存在相同费用规则,请检查");
                 }
+                if(StrUtil.isEmpty(costAdd.getPtlAgreementId())){
+                    log.info("新增费用的时候,需要指定关联的协议信息。ptlAgreemenCostAdd=[{}]", JSONUtil.toJsonStr(ptlAgreemenCostAdd));
+                    return HttpResult.error("新增费用的时候,需要指定关联的协议信息");
+                }
                 ptlAgreementCostAdd.setPtlAgreementId(costAdd.getPtlAgreementId());
                 ptlAgreementCostAdd.setProductId(costAdd.getProductId());
                 ptlAgreementCostAdd.setProductName(costAdd.getProductName());

+ 56 - 18
tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementDispatchServiceImpl.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.extension.service.impl.ServiceImpl;
@@ -121,8 +122,8 @@ public class PtlAgreementDispatchServiceImpl extends ServiceImpl<PtlAgreementDis
         PtlAgreementDispatchVo dispatchVos = new PtlAgreementDispatchVo();
         List<String> dispatchIds = ptlAgreementDispatches.stream().map(PtlAgreementDispatch::getId).collect(Collectors.toList());
         if (!dispatchIds.isEmpty()) {
-            List<SysDict> dispatchBeforeActionDict = sysDictService.getByTypeCode("dispatch_before_action");
-            //List<SysDict> dispatchAfterActionDict = sysDictService.getByTypeCode("dispatch_after_action");
+            List<SysDict> beforeActionDicts = sysDictService.getByTypeCode("dispatch_before_action");
+            List<SysDict> afterActionsDicts = sysDictService.getByTypeCode("dispatch_after_action");
 
             // 查询保司所有的规则属性 然后进行分组
             List<PtlAgreementDispatchRulesAttrLink> ptlAgreementDispatchRulesAttrLinks = rulesAttrLinkMapper.selectList(new LambdaQueryWrapper<PtlAgreementDispatchRulesAttrLink>()
@@ -136,7 +137,7 @@ public class PtlAgreementDispatchServiceImpl extends ServiceImpl<PtlAgreementDis
             // 获取所有保司的动作
             List<PtlAgreementDispatchAction> ptlAgreementDispatchActions = actionMapper.getActions(dispatchIds);
             // 获取保司的报价失败之后的动作
-            List<PtlAgreementDispatchAfterAction> ptlAgreementDispatchAfterActions = afterActionMapper.getAfterActions(ptlAgreementDispatchQuery.getCompanyId());
+            List<PtlAgreementDispatchAfterAction> afterActions = afterActionMapper.getAfterActions(ptlAgreementDispatchQuery.getCompanyId());
             int index = 1;
             // add by lipf, 对协议配置中的字典序号进行转义 2026年5月20日16:43:34
             List<PtlAgreementUndwrtRulesDictLabal> ptlAgreementUndwrtRulesDictLabals = baseMapper.queryAllDictLabal();
@@ -165,9 +166,26 @@ public class PtlAgreementDispatchServiceImpl extends ServiceImpl<PtlAgreementDis
                         String minName = ptlAreaLicenseService.convertAreaNumber2License(areaLicenseMap, attrlink.getMin());
                         attrlink.setMinName(minName);
                     }else{
-                        String minName = dictLabalId2Name.getOrDefault(attrlink.getMin(),attrlink.getMin());
+                        String minName = dictLabalId2Name.get(attrlink.getMin());
+                        if(StrUtil.isNotEmpty(minName)){
+                            attrlink.setMinName(minName);
+                        }else{
+                            List<String> names = new ArrayList<>();
+                            minName = attrlink.getMin();
+                            if(StrUtil.isNotEmpty(attrlink.getMin())){
+                                String[] split = attrlink.getMin().split(",");
+                                if(split.length >=2){
+                                    for (String s : split) {
+                                        names.add(dictLabalId2Name.get(s));
+                                    }
+                                    minName = String.join(",", names);
+                                }
+                            }
+                            attrlink.setMinName(minName);
+                        }
+
                         String maxName = dictLabalId2Name.getOrDefault(attrlink.getMax(),attrlink.getMax());
-                        attrlink.setMinName(minName);
+
                         attrlink.setMaxName(maxName);
                     }
                     PtlAgreementUndwrtRulesAttr undwrtRuleAttrByAttrCode = ptlAgreementUndwrtRulesAttrService.getUndwrtRuleAttrByAttrCode(attrlink.getAttrCode());
@@ -189,7 +207,7 @@ public class PtlAgreementDispatchServiceImpl extends ServiceImpl<PtlAgreementDis
                 }
 
                 for(PtlAgreementDispatchAction action : actions){
-                    SysDict sysDict = dispatchBeforeActionDict.stream().filter(x -> x.getValue().equals(action.getActionCode())).findFirst().orElse(null);
+                    SysDict sysDict = beforeActionDicts.stream().filter(x -> x.getValue().equals(action.getActionCode())).findFirst().orElse(null);
                     if(sysDict == null){
                         action.setActionName("未知动作");
                     }else{
@@ -202,26 +220,28 @@ public class PtlAgreementDispatchServiceImpl extends ServiceImpl<PtlAgreementDis
                                 }
                             }
                         }else if("change_bs_account".equals(action.getActionCode())){
-                            String accountId = action.getActionJson().get("accountId").toString();
-                            if(Objects.nonNull(accountId)){
-                                HttpResult<PtlAgreementAttribution> agreementAttribution = platformClient.getAgreementAttribution2(accountId);
-                                //HttpResult<PtlAgreementAttribution> agreementAttribution = esmInsCompanyClient.getAgreementAttribution(accountId);
-                                if (agreementAttribution.getCode() == 200) {
-                                    PtlAgreementAttribution data = agreementAttribution.getData();
-                                    action.getActionJson().put("userName", data.getUsername());
-                                    action.getActionJson().put("companyName", data.getInsCompanyName());
+                            if (action.getActionJson() != null && !action.getActionJson().isEmpty()) {
+                                // 修改这里:直接使用 getString,即使值为 null 也不会报错
+                                String accountId = action.getActionJson().getString("accountId");
+                                // 你的 Objects.nonNull 判断依然有效且非常规范
+                                if (Objects.nonNull(accountId)) {
+                                    HttpResult<PtlAgreementAttribution> agreementAttribution = platformClient.getAgreementAttribution2(accountId);
+                                    if (agreementAttribution.getCode() == 200) {
+                                        PtlAgreementAttribution data = agreementAttribution.getData();
+                                        action.getActionJson().put("userName", data.getUsername());
+                                        action.getActionJson().put("companyName", data.getInsCompanyName());
+                                    }
                                 }
                             }
                         }
                     }
                 }
-
                 PtlAgreementDispatchVo.DispatchVo vo = new PtlAgreementDispatchVo.DispatchVo(dispatch,attrLinks,actions);
                 dispatchVos.getDispatchVos().add(vo);
             }
 
-            for(PtlAgreementDispatchAfterAction afterAction : ptlAgreementDispatchAfterActions){
-                SysDict sysDict = dispatchBeforeActionDict.stream().filter(x -> x.getValue().equals(afterAction.getActionCode())).findFirst().orElse(null);
+            for(PtlAgreementDispatchAfterAction afterAction : afterActions){
+                SysDict sysDict = afterActionsDicts.stream().filter(x -> x.getValue().equals(afterAction.getActionCode())).findFirst().orElse(null);
                 if(sysDict == null){
                     afterAction.setActionName("未知动作");
                 }else{
@@ -245,7 +265,7 @@ public class PtlAgreementDispatchServiceImpl extends ServiceImpl<PtlAgreementDis
                     }
                 }
             }
-            dispatchVos.setAfterActions(ptlAgreementDispatchAfterActions);
+            dispatchVos.setAfterActions(afterActions);
         }
 
 
@@ -287,6 +307,24 @@ public class PtlAgreementDispatchServiceImpl extends ServiceImpl<PtlAgreementDis
         return false;
     }
 
+    /**
+     * 删除后置处理动作
+     *
+     * @param afterActionId ptl_agreement_dispatch_after_action表的序号
+     * @author lipf
+     * @date 2026/5/26 15:22
+     */
+    @Override
+    public HttpResult<String> deleteAfterActionById(String afterActionId) {
+        log.info("删除后置处理操作:afterActionId=[{}]",afterActionId);
+        PtlAgreementDispatchAfterAction ptlAgreementDispatchAfterAction = afterActionMapper.selectById(afterActionId);
+        if(ptlAgreementDispatchAfterAction == null) {
+            log.info("要删除的后置操作不存在. afterActionId=[{}]",afterActionId);
+            return HttpResult.error("要删除的后置操作不存在");
+        }
+        afterActionMapper.deleteById(afterActionId);
+        return HttpResult.ok("删除成功");
+    }
 }
 
 

+ 1 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlSchemeServiceImpl.java

@@ -184,6 +184,7 @@ public class PtlSchemeServiceImpl extends ServiceImpl<PtlSchemeMapper, PtlScheme
 
     @Override
     public PtlSchemeQueryVo getScheme(String id) {
+        log.info("根据方案id=[{}]获取方案信息(ptl_scheme_info)",id);
         //获取方案信息
         PtlSchemeInfo ptlSchemeInfo = ptlSchemeInfoMapper.selectOne(new LambdaQueryWrapper<PtlSchemeInfo>()
                 .eq(PtlSchemeInfo::getId, id));

+ 246 - 33
tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java

@@ -128,6 +128,10 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
     private static final String JY_INVOICING_COMMISSION_LOCK = "JY_INVOICING_COMMISSION_LOCK:";
     // 驾意险跟单费结算所
     private static final String JY_INVOICING_OTHER_LOCK = "JY_INVOICING_OTHER_LOCK:";
+    // 平台车险结算锁
+    private static final String PT_INVOICING_COMMISSION_LOCK = "PT_INVOICING_COMMISSION_LOCK:";
+    // 平台非车险结算锁
+    private static final String PT_INVOICING_OTHER_LOCK = "PT_INVOICING_OTHER_LOCK:";
 
 
 //    @Override
@@ -473,6 +477,34 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         return invoiceIds;
     }
 
+    /**
+     * 开票前计算应收金额等信息
+     *
+     * @param invoicingVo 获取订单编号等信息
+     * @author lipf
+     * @date 2026/5/26 10:45
+     */
+    @Override
+    public InsPlyIncomeInvoiceVO calBeforeInvoice(InvoicingVo invoicingVo) {
+        log.info("开票前校验并计算应收金额等金额。 invoicingVO=[{}]", JSONUtil.toJsonStr(invoicingVo));
+        InsPlyIncomeInvoiceVO invoice = new InsPlyIncomeInvoiceVO();
+        boolean b = this.invoicingCheck(invoicingVo);
+        if(!b){
+            List<String> invoiceIds = this.queryIncomeBindInvoice(invoicingVo);
+            invoice.setCanInvoice(false);
+            invoice.setErrMsg("订单已开票。发票序号是"+ invoiceIds.toString());
+            return invoice;
+        }
+        invoice.setCanInvoice(true);
+        BigDecimal receivableAmount = this.getReceivableAmount(invoicingVo);
+        log.info("根据订单号[{}]计算得到的应收金额是[{}]",JSONUtil.toJsonStr(invoicingVo),receivableAmount);
+        invoice.setReceivableSupervisePremium(receivableAmount);
+        invoice.setCompanyId(invoicingVo.getCompanyId());
+        invoice.setInvoiceTime(LocalDateTime.now());
+        invoice.setInvoiceType(invoicingVo.getInvoiceType());
+        return invoice;
+    }
+
     /**
      * 开票重复校验
      * 功能:DB+Redis双重校验,防止并发重复开票
@@ -495,12 +527,15 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             return false;
         }
 
+        // 开票类型  1、手续费  2、跟单费  3、驾意险手续费 4、驾意险跟单费 5、平台应收-车险 6、平台应收-非车险
         // 3. 根据开票类型获取Redis锁前缀
         String redisKeyPrefix = switch (invoicingVo.getInvoiceType()) {
             case "1" -> CAR_INVOICING_COMMISSION_LOCK;
             case "2" -> CAR_INVOICING_OTHER_LOCK;
             case "3" -> JY_INVOICING_COMMISSION_LOCK;
             case "4" -> JY_INVOICING_OTHER_LOCK;
+            case "5" -> PT_INVOICING_COMMISSION_LOCK;
+            case "6" -> PT_INVOICING_OTHER_LOCK;
             default -> throw new SystemException("不支持的开票类型");
         };
 
@@ -567,6 +602,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
 
     @Override
     public BigDecimal getReceivableAmount(InvoicingVo invoicingVo) {
+        log.info("获取订单的应收金额:invoicingVo=[{}]", JSONUtil.toJsonStr(invoicingVo));
         String invoiceType = invoicingVo.getInvoiceType();
         List<String> orderNos = invoicingVo.getOrderNos();
         orderNos = orderNos.stream()
@@ -596,6 +632,12 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         } else if (invoiceType.equals("4")) {
             // 驾意险的总跟单费(jy_follow_premium)
             return jyFollowPremium;
+        } else if (invoiceType.equals("5")) {
+            // 交强的总手续费(jq_commission_premium) + 商业的总手续费(sy_commission_premium) + 交强的总跟单费(jq_follow_premium) + 商业的总跟单费(sy_follow_premium)
+            return jqCommissionPremium.add(syCommissionPremium).add(jqFollowPremium).add(syFollowPremium);
+        } else if (invoiceType.equals("6")) {
+            // 驾意险的总手续费(jy_commission_premium) + 驾意险的总跟单费(jy_follow_premium)
+            return jyCommissionPremium.add(jyFollowPremium);
         }
         return null;
     }
@@ -603,34 +645,34 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
     /**
      * 添加发票
      *
-     * @param invoicingVo
-     * @return
+     * @param invoicingVo 开票相关的信息
+     * @return InvoiceingResult 开票的结果
      */
     @Override
     @Transactional
-    public InvoiceingResult addInvoicing(InvoicingVo invoicingVo) {
+    public InvoiceingResult addInvoicing(InsPlyIncomeInvoiceVO invoicingVo) {
+        log.info("开票:invoicingVo=[{}]", JSONUtil.toJsonStr(invoicingVo));
         try {
-            invoicingVo.setReceivablePremium(this.getReceivableAmount(invoicingVo));
-
             InvoiceingResult result = new InvoiceingResult();
             InsPlyIncomeInvoice invoice = new InsPlyIncomeInvoice();
+            BeanUtils.copyProperties(invoicingVo, invoice);
             invoice.setId(IdGenerate.nextId());
             invoice.setCompanyId(invoicingVo.getCompanyId());
             invoice.setInvoiceType(invoicingVo.getInvoiceType());
-            // 开票类型  1 手续费  2 跟单费  3 驾意险手续费 4 驾意险跟单费
+            //  开票类型  1、手续费  2、跟单费  3、驾意险手续费 4、驾意险跟单费 5、平台应收-车险 6、平台应收-非车险
             if("1".equals(invoicingVo.getInvoiceType()) || "2".equals(invoicingVo.getInvoiceType())){
                 invoice.setInvoiceRiskType("10");
+            }else if("5".equals(invoicingVo.getInvoiceType()) || "6".equals(invoicingVo.getInvoiceType())){
+                invoice.setInvoiceRiskType("30");
             }else{
                 invoice.setInvoiceRiskType("20");
             }
             invoice.setInvoiceParty(invoicingVo.getInvoiceParty());
             invoice.setOverinflatedAmount(invoicingVo.getOverinflatedAmount());
-            invoice.setReceivableSupervisePremium(invoicingVo.getReceivablePremium());
+            invoice.setReceivableSupervisePremium(invoicingVo.getReceivableSupervisePremium());
             invoice.setTaxPoint(invoicingVo.getTaxPoint());
             insPlyIncomeInvoiceMapper.insert(invoice);
-
-            List<InsPlyIncomeInvoiceLink> invoicingLinkList = new ArrayList();
-
+            List<InsPlyIncomeInvoiceLink> invoicingLinkList = new ArrayList<InsPlyIncomeInvoiceLink>();
             invoicingVo.getIncomeIds().forEach(incomeId -> {
                 InsPlyIncomeInvoiceLink link = new InsPlyIncomeInvoiceLink();
                 link.setId(IdGenerate.nextId());
@@ -641,7 +683,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             });
             insPlyIncomeInvoiceLinkMapper.insert(invoicingLinkList);
             result.setInvoiceId(invoice.getId());
-            result.setSumPrice(null != invoicingVo.getReceivablePremium() ? invoicingVo.getReceivablePremium().toString() : null);
+            result.setSumPrice(null != invoicingVo.getReceivableSupervisePremium() ? invoicingVo.getReceivableSupervisePremium().toString() : null);
             return result;
         } catch (Exception e) {
             log.info("开票异常.invoicingVo=[{}]",JSONUtil.toJsonStr(invoicingVo), e);
@@ -691,12 +733,141 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
                         .in(InsPlyIncome::getId, invoiceIds)
                         .set(InsPlyIncome::getJyOtherSettlement, "1"));
                 break;
+            case "5":
+                result = baseMapper.update(new LambdaUpdateWrapper<InsPlyIncome>()
+                        .in(InsPlyIncome::getId, invoiceIds)
+                        .set(InsPlyIncome::getPlatformSuperviseSettlement, "1").set(InsPlyIncome::getSettlementStatus, "1"));
+                break;
+            case "6":
+                result = baseMapper.update(new LambdaUpdateWrapper<InsPlyIncome>()
+                        .in(InsPlyIncome::getId, invoiceIds)
+                        .set(InsPlyIncome::getPlatformOtherSettlement, "1").set(InsPlyIncome::getSettlementStatus, "1"));
+                break;
             default:
                 result = 0;
         }
         return result > 0;
     }
 
+    /**
+     * 开票并结算
+     *
+     * @param settlementVo 开票信息和结算信息
+     * @author lipf
+     * @date 2026/5/26 11:44
+     */
+    @Override
+    public HttpResult<String> invoiceAndSettlement(InvoiceAndSettlementVo settlementVo) {
+        log.info("开票并结算: settlementVo=[{}]", JSONUtil.toJsonStr(settlementVo));
+        InvoiceingResult result = this.addInvoicing(settlementVo.getInvoiceVO());
+        if (Objects.nonNull(result)){
+            SettlementVo settlementVo1 = new SettlementVo();
+            BeanUtils.copyProperties(settlementVo, settlementVo1);
+            settlementVo1.setInvoicingId(result.getInvoiceId());
+            boolean settlement = this.settlement(settlementVo1);
+            if(settlement){
+                return HttpResult.ok("开票并结算成功");
+            }else{
+                return HttpResult.error("开票成功但结算失败");
+            }
+        }
+        return HttpResult.error("开票失败");
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean platformSettlement(PlatformSettlementVo platformSettlementVo) {
+        SettlementVo settlementVo = platformSettlementVo.getSettlementVo();
+        InvoicingVo invoicingVo = platformSettlementVo.getInvoicingVo();
+
+        log.info("平台结算:platformSettlement=[{}]", JSONUtil.toJsonStr(platformSettlementVo));
+        try {
+            // ============================开票逻辑============================
+            invoicingVo.setReceivablePremium(this.getReceivableAmount(invoicingVo));
+
+            InvoiceingResult result = new InvoiceingResult();
+            InsPlyIncomeInvoice invoice = new InsPlyIncomeInvoice();
+            invoice.setId(IdGenerate.nextId());
+            invoice.setCompanyId(invoicingVo.getCompanyId());
+            invoice.setInvoiceType(invoicingVo.getInvoiceType());
+            //  开票类型  1、手续费  2、跟单费  3、驾意险手续费 4、驾意险跟单费 5、平台应收-车险 6、平台应收-非车险
+            if("1".equals(invoicingVo.getInvoiceType()) || "2".equals(invoicingVo.getInvoiceType())){
+                invoice.setInvoiceRiskType("10");
+            }else if("5".equals(invoicingVo.getInvoiceType()) || "6".equals(invoicingVo.getInvoiceType())){
+                invoice.setInvoiceRiskType("30");
+            }else{
+                invoice.setInvoiceRiskType("20");
+            }
+            invoice.setInvoiceParty(invoicingVo.getInvoiceParty());
+            invoice.setOverinflatedAmount(invoicingVo.getOverinflatedAmount());
+            invoice.setReceivableSupervisePremium(invoicingVo.getReceivablePremium());
+            invoice.setTaxPoint(invoicingVo.getTaxPoint());
+
+            List<InsPlyIncomeInvoiceLink> invoicingLinkList = new ArrayList();
+
+            invoicingVo.getIncomeIds().forEach(incomeId -> {
+                InsPlyIncomeInvoiceLink link = new InsPlyIncomeInvoiceLink();
+                link.setId(IdGenerate.nextId());
+                link.setInvoiceId(invoice.getId());
+                link.setIncomeId(incomeId);
+                link.setInvoiceType(invoicingVo.getInvoiceType());
+                invoicingLinkList.add(link);
+            });
+            insPlyIncomeInvoiceLinkMapper.insert(invoicingLinkList);
+            result.setInvoiceId(invoice.getId());
+            result.setSumPrice(null != invoicingVo.getReceivablePremium() ? invoicingVo.getReceivablePremium().toString() : null);
+
+            // ============================结算逻辑============================
+            // 实际已经收了的金额
+            BigDecimal actualReceivedAmount = this.getInvoicingAmount(settlementVo.getInvoicingId());
+
+            // 所有需要结算的金额
+            BigDecimal allToSettlement = invoice.getReceivableSupervisePremium().add(invoice.getOverinflatedAmount());
+            // 剩余的金额
+            BigDecimal surplusPremium = allToSettlement.subtract(actualReceivedAmount);
+            log.info("invoiceId=[{}],一共需要结算的金额[{}],实际已经结算的金额[{}],本次计划结算的金额[{}]",
+                    settlementVo.getInvoicingId(), allToSettlement,actualReceivedAmount,settlementVo.getActualReceivedAmount());
+            // 校验是否超出了剩余的金额
+            AssertionUtils.isFail(surplusPremium.compareTo(settlementVo.getActualReceivedAmount()) < 0, "已超出应收金额,请核对!");
+
+            // 处理结算数据
+            // 未完全结算完成
+            InsPlyIncomeInvoiceSettlement settlement = new InsPlyIncomeInvoiceSettlement(invoice.getId(), settlementVo.getActualReceivedAmount(),
+                    DateTime.now(), settlementVo.getPaymentDifference(), settlementVo.getPaymentReason());
+            insPlyIncomeInvoiceSettlementMapper.insert(settlement);
+
+            if (CollectionUtils.isNotEmpty(settlementVo.getAttachmentIds())) {
+                // 添加发票附件
+                List<InsPlyIncomeInvoiceSettlementFile> files = new ArrayList<>();
+                for (String fileId : settlementVo.getAttachmentIds()) {
+                    InsPlyIncomeInvoiceSettlementFile file = new InsPlyIncomeInvoiceSettlementFile();
+                    file.setId(IdGenerate.nextId());
+                    file.setSettlementId(settlement.getId());
+                    file.setFileId(fileId);
+                    files.add(file);
+                }
+                insPlyIncomeInvoiceSettlementFileMapper.insert(files);
+            }
+
+            // 判断是否已经结算完成
+            if (surplusPremium.compareTo(settlementVo.getActualReceivedAmount()) == 0) {
+                log.info("序号为[{}]的发票已经结算完成",invoice.getId());
+                // 更新发票状态
+                invoice.setStatus("1");
+                insPlyIncomeInvoiceMapper.insert(invoice);
+                // 判断是需要更新哪个字段
+                this.updateIncomeSettlementStatus(invoice.getInvoiceType(), invoicingVo.getIncomeIds());
+            }else{
+                log.info("invoiceId=[{}], 还剩[{}]钱没有结算",settlementVo.getInvoicingId(), surplusPremium.subtract(settlementVo.getActualReceivedAmount()));
+            }
+            return true;
+        } catch (Exception e) {
+            log.error("平台结算异常. settlementVo=[{}]",JSONUtil.toJsonStr(settlementVo), e);
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public boolean settlement(SettlementVo settlementVo) {
@@ -705,15 +876,15 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             // 获取应收的金额
             InsPlyIncomeInvoice insPlyIncomeInvoice = insPlyIncomeInvoiceMapper.selectById(settlementVo.getInvoicingId());
             AssertionUtils.isFail(Objects.isNull(insPlyIncomeInvoice), "发票数据不存在");
-            // 实际已经收的了金额
-            BigDecimal ctualReceivedAmount = this.getInvoicingAmount(settlementVo.getInvoicingId());
+            // 实际已经收了的金额
+            BigDecimal actualReceivedAmount = this.getInvoicingAmount(settlementVo.getInvoicingId());
 
             // 所有需要结算的金额
             BigDecimal allToSettlement = insPlyIncomeInvoice.getReceivableSupervisePremium().add(insPlyIncomeInvoice.getOverinflatedAmount());
             // 剩余的金额
-            BigDecimal surplusPremium = allToSettlement.subtract(ctualReceivedAmount);
+            BigDecimal surplusPremium = allToSettlement.subtract(actualReceivedAmount);
             log.info("invoiceId=[{}],一共需要结算的金额[{}],实际已经结算的金额[{}],本次计划结算的金额[{}]",
-                    settlementVo.getInvoicingId(), allToSettlement,ctualReceivedAmount,settlementVo.getActualReceivedAmount());
+                    settlementVo.getInvoicingId(), allToSettlement,actualReceivedAmount,settlementVo.getActualReceivedAmount());
             // 校验是否超出了剩余的金额
             AssertionUtils.isFail(surplusPremium.compareTo(settlementVo.getActualReceivedAmount()) < 0, "已超出应收金额,请核对!");
 
@@ -724,6 +895,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             insPlyIncomeInvoiceSettlementMapper.insert(settlement);
 
             if (CollectionUtils.isNotEmpty(settlementVo.getAttachmentIds())) {
+                log.info("结算的凭证是:settlementVo.getAttachmentIds()=[{}]", JSONUtil.toJsonStr(settlementVo.getAttachmentIds()));
                 // 添加发票附件
                 List<InsPlyIncomeInvoiceSettlementFile> files = new ArrayList<>();
                 for (String fileId : settlementVo.getAttachmentIds()) {
@@ -779,7 +951,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             List<SuperviseExcelVo> dataList = listener.getDataList();
             return dataList;
         } catch (Exception e) {
-            e.printStackTrace();
+            log.error("导入excel异常。",e);
             return null;
         }
     }
@@ -1080,7 +1252,8 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             // 数据库已存在 → 继续后续校验
             // 判断已开票 / 已结算
             if ("1".equals(existIncome.getSuperviseSettlement()) || "1".equals(existIncome.getOtherSettlement())
-                    || "1".equals(existIncome.getJySuperviseSettlement()) || "1".equals(existIncome.getJyOtherSettlement())) {
+                    || "1".equals(existIncome.getJySuperviseSettlement()) || "1".equals(existIncome.getJyOtherSettlement())
+                    || "1".equals(existIncome.getPlatformSuperviseSettlement()) || "1".equals(existIncome.getPlatformOtherSettlement())) {
                 failedNumber++;
                 vo.setErrorMessage("应收数据已结算");
                 failedExcel.add(vo);
@@ -1428,6 +1601,36 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
     @Override
     public Page<ExportSuperviseSettlementExcelDto> superviseSettlementExcel(Page page, SettlementQueryVo settlementQueryVo) {
         log.info("查询结算手续费结算记录:settlementQueryVo=[{}]", JSONUtil.toJsonStr(settlementQueryVo));
+        // 设置空条件
+        setNoneCondition(settlementQueryVo);
+        Page<ExportSuperviseSettlementExcelDto> exportSuperviseSettlementExcelDtos = baseMapper.superviseSettlementExcelDtos(page, settlementQueryVo);
+        // 补充、转换列表的数据
+        supplementaryListData(exportSuperviseSettlementExcelDtos);
+        return exportSuperviseSettlementExcelDtos;
+    }
+
+    /**
+     * 平台协议结算记录
+     *
+     * @param settlementQueryVo
+     * @return
+     */
+    @Override
+    public Page<ExportSuperviseSettlementExcelDto> platformSettlementExcel(Page page, SettlementQueryVo settlementQueryVo) {
+        log.info("查询平台结算记录:settlementQueryVo=[{}]", JSONUtil.toJsonStr(settlementQueryVo));
+        // 设置空条件
+        setNoneCondition(settlementQueryVo);
+        Page<ExportSuperviseSettlementExcelDto> exportSuperviseSettlementExcelDtos = baseMapper.platformSettlementExcelDtos(page, settlementQueryVo);
+        // 补充、转换列表的数据
+        supplementaryListData(exportSuperviseSettlementExcelDtos);
+        return exportSuperviseSettlementExcelDtos;
+    }
+
+    /**
+     * 设置空条件
+     * @param settlementQueryVo
+     */
+    private static void setNoneCondition(SettlementQueryVo settlementQueryVo) {
         if("30".equals(settlementQueryVo.getInvoiceParty())){
             settlementQueryVo.setInvoiceParty(null);
         }
@@ -1437,7 +1640,13 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         if("30".equals(settlementQueryVo.getStatus())){
             settlementQueryVo.setStatus(null);
         }
-        Page<ExportSuperviseSettlementExcelDto> exportSuperviseSettlementExcelDtos = baseMapper.superviseSettlementExcelDtos(page, settlementQueryVo);
+    }
+
+    /**
+     * 补充、转换列表的数据
+     * @param exportSuperviseSettlementExcelDtos
+     */
+    private void supplementaryListData(Page<ExportSuperviseSettlementExcelDto> exportSuperviseSettlementExcelDtos) {
         exportSuperviseSettlementExcelDtos.getRecords().forEach(dto -> {
             if ("1".equals(dto.getInvoiceParty())) {
                 dto.setInvoiceParty("我方开票");
@@ -1450,6 +1659,8 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
                 case "2" -> dto.setInvoiceType("跟单费");
                 case "3" -> dto.setInvoiceType("驾意险手续费");
                 case "4" -> dto.setInvoiceType("驾意险跟单费");
+                case "5" -> dto.setInvoiceType("平台协议车险应收");
+                case "6" -> dto.setInvoiceType("平台协议非车险应收");
             }
             dto.setInvoiceTypeName(Constant.invoiceRiskTypeMap.get(Objects.toString(dto.getInvoiceType())));
             LambdaQueryWrapper<InsPlyIncomeInvoiceSettlementFile> wrapper = new LambdaQueryWrapper<InsPlyIncomeInvoiceSettlementFile>();
@@ -1469,7 +1680,6 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
                 }
             }
         });
-        return exportSuperviseSettlementExcelDtos;
     }
 
     /**
@@ -1481,20 +1691,23 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
     @Override
     public void exportSuperviseSettlementExcel(Page page, SettlementQueryVo settlementQueryVo) {
         Page<ExportSuperviseSettlementExcelDto> exportSuperviseSettlementExcelDtos = baseMapper.superviseSettlementExcelDtos(page, settlementQueryVo);
-        exportSuperviseSettlementExcelDtos.getRecords().forEach(dto -> {
-            if ("1".equals(dto.getInvoiceParty())) {
-                dto.setInvoiceParty("我方开票");
-            } else if ("2".equals(dto.getInvoiceParty())) {
-                dto.setInvoiceParty("保司开票");
-            }
-            dto.setInvoiceType(Objects.toString(dto.getInvoiceType(),""));
-            switch (dto.getInvoiceType()) {
-                case "1" -> dto.setInvoiceType("手续费");
-                case "2" -> dto.setInvoiceType("跟单费");
-                case "3" -> dto.setInvoiceType("驾意险手续费");
-                case "4" -> dto.setInvoiceType("驾意险跟单费");
-            }
-        });
+        // 补充、转换列表的数据
+        supplementaryListData(exportSuperviseSettlementExcelDtos);
+        List<ExportSuperviseSettlementExcelDto> list = exportSuperviseSettlementExcelDtos.getRecords();
+        EasyExcelUtils.exportForWeb(ServletUtils.getResponse(), ExportSuperviseSettlementExcelDto.class, list, "车险手续费结算明细");
+    }
+
+    /**
+     * 导出平台结算记录excel文件
+     *
+     * @param settlementQueryVo
+     * @return
+     */
+    @Override
+    public void exportPlatformSettlementExcel(Page page, SettlementQueryVo settlementQueryVo) {
+        Page<ExportSuperviseSettlementExcelDto> exportSuperviseSettlementExcelDtos = baseMapper.platformSettlementExcelDtos(page, settlementQueryVo);
+        // 补充、转换列表的数据
+        supplementaryListData(exportSuperviseSettlementExcelDtos);
         List<ExportSuperviseSettlementExcelDto> list = exportSuperviseSettlementExcelDtos.getRecords();
         EasyExcelUtils.exportForWeb(ServletUtils.getResponse(), ExportSuperviseSettlementExcelDto.class, list, "车险手续费结算明细");
     }

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

@@ -510,7 +510,9 @@
         ipii.invoice_type,
         ipii.invoice_party,
         ipii.tax_point,
+        ipi.order_no as orderNo,
         ipiis.actual_received_amount,
+        ipii.receivable_supervise_premium,
         ipiis.receive_payment_date,
         ipiis.create_by ,
         ipiis.create_time
@@ -571,6 +573,78 @@
         order by ipiis.create_time desc
     </select>
 
+    <select id="platformSettlementExcelDtos" resultType="com.jzg.commons.entity.finance.dto.ExportSuperviseSettlementExcelDto">
+        SELECT
+        ipiis.id AS settlementId,
+        -- 拼接需要合并的字段,DISTINCT 去重,SEPARATOR '、' 用顿号分隔
+        GROUP_CONCAT(DISTINCT ipiis.invoice_id SEPARATOR ',') AS invoiceId,
+        GROUP_CONCAT(DISTINCT io.company_id SEPARATOR ',') AS company_id,
+        GROUP_CONCAT(DISTINCT io.company_name SEPARATOR ',') AS company_name,
+        GROUP_CONCAT(DISTINCT ipii.invoice_type SEPARATOR ',') AS invoice_type,
+        GROUP_CONCAT(DISTINCT ipii.invoice_party SEPARATOR ',') AS invoice_party,
+        GROUP_CONCAT(DISTINCT ipii.tax_point SEPARATOR ',') AS tax_point,
+        GROUP_CONCAT(DISTINCT ipi.order_no SEPARATOR ',') AS orderNo,
+        -- 金额/日期这类同一settlementId相同的字段,直接取任意一个即可
+        MAX(ipiis.actual_received_amount) AS actual_received_amount,
+        MAX(ipiis.receive_payment_date) AS receive_payment_date,
+        MAX(ipiis.create_by) AS create_by,
+        MAX(ipiis.create_time) AS create_time
+        FROM ins_ply_income_invoice_settlement ipiis
+        LEFT JOIN ins_ply_income_invoice ipii ON ipii.id = ipiis.invoice_id
+        LEFT JOIN ins_ply_income_invoice_link ipil ON ipil.invoice_id = ipiis.invoice_id
+        LEFT JOIN ins_ply_income ipi ON ipi.id = ipil.income_id
+        LEFT JOIN ins_orders io ON ipi.order_no = io.id
+        LEFT JOIN ptl_agreement agree ON io.agreement_id = agree.id
+        WHERE 1 = 1
+        <if test="settlementQueryVo.settlementIds != null and settlementQueryVo.settlementIds != ''">
+            AND ipiis.id IN
+            <foreach collection="settlementQueryVo.settlementIds" item="settlementId" open="(" separator="," close=")">
+                #{settlementId}
+            </foreach>
+        </if>
+        <if test="settlementQueryVo.invoiceTypes != null and settlementQueryVo.invoiceTypes != ''">
+            AND ipii.invoice_type IN
+            <foreach collection="settlementQueryVo.invoiceTypes" item="invoiceType" open="(" separator="," close=")">
+                #{invoiceType}
+            </foreach>
+        </if>
+        <if test="settlementQueryVo.companyId != null and settlementQueryVo.companyId != ''">
+            and io.company_id = #{settlementQueryVo.companyId}
+        </if>
+        <if test="settlementQueryVo.invoiceParty != null and settlementQueryVo.invoiceParty != ''">
+            and ipii.invoice_party = #{settlementQueryVo.invoiceParty}
+        </if>
+        <if test="settlementQueryVo.invoiceRiskType != null and settlementQueryVo.invoiceRiskType != ''">
+            and ipii.invoice_risk_type = #{settlementQueryVo.invoiceRiskType}
+        </if>
+        <if test="settlementQueryVo.status != null and settlementQueryVo.status != ''">
+            and ipii.status = #{settlementQueryVo.status}
+        </if>
+        <if test="settlementQueryVo.settlementPerson != null and settlementQueryVo.settlementPerson != ''">
+            and ipiis.create_by = #{settlementQueryVo.settlementPerson}
+        </if>
+        <if test="settlementQueryVo.agreementType != null and settlementQueryVo.agreementType != ''">
+            AND (agree.agreement_type = #{settlementQueryVo.agreementType} or agree.agreement_type is null)
+        </if>
+        <if test="settlementQueryVo.invoiceId != null and settlementQueryVo.invoiceId != ''">
+            AND ipiis.invoice_id = #{settlementQueryVo.invoiceId}
+        </if>
+        <if test="settlementQueryVo.settlementId != null and settlementQueryVo.settlementId != ''">
+            AND ipiis.id = #{settlementQueryVo.settlementId}
+        </if>
+        <if test="settlementQueryVo.settlementDateStart != null and settlementQueryVo.settlementDateStart != ''">
+            and ipiis.create_time >= date(#{settlementQueryVo.settlementDateStart})
+        </if>
+        <if test="settlementQueryVo.settlementDateEndStr != null and settlementQueryVo.settlementDateEndStr != ''">
+            and ipiis.create_time &lt;= date(#{settlementQueryVo.settlementDateEndStr})
+        </if>
+        <if test="settlementQueryVo.settlementId != null and settlementQueryVo.settlementId != ''">
+            AND ipiis.id = #{settlementQueryVo.settlementId}
+        </if>
+        GROUP BY ipiis.id
+        order by ipiis.create_time desc
+    </select>
+
 <!--    <select id="getSuperviseSettlementExcelDtos" resultType="com.jzg.commons.entity.finance.dto.ExportSuperviseSettlementExcelDto">-->
 <!--        select-->
 <!--            ipiis.id as settlementId,-->
@@ -638,7 +712,10 @@
         LEFT JOIN ins_ply_income ipi ON ipi.id = ipil.income_id
         LEFT JOIN ins_orders io ON ipi.order_no = io.id
         WHERE
-        1=1
+        1 = 1
+        <if test="settlementQueryVo.settlementId != null and settlementQueryVo.settlementId != ''">
+            and ipiis.id = #{settlementQueryVo.settlementId}
+        </if>
         <if test="settlementQueryVo.settlementIds != null and settlementQueryVo.settlementIds != ''">
             AND ipiis.id IN
             <foreach collection="settlementQueryVo.settlementIds" item="settlementId" open="(" separator="," close=")">