Преглед изворни кода

Merge remote-tracking branch 'origin/master'

lixiaolong пре 2 месеци
родитељ
комит
94800c66ab

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

@@ -58,6 +58,10 @@ public class InsPlyIncomeDto extends BaseModel {
     @TableField(exist = false)
     private String signYear;
 
+    @Schema(description = "签单月份")
+    @TableField(exist = false)
+    private String signMonth;
+
     @Schema(description = "签单日期 yyyy-mm-dd 格式")
     @TableField(exist = false)
     private String signDate;

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

@@ -46,6 +46,12 @@ public class IncomeDataVO implements Serializable {
     private String contactPersonPhone;
 
 
+    /**
+     * 类型:1:手续费 2:跟单费 3:驾意手续费 4:驾意跟单费
+     */
+    private String invoiceType;
+
+
     @Data
     public static class SearchVO implements Serializable {
         @Serial

+ 30 - 0
commons/src/main/java/com/jzg/commons/entity/finance/vo/QueryFollowIncomeVo.java

@@ -0,0 +1,30 @@
+package com.jzg.commons.entity.finance.vo;
+
+import com.jzg.commons.core.base.PageRequest;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+public class QueryFollowIncomeVo  extends PageRequest implements Serializable {
+
+    @Schema(description = "开始年份")
+    private Integer startYear;
+
+    @Schema(description = "结束年份")
+    private Integer endYear;
+
+    @Schema(description = "租户id")
+    private String systemCode;
+
+    @Schema(description = "保险公司id")
+    private List<String> companyIdList;
+
+    @Schema(description = "保险公司id")
+    private String companyId;
+
+}

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

@@ -116,4 +116,9 @@ public class ReceivableQueryVo extends PageRequest {
     @Schema(description = "租户代码")
     private String systemCode;
 
+    /**
+     * 类型:1:手续费 2:跟单费 3:驾意手续费 4:驾意跟单费
+     */
+    private String invoiceType;
+
 }

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

@@ -16,6 +16,9 @@ public class SettlementReportQueryVo extends PageRequest {
     @Schema(description = "保险公司id")
     private String companyId;
 
+    @Schema(description = "保险公司id")
+    private List<String> companyIdList;
+
     @Schema(description = "对接人")
     private String contactPerson;
 

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

@@ -116,28 +116,6 @@ public class InsFeeOrdersServiceImpl extends ServiceImpl<InsFeeOrdersMapper, Ins
         // 获取费用信息
         InsFeeOrders insFeeOrders = insFeeOrdersMapper.selectById(insOrders.getId());
 
-        // add by lipf, 2026年6月23日18:32:24 按照财务和田智沟通后的结果,当入口手续费比例大于入口比例的时候,强制设置入口手续费比例为入口比例。
-//        BigDecimal jqInletRatio = insFeeOrders.getJqInletRatio();
-//        BigDecimal syInletRatio = insFeeOrders.getSyInletRatio();
-//        BigDecimal jyInletRatio = insFeeOrders.getJyInletRatio();
-//
-//        BigDecimal jqCommissionRatio = insFeeOrders.getJqCommissionRatio();
-//        BigDecimal syCommissionRatio = insFeeOrders.getSyCommissionRatio();
-//        BigDecimal jyCommissionRatio = insFeeOrders.getJyCommissionRatio();
-//
-//        if(BigDecimalUtil.subtract(jqCommissionRatio,jqInletRatio).compareTo(BigDecimal.ZERO)>0){
-//            insFeeOrders.setJqCommissionRatio(jqInletRatio);
-//            insFeeOrders.setJqFollowRatio(BigDecimal.ZERO);
-//        }
-//        if(BigDecimalUtil.subtract(syCommissionRatio,syInletRatio).compareTo(BigDecimal.ZERO)>0){
-//            insFeeOrders.setSyCommissionRatio(syInletRatio);
-//            insFeeOrders.setSyFollowRatio(BigDecimal.ZERO);
-//        }
-//        if(BigDecimalUtil.subtract(jyCommissionRatio,jyInletRatio).compareTo(BigDecimal.ZERO)>0){
-//            insFeeOrders.setJyCommissionRatio(jyInletRatio);
-//            insFeeOrders.setJyFollowRatio(BigDecimal.ZERO);
-//        }
-
         // 关键:获取是否含税标识
         Integer withTax = ptlAgreement.getWithTax(); // 0-否 1-是
 
@@ -234,7 +212,8 @@ public class InsFeeOrdersServiceImpl extends ServiceImpl<InsFeeOrdersMapper, Ins
 //        log.info("分销总费用:distributionFee=【{}】",distributionFee);
 //        BigDecimal keepPoint = BigDecimalUtil.subtract(BigDecimalUtil.add(inlet,addThrow),BigDecimalUtil.add(export, distributionFee));
 //        log.info("留点费用:inlet=[{}],addThrow=[{}],export=[{}], distributionFee=[{}]mkeepPoint=[{}]", inlet, addThrow, export, distributionFee, keepPoint);
-        BigDecimal exportContainDistribute = premium.multiply(exportRatioContainDistribution).setScale(scale, RoundingMode.HALF_DOWN);
+        // modify by lipf 财务要求,计算留点的时候,出口费用,按照两位进行截断
+        BigDecimal exportContainDistribute = premium.multiply(exportRatioContainDistribution).setScale(2, RoundingMode.DOWN);
         BigDecimal keepPoint = BigDecimalUtil.subtract(BigDecimalUtil.add(inlet,addThrow),exportContainDistribute);
         log.info("计算留点:inlet=[{}],addThrow=[{}].exportContainDistribute=[{}]", inlet, addThrow, exportContainDistribute);
 
@@ -412,15 +391,15 @@ public class InsFeeOrdersServiceImpl extends ServiceImpl<InsFeeOrdersMapper, Ins
             jyCommissionRatio = jyInletRatio;
         }
 
-        // 手续费
+        // 手续费比例
         insFeeOrders.setJqCommissionRatio(jqCommissionRatio);
         insFeeOrders.setSyCommissionRatio(syCommissionRatio);
         insFeeOrders.setJyCommissionRatio(jyCommissionRatio);
-        // 入口费用
+        // 入口费用比例
         insFeeOrders.setJqInletRatio(jqInletRatio);
         insFeeOrders.setSyInletRatio(syInletRatio);
         insFeeOrders.setJyInletRatio(jyInletRatio);
-        // 跟单费
+        // 跟单费比例
         insFeeOrders.setJqFollowRatio(jqFollowRatio);
         insFeeOrders.setSyFollowRatio(syFollowRatio);
         insFeeOrders.setJyFollowRatio(jyFollowRatio);
@@ -446,8 +425,8 @@ public class InsFeeOrdersServiceImpl extends ServiceImpl<InsFeeOrdersMapper, Ins
         BigDecimal jqKeepPointRatio = (jqInletRatio.divide(taxFactor, 5, RoundingMode.HALF_EVEN)).add(jqAdditionalRatio).subtract(BigDecimalUtil.add(jqExportRatio,distributionRatio));
         log.info("计算留点比例。 distributionRatio=[{}],jqInletRatio=[{}],jqAdditionalRatio=[{}],jqExportRatio=[{}]", distributionRatio,jqInletRatio,jqAdditionalRatio,jqExportRatio);
 
-        BigDecimal syKeepPointRatio = (syInletRatio.divide(taxFactor, 5, RoundingMode.HALF_EVEN)).add(syAdditionalRatio).subtract(BigDecimalUtil.add(jqExportRatio,syExportRatio));
-        BigDecimal jyKeepPointRatio = (jyInletRatio.divide(taxFactor, 5, RoundingMode.HALF_EVEN)).add(jyAdditionalRatio).subtract(BigDecimalUtil.add(jqExportRatio,jyExportRatio));
+        BigDecimal syKeepPointRatio = (syInletRatio.divide(taxFactor, 5, RoundingMode.HALF_EVEN)).add(syAdditionalRatio).subtract(BigDecimalUtil.add(syExportRatio,distributionRatio));
+        BigDecimal jyKeepPointRatio = (jyInletRatio.divide(taxFactor, 5, RoundingMode.HALF_EVEN)).add(jyAdditionalRatio).subtract(BigDecimalUtil.add(jyExportRatio,distributionRatio));
         // 留点比例
         insFeeOrders.setJqKeepPointRatio(jqKeepPointRatio);
         insFeeOrders.setSyKeepPointRatio(syKeepPointRatio);

+ 2 - 6
tenant/organization/src/main/java/com/jzg/organization/mapper/ReceivableMapper.java

@@ -269,14 +269,10 @@ public interface ReceivableMapper extends BaseMapper<InsPlyIncome> {
 
     /**
      * 查询
-     * @param startYear
-     * @param endYear
-     * @param systemCode
+     * @param queryFollowIncomeVo
      * @return
      */
-    List<InsPlyIncomeDto> queryFollowIncome(@Param("startYear") Integer startYear,
-                                            @Param("endYear") Integer endYear,
-                                            @Param("systemCode")  String systemCode);
+    List<InsPlyIncomeDto> queryFollowIncome(@Param("query") QueryFollowIncomeVo queryFollowIncomeVo);
 
     /**
      * 查询发票结算的金额

+ 154 - 92
tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java

@@ -6,7 +6,6 @@ import cn.hutool.core.date.DateTime;
 import cn.hutool.core.lang.tree.Tree;
 import cn.hutool.core.lang.tree.TreeNodeConfig;
 import cn.hutool.core.lang.tree.TreeUtil;
-import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.excel.EasyExcel;
@@ -25,10 +24,7 @@ import com.jzg.commons.entity.finance.dto.*;
 import com.jzg.commons.entity.finance.po.*;
 import com.jzg.commons.entity.finance.vo.*;
 import com.jzg.commons.entity.orders.po.InsOrderAdjust;
-import com.jzg.commons.entity.po.EsmInsCompany;
-import com.jzg.commons.entity.po.InsFeeOrders;
-import com.jzg.commons.entity.po.PtlAgreement;
-import com.jzg.commons.entity.po.SysUploadFiles;
+import com.jzg.commons.entity.po.*;
 import com.jzg.commons.entity.quote.vo.orders.InsOrdersVo;
 import com.jzg.commons.entity.vo.PtlAgreementCostRatioVo;
 import com.jzg.commons.exception.ServiceException;
@@ -288,7 +284,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         log.info("获取私有协议手续费应收列表。receivableQueryVo=[{}]", JSONUtil.toJsonStr(receivableQueryVo));
         Page<InsPlyIncome> page = baseMapper.getReceivablePage(receivableQueryVo.getPage(), receivableQueryVo);
         List<InsPlyIncome> records = page.getRecords();
-        records = this.fillOtherInfo(records);
+        records = this.fillOtherInfo(records,receivableQueryVo.getInvoiceType());
         page.setRecords(records);
         return page;
     }
@@ -647,7 +643,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             }
         }
 
-        filterIncomes = this.fillOtherInfo(filterIncomes);
+        filterIncomes = this.fillOtherInfo(filterIncomes,incomeDataVO.getInvoiceType());
         return HttpResult.ok(filterIncomes);
     }
 
@@ -711,19 +707,25 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
     /**
      * 私有协议-跟单结算记录-结算报表查询
      * <p>
-     * 该方法用于查询私有协议的跟单结算报表数据,包括以下处理逻辑:
-     * 1. 从数据库查询基础结算报表数据
-     * 2. 调用保险公司客户端获取所有保险公司信息
-     * 3. 如果保险公司数据为空,直接返回原始数据
-     * 4. 匹配并填充保险公司名称
-     * 5. 计算未结算金额(已开票金额 - 已结算金额)
-     * 6. 计算未开票金额(累计应收 - 已开票金额)
+     * 该方法用于查询私有协议下跟单车险的结算报表数据,主要处理逻辑包括:
+     * 1. 查询跟单费用结算报表基础数据
+     * 2. 获取保险公司信息并映射公司名称
+     * 3. 按合作公司ID、年份、月份分组统计结算数据
+     * 4. 计算各项金额指标:总应收、已开票、未开票、已结算、未结算等
+     * 5. 补充收入表中的其他费用应收数据(驾意险相关费用)
      * </p>
      *
-     * @param settlementReportQueryVo 结算报表查询条件对象,包含以下主要查询参数:
-     * - companyId: 保险公司ID  - contactPerson: 对接人  - contactPersonPhone: 对接人手机号  - startTime/endTime: 创建时间范围    - invoiceStartTime/invoiceEndTime: 开票时间范围  - settlementStartTime/settlementEndTime: 结算时间范围     - status: 结算状态   - invoiceTypes: 开票类型列表(1-手续费, 2-跟单费, 3-驾意险手续费, 4-驾意险跟单费)  - agreementType: 协议类型  - invoiceStatus: 开票状态(0-未开票, 1-已开票) - systemCode: 租户代码  - signingStartTime/signingEndTime: 签单时间范围
-     * @return List<FollowCompanyFeeVO> 返回跟随公司费用视图对象列表,每个对象包含:
-     * - companyName: 保险公司名称(根据partnerCompanyId匹配填充) - companyId: 保险公司ID   - contactPerson: 对接人  - contactPersonPhone: 对接人手机号  - partnerCompanyId: 分支保险公司ID  - totalInvoiced: 已开票总金额  - totalUnInvoiced: 未开票总金额(计算得出:累计应收 - 已开票金额)   - totalSettlementAmount: 已结算总金额 - totalUnSettlementAmount: 未结算总金额(计算得出:已开票金额 - 已结算金额)  - totalPaymentDifference: 回款差额  - totalReceivable: 累计应收
+     * @param settlementReportQueryVo 结算报表查询条件对象,包含查询所需的过滤参数(如时间范围、公司ID等)
+     * @return List<FollowCompanyFeeVO> 返回跟单公司费用视图对象列表,每个对象包含:
+     *         - partnerCompanyId: 合作公司ID
+     *         - companyName: 合作公司名称
+     *         - year: 年份
+     *         - month: 月份
+     *         - totalReceivable: 总应收金额
+     *         - totalInvoiced: 已开票总金额
+     *         - totalUnInvoiced: 未开票总金额
+     *         - totalSettlementAmount: 已结算总金额
+     *         - totalUnSettlementAmount: 未结算总金额
      */
     @Override
     public List<FollowCompanyFeeVO> followCompanySuperviseSettlementReport(SettlementReportQueryVo settlementReportQueryVo) {
@@ -736,71 +738,123 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         // 查询所有保险公司,匹配保险公司的id和名称
         HttpResult<Map<String, EsmInsCompany>> mapHttpResult = esmInsCompanyClient.queryAllCompanyMap();
         Map<String, EsmInsCompany> data = mapHttpResult.getData();
-        if (CollUtil.isEmpty(data) || CollUtil.isEmpty(followCompanyFeeVos)){
+        if (CollUtil.isEmpty(data)){
             return resultList;
         }
 
-        // 根据分支公司分组
-        Map<String, List<FollowCompanyFeeVO>> followMap = followCompanyFeeVos.stream().collect(Collectors.groupingBy(follow -> follow.getPartnerCompanyId() + "_" + follow.getYear() + "_" + follow.getMonth()));
-        for (Map.Entry<String, List<FollowCompanyFeeVO>> entry : followMap.entrySet()) {
-            // key = 合作公司ID
-            String key = entry.getKey();
-
-            // 分组参数
-            String[] arr = key.split("_");
-            String partnerCompanyId = arr[0];
-            String year = arr[1];
-            String month = arr[2];
-
-
-            // value = 当前公司下所有VO集合
-            List<FollowCompanyFeeVO> voList = entry.getValue();
-
-            // 返回值
-            FollowCompanyFeeVO followCompanyFeeVO = new FollowCompanyFeeVO();
-            followCompanyFeeVO.setPartnerCompanyId(partnerCompanyId);
-
-            List<String> followIds = voList.stream().map(FollowCompanyFeeVO::getFollowId).toList();
-            List<String> invoiceIds = voList.stream().map(FollowCompanyFeeVO::getInvoiceId).toList();
-            List<String> settlementIds = voList.stream().map(FollowCompanyFeeVO::getSettlementId).toList();
-
-            // 根据所有followCompanyFeeVos的followId统计出已开票
-            LambdaQueryWrapper<InsFeeFollowOrder> insFeeFollowOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
-            insFeeFollowOrderLambdaQueryWrapper.in(InsFeeFollowOrder::getId, followIds);
-            List<InsFeeFollowOrder> insFeeFollowOrders = insFeeFollowOrderMapper.selectList(insFeeFollowOrderLambdaQueryWrapper);
-            // 总金额
-            InsFeeFollowOrder feeFollowOrder = CollUtil.getFirst(insFeeFollowOrders);
-            // 取对账金额
-            BigDecimal receivablePremium = feeFollowOrder.getReconciliationAmount();
-            followCompanyFeeVO.setTotalReceivable(receivablePremium);
-
-            BigDecimal totalInvoiced = insFeeFollowOrders.stream().map(InsFeeFollowOrder::getInvoiced).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
-            // 已开票总金额
-            followCompanyFeeVO.setTotalInvoiced(totalInvoiced);
-
-            // 未结算金额
-            followCompanyFeeVO.setTotalUnInvoiced(receivablePremium.subtract(totalInvoiced));
-
-            // 统计结算金额
-            LambdaQueryWrapper<InsPlyIncomeInvoiceSettlement> insPlyIncomeInvoiceSettlementLambdaQueryWrapper = new LambdaQueryWrapper<>();
-            insPlyIncomeInvoiceSettlementLambdaQueryWrapper.in(InsPlyIncomeInvoiceSettlement::getId, settlementIds);
-            List<InsPlyIncomeInvoiceSettlement> insPlyIncomeInvoiceSettlements = insPlyIncomeInvoiceSettlementMapper.selectList(insPlyIncomeInvoiceSettlementLambdaQueryWrapper);
-            BigDecimal totalSettlementAmount = insPlyIncomeInvoiceSettlements.stream().map(InsPlyIncomeInvoiceSettlement::getActualReceivedAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
-            // 已结算总金额
-            followCompanyFeeVO.setTotalSettlementAmount(totalSettlementAmount);
-
-            // 未结算金额
-            followCompanyFeeVO.setTotalUnSettlementAmount(totalInvoiced.subtract(totalSettlementAmount));
-            followCompanyFeeVO.setCompanyName(null != data.get(partnerCompanyId) ? data.get(partnerCompanyId).getName() : "");
-
-            resultList.add(followCompanyFeeVO);
+        if (CollUtil.isNotEmpty(followCompanyFeeVos)){
+            // 根据分支公司分组
+            Map<String, List<FollowCompanyFeeVO>> followMap = followCompanyFeeVos.stream().collect(Collectors.groupingBy(follow -> follow.getPartnerCompanyId() + "_" + follow.getYear() + "_" + follow.getMonth()));
+            for (Map.Entry<String, List<FollowCompanyFeeVO>> entry : followMap.entrySet()) {
+                // key = 合作公司ID
+                String key = entry.getKey();
+
+                // 分组参数
+                String[] arr = key.split("_");
+                String partnerCompanyId = arr[0];
+                String year = arr[1];
+                String month = arr[2];
+
+
+                // value = 当前公司下所有VO集合
+                List<FollowCompanyFeeVO> voList = entry.getValue();
+
+                // 返回值
+                FollowCompanyFeeVO followCompanyFeeVO = new FollowCompanyFeeVO();
+                followCompanyFeeVO.setPartnerCompanyId(partnerCompanyId);
+
+                List<String> followIds = voList.stream().map(FollowCompanyFeeVO::getFollowId).toList();
+                List<String> invoiceIds = voList.stream().map(FollowCompanyFeeVO::getInvoiceId).toList();
+                List<String> settlementIds = voList.stream().map(FollowCompanyFeeVO::getSettlementId).toList();
+
+                // 根据所有followCompanyFeeVos的followId统计出已开票
+                LambdaQueryWrapper<InsFeeFollowOrder> insFeeFollowOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
+                insFeeFollowOrderLambdaQueryWrapper.in(InsFeeFollowOrder::getId, followIds);
+                List<InsFeeFollowOrder> insFeeFollowOrders = insFeeFollowOrderMapper.selectList(insFeeFollowOrderLambdaQueryWrapper);
+                // 总金额
+                InsFeeFollowOrder feeFollowOrder = CollUtil.getFirst(insFeeFollowOrders);
+                // 取应收金额
+                BigDecimal receivablePremium = feeFollowOrder.getReceivablePremium();
+                followCompanyFeeVO.setTotalReceivable(receivablePremium);
+
+                BigDecimal totalInvoiced = insFeeFollowOrders.stream().map(InsFeeFollowOrder::getInvoiced).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
+                // 已开票总金额
+                followCompanyFeeVO.setTotalInvoiced(totalInvoiced);
+
+                // 未结算金额
+                followCompanyFeeVO.setTotalUnInvoiced(receivablePremium.subtract(totalInvoiced));
+
+                // 统计结算金额
+                LambdaQueryWrapper<InsPlyIncomeInvoiceSettlement> insPlyIncomeInvoiceSettlementLambdaQueryWrapper = new LambdaQueryWrapper<>();
+                insPlyIncomeInvoiceSettlementLambdaQueryWrapper.in(InsPlyIncomeInvoiceSettlement::getId, settlementIds);
+                List<InsPlyIncomeInvoiceSettlement> insPlyIncomeInvoiceSettlements = insPlyIncomeInvoiceSettlementMapper.selectList(insPlyIncomeInvoiceSettlementLambdaQueryWrapper);
+                BigDecimal totalSettlementAmount = insPlyIncomeInvoiceSettlements.stream().map(InsPlyIncomeInvoiceSettlement::getActualReceivedAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
+                // 已结算总金额
+                followCompanyFeeVO.setTotalSettlementAmount(totalSettlementAmount);
+
+                // 未结算金额
+                followCompanyFeeVO.setTotalUnSettlementAmount(totalInvoiced.subtract(totalSettlementAmount));
+                followCompanyFeeVO.setCompanyName(null != data.get(partnerCompanyId) ? data.get(partnerCompanyId).getName() : "");
+                followCompanyFeeVO.setYear(year);
+                followCompanyFeeVO.setMonth(month);
+
+                resultList.add(followCompanyFeeVO);
+            }
+        }
+
+        // 根据incomes的partnerCompanyId + signYear + signMonth,过滤resultList的partnerCompanyId + year + month,根据过滤后的数据进行partnerCompanyId + signYear + signMonth的分组,然后将过滤后剩余的数据,将入到resultList中,
+        // 并且设置partnerCompanyId、year、month、totalReceivable为incomes的partnerCompanyId、signYear、signMonth、jq_other_costs_premiums + sy_other_costs_premiums
+        QueryFollowIncomeVo queryFollowIncomeVo = new QueryFollowIncomeVo(null, null, baseController.getSystemCode(), null, settlementReportQueryVo.getCompanyId());
+        List<InsPlyIncomeDto> incomes = baseMapper.queryFollowIncome(queryFollowIncomeVo);
+        if (CollUtil.isNotEmpty(incomes)) {
+            // 1. 将resultList现有数据构建 key: partnerCompanyId_year_month 映射,方便快速匹配
+            Map<String, FollowCompanyFeeVO> existVoMap = resultList.stream()
+                    .collect(Collectors.toMap(
+                            vo -> vo.getPartnerCompanyId() + "_" + vo.getYear() + "_" + vo.getMonth(),
+                            Function.identity(),
+                            (oldVal, newVal) -> oldVal // 重复key保留原有
+                    ));
+
+            // 2. 将incomes按 partnerCompanyId_signYear_signMonth 分组
+            Map<String, List<InsPlyIncomeDto>> incomeGroupMap = incomes.stream()
+                    .collect(Collectors.groupingBy(income -> income.getPartnerCompanyId() + "_" + income.getSignYear() + "_" + income.getSignMonth()));
+
+            // 3. 遍历分组后的收入数据
+            for (Map.Entry<String, List<InsPlyIncomeDto>> entry : incomeGroupMap.entrySet()) {
+                String groupKey = entry.getKey();
+                List<InsPlyIncomeDto> dtoList = entry.getValue();
+                InsPlyIncomeDto firstDto = CollUtil.getFirst(dtoList);
+                String partnerCompanyId = firstDto.getPartnerCompanyId();
+                String signYear = firstDto.getSignYear();
+                String signMonth = firstDto.getSignMonth();
+
+                // 汇总其他费用应收:jq_other_costs_premiums + sy_other_costs_premiums
+                BigDecimal totalOtherReceivable = dtoList.stream()
+                        .map(dto -> new BigDecimal(dto.getJqOtherCostsPremiums()).add(new BigDecimal(dto.getSyOtherCostsPremiums())))
+                        .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
+
+                // 4. 判断当前分组是否已经存在于resultList(原有跟单数据)
+                FollowCompanyFeeVO existVo = existVoMap.get(groupKey);
+                if (existVo == null) {
+                    // 不存在原有数据,新建VO加入结果集
+                    FollowCompanyFeeVO newVo = new FollowCompanyFeeVO();
+                    newVo.setPartnerCompanyId(partnerCompanyId);
+                    newVo.setYear(signYear);
+                    newVo.setMonth(signMonth);
+                    // 设置总应收为其他费用合计
+                    newVo.setTotalReceivable(totalOtherReceivable);
+                    // 其余金额默认0(无开票、结算数据)
+                    newVo.setTotalInvoiced(BigDecimal.ZERO);
+                    newVo.setTotalUnInvoiced(BigDecimal.ZERO);
+                    newVo.setTotalSettlementAmount(BigDecimal.ZERO);
+                    newVo.setTotalUnSettlementAmount(BigDecimal.ZERO);
+                    // 匹配公司名称
+                    newVo.setCompanyName(null != data.get(partnerCompanyId) ? data.get(partnerCompanyId).getName() : "");
+                    resultList.add(newVo);
+                }
+            }
         }
 
-//        for (FollowCompanyFeeVO followCompanyFeeVo : followCompanyFeeVos) {
-//            followCompanyFeeVo.setCompanyName(null != data.get(followCompanyFeeVo.getPartnerCompanyId()) ? data.get(followCompanyFeeVo.getPartnerCompanyId()).getName() : "");
-//            followCompanyFeeVo.setTotalUnSettlementAmount(followCompanyFeeVo.getTotalInvoiced().subtract(followCompanyFeeVo.getTotalSettlementAmount()));
-//            followCompanyFeeVo.setTotalUnInvoiced(followCompanyFeeVo.getTotalReceivable().subtract(followCompanyFeeVo.getTotalInvoiced()));
-//        }
         return resultList;
     }
 
@@ -841,7 +895,8 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
                 platformCompanyFeeVo.setTotalSettlementAmount(BigDecimal.ZERO);
                 platformCompanyFeeVo.setTotalPaymentDifference(BigDecimal.ZERO);
             }
-            platformCompanyFeeVo.setTotalUnSettlementAmount(BigDecimalUtil.subtract(BigDecimalUtil.subtract(platformCompanyFeeVo.getTotalReceivable(),platformCompanyFeeVo.getTotalSettlementAmount()), platformCompanyFeeVo.getTotalPaymentDifference()));
+            //platformCompanyFeeVo.setTotalUnSettlementAmount(BigDecimalUtil.subtract(BigDecimalUtil.subtract(platformCompanyFeeVo.getTotalReceivable(),platformCompanyFeeVo.getTotalSettlementAmount()), platformCompanyFeeVo.getTotalPaymentDifference()));
+            platformCompanyFeeVo.setTotalUnSettlementAmount(BigDecimalUtil.subtract(platformCompanyFeeVo.getTotalReceivable(),platformCompanyFeeVo.getTotalSettlementAmount()));
         }
         return platformCompanyFeeVos;
     }
@@ -856,17 +911,18 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
      * 3. 批量查询订单与发票的关联关系,构建订单ID到发票ID的映射
      * 4. 查询业务员类型属性映射表
      * 5. 遍历每条订单记录,填充以下字段:
-     *    - settlementStatusName: 结算状态名称(0-未结算,1-已结算)
-     *    - typeAttr: 业务员类型属性代码
-     *    - typeAttrName: 业务员类型属性名称
-     *    - invoiceStatusName: 开票状态名称(有发票ID则为"已开票",否则为"未开票")
-     *    - invoiceId: 关联的发票ID
+     * - settlementStatusName: 结算状态名称(0-未结算,1-已结算)
+     * - typeAttr: 业务员类型属性代码
+     * - typeAttrName: 业务员类型属性名称
+     * - invoiceStatusName: 开票状态名称(有发票ID则为"已开票",否则为"未开票")
+     * - invoiceId: 关联的发票ID
      * </p>
      *
-     * @param records 应收订单列表,需要填充额外信息的订单数据
+     * @param records     应收订单列表,需要填充额外信息的订单数据
+     * @param invoiceType 开票类型 1:手续费 2:跟单费 3:驾意手续费 4:驾意跟单费
      * @return List<InsPlyIncome> 返回填充了必要字段后的完整订单列表
      */
-    List<InsPlyIncome> fillOtherInfo(List<InsPlyIncome> records){
+    List<InsPlyIncome> fillOtherInfo(List<InsPlyIncome> records, String invoiceType){
         if(CollUtil.isEmpty(records)){
             return records;
         }
@@ -876,9 +932,12 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         List<InsPlyIncomeInvoiceLink> links = baseMapper.queryIncomeBindInvoice(invoicingVo);
         Map<String, String> income2InvoceIdMap = links.stream()
                 .filter(action -> StrUtil.isNotEmpty(action.getIncomeId()))
-                .collect(Collectors.toMap(InsPlyIncomeInvoiceLink::getIncomeId, InsPlyIncomeInvoiceLink::getInvoiceId, (oleItem, newItem) -> oleItem));
-
-
+                .filter(action -> {
+                    if(StrUtil.isEmpty(invoiceType)){
+                        return true;
+                    }
+                    return invoiceType.equals(action.getInvoiceType());
+                }).collect(Collectors.toMap(InsPlyIncomeInvoiceLink::getIncomeId, InsPlyIncomeInvoiceLink::getInvoiceId, (oleItem, newItem) -> oleItem));
         Map<String, String> typeAttrMaps = sysUserJzgInfoSalesmanService.queryYwyTypeAttrMap();
         records.forEach(insPlyIncome -> {
             if("0".equals(insPlyIncome.getSettlementStatus())){
@@ -1270,6 +1329,8 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
             insPlyIncomeInvoiceLinkMapper.insert(invoicingLinkList);
             result.setInvoiceId(invoice.getId());
             result.setSumPrice(null != invoicingVo.getReceivableSupervisePremium() ? invoicingVo.getReceivableSupervisePremium().toString() : null);
+
+
             return result;
         } catch (Exception e) {
             log.info("开票异常.invoicingVo=[{}]",JSONUtil.toJsonStr(invoicingVo), e);
@@ -3648,7 +3709,8 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         String systemCode = baseController.getUserSystemCode();
 
         // 查询该年份下的所有跟进收入数据,并按合作方公司ID进行分组
-        List<InsPlyIncomeDto> incomes = baseMapper.queryFollowIncome(startYear, endYear, systemCode);
+        QueryFollowIncomeVo queryFollowIncomeVo = new QueryFollowIncomeVo(startYear, endYear, systemCode, null, null);
+        List<InsPlyIncomeDto> incomes = baseMapper.queryFollowIncome(queryFollowIncomeVo);
 
         // ====================== 增加动态条件过滤 ======================
         List<InsPlyIncomeDto> filterIncomes = new ArrayList<>();
@@ -4023,7 +4085,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         log.info("获取平台协议列表. receivableQueryVo=[{}]", JSONUtil.toJsonStr(receivableQueryVo));
         Page<InsPlyIncome> page = baseMapper.getReceivablePage(receivableQueryVo.getPage(), receivableQueryVo);
         List<InsPlyIncome> records = page.getRecords();
-        records = this.fillOtherInfo(records);
+        records = this.fillOtherInfo(records,null);
         page.setRecords(records);
         return page;
     }
@@ -4436,7 +4498,7 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         receivableQueryVo.setSystemCode(baseController.getSystemCode());
 
         List<InsPlyIncome> receivableList = baseMapper.getReceivableList(receivableQueryVo);
-        receivableList = this.fillOtherInfo(receivableList);
+        receivableList = this.fillOtherInfo(receivableList, null);
 
         // 调用动态导出
         return exportBaseService.upLoadFile(

+ 8 - 2
tenant/organization/src/main/resources/mapper/InsFeeFollowOrderMapper.xml

@@ -66,8 +66,14 @@
         <where>
             ffo.is_delete = 0
             -- 保险公司companyId筛选
-            <if test="query.companyId != null and query.companyId != ''">
-                AND ffo.company_id = #{query.companyId}
+            <if test="query.companyIdList != null and query.companyIdList.size() > 0" >
+                AND ffo.partner_company_id in
+                <foreach collection="query.companyIdList" item="item" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+            <if test="query.companyId != null and query.companyId != ''" >
+                AND ffo.partner_company_id = #{query.companyId}
             </if>
             -- 跟单订单创建时间范围
             <if test="query.startTime != null and query.startTime != '' and query.endTime != null and query.endTime != ''">

+ 18 - 11
tenant/organization/src/main/resources/mapper/ReceivableMapper.xml

@@ -731,8 +731,8 @@
         GROUP_CONCAT(DISTINCT ipii.invoice_party SEPARATOR ',') AS invoice_party,
         GROUP_CONCAT(DISTINCT ipii.tax_point SEPARATOR ',') AS tax_point,
         GROUP_CONCAT(DISTINCT ipiis.settlement_payment_reason SEPARATOR ',') AS settlement_payment_reason,
-        MAX(ipiis.settlement_payment_difference) AS settlement_payment_difference,
-        MAX(ipiis.actual_received_amount) AS actual_received_amount,
+        MAX(COALESCE(ipiis.settlement_payment_difference, 0)) AS settlement_payment_difference,
+        MAX(COALESCE(ipiis.actual_received_amount, 0)) 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
@@ -1478,11 +1478,7 @@
         LEFT JOIN ins_ply_income_invoice_settlement ipiis ON ipii.id = ipiis.invoice_id AND ipiis.is_delete = 0
         LEFT JOIN esm_ins_company eic on eic.id = ipii.company_id AND eic.is_delete = 0
         <where>
-            ipii.is_delete = 0
-            AND ipii.system_code = #{invoiceRecordQueryVo.systemCode}
-            <if test="invoiceRecordQueryVo.invoiceType != null and invoiceRecordQueryVo.invoiceType != ''">
-                AND ipii.invoice_type = #{invoiceRecordQueryVo.invoiceType}
-            </if>
+            ipii.is_delete = 0 AND ipii.system_code = #{invoiceRecordQueryVo.systemCode}
             <if test="invoiceRecordQueryVo.accountsReceivable != null and invoiceRecordQueryVo.accountsReceivable != ''">
                 AND ipii.invoice_risk_type = #{invoiceRecordQueryVo.accountsReceivable}
             </if>
@@ -2033,6 +2029,7 @@
         a.*,
         date(a.signing_time ) as sign_date,
         year(a.signing_time) as sign_year,
+        month(a.signing_time) as sign_month,
         b.partner_company_id,
         (SELECT eic.name FROM esm_ins_company eic WHERE b.partner_company_id = eic.id AND eic.is_delete = 0) AS partnerCompanyName,
         (SELECT eic.name FROM esm_ins_company eic WHERE a.company_id = eic.id AND eic.is_delete = 0) AS companyName
@@ -2041,11 +2038,21 @@
         <where>
             a.is_delete=0
             AND a.agreement_type = 2
-            <if test="startYear != null and endYear != null">
-                AND YEAR(a.signing_time) BETWEEN #{startYear} AND #{endYear}
+            AND a.signing_time is not null
+            <if test="query.startYear != null and query.endYear != null">
+                AND YEAR(a.signing_time) BETWEEN #{query.startYear} AND #{query.endYear}
             </if>
-            <if test="systemCode != null">
-                AND a.system_code = #{systemCode}
+            <if test="query.systemCode != null">
+                AND a.system_code = #{query.systemCode}
+            </if>
+            <if test="query.companyId != null and query.companyId != ''">
+                AND a.company_id = #{query.companyId}
+            </if>
+            <if test="query.companyIdList != null and query.companyIdList.size() > 0" >
+                AND a.company_id in
+                <foreach collection="query.companyIdList" item="item" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
             </if>
         </where>
     </select>