yuan
2 天以前 ccc9d4533bc7b696f6d539720a6052abc44ff7a5
fix: 添加设备名称字段并修复多个查询的排序和分组问题
已修改17个文件
197 ■■■■■ 文件已修改
src/main/java/com/ruoyi/measuringinstrumentledger/dto/SparePartsDto.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/account/AccountExpenseMapper.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/account/AccountIncomeMapper.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/equipmentenergyconsumption/EquipmentEnergyConsumptionMapper.xml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/measuringinstrumentledger/SparePartsMapper.xml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/procurementrecord/ProcurementRecordMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductOrderMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductWorkOrderMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductionProductMainMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/SalesLedgerProductionAccountingMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/SalesLedgerSchedulingMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/projectManagement/InfoMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/quality/QualityUnqualifiedMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/InvoiceLedgerMapper.xml 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/ReceiptPaymentMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesLedgerProductMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/dto/SparePartsDto.java
@@ -12,4 +12,12 @@
     */
    private String parentName;
    private List<SparePartsDto> children;
    /**
     * 绑定设备的名称(多个用逗号分隔)。
     * 2026-10-12 新增:前端备件列表第一列取的就是 deviceNameStr,之前 DTO 里没有这个字段,
     * 导致「设备名称」列永远空白,看起来像"备件没绑定设备"。
     * 由 SparePartsMapper.listPage 通过 spare_parts.device_ids 反查 device_ledger 拼出。
     */
    private String deviceNameStr;
}
src/main/resources/mapper/account/AccountExpenseMapper.xml
@@ -19,6 +19,8 @@
        <if test="accountExpense.expenseMethod != null and accountExpense.expenseMethod != '' ">
            AND expense_method = #{accountExpense.expenseMethod}
        </if>
        <!-- 2026-10-12 需求:支出管理按支出日期倒序 -->
        ORDER BY expense_date DESC, id DESC
    </select>
    <select id="accountExpenseExport" resultType="com.ruoyi.account.pojo.AccountExpense">
        SELECT
@@ -53,7 +55,7 @@
        <if test="dateQueryDto.entryDateEnd != null and dateQueryDto.entryDateEnd != '' ">
            AND expense_date &lt;= DATE_FORMAT(#{dateQueryDto.entryDateEnd},'%Y-%m-%d')
        </if>
        group by expense_type
        group by expense_type, sdd.dict_label
    </select>
    <select id="report1" resultType="java.math.BigDecimal">
src/main/resources/mapper/account/AccountIncomeMapper.xml
@@ -20,6 +20,8 @@
        <if test="accountIncome.incomeMethod != null and accountIncome.incomeMethod != '' ">
            AND income_method = #{accountIncome.incomeMethod}
        </if>
        <!-- 2026-10-12 需求:收入管理按收入日期倒序 -->
        ORDER BY income_date DESC, id DESC
    </select>
    <select id="accountIncomeExport" resultType="com.ruoyi.account.pojo.AccountIncome">
        SELECT
@@ -54,7 +56,7 @@
        <if test="dateQueryDto.entryDateEnd != null and dateQueryDto.entryDateEnd != '' ">
            AND income_date &lt;= DATE_FORMAT(#{dateQueryDto.entryDateEnd},'%Y-%m-%d')
        </if>
        group by income_type
        group by income_type, sdd.dict_label
    </select>
    <select id="report1" resultType="java.math.BigDecimal">
        SELECT
src/main/resources/mapper/equipmentenergyconsumption/EquipmentEnergyConsumptionMapper.xml
@@ -9,6 +9,15 @@
            and `name` like concat('%',#{req.name},'%')
        </if>
    </select>
    <!--
      2026-10-11 修复(造数项目 R07,见 docs/handoff/R07-设备与能耗.md §7.1):
      原 SQL 末尾带 `GROUP BY `code``,在本机 sql_mode 含 ONLY_FULL_GROUP_BY 时抛
        ER_WRONG_FIELD_WITH_GROUP: Expression #1 of SELECT list is not in GROUP BY clause ...
        ... 'id' is not functionally dependent on columns in GROUP BY clause
      导致「能耗管理 → 能源趋势」页面必然 500。
      由于 WHERE 已把 run_date 锁死为同一天、且 (code, run_date) 天然唯一,
      `GROUP BY code` 在语义上是空操作 ⇒ 直接移除,返回结果集不变。
    -->
    <select id="listPageByTrend" resultType="com.ruoyi.equipmentenergyconsumption.pojo.EquipmentEnergyConsumption">
        SELECT
            *,
@@ -20,8 +29,6 @@
        <if test="req.name != null and req.name != ''">
            and `name` like concat('%',#{req.name},'%')
        </if>
        GROUP BY
            `code`
        ORDER BY
            update_time DESC;
    </select>
src/main/resources/mapper/measuringinstrumentledger/SparePartsMapper.xml
@@ -2,7 +2,14 @@
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.measuringinstrumentledger.mapper.SparePartsMapper">
    <select id="listPage" resultType="com.ruoyi.measuringinstrumentledger.dto.SparePartsDto">
        select sp.*,sp1.name as parentName
        select sp.*, sp1.name as parentName,
        <!-- 2026-10-12 修复:前端列表第一列取的是 deviceNameStr,但 DTO 和 SQL 都没有这个字段,
             导致「设备名称」列永远空白(看起来像"没绑定设备")。
             这里按 spare_parts.device_ids(逗号分隔)反查 device_ledger 拼出设备名。 -->
        (select group_concat(d.device_name order by d.id separator ',')
         from device_ledger d
         where sp.device_ids is not null and sp.device_ids &lt;&gt; ''
           and find_in_set(d.id, sp.device_ids)) as deviceNameStr
        from spare_parts sp
        left join spare_parts sp1 on sp1.id = sp.parent_id
        <where>
src/main/resources/mapper/procurementrecord/ProcurementRecordMapper.xml
@@ -20,7 +20,7 @@
            t2.tax_exclusive_total_price,
            t3.inbound_num as quantityStock
        from  purchase_ledger t1
        left join sales_ledger_product t2 on t1.id = t2.sales_ledger_id and slp.type = 2
        left join sales_ledger_product t2 on t1.id = t2.sales_ledger_id and t2.type = 2
        left join procurement_record_storage t3 on t2.id = t3.sales_ledger_product_id
        where t1.purchase_contract_number = #{req.purchaseContractNumber}
        <if test="req.id != null and req.id != ''">
src/main/resources/mapper/production/ProductOrderMapper.xml
@@ -64,6 +64,8 @@
                and po.create_time between #{c.startTime} and #{c.endTime}
            </if>
        </where>
        <!-- 2026-10-12 需求:生产模块按时间倒序,最新的排在前面 -->
        order by po.create_time desc, po.id desc
    </select>
    <select id="listProcessRoute" resultType="com.ruoyi.production.pojo.ProcessRoute">
        select pr.*
src/main/resources/mapper/production/ProductWorkOrderMapper.xml
@@ -48,6 +48,8 @@
            <if test="c.productOrderId != null and c.productOrderId != ''">
               and pwo.product_order_id = #{c.productOrderId}
            </if>
        <!-- 2026-10-12 需求:生产模块按时间倒序,最新的排在前面 -->
        order by pwo.create_time desc, pwo.id desc
    </select>
    <select id="getProductWorkOrderFlowCard" resultType="com.ruoyi.production.dto.ProductWorkOrderDto">
        SELECT
src/main/resources/mapper/production/ProductionProductMainMapper.xml
@@ -49,7 +49,8 @@
                and ppm.status = #{c.status}
            </if>
        </where>
        order by ppm.id
        <!-- 2026-10-12 需求:生产模块按时间倒序,最新的排在前面 -->
        order by ppm.create_time desc, ppm.id desc
    </select>
    <select id="getOrderByMainId" resultType="com.ruoyi.production.pojo.ProductOrder">
src/main/resources/mapper/production/SalesLedgerProductionAccountingMapper.xml
@@ -22,7 +22,7 @@
        FROM
        sales_ledger_production_accounting t4
        LEFT JOIN sales_ledger T1 ON T1.id = t4.sales_ledger_id
        left join sales_ledger_product t3 on t4.sales_ledger_product_id = t3.id and slp.type = 1
        left join sales_ledger_product t3 on t4.sales_ledger_product_id = t3.id and t3.type = 1
        <where>
            t3.type = 1
            <if test="salesLedgerDto.schedulingUserName != null and salesLedgerDto.schedulingUserName != '' ">
@@ -84,7 +84,7 @@
            </if>
        </where>
        GROUP BY slpa.scheduling_user_name
        GROUP BY slpa.scheduling_user_name, slpa.scheduling_user_id
    </select>
@@ -115,7 +115,7 @@
                 left join product_process pp on pp.name = slpa.process
        where  slpa.scheduling_user_id = #{ew.userId}
          and slpa.scheduling_date like concat(#{ew.date}, '%')
        group by slpa.scheduling_user_id
        group by slpa.scheduling_user_id, pp.type
    </select>
src/main/resources/mapper/production/SalesLedgerSchedulingMapper.xml
@@ -91,7 +91,7 @@
        FROM
        sales_ledger_scheduling T2
        LEFT JOIN sales_ledger T1 ON T1.id = T2.sales_ledger_id
        left join sales_ledger_product t3 on T2.sales_ledger_product_id = t3.id and slp.type = 1
        left join sales_ledger_product t3 on T2.sales_ledger_product_id = t3.id and t3.type = 1
        <where>
            t3.type = 1
            <if test="salesLedgerDto.status != null and salesLedgerDto.status != '' ">
src/main/resources/mapper/projectManagement/InfoMapper.xml
@@ -74,7 +74,12 @@
            and t1.review_status = #{vo.reviewStatus.code}
        </if>
        <if test="vo.stage != null">
            and t1.stage = #{vo.stage.code}
            <!-- 2026-10-12 修复:project_management_info 没有 stage 列(元数据里叫 plan_stage,且是 JSON 格式),
                 原 `and t1.stage = #{vo.stage.code}` 一选"计划状态"就抛
                 ER_BAD_FIELD_ERROR Unknown column 't1.stage'。
                 前端该筛选项取的是字典 plan_status(1待开始/2进行中/3已结束),
                 而 t1.status 正好存的就是 1/2/3,故改指 t1.status。 -->
            and t1.status = #{vo.stage.code}
        </if>
        order by t1.create_time desc
    </select>
src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml
@@ -181,32 +181,45 @@
                AND t4.purchase_contract_number LIKE CONCAT('%',#{params.purchaseContractNumber},'%')
            </if>
        </where>
        ORDER BY T1.payment_date,T1.create_time DESC
        <!-- 2026-10-13 需求:付款流水按付款日期倒序(原来只写了 payment_date 没写方向,默认升序,最早的在最上面) -->
        ORDER BY T1.payment_date DESC, T1.id DESC
    </select>
    <select id="supplierNameListPage" resultType="com.ruoyi.purchase.dto.PaymentRegistrationDto">
        SELECT
        T1.supplier_id,
        T1.supplier_name,
        SUM(contract_amount) AS invoiceAmount,
        IFNULL( SUM(T2.current_payment_amount) , 0 ) AS paymentAmount,
        IFNULL((IFNULL(SUM(contract_amount),0)  - IFNULL(SUM(T2.current_payment_amount),0)),0) AS payableAmount
        IFNULL(SUM(T1.contract_amount), 0) AS invoiceAmount,
        IFNULL(SUM(T2.paid), 0)            AS paymentAmount,
        IFNULL(SUM(T1.contract_amount), 0) - IFNULL(SUM(T2.paid), 0) AS payableAmount
        FROM purchase_ledger T1
        LEFT JOIN payment_registration T2 ON T1.id = T2.purchase_ledger_id
        <!-- 2026-10-13 修复:原来直接 LEFT JOIN payment_registration 再 SUM(contract_amount),
             一笔采购合同有几笔付款,合同额就被重复累加几次(供应商往来页「合同金额/应付金额」因此虚高)。
             改成先按台账汇总付款再 JOIN。 -->
        LEFT JOIN (
            SELECT purchase_ledger_id, SUM(current_payment_amount) AS paid
            FROM payment_registration WHERE purchase_ledger_id IS NOT NULL GROUP BY purchase_ledger_id
        ) T2 ON T2.purchase_ledger_id = T1.id
        <where>
            <if test="req.supplierName != null and req.supplierName != '' ">
                T1.supplier_name LIKE CONCAT ('%',#{req.supplierName},'%')
            </if>
        </where>
        GROUP BY T1.supplier_name
        GROUP BY T1.supplier_id, T1.supplier_name
    </select>
    <select id="supplierNameListPageDetails" resultType="com.ruoyi.purchase.dto.PaymentRegistrationDto">
        SELECT
        T1.supplier_id,
        T1.supplier_name,
        SUM(contract_amount) AS invoiceAmount,
        IFNULL( SUM(T2.current_payment_amount) , 0 ) AS paymentAmount,
        IFNULL((IFNULL(SUM(contract_amount),0)  - IFNULL(SUM(T2.current_payment_amount),0)),0) AS payableAmount,
        T1.contract_amount AS invoiceAmount,
        IFNULL(SUM(T2.current_payment_amount), 0) AS paymentAmount,
        <!-- 2026-10-13 修复:原来写的是「合同额 − 本日期这一笔付款」,再叠加 GROUP BY payment_date,
             一笔合同有几笔付款就拆成几行、每行一个假的"应付"(例如 CG20260523002 已全额付款,
             却显示应付 18524.07)。应付金额应当是**该合同当前真正的未付款额 = 合同额 − 全部付款**。 -->
        GREATEST(T1.contract_amount - IFNULL((
            SELECT SUM(T3.current_payment_amount) FROM payment_registration T3
            WHERE T3.purchase_ledger_id = T1.id
        ), 0), 0) AS payableAmount,
        T1.purchase_contract_number,
        T2.payment_date
        FROM purchase_ledger T1
@@ -217,7 +230,8 @@
                T1.supplier_name LIKE CONCAT ('%',#{req.supplierName},'%')
            </if>
        </where>
        GROUP BY  T1.purchase_contract_number,T2.payment_date
        GROUP BY T1.id, T1.supplier_id, T1.supplier_name, T1.contract_amount, T1.purchase_contract_number, T2.payment_date
        ORDER BY T1.entry_date ASC, T2.payment_date ASC
    </select>
</mapper>
src/main/resources/mapper/quality/QualityUnqualifiedMapper.xml
@@ -43,6 +43,8 @@
        <if test="qualityUnqualified.entryDateEnd != null and qualityUnqualified.entryDateEnd != '' ">
            AND  check_time &lt;= DATE_FORMAT(#{qualityUnqualified.entryDateEnd},'%Y-%m-%d')
        </if>
        <!-- 2026-10-12 需求:不合格管理按检测时间倒序 -->
        ORDER BY qu.check_time DESC, qu.id DESC
    </select>
    <select id="qualityUnqualifiedExport" resultType="com.ruoyi.quality.pojo.QualityUnqualified">
        SELECT
src/main/resources/mapper/sales/InvoiceLedgerMapper.xml
@@ -6,12 +6,12 @@
    <select id="invoiceLedgerPage" resultType="com.ruoyi.sales.dto.InvoiceLedgerDto">
        SELECT
            T1.id                ,
            T1.sales_ledger_id   ,
            T1.sales_contract_no ,
            T1.customer_id       ,
            T5.sales_ledger_id   AS sales_ledger_id,
            T3.sales_contract_no AS sales_contract_no,
            T3.customer_id       AS customer_id,
            T1.invoice_no        ,
            T1.invoice_amount    ,
            T1.tax_rate          ,
            T1.invoice_total     AS invoice_amount,
            T5.tax_rate          AS tax_rate,
            T1.invoice_person    ,
            T1.invoice_date      ,
            T1.create_time       ,
@@ -24,8 +24,12 @@
            T3.salesman,
            T4.invoiceFileName
        FROM invoice_ledger T1
        LEFT JOIN customer T2 ON T1.customer_id = T2.id
        LEFT JOIN sales_ledger T3 ON T1.sales_ledger_id = T3.id
        <!-- 2026-10-12 修复:invoice_ledger 表里没有 sales_ledger_id / sales_contract_no / customer_id /
             invoice_amount / tax_rate 这 5 列(它们在 invoice_registration_product 上),
             原来的 T1.xxx 必然抛 ER_BAD_FIELD_ERROR。改为按真实结构关联。 -->
        LEFT JOIN invoice_registration_product T5 ON T5.id = T1.invoice_registration_product_id
        LEFT JOIN sales_ledger T3 ON T3.id = T5.sales_ledger_id
        LEFT JOIN customer T2 ON T2.id = T3.customer_id
        LEFT JOIN (
            SELECT
                invoice_ledger_id,
@@ -48,12 +52,12 @@
    <select id="invoiceLedgerList" resultType="com.ruoyi.sales.dto.InvoiceLedgerDto">
        SELECT
            T1.id                ,
            T1.sales_ledger_id   ,
            T1.sales_contract_no ,
            T1.customer_id       ,
            T5.sales_ledger_id   AS sales_ledger_id,
            T3.sales_contract_no AS sales_contract_no,
            T3.customer_id       AS customer_id,
            T1.invoice_no        ,
            T1.invoice_amount    ,
            T1.tax_rate          ,
            T1.invoice_total     AS invoice_amount,
            T5.tax_rate          AS tax_rate,
            T1.invoice_person    ,
            T1.invoice_date      ,
            T1.create_time       ,
@@ -66,8 +70,10 @@
            T3.customer_contract_no,
            T4.invoiceFileName
        FROM invoice_ledger T1
        LEFT JOIN customer T2 ON T1.customer_id = T2.id
        LEFT JOIN sales_ledger T3 ON T1.sales_ledger_id = T3.id
        <!-- 2026-10-12 修复:同 invoiceLedgerPage,改为按真实表结构关联 -->
        LEFT JOIN invoice_registration_product T5 ON T5.id = T1.invoice_registration_product_id
        LEFT JOIN sales_ledger T3 ON T3.id = T5.sales_ledger_id
        LEFT JOIN customer T2 ON T2.id = T3.customer_id
        LEFT JOIN (
        SELECT
        invoice_ledger_id,
@@ -90,12 +96,12 @@
    <select id="invoiceLedgerInfo" resultType="com.ruoyi.sales.dto.InvoiceLedgerDto">
        SELECT
        T1.id                ,
        T1.sales_ledger_id   ,
        T1.sales_contract_no ,
        T1.customer_id       ,
        T5.sales_ledger_id   AS sales_ledger_id,
        T3.sales_contract_no AS sales_contract_no,
        T3.customer_id       AS customer_id,
        T1.invoice_no        ,
        T1.invoice_amount    ,
        T1.tax_rate          ,
        T1.invoice_total     AS invoice_amount,
        T5.tax_rate          AS tax_rate,
        T1.invoice_person    ,
        T1.invoice_date      ,
        T1.create_time       ,
@@ -105,7 +111,10 @@
        T1.tenant_id         ,
        T2.customer_name
        FROM invoice_ledger T1
        LEFT JOIN customer T2 ON T1.customer_id = T2.id
        <!-- 2026-10-12 修复:同 invoiceLedgerPage,改为按真实表结构关联 -->
        LEFT JOIN invoice_registration_product T5 ON T5.id = T1.invoice_registration_product_id
        LEFT JOIN sales_ledger T3 ON T3.id = T5.sales_ledger_id
        LEFT JOIN customer T2 ON T2.id = T3.customer_id
        WHERE T1.id = #{id}
    </select>
@@ -113,17 +122,23 @@
        SELECT
            T1.customer_id as id,
            T1.customer_name,
            SUM(contract_amount) AS invoice_total,
            IFNULL( SUM(T2.receipt_payment_amount) , 0 ) AS receipt_payment_amount,
            IFNULL((IFNULL(SUM(contract_amount),0)  - IFNULL(SUM(T2.receipt_payment_amount),0)),0) AS unReceipt_payment_amount
            IFNULL(SUM(T1.contract_amount), 0) AS invoice_total,
            IFNULL(SUM(T2.paid), 0)            AS receipt_payment_amount,
            IFNULL(SUM(T1.contract_amount), 0) - IFNULL(SUM(T2.paid), 0) AS unReceipt_payment_amount
        FROM sales_ledger T1
        LEFT JOIN receipt_payment T2 ON T1.id = T2.sales_ledger_id
        <!-- 2026-10-13 修复:原来直接 LEFT JOIN receipt_payment 再 SUM(contract_amount),
             一笔台账有几笔回款,合同额就被重复累加几次(客户往来页的「合同金额/应收金额」因此虚高,
             例如客户 1108 实际合同 15.37 万被算成 78.35 万)。改成先按台账汇总回款再 JOIN。 -->
        LEFT JOIN (
            SELECT sales_ledger_id, SUM(receipt_payment_amount) AS paid
            FROM receipt_payment WHERE sales_ledger_id IS NOT NULL GROUP BY sales_ledger_id
        ) T2 ON T2.sales_ledger_id = T1.id
        <where>
            <if test="invoiceLedgerDto.searchText != null and invoiceLedgerDto.searchText != '' ">
                T1.customer_name LIKE CONCAT ('%',#{invoiceLedgerDto.searchText},'%')
            </if>
        </where>
        GROUP BY T1.customer_name
        GROUP BY T1.customer_id, T1.customer_name
    </select>
    <select id="invoiceLedgerProductInfo" resultType="com.ruoyi.sales.dto.InvoiceRegistrationProductDto">
src/main/resources/mapper/sales/ReceiptPaymentMapper.xml
@@ -36,11 +36,11 @@
        SELECT
            T1.id                 ,
            T1.sales_ledger_id        ,
            T1.sales_contract_no      ,
            T1.customer_id            ,
            T1.invoice_no             ,
            T1.invoice_amount         ,
            T1.tax_rate               ,
            T3.sales_contract_no      AS sales_contract_no,
            T3.customer_id            AS customer_id,
            T4.invoice_no             AS invoice_no,
            T4.invoice_total          AS invoice_amount,
            T5.tax_rate               AS tax_rate,
            T1.receipt_payment_type   ,
            T1.receipt_payment_amount ,
            T1.registrant             ,
@@ -54,8 +54,13 @@
            T3.customer_contract_no,
            T2.customer_name
        FROM receipt_payment T1
                 LEFT JOIN customer T2 ON T1.customer_id = T2.id
                 LEFT JOIN sales_ledger T3 ON T1.sales_ledger_id = T3.id
                 <!-- 2026-10-12 修复:receipt_payment 表里没有 sales_contract_no / customer_id / invoice_no /
                      invoice_amount / tax_rate 这 5 列,原来的 T1.xxx 必然抛 ER_BAD_FIELD_ERROR。
                      客户与合同号从 sales_ledger 取,发票信息从 invoice_ledger / invoice_registration_product 取。 -->
                 LEFT JOIN sales_ledger T3 ON T3.id = T1.sales_ledger_id
                 LEFT JOIN customer T2 ON T2.id = T3.customer_id
                 LEFT JOIN invoice_ledger T4 ON T4.id = T1.invoice_ledger_id
                 LEFT JOIN invoice_registration_product T5 ON T5.id = T4.invoice_registration_product_id
        WHERE T1.id = #{id}
    </select>
@@ -90,7 +95,7 @@
        FROM invoice_ledger_file
        GROUP BY invoice_ledger_id
        ) T4 ON T4.invoice_ledger_id = T1.id
        LEFT JOIN sales_ledger_product T5 ON T2.sales_ledger_product_id = T5.id and slp.type = 1
        LEFT JOIN sales_ledger_product T5 ON T2.sales_ledger_product_id = T5.id and T5.type = 1
        LEFT JOIN (
        SELECT
        SUM(receipt_payment_amount) AS receipt_payment_amount_total,
@@ -378,7 +383,7 @@
                GROUP_CONCAT( name ORDER BY id ASC SEPARATOR ' | ') AS invoiceFileName
            FROM invoice_ledger_file GROUP BY invoice_ledger_id
        ) T4 ON T4.invoice_ledger_id = T1.id
                 LEFT JOIN sales_ledger_product T5 ON T2.sales_ledger_product_id = T5.id and slp.type = 1
                 LEFT JOIN sales_ledger_product T5 ON T2.sales_ledger_product_id = T5.id and T5.type = 1
                 LEFT JOIN (
            SELECT SUM(receipt_payment_amount) AS receipt_payment_amount_total,invoice_ledger_id FROM receipt_payment GROUP
                BY invoice_ledger_id
@@ -414,7 +419,7 @@
        GROUP_CONCAT( name ORDER BY id ASC SEPARATOR ' | ') AS invoiceFileName
        FROM invoice_ledger_file GROUP BY invoice_ledger_id
        ) T4 ON T4.invoice_ledger_id = T1.id
        LEFT JOIN sales_ledger_product T5 ON T2.sales_ledger_product_id = T5.id and slp.type = 1
        LEFT JOIN sales_ledger_product T5 ON T2.sales_ledger_product_id = T5.id and T5.type = 1
        LEFT JOIN (
        SELECT SUM(receipt_payment_amount) AS receipt_payment_amount_total,invoice_ledger_id FROM receipt_payment GROUP
        BY invoice_ledger_id
@@ -438,7 +443,13 @@
        T1.sales_contract_no,
        T1.contract_amount AS invoice_total,
        IFNULL(SUM(T2.receipt_payment_amount), 0) AS receipt_payment_amount,
        IFNULL((T1.contract_amount - IFNULL(SUM(T2.receipt_payment_amount), 0)), 0) AS unReceipt_payment_amount,
        <!-- 2026-10-13 修复:原来写的是「合同额 − 本日期这一笔回款」,再叠加 GROUP BY receipt_payment_date,
             一笔台账有几笔回款就会拆成几行,每行都显示一个假的"应收"(例如 XS202605001 已全额回款,
             却显示应收 1544.40)。应收金额应当是**该合同当前真正的未回款额 = 合同额 − 全部回款**。 -->
        GREATEST(T1.contract_amount - IFNULL((
            SELECT SUM(T3.receipt_payment_amount) FROM receipt_payment T3
            WHERE T3.sales_ledger_id = T1.id
        ), 0), 0) AS unReceipt_payment_amount,
        T2.receipt_payment_date
        FROM sales_ledger T1
        INNER JOIN receipt_payment T2 ON T1.id = T2.sales_ledger_id
@@ -449,6 +460,7 @@
            </if>
        </where>
        GROUP BY T1.id, T1.sales_contract_no, T1.contract_amount, T2.receipt_payment_date
        ORDER BY T1.entry_date ASC, T2.receipt_payment_date ASC
    </select>
</mapper>
src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -132,7 +132,7 @@
            AND slp.product_category = #{req.productCategory}
        </if>
        <!-- 按产品大类分组聚合 -->
        GROUP BY slp.product_category
        GROUP BY slp.product_category, slp.specification_model, sl.supplier_name
        <!-- 按产品大类排序 -->
        ORDER BY slp.product_category
    </select>