Selaa lähdekoodia

Merge remote-tracking branch 'origin/dev_jzg_lipf_v20260518' into dev_jzg_lipf_v20260518

lipf 4 kuukautta sitten
vanhempi
commit
727d8968e8
16 muutettua tiedostoa jossa 1389 lisäystä ja 290 poistoa
  1. 1 1
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/build/BoHaiCrawlerQuoteResultsVoBuild.java
  2. 2 2
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/component/BoHaiCrawlerRequestComponent.java
  3. 7 7
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/entity/request/BoHaiCrawlerQuotationRequest2.java
  4. 31 1
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/entity/request/BoHaiCrawlerVehicleConfirmationReqeust1.java
  5. 4 5
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/service/impl/BoHaiCrawlerQuoteProcessServiceImpl.java
  6. 267 94
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/service/impl/BoHaiCrawlerRequestImpl.java
  7. 2 2
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/util/PythonExecutor.java
  8. 3 3
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/crawler/util/novel.py
  9. 10 2
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/DateTimeUtil.java
  10. 1 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/service/Impl/ZiJinApiRequestImpl.java
  11. 6 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/build/ZiJinCrawlerQuoteResultsVoBuild.java
  12. 21 6
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/component/ZiJinCrawlerRequestComponent.java
  13. 6 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerGetOrderNoRequest.java
  14. 24 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/entity/request/ZiJinCrawlerQuotationRequest.java
  15. 29 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerQuoteProcessServiceImpl.java
  16. 975 167
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/crawler/service/impl/ZiJinCrawlerRequestImpl.java

+ 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())
 
-

+ 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();
+        }
     }
 
 

+ 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;
     }