lipf пре 4 месеци
родитељ
комит
f220b16b31

+ 3 - 0
commons/src/main/java/com/jzg/commons/entity/finance/dto/CompanySuperviseSettlementReportDto.java

@@ -44,4 +44,7 @@ public class CompanySuperviseSettlementReportDto {
 
     @Schema(description = "子保险公司数据")
     private List<CompanySuperviseSettlementReportDto> children;
+
+    @Schema(description = "上级公司ID")
+    private String parentId; // 必须加!构建树形结构需要
 }

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

@@ -130,6 +130,8 @@ public interface ReceivableMapper extends BaseMapper<InsPlyIncome> {
      */
     List<CompanySuperviseSettlementReportDto> selectRootCompanies(@Param("settlementReportQueryVo") SettlementReportQueryVo settlementReportQueryVo);
 
+    List<CompanySuperviseSettlementReportDto> selectAllCompanies(SettlementReportQueryVo settlementReportQueryVo);
+
     /**
      * 根据父公司ID获取子公司
      */

+ 75 - 60
tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java

@@ -1554,87 +1554,102 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
     @Override
     public List<CompanySuperviseSettlementReportDto> companySuperviseSettlementReport(SettlementReportQueryVo settlementReportQueryVo) {
         log.info("保险公司结算报表:查询结算报表:settlementReportQueryVo=[{}]", JSONUtil.toJsonStr(settlementReportQueryVo));
-//        // 构建查手续费类型的数组
-//        List<String> invoiceTypes = new ArrayList<>();
-//        invoiceTypes.add("1");
-//        invoiceTypes.add("3");
-//        settlementReportQueryVo.setInvoiceTypes(invoiceTypes);
-        // 手续费应开票金额
+
+        // 1. 预加载手续费应开票金额(全局唯一一次查询)
         List<InvoiceAmountDto> commissionInvoicingAmount = baseMapper.getSuperviseAmount();
         Map<String, BigDecimal> invoicingAmountMap = commissionInvoicingAmount.stream()
                 .collect(Collectors.toMap(
                         InvoiceAmountDto::getCompanyId,
-                        dto -> dto.getSuperviseAmount()  != null ? dto.getSuperviseAmount() : BigDecimal.ZERO,
+                        dto -> dto.getSuperviseAmount() != null ? dto.getSuperviseAmount() : BigDecimal.ZERO,
                         (existing, replacement) -> existing
                 ));
 
-        List<CompanySuperviseSettlementReportDto> companySuperviseSettlementReportDtos = baseMapper.selectRootCompanies(settlementReportQueryVo);
-        for (CompanySuperviseSettlementReportDto companySuperviseSettlementReportDto : companySuperviseSettlementReportDtos) {
-            // 递归设置子公司数据
-            setChildren(companySuperviseSettlementReportDto, settlementReportQueryVo);
-            updateUnInvoicedAmount(companySuperviseSettlementReportDto, invoicingAmountMap);
+        // 2. 固定开票类型,只初始化一次
+        List<String> invoiceTypes = java.util.Arrays.asList("1", "3");
+        settlementReportQueryVo.setInvoiceTypes(invoiceTypes);
+
+        // 3. 一次性查询所有公司数据
+        List<CompanySuperviseSettlementReportDto> allCompanies = baseMapper.selectAllCompanies(settlementReportQueryVo);
+        if (allCompanies == null || allCompanies.isEmpty()) {
+            return java.util.Collections.emptyList();
         }
 
-        return companySuperviseSettlementReportDtos;
-    }
+        // 4. 内存构建树形结构
+        Map<String, CompanySuperviseSettlementReportDto> companyMap = allCompanies.stream()
+                .collect(java.util.stream.Collectors.toMap(
+                        CompanySuperviseSettlementReportDto::getCompanyId,
+                        dto -> dto,
+                        (o1, o2) -> o1
+                ));
 
-    private void setChildren(CompanySuperviseSettlementReportDto companySuperviseSettlementReportDto, SettlementReportQueryVo settlementReportQueryVo) {
-        // 构建查手续费类型的数组
-        List<String> invoiceTypes = new ArrayList<>();
-        invoiceTypes.add("1");
-        invoiceTypes.add("3");
-        // 获取子公司数据
-        List<CompanySuperviseSettlementReportDto> children = baseMapper.selectChildrenByParentId(companySuperviseSettlementReportDto.getCompanyId(), settlementReportQueryVo);
-        // 如果子公司存在,递归设置每个子公司的children
-        if (children != null && !children.isEmpty()) {
-            companySuperviseSettlementReportDto.setChildren(children);
-            // 递归调用,设置每个子公司的children
-            for (CompanySuperviseSettlementReportDto child : children) {
-                setChildren(child, settlementReportQueryVo);
-
-                // 将子公司的数据加到父公司
-                companySuperviseSettlementReportDto.setTotalReceivable(
-                        addAmounts(companySuperviseSettlementReportDto.getTotalReceivable(), child.getTotalReceivable())
-                );
-                companySuperviseSettlementReportDto.setSuperviseFee(
-                        addAmounts(companySuperviseSettlementReportDto.getSuperviseFee(), child.getSuperviseFee())
-                );
-                companySuperviseSettlementReportDto.setInvoicedAmount(
-                        addAmounts(companySuperviseSettlementReportDto.getInvoicedAmount(), child.getInvoicedAmount())
-                );
-                companySuperviseSettlementReportDto.setSettledAmount(
-                        addAmounts(companySuperviseSettlementReportDto.getSettledAmount(), child.getSettledAmount())
-                );
-                companySuperviseSettlementReportDto.setUnInvoicedAmount(
-                        addAmounts(companySuperviseSettlementReportDto.getUnInvoicedAmount(), child.getUnInvoicedAmount())
-                );
-                companySuperviseSettlementReportDto.setUnSettledAmount(
-                        addAmounts(companySuperviseSettlementReportDto.getUnSettledAmount(), child.getUnSettledAmount())
-                );
+        List<CompanySuperviseSettlementReportDto> rootNodes = new ArrayList<>();
+        for (CompanySuperviseSettlementReportDto company : allCompanies) {
+            // 根节点 parent_id = 0
+            if ("0".equals(company.getParentId())) {
+                rootNodes.add(company);
+            } else {
+                CompanySuperviseSettlementReportDto parent = companyMap.get(company.getParentId());
+                if (parent != null) {
+                    if (parent.getChildren() == null) {
+                        parent.setChildren(new ArrayList<>());
+                    }
+                    parent.getChildren().add(company);
+                }
             }
         }
-    }
-
-    private void updateUnInvoicedAmount(CompanySuperviseSettlementReportDto dto, Map<String, BigDecimal> invoicingAmountMap) {
-        // 1. 获取当前公司的应开票金额(默认0)
-        BigDecimal invoicingAmount = invoicingAmountMap.getOrDefault(dto.getCompanyId(), BigDecimal.ZERO);
 
-        // 2. 获取当前公司的已开票金额(默认0)
-        BigDecimal invoicedAmount = dto.getInvoicedAmount() != null ? new BigDecimal(dto.getInvoicedAmount()) : BigDecimal.ZERO;
+        // 5. 一次递归完成:汇总 + 未开票计算
+        for (CompanySuperviseSettlementReportDto root : rootNodes) {
+            calculateTreeData(root, invoicingAmountMap);
+        }
 
-        // 3. 计算未开票金额(应开票 - 已开票)
-        BigDecimal unInvoicedAmount = invoicingAmount.subtract(invoicedAmount);
+        return rootNodes;
+    }
 
-        // 4. 设置未开票金额
-        dto.setUnInvoicedAmount(String.valueOf(unInvoicedAmount));
+    /**
+     * 递归:子公司金额汇总 + 未开票金额计算
+     */
+    private void calculateTreeData(CompanySuperviseSettlementReportDto dto, Map<String, BigDecimal> invoicingAmountMap) {
+        BigDecimal totalReceivable = toBigDecimal(dto.getTotalReceivable());
+        BigDecimal superviseFee = toBigDecimal(dto.getSuperviseFee());
+        BigDecimal invoicedAmount = toBigDecimal(dto.getInvoicedAmount());
+        BigDecimal settledAmount = toBigDecimal(dto.getSettledAmount());
+        BigDecimal unSettledAmount = toBigDecimal(dto.getUnSettledAmount());
 
-        // 5. 递归处理子公司
         List<CompanySuperviseSettlementReportDto> children = dto.getChildren();
         if (children != null && !children.isEmpty()) {
             for (CompanySuperviseSettlementReportDto child : children) {
-                updateUnInvoicedAmount(child, invoicingAmountMap);
+                calculateTreeData(child, invoicingAmountMap);
+
+                totalReceivable = totalReceivable.add(toBigDecimal(child.getTotalReceivable()));
+                superviseFee = superviseFee.add(toBigDecimal(child.getSuperviseFee()));
+                invoicedAmount = invoicedAmount.add(toBigDecimal(child.getInvoicedAmount()));
+                settledAmount = settledAmount.add(toBigDecimal(child.getSettledAmount()));
+                unSettledAmount = unSettledAmount.add(toBigDecimal(child.getUnSettledAmount()));
             }
         }
+
+        // 回填汇总金额
+        dto.setTotalReceivable(totalReceivable.toString());
+        dto.setSuperviseFee(superviseFee.toString());
+        dto.setInvoicedAmount(invoicedAmount.toString());
+        dto.setSettledAmount(settledAmount.toString());
+        dto.setUnSettledAmount(unSettledAmount.toString());
+
+        // 计算未开票
+        BigDecimal shouldInvoice = invoicingAmountMap.getOrDefault(dto.getCompanyId(), BigDecimal.ZERO);
+        BigDecimal unInvoice = shouldInvoice.subtract(invoicedAmount);
+        dto.setUnInvoicedAmount(unInvoice.toString());
+    }
+
+    /**
+     * 字符串转 BigDecimal,空值返回 0
+     */
+    private BigDecimal toBigDecimal(String amount) {
+        if (amount == null || amount.isBlank()) {
+            return BigDecimal.ZERO;
+        }
+        return new BigDecimal(amount);
     }
 
     // 用于加总字符串金额

+ 111 - 49
tenant/organization/src/main/resources/mapper/ReceivableMapper.xml

@@ -1083,63 +1083,125 @@
         <result column="un_settled_amount" property="unSettledAmount"/>
     </resultMap>
 
+    <!-- 优化:一次性查询所有公司数据,替代递归查库 -->
+    <select id="selectAllCompanies" resultMap="BaseResultMap">
+        SELECT
+        eic.id as company_id,
+        eic.parent_id,  <!-- 必须加这个,树形结构需要 -->
+        eic.name as company_name,
+        COALESCE(SUM(ipi.jq_receivable_premium + ipi.sy_receivable_premium + ipi.jy_receivable_premium), 0) as total_receivable,
+        COALESCE(SUM(ipi.jq_supervise_costs_premiums + ipi.sy_supervise_costs_premiums + ipi.jy_supervise_costs_premiums), 0) as supervise_fee,
+        COALESCE(SUM(ipi.jq_other_costs_premiums + ipi.sy_other_costs_premiums + ipi.jy_other_costs_premiums), 0) as follow_fee,
+        COALESCE(SUM(invoice_summary.total_invoice), 0) as invoiced_amount,
+        COALESCE(SUM(invoice_summary.settled_invoice), 0) as settled_amount,
+        COALESCE(SUM(invoice_summary.unsettled_invoice), 0) as un_settled_amount
+        FROM
+        esm_ins_company eic
+        LEFT JOIN ins_ply_income ipi ON eic.id = ipi.company_id and ipi.agreement_type = #{agreementType}
+        LEFT JOIN (
+        SELECT
+        ipiil.income_id,
+        ipii.invoice_time,
+        SUM(ipii.receivable_supervise_premium) as total_invoice,
+        SUM(CASE WHEN ipii.status = 1 THEN ipii.receivable_supervise_premium ELSE 0 END) as settled_invoice,
+        SUM(CASE WHEN ipii.status = 0 THEN ipii.receivable_supervise_premium ELSE 0 END) as unsettled_invoice
+        FROM ins_ply_income_invoice_link ipiil
+        LEFT JOIN ins_ply_income_invoice ipii ON ipii.id = ipiil.invoice_id
+        <where>
+            <if test="invoiceTypes != null and invoiceTypes.size() > 0">
+                AND ipii.invoice_type IN
+                <foreach item="item" collection="invoiceTypes" separator="," open="(" close=")">
+                    #{item}
+                </foreach>
+            </if>
+            <if test="status != null and status != ''">
+                and ipii.status = #{status}
+            </if>
+        </where>
+        GROUP BY ipiil.income_id, ipii.invoice_time
+        ) invoice_summary ON invoice_summary.income_id = ipi.id
+        LEFT JOIN (
+        SELECT
+        ifo.order_no,
+        SUM(DISTINCT (ifo.jq_commission_premium + ifo.sy_commission_premium + ifo.jy_commission_premium)) as total_commission
+        FROM ins_fee_orders ifo
+        GROUP BY ifo.order_no
+        ) fee_summary ON ipi.order_no = fee_summary.order_no
+        <where>
+            <if test="companyId != null and companyId != ''">
+                AND eic.id = #{companyId}
+            </if>
+            <if test="startTime != null and startTime != ''">
+                AND ipi.signing_time BETWEEN #{startTime} AND #{endTime}
+                AND (
+                invoice_summary.invoice_time BETWEEN #{startTime} AND #{endTime}
+                OR invoice_summary.invoice_time IS NULL
+                )
+            </if>
+        </where>
+        GROUP BY eic.id, eic.name, eic.parent_id;
+    </select>
+
     <!-- 获取根级保险公司(parent_id为0) -->
     <select id="selectRootCompanies" resultMap="BaseResultMap">
         SELECT
-            eic.id as company_id,
-            eic.name as company_name,
-            COALESCE(SUM(ipi.jq_receivable_premium + ipi.sy_receivable_premium + ipi.jy_receivable_premium), 0) as total_receivable,
-            COALESCE(SUM(ipi.jq_supervise_costs_premiums + ipi.sy_supervise_costs_premiums + ipi.jy_supervise_costs_premiums), 0) as supervise_fee,
-            COALESCE(SUM(ipi.jq_other_costs_premiums + ipi.sy_other_costs_premiums + ipi.jy_other_costs_premiums), 0) as follow_fee,
-            COALESCE(SUM(invoice_summary.total_invoice), 0) as invoiced_amount,
-            COALESCE(SUM(fee_summary.total_commission) - SUM(invoice_summary.total_invoice), 0) as un_invoiced_amount,
-            COALESCE(SUM(invoice_summary.settled_invoice), 0) as settled_amount,
-            COALESCE(SUM(invoice_summary.unsettled_invoice), 0) as un_settled_amount
+        eic.id as company_id,
+        eic.name as company_name,
+        COALESCE(SUM(ipi.jq_receivable_premium + ipi.sy_receivable_premium + ipi.jy_receivable_premium), 0) as total_receivable,
+        COALESCE(SUM(ipi.jq_supervise_costs_premiums + ipi.sy_supervise_costs_premiums + ipi.jy_supervise_costs_premiums), 0) as supervise_fee,
+        COALESCE(SUM(ipi.jq_other_costs_premiums + ipi.sy_other_costs_premiums + ipi.jy_other_costs_premiums), 0) as follow_fee,
+        COALESCE(SUM(invoice_summary.total_invoice), 0) as invoiced_amount,
+        COALESCE(SUM(fee_summary.total_commission) - SUM(invoice_summary.total_invoice), 0) as un_invoiced_amount,
+        COALESCE(SUM(invoice_summary.settled_invoice), 0) as settled_amount,
+        COALESCE(SUM(invoice_summary.unsettled_invoice), 0) as un_settled_amount
         FROM
-            esm_ins_company eic
-            LEFT JOIN ins_ply_income ipi ON eic.id = ipi.company_id and ipi.agreement_type = #{settlementReportQueryVo.agreementType}
-            LEFT JOIN (
-            SELECT
-            ipiil.income_id,
-            SUM(ipii.receivable_supervise_premium) as total_invoice,
-            SUM(CASE WHEN ipii.status = 1 THEN ipii.receivable_supervise_premium ELSE 0 END) as settled_invoice,
-            SUM(CASE WHEN ipii.status = 0 THEN ipii.receivable_supervise_premium ELSE 0 END) as unsettled_invoice
-            FROM ins_ply_income_invoice_link ipiil
-            LEFT JOIN ins_ply_income_invoice ipii
-            ON ipii.id = ipiil.invoice_id
-            <where>
-                <if test="settlementReportQueryVo.invoiceTypes != null and settlementReportQueryVo.invoiceTypes.size() > 0">
-                    AND ipii.invoice_type IN
-                    <foreach item="item" collection="settlementReportQueryVo.invoiceTypes" separator="," open="(" close=")">
-                        #{item}
-                    </foreach>
-                </if>
-                <if test="settlementReportQueryVo.status != null and settlementReportQueryVo.status != ''">
-                    and ipii.status = #{settlementReportQueryVo.status}
-                </if>
-            </where>
-            GROUP BY ipiil.income_id
-            ) invoice_summary ON invoice_summary.income_id = ipi.id
+        esm_ins_company eic
+        LEFT JOIN ins_ply_income ipi ON eic.id = ipi.company_id and ipi.agreement_type = #{settlementReportQueryVo.agreementType}
         LEFT JOIN (
-                     SELECT
-                     ifo.order_no,
-                     SUM(DISTINCT (ifo.jq_commission_premium + ifo.sy_commission_premium + ifo.jy_commission_premium)) as total_commission
-                     FROM ins_fee_orders ifo
-                     GROUP BY ifo.order_no
-                     ) fee_summary ON ipi.order_no = fee_summary.order_no
-        WHERE
-        eic.parent_id = 0
-            <if test="settlementReportQueryVo.companyId != null and settlementReportQueryVo.companyId != ''">
-                and eic.id = #{settlementReportQueryVo.companyId}
+        SELECT
+        ipiil.income_id,
+        ipii.invoice_time,
+        SUM(ipii.receivable_supervise_premium) as total_invoice,
+        SUM(CASE WHEN ipii.status = 1 THEN ipii.receivable_supervise_premium ELSE 0 END) as settled_invoice,
+        SUM(CASE WHEN ipii.status = 0 THEN ipii.receivable_supervise_premium ELSE 0 END) as unsettled_invoice
+        FROM ins_ply_income_invoice_link ipiil
+        LEFT JOIN ins_ply_income_invoice ipii
+        ON ipii.id = ipiil.invoice_id
+        <where>
+            <if test="settlementReportQueryVo.invoiceTypes != null and settlementReportQueryVo.invoiceTypes.size() > 0">
+                AND ipii.invoice_type IN
+                <foreach item="item" collection="settlementReportQueryVo.invoiceTypes" separator="," open="(" close=")">
+                    #{item}
+                </foreach>
             </if>
-            <if test="settlementReportQueryVo.startTime != null and settlementReportQueryVo.startTime != ''">
-                AND ipi.signing_time BETWEEN #{settlementReportQueryVo.startTime} AND #{settlementReportQueryVo.endTime}
-                AND (invoice_summary.invoiceTime BETWEEN #{settlementReportQueryVo.startTime} AND #{settlementReportQueryVo.endTime}
-                OR invoice_summary.invoiceTime IS NULL)
+            <if test="settlementReportQueryVo.status != null and settlementReportQueryVo.status != ''">
+                and ipii.status = #{settlementReportQueryVo.status}
             </if>
+        </where>
+        GROUP BY ipiil.income_id, ipii.invoice_time
+        ) invoice_summary ON invoice_summary.income_id = ipi.id
+        LEFT JOIN (
+        SELECT
+        ifo.order_no,
+        SUM(DISTINCT (ifo.jq_commission_premium + ifo.sy_commission_premium + ifo.jy_commission_premium)) as total_commission
+        FROM ins_fee_orders ifo
+        GROUP BY ifo.order_no
+        ) fee_summary ON ipi.order_no = fee_summary.order_no
+        WHERE
+        eic.parent_id = 0
+        <if test="settlementReportQueryVo.companyId != null and settlementReportQueryVo.companyId != ''">
+            and eic.id = #{settlementReportQueryVo.companyId}
+        </if>
+        <if test="settlementReportQueryVo.startTime != null and settlementReportQueryVo.startTime != ''">
+            AND ipi.signing_time BETWEEN #{settlementReportQueryVo.startTime} AND #{settlementReportQueryVo.endTime}
+            AND (
+            invoice_summary.invoice_time BETWEEN #{settlementReportQueryVo.startTime} AND #{settlementReportQueryVo.endTime}
+            OR invoice_summary.invoice_time IS NULL
+            )
+        </if>
         GROUP BY
-            eic.id,
-            eic.name;
+        eic.id,
+        eic.name;
     </select>
 
     <!-- 获取子公司 -->