Selaa lähdekoodia

Merge branch 'master' into wrq_dev

wangrq 2 kuukautta sitten
vanhempi
commit
98ea3af2f4
45 muutettua tiedostoa jossa 757 lisäystä ja 124 poistoa
  1. 8 0
      commons/src/main/java/com/jzg/commons/entity/account/po/SysUserAccountChangeLog.java
  2. 8 0
      commons/src/main/java/com/jzg/commons/entity/finance/dto/ExportSuperviseSettlementExcelDto.java
  3. 10 0
      commons/src/main/java/com/jzg/commons/entity/finance/po/InsPlyIncome.java
  4. 6 0
      commons/src/main/java/com/jzg/commons/entity/finance/vo/InvoiceAndSettlementVo.java
  5. 3 0
      commons/src/main/java/com/jzg/commons/entity/finance/vo/ReceivableQueryVo.java
  6. 39 0
      commons/src/main/java/com/jzg/commons/entity/report/dto/FeeAuditSummaryVo.java
  7. 29 0
      commons/src/main/java/com/jzg/commons/entity/report/vo/FeeAuditDetailParam.java
  8. 26 0
      commons/src/main/java/com/jzg/commons/entity/report/vo/FeeAuditSummaryParam.java
  9. 2 0
      commons/src/main/java/com/jzg/commons/entity/rights/dto/InsOrderRightsDto.java
  10. 2 0
      commons/src/main/java/com/jzg/commons/entity/rights/dto/InsOrderRightsPackageDto.java
  11. 1 1
      commons/src/main/java/com/jzg/commons/entity/rights/dto/RightsGrantReceiverDTO.java
  12. 1 1
      commons/src/main/java/com/jzg/commons/entity/vo/RuleAttrMappingVo.java
  13. 5 0
      consoleStatistics/pom.xml
  14. 22 0
      consoleStatistics/src/main/java/com/jzg/console/client/FeeAuditClient.java
  15. 44 5
      consoleStatistics/src/main/java/com/jzg/console/controller/ReportFinanceDataManageController.java
  16. 18 0
      consoleStatistics/src/main/java/com/jzg/console/mapper/ReportFeeAuditSummaryMapper.java
  17. 24 0
      consoleStatistics/src/main/java/com/jzg/console/service/ReportFeeAuditSummaryService.java
  18. 63 0
      consoleStatistics/src/main/java/com/jzg/console/service/impl/ReportFeeAuditSummaryServiceImpl.java
  19. 35 0
      consoleStatistics/src/main/resources/mapper/ReportFeeAuditSummaryMapper.xml
  20. 1 1
      tenant/insurance/quotation-ansheng/src/main/java/com/jzg/quotation/ansheng/crawler/entity/request/AnShengCrawlerCalculatePremiumApplyMessage.java
  21. 10 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/client/OrgClient.java
  22. 2 1
      tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/crawler/entity/request/GuoRenCrawlerQueryQuotationRequest.java
  23. 11 3
      tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/component/HengBangCrawlerRequestComponent.java
  24. 49 12
      tenant/insurance/quotation-hengbang/src/main/java/com/jzg/quotation/hengbang/crawler/service/Impl/HengBangCrawlerRequestImpl.java
  25. 17 3
      tenant/insurance/quotation-huanong/src/main/java/com/jzg/quotation/huanong/crawler/entity/request/HuaNongCrawlerQuotedPriceRequestRequest.java
  26. 13 4
      tenant/insurance/quotation-huatai/src/main/java/com/jzg/quotation/huatai/crawler/service/Impl/HuaTaiCrawlerRequestImpl.java
  27. 34 17
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/OrderOperationLogAspect.java
  28. 61 23
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/aspect/QuoteVerificationAspect.java
  29. 1 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/InsFeeAuditController.java
  30. 3 0
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/entity/dto/ChannelRightsQueryDTO.java
  31. 1 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsFeeOrdersServiceImpl.java
  32. 4 2
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrderRightsInfoServiceImpl.java
  33. 5 1
      tenant/insurance/quotation-taiping/src/main/java/com/jzg/quotation/taiping/crawler/entity/request/TaiPingCrawlerPremiumCalculateRequest.java
  34. 6 2
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/component/TaiShanCrawlerRequestComponent.java
  35. 34 9
      tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/service/impl/TaiShanCrawlerRequestImpl.java
  36. 22 5
      tenant/insurance/quotation-zhongan/src/main/java/com/jzg/quotation/zhongan/crawler/entity/request/ZhongAnCrawlerQuoteRequest.java
  37. 3 3
      tenant/organization/src/main/java/com/jzg/organization/controller/ReceivableController.java
  38. 12 0
      tenant/organization/src/main/java/com/jzg/organization/controller/UserController.java
  39. 17 1
      tenant/organization/src/main/java/com/jzg/organization/mapper/SysUserAccountIncomeLogMapper.java
  40. 9 0
      tenant/organization/src/main/java/com/jzg/organization/service/SysUserService.java
  41. 70 23
      tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java
  42. 1 1
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserJzgInfoBankCardServiceImpl.java
  43. 12 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserServiceImpl.java
  44. 12 3
      tenant/organization/src/main/resources/mapper/ReceivableMapper.xml
  45. 1 1
      tenant/organization/src/main/resources/mapper/SysUserJzgInfoBankCardMapper.xml

+ 8 - 0
commons/src/main/java/com/jzg/commons/entity/account/po/SysUserAccountChangeLog.java

@@ -118,6 +118,14 @@ public class SysUserAccountChangeLog extends BaseModel {
     @Schema(description = "备注")
     private String remark;
 
+    @ExcelProperty("签单时间")
+    @Schema(description = "签单时间")
+    private String signTime;
+
+    @ExcelProperty("提现时间")
+    @Schema(description = "提现时间")
+    private String payTime;
+
     public SysUserAccountChangeLog(){
 
     }

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

@@ -97,4 +97,12 @@ public class ExportSuperviseSettlementExcelDto {
     @ExcelProperty(value = "订单号")
     private String orderNo;
 
+    @Schema(description = "对接人姓名")
+    @ExcelProperty(value = "对接人姓名")
+    private String contactPerson;
+
+    @Schema(description = "对接人手机号")
+    @ExcelProperty(value = "对接人手机号")
+    private String contactPersonPhone;
+
 }

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

@@ -199,6 +199,16 @@ public class InsPlyIncome extends BaseModel {
     @ExcelProperty("总应收金额")
     private String receivableAmount;
 
+    @TableField(exist = false)
+    @Schema(description = "总应收金额(车险)")
+    @ExcelProperty("总应收金额(车险)")
+    private String receivableAmount4Car;
+
+    @TableField(exist = false)
+    @Schema(description = "总应收金额(非车)")
+    @ExcelProperty("总应收金额(非车)")
+    private String receivableAmount4Other;
+
     @TableField(exist = false)
     @Schema(description = "车险应收手续费")
     @ExcelProperty("车险应收手续费")

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

@@ -34,6 +34,12 @@ public class InvoiceAndSettlementVo {
     @Schema(description = "差额原因")
     private String paymentReason;
 
+
+    @Schema(description = "回款差额(开票并结算的时候使用)")
+    private BigDecimal settlementPaymentDifference;
+    @Schema(description = "差额原因(开票并结算的时候使用)")
+    private String settlementPaymentReason;
+
     @Schema(description = "附加id")
     private List<String> attachmentIds;
 }

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

@@ -107,6 +107,9 @@ public class ReceivableQueryVo extends PageRequest {
     @Schema(description = "结算状态")
     private String settlementStatus;
 
+    @Schema(description = "开票和结算状态")
+    private String invoiceSettlementStatus;
+
     @Schema(description = "增加类型")
     private String addType;
 

+ 39 - 0
commons/src/main/java/com/jzg/commons/entity/report/dto/FeeAuditSummaryVo.java

@@ -0,0 +1,39 @@
+package com.jzg.commons.entity.report.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 费用审核汇总统计结果VO:按保险公司分组统计各审核状态数量及平均审核时长
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Schema(description = "费用审核汇总统计结果VO")
+public class FeeAuditSummaryVo {
+
+    @Schema(description = "保险公司ID")
+    private String companyId;
+
+    @Schema(description = "保险公司名称")
+    private String companyName;
+
+    @Schema(description = "待审核条数")
+    private Long pendingReviewNum;
+
+    @Schema(description = "已审核条数")
+    private Long approvedNum;
+
+    @Schema(description = "审核不通过条数")
+    private Long rejectedNum;
+
+    @Schema(description = "疑问订单条数")
+    private Long problemOrderNum;
+
+    @Schema(description = "平均审核时长(秒)")
+    private Long avgAuditDuration;
+}

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

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

+ 26 - 0
commons/src/main/java/com/jzg/commons/entity/report/vo/FeeAuditSummaryParam.java

@@ -0,0 +1,26 @@
+package com.jzg.commons.entity.report.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jzg.commons.core.base.PageRequest;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+
+/**
+ * 费用审核汇总统计请求参数
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(description = "费用审核汇总统计请求参数")
+public class FeeAuditSummaryParam extends PageRequest {
+
+    @Schema(description = "审核开始时间")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate auditTimeStart;
+
+    @Schema(description = "审核结束时间")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate auditTimeEnd;
+}

+ 2 - 0
commons/src/main/java/com/jzg/commons/entity/rights/dto/InsOrderRightsDto.java

@@ -20,6 +20,8 @@ import java.util.List;
 @Schema(description = "订单选择权益券DTO")
 @Data
 public class InsOrderRightsDto {
+    @Schema(description = "权益id")
+    private String id;
 
     @Schema(description = "权益类型 1 券  2 套餐")
     private String rightType;

+ 2 - 0
commons/src/main/java/com/jzg/commons/entity/rights/dto/InsOrderRightsPackageDto.java

@@ -20,6 +20,8 @@ import java.util.List;
 @Schema(description = "订单选择权益套餐DTO")
 @Data
 public class InsOrderRightsPackageDto {
+    @Schema(description = "id")
+    private String id;
     @Schema(description = "权益套餐id:对应生活服务平台返回的id")
     private String rightsId;
 

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

@@ -13,7 +13,7 @@ import lombok.Data;
 @Schema(description = "权益发放接收人DTO")
 public class RightsGrantReceiverDTO {
 
-    @Schema(description = "接收人类型 1 车主 2 投保人 3 被保人")
+    @Schema(description = "接收人类型 1 车主 2 投保人 3 被保人 4 其他")
     private Integer receiverType;
 
     @Schema(description = "接收人姓名")

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

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

+ 5 - 0
consoleStatistics/pom.xml

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

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

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

+ 44 - 5
consoleStatistics/src/main/java/com/jzg/console/controller/ReportFinanceDataManageController.java

@@ -1,9 +1,14 @@
 package com.jzg.console.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jzg.commons.core.base.BaseController;
 import com.jzg.commons.core.page.HttpResult;
+import com.jzg.commons.entity.report.dto.FeeAuditSummaryVo;
+import com.jzg.commons.entity.report.vo.FeeAuditDetailParam;
+import com.jzg.commons.entity.report.vo.FeeAuditSummaryParam;
 import com.jzg.commons.entity.report.vo.ReportSearchCommonVo;
+import com.jzg.commons.entity.orders.vo.FeeAuditVo;
 import com.jzg.console.service.*;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -45,6 +50,10 @@ public class ReportFinanceDataManageController extends BaseController {
     @Autowired
     private ReportPersonCheckDataService reportPersonCheckDataService;
 
+    //费用审核汇总统计
+    @Autowired
+    private ReportFeeAuditSummaryService reportFeeAuditSummaryService;
+
 
 
     /**
@@ -154,8 +163,8 @@ public class ReportFinanceDataManageController extends BaseController {
     @PostMapping(value = "/receivableDataDetailPageList")
     public HttpResult<?> receivableDataDetailPageList(@RequestBody ReportSearchCommonVo reportSearchCommonVo) {
         try{
-            List<?> list = reportReceivableDataService.getDetailListByParams(reportSearchCommonVo);
-            return HttpResult.ok(list);
+            IPage<?> pageList = reportReceivableDataService.getPageDetailListByParams(reportSearchCommonVo);
+            return HttpResult.ok(pageList);
         }catch (Exception e){
             return HttpResult.error(e.getMessage());
         }
@@ -187,8 +196,8 @@ public class ReportFinanceDataManageController extends BaseController {
     @PostMapping(value = "/meetDataPageList")
     public HttpResult<?> meetDataPageList(@RequestBody ReportSearchCommonVo reportSearchCommonVo) {
         try{
-            List<?> list = reportMeetDataService.getListByParams(reportSearchCommonVo);
-            return HttpResult.ok(list);
+            IPage<?> pageList = reportMeetDataService.getPageListByParams(reportSearchCommonVo);
+            return HttpResult.ok(pageList);
         }catch (Exception e){
             return HttpResult.error(e.getMessage());
         }
@@ -213,7 +222,7 @@ public class ReportFinanceDataManageController extends BaseController {
      *  @version
      *  @author: hxl
      *  @Date: 2025/9/22 17:11
-     *  @Description:  业务数据-对接人-明细查询
+     *  @Description:  财务数据-应付-明细查询
      */
     @Operation(summary = "财务数据-应付-明细查询", description = "财务数据-应付-明细查询")
     @PostMapping(value = "/meetDataDetailPageList")
@@ -340,4 +349,34 @@ public class ReportFinanceDataManageController extends BaseController {
         }
     }
 
+    /**
+     * 费用审核汇总统计:按保险公司分组统计待审核、已审核、审核不通过、疑问订单数量及平均审核时长
+     * @author: jk
+     */
+    @Operation(summary = "费用审核-汇总统计列表", description = "费用审核-汇总统计列表")
+    @PostMapping(value = "/feeAuditSummaryPageList")
+    public HttpResult<IPage<FeeAuditSummaryVo>> feeAuditSummaryPageList(@RequestBody FeeAuditSummaryParam param) {
+        try {
+            IPage<FeeAuditSummaryVo> pageList = reportFeeAuditSummaryService.getFeeAuditSummaryPage(param);
+            return HttpResult.ok(pageList);
+        } catch (Exception e) {
+            return HttpResult.error(e.getMessage());
+        }
+    }
+
+    /**
+     * 费用审核明细列表:根据保险公司ID查询该公司的所有审核明细(不区分审核状态)
+     * @author: jk
+     */
+    @Operation(summary = "费用审核-明细列表", description = "费用审核-明细列表")
+    @PostMapping(value = "/feeAuditDetailPageList")
+    public HttpResult<Page<FeeAuditVo>> feeAuditDetailPageList(@RequestBody FeeAuditDetailParam param) {
+        try {
+            Page<FeeAuditVo> pageList = reportFeeAuditSummaryService.getFeeAuditDetailPage(param);
+            return HttpResult.ok(pageList);
+        } catch (Exception e) {
+            return HttpResult.error(e.getMessage());
+        }
+    }
+
 }

+ 18 - 0
consoleStatistics/src/main/java/com/jzg/console/mapper/ReportFeeAuditSummaryMapper.java

@@ -0,0 +1,18 @@
+package com.jzg.console.mapper;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.jzg.commons.entity.report.dto.FeeAuditSummaryVo;
+import com.jzg.commons.entity.report.vo.FeeAuditSummaryParam;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 费用审核汇总统计 Mapper
+ */
+public interface ReportFeeAuditSummaryMapper {
+
+    /**
+     * 按保险公司分组统计费用审核汇总数据
+     */
+    IPage<FeeAuditSummaryVo> getFeeAuditSummaryPage(Page<FeeAuditSummaryVo> page, @Param("param") FeeAuditSummaryParam param);
+}

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

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

+ 63 - 0
consoleStatistics/src/main/java/com/jzg/console/service/impl/ReportFeeAuditSummaryServiceImpl.java

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

+ 35 - 0
consoleStatistics/src/main/resources/mapper/ReportFeeAuditSummaryMapper.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jzg.console.mapper.ReportFeeAuditSummaryMapper">
+
+    <!-- 按保险公司分组统计费用审核汇总数据 -->
+    <select id="getFeeAuditSummaryPage" resultType="com.jzg.commons.entity.report.dto.FeeAuditSummaryVo">
+        SELECT
+            io.company_id AS companyId,
+            io.company_name AS companyName,
+            -- 待审核:audit_status = 0 AND is_problem = 0
+            COUNT(CASE WHEN ifa.audit_status = 0 AND (ifa.is_problem IS NULL OR ifa.is_problem = 0) THEN 1 END) AS pendingReviewNum,
+            -- 已审核:audit_status = 1 AND (is_problem IS NULL OR is_problem = 0)
+            COUNT(CASE WHEN ifa.audit_status = 1 AND (ifa.is_problem IS NULL OR ifa.is_problem = 0) THEN 1 END) AS approvedNum,
+            -- 审核不通过:audit_status = 2 AND (is_problem IS NULL OR is_problem = 0)
+            COUNT(CASE WHEN ifa.audit_status = 2 AND (ifa.is_problem IS NULL OR ifa.is_problem = 0) THEN 1 END) AS rejectedNum,
+            -- 疑问订单:is_problem = 1
+            COUNT(CASE WHEN ifa.is_problem = 1 THEN 1 END) AS problemOrderNum,
+            -- 平均审核时长(秒):audit_time - receive_time
+            COALESCE(ROUND(AVG(TIMESTAMPDIFF(SECOND, ifa.receive_time, ifa.audit_time)), 0), 0) AS avgAuditDuration
+        FROM ins_fee_audit ifa
+        LEFT JOIN ins_orders io ON ifa.order_no = io.id AND io.is_delete = 0
+        <where>
+            ifa.is_delete = 0
+            <if test="param.auditTimeStart != null">
+                AND (ifa.audit_time &gt;= #{param.auditTimeStart} OR ifa.audit_time IS NULL)
+            </if>
+            <if test="param.auditTimeEnd != null">
+                AND (ifa.audit_time &lt;= #{param.auditTimeEnd} OR ifa.audit_time IS NULL)
+            </if>
+        </where>
+        GROUP BY io.company_id, io.company_name
+        ORDER BY approvedNum DESC, pendingReviewNum DESC
+    </select>
+
+</mapper>

+ 1 - 1
tenant/insurance/quotation-ansheng/src/main/java/com/jzg/quotation/ansheng/crawler/entity/request/AnShengCrawlerCalculatePremiumApplyMessage.java

@@ -35,7 +35,7 @@ public class AnShengCrawlerCalculatePremiumApplyMessage {
     public AnShengCrawlerCalculatePremiumApplyMessage(QuoteVo quoteVo, AnShengCrawlerSearchVehicleByVinResponse.DataDTO dataDTO,
                                                       AnShengCrawlerGetUserDetailResponse.DataDTO.AgentDefineDTO userDetailResponse, DepartmentPlanCode departmentPlanCode,
                                                       String checkVehicleCodeSecret) {
-        RiskInfoVo riskInfoVo = Optional.ofNullable(quoteVo.getCiRiskInfoVo()).orElse(quoteVo.getBiRiskInfoVo());
+        RiskInfoVo riskInfoVo = Optional.ofNullable(quoteVo.getBiRiskInfoVo()).orElseGet(() -> quoteVo.getCiRiskInfoVo() );
 
         String customerNegotiatePrice = CustomerNegotiatePriceUtils.calculateTheDepreciationValue(departmentPlanCode.getCode(), quoteVo.getCarInfoVo()
                         .getEnergyTypeCode(),

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

@@ -245,4 +245,14 @@ public interface OrgClient {
      */
     @PostMapping("/api/v1/organization/queryJzgInfoId2UserId")
     public HttpResult<Map<String,String>> queryJzgInfoId2UserId(@RequestBody List<String> jzgInfoTids);
+
+    /**
+     * 根据用户登录名查询sysUser对象
+     *
+     * @param userName 用户登录名,默认为手机号
+     * @author lipf
+     * @date 2026/7/10 15:04
+     */
+    @GetMapping("/userInfo/querySysUserByUserName")
+    public HttpResult<SysUser> querySysUserByUserName(@RequestParam("userName") String userName);
 }

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

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

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

@@ -333,9 +333,17 @@ public class HengBangCrawlerRequestComponent {
                         String time = extractDuplicateEndTime(detail);
                         if (time != null) {
                             String utcTime = DateUtil.toUtcDateTime(time);
-                            calculationRequest.setBegintimeCi(utcTime);
-                            calculationRequest.setBegintimeBi(utcTime);
-                            calculationRequest.setBegintimeAccident(utcTime);
+                            // 根据重复投保类型分别设置起保时间:交强险只改 begintimeCi,商业险只改 begintimeBi
+                            // 注意:商业险错误信息不含"商业险平台返回",故通过"交强险平台返回"反推
+                            if (detail.contains("交强险平台返回")) {
+                                calculationRequest.setBegintimeCi(utcTime);
+                            } else {
+                                calculationRequest.setBegintimeBi(utcTime);
+                            }
+                            // 驾意险不支持即时起保:北京时间0点则直接复用,非0点则自动设为下一日0点
+                            calculationRequest.setBegintimeAccident(DateUtil.isBeijingMidnight(utcTime)
+                                    ? utcTime
+                                    : DateUtil.getNextDayMidnightUtc(utcTime));
                             return getCalculationResult(calculationRequest, headers);
                         } else {
                             return StrUtil.isNotBlank(detail) ? detail : responseBody;

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

@@ -178,18 +178,30 @@ public class HengBangCrawlerRequestImpl implements HengBangCrawlerRequest {
             }
         }
 
-        // 重复投保:循环重试,优先从responseBody.begintimeBi获取建议起保时间
+        // 重复投保:循环重试,优先从responseBody获取建议起保时间
         int maxRetry = 3;
         while (errorMsg.contains("重复投保") && maxRetry-- > 0) {
             String time = getDuplicateBegintime(resJsonObj, errorMsg);
-            log.info("重复投保,重试次数:{}, 建议起保时间:{}", 3 - maxRetry, time);
+            log.info("重复投保,重试次数:{}, 建议起保时间:{}, 错误信息前100字符:{}", 3 - maxRetry, time,
+                    errorMsg.length() > 100 ? errorMsg.substring(0, 100) : errorMsg);
             if (time == null) {
                 break;
             }
             String utcTime = DateUtil.toUtcDateTime(time);
-            calculationRequest.setBegintimeCi(utcTime);
-            calculationRequest.setBegintimeBi(utcTime);
-            calculationRequest.setBegintimeAccident(utcTime);
+
+            // 根据重复投保类型分别设置起保时间:交强险只改 begintimeCi,商业险只改 begintimeBi
+            // 注意:商业险错误信息不含"商业险平台返回",故通过"交强险平台返回"反推
+            if (errorMsg.contains("交强险平台返回")) {
+                calculationRequest.setBegintimeCi(utcTime);
+            } else {
+                // 不含交强险标识则为商业险重复投保
+                calculationRequest.setBegintimeBi(utcTime);
+            }
+            // 驾意险不支持即时起保:北京时间0点则直接复用,非0点则自动设为下一日0点
+            calculationRequest.setBegintimeAccident(DateUtil.isBeijingMidnight(utcTime)
+                    ? utcTime
+                    : DateUtil.getNextDayMidnightUtc(utcTime));
+
             resJsonObj = callCalculation(calculationRequest, headers);
             if (resJsonObj == null) {
                 return buildErrorResult(quoteVo);
@@ -254,19 +266,44 @@ public class HengBangCrawlerRequestImpl implements HengBangCrawlerRequest {
 
     /**
      * 获取重复投保场景的建议起保时间(yyyy-MM-dd HH:mm:ss 格式)
-     * 优先从 responseBody.begintimeBi 获取,兜底从 message 正则提取
+     * 优先从 responseBody.begintimeCi/begintimeBi 获取,兜底从 message 正则提取
      */
     private String getDuplicateBegintime(JSONObject resJsonObj, String errorMsg) {
-        // 优先从 responseBody.begintimeBi 获取
-        JSONObject responseBody = resJsonObj.getJSONObject("responseBody");
+        // 优先从 responseBody 获取建议起保时间(支持顶层和 map.responseBody 嵌套)
+        JSONObject responseBody = getNestedResponseBody(resJsonObj);
         if (responseBody != null) {
+            // 检查 begintimeCi(交强险建议起保时间),保司返回可能带前导空格
+            String begintimeCi = responseBody.getString("begintimeCi");
+            if (StrUtil.isNotBlank(begintimeCi)) {
+                log.info("重复投保,从 responseBody.begintimeCi 获取建议起保时间:{}", begintimeCi);
+                return normalizeTimeFormat(begintimeCi.trim());
+            }
+            // 检查 begintimeBi(商业险建议起保时间)
             String begintimeBi = responseBody.getString("begintimeBi");
-            if (begintimeBi != null) {
-                return normalizeTimeFormat(begintimeBi);
+            if (StrUtil.isNotBlank(begintimeBi)) {
+                log.info("重复投保,从 responseBody.begintimeBi 获取建议起保时间:{}", begintimeBi);
+                return normalizeTimeFormat(begintimeBi.trim());
             }
         }
-        // 兼容:从 message 正则提取终保日期
-        return hbCrawlerRequestComponent.extractDuplicateEndTime(errorMsg);
+        // 兜底:从 message 正则提取终保日期
+        String endTime = hbCrawlerRequestComponent.extractDuplicateEndTime(errorMsg);
+        log.info("重复投保,从 errorMsg 正则提取终保日期:{}", endTime);
+        return endTime;
+    }
+
+    /**
+     * 获取嵌套的 responseBody(保司返回可能在顶层或 map.responseBody 中)
+     */
+    private JSONObject getNestedResponseBody(JSONObject resJsonObj) {
+        JSONObject responseBody = resJsonObj.getJSONObject("responseBody");
+        if (responseBody != null) {
+            return responseBody;
+        }
+        JSONObject map = resJsonObj.getJSONObject("map");
+        if (map != null) {
+            return map.getJSONObject("responseBody");
+        }
+        return null;
     }
 
     /**

+ 17 - 3
tenant/insurance/quotation-huanong/src/main/java/com/jzg/quotation/huanong/crawler/entity/request/HuaNongCrawlerQuotedPriceRequestRequest.java

@@ -3227,8 +3227,8 @@ public class HuaNongCrawlerQuotedPriceRequestRequest implements HuaNongHeadReque
                 this.nativePlace = customerInfoVo.getAddr();
                 this.riskLevel = "0";
                 this.secrecyUnitFlag = false;
-                this.sex = customerInfoVo.getGender();
-                this.fxqSex = customerInfoVo.getGender();
+                this.sex = getSex(customerInfoVo.getIdentifyNumber());
+                this.fxqSex = getSex(customerInfoVo.getIdentifyNumber());
                /* this.sex = "2";
                 this.fxqSex = "2";*/
                 this.tandBRelationship = tandBRelationship;
@@ -3256,7 +3256,21 @@ public class HuaNongCrawlerQuotedPriceRequestRequest implements HuaNongHeadReque
                         new CustomerDTO(policyHolderInfo, "1", tandBRelationship, agentCode, comCode)
                 );
             }
-
+            /**
+             * 根据18位身份证获取性别
+             * @param idCard 身份证号
+             * @return 1-男  2-女
+             */
+            public static String getSex(String idCard) {
+                // 简单校验长度
+                if (idCard == null || idCard.length() != 18) {
+                    throw new IllegalArgumentException("身份证必须为18位");
+                }
+                // 取第17位字符,下标16
+                char sexChar = idCard.charAt(16);
+                int num = Character.getNumericValue(sexChar);
+                return num % 2 == 0 ? "2" : "1";
+            }
 
             @NoArgsConstructor
             @Data

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

@@ -90,6 +90,8 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
     private static final String BASE_URL = "https://cspxp.pc.ehuatai.com";
     private static final int MAX_RETRIES = 3;
     private static final long RETRY_DELAY_MS = 3000;
+    /** 指数退避倍率:每次重试间隔 = RETRY_DELAY_MS * (BACKOFF_FACTOR ^ 重试次数) */
+    private static final int BACKOFF_FACTOR = 2;
     private static final long SHORT_DELAY_MS = 100;
     private static final String RISK_CODE = "1251";
     private static final String XBCOM_CODE = "927";
@@ -221,9 +223,13 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
         quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.QUOTE_FAIL);
         // 带重试的获取报价编号、车型型号
         Map<String, Object> xbResult = retry(() -> {
-            try { return xbQuery(dto.getUsername(), cookie, car); }
+            try {
+                String freshCookie = cache.getCookie();
+                String useCookie = StringUtils.hasText(freshCookie) ? freshCookie : cookie;
+                return xbQuery(dto.getUsername(), useCookie, car);
+            }
             catch (Exception e) { refreshLogin(dto); throw new Exception(e); }
-        }, MAX_RETRIES, RETRY_DELAY_MS, "预报价获取登录信息");
+        }, MAX_RETRIES, RETRY_DELAY_MS, BACKOFF_FACTOR, "预报价获取登录信息");
 
         String quotationNo = str(xbResult, "quotationNo");
         String modelcodexh = StringUtils.isBlank(str(xbResult, "modelcodexh")) ? car.getCarModelNo() : str(xbResult, "modelcodexh");
@@ -1333,13 +1339,16 @@ public class HuaTaiCrawlerRequestImpl implements HuaTaiCrawlerRequest {
     @FunctionalInterface
     public interface RetryableTask<T> { T execute() throws Exception; }
 
-    private <T> T retry(RetryableTask<T> task, int max, long delay, String name) {
+    private <T> T retry(RetryableTask<T> task, int max, long delay, int backoffFactor, String name) {
         for (int i = 0; i < max; i++) {
             try { return task.execute(); }
             catch (Exception e) {
                 log.warn("{} 失败,第 {} 次重试", name, i + 1);
                 if (i + 1 >= max) throw new SystemException(name + " 失败,已重试 " + max + " 次", e.getMessage());
-                sleep(delay);
+                // 指数退避:第1次 baseDelay,第2次 baseDelay*factor,第3次 baseDelay*factor^2 ...
+                long waitMs = delay * (long) Math.pow(Math.max(backoffFactor, 1), i);
+                log.info("{} 等待 {} ms 后重试", name, waitMs);
+                sleep(waitMs);
             }
         }
         throw new SystemException(name + " 失败,已达到最大重试次数");

+ 34 - 17
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/aop/OrderOperationLogAspect.java

@@ -1,10 +1,12 @@
 package com.jzg.quotation.summary.aop;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson2.JSON;
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
 import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.dto.VerifyAdjustParam;
+import com.jzg.commons.entity.finance.vo.BatchModifyVo;
 import com.jzg.commons.entity.orders.po.InsOrderAdjust;
 import com.jzg.commons.entity.orders.po.InsOrders;
 import com.jzg.commons.entity.orders.po.InsOrdersCarInfo;
@@ -12,6 +14,7 @@ import com.jzg.commons.entity.orders.po.InsOrdersTrack;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.commons.entity.quote.vo.aggregated.*;
 import com.jzg.commons.entity.vo.AdjustAllRefundVo;
+import com.jzg.commons.entity.vo.PtlAgreementCostRatioVo;
 import com.jzg.quotation.commons.constant.SpElMapping;
 import com.jzg.quotation.commons.utils.SpElFieldExtractor;
 import com.jzg.quotation.summary.aop.aspect.OrderOperationLog;
@@ -157,16 +160,16 @@ public class OrderOperationLogAspect {
             // 费用调整
             case 15:
                 logger.info("费用调整log.orderSpEl()=[{}]",log.orderSpEl());
+                PtlAgreementCostRatioVo vo = parser.parseExpression(log.orderSpEl()).getValue(context, PtlAgreementCostRatioVo.class);
                 result = joinPoint.proceed();
-                String orderNo01 = "001";
-                this.saveCostInfo(orderNo01,result,log);
+                this.saveCostInfo(result,log, vo);
                 break;
             // 批量修改比例
             case 16:
                 logger.info("批量修改比例.log.orderSpEl()=[{}]",log.orderSpEl());
+                BatchModifyVo batchModifyVo = parser.parseExpression(log.orderSpEl()).getValue(context, BatchModifyVo.class);
                 result = joinPoint.proceed();
-                String orderNo02 = "002";
-                this.batchModify(orderNo02,result,log);
+                this.batchModify(result,log, batchModifyVo);
                 break;
         }
         return result;
@@ -178,14 +181,25 @@ public class OrderOperationLogAspect {
      * @author lipf
      * @date 2026/7/8 15:29
      */
-    private void batchModify(String orderNo, Object result, OrderOperationLog log) {
-        InsOrdersTrack track = new InsOrdersTrack();
-        track.setModule("应收订单");
-        track.setSubModule("");
-        track.setOptType(16);
-        track.setOrderNo(orderNo);
-        track.setResult(JSONUtil.toJsonStr(result));
-        traceService.save(track);
+    private void batchModify(Object result, OrderOperationLog log, BatchModifyVo vo) {
+        List<String> orderNos = vo.getOrderNos();
+        if(CollUtil.isEmpty(orderNos)){
+            logger.info("批量修改没有传入订单号");
+            return;
+        }
+        for (String orderNo : orderNos) {
+            InsOrdersTrack track = new InsOrdersTrack();
+            track.setModule(log.module());
+            track.setSubModule(log.subModule());
+            track.setOptType(log.optType().getCode());
+            track.setOptContent(log.description());
+            track.setChangeAfter(JSONUtil.toJsonStr(vo));
+            track.setResult(JSONUtil.toJsonStr(result));
+            track.setOrderNo(orderNo);
+            traceService.save(track);
+
+        }
+
     }
 
     /**
@@ -193,12 +207,15 @@ public class OrderOperationLogAspect {
      * @author lipf
      * @date 2026/7/8 15:28
      */
-    private void saveCostInfo(String orderNo, Object result, OrderOperationLog log) {
+    private void saveCostInfo(Object result, OrderOperationLog log, PtlAgreementCostRatioVo vo) {
         InsOrdersTrack track = new InsOrdersTrack();
-        track.setModule("订单审核");
-        track.setSubModule("我的审核");
-        track.setOptType(15);
-        track.setOrderNo(orderNo);
+        track.setModule(log.module());
+        track.setSubModule(log.subModule());
+        track.setOptType(log.optType().getCode());
+        track.setOptContent(log.description());
+        track.setResult(JSONUtil.toJsonStr(result));
+        track.setChangeAfter(JSONUtil.toJsonStr(vo));
+        track.setOrderNo(vo.getOrderNo());
         track.setResult(JSONUtil.toJsonStr(result));
         traceService.save(track);
     }

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

@@ -1,6 +1,7 @@
 package com.jzg.quotation.summary.aop.aspect;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.jzg.commons.constants.quote.enums.quote.EnergyTypeCode;
@@ -12,10 +13,10 @@ import com.jzg.commons.entity.agreement.dispatch.vo.PtlAgreementDispatchVo;
 import com.jzg.commons.entity.dto.CostAgreementParam;
 import com.jzg.commons.entity.orders.po.*;
 import com.jzg.commons.entity.po.*;
-import com.jzg.commons.entity.quote.vo.KindInfoVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.commons.entity.quote.vo.aggregated.QuoteResultsVo;
 import com.jzg.commons.entity.vo.*;
+import com.jzg.commons.exception.ServiceException;
 import com.jzg.commons.util.BigDecimalUtil;
 import com.jzg.commons.util.StringUtils;
 import com.jzg.quotation.commons.client.OrgClient;
@@ -74,6 +75,7 @@ public class QuoteVerificationAspect {
 
     @AfterReturning(pointcut = "@annotation(com.jzg.quotation.summary.aop.QuoteVerification)", returning = "result")
     public void doAfter(HttpResult<QuoteResultsVo> result) {
+        String loginUserId = baseController.getUserId();
         if (result.getCode() == 200) {
             StringBuilder logs = new StringBuilder();
             InsOrders insOrders = insOrdersService.getById(result.getData().getOrdersNo());
@@ -132,7 +134,10 @@ public class QuoteVerificationAspect {
                         insOrdersCarUserInfos, kindList, insOrdersCosts, insOrdersAccidentalDriving, insOrders);
                 if (costId != null) {
                     // 根据匹配到的协议、费用 开始计算入口费用
-                    InsFeeOrders insFeeOrders = calcCosts(agreementInfoVo,costId, insOrders,insOrdersCosts);
+                    boolean isrecordByLeader = false;
+                    String reqlQuoteUserId = this.queryReqlQuoteUserIdByUserName(insOrders.getRealQuoteUserId());
+                    isrecordByLeader = !Objects.equals(loginUserId, reqlQuoteUserId);
+                    InsFeeOrders insFeeOrders = calcCosts(agreementInfoVo,costId, insOrders,insOrdersCosts,isrecordByLeader);
                     log.info("费用因子校验通过,子订单id:" + insOrders.getId() + ",费用id:" + costId);
                     result.getData().setFeeOrders(insFeeOrders);
                     return;
@@ -144,6 +149,23 @@ public class QuoteVerificationAspect {
         }
     }
 
+    /**
+     * 根据用户的登录名查询用户的useId
+     *
+     * @author lipf
+     * @date 2026/7/10 14:58
+     */
+    private String queryReqlQuoteUserIdByUserName(String userName) {
+        if(StrUtil.isEmpty(userName)){
+            return StrUtil.EMPTY;
+        }
+        HttpResult<SysUser> sysUserHttpResult = orgClient.querySysUserByUserName(userName);
+        if(sysUserHttpResult.isSuccess()){
+            return sysUserHttpResult.getData().getId();
+        }
+        throw new ServiceException("调用异常,请查看orgnization服务是否启动");
+    }
+
 
     /**
      * 最开始的过滤 过滤 能源 车辆类型
@@ -245,7 +267,8 @@ public class QuoteVerificationAspect {
         return null;
     }
 
-    public InsFeeOrders calcCosts(AgreementInfoVo agreementInfoVo, String costId, InsOrders insOrders, InsOrdersCosts insOrdersCosts) {
+
+    public InsFeeOrders calcCosts(AgreementInfoVo agreementInfoVo, String costId, InsOrders insOrders, InsOrdersCosts insOrdersCosts,boolean isrecordByLeader) {
         InsFeeOrders insFeeOrders = new InsFeeOrders();
         insFeeOrders.setOrderNo(insOrders.getId());
         insFeeOrders.setAgreementId(insOrders.getAgreementId());
@@ -340,27 +363,27 @@ public class QuoteVerificationAspect {
                 insFeeOrders,
                 InsFeeOrders::setJqReceivablePremium, InsFeeOrders::setJqPayablePremium,
                 InsFeeOrders::setJqCommissionPremium, InsFeeOrders::setJqFollowPremium, InsFeeOrders::setJqAdditionalPremium,
-                InsFeeOrders::setJqKeepPointRatio,InsFeeOrders::setJqKeepPointPremium);
+                InsFeeOrders::setJqKeepPointRatio,InsFeeOrders::setJqKeepPointPremium, isrecordByLeader);
 
         processInsuranceType(
                 insOrdersCosts.getSyPremium(), syCostType, syEntranceFeeRatio, syFollowRatio, taxFactor,
                 insFeeOrders,
                 InsFeeOrders::setSyReceivablePremium, InsFeeOrders::setSyPayablePremium,
                 InsFeeOrders::setSyCommissionPremium, InsFeeOrders::setSyFollowPremium, InsFeeOrders::setSyAdditionalPremium,
-                InsFeeOrders::setSyKeepPointRatio,InsFeeOrders::setSyKeepPointPremium);
+                InsFeeOrders::setSyKeepPointRatio,InsFeeOrders::setSyKeepPointPremium, isrecordByLeader);
 
         processInsuranceType(
                 insOrdersCosts.getJyPremium(), jyCostType, jyEntranceFeeRatio, jyFollowRatio, taxFactor,
                 insFeeOrders,
                 InsFeeOrders::setJyReceivablePremium, InsFeeOrders::setJyPayablePremium,
                 InsFeeOrders::setJyCommissionPremium, InsFeeOrders::setJyFollowPremium, InsFeeOrders::setJyAdditionalPremium,
-                InsFeeOrders::setJyKeepPointRatio,InsFeeOrders::setJyKeepPointPremium);
+                InsFeeOrders::setJyKeepPointRatio,InsFeeOrders::setJyKeepPointPremium, isrecordByLeader);
 
         // 7. 计算分销费用  返回分销的差值
         BigDecimal distributionDiff = calculateDistributionFee(insOrdersCosts,insFeeOrders, insOrders);
 
         // 8. 计算总应收、总应付、保存费用比例 入库
-        saveRatio(insFeeOrders, agreementInfoVo, jqCostType, syCostType, jyCostType);
+        saveRatio(insFeeOrders, agreementInfoVo, jqCostType, syCostType, jyCostType, isrecordByLeader);
         calculateTotalPremium(insFeeOrders, distributionDiff);
 
 
@@ -406,19 +429,20 @@ public class QuoteVerificationAspect {
     /**
      * 处理单个险种的费用计算(核心复用方法)
      *
-     * @param premium         险种保费
-     * @param costType        险种费用类型配置
-     * @param commissionRatio 手续费比例
-     * @param followRatio     跟单费比例
-     * @param taxFactor       税率因子(平台协议为1,私有协议为1/1.06)
-     * @param insFeeOrders    费用订单对象
-     * @param setReceivable   应收金额setter
-     * @param setPayable      应付金额setter
-     * @param setCommission   手续费setter
-     * @param setFollow       跟单费setter
-     * @param setAdditional   加投费setter
-     * @param keepPointRate 留点比例
+     * @param premium          险种保费
+     * @param costType         险种费用类型配置
+     * @param commissionRatio  手续费比例
+     * @param followRatio      跟单费比例
+     * @param taxFactor        税率因子(平台协议为1,私有协议为1/1.06)
+     * @param insFeeOrders     费用订单对象
+     * @param setReceivable    应收金额setter
+     * @param setPayable       应付金额setter
+     * @param setCommission    手续费setter
+     * @param setFollow        跟单费setter
+     * @param setAdditional    加投费setter
+     * @param keepPointRate    留点比例
      * @param keepPointPremium 留点费用
+     * @param isrecordByLeader 是否是代课录单
      */
     private void processInsuranceType(
             BigDecimal premium,
@@ -433,7 +457,8 @@ public class QuoteVerificationAspect {
             BiConsumer<InsFeeOrders, BigDecimal> setFollow,
             BiConsumer<InsFeeOrders, BigDecimal> setAdditional,
             BiConsumer<InsFeeOrders, BigDecimal> keepPointRate,
-            BiConsumer<InsFeeOrders, BigDecimal> keepPointPremium) {
+            BiConsumer<InsFeeOrders, BigDecimal> keepPointPremium,
+            boolean isrecordByLeader) {
         // 若险种配置为空,默认应收应付为0
         if (costType == null) {
             setReceivable.accept(insFeeOrders, BigDecimal.ZERO);
@@ -449,6 +474,11 @@ public class QuoteVerificationAspect {
         BigDecimal addThrowPercent = convertPercent(costType.getAddThrow());
         BigDecimal exportPercent = convertPercent(costType.getExport());
 
+        if(isrecordByLeader){
+            // 如果是代客录单,出口比例减去一个百分比,也就是 0.01 2026年7月11日09:30:09
+            exportPercent = BigDecimalUtil.subtract(exportPercent, new BigDecimal("0.01"));
+        }
+
         // 去税保费金额
         BigDecimal taxablePremium = premium.divide(taxFactor,5,RoundingMode.HALF_EVEN);
 
@@ -573,8 +603,11 @@ public class QuoteVerificationAspect {
     }
     /**
      * 保存比例
+     * @param isrecordByLeader 是否代客录单,如果是代客入单,出口比例减一个百分比
      */
-    private void saveRatio(InsFeeOrders insFeeOrders, AgreementInfoVo agreementInfoVo,PtlAgreementCostTypeVo jqCostType,PtlAgreementCostTypeVo syCostType,PtlAgreementCostTypeVo jyCostType) {
+    private void saveRatio(InsFeeOrders insFeeOrders, AgreementInfoVo agreementInfoVo,
+                           PtlAgreementCostTypeVo jqCostType, PtlAgreementCostTypeVo syCostType,
+                           PtlAgreementCostTypeVo jyCostType, boolean isrecordByLeader) {
         // 手续费比例
         insFeeOrders.setJqCommissionRatio(agreementInfoVo.getAgreement().getJqEntranceFeeRatio());
         insFeeOrders.setSyCommissionRatio(agreementInfoVo.getAgreement().getSyEntranceFeeRatio());
@@ -629,19 +662,24 @@ public class QuoteVerificationAspect {
                                 ? convertPercent(jqCostType.getExport()).subtract(convertPercent(firstDistributionRatio))
                                   .subtract(convertPercent(secondDistributionRatio)).subtract(convertPercent(thirdDistributionRatio))
                                 : BigDecimal.ZERO));
-
         insFeeOrders.setSyExportRatio(syCostType == null ? BigDecimal.ZERO :
                         (syCostType.getExport() != null && syCostType.getExport().compareTo(BigDecimal.ZERO) > 0
                                 ? convertPercent(syCostType.getExport()).subtract(convertPercent(firstDistributionRatio))
                                   .subtract(convertPercent(secondDistributionRatio)).subtract(convertPercent(thirdDistributionRatio))
                                 : BigDecimal.ZERO));
-
         insFeeOrders.setJyExportRatio(jyCostType == null ?  BigDecimal.ZERO :
                         (jyCostType.getExport() != null && jyCostType.getExport().compareTo(BigDecimal.ZERO) > 0
                                 ? convertPercent(jyCostType.getExport()).subtract(convertPercent(firstDistributionRatio))
                                   .subtract(convertPercent(secondDistributionRatio)).subtract(convertPercent(thirdDistributionRatio))
                                 : BigDecimal.ZERO));
 
+        if(isrecordByLeader){
+            // 如果是代客录单, 交强,商业,驾意的出口比例减1%, 也就是0.01 add by lipf 2026年7月10日15:40:47
+            insFeeOrders.setJqExportRatio(BigDecimalUtil.subtract(insFeeOrders.getJqExportRatio(), new BigDecimal("0.01")));
+            insFeeOrders.setSyExportRatio(BigDecimalUtil.subtract(insFeeOrders.getSyExportRatio(), new BigDecimal("0.01")));
+            insFeeOrders.setJyExportRatio(BigDecimalUtil.subtract(insFeeOrders.getJyExportRatio(), new BigDecimal("0.01")));
+        }
+
         // 出口留点比例
         insFeeOrders.setJqExportKeepPointRatio(jqCostType != null
                 ? convertPercent(jqCostType.getExportKeepPointRatio() != null ? jqCostType.getExportKeepPointRatio() : BigDecimal.ZERO)

+ 1 - 1
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/InsFeeAuditController.java

@@ -189,7 +189,7 @@ public class InsFeeAuditController {
             subModule = "我的审核",
             optType = QuoteNumberConstant.QuoteOptType.OPT_TYPE_15,
             description = "费用调整",
-            orderSpEl = "#quoteVo",
+            orderSpEl = "#param",
             feedbackSpEl = "#ret.code + ' - ' + #ret.msg+ ' - ' + #ret.data"
     )
     @PostMapping("/saveCostInfo")

+ 3 - 0
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/entity/dto/ChannelRightsQueryDTO.java

@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 @Data
 @Schema(description = "权益券查询参数")
@@ -30,6 +31,8 @@ public class ChannelRightsQueryDTO {
     @Schema(description = "权益券分类")
     private String classify;
 
+    @Schema(description = "权益券分类集合")
+    private List<String> classifyList;
     @Schema(description = "页码,默认1")
     private Integer pageNo = 1;
 

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

@@ -188,7 +188,7 @@ public class InsFeeOrdersServiceImpl extends ServiceImpl<InsFeeOrdersMapper, Ins
         BigDecimal base;
         if (withTax == 0) {
             // 不含税:保费 / 1.06
-            base = premium.divide(taxRate, scale, RoundingMode.HALF_EVEN);
+            base = premium.divide(taxRate, 6, RoundingMode.HALF_EVEN);
         } else {
             // 含税:直接用保费
             base = premium;

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

@@ -17,7 +17,7 @@ import com.jzg.commons.util.AssertionUtils;
 import com.jzg.quotation.summary.service.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.beanutils.BeanUtils;
+import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.interceptor.TransactionAspectSupport;
@@ -74,13 +74,14 @@ public class InsOrderRightsInfoServiceImpl implements InsOrderRightsInfoService
                 List<InsOrderRights> insOrderRightsList = new ArrayList<>();
                 for(InsOrderRightsDto insOrderRightsDto:insOrderRightsDtoList){
                     InsOrderRights insOrderRights = new InsOrderRights();
-                    BeanUtils.copyProperties(insOrderRights,insOrderRightsDto);
+                    BeanUtils.copyProperties(insOrderRightsDto,insOrderRights,"id");
                     //获取接收人信息入库
                     RightsGrantReceiverDTO rightsGrantReceiverDTO  = insOrderRightsInfoDto.getRightsGrantReceiverDTO();
                     insOrderRights.setReceiverMobile(rightsGrantReceiverDTO.getReceiverMobile());
                     insOrderRights.setReceiverName(rightsGrantReceiverDTO.getReceiverName());
                     insOrderRights.setReceiverType(rightsGrantReceiverDTO.getReceiverType());
                     insOrderRights.setOrderId(orderNo);
+                    insOrderRights.setRightsId(insOrderRightsDto.getId());
                     insOrderRightsList.add(insOrderRights);
                 }
                 insOrderRightsService.saveInsOrderRights(insOrderRightsList);
@@ -99,6 +100,7 @@ public class InsOrderRightsInfoServiceImpl implements InsOrderRightsInfoService
                     insOrderRightsPackage.setReceiverName(rightsGrantReceiverDTO.getReceiverName());
                     insOrderRightsPackage.setReceiverType(rightsGrantReceiverDTO.getReceiverType());
                     insOrderRightsPackage.setOrderId(orderNo);
+                    insOrderRightsPackage.setRightsId(insOrderRightsPackageDto.getId());
                     insOrderRightsPackageList.add(insOrderRightsPackage);
                 }
                 insOrderRightsPackageService.saveInsOrderRightsPackage(insOrderRightsPackageList);

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

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

+ 6 - 2
tenant/insurance/quotation-taishan/src/main/java/com/jzg/quotation/taishan/crawler/component/TaiShanCrawlerRequestComponent.java

@@ -314,9 +314,13 @@ public class TaiShanCrawlerRequestComponent {
     public TaiShanCrawlerQuotationResponse quotation(TaiShanCrawlerQuotationRequest request, HttpHeaders headers, int repeatNumber) {
         TaiShanCrawlerQuotationResponse response = post(RequestUrl.PRICE, request, TaiShanCrawlerQuotationResponse.class, headers);
 
+        if (response.getResult() == null) {
+            throw new SystemException(response.getMessage() != null ? response.getMessage() : "报价接口返回异常,result为空");
+        }
+
         TaiShanCrawlerQuotationResponse.ResultDTO.ExceptionDTO exception = response.getResult().getException();
-        String errorMessage = response.getResult() != null ? exception.getMsg() : response.getMessage();
-        ResultEnum.verify(exception.getCode(), errorMessage);
+        String errorMessage = exception != null ? exception.getMsg() : response.getMessage();
+        ResultEnum.verify(exception != null ? exception.getCode() : null, errorMessage);
 
         // 通过状态码获取处理器处理
         ResponseMessageAbstractHandler responseMessageAbstractHandler =

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

@@ -113,6 +113,9 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
         // 2.2 计算折旧价格 获取车辆实际价值
         TaiShanCrawlerGetActualValueRequest taiShanCrawlerGetActualValueRequest = new TaiShanCrawlerGetActualValueRequest(quoteVo,modelsDTO);
         TaiShanCrawlerGetActualValueResponse taiShanCrawlerGetActualValueResponse = taiShanCrawlerRequestComponent.getActualValue(taiShanCrawlerGetActualValueRequest, headers);
+        if (taiShanCrawlerGetActualValueResponse.getResult() == null) {
+            throw new SystemException("获取车辆实际价值失败:" + taiShanCrawlerGetActualValueResponse.getMessage());
+        }
         String currentValue = taiShanCrawlerGetActualValueResponse.getResult().getActualValue();
         log.info("车辆当前价值:{}", currentValue);
 
@@ -135,12 +138,22 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
         log.info("taiShanCrawlerQuotationRequest参数的值:{}", JSON.toJSONString(taiShanCrawlerQuotationRequest));
         TaiShanCrawlerQuotationResponse taiShanCrawlerQuotationResponse = taiShanCrawlerRequestComponent.quotation(taiShanCrawlerQuotationRequest, headers,CIRCULATE_NUMBER);
         log.info("taiShanCrawlerQuotationResponse参数的值:{}", JSON.toJSONString(taiShanCrawlerQuotationResponse));
-        TaiShanCrawlerQuotationResponse.ResultDTO.ExceptionDTO exception = taiShanCrawlerQuotationResponse.getResult().getException();
         String errMsg = null;
         TaiShanCrawlerQuotationSaveResponse taiShanCrawlerQuotationSaveResponse = null;
         TaiShanCrawlerRiskManagementResponse taiShanCrawlerRiskManagementResponse = null;
         boolean success = false;
-        if (exception.getCode().equals("H1")){
+
+        if (taiShanCrawlerQuotationResponse.getResult() == null) {
+            errMsg = taiShanCrawlerQuotationResponse.getMessage();
+            throw new SystemException(errMsg != null ? errMsg : "报价接口返回异常,result为空");
+        }
+
+        TaiShanCrawlerQuotationResponse.ResultDTO.ExceptionDTO exception = taiShanCrawlerQuotationResponse.getResult().getException();
+        if (exception == null || exception.getCode() == null) {
+            throw new SystemException("报价接口返回异常:缺少异常信息");
+        }
+
+        if ("H1".equals(exception.getCode())){
             String colorCode = quoteVo.getCarInfoVo().getColorCode();
             if(org.apache.commons.lang3.StringUtils.isBlank(colorCode)){
                 taiShanCrawlerQuotationRequest.getVehicleInfo().setCarColor("01");
@@ -166,9 +179,13 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
                         // 重新报价
                         taiShanCrawlerQuotationResponse = taiShanCrawlerRequestComponent.quotation(taiShanCrawlerQuotationRequest, headers, CIRCULATE_NUMBER);
                         log.info("泰山报价重复投保后报价响应: {}", JSON.toJSONString(taiShanCrawlerQuotationResponse));
+                        if (taiShanCrawlerQuotationResponse.getResult() == null) {
+                            errMsg = taiShanCrawlerQuotationResponse.getMessage();
+                            throw new SystemException(errMsg != null ? errMsg : "重复投保后报价接口返回异常,result为空");
+                        }
                         exception = taiShanCrawlerQuotationResponse.getResult().getException();
-                        if (!exception.getCode().equals("H1")) {
-                            errMsg = exception.getMsg();
+                        if (exception == null || !"H1".equals(exception.getCode())) {
+                            errMsg = exception != null ? exception.getMsg() : "重复投保后报价失败";
                             return TaiShanCrawlerQuoteResultsVoBuild.buildQuoteResultsVo(quoteVo, null, null, errMsg, false);
                         }
                         // 更新报价信息
@@ -186,18 +203,22 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
             log.info("taiShanCrawlerQuotationSaveResponse参数的值:{}", JSON.toJSONString(taiShanCrawlerQuotationSaveResponse));
             if (taiShanCrawlerQuotationSaveResponse.getResult() != null) {
                 TaiShanCrawlerQuotationSaveResponse.Result.Exception saveException = taiShanCrawlerQuotationSaveResponse.getResult().getException();
-                if (saveException.getCode().equals("H1")){
+                if (saveException != null && "H1".equals(saveException.getCode())){
                     TaiShanCrawlerOrder taiShanCrawlerOrder = new TaiShanCrawlerOrder();
                     taiShanCrawlerOrder.setOrdersNo(quoteVo.getOrder().getOrdersNo());
                     taiShanCrawlerOrderService.save(taiShanCrawlerQuotationSaveResponse, taiShanCrawlerOrder);
                     success = true;
 
                     //风险管控
-                    String proposalNo = taiShanCrawlerQuotationSaveResponse.getResult().getCompulsoryInsurance().getProductInfo().getProposalNo();
+                    TaiShanCrawlerQuotationSaveResponse.Result.CompulsoryInsurance compulsoryIns = taiShanCrawlerQuotationSaveResponse.getResult().getCompulsoryInsurance();
+                    if (compulsoryIns == null || compulsoryIns.getProductInfo() == null) {
+                        throw new SystemException("保存报价成功但获取交强险产品信息失败");
+                    }
+                    String proposalNo = compulsoryIns.getProductInfo().getProposalNo();
                     TaiShanCrawlerRiskManagementRequest taiShanCrawlerRiskManagementRequest = new TaiShanCrawlerRiskManagementRequest(proposalNo);
                     taiShanCrawlerRiskManagementResponse = taiShanCrawlerRequestComponent.getRiskManagement(taiShanCrawlerRiskManagementRequest, headers);
                 }else{
-                    errMsg = saveException.getMsg();
+                    errMsg = saveException != null ? saveException.getMsg() : taiShanCrawlerQuotationSaveResponse.getMessage();
                     throw new SystemException(errMsg);
                 }
             }else {
@@ -205,7 +226,7 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
                 throw new SystemException(errMsg);
             }
         }else{
-            errMsg = taiShanCrawlerQuotationResponse.getResult() != null ? exception.getMsg() : taiShanCrawlerQuotationResponse.getMessage();
+            errMsg = exception != null ? exception.getMsg() : taiShanCrawlerQuotationSaveResponse.getMessage();
             throw new SystemException(errMsg);
         }
         return TaiShanCrawlerQuoteResultsVoBuild.buildQuoteResultsVo(quoteVo,
@@ -640,7 +661,11 @@ public class TaiShanCrawlerRequestImpl implements TaiShanCrawlerRequest {
         log.info("taiShanCrawlerOrderQueryResponse对象的值:{}", JSON.toJSONString(taiShanCrawlerOrderQueryResponse));
         OrderStatusResultVo orderStatusResultVo = new OrderStatusResultVo();
         if ("200".equals(taiShanCrawlerOrderQueryResponse.getCode())) {
-            //获取订单状态
+            if (taiShanCrawlerOrderQueryResponse.getResult() == null
+                    || taiShanCrawlerOrderQueryResponse.getResult().getList() == null
+                    || taiShanCrawlerOrderQueryResponse.getResult().getList().isEmpty()) {
+                return orderStatusResultVo;
+            }
             String orderStatus = taiShanCrawlerOrderQueryResponse.getResult().getList().get(0).getStatus();
             //将保司返回的订单状态转换为系统定义的订单状态枚举类型
             InsOrderStatusEnum orderStatusEnum = null;

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

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

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

@@ -545,11 +545,11 @@ public class ReceivableController {
      * @date 2026/5/27 20:25
      */
     @OrderOperationLog(
-            module = "私有协议应收",
+            module = "私有/平台协议应收",
             subModule = "订单审核",
             optType = QuoteNumberConstant.QuoteOptType.OPT_TYPE_16,
-            description = "费用调整",
-            orderSpEl = "#quoteVo",
+            description = "批量修改",
+            orderSpEl = "#batchModifyVo",
             feedbackSpEl = "#ret.code + ' - ' + #ret.msg+ ' - ' + #ret.data"
     )
     @PostMapping("batchModify")

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

@@ -351,5 +351,17 @@ public class UserController extends BaseController {
         return HttpResult.ok(sysUser);
     }
 
+    /**
+     * 根据用户登录名查询sysUser对象
+     *
+     * @param userName 用户登录名,默认为手机号
+     * @author lipf
+     * @date 2026/7/10 15:04
+     */
+    @GetMapping("/querySysUserByUserName")
+    public HttpResult<SysUser> querySysUserByUserName(@RequestParam("userName") String userName){
+        return HttpResult.ok(sysUserService.querySysUserByUserName(userName));
+    }
+
 
 }

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

@@ -20,6 +20,22 @@ public interface SysUserAccountIncomeLogMapper extends BaseMapper<SysUserAccount
      * @author lipf
      * @date 2026/6/8 17:25
      */
-    @Select("select ioci.license_no , a.* from sys_user_account_change_log a  left join ins_orders_car_info ioci on a.related_order_id = ioci.order_no where a.user_id = #{ywyUserId} and a.create_time >= #{beginDate} and a.create_time < #{endDate} and a.is_delete = 0 order by a.create_time desc")
+    @Select("""
+        select
+            ioci.license_no ,
+            io.signing_time  as signTime,
+            saa.auditing_time as payTime,
+            a.*
+        from
+            sys_user_account_change_log a
+        left join ins_orders_car_info ioci on
+            a.related_order_id = ioci.order_no
+        left join ins_orders io
+            on a.related_order_id = io.id
+        left join sys_amount_auditing saa
+        on saa.user_id = a.user_id
+        where
+            a.user_id = #{ywyUserId} and a.create_time >= #{beginDate} and a.create_time < #{endDate} and a.is_delete = 0 order by a.create_time desc
+        """)
     List<SysUserAccountChangeLog> queryYwyIORecs(String ywyUserId, LocalDate beginDate, LocalDate endDate);
 }

+ 9 - 0
tenant/organization/src/main/java/com/jzg/organization/service/SysUserService.java

@@ -294,4 +294,13 @@ public interface SysUserService extends IService<SysUser> {
      * @date 2026/6/30 11:27
      */
     SysUser querySysUserByUserId(String userId);
+
+    /**
+     * 根据用户登录名查询sysUser对象
+     *
+     * @param userName 用户登录名,默认为手机号
+     * @author lipf
+     * @date 2026/7/10 15:04
+     */
+    SysUser querySysUserByUserName(String userName);
 }

+ 70 - 23
tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java

@@ -398,19 +398,6 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         log.info("应收数据的二次过滤:incomeDataVO=[{}]", JSONUtil.toJsonStr(incomeDataVO));
         List<String> orderNos = incomeDataVO.getOrderNos();
         String companyId = incomeDataVO.getCompanyId();
-//        if(CollUtil.isEmpty(orderNos)){
-//            log.info("应收数据的二次过滤: 订单号不能为空");
-//            return HttpResult.error("请勾选要处理的订单信息");
-//        }
-//        if (StrUtil.isEmpty(companyId)) {
-//            log.info("应收数据的二次过滤. 保司不能为空");
-//            return HttpResult.error("保司不能为空");
-//        }
-//        if(!"and".equalsIgnoreCase(incomeDataVO.getLogicJudge()) && "20".equalsIgnoreCase(incomeDataVO.getLogicJudge())){
-//            log.info("应收数据的二次过滤. 逻辑条件必须是and或or");
-//            return HttpResult.error("逻辑条件必须是and或or");
-//        }
-
         List<InsPlyIncome> incomes =  baseMapper.queryIncomeDatasByOrderIds(orderNos,companyId);
         log.info("根据订单号和保司id查询出[{}]条记录。 orderNos =[{}],companyId=[{}]",CollUtil.size(incomes), JSONUtil.toJsonStr(orderNos), companyId);
         // 需要查询未结算的数据 modify by lipf 2026年6月4日11:06:50
@@ -1483,22 +1470,23 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
 
         // 私有手续费 应收金额
         // 交强的总手续费(jq_commission_premium) + 商业的总手续费(sy_commission_premium)
-        BigDecimal result = switch (invoiceType) {
-            case "1" -> jqCommissionPremium.add(syCommissionPremium);
-            case "2" ->
+        InvoiceTypeEnum invoiceTypeEnum = InvoiceTypeEnum.getByCode(invoiceType);
+        BigDecimal result = switch (invoiceTypeEnum) {
+            case FEE_1 -> jqCommissionPremium.add(syCommissionPremium);
+            case FEE_2 ->
                 // 交强的总跟单费(jq_follow_premium) + 商业的总跟单费(sy_follow_premium)
                     jqFollowPremium.add(syFollowPremium);
-            case "3" ->
+            case FEE_3 ->
                 // 驾意险的总手续费(jy_commission_premium)
                     jyCommissionPremium;
-            case "4" ->
+            case FEE_4 ->
                 // 驾意险的总跟单费(jy_follow_premium)
                     jyFollowPremium;
-            case "5" ->
-                    // 现在平台不区分车险非车险了,所以都统计到一起
+            case FEE_5 ->
+                // 现在平台不区分车险非车险了,所以都统计到一起
                 // 交强的总手续费(jq_commission_premium) + 商业的总手续费(sy_commission_premium) + 交强的总跟单费(jq_follow_premium) + 商业的总跟单费(sy_follow_premium) + 驾意险的总手续费(jy_commission_premium) + 驾意险的总跟单费(jy_follow_premium)
                     jqCommissionPremium.add(syCommissionPremium).add(jqFollowPremium).add(syFollowPremium).add(jyCommissionPremium).add(jyFollowPremium);
-            case "6" ->
+            case FEE_6 ->
                 // 驾意险的总手续费(jy_commission_premium) + 驾意险的总跟单费(jy_follow_premium)
                     jyCommissionPremium.add(jyFollowPremium);
             default -> null;
@@ -4088,7 +4076,62 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             }
         }
 
-        return result;
+        // ========== 新增:调用月份过滤方法,过滤组装完成后的VO数据 ==========
+        List<InsFeeFollowOrderVo> finalResult = filterResultByMonth(result, followInvoicePageListVo);
+        return finalResult;
+    }
+
+
+    /**
+     * 根据前端传入的月份条件过滤已组装完成的保费跟踪VO列表
+     * @param originVoList 组装完成的全部vo数据
+     * @param queryParam 前端查询参数
+     * @return 过滤后符合月份条件的数据
+     */
+    private List<InsFeeFollowOrderVo> filterResultByMonth(List<InsFeeFollowOrderVo> originVoList, FollowInvoicePageListVo queryParam) {
+        // 无搜索条件直接返回原数据
+        if (CollUtil.isEmpty(queryParam.getSearchList())) {
+            return originVoList;
+        }
+        // 取出月份搜索条件 signDate
+        FollowInvoicePageListVo.SearchVO monthSearch = queryParam.getSearchList().stream()
+                .filter(s -> FollowInvoicePageListVo.SearchVO.signDate.equals(s.getName()))
+                .findFirst()
+                .orElse(null);
+        // 不存在月份条件 / 搜索值为空,直接返回原数据
+        if (monthSearch == null || StrUtil.isBlank(monthSearch.getSearch())) {
+            return originVoList;
+        }
+        String searchType = monthSearch.getType();
+        String searchValue = monthSearch.getSearch();
+        // 分割多月份
+        List<Integer> targetMonthList = Arrays.stream(searchValue.split(","))
+                .map(String::trim)
+                .filter(StrUtil::isNotBlank)
+                .map(Integer::valueOf)
+                .collect(Collectors.toList());
+        if (CollUtil.isEmpty(targetMonthList)) {
+            return originVoList;
+        }
+        // 构建过滤断言
+        Predicate<InsFeeFollowOrderVo> monthPredicate;
+        switch (searchType) {
+            case "等于":
+            case "包含":
+                monthPredicate = vo -> targetMonthList.contains(vo.getMonth());
+                break;
+            case "不等于":
+            case "不包含":
+                monthPredicate = vo -> !targetMonthList.contains(vo.getMonth());
+                break;
+            default:
+                // 其他类型不做过滤
+                return originVoList;
+        }
+        // 过滤返回
+        return originVoList.stream()
+                .filter(monthPredicate)
+                .collect(Collectors.toList());
     }
 
     /**
@@ -4493,7 +4536,11 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
                 // 设置已结算的金额
                 action.setSettlementAmount(settlementAmount);
                 // 设置待结算金额
-                action.setRemainSettlementAmount(remainSettlementAmount);
+                if(remainSettlementAmount.compareTo(BigDecimal.ZERO) < 0){
+                    // 特殊梳理,当待结算金额计算出来为负数时, 设置为0
+                    remainSettlementAmount = BigDecimal.ZERO;
+                }
+                action.setRemainSettlementAmount( remainSettlementAmount);
                 action.setCompanyAllName(allCompanyHierarchyPaths.get(Objects.toString(action.getCompanyId(),"")));
                 action.setSettlementStatus(settlementStatusName);
                 // 回款差额

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

@@ -100,7 +100,7 @@ public class SysUserJzgInfoBankCardServiceImpl extends ServiceImpl<SysUserJzgInf
      */
     @Override
     public Page<SysUserJzgInfoBankCardDto> getBankCardPageList(Page page, SysUserJzgInfoBankCardVo sysUserJzgInfoBankCardVo) {
-        log.info("查询业务员账户:sysUserJzgInfoBankCardVo=[{}]", JSONUtil.toJsonStr(sysUserJzgInfoBankCardVo));
+        log.info("查询业务员银行卡:sysUserJzgInfoBankCardVo=[{}]", JSONUtil.toJsonStr(sysUserJzgInfoBankCardVo));
         Page<SysUserJzgInfoBankCardDto> pageList = sysUserJzgInfoBankCardMapper.getBankCardPageList(page, sysUserJzgInfoBankCardVo);
         // 查询业务员类型
         Map<String, String> typeAttrMap = sysUserJzgInfoSalesmanService.queryYwyTypeAttrMap();

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

@@ -1652,6 +1652,18 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
         }
     }
 
+    /**
+     * 根据用户登录名查询sysUser对象
+     *
+     * @param userName 用户登录名,默认为手机号
+     * @author lipf
+     * @date 2026/7/10 15:04
+     */
+    @Override
+    public SysUser querySysUserByUserName(String userName) {
+        return baseMapper.selectOne(new LambdaQueryWrapper<SysUser>()
+                .eq(SysUser::getUsername,userName));
+    }
 
 }
 

+ 12 - 3
tenant/organization/src/main/resources/mapper/ReceivableMapper.xml

@@ -226,6 +226,8 @@
         ipi.license_no,
         -- 1. 总应收金额 (修复了多余的右括号)
         (COALESCE(ipi.jq_receivable_premium, 0) + COALESCE(ipi.sy_receivable_premium, 0) + COALESCE(ipi.jy_receivable_premium, 0)) AS receivableAmount,
+        (COALESCE(ipi.jq_receivable_premium, 0) + COALESCE(ipi.sy_receivable_premium, 0) ) AS receivableAmount4Car,
+        (COALESCE(ipi.jy_receivable_premium, 0)) AS receivableAmount4Other,
         -- 2. 总应收手续费 (为最后一个字段补充了默认值 0)
         (COALESCE(ipi.jq_supervise_costs_premiums, 0) + COALESCE(ipi.sy_supervise_costs_premiums, 0) + COALESCE(ipi.jy_supervise_costs_premiums, 0)) AS superviseCostsPremiums,
         -- 3. 总应收跟单费 (修复了括号位置错误,并为最后一个字段补充了默认值 0)
@@ -330,6 +332,13 @@
             left join sys_user su on su.id = suji.user_id and su.is_delete = 0
             where sujis.type_attr =#{receivableQueryVo.typeAttr})
         </if>
+        <if test="receivableQueryVo.invoiceSettlementStatus != null and receivableQueryVo.invoiceSettlementStatus != ''">
+            AND ipi.id  in (
+            select ipil.income_id  from ins_ply_income_invoice_link ipil
+            LEFT JOIN ins_ply_income_invoice ipii ON ipil.invoice_id = ipii.id AND ipii.is_delete = 0
+            where ipii.status = #{receivableQueryVo.invoiceSettlementStatus} and ipil.is_delete = 0
+            )
+        </if>
         <if test = "receivableQueryVo.agreementType != null and receivableQueryVo.agreementType != ''">
             AND ipi.agreement_type = #{receivableQueryVo.agreementType}
         </if>
@@ -582,7 +591,7 @@
         ipii.receivable_supervise_premium,
         ipiis.receive_payment_date,
         ipiis.create_by ,
-        ipiis.create_time
+        ipiis.create_time, ipiis.settlement_payment_difference , ipiis.settlement_payment_reason
         FROM
         ins_ply_income_invoice_settlement ipiis
         LEFT JOIN ins_ply_income_invoice ipii ON ipii.id = ipiis.invoice_id AND ipii.is_delete = 0
@@ -665,7 +674,7 @@
         MAX(ipiis.actual_received_amount) AS actual_received_amount,
         MAX(ipiis.receive_payment_date) AS receive_payment_date,
         MAX(ipiis.create_by) AS create_by,
-        MAX(ipiis.create_time) AS create_time, ipiis.settlement_payment_difference , ipiis.settlement_payment_reason, ipii.receivable_supervise_premium
+        MAX(ipiis.create_time) AS create_time, ipiis.settlement_payment_difference , ipiis.settlement_payment_reason, ipii.receivable_supervise_premium,ipii.contact_person , ipii.contact_person_phone
         FROM ins_ply_income_invoice_settlement ipiis
         LEFT JOIN ins_ply_income_invoice ipii ON ipii.id = ipiis.invoice_id AND ipii.is_delete = 0
         LEFT JOIN ins_ply_income_invoice_link ipil ON ipil.invoice_id = ipiis.invoice_id AND ipil.is_delete = 0
@@ -1920,7 +1929,7 @@
         eic.parent_id,
         ipi.company_id,
         ipi.system_code,
-        sum(COALESCE(ipi.jq_supervise_costs_premiums, 0)+ COALESCE(ipi.sy_supervise_costs_premiums,0)+coalesce(ipi.jy_supervise_costs_premiums,0 )+COALESCE(ipi.jq_other_costs_premiums, 0)+ COALESCE(ipi.sy_other_costs_premiums,0)+coalesce(ipi.jy_other_costs_premiums,0 )) as totalReceivable ,
+        sum(COALESCE(ipi.jq_receivable_premium, 0)+ COALESCE(ipi.sy_receivable_premium ,0)+coalesce(ipi.jy_receivable_premium ,0 )) as totalReceivable,
         sum(COALESCE(ipi.jq_other_costs_premiums, 0)+ COALESCE(ipi.sy_other_costs_premiums,0)+coalesce(ipi.jy_other_costs_premiums,0 )) as superviseFee4Other ,
         sum(COALESCE(ipi.jq_supervise_costs_premiums, 0)+ COALESCE(ipi.sy_supervise_costs_premiums,0)+coalesce(ipi.jy_supervise_costs_premiums,0 )) as superviseFee
         from

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

@@ -72,7 +72,7 @@
                 and sujibc.audit_status = #{sysUserJzgInfoBankCardVo.auditStatus}
             </if>
             <if test="sysUserJzgInfoBankCardVo.userId != null and sysUserJzgInfoBankCardVo.userId != ''">
-                and sujibc.user_info_id = #{sysUserJzgInfoBankCardVo.userId}
+                and su.id = #{sysUserJzgInfoBankCardVo.userId}
             </if>
         </where>
         order by