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

Merge branch 'master' into wrq_dev

wangrq 3 месяцев назад
Родитель
Сommit
9758b8fca7
32 измененных файлов с 1395 добавлено и 182 удалено
  1. 1 2
      authentication/src/main/java/com/jzg/client/PartnerDistributionClient.java
  2. 3 1
      authentication/src/main/java/com/jzg/controller/AppAuthController.java
  3. 1 6
      authentication/src/main/java/com/jzg/service/impl/InitializePartnerCommissionServiceImpl.java
  4. 4 1
      commons/src/main/java/com/jzg/commons/config/BaseFeignConfig.java
  5. 10 0
      commons/src/main/java/com/jzg/commons/entity/dto/AgreementContactAddParam.java
  6. 14 0
      commons/src/main/java/com/jzg/commons/entity/dto/AgreementContactEditParam.java
  7. 1 1
      commons/src/main/java/com/jzg/commons/entity/dto/PtlAgreementCostExternalAdd.java
  8. 73 0
      commons/src/main/java/com/jzg/commons/entity/quote/vo/orders/InsFeeCalculateRequest.java
  9. 30 0
      commons/src/main/java/com/jzg/commons/entity/quote/vo/orders/InsFeeCalculateResponse.java
  10. 2 2
      commons/src/main/java/com/jzg/commons/entity/vo/DistributionVo.java
  11. 1 1
      partner/src/main/java/com/jzg/controller/DistributionController.java
  12. 2 2
      partner/src/main/java/com/jzg/controller/PartnerUserController.java
  13. 1 1
      partner/src/main/java/com/jzg/mapper/PartnerUserMapper.java
  14. 2 2
      partner/src/main/java/com/jzg/service/Impl/PartnerUserServiceImpl.java
  15. 1 1
      partner/src/main/java/com/jzg/service/PartnerUserService.java
  16. 15 15
      partner/src/main/java/com/jzg/utils/DistributionUtils.java
  17. 0 1
      partner/src/main/resources/mapper/PartnerUserMapper.xml
  18. 22 2
      tenant/insurance/quotation-ansheng/src/main/java/com/jzg/quotation/ansheng/crawler/build/AnShengCrawlerQuoteResultsVoBuild.java
  19. 4 0
      tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/crawler/build/GuoRenCrawlerQuoteResultsVoBuild.java
  20. 16 7
      tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/build/HbCrawlerQuoteResultVoBuild.java
  21. 12 4
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerCarQueryRequest.java
  22. 11 11
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerQuoteRequest.java
  23. 31 17
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/service/Impl/HuaTaiCrawlerRequestImpl.java
  24. 4 4
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/aspect/QuoteVerificationAspect.java
  25. 9 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/InsOrdersController.java
  26. 5 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsOrdersService.java
  27. 11 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeAuditServiceImpl.java
  28. 371 19
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrdersServiceImpl.java
  29. 5 1
      tenant/insurance/quotation-summary/src/main/resources/mapper/InsOrdersMapper.xml
  30. 8 4
      tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/build/ZhongAnCrawlerQuoteResultsVoBuild.java
  31. 34 14
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementCostExternalServiceImpl.java
  32. 691 63
      tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java

+ 1 - 2
authentication/src/main/java/com/jzg/client/PartnerDistributionClient.java

@@ -4,7 +4,6 @@ package com.jzg.client;
 import com.jzg.commons.core.page.HttpResult;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestParam;
 
 @FeignClient(name = "jzg-partner")
@@ -16,6 +15,6 @@ public interface PartnerDistributionClient {
 
 
     @GetMapping("/partnerDistribution/initializeCommissionDetails")
-    HttpResult<Boolean> initializeCommissionDetails(@RequestParam String userId,@RequestHeader("Authorization") String token);
+    HttpResult<Boolean> initializeCommissionDetails(@RequestParam String userId);
 
 }

+ 3 - 1
authentication/src/main/java/com/jzg/controller/AppAuthController.java

@@ -36,6 +36,7 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.context.request.RequestAttributes;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
@@ -102,13 +103,14 @@ public class AppAuthController extends BaseController {
             if (!isApproved){
                 throw new ServletException("当前用户未审核通过");
             }
+            modifyPass(loginFormVo);
+            RequestContextHolder.getRequestAttributes().setAttribute("Authorization",tokenStore.getTokenByUsername(loginFormVo.getMobile()), RequestAttributes.SCOPE_REQUEST);
             HttpResult<Boolean> isTherePartner = partnerDistributionClient.isTherePartner(sysUserJzgInfo.getId());
             if (200 == isTherePartner.getCode()) {
                 if (!isTherePartner.getData()) {
                     throw new ServletException("当前用户无登录权限");
                 }
             }
-            modifyPass(loginFormVo);
             partnerCommissionService.initializePartnerCommission(sysUserJzgInfo.getId(),loginFormVo.getMobile());
         } catch (Exception e) {
             throw new ServletException("当前用户不存在或已注销");

+ 1 - 6
authentication/src/main/java/com/jzg/service/impl/InitializePartnerCommissionServiceImpl.java

@@ -1,11 +1,9 @@
 package com.jzg.service.impl;
 
 import com.jzg.client.PartnerDistributionClient;
-import com.jzg.config.JzgTokenService;
 import com.jzg.service.InitializePartnerCommissionService;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
@@ -14,9 +12,6 @@ import org.springframework.stereotype.Service;
 @Service
 public class InitializePartnerCommissionServiceImpl implements InitializePartnerCommissionService {
 
-    @Autowired
-    private JzgTokenService tokenStore;
-
     @Resource
     private PartnerDistributionClient distributionClient;
 
@@ -24,7 +19,7 @@ public class InitializePartnerCommissionServiceImpl implements InitializePartner
     @Override
     public void initializePartnerCommission(String userId,String mobile) {
         try {
-            distributionClient.initializeCommissionDetails(userId,tokenStore.getTokenByUsername(mobile));
+            distributionClient.initializeCommissionDetails(userId);
         }catch (Exception e){
             log.error("初始化用户佣金失败:{}", e.getMessage(),e);
         }

+ 4 - 1
commons/src/main/java/com/jzg/commons/config/BaseFeignConfig.java

@@ -19,7 +19,10 @@ public class BaseFeignConfig {
             RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
             if (requestAttributes instanceof ServletRequestAttributes) {
                 HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
-                String token = request.getHeader("Authorization");
+                String token = (String) request.getAttribute("Authorization");
+                if (com.jzg.commons.util.StringUtils.isEmpty(token)){
+                    token = request.getHeader("Authorization");
+                }
                 if (token != null) {
                     requestTemplate.header("Authorization", token);
                 }

+ 10 - 0
commons/src/main/java/com/jzg/commons/entity/dto/AgreementContactAddParam.java

@@ -6,6 +6,7 @@ import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Size;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
 @Schema(description = "外部协议表新增dto")
@@ -69,4 +70,13 @@ public class AgreementContactAddParam {
     @Schema(description = "对接管理人id")
     @NotNull(message = "请选择协议管理人")
     private String custodianId;
+
+    @Schema(description = "交强入口手续费比例")
+    private BigDecimal jqEntranceFeeRatio;
+
+    @Schema(description = "商业入口手续费比例")
+    private BigDecimal syEntranceFeeRatio;
+
+    @Schema(description = "驾意入口手续费比例")
+    private BigDecimal jyEntranceFeeRatio;
 }

+ 14 - 0
commons/src/main/java/com/jzg/commons/entity/dto/AgreementContactEditParam.java

@@ -6,6 +6,7 @@ import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Size;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
 @Schema(description = "外部协议表修改dto")
@@ -71,4 +72,17 @@ public class AgreementContactEditParam {
     @Schema(description = "api类型")
     @NotNull(message = "请选择api类型")
     private Integer apiType;
+
+    @Schema(description = "交强入口手续费比例")
+    private BigDecimal jqEntranceFeeRatio;
+
+    @Schema(description = "商业入口手续费比例")
+    private BigDecimal syEntranceFeeRatio;
+
+    @Schema(description = "驾意入口手续费比例")
+    private BigDecimal jyEntranceFeeRatio;
+
+
+
+
 }

+ 1 - 1
commons/src/main/java/com/jzg/commons/entity/dto/PtlAgreementCostExternalAdd.java

@@ -37,7 +37,7 @@ public class PtlAgreementCostExternalAdd {
     @Schema(description = "0-申请审核1-审核通过2-审核未通过")
     private String auditStatus;
 
-    @Schema(description = "是否现询")
+    @Schema(description = "是否现询(0:是,1:否)")
     private String isInquiry;
 
     @Schema(description = "费用描述")

+ 73 - 0
commons/src/main/java/com/jzg/commons/entity/quote/vo/orders/InsFeeCalculateRequest.java

@@ -0,0 +1,73 @@
+package com.jzg.commons.entity.quote.vo.orders;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 费用计算请求参数。
+ * 入口手续费比例从协议(PtlAgreement)自动获取,
+ * 其余费用比例(入口/加投/出口/出口留点)由调用方传入。
+ * @author wh
+ * @date 2026/6/27
+ */
+@Data
+@Schema(description = "费用计算请求")
+public class InsFeeCalculateRequest {
+
+    @Schema(description = "协议ID(用于获取税率因子)", required = true)
+    private String agreementId;
+    @Schema(description = "业务员手机号", required = true)
+    private String mobile;
+
+    // ── 保费 ──
+    @Schema(description = "交强险保费", example = "0")
+    private BigDecimal jqPremium;
+
+    @Schema(description = "商业险保费", example = "0")
+    private BigDecimal syPremium;
+
+    @Schema(description = "驾意险保费", example = "0")
+    private BigDecimal jyPremium;
+
+    // ── 入口比例(百分比,来自 PtlAgreementCostType)──
+    @Schema(description = "交强险入口比例(百分比)", example = "0")
+    private BigDecimal jqInlet;
+
+    @Schema(description = "商业险入口比例(百分比)", example = "0")
+    private BigDecimal syInlet;
+
+    @Schema(description = "驾意险入口比例(百分比)", example = "0")
+    private BigDecimal jyInlet;
+
+    // ── 加投比例(百分比)──
+    @Schema(description = "交强险加投比例(百分比)", example = "0")
+    private BigDecimal jqAddThrow;
+
+    @Schema(description = "商业险加投比例(百分比)", example = "0")
+    private BigDecimal syAddThrow;
+
+    @Schema(description = "驾意险加投比例(百分比)", example = "0")
+    private BigDecimal jyAddThrow;
+
+    // ── 出口比例(百分比)──
+    @Schema(description = "交强险出口比例(百分比)", example = "0")
+    private BigDecimal jqExport;
+
+    @Schema(description = "商业险出口比例(百分比)", example = "0")
+    private BigDecimal syExport;
+
+    @Schema(description = "驾意险出口比例(百分比)", example = "0")
+    private BigDecimal jyExport;
+
+    // ── 出口留点比例(百分比)──
+    @Schema(description = "交强险出口留点比例(百分比)", example = "0")
+    private BigDecimal jqExportKeepPointRatio;
+
+    @Schema(description = "商业险出口留点比例(百分比)", example = "0")
+    private BigDecimal syExportKeepPointRatio;
+
+    @Schema(description = "驾意险出口留点比例(百分比)", example = "0")
+    private BigDecimal jyExportKeepPointRatio;
+}

+ 30 - 0
commons/src/main/java/com/jzg/commons/entity/quote/vo/orders/InsFeeCalculateResponse.java

@@ -0,0 +1,30 @@
+package com.jzg.commons.entity.quote.vo.orders;
+
+import com.jzg.commons.entity.po.InsFeeOrders;
+import com.jzg.commons.entity.vo.PtlAgreementCostRatioVo;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 费用计算响应结果
+ *
+ * @author lipf
+ * @date 2026/6/27
+ */
+@Data
+@NoArgsConstructor
+@Schema(description = "费用计算响应")
+public class InsFeeCalculateResponse {
+
+    @Schema(description = "费用订单明细")
+    private InsFeeOrders feeOrdersVo;
+
+    @Schema(description = "协议费用比例")
+    private PtlAgreementCostRatioVo costRatio;
+
+    public InsFeeCalculateResponse(InsFeeOrders feeOrders, PtlAgreementCostRatioVo costRatio) {
+        this.feeOrdersVo = feeOrders;
+        this.costRatio = costRatio;
+    }
+}

+ 2 - 2
commons/src/main/java/com/jzg/commons/entity/vo/DistributionVo.java

@@ -2,7 +2,7 @@ package com.jzg.commons.entity.vo;
 
 
 import com.jzg.commons.entity.orders.po.InsOrders;
-import com.jzg.commons.entity.orders.po.InsOrdersCosts;
+import com.jzg.commons.entity.po.InsFeeOrders;
 import lombok.Data;
 
 @Data
@@ -12,7 +12,7 @@ public class DistributionVo {
     private InsOrders insOrders;
 
 
-    private InsOrdersCosts ordersCosts;
+    private InsFeeOrders feeOrders;
 
 
     private String licenseNo;

+ 1 - 1
partner/src/main/java/com/jzg/controller/DistributionController.java

@@ -21,7 +21,7 @@ public class DistributionController extends BaseController {
     public HttpResult distribution(@RequestBody DistributionVo vo) {
         try {
             log.info("入参:{}", JSONObject.toJSONString(vo));
-            DistributionUtils.newSaveFeeInfo(vo.getInsOrders(), vo.getOrdersCosts(), vo.getLicenseNo());
+            DistributionUtils.newSaveFeeInfo(vo.getInsOrders(), vo.getFeeOrders(), vo.getLicenseNo());
         } catch (Exception e) {
             log.error("合伙人分销明细数据生成失败:{}", e.getMessage(),e);
         }

+ 2 - 2
partner/src/main/java/com/jzg/controller/PartnerUserController.java

@@ -45,8 +45,8 @@ public class PartnerUserController extends BaseController {
     }
 
     @GetMapping("isTherePartner")
-    public HttpResult isTherePartner(@RequestParam String userId, @RequestParam String systemCode) {
-        return partnerUserService.isTherePartner(userId, systemCode);
+    public HttpResult isTherePartner(@RequestParam String userId) {
+        return partnerUserService.isTherePartner(userId);
     }
 
     @PostMapping("addPartnerRule")

+ 1 - 1
partner/src/main/java/com/jzg/mapper/PartnerUserMapper.java

@@ -209,7 +209,7 @@ public interface PartnerUserMapper extends BaseMapper<PartnerUser> {
 
     PartnerDetailsVo partnerDetails(@Param("userId") String userId);
 
-    List<PartnerUser> selectLoginList(@Param("userId")String userId, @Param("systemCode")String systemCode);
+    List<PartnerUser> selectLoginList(@Param("userId")String userId);
 
     AppUserInfoVo queryAppUserInfoVoByUserId(@Param("userId") String userId);
 

+ 2 - 2
partner/src/main/java/com/jzg/service/Impl/PartnerUserServiceImpl.java

@@ -1753,8 +1753,8 @@ public class PartnerUserServiceImpl extends ServiceImpl<PartnerUserMapper, Partn
     }
 
     @Override
-    public HttpResult isTherePartner(String userId, String systemCode) {
-        List<PartnerUser> partnerUsers = baseMapper.selectLoginList(userId, systemCode);
+    public HttpResult isTherePartner(String userId) {
+        List<PartnerUser> partnerUsers = baseMapper.selectLoginList(userId);
         return HttpResult.ok(CollectionUtil.isNotEmpty(partnerUsers) ? true : false);
     }
 

+ 1 - 1
partner/src/main/java/com/jzg/service/PartnerUserService.java

@@ -99,7 +99,7 @@ public interface PartnerUserService extends IService<PartnerUser> {
 
     HttpResult addPartnerRule(SysUserVo sysUserVo,List<String> gradeList,String token);
 
-    HttpResult isTherePartner(String userId,String systemCode);
+    HttpResult isTherePartner(String userId);
 
     HttpResult enableDisable(String userId,boolean status,String token);
 

+ 15 - 15
partner/src/main/java/com/jzg/utils/DistributionUtils.java

@@ -5,7 +5,7 @@ import cn.hutool.extra.spring.SpringUtil;
 import com.esotericsoftware.minlog.Log;
 import com.jzg.client.OrganizationClient;
 import com.jzg.commons.entity.orders.po.InsOrders;
-import com.jzg.commons.entity.orders.po.InsOrdersCosts;
+import com.jzg.commons.entity.po.InsFeeOrders;
 import com.jzg.commons.entity.po.SysUserJzgInfo;
 import com.jzg.entity.PartnerPremiumDetails;
 import com.jzg.entity.PartnerUser;
@@ -60,8 +60,8 @@ public class DistributionUtils {
     /**
      * 保存新的费用信息
      */
-    public static void newSaveFeeInfo(InsOrders insOrders, InsOrdersCosts ordersCosts, String licenseNo) {
-        if (Objects.isNull(insOrders) || Objects.isNull(ordersCosts) || Objects.isNull(licenseNo)
+    public static void newSaveFeeInfo(InsOrders insOrders, InsFeeOrders feeOrders, String licenseNo) {
+        if (Objects.isNull(insOrders) || Objects.isNull(feeOrders) || Objects.isNull(licenseNo)
                 || Objects.isNull(insOrders.getRealQuoteUserId())) {
             throw new IllegalArgumentException("入参不能为空,订单信息与用户ID必须有效");
         }
@@ -79,9 +79,9 @@ public class DistributionUtils {
             return;
         }
         List<PartnerPremiumDetails> premiumDetailsList = new ArrayList<>();
-        PartnerPremiumDetails premiumDetails = buildPartnerPremiumDetails(partnerUser, insOrders, ordersCosts, licenseNo, userId, userId3, userId4);
+        PartnerPremiumDetails premiumDetails = buildPartnerPremiumDetails(partnerUser, insOrders, feeOrders, licenseNo, userId, userId3, userId4);
         premiumDetailsList.add(premiumDetails);
-        saveFeeLevelInfo(partnerUser.getGrade() - 1, partnerUser.getReferrerId(), insOrders, ordersCosts, licenseNo, userId, premiumDetailsList, userId3, userId4);
+        saveFeeLevelInfo(partnerUser.getGrade() - 1, partnerUser.getReferrerId(), insOrders, feeOrders, licenseNo, userId, premiumDetailsList, userId3, userId4);
         if (!premiumDetailsList.isEmpty()) {
             staticPartnerPremiumDetailsMapper.insert(premiumDetailsList);
         }
@@ -93,7 +93,7 @@ public class DistributionUtils {
      * 保存层级费用信息
      */
     private static void saveFeeLevelInfo(Integer currentGrade, String referrerId,
-            InsOrders insOrders, InsOrdersCosts ordersCosts,String licenseNo, String userId,List<PartnerPremiumDetails> premiumDetailsList,String userId3, String userId4) {
+            InsOrders insOrders,InsFeeOrders feeOrders,String licenseNo, String userId,List<PartnerPremiumDetails> premiumDetailsList,String userId3, String userId4) {
         if (Objects.isNull(currentGrade) || currentGrade <= 0 || Objects.isNull(referrerId)) {
             return;
         }
@@ -102,7 +102,7 @@ public class DistributionUtils {
             return;
         }
         if (Arrays.stream(VALID_GRADES).anyMatch(partnerUser.getGrade()::equals)) {
-            PartnerPremiumDetails premiumDetails = buildPartnerPremiumDetails(partnerUser, insOrders, ordersCosts, licenseNo, userId, userId3, userId4);
+            PartnerPremiumDetails premiumDetails = buildPartnerPremiumDetails(partnerUser, insOrders, feeOrders, licenseNo, userId, userId3, userId4);
             if (partnerUser.isIdentityStatus()) {
                 premiumDetails.setAppStatus(APP_STATUS_PASS);
             }
@@ -111,13 +111,13 @@ public class DistributionUtils {
                     new BigDecimal(premiumDetails.getProportional()), premiumDetails, userId3, userId4
             );
         }
-        saveFeeLevelInfo(currentGrade - 1, partnerUser.getReferrerId(), insOrders, ordersCosts, licenseNo, userId, premiumDetailsList, userId3, userId4);
+        saveFeeLevelInfo(currentGrade - 1, partnerUser.getReferrerId(), insOrders, feeOrders, licenseNo, userId, premiumDetailsList, userId3, userId4);
     }
 
     /**
      * 构建 PartnerPremiumDetails 实例
      */
-    private static PartnerPremiumDetails buildPartnerPremiumDetails(PartnerUser partnerUser, InsOrders insOrders, InsOrdersCosts ordersCosts,
+    private static PartnerPremiumDetails buildPartnerPremiumDetails(PartnerUser partnerUser, InsOrders insOrders,InsFeeOrders feeOrders,
             String licenseNo, String userId, String userId3, String userId4) {
         PartnerPremiumDetails details = new PartnerPremiumDetails();
         details.setUserId(partnerUser.getUserId());
@@ -128,14 +128,14 @@ public class DistributionUtils {
         details.setCompanyId(insOrders.getId());
         details.setDeptId(partnerUser.getDeptId());
         details.setLicenseno(licenseNo);
-        details.setSumpremium(ordersCosts.getSumPremium());
-        details.setJqpremium(ordersCosts.getJqPremium());
-        details.setSypremium(ordersCosts.getSyPremium());
-        details.setJypremium(ordersCosts.getJyPremium());
+        details.setSumpremium(feeOrders.getTotalPremium());
+        details.setJqpremium(feeOrders.getJqPremium());
+        details.setSypremium(feeOrders.getSyPremium());
+        details.setJypremium(feeOrders.getJyPremium());
         BigDecimal commissionRate = CalculateCommissionUtils.calculateCommission(String.valueOf(partnerUser.getGrade()), partnerUser.getUserId(), userId3, userId4);
         details.setProportional(String.valueOf(commissionRate));
-        BigDecimal extractFee = Objects.nonNull(ordersCosts.getSumPremium())
-                ? ordersCosts.getSumPremium().multiply(commissionRate)
+        BigDecimal extractFee = Objects.nonNull(feeOrders.getTotalPremium())
+                ? feeOrders.getTotalPremium().multiply(commissionRate)
                 .divide(PERCENT_DIVISOR, SCALE_2, RoundingMode.DOWN)
                 : BigDecimal.ZERO;
         details.setExtractFee(extractFee);

+ 0 - 1
partner/src/main/resources/mapper/PartnerUserMapper.xml

@@ -1236,7 +1236,6 @@
         <where>
             is_delete = 0
             AND user_id = #{userId}
-            AND system_code = #{systemCode}
             AND grade &lt; 5
         </where>
     </select>

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

@@ -117,7 +117,6 @@ public final class AnShengCrawlerQuoteResultsVoBuild {
         itemList.add(new ScoreItem("basicstring", AnShengCrawlerCalculatePremiumApplyResponse.DataDTO::getBasicstring));
         itemList.add(new ScoreItem("blackDivisor", AnShengCrawlerCalculatePremiumApplyResponse.DataDTO::getBlackDivisor));
         itemList.add(new ScoreItem("comprehensiveScoreStr", AnShengCrawlerCalculatePremiumApplyResponse.DataDTO::getComprehensiveScoreStr));
-        itemList.add(new ScoreItem("riskScore", AnShengCrawlerCalculatePremiumApplyResponse.DataDTO::getRiskScore));
         itemList.add(new ScoreItem("unifiedScore", AnShengCrawlerCalculatePremiumApplyResponse.DataDTO::getUnifiedScore));
 
         final String splitChar = ":";
@@ -125,7 +124,26 @@ public final class AnShengCrawlerQuoteResultsVoBuild {
             String sourceStr = item.valueFunc().apply(data);
             fillScoreItem(scoreArray, splitChar, item.scoreKey(), sourceStr);
         }
+        JSONObject bussinessLevel = JSONObject.of(
+                "scoreName", "统一客户类型-条件",
+                "scoreKey", "bussinessLevel",
+                "score", data.getBussinessLevel()
+        );
+        for (AnShengCrawlerCalculatePremiumApplyResponse.DataDTO.ContractsDTO contract : data.getContracts()) {
+            JSONObject jsonObject = new JSONObject();
+            if (StringUtils.equals("105",contract.getPlanDefine().getPlanCode())){
+                jsonObject.put("scoreName","交强");
+                jsonObject.put("scoreKey","compulsoryInsure");
+                jsonObject.put("score",contract.getPlanDefine().getCompulsoryInsure() ? "是" : "否");
+            }else if (StringUtils.equals("109",contract.getPlanDefine().getPlanCode())){
+                jsonObject.put("scoreName","交强");
+                jsonObject.put("scoreKey","businessInsure");
+                jsonObject.put("score",contract.getPlanDefine().getBusinessInsure() ? "是" : "否");
+            }
 
+            scoreArray.add(jsonObject);
+        }
+        scoreArray.add(bussinessLevel);
         scoreVo.setScoreJson(scoreArray);
         return scoreVo;
     }
@@ -144,7 +162,9 @@ public final class AnShengCrawlerQuoteResultsVoBuild {
         String[] parts = sourceStr.split(splitChar, 2);
         String scoreName = parts.length >= 1 ? parts[0].trim() : "";
         String scoreVal = parts.length >= 2 ? parts[1].trim() : "";
-
+        if (scoreVal.endsWith("分")) {
+            scoreVal = scoreVal.substring(0, scoreVal.length() - 1);
+        }
         JSONObject jsonObj = JSONObject.of(
                 "scoreName", scoreName,
                 "scoreKey", scoreKey,

+ 4 - 0
tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/crawler/build/GuoRenCrawlerQuoteResultsVoBuild.java

@@ -57,6 +57,8 @@ public final class GuoRenCrawlerQuoteResultsVoBuild {
         quoteResultsVo.getCosts().setBiPremium(biPremium); // 注意这里CI和BI保费相同
         quoteResultsVo.getCosts().setNiPremium(bcPremium);
         quoteResultsVo.getCosts().setVvTax(vvTax);
+        String sumPremium = String.valueOf(Integer.parseInt(biPremium) + Double.parseDouble(ciPremium) + Integer.parseInt(bcPremium) + Double.parseDouble(vvTax));
+        quoteResultsVo.getCosts().setSumPremium(sumPremium);
         quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.WAIT_AUDIT);
 
         quoteResultsVo.setCiRiskInfoVo(quoteVo.getCiRiskInfoVo());
@@ -72,6 +74,8 @@ public final class GuoRenCrawlerQuoteResultsVoBuild {
         scoreVo.setLossRation(calculationPremium.getBc().getAutoPriceOutputXOMRespVo().getStrBillELR2());
         scoreVo.setJqLossRation(calculationPremium.getBc().getAutoPriceOutputXOMRespVo().getStrBillCTPELR2());
         scoreVo.setSyLossRation(calculationPremium.getBc().getAutoPriceOutputXOMRespVo().getStrBillCOMELR2());
+        scoreVo.setJqRenewal(Integer.parseInt(calculationPremium.getBc().getPrpTitemCar().getOriginalRouteRenewalFlagci()) + 1 + "");
+        scoreVo.setSyRenewal(Integer.parseInt(calculationPremium.getBc().getPrpTitemCar().getOriginalRouteRenewalFlagbi()) + 1 + "");
 
         // 保司评分
         JSONArray scoreJson = new JSONArray();

+ 16 - 7
tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/build/HbCrawlerQuoteResultVoBuild.java

@@ -1,21 +1,18 @@
 package com.jzg.quotation.hengbang.crawler.build;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 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.commons.entity.quote.vo.QuoteVo;
 import com.jzg.quotation.commons.utils.DateTimeUtil;
 import com.jzg.quotation.hengbang.crawler.entity.response.HbCrawlerProposalResponse;
 import org.apache.http.util.TextUtils;
 
 import java.time.LocalDateTime;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -144,17 +141,29 @@ public final class HbCrawlerQuoteResultVoBuild {
         //商业险数据
         HbCrawlerProposalResponse.BusiCarInsureRiskDTO busiCarInsureRisk = proposalResponse.getBusiCarInsureRisk();
         HbCrawlerProposalResponse.CarInsureShiptaxDTO carInsureShiptax = proposalResponse.getCarInsureShiptax();
+
+        String biPremium = "0";
+        String ciPremium = "0";
+        String vvTax = "0";
+
         if (Objects.nonNull(busiCarInsureRisk)) {
-            quoteResultsVo.getCosts().setBiPremium(busiCarInsureRisk.getSumPremium());
+            biPremium = busiCarInsureRisk.getSumPremium();
+            quoteResultsVo.getCosts().setBiPremium(biPremium);
         }
         if (Objects.nonNull(forceCarInsureRisk)) {
-            quoteResultsVo.getCosts().setCiPremium(forceCarInsureRisk.getSumPremium());
+            ciPremium = forceCarInsureRisk.getSumPremium();
+            quoteResultsVo.getCosts().setCiPremium(ciPremium);
         }
         if (Objects.nonNull(carInsureShiptax)) {
-            quoteResultsVo.getCosts().setVvTax(carInsureShiptax.getSumtax());
+            vvTax = carInsureShiptax.getSumtax();
+            quoteResultsVo.getCosts().setVvTax(vvTax);
         }
         //设置非车保费
         quoteResultsVo.getCosts().setNiPremium(proposalResponse.getAccidentTotalPremium());
+        String sumPremium = String.valueOf(Integer.parseInt(biPremium) + Integer.parseInt(ciPremium) + Integer.parseInt(vvTax));
+        quoteResultsVo.getCosts().setSumPremium(sumPremium);
+
+
     }
 
 }

+ 12 - 4
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerCarQueryRequest.java

@@ -5,12 +5,14 @@ import com.alibaba.fastjson.JSON;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.jzg.commons.entity.quote.vo.CarInfoVo;
 import com.jzg.commons.exception.SystemException;
+import com.jzg.commons.util.StringUtils;
 import com.jzg.quotation.huatai.crawler.util.HuaTaiCryptUtil;
 import lombok.Data;
 
 import java.io.Serial;
 import java.io.Serializable;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @description: 华泰财险 查询车型 请求参数
@@ -22,9 +24,9 @@ public class HtCrawlerCarQueryRequest implements Serializable {
     @Serial
     private static final long serialVersionUID = 3366912683677575492L;
 
-    public HtCrawlerCarQueryRequest(CarInfoVo carInfoVo, String modelcodexh) {
+    public HtCrawlerCarQueryRequest(CarInfoVo carInfoVo, String modelcodexh, Map<String, Object> xbResult) {
         DataDTO dataDTO = new DataDTO();
-        dataDTO.setVehicleModel("");//carInfoVo.getBrandName()
+        dataDTO.setVehicleModel(carInfoVo.getBrandName());//carInfoVo.getBrandName()
         // 车辆类型自动判断
         if ("04".equals(carInfoVo.getVehicleUseCode())) {
             dataDTO.setMotortypecode("H0");
@@ -63,11 +65,17 @@ public class HtCrawlerCarQueryRequest implements Serializable {
         dataDTO.setLicenseplateno(carInfoVo.getLicenseNo());
         dataDTO.setEngineno(carInfoVo.getEngineNo());
         dataDTO.setVehicleregisterdate(carInfoVo.getRegisterDate());
+
+        if(StringUtils.isBlank(modelcodexh)) {
+            dataDTO.setJLlxVehicleList(xbResult.get("jLlxVehiclelList")==null?"":xbResult.get("jLlxVehiclelList").toString());
+        }
+
 //        dataDTO.setFueltype("");
 //        dataDTO.setPurerange("");
         dataDTO.setModelflag("1");
         dataDTO.setModelcodexh(modelcodexh);
         String data = JSON.toJSONString(dataDTO);
+        System.out.println("HtCrawlerCarQueryRequest,dataDTO:"+data);
         String key = HuaTaiCryptUtil.generateKey(16);
         try {
             String accessToken = HuaTaiCryptUtil.RSAEncrypt(key);
@@ -105,14 +113,14 @@ public class HtCrawlerCarQueryRequest implements Serializable {
      *   "modelflag": "1",
      *   "checkcode": "",
      *   "gdjgvehiclecheckflag": "",
-     *   "jLlxVehicleList": "{}"
+     *   "jLlxVehicleList": "{}"  "[{\"vehicleCode\":\"BMI1099DGB\",\"vehicleName\":\"迷你MINI COOPER 1.6L轿车\"}]"
      * }
      */
     @Data
     public static class DataDTO implements Serializable {
         @Serial
         private static final long serialVersionUID = -921901450062929380L;
-        @JsonProperty("vehicleModel")
+        @JsonProperty("vehiclemodel")
         private String vehicleModel;
         @JsonProperty("motortypecode")
         private String motortypecode;

+ 11 - 11
tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/entity/Request/HtCrawlerQuoteRequest.java

@@ -72,11 +72,11 @@ public class HtCrawlerQuoteRequest implements Serializable {
             RiskInfoVo ciRiskInfoVo = quoteVo.getCiRiskInfoVo();
             RiskInfoVo biRiskInfoVo = quoteVo.getBiRiskInfoVo();
             VehicleAndVesselTaxVo taxVo = quoteVo.getVehicleAndVesselTaxVo();
-            this.isFirstCount = "false";
-            if (limitAmount.contains(",")) {
-                this.transferFlag = limitAmount.split(",")[1];
-            }
-            this.isGlmPrice = 0;
+            this.isFirstCount = "true";
+            //if (limitAmount.contains(",")) {
+            //    this.transferFlag = limitAmount.split(",")[1];
+            //}
+            this.isGlmPrice = "3";
             if (ciRiskInfoVo != null) {
                 this.isInsureTraffic = "true";
             } else {
@@ -87,7 +87,7 @@ public class HtCrawlerQuoteRequest implements Serializable {
             } else {
                 this.isInsureBusi = false;
             }
-            this.afloatValue = "0.0";
+            //this.afloatValue = "";
             this.hastax = this.isInsureTraffic;
             this.mealid = StringUtils.isBlank(mealid) ? "" : mealid;
             List<CovListDTO> covListDTOS = getCovListDTOS(quoteVo, limitAmount.contains(",") ? limitAmount.split(",")[0] : limitAmount);
@@ -324,17 +324,17 @@ public class HtCrawlerQuoteRequest implements Serializable {
 
             return personalInsuredDTOList;
         }
-        @JsonProperty("afloatValue")
-        private String afloatValue;
+        //@JsonProperty("afloatValue")
+        //private String afloatValue;
 
         @JsonProperty("isFirstCount")
         private String isFirstCount;
 
-        @JsonProperty("transferFlag")
-        private String transferFlag;
+        //@JsonProperty("transferFlag")
+        //private String transferFlag="";
 
         @JsonProperty("isGlmPrice")
-        private Integer isGlmPrice;
+        private String isGlmPrice;
 
         @JsonProperty("isInsureTraffic")
         private String isInsureTraffic;

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

@@ -187,14 +187,14 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
         Map<String, Object> m = new HashMap<>();
         m.put("licenseplateno", car.getLicenseNo());
         m.put("vin", car.getVinNo());
-        m.put("engineno", car.getEngineNo());
-        m.put("liceenseplatetype", car.getLicenseKindCode());
+        m.put("engineno", "");
+        m.put("liceenseplatetype", "02 小型汽车号牌");//
         m.put("ecdemicvehicleflag", "0");
         fillVehicleTypeCodes(car, m);
         m.put("xbcomcode", XBCOM_CODE);
         m.put("quotationNo", quotationNo);
         m.put("riskCode", RISK_CODE);
-        m.putAll(Map.of("engineno2", "", "enrollDate", "", "isJllxFlagType", "1",
+        m.putAll(Map.of("engineno2", car.getEngineNo(), "enrollDate", car.getRegisterDate(), "isJllxFlagType", "1",
                 "carModelCodexhQuery", "1", "telemarketFlag", ""));
         return m;
     }
@@ -221,9 +221,12 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
         }, MAX_RETRIES, RETRY_DELAY_MS, "预报价获取登录信息");
 
         String quotationNo = str(xbResult, "quotationNo");
-        String modelcodexh = str(xbResult, "modelcodexh");
+        String modelcodexh = StringUtils.isBlank(str(xbResult, "modelcodexh")) ? car.getCarModelNo() : str(xbResult, "modelcodexh");
+        log.info("modelcodexh: {}", str(xbResult, "modelcodexh"));
+        log.info("modelcodexh: {}", modelcodexh);
+
         // 报价前预处理-保存车辆信息、过滤车型等处理
-        PreResult pre = prepareQuote(attr, mmap, car, modelcodexh, cookie, quotationNo);
+        PreResult pre = prepareQuote(attr, mmap, car, modelcodexh, cookie, quotationNo, xbResult);
         // 报价
         CoreResult core = executeQuote(quoteVo, quotationNo, dto, cookie, pre, gsInfo, attr);
         if (!core.success()) throw new SystemException("报价失败");
@@ -286,21 +289,33 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
 
     // ====================== 报价预处理 ======================
     private PreResult prepareQuote(AttributionInformationVo attr, Map<String, Object> mmap,
-                                   CarInfoVo car, String modelcodexh, String cookie, String quotationNo) throws Exception {
+                                   CarInfoVo car, String modelcodexh, String cookie, String quotationNo, Map<String, Object> xbResult) throws Exception {
         HtCrawlerConfigureParameters params = ConfigureParametersConversion.conversionEntity(
                 HtCrawlerConfigureParameters.class, attr.getConfigInfo());
         params.setFullComCode(params.getComCode());
-        //参数格式保持一致
+        //参数格式保持一致--方便过滤
         car.setPurchasePrice(car.getPurchasePrice().replace(".00", ""));
         //车辆查询
-        HtCrawlerCarQueryResponse.DataDTO dataDTO = req.carQuery(
-                new HtCrawlerCarQueryRequest(car, modelcodexh), req.getHeaders1(), car);
+        HtCrawlerCarQueryResponse.DataDTO dataDTO = req.carQuery(new HtCrawlerCarQueryRequest(car, modelcodexh, xbResult), req.getHeaders1(), car);
         //过滤车辆
-        HtCrawlerCarQueryResponse.DataDTO.DataListDTO carDTO = CarModelsFilterUtils.to(dataDTO.getDatalist(), car);
+        HtCrawlerCarQueryResponse.DataDTO.DataListDTO carDTO = null;
+        if(dataDTO.getDatalist() != null && !dataDTO.getDatalist().isEmpty()) {
+            carDTO = CarModelsFilterUtils.to(dataDTO.getDatalist(), car);
+        }
+        log.info("车辆查询,carDTO,{}",carDTO);
+        if (carDTO == null) {
+            // 未匹配则第二次carquery,带modelCName-->vehiclemodel
+            //dataDTO = req.carQuery(new HtCrawlerCarQueryRequest2(car), req.getHeaders1(), car);
+            dataDTO = req.carQuery(new HtCrawlerCarQueryRequest(car, "", xbResult), req.getHeaders1(), car);
+            log.info("未匹配则第二次车辆查询,dataDTO,{}",JSONObject.toJSONString(dataDTO));
+            //过滤车辆
+            carDTO = CarModelsFilterUtils.to(dataDTO.getDatalist(), car);
+            log.info("未匹配则第二次车辆查询,carDTO,{}",JSONObject.toJSONString(carDTO));
+        }
         log.info("过滤后的车型carDTO: {}", JSONObject.toJSONString(carDTO));
         //保存车辆信息
         executeSaveCarQuery(carDTO, dataDTO, car, cookie);
-        //车型查询
+        //车型查询 -- renewCarInfo
         String carData = executeCarModelCodexhQuery(carDTO, car, cookie, quotationNo);
         // 核心:关闭「未知字段抛出异常」,优先级 > 类注解
         MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
@@ -323,8 +338,9 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
             dataDTO.setDatalist2(dataList2);
             //过滤车型
             carDTO = CarModelsFilterUtils.to(dataDTO.getDatalist(), car);
+            log.info("二次过滤后的车型carDTO: {}", JSONObject.toJSONString(carDTO));
         }
-        //额外请求
+        //额外请求--消息中心心跳
         executeMessageCentreTimeBoom(cookie);
         //以上请求模拟浏览器请求流程,否则报价失败
         return new PreResult(params, dataDTO, carDTO);
@@ -343,14 +359,14 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
         fd.add("vin", car.getVinNo());
         fd.add("modelcodexh", carDTO.getModelcodexh());
         fd.add("VehicleStyleUniqueId", "");
-
+        log.info("executeSaveCarQuery,{}",JSONObject.toJSONString(fd));
         post(BASE_URL + "/htcsp/VehicleInfoEntryAction.do?cmd=savecarquery", buildCarQueryHeaders(cookie), fd);
     }
 
     private String executeCarModelCodexhQuery(HtCrawlerCarQueryResponse.DataDTO.DataListDTO carDTO,
                                             CarInfoVo car, String cookie, String quotationNo) {
         MultiValueMap<String, String> fd = new LinkedMultiValueMap<>();
-        fd.add("modelCode", carDTO.getModelcodexh());
+        fd.add("modelCode", "BCHFCBUB0001");
         fd.add("licenseNo", car.getLicenseNo());
         fd.add("licenseKindCode", "02 小型汽车号牌");
         fd.add("engineNo", car.getEngineNo());
@@ -477,7 +493,7 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
                         AttributionInformationVo attr = q.getOrder().getAttributionInformationVo();
                         log.info(map.get("unMatchVehicleFrameMessage")+"已重新执行prepareQuote,新modelcodexh:{}", currentModelCodexh);
                         currentPre = prepareQuote(attr, gsInfo, q.getCarInfoVo(),
-                                currentModelCodexh, cookie, quotationNo);
+                                currentModelCodexh, cookie, quotationNo, map);
                         executeQuoteSteps(q, quotationNo, dto, cookie, currentPre, gsInfo);
 
                         // 跳过当前循环,重新执行报价流程
@@ -695,11 +711,9 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
                         String chesun_startDate = m.group(1);
                         log.info("报价响应结果BI,终保日期{}", chesun_startDate);
                         duplQuoteResult.q().getBiRiskInfoVo().setStartDate(chesun_startDate);
-                        duplQuoteResult.q().getCiRiskInfoVo().setStartDate(chesun_startDate);
                         LocalDateTime dt = LocalDateTime.parse(chesun_startDate.replace(" ", "T"), DateTimeFormatter.ofPattern(DATE_FMT_T));
                         String newEnd = dt.plusYears(1).format(DateTimeFormatter.ofPattern(DATE_FMT));
                         duplQuoteResult.q().getBiRiskInfoVo().setEndDate(newEnd);
-                        duplQuoteResult.q().getCiRiskInfoVo().setEndDate(newEnd);
                         decryptData = req.quote(new HtCrawlerQuoteRequest(duplQuoteResult.q(), mealid, limitAmount, "", personalInsuredJSON), h);
                         return resolveQuoteResponse(duplQuoteResult, decryptData, mealid, limitAmount, h, personalInsuredJSON);
                     }

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

@@ -579,9 +579,9 @@ public class QuoteVerificationAspect {
                 ? insFeeOrders.getJyKeepPointRatio() : BigDecimal.ZERO);
 
         // 出口比例 = 出口比例 - 分销比例
-        BigDecimal firstDistributionRatio = insFeeOrders.getFirstDistributionRatio();
-        BigDecimal secondDistributionRatio = insFeeOrders.getSecondDistributionRatio();
-        BigDecimal thirdDistributionRatio = insFeeOrders.getThirdDistributionRatio();
+        BigDecimal firstDistributionRatio = Optional.ofNullable(insFeeOrders.getFirstDistributionRatio()).orElse(BigDecimal.ZERO);
+        BigDecimal secondDistributionRatio = Optional.ofNullable(insFeeOrders.getSecondDistributionRatio()).orElse(BigDecimal.ZERO);
+        BigDecimal thirdDistributionRatio = Optional.ofNullable(insFeeOrders.getThirdDistributionRatio()).orElse(BigDecimal.ZERO);
         insFeeOrders.setJqExportRatio(jqCostType == null ? BigDecimal.ZERO :
                         (jqCostType.getExport() != null && jqCostType.getExport().compareTo(BigDecimal.ZERO) > 0
                                 ? convertPercent(jqCostType.getExport()).subtract(firstDistributionRatio).subtract(secondDistributionRatio).subtract(thirdDistributionRatio)
@@ -622,7 +622,7 @@ public class QuoteVerificationAspect {
         if (sysDistributionSetting != null) {
             // 判断业务员所属机构是否被排除
             // 1.获取业务员所属机构
-            String deptId = baseController.getUserDeptId();
+            String deptId = sysUserJzgInfoResult.getData().getDeptId();
             HttpResult<SysDeptVo> sysDept = orgClient.deptGet(deptId);
             if (sysDept.getData() != null && sysDept.getData().getIsDistribution().equals("1")) {
                 // 获取租户分销设置为几级分销

+ 9 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/InsOrdersController.java

@@ -18,6 +18,8 @@ import com.jzg.commons.entity.po.InsFeeOrders;
 import com.jzg.commons.entity.quote.vo.KindInfoVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.commons.entity.quote.vo.aggregated.QuoteEchoVo;
+import com.jzg.commons.entity.quote.vo.orders.InsFeeCalculateRequest;
+import com.jzg.commons.entity.quote.vo.orders.InsFeeCalculateResponse;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersAdd;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersEnd;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersVo;
@@ -74,6 +76,13 @@ public class InsOrdersController extends BaseController {
         return insOrdersService.saveOrders(ordersAdd);
     }
 
+    @Operation(summary = "计算补录单费用")
+    @PostMapping("cvalculateFees")
+    public HttpResult<InsFeeCalculateResponse> cvalculateFees(@RequestBody InsFeeCalculateRequest request) {
+        return insOrdersService.cvalculateFees(request);
+    }
+
+
     @OperatorTrajectory(moduleName = "车险订单/补录订单修改)",mapperClass = InsOrdersMapper.class,entityClass = InsOrdersAdd.class,isRecorded = "insOrders.isTemporarily")
     @Operation(summary = "录入订单修改")
     @PostMapping("updateOrders")

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

@@ -10,6 +10,7 @@ import com.jzg.commons.entity.enums.MessageCodeEnum;
 import com.jzg.commons.entity.finance.vo.BatchModifyVo;
 import com.jzg.commons.entity.orders.po.InsOrders;
 import com.jzg.commons.entity.orders.po.InsOrdersCarInfo;
+
 import com.jzg.commons.entity.orders.po.InsOrdersCosts;
 import com.jzg.commons.entity.orders.vo.HistoryQuoteQueryVo;
 import com.jzg.commons.entity.orders.vo.HistoryQuoteResultVo;
@@ -25,6 +26,8 @@ import com.jzg.commons.entity.vo.OrdersListVo;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersAdd;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersEnd;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersVo;
+import com.jzg.commons.entity.quote.vo.orders.InsFeeCalculateRequest;
+import com.jzg.commons.entity.quote.vo.orders.InsFeeCalculateResponse;
 import com.jzg.quotation.summary.entity.vo.*;
 
 import java.lang.reflect.InvocationTargetException;
@@ -293,4 +296,6 @@ public interface InsOrdersService extends IService<InsOrders> {
      * @date 2026/6/18 9:49
      */
     BigDecimal obtainTaxRate(String orderNo);
+
+    HttpResult<InsFeeCalculateResponse> cvalculateFees(InsFeeCalculateRequest request);
 }

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

@@ -31,6 +31,7 @@ import com.jzg.commons.util.StringUtils;
 import com.jzg.commons.util.idgen.IdGenerate;
 import com.jzg.quotation.commons.client.OrgClient;
 import com.jzg.quotation.commons.client.PartnerClient;
+import com.jzg.quotation.commons.client.PartnerDistributionClient;
 import com.jzg.quotation.commons.client.PlatformClient;
 import com.jzg.quotation.summary.client.EsmInsCompanyClient;
 import com.jzg.quotation.summary.client.LocalLivingClient;
@@ -110,6 +111,9 @@ public class InsFeeAuditServiceImpl extends ServiceImpl<InsFeeAuditMapper, InsFe
     @Autowired
     private InsFeeOrdersService feeOrdersService;
 
+    @Autowired
+    InsOrdersCarInfoService insOrdersCarInfoService;
+
     @Autowired
     private AuditStateListener auditStateListener;
     @Autowired
@@ -124,6 +128,7 @@ public class InsFeeAuditServiceImpl extends ServiceImpl<InsFeeAuditMapper, InsFe
 
     private final LocalLivingClient localLivingClient;
 
+    private final PartnerDistributionClient partnerDistributionClient;
 
     @Override
     public Page<FeeAuditVo> queryPage(FeeAuditParam param) {
@@ -523,6 +528,12 @@ public class InsFeeAuditServiceImpl extends ServiceImpl<InsFeeAuditMapper, InsFe
 
         //合伙人佣金比例
         try {
+            DistributionVo vo = new DistributionVo();
+            vo.setInsOrders(orders);
+            vo.setFeeOrders(feeOrders);
+            InsOrdersCarInfo carInfo = insOrdersCarInfoService.getByOrderId(audit.getOrderNo());
+            vo.setLicenseNo(carInfo.getLicenseNo());
+            partnerDistributionClient.distribution(vo);
             partnerClient.extractFeeSave(orders.getQuoteNo(),orders.getId());
         }catch (Exception e){
             log.error("保存合伙人佣金计算异常:{}",e.getMessage(), e);

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

@@ -36,6 +36,8 @@ import com.jzg.commons.entity.quote.vo.aggregated.QuoteEchoVo;
 import com.jzg.commons.entity.quote.vo.aggregated.QuoteResultsVo;
 import com.jzg.commons.entity.quote.vo.aggregated.UnderwritingResultsVo;
 import com.jzg.commons.entity.quote.vo.image.InsuranceImageVo;
+import com.jzg.commons.entity.quote.vo.orders.InsFeeCalculateRequest;
+import com.jzg.commons.entity.quote.vo.orders.InsFeeCalculateResponse;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersAdd;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersEnd;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersVo;
@@ -46,10 +48,10 @@ import com.jzg.commons.exception.SystemException;
 import com.jzg.commons.util.*;
 import com.jzg.commons.util.idgen.IdGenerate;
 import com.jzg.quotation.commons.client.OrgClient;
-import com.jzg.quotation.commons.client.PartnerDistributionClient;
 import com.jzg.quotation.commons.client.PlatformClient;
 import com.jzg.quotation.commons.utils.BeanCopyUtil;
 import com.jzg.quotation.commons.utils.SnowFlakeUtil;
+import com.jzg.quotation.summary.aop.aspect.QuoteVerificationAspect;
 import com.jzg.quotation.summary.consumer.template.OrderMessageTemplate;
 import com.jzg.quotation.summary.entity.bo.DataValueBo;
 import com.jzg.quotation.summary.entity.vo.*;
@@ -73,6 +75,7 @@ import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.net.URL;
 import java.time.Instant;
 import java.time.LocalDate;
@@ -115,8 +118,6 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
 
     private final PlatformClient platformClient;
 
-    private final PartnerDistributionClient partnerDistributionClient;
-
     private final BaseController baseController;
 
     private final InsOrderAdjustInfoService orderAdjustInfoService;
@@ -529,17 +530,21 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
                 .eq(InsFeeOrders::getOrderNo, insOrdersVo.getInsOrders().getId()));
         // 比例信息 分销员信息
         if (insFeeOrders != null) {
-            HttpResult<SysUserJzgInfo> firstDistributor = orgClient.getUserInfoById(insFeeOrders.getFirstDistributorId());
-            HttpResult<SysUserJzgInfo> secondDistributor = orgClient.getUserInfoById(insFeeOrders.getSecondDistributorId());
-            HttpResult<SysUserJzgInfo> thirdDistributor = orgClient.getUserInfoById(insFeeOrders.getThirdDistributorId());
-            if (firstDistributor.getData() != null) {
-                insFeeOrders.setFirstDistributorName(firstDistributor.getData().getName());
-            }
-            if (secondDistributor.getData() != null) {
-                insFeeOrders.setSecondDistributorName(secondDistributor.getData().getName());
-            }
-            if (thirdDistributor.getData() != null) {
-                insFeeOrders.setThirdDistributorName(thirdDistributor.getData().getName());
+            if(insFeeOrders.getFirstDistributorId() != null && insFeeOrders.getSecondDistributorId() != null &&
+                    insFeeOrders.getThirdDistributorId() != null){
+                HttpResult<SysUserJzgInfo> firstDistributor = orgClient.getUserInfoById(insFeeOrders.getFirstDistributorId());
+                HttpResult<SysUserJzgInfo> secondDistributor = orgClient.getUserInfoById(insFeeOrders.getSecondDistributorId());
+                HttpResult<SysUserJzgInfo> thirdDistributor = orgClient.getUserInfoById(insFeeOrders.getThirdDistributorId());
+                if (firstDistributor.getData() != null) {
+                    insFeeOrders.setFirstDistributorName(firstDistributor.getData().getName());
+                }
+                if (secondDistributor.getData() != null) {
+                    insFeeOrders.setSecondDistributorName(secondDistributor.getData().getName());
+                }
+                if (thirdDistributor.getData() != null) {
+                    insFeeOrders.setThirdDistributorName(thirdDistributor.getData().getName());
+                }
+
             }
             insOrdersVo.setCostRatio(new PtlAgreementCostRatioVo(insFeeOrders));
             insOrdersVo.setFeeOrdersVo(new InsFeeOrdersVo(insFeeOrders));
@@ -1500,11 +1505,6 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
             this.orderStatusMessage(insOrders,
                     insOrdersCarInfo, costs,
                     baseController.getToken(), MessageCodeEnum.TEMPLATE_6);
-            DistributionVo vo = new DistributionVo();
-            vo.setInsOrders(insOrders);
-            vo.setOrdersCosts(costs);
-            vo.setLicenseNo(insOrdersCarInfo.getLicenseNo());
-            partnerDistributionClient.distribution(vo);
         } else {
             insOrders.setErrorMessage(orderStatusResultVo.getErrorMsg());
         }
@@ -1698,6 +1698,358 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
         return taxFactor;
     }
 
+    /**
+     * 计算保单费用(应收/应付/手续费/跟单费/留点费/出口费等)。
+     * 本方法为纯计算接口,不需要已有订单,直接根据保费和费用比例计算费用明细。
+     * 入口手续费比例从协议(PtlAgreement)自动获取,其余费用比例由调用方传入。
+     *
+     * @param request 保费 + 各险种费用比例(入口/加投/出口/出口留点)
+     * @return InsFeeCalculateResponse(费用明细 + 协议费用比例VO)
+     */
+    @Override
+    public HttpResult<InsFeeCalculateResponse> cvalculateFees(InsFeeCalculateRequest request) {
+        String agreementId = request.getAgreementId();
+        // 保费 & 所有比例字段 null → 0
+        BigDecimal jqPremium  = nvl(request.getJqPremium());
+        BigDecimal syPremium  = nvl(request.getSyPremium());
+        BigDecimal jyPremium  = nvl(request.getJyPremium());
+        BigDecimal sumPremium = jqPremium.add(syPremium).add(jyPremium);
+        BigDecimal jqInlet    = nvl(request.getJqInlet());
+        BigDecimal syInlet    = nvl(request.getSyInlet());
+        BigDecimal jyInlet    = nvl(request.getJyInlet());
+        BigDecimal jqAddThrow = nvl(request.getJqAddThrow());
+        BigDecimal syAddThrow = nvl(request.getSyAddThrow());
+        BigDecimal jyAddThrow = nvl(request.getJyAddThrow());
+        BigDecimal jqExport   = nvl(request.getJqExport());
+        BigDecimal syExport   = nvl(request.getSyExport());
+        BigDecimal jyExport   = nvl(request.getJyExport());
+        BigDecimal jqEKP      = nvl(request.getJqExportKeepPointRatio());
+        BigDecimal syEKP      = nvl(request.getSyExportKeepPointRatio());
+        BigDecimal jyEKP      = nvl(request.getJyExportKeepPointRatio());
+
+        // 1. 查询协议(同时获取入口手续费比例 + 税率因子,一次查询)
+        PtlAgreement ptlAgreement = orgClient.getByAgreementId(agreementId);
+        if (ptlAgreement == null) {
+            throw new ServiceException(String.format("协议不存在,协议编号=%s", agreementId));
+        }
+        // 入口手续费比例(来自协议 PtlAgreement)
+        BigDecimal jqRatio = ptlAgreement.getJqEntranceFeeRatio();
+        BigDecimal syRatio = ptlAgreement.getSyEntranceFeeRatio();
+        BigDecimal jyRatio = ptlAgreement.getJyEntranceFeeRatio();
+        // 税率因子(协议含税→1,不含税→1.06)
+        BigDecimal taxFactor = resolveTaxFactor(ptlAgreement);
+
+        // 2. 从请求构建各险种费用类型配置(入口/加投/出口/出口留点)
+        PtlAgreementCostTypeVo jqCostType = buildCostType(jqInlet, jqAddThrow, jqExport, jqEKP);
+        PtlAgreementCostTypeVo syCostType = buildCostType(syInlet, syAddThrow, syExport, syEKP);
+        PtlAgreementCostTypeVo jyCostType = buildCostType(jyInlet, jyAddThrow, jyExport, jyEKP);
+
+        // 3. 入口手续费比例上限控制
+        jqRatio = capRatio(jqRatio, jqCostType);
+        syRatio = capRatio(syRatio, syCostType);
+        jyRatio = capRatio(jyRatio, jyCostType);
+
+        // 4. 跟单费比例 = 入口比例 - 手续费比例
+        BigDecimal jqFollow = calcFollowRatio(jqCostType, jqRatio);
+        BigDecimal syFollow = calcFollowRatio(syCostType, syRatio);
+        BigDecimal jyFollow = calcFollowRatio(jyCostType, jyRatio);
+
+        // 5. 组装 InsFeeOrders
+        InsFeeOrders feeOrders = new InsFeeOrders();
+        feeOrders.setAgreementId(agreementId);
+        feeOrders.setJqPremium(jqPremium);
+        feeOrders.setSyPremium(syPremium);
+        feeOrders.setJyPremium(jyPremium);
+        feeOrders.setTotalPremium(sumPremium);
+        feeOrders.setJqFollowRatio(jqFollow);
+        feeOrders.setSyFollowRatio(syFollow);
+        feeOrders.setJyFollowRatio(jyFollow);
+
+        // 6. 各险种费用计算(应收/应付/手续费/跟单费/加投费/留点)
+        calcInsuranceType(feeOrders, jqPremium, jqCostType, jqRatio, jqFollow, taxFactor, "jq");
+        calcInsuranceType(feeOrders, syPremium, syCostType, syRatio, syFollow, taxFactor, "sy");
+        calcInsuranceType(feeOrders, jyPremium, jyCostType, jyRatio, jyFollow, taxFactor, "jy");
+
+        // 7. 保存各比例(小数)到 feeOrders
+        // 保存各比例到 feeOrders
+        feeOrders.setJqCommissionRatio(div100(ptlAgreement.getJqEntranceFeeRatio()));
+        feeOrders.setSyCommissionRatio(div100(ptlAgreement.getSyEntranceFeeRatio()));
+        feeOrders.setJyCommissionRatio(div100(ptlAgreement.getJyEntranceFeeRatio()));
+        feeOrders.setJqInletRatio(div100(jqInlet));
+        feeOrders.setSyInletRatio(div100(syInlet));
+        feeOrders.setJyInletRatio(div100(jyInlet));
+        feeOrders.setJqFollowRatio(nvl(feeOrders.getJqFollowRatio()));
+        feeOrders.setSyFollowRatio(nvl(feeOrders.getSyFollowRatio()));
+        feeOrders.setJyFollowRatio(nvl(feeOrders.getJyFollowRatio()));
+        feeOrders.setJqAdditionalRatio(div100(jqAddThrow));
+        feeOrders.setSyAdditionalRatio(div100(syAddThrow));
+        feeOrders.setJyAdditionalRatio(div100(jyAddThrow));
+        feeOrders.setJqKeepPointRatio(nvl(feeOrders.getJqKeepPointRatio()));
+        feeOrders.setSyKeepPointRatio(nvl(feeOrders.getSyKeepPointRatio()));
+        feeOrders.setJyKeepPointRatio(nvl(feeOrders.getJyKeepPointRatio()));
+        feeOrders.setJqExportRatio(div100(jqExport));
+        feeOrders.setSyExportRatio(div100(syExport));
+        feeOrders.setJyExportRatio(div100(jyExport));
+        feeOrders.setJqExportKeepPointRatio(div100(jqEKP));
+        feeOrders.setSyExportKeepPointRatio(div100(syEKP));
+        feeOrders.setJyExportKeepPointRatio(div100(jyEKP));
+
+        // 计算分销费用(返回分销精度差值)
+        BigDecimal distributionDiff = calcDistributionFee(sumPremium, feeOrders,request.getMobile());
+
+        // 8. 总应收/总应付
+        feeOrders.setTotalReceivablePremium(feeOrders.getJqReceivablePremium()
+                .add(feeOrders.getSyReceivablePremium()).add(feeOrders.getJyReceivablePremium())
+                .setScale(5, RoundingMode.HALF_EVEN));
+        feeOrders.setTotalPayablePremium(feeOrders.getJqPayablePremium()
+                .add(feeOrders.getSyPayablePremium()).add(feeOrders.getJyPayablePremium())
+                .setScale(2, RoundingMode.DOWN));
+
+        // 9. 出口费用(setScale(2,DOWN) 截断)& 出口留点费用
+        BigDecimal jqEOrigin = feeOrders.getJqExportRatio().multiply(jqPremium);
+        BigDecimal jqE = jqEOrigin.setScale(2, RoundingMode.DOWN);
+        feeOrders.setJqExportPremium(jqE);
+        BigDecimal syEOrigin = feeOrders.getSyExportRatio().multiply(syPremium);
+        BigDecimal syE = syEOrigin.setScale(2, RoundingMode.DOWN);
+        feeOrders.setSyExportPremium(syE);
+        BigDecimal jyEOrigin = feeOrders.getJyExportRatio().multiply(jyPremium);
+        BigDecimal jyE = jyEOrigin.setScale(2, RoundingMode.DOWN);
+        feeOrders.setJyExportPremium(jyE);
+
+        BigDecimal jqK = feeOrders.getJqExportKeepPointRatio().multiply(jqPremium);
+        feeOrders.setJqExportKeepPointPremium(jqK);
+        BigDecimal syK = feeOrders.getSyExportKeepPointRatio().multiply(syPremium);
+        feeOrders.setSyExportKeepPointPremium(syK);
+        BigDecimal jyK = feeOrders.getJyExportKeepPointRatio().multiply(jyPremium);
+        feeOrders.setJyExportKeepPointPremium(jyK);
+
+        // 截断差值 = 出口精度损失 + 分销差值
+        List<BigDecimal> diffs = new ArrayList<>();
+        diffs.add(BigDecimalUtil.subtract(jqEOrigin, jqE));
+        diffs.add(BigDecimalUtil.subtract(syEOrigin, syE));
+        diffs.add(BigDecimalUtil.subtract(jyEOrigin, jyE));
+        diffs.add(distributionDiff);
+        feeOrders.setTotalExportDiffAmount(BigDecimalUtil.add(diffs));
+
+        feeOrders.setAvailableAmount(jqE.add(syE).add(jyE).subtract(jqK).subtract(syK).subtract(jyK)
+                .setScale(2, RoundingMode.HALF_UP));
+        feeOrders.setTotalExportPremium(jqE.add(syE).add(jyE));
+        feeOrders.setTotalExportKeepPointPremium(jqK.add(syK).add(jyK));
+
+        // 10. 构建比例VO
+        PtlAgreementCostRatioVo costRatio = new PtlAgreementCostRatioVo(feeOrders);
+
+        return HttpResult.ok(new InsFeeCalculateResponse(feeOrders, costRatio));
+    }
+
+    /** null-safe → BigDecimal.ZERO */
+    private static BigDecimal nvl(BigDecimal v) { return v != null ? v : BigDecimal.ZERO; }
+
+    /** 从请求参数构建费用类型配置VO */
+    private PtlAgreementCostTypeVo buildCostType(BigDecimal inlet, BigDecimal addThrow,
+                                                  BigDecimal export, BigDecimal exportKeepPointRatio) {
+        PtlAgreementCostTypeVo vo = new PtlAgreementCostTypeVo();
+        vo.setInlet(inlet);
+        vo.setAddThrow(addThrow);
+        vo.setExport(export);
+        vo.setExportKeepPointRatio(exportKeepPointRatio);
+        return vo;
+    }
+
+    /** 从已查询的协议中解析税率因子:withTax=0(不含税)→ 1.06,withTax=1(含税)→ 1 */
+    private BigDecimal resolveTaxFactor(PtlAgreement ptlAgreement) {
+        Integer withTax = ptlAgreement.getWithTax();
+        if (withTax == null) {
+            throw new ServiceException(String.format("协议未配置是否含税,协议编号=%s", ptlAgreement.getId()));
+        }
+        return withTax == 0 ? new BigDecimal("1.06") : BigDecimal.ONE;
+    }
+
+    // ===== 分销费用计算(复用 calcCosts 中的 calculateDistributionFee 逻辑)=====
+
+    /**
+     * 计算分销费用(与原 calcCosts 中 calculateDistributionFee 逻辑一致)。
+     * 区别:userId 取自当前登录用户 baseController.getUserId(),而非订单。
+     *
+     * @param totalPremium 总保费
+     * @param feeOrders    费用订单对象(用于设置分销字段)
+     * @param mobile    业务员手机号
+     * @return 分销精度差值(scale=5 - scale=2)
+     */
+    private BigDecimal calcDistributionFee(BigDecimal totalPremium, InsFeeOrders feeOrders,String mobile) {
+
+        HttpResult<SysUserJzgInfo> userResult = orgClient.getUserInfoByMobile(mobile);
+        if (userResult == null || userResult.getData() == null) {
+            return BigDecimal.ZERO;
+        }
+        String userId = userResult.getData().getUserId();
+
+        // 获取租户分销设置
+        HttpResult<SysDistributionSetting> settingResult = orgClient.getSettingBySystemCode();
+        if (settingResult == null || settingResult.getData() == null) {
+            return BigDecimal.ZERO;
+        }
+        SysDistributionSetting sysDistributionSetting = settingResult.getData();
+        // 判断业务员所属机构是否开启分销
+        String deptId = userResult.getData().getDeptId();
+        HttpResult<SysDeptVo> deptResult = orgClient.deptGet(deptId);
+        if (deptResult == null || deptResult.getData() == null
+                || !"1".equals(deptResult.getData().getIsDistribution())) {
+            return BigDecimal.ZERO;
+        }
+        String level = sysDistributionSetting.getDistributionMode();
+        BigDecimal diffAmount = BigDecimal.ZERO;
+        switch (level) {
+            case "1":
+                Map<String, Object> lv1 = calcDistLevel1(feeOrders, totalPremium, userId, sysDistributionSetting);
+                if (lv1 != null) diffAmount = new BigDecimal(lv1.get("diffAmount").toString());
+                break;
+            case "2":
+                Map<String, Object> first = calcDistLevel1(feeOrders, totalPremium, userId, sysDistributionSetting);
+                if (first != null) {
+                    Map<String, Object> second = calcDistLevel2(feeOrders, totalPremium, first.get("id").toString(), sysDistributionSetting);
+                    if (second != null) diffAmount = new BigDecimal(second.get("diffAmount").toString());
+                    diffAmount = diffAmount.add(new BigDecimal(first.get("diffAmount").toString()));
+                }
+                break;
+            case "3":
+                Map<String, Object> l1 = calcDistLevel1(feeOrders, totalPremium, userId, sysDistributionSetting);
+                if (l1 != null) {
+                    Map<String, Object> l2 = calcDistLevel2(feeOrders, totalPremium, l1.get("id").toString(), sysDistributionSetting);
+                    if (l2 != null) {
+                        BigDecimal l3Diff = calcDistLevel3(feeOrders, totalPremium, l2.get("id").toString(), sysDistributionSetting);
+                        diffAmount = diffAmount.add(l3Diff);
+                        diffAmount = diffAmount.add(new BigDecimal(l2.get("diffAmount").toString()));
+                    }
+                    diffAmount = diffAmount.add(new BigDecimal(l1.get("diffAmount").toString()));
+                }
+                break;
+        }
+        return diffAmount;
+    }
+
+    private Map<String, Object> calcDistLevel1(InsFeeOrders o, BigDecimal totalPremium, String userId, SysDistributionSetting setting) {
+        HttpResult<EsmUserReferrer> ref = orgClient.getReferrer(userId);
+        if (ref == null || ref.getData() == null) return null;
+        EsmUserReferrer referrer = ref.getData();
+        HttpResult<SysUserJzgInfo> info = orgClient.getUserInfo(referrer.getReferrerId());
+        if (info == null || info.getData() == null || !"1".equals(info.getData().getIsDistribution())) {
+            o.setFirstDistributionFee(BigDecimal.ZERO);
+            o.setFirstDistributionRatio(BigDecimal.ZERO);
+            return null;
+        }
+        o.setFirstDistributorId(referrer.getReferrerId());
+        BigDecimal fee5 = totalPremium.multiply(setting.getCommissionRatioLevel1()).setScale(5, RoundingMode.DOWN);
+        o.setFirstDistributionFee(totalPremium.multiply(setting.getCommissionRatioLevel1()).setScale(2, RoundingMode.DOWN));
+        o.setFirstDistributionRatio(setting.getCommissionRatioLevel1());
+        Map<String, Object> map = new HashMap<>();
+        map.put("id", referrer.getReferrerId());
+        map.put("diffAmount", fee5.subtract(o.getFirstDistributionFee()));
+        return map;
+    }
+
+    private Map<String, Object> calcDistLevel2(InsFeeOrders o, BigDecimal totalPremium, String upperId, SysDistributionSetting setting) {
+        HttpResult<EsmUserReferrer> ref = orgClient.getReferrer(upperId);
+        if (ref == null || ref.getData() == null) return null;
+        EsmUserReferrer referrer = ref.getData();
+        HttpResult<SysUserJzgInfo> info = orgClient.getUserInfo(referrer.getReferrerId());
+        if (info == null || info.getData() == null || !"1".equals(info.getData().getIsDistribution())) {
+            o.setSecondDistributionFee(BigDecimal.ZERO);
+            o.setSecondDistributionRatio(BigDecimal.ZERO);
+            return null;
+        }
+        o.setSecondDistributorId(referrer.getReferrerId());
+        BigDecimal fee5 = totalPremium.multiply(setting.getCommissionRatioLevel2()).setScale(5, RoundingMode.DOWN);
+        o.setSecondDistributionFee(totalPremium.multiply(setting.getCommissionRatioLevel2()).setScale(2, RoundingMode.DOWN));
+        o.setSecondDistributionRatio(setting.getCommissionRatioLevel2());
+        Map<String, Object> map = new HashMap<>();
+        map.put("id", referrer.getReferrerId());
+        map.put("diffAmount", fee5.subtract(o.getSecondDistributionFee()));
+        return map;
+    }
+
+    private BigDecimal calcDistLevel3(InsFeeOrders o, BigDecimal totalPremium, String upperId, SysDistributionSetting setting) {
+        HttpResult<EsmUserReferrer> ref = orgClient.getReferrer(upperId);
+        if (ref == null || ref.getData() == null) return BigDecimal.ZERO;
+        EsmUserReferrer referrer = ref.getData();
+        HttpResult<SysUserJzgInfo> info = orgClient.getUserInfo(referrer.getReferrerId());
+        if (info == null || info.getData() == null || !"1".equals(info.getData().getIsDistribution())) {
+            o.setThirdDistributionFee(BigDecimal.ZERO);
+            o.setThirdDistributionRatio(BigDecimal.ZERO);
+            return BigDecimal.ZERO;
+        }
+        o.setThirdDistributorId(referrer.getReferrerId());
+        BigDecimal fee5 = totalPremium.multiply(setting.getCommissionRatioLevel3()).setScale(5, RoundingMode.DOWN);
+        o.setThirdDistributionFee(totalPremium.multiply(setting.getCommissionRatioLevel3()).setScale(2, RoundingMode.DOWN));
+        o.setThirdDistributionRatio(setting.getCommissionRatioLevel3());
+        return fee5.subtract(o.getThirdDistributionFee());
+    }
+
+    // ===== 费用计算辅助方法 =====
+
+    /** 百分比转小数 */
+    private static BigDecimal div100(BigDecimal pct) {
+        return pct != null ? pct.divide(BigDecimal.valueOf(100), 10, RoundingMode.HALF_EVEN) : BigDecimal.ZERO;
+    }
+
+    /** 入口手续费比例上限控制:入口手续费比例 > 入口比例时强制取入口比例 */
+    private static BigDecimal capRatio(BigDecimal ratio, PtlAgreementCostTypeVo costType) {
+        if (costType == null || costType.getInlet() == null) return ratio != null ? ratio : BigDecimal.ZERO;
+        BigDecimal inlet = BigDecimalUtil.divide(costType.getInlet(), new BigDecimal(100)); // scale=5, HALF_EVEN
+        return BigDecimalUtil.subtract(ratio, inlet).compareTo(BigDecimal.ZERO) > 0 ? inlet : ratio;
+    }
+
+    /** 跟单费比例 = 入口比例 - 手续费比例 */
+    private static BigDecimal calcFollowRatio(PtlAgreementCostTypeVo costType, BigDecimal entranceFeeRatio) {
+        if (costType == null || costType.getInlet() == null || entranceFeeRatio == null) return BigDecimal.ZERO;
+        return div100(costType.getInlet()).subtract(entranceFeeRatio).setScale(5, RoundingMode.HALF_UP);
+    }
+
+    /** 单个险种费用计算 */
+    private static void calcInsuranceType(InsFeeOrders o, BigDecimal premium, PtlAgreementCostTypeVo ct,
+                                          BigDecimal commissionRatio, BigDecimal followRatio, BigDecimal taxFactor,
+                                          String type) {
+        if (ct == null || premium == null) {
+            if ("jq".equals(type)) { o.setJqReceivablePremium(BigDecimal.ZERO); o.setJqPayablePremium(BigDecimal.ZERO); }
+            else if ("sy".equals(type)) { o.setSyReceivablePremium(BigDecimal.ZERO); o.setSyPayablePremium(BigDecimal.ZERO); }
+            else { o.setJyReceivablePremium(BigDecimal.ZERO); o.setJyPayablePremium(BigDecimal.ZERO); }
+            return;
+        }
+        BigDecimal inlet   = div100(ct.getInlet());
+        BigDecimal addThrow = div100(ct.getAddThrow());
+        BigDecimal export  = div100(ct.getExport());
+
+        BigDecimal taxable = premium.divide(taxFactor, 5, RoundingMode.HALF_EVEN);
+        BigDecimal payable = premium.multiply(export.setScale(5, RoundingMode.DOWN)).setScale(2, RoundingMode.DOWN);
+        BigDecimal commission = taxable.multiply(commissionRatio).setScale(5, RoundingMode.HALF_EVEN);
+        BigDecimal addAmt = premium.multiply(addThrow).setScale(5, RoundingMode.HALF_EVEN);
+        BigDecimal receivable = taxable.multiply(commissionRatio.add(followRatio)).setScale(5, RoundingMode.HALF_EVEN);
+        receivable = receivable.setScale(5, RoundingMode.HALF_EVEN); // 与旧代码保持一致:二次setScale
+        BigDecimal follow = receivable.subtract(commission);
+        BigDecimal keepRate = BigDecimalUtil.subtract(BigDecimalUtil.add(BigDecimalUtil.divide(inlet, taxFactor), addThrow), export)
+                .setScale(5, RoundingMode.HALF_EVEN);
+        BigDecimal keepAmt = BigDecimalUtil.subtract(BigDecimalUtil.add(receivable, addAmt), payable)
+                .setScale(5, RoundingMode.HALF_EVEN);
+
+        switch (type) {
+            case "jq":
+                o.setJqReceivablePremium(receivable); o.setJqPayablePremium(payable);
+                o.setJqCommissionPremium(commission); o.setJqFollowPremium(follow);
+                o.setJqAdditionalPremium(addAmt); o.setJqKeepPointRatio(keepRate); o.setJqKeepPointPremium(keepAmt);
+                break;
+            case "sy":
+                o.setSyReceivablePremium(receivable); o.setSyPayablePremium(payable);
+                o.setSyCommissionPremium(commission); o.setSyFollowPremium(follow);
+                o.setSyAdditionalPremium(addAmt); o.setSyKeepPointRatio(keepRate); o.setSyKeepPointPremium(keepAmt);
+                break;
+            case "jy":
+                o.setJyReceivablePremium(receivable); o.setJyPayablePremium(payable);
+                o.setJyCommissionPremium(commission); o.setJyFollowPremium(follow);
+                o.setJyAdditionalPremium(addAmt); o.setJyKeepPointRatio(keepRate); o.setJyKeepPointPremium(keepAmt);
+                break;
+        }
+    }
+
     /**
      * 车险报价批量修改联系人等信息
      *

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

@@ -25,6 +25,8 @@
         <result property="signingTime" column="signing_time" jdbcType="VARCHAR"/>
         <result property="isTemporarily" column="is_temporarily" jdbcType="VARCHAR"/>
         <result property="realQuoteUserId" column="real_quote_user_id" jdbcType="VARCHAR"/>
+        <result property="dockingPersonPhone" column="docking_person_phone" jdbcType="VARCHAR"/>
+        <result property="dockingPerson" column="docking_person" jdbcType="VARCHAR"/>
     </resultMap>
     <!--    订单 车辆信息-->
     <resultMap id="carInfoMap" type="com.jzg.commons.entity.quote.vo.CarInfoVo">
@@ -647,7 +649,9 @@
         pay_link,
         ins_order_no,
         signing_time,
-        is_temporarily
+        is_temporarily,
+        docking_person,
+        docking_person_phone
         from ins_orders
         <where>
             and is_delete = 0

+ 8 - 4
tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/build/ZhongAnCrawlerQuoteResultsVoBuild.java

@@ -49,8 +49,10 @@ public class ZhongAnCrawlerQuoteResultsVoBuild {
         RiskInfoVo riskInfoVo = new RiskInfoVo();
         Long compelInsEffectiveDate = dataDTO.getVehiclePremium().getCompelInsEffectiveDate();
         Long compelExpireDate = dataDTO.getVehiclePremium().getCompelExpireDate();
-        riskInfoVo.setStartDate(DateUtil.formatDateTime(DateUtil.date(compelInsEffectiveDate)));
-        riskInfoVo.setEndDate(DateUtil.formatDateTime(DateUtil.date(compelExpireDate)));
+        if (compelInsEffectiveDate != null && compelExpireDate != null) {
+            riskInfoVo.setStartDate(DateUtil.formatDateTime(DateUtil.date(compelInsEffectiveDate)));
+            riskInfoVo.setEndDate(DateUtil.formatDateTime(DateUtil.date(compelExpireDate)));
+        }
         return riskInfoVo;
     }
 
@@ -58,8 +60,10 @@ public class ZhongAnCrawlerQuoteResultsVoBuild {
         RiskInfoVo riskInfoVo = new RiskInfoVo();
         Long businessInsEffectiveDate = dataDTO.getVehiclePremium().getBusinessInsEffectiveDate();
         Long businessExpireDate = dataDTO.getVehiclePremium().getBusinessExpireDate();
-        riskInfoVo.setStartDate(DateUtil.formatDateTime(DateUtil.date(businessInsEffectiveDate)));
-        riskInfoVo.setEndDate(DateUtil.formatDateTime(DateUtil.date(businessExpireDate)));
+        if (businessInsEffectiveDate != null && businessExpireDate != null) {
+            riskInfoVo.setStartDate(DateUtil.formatDateTime(DateUtil.date(businessInsEffectiveDate)));
+            riskInfoVo.setEndDate(DateUtil.formatDateTime(DateUtil.date(businessExpireDate)));
+        }
         return riskInfoVo;
     }
 

+ 34 - 14
tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementCostExternalServiceImpl.java

@@ -49,10 +49,14 @@ public class PtlAgreementCostExternalServiceImpl extends ServiceImpl<PtlAgreemen
     @Transactional
     public HttpResult save(CostExternalAdd costExternalAdd) {
         try {
-            if (verifyAgreementCostExternal(costExternalAdd.getContactPerson(), costExternalAdd.getContactMobile(),null)){
-                throw new SystemException("对接人姓名和对接人手机号已存在");
-            }
             costExternalAdd.getPtlAgreementCostExternalAddList().forEach(ptlAgreementCostExternalAdd -> {
+                // 非现询不限制一条
+                if(!"1".equals(ptlAgreementCostExternalAdd.getIsInquiry())){
+                    if (verifyAgreementCostExternal(costExternalAdd.getContactPerson(), costExternalAdd.getContactMobile(),
+                            ptlAgreementCostExternalAdd.getProductId(), null) ) {
+                        throw new SystemException("对接人姓名和对接人手机号在同一险种下已存在现询记录");
+                    }
+                }
                 ptlAgreementCostExternalAdd.setPtlAgreementId(costExternalAdd.getPtlAgreementId());
                 ptlAgreementCostExternalAdd.setContactPerson(costExternalAdd.getContactPerson());
                 ptlAgreementCostExternalAdd.setContactMobile(costExternalAdd.getContactMobile());
@@ -66,20 +70,30 @@ public class PtlAgreementCostExternalServiceImpl extends ServiceImpl<PtlAgreemen
             return HttpResult.ok(ReturnInformation.SUCCESS_MESSAGE);
         } catch (Exception e) {
             log.error("保存失败: ", e);
-            return HttpResult.error(ReturnInformation.FAILURE_MESSAGE);
+            return HttpResult.error(e.getMessage());
         }
     }
 
 
-    public boolean verifyAgreementCostExternal(String contactPerson, String contactMobile,List<String> ids) {
-        if (baseMapper.selectCount(new LambdaQueryWrapper<>(PtlAgreementCostExternal.class)
+    /**
+     * 校验对接人+手机号+产品ID下是否已存在isInquiry=0的记录(同一产品只能有一个现询)
+     *
+     * @param contactPerson 对接人姓名
+     * @param contactMobile 对接人手机号
+     * @param productId     产品ID(险种)
+     * @param ids           排除的ID列表(更新时排除自身)
+     */
+    public boolean verifyAgreementCostExternal(String contactPerson, String contactMobile, String productId, List<String> ids) {
+        LambdaQueryWrapper<PtlAgreementCostExternal> wrapper = new LambdaQueryWrapper<>(PtlAgreementCostExternal.class)
                 .eq(PtlAgreementCostExternal::getContactPerson, contactPerson)
                 .eq(PtlAgreementCostExternal::getContactMobile, contactMobile)
-                .eq(PtlAgreementCostExternal::getIsDelete, Constants.NOT_DELETED)
-                .notIn(CollectionUtils.isNotEmpty(ids),PtlAgreementCostExternal::getId, ids) ) > 0 ){
-            return true;
+                .eq(PtlAgreementCostExternal::getProductId, productId)
+                .eq(PtlAgreementCostExternal::getIsInquiry, 0)
+                .eq(PtlAgreementCostExternal::getIsDelete, Constants.NOT_DELETED);
+        if (CollectionUtils.isNotEmpty(ids)) {
+            wrapper.notIn(PtlAgreementCostExternal::getId, ids);
         }
-        return false;
+        return baseMapper.selectCount(wrapper) > 0;
     }
 
 
@@ -174,11 +188,17 @@ public class PtlAgreementCostExternalServiceImpl extends ServiceImpl<PtlAgreemen
     @Override
     public HttpResult updateList(CostExternalEnd costExternalEnd) {
         try {
-            List<String> collect = costExternalEnd.getPtlAgreementCostExternalAddList().stream().map(PtlAgreementCostExternalEnd::getId).collect(Collectors.toList());
-            if (verifyAgreementCostExternal(costExternalEnd.getContactPerson(), costExternalEnd.getContactMobile(),collect)){
-                throw new SystemException("对接人姓名和对接人手机号已存在");
-            }
             costExternalEnd.getPtlAgreementCostExternalAddList().forEach(agreementCostExternalEnd -> {
+                List<String> excludeIds = agreementCostExternalEnd.getId() != null
+                        ? Collections.singletonList(agreementCostExternalEnd.getId()) : null;
+                // 非现询不限制条数
+                if(!"1".equals(agreementCostExternalEnd.getIsInquiry())){
+                    if (verifyAgreementCostExternal(costExternalEnd.getContactPerson(), costExternalEnd.getContactMobile(),
+                            agreementCostExternalEnd.getProductId(), excludeIds)) {
+                        throw new SystemException("对接人姓名和对接人手机号在同一险种下已存在现询记录");
+                    }
+                }
+
                 agreementCostExternalEnd.setPtlAgreementId(costExternalEnd.getPtlAgreementId());
                 agreementCostExternalEnd.setContactPerson(costExternalEnd.getContactPerson());
                 agreementCostExternalEnd.setContactMobile(costExternalEnd.getContactMobile());

Разница между файлами не показана из-за своего большого размера
+ 691 - 63
tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java


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