Przeglądaj źródła

Merge branch 'dev_jzg_lipf_v20260622'

lipf 1 miesiąc temu
rodzic
commit
b68704b0d4

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

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

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

@@ -503,7 +503,7 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
             ordersPolicy.setJyPolicyNo(ordersExternalPolicy.getNoPolicy());
             insOrdersPolicyService.updateByOrderNo(ordersPolicy);
 
-            insFeeAuditService.feeAuditAdd(insOrders, baseController.getSystemCode());
+
             // 发送订单状态变更消息
             this.orderStatusMessage(insOrders, insOrdersCarInfo, insOrdersCosts, baseController.getToken(), MessageCodeEnum.TEMPLATE_9);
             if (nullOrders) {
@@ -512,6 +512,10 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
                 insOrdersAdd.setInsOrders(orders);
                 saveOrders(insOrdersAdd);
             }
+            // modify by lipf , 2026年8月21日11:49:44 解决新车第一次报价的时候,费用审核有两条记录的bug
+            if (!nullOrders) {
+                insFeeAuditService.feeAuditAdd(insOrders, baseController.getSystemCode());
+            }
             // 返回成功信息,表示订单、车辆和用户信息保存成功
             return HttpResult.ok("保存成功");
 

+ 37 - 138
tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java

@@ -90,7 +90,6 @@ import java.util.function.BiConsumer;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
  * @author tz
@@ -1145,93 +1144,6 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         return baseMapper.queryFollowIncome(incomeVo);
     }
 
-    /**
-     * 根据发票状态、开票时间、结算时间过滤收入数据
-     * 优化:嵌套anyMatch改为HashMapID映射匹配,O(n²) -> O(n)
-     */
-    private List<InsPlyIncomeDto>  filterIncomeByInvoiceAndSettleCondition(List<InsPlyIncomeDto> incomeList, SettlementReportQueryVo queryVo) {
-        log.info("对查询条件进行转义:queryVo=[{}]", JSONUtil.toJsonStr(queryVo));
-        String status = queryVo.getStatus();
-        String invoiceStartTime = queryVo.getInvoiceStartTime();
-        String invoiceEndTime = queryVo.getInvoiceEndTime();
-        String settleStartTime = queryVo.getSettlementStartTime();
-        String settleEndTime = queryVo.getSettlementEndTime();
-
-        // 无筛选条件,直接原数据返回
-        boolean noFilterCond = StrUtil.isBlank(status)
-                && (StrUtil.isBlank(invoiceStartTime) || StrUtil.isBlank(invoiceEndTime))
-                && (StrUtil.isBlank(settleStartTime) || StrUtil.isBlank(settleEndTime));
-        if (noFilterCond || CollUtil.isEmpty(incomeList)) {
-            return incomeList;
-        }
-
-        // 查询收入关联链路
-        List<String> incomeIds = incomeList.stream().map(InsPlyIncomeDto::getId).distinct().toList();
-        LambdaQueryWrapper<InsPlyIncomeInvoiceLink> linkWrapper = new LambdaQueryWrapper<>();
-        linkWrapper.in(InsPlyIncomeInvoiceLink::getIncomeId, incomeIds);
-        List<InsPlyIncomeInvoiceLink> linkList = insPlyIncomeInvoiceLinkMapper.selectList(linkWrapper);
-        if (CollUtil.isEmpty(linkList)) {
-            return new ArrayList<>(0);
-        }
-
-        // 链路ID映射
-        Map<String, InsPlyIncomeInvoiceLink> linkInvoiceIdMap = linkList.stream()
-                .collect(Collectors.toMap(InsPlyIncomeInvoiceLink::getInvoiceId, Function.identity(), (k1, k2) -> k1));
-        Set<String> linkInvoiceIds = linkInvoiceIdMap.keySet();
-
-        // 查询发票
-        LambdaQueryWrapper<InsPlyIncomeInvoice> invoiceWrapper = new LambdaQueryWrapper<>();
-        invoiceWrapper.in(InsPlyIncomeInvoice::getId, linkInvoiceIds);
-        if (StrUtil.isNotBlank(status)) {
-            invoiceWrapper.eq(InsPlyIncomeInvoice::getStatus, status);
-        }
-        boolean invoiceTimeCond = StrUtil.isNotBlank(invoiceStartTime) && StrUtil.isNotBlank(invoiceEndTime);
-        if (invoiceTimeCond) {
-            invoiceWrapper.between(InsPlyIncomeInvoice::getInvoiceTime, toStartDateTime(invoiceStartTime), toEndDateTime(invoiceEndTime));
-        }
-        invoiceWrapper.eq(InsPlyIncomeInvoice::getInvoiceType, queryVo.getInvoiceType());
-        List<InsPlyIncomeInvoice> invoiceList = insPlyIncomeInvoiceMapper.selectList(invoiceWrapper);
-        if ((StrUtil.isNotBlank(status) || invoiceTimeCond) && CollUtil.isEmpty(invoiceList)) {
-            return new ArrayList<>(0);
-        }
-
-        // 结算时间过滤
-        boolean settleTimeCond = StrUtil.isNotBlank(settleStartTime) && StrUtil.isNotBlank(settleEndTime);
-        if (settleTimeCond) {
-            Set<String> invoiceIdSet = invoiceList.stream().map(InsPlyIncomeInvoice::getId).collect(Collectors.toSet());
-            LambdaQueryWrapper<InsPlyIncomeInvoiceSettlement> settleWrapper = new LambdaQueryWrapper<>();
-            settleWrapper.in(InsPlyIncomeInvoiceSettlement::getInvoiceId, invoiceIdSet);
-            settleWrapper.between(InsPlyIncomeInvoiceSettlement::getCreateTime, toStartDateTime(settleStartTime), toEndDateTime(settleEndTime));
-            List<InsPlyIncomeInvoiceSettlement> settleList = insPlyIncomeInvoiceSettlementMapper.selectList(settleWrapper);
-            if (CollUtil.isEmpty(settleList)) {
-                return new ArrayList<>(0);
-            }
-            // 保留存在结算记录的发票
-            Set<String> validSettleInvoiceIds = settleList.stream()
-                    .map(InsPlyIncomeInvoiceSettlement::getInvoiceId)
-                    .collect(Collectors.toSet());
-            invoiceList = invoiceList.stream()
-                    .filter(invoice -> validSettleInvoiceIds.contains(invoice.getId()))
-                    .toList();
-        }
-
-        // 合法发票ID集合
-        Set<String> validInvoiceIds = invoiceList.stream()
-                .map(InsPlyIncomeInvoice::getId)
-                .collect(Collectors.toSet());
-        // 过滤合法链路
-        List<InsPlyIncomeInvoiceLink> validLinkList = linkList.stream()
-                .filter(link -> validInvoiceIds.contains(link.getInvoiceId()))
-                .toList();
-        Set<String> validIncomeIds = validLinkList.stream()
-                .map(InsPlyIncomeInvoiceLink::getIncomeId)
-                .collect(Collectors.toSet());
-
-        // 最终过滤收入数据
-        return incomeList.stream()
-                .filter(income -> validIncomeIds.contains(income.getId()))
-                .toList();
-    }
 
     /**
      * 将其他费用收入合并至结果集,不存在则新增VO
@@ -5485,8 +5397,8 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         // 用ins_ply_income的id关联查到ins_ply_income_invoice_link再关联到ins_ply_income_invoice_settlement,取出结算日期、结算人
         if (CollUtil.isNotEmpty(exportPlatFormReceivableVOS)) {
             //1.拿到所有incomeId集合
-            List<Long> incomeIdList = exportPlatFormReceivableVOS.stream()
-                    .map(item -> Long.valueOf(item.getId()))
+            List<String> incomeIdList = exportPlatFormReceivableVOS.stream()
+                    .map(ExportPlatFormReceivableVO::getId)
                     .collect(Collectors.toList());
 
             Map<String, InsPlyIncomeInvoiceSettlement> settlementMap = IncomeInvoiceLinkUtil.querySettlementByIncomeList(incomeIdList, insPlyIncomeInvoiceLinkMapper, insPlyIncomeInvoiceSettlementMapper);
@@ -5984,8 +5896,37 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
                 })
                 .toList();
         // 过滤数据
-        List<InsPlyIncomeDto> filterIncomeList = filterIncomeByInvoiceAndSettleCondition(dtoList, queryVo);
-        allCompaniesIncomeDatas = allCompaniesIncomeDatas.stream().filter(all -> filterIncomeList.stream().anyMatch(x -> x.getId().equals(all.getId()))).toList();
+        List<InsPlyIncomeDto> filterIncomeList = IncomeInvoiceLinkUtil.filterIncomeByInvoiceAndSettleCondition(
+                dtoList,
+                queryVo,
+                insPlyIncomeInvoiceLinkMapper,
+                insPlyIncomeInvoiceMapper,
+                insPlyIncomeInvoiceSettlementMapper
+        );
+        Map<String, List<String>> invoiceIdMap = IncomeInvoiceLinkUtil.queryIncomeToInvoiceIdMap(filterIncomeList.stream().map(InsPlyIncomeDto::getId).toList(), insPlyIncomeInvoiceLinkMapper);
+
+        // 给每个dto赋值逗号拼接的InvoiceIds
+        for (InsPlyIncomeDto incomeDto : filterIncomeList) {
+            String incomeId = incomeDto.getId();
+            List<String> invoiceIdList = invoiceIdMap.getOrDefault(incomeId, CollUtil.newArrayList());
+            if (CollUtil.isNotEmpty(invoiceIdList)) {
+                // 逗号拼接多个发票id
+                String invoiceIdsStr = String.join(",", invoiceIdList);
+                incomeDto.setInvoiceIds(invoiceIdsStr);
+            } else {
+                // 无关联发票,置空
+                incomeDto.setInvoiceIds(null);
+            }
+        }
+
+        // 根据结算状态过滤:0-已开票未结清 1-已结清 2-未开票
+        List<InsPlyIncomeDto> insPlyIncomeDtos = IncomeInvoiceLinkUtil.filterBySettlementStatus(filterIncomeList,
+                queryVo.getSettlementStatus(),
+                InsPlyIncomeDto::getInvoiceIds,
+                baseMapper);
+
+
+        allCompaniesIncomeDatas = allCompaniesIncomeDatas.stream().filter(all -> insPlyIncomeDtos.stream().anyMatch(x -> x.getId().equals(all.getId()))).toList();
 
         // 按公司ID分组聚合求和
         Map<String, List<CompanySuperviseSettlementReportDto>> groupByCompany = allCompaniesIncomeDatas.stream()
@@ -6482,31 +6423,10 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
                 }
             }
             // 根据结算状态过滤:0-已开票未结清 1-已结清 2-未开票
-            if(StrUtil.isNotEmpty(settlementReportQueryVo.getSettlementStatus())){
-                String settlementStatus = settlementReportQueryVo.getSettlementStatus();
-                if("2".equals(settlementStatus)){
-                    // 未开票:ins_ply_income_invoice没有数据
-                    records = records.stream().filter(action -> StrUtil.isEmpty(action.getInvoiceIds())).toList();
-                } else if("0".equals(settlementStatus)){
-                    // 已开票未结清:有发票数据,且存在status=0的发票
-                    records = records.stream().filter(action -> {
-                        if(StrUtil.isEmpty(action.getInvoiceIds())){
-                            return false;
-                        }
-                        List<String> invoiceIdList = Arrays.asList(action.getInvoiceIds().split(","));
-                        return baseMapper.countUnsettledInvoicesByInvoiceIds(invoiceIdList) > 0;
-                    }).toList();
-                } else if("1".equals(settlementStatus)){
-                    // 已结清:有发票数据,且所有发票status=1
-                    records = records.stream().filter(action -> {
-                        if(StrUtil.isEmpty(action.getInvoiceIds())){
-                            return false;
-                        }
-                        List<String> invoiceIdList = Arrays.asList(action.getInvoiceIds().split(","));
-                        return baseMapper.countUnsettledInvoicesByInvoiceIds(invoiceIdList) == 0;
-                    }).toList();
-                }
-            }
+            records = IncomeInvoiceLinkUtil.filterBySettlementStatus(records,
+                    settlementReportQueryVo.getSettlementStatus(),
+                    ReceiverSettlementReportDto::getInvoiceIds,
+                    baseMapper);
             receiverSettlementReport.setRecords(records);
         }
         return receiverSettlementReport;
@@ -6860,27 +6780,6 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         }
     }
 
-    /**
-     * yyyy-MM-dd 转当天起始 LocalDateTime
-     */
-    public static LocalDateTime toStartDateTime(String dateStr) {
-        if (StrUtil.isBlank(dateStr)){
-            return null;
-        }
-        LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE);
-        return date.atStartOfDay();
-    }
-
-    /**
-     * yyyy-MM-dd 转当天结束 LocalDateTime
-     */
-    public static LocalDateTime toEndDateTime(String dateStr) {
-        if (StrUtil.isBlank(dateStr)){
-            return null;
-        }
-        LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE);
-        return date.atTime(23, 59, 59, 999999999);
-    }
 
     // 递归获取所有子孙ID
     private List<String> getAllChildIdsOptimized(String parentId, Map<String, List<EsmInsCompany>> parentGroupMap) {

+ 236 - 16
tenant/organization/src/main/java/com/jzg/organization/utils/IncomeInvoiceLinkUtil.java

@@ -1,18 +1,25 @@
 package com.jzg.organization.utils;
 
 import cn.hutool.core.collection.CollUtil;
-import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.util.*;
-import java.util.stream.Collectors;
-
 import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.jzg.commons.entity.finance.dto.InsPlyIncomeDto;
+import com.jzg.commons.entity.finance.po.InsPlyIncomeInvoice;
 import com.jzg.commons.entity.finance.po.InsPlyIncomeInvoiceLink;
 import com.jzg.commons.entity.finance.po.InsPlyIncomeInvoiceSettlement;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.jzg.commons.entity.finance.vo.SettlementReportQueryVo;
 import com.jzg.organization.mapper.InsPlyIncomeInvoiceLinkMapper;
+import com.jzg.organization.mapper.InsPlyIncomeInvoiceMapper;
 import com.jzg.organization.mapper.InsPlyIncomeInvoiceSettlementMapper;
+import com.jzg.organization.mapper.ReceivableMapper;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 public class IncomeInvoiceLinkUtil {
 
@@ -20,13 +27,13 @@ public class IncomeInvoiceLinkUtil {
     }
 
     /**
-     * 根据incomeId集合 查询应收开票结算
+     * 根据incomeId集合 查询应收开票结算的数据
      * @param incomeIdList 应收主表id集合
      * @param linkMapper link表mapper
      * @param settlementMapper settlement表mapper
      * @return key: invoiceId, value: settlement结算记录,旧值会被新值替换,按创建时间倒序
      */
-    public static Map<String, InsPlyIncomeInvoiceSettlement> querySettlementByIncomeList(List<Long> incomeIdList,
+    public static Map<String, InsPlyIncomeInvoiceSettlement> querySettlementByIncomeList(List<String> incomeIdList,
                                                                           InsPlyIncomeInvoiceLinkMapper linkMapper,
                                                                           InsPlyIncomeInvoiceSettlementMapper settlementMapper) {
         if (CollUtil.isEmpty(incomeIdList)) {
@@ -57,19 +64,44 @@ public class IncomeInvoiceLinkUtil {
                     .collect(Collectors.toMap(InsPlyIncomeInvoiceSettlement::getInvoiceId, s -> s, (exist, newVal) -> newVal));
         }
 
+        return settlementMap;
+    }
 
 
-        return settlementMap;
+    /**
+     * 根据应收id集合,获取 key:incomeId, value:对应多个invoiceId集合 的Map
+     * @param incomeIdList 应收主表id集合
+     * @param linkMapper link中间表mapper
+     * @return key:incomeId,value:该应收关联的发票id集合,无数据返回空Map,内部list不会为null
+     */
+    public static Map<String, List<String>> queryIncomeToInvoiceIdMap(List<String> incomeIdList,
+                                                                      InsPlyIncomeInvoiceLinkMapper linkMapper) {
+        if (CollUtil.isEmpty(incomeIdList)) {
+            return MapUtil.empty();
+        }
+        List<InsPlyIncomeInvoiceLink> invoiceLinkList = getInvoiceLinkList(incomeIdList, linkMapper);
+        if (CollUtil.isEmpty(invoiceLinkList)) {
+            return MapUtil.empty();
+        }
+
+        // 按incomeId分组,提取每个下的invoiceId,过滤null并去重
+        return invoiceLinkList.stream()
+                .collect(Collectors.groupingBy(
+                        InsPlyIncomeInvoiceLink::getIncomeId,
+                        Collectors.mapping(InsPlyIncomeInvoiceLink::getInvoiceId,
+                                Collectors.filtering(Objects::nonNull,
+                                        Collectors.toList()))
+                ));
     }
 
 
     /**
      * 根据incomeId获取invoiceLink的Map分组
-     * @param incomeIdList
-     * @param linkMapper
-     * @return
+     * @param incomeIdList incomeId的集合
+     * @param linkMapper ins_ply_income_invoice_link中间表的数据
+     * @return 按incomeId分组,一个income可能多条link
      */
-    public static Map<String, List<InsPlyIncomeInvoiceLink>> queryInvoiceLinkByIncomeId(List<Long> incomeIdList,
+    public static Map<String, List<InsPlyIncomeInvoiceLink>> queryInvoiceLinkByIncomeId(List<String> incomeIdList,
                                                                                    InsPlyIncomeInvoiceLinkMapper linkMapper) {
 
         List<InsPlyIncomeInvoiceLink> invoiceLinkList = getInvoiceLinkList(incomeIdList, linkMapper);
@@ -84,12 +116,200 @@ public class IncomeInvoiceLinkUtil {
     }
 
 
-    // 单纯获取InsPlyIncomeInvoiceLink的列表
-    public static List<InsPlyIncomeInvoiceLink> getInvoiceLinkList(List<Long> incomeIdList, InsPlyIncomeInvoiceLinkMapper linkMapper) {
+    /**
+     * 单纯获取InsPlyIncomeInvoiceLink的列表
+     */
+    public static List<InsPlyIncomeInvoiceLink> getInvoiceLinkList(List<String> incomeIdList, InsPlyIncomeInvoiceLinkMapper linkMapper) {
         // 1、查询link关联表
         LambdaQueryWrapper<InsPlyIncomeInvoiceLink> linkWrapper = new LambdaQueryWrapper<>();
         linkWrapper.in(InsPlyIncomeInvoiceLink::getIncomeId, incomeIdList);
         linkWrapper.eq(InsPlyIncomeInvoiceLink::getIsDelete, 0);
         return linkMapper.selectList(linkWrapper);
     }
+
+    /**
+     * 根据发票状态、开票时间、结算时间过滤收入数据
+     * 优化:嵌套anyMatch改为HashMapID映射匹配,O(n²) -> O(n)
+     *
+     * @param incomeList               待过滤收入dto列表
+     * @param queryVo                  查询条件
+     * @param incomeInvoiceLinkMapper  收入发票链路mapper
+     * @param incomeInvoiceMapper      发票mapper
+     * @param invoiceSettlementMapper  发票结算mapper
+     * @return 过滤之后收入数据
+     */
+    public static List<InsPlyIncomeDto> filterIncomeByInvoiceAndSettleCondition(
+            List<InsPlyIncomeDto> incomeList,
+            SettlementReportQueryVo queryVo,
+            InsPlyIncomeInvoiceLinkMapper incomeInvoiceLinkMapper,
+            InsPlyIncomeInvoiceMapper incomeInvoiceMapper,
+            InsPlyIncomeInvoiceSettlementMapper invoiceSettlementMapper
+    ) {
+
+        String status = queryVo.getStatus();
+        String invoiceStartTime = queryVo.getInvoiceStartTime();
+        String invoiceEndTime = queryVo.getInvoiceEndTime();
+        String settleStartTime = queryVo.getSettlementStartTime();
+        String settleEndTime = queryVo.getSettlementEndTime();
+
+        // 无筛选条件,直接原数据返回
+        boolean noFilterCond = StrUtil.isBlank(status)
+                && (StrUtil.isBlank(invoiceStartTime) || StrUtil.isBlank(invoiceEndTime))
+                && (StrUtil.isBlank(settleStartTime) || StrUtil.isBlank(settleEndTime));
+        if (noFilterCond || CollUtil.isEmpty(incomeList)) {
+            return incomeList;
+        }
+
+        // 查询收入关联链路
+        List<String> incomeIds = incomeList.stream()
+                .map(InsPlyIncomeDto::getId)
+                .distinct()
+                .toList();
+
+        LambdaQueryWrapper<InsPlyIncomeInvoiceLink> linkWrapper = new LambdaQueryWrapper<>();
+        linkWrapper.in(InsPlyIncomeInvoiceLink::getIncomeId, incomeIds);
+        List<InsPlyIncomeInvoiceLink> linkList = incomeInvoiceLinkMapper.selectList(linkWrapper);
+        if (CollUtil.isEmpty(linkList)) {
+            return new ArrayList<>(0);
+        }
+
+        // 链路ID映射
+        Map<String, InsPlyIncomeInvoiceLink> linkInvoiceIdMap = linkList.stream()
+                .collect(Collectors.toMap(InsPlyIncomeInvoiceLink::getInvoiceId,
+                        Function.identity(),
+                        (k1, k2) -> k1));
+        Set<String> linkInvoiceIds = linkInvoiceIdMap.keySet();
+
+        // 查询发票
+        LambdaQueryWrapper<InsPlyIncomeInvoice> invoiceWrapper = new LambdaQueryWrapper<>();
+        invoiceWrapper.in(InsPlyIncomeInvoice::getId, linkInvoiceIds);
+        if (StrUtil.isNotBlank(status)) {
+            invoiceWrapper.eq(InsPlyIncomeInvoice::getStatus, status);
+        }
+        boolean invoiceTimeCond = StrUtil.isNotBlank(invoiceStartTime) && StrUtil.isNotBlank(invoiceEndTime);
+        if (invoiceTimeCond) {
+            invoiceWrapper.between(InsPlyIncomeInvoice::getInvoiceTime,
+                    toStartDateTime(invoiceStartTime),
+                    toEndDateTime(invoiceEndTime));
+        }
+        invoiceWrapper.eq(InsPlyIncomeInvoice::getInvoiceType, queryVo.getInvoiceType());
+        List<InsPlyIncomeInvoice> invoiceList = incomeInvoiceMapper.selectList(invoiceWrapper);
+
+        if ((StrUtil.isNotBlank(status) || invoiceTimeCond) && CollUtil.isEmpty(invoiceList)) {
+            return new ArrayList<>(0);
+        }
+
+        // 结算时间过滤
+        boolean settleTimeCond = StrUtil.isNotBlank(settleStartTime) && StrUtil.isNotBlank(settleEndTime);
+        if (settleTimeCond) {
+            Set<String> invoiceIdSet = invoiceList.stream()
+                    .map(InsPlyIncomeInvoice::getId)
+                    .collect(Collectors.toSet());
+
+            LambdaQueryWrapper<InsPlyIncomeInvoiceSettlement> settleWrapper = new LambdaQueryWrapper<>();
+            settleWrapper.in(InsPlyIncomeInvoiceSettlement::getInvoiceId, invoiceIdSet);
+            settleWrapper.between(InsPlyIncomeInvoiceSettlement::getCreateTime,
+                    toStartDateTime(settleStartTime),
+                    toEndDateTime(settleEndTime));
+
+            List<InsPlyIncomeInvoiceSettlement> settleList = invoiceSettlementMapper.selectList(settleWrapper);
+            if (CollUtil.isEmpty(settleList)) {
+                return new ArrayList<>(0);
+            }
+            // 保留存在结算记录的发票
+            Set<String> validSettleInvoiceIds = settleList.stream()
+                    .map(InsPlyIncomeInvoiceSettlement::getInvoiceId)
+                    .collect(Collectors.toSet());
+
+            invoiceList = invoiceList.stream()
+                    .filter(invoice -> validSettleInvoiceIds.contains(invoice.getId()))
+                    .toList();
+        }
+
+        // 合法发票ID集合
+        Set<String> validInvoiceIds = invoiceList.stream()
+                .map(InsPlyIncomeInvoice::getId)
+                .collect(Collectors.toSet());
+
+        // 过滤合法链路
+        List<InsPlyIncomeInvoiceLink> validLinkList = linkList.stream()
+                .filter(link -> validInvoiceIds.contains(link.getInvoiceId()))
+                .toList();
+
+        Set<String> validIncomeIds = validLinkList.stream()
+                .map(InsPlyIncomeInvoiceLink::getIncomeId)
+                .collect(Collectors.toSet());
+
+        // 最终过滤收入数据
+        return incomeList.stream()
+                .filter(income -> validIncomeIds.contains(income.getId()))
+                .toList();
+    }
+
+
+    /**
+     * 结算状态内存过滤(无接口,函数式getter)
+     * 0-已开票未结清 1-已结清 2-未开票
+     *
+     * @param records           待过滤dto列表
+     * @param settlementStatus  结算状态:0/1/2
+     * @param getInvoiceIdFunc  获取invoiceIds的getter函数
+     * @param baseMapper        mapper,用于统计未结清发票数量
+     * @param <T>               任意类型
+     * @return 过滤后集合
+     */
+    public static <T> List<T> filterBySettlementStatus(
+            List<T> records,
+            String settlementStatus,
+            Function<T, String> getInvoiceIdFunc,
+            ReceivableMapper baseMapper
+    ) {
+        if (CollUtil.isEmpty(records) || StrUtil.isBlank(settlementStatus)) {
+            return records;
+        }
+        return records.stream().filter(action -> {
+            String invoiceIds = getInvoiceIdFunc.apply(action);
+            if ("2".equals(settlementStatus)) {
+                return StrUtil.isEmpty(invoiceIds);
+            } else if ("0".equals(settlementStatus)) {
+                if (StrUtil.isEmpty(invoiceIds)) {
+                    return false;
+                }
+                List<String> invoiceIdList = Arrays.asList(invoiceIds.split(","));
+                return baseMapper.countUnsettledInvoicesByInvoiceIds(invoiceIdList) > 0;
+            } else if ("1".equals(settlementStatus)) {
+                if (StrUtil.isEmpty(invoiceIds)) {
+                    return false;
+                }
+                List<String> invoiceIdList = Arrays.asList(invoiceIds.split(","));
+                return baseMapper.countUnsettledInvoicesByInvoiceIds(invoiceIdList) == 0;
+            }
+            return true;
+        }).toList();
+    }
+
+
+
+
+    /**
+     * yyyy-MM-dd 转当天起始 LocalDateTime
+     */
+    public static LocalDateTime toStartDateTime(String dateStr) {
+        if (StrUtil.isBlank(dateStr)){
+            return null;
+        }
+        LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE);
+        return date.atStartOfDay();
+    }
+
+    /**
+     * yyyy-MM-dd 转当天结束 LocalDateTime
+     */
+    public static LocalDateTime toEndDateTime(String dateStr) {
+        if (StrUtil.isBlank(dateStr)){
+            return null;
+        }
+        LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE);
+        return date.atTime(23, 59, 59, 999999999);
+    }
 }