yuan
2 天以前 7dfff767d0fae788ba2bf67a707ce41836bd0f42
fix: 优化客户往来查询逻辑,调整应收金额计算方式以避免尾差问题
已修改2个文件
98 ■■■■■ 文件已修改
src/main/resources/mapper/basic/CustomerMapper.xml 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/basic/SupplierManageMapper.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/basic/CustomerMapper.xml
@@ -111,49 +111,75 @@
    </select>
    <!--
      客户往来(回款台账主表):
        应收金额 = 已出库金额 − 已退货款 − 已回款金额(不小于 0)
        应收金额 = 各销售台账的应收金额之和,
        单条台账应收金额 = 该台账已出库金额 − 已退货款 − 已回款金额(不小于 0)。
      即「回款金额」是累计回款,「应收金额」是还没收回来的部分。
      注意 T3 按 (shipping_info, 产品行) 先聚合再求和,避免同一发货单多批号出库时重复计数。
      注意 出库金额 = sum(出库数量 * 6位小数的含税单价),会带有「分」以下的零头,
           而回款是按分录入的整数金额,两者相减会出现 0.0045、0.004 这类无意义的尾差,
           因此单条台账的应收金额按分计算,分以下的尾差不计入。
      注意 必须先按台账算好应收、再按客户汇总(与 customewTransactionsDetails 口径一致)。
           若先按客户汇总再取整,各家台账的尾差会累加,出现「主表 0.01、明细全是 0」的对不上问题。
      注意 出库金额按台账 (sales_ledger.id) 聚合,同一发货单多批号出库时不会重复计数。
    -->
    <select id="customewTransactions" resultType="com.ruoyi.sales.vo.CustomerTransactionsVo">
        select T1.customer_id,
               c.customer_name,
               T1.contractAmounts,
               IFNULL(T2.receiptPaymentAmount, 0) AS receiptPaymentAmount,
               GREATEST(
                   IFNULL(T3.outboundAmount, 0) - IFNULL(T4.returnAmount, 0)
                       - IFNULL(T2.receiptPaymentAmount, 0),
                   0) AS receiptableAmount
               IFNULL(T5.receiptableAmount, 0) AS receiptableAmount
        from (select customer_id, sum(contract_amount) as contractAmounts from sales_ledger group by customer_id) T1
        left join (select customer_id, sum(collection_amount) as receiptPaymentAmount from account_sales_collection group by customer_id) T2 on T1.customer_id = T2.customer_id
        left join (
            SELECT customer_id, sum(shipped_amount) as outboundAmount from (
            select
                sl.customer_id,
                sum(GREATEST(
                    TRUNCATE(IFNULL(T3.outboundAmount, 0) - IFNULL(T4.returnAmount, 0)
                                 - IFNULL(T6.receiptPaymentAmount, 0), 2),
                    0)) AS receiptableAmount
            from sales_ledger sl
            left join (
                select
                    sl.id,
                    sum(t.collection_amount) as receiptPaymentAmount
                from (
                    select
                        ascc.collection_amount,
                        s.sales_ledger_id
                    from account_sales_collection ascc
                    left join stock_out_record sor on FIND_IN_SET(sor.id, ascc.stock_out_record_ids) > 0
                    left join shipping_info s on sor.record_id = s.id
                    where sor.record_type='13'
                      and sor.approval_status=1
                    group by ascc.id, s.sales_ledger_id
                ) t
                left join sales_ledger sl on t.sales_ledger_id = sl.id
                group by sl.id
            ) T6 on T6.id = sl.id
            left join (
                SELECT
                    sl.customer_id,
                    s.id AS shipping_id,
                    s.sales_ledger_product_id,
                    sum(sor.stock_out_num * slp.tax_inclusive_unit_price) as shipped_amount
                    sl.id,
                    sum(sor.stock_out_num * slp.tax_inclusive_unit_price) as outboundAmount
                FROM stock_out_record sor
                LEFT join shipping_info s on sor.record_id = s.id
                LEFT JOIN sales_ledger sl ON s.sales_ledger_id = sl.id
                LEFT JOIN sales_ledger_product slp ON s.sales_ledger_product_id = slp.id
                    left join shipping_info s on sor.record_id = s.id
                    LEFT JOIN sales_ledger sl ON s.sales_ledger_id = sl.id
                    LEFT JOIN sales_ledger_product slp ON s.sales_ledger_product_id = slp.id
                WHERE sor.record_type='13'
                    and sor.approval_status=1
                    and slp.type = 1
                group by sl.customer_id, s.id, s.sales_ledger_product_id
            ) g
            group by customer_id
        ) T3 on T3.customer_id=T1.customer_id
        left join (
            select
                sl.customer_id,
                sum(rm.refund_amount) as returnAmount
            from return_management rm
            left join shipping_info si on rm.shipping_id = si.id
            left join sales_ledger sl on si.sales_ledger_id = sl.id
            where rm.status=1
                group by sl.id
            ) T3 on T3.id = sl.id
            left join (
                select
                    sl.id,
                    sum(rm.refund_amount) as returnAmount
                from return_management rm
                left join shipping_info si on rm.shipping_id = si.id
                left join sales_ledger sl on si.sales_ledger_id = sl.id
                where rm.status=1
                group by sl.id
            ) T4 on T4.id = sl.id
            group by sl.customer_id
        ) T4 on T4.customer_id=T1.customer_id
        ) T5 on T5.customer_id = T1.customer_id
        left join customer c on T1.customer_id = c.id
        <where>
            <if test="customerName!=null and customerName!=''">
@@ -166,6 +192,7 @@
      客户往来明细(按销售台账):应收金额 = 该台账已出库 − 已退货 − 已回款。
      单条回款只统计一次:同一回款可能同时命中该台账的多条出库记录,
      先用 GROUP BY ascc.id, sl.id 去重,再按台账求和。
      金额同样按分(2 位小数)计算,分以下的尾差不计入。
    -->
    <select id="customewTransactionsDetails"
            resultType="com.ruoyi.sales.vo.CustomerTransactionsDetailsVo">
@@ -175,8 +202,8 @@
               sl.contract_amount,
               IFNULL(T1.receiptPaymentAmount, 0) AS receiptPaymentAmount,
               GREATEST(
                   IFNULL(T2.outboundAmount, 0) - IFNULL(T3.returnAmount, 0)
                       - IFNULL(T1.receiptPaymentAmount, 0),
                   TRUNCATE(IFNULL(T2.outboundAmount, 0) - IFNULL(T3.returnAmount, 0)
                                - IFNULL(T1.receiptPaymentAmount, 0), 2),
                   0) AS receiptableAmount
        from sales_ledger sl
        left join (
src/main/resources/mapper/basic/SupplierManageMapper.xml
@@ -75,18 +75,20 @@
               c.contractAmounts,
               -- 付款金额:逐合同按合同金额封顶后再汇总,避免重复付款导致付款金额大于合同金额
               c.paymentAmount,
               -- 应付金额:逐合同「取(入库金额, 合同金额)较小者 - 封顶后付款金额 - 退货金额」后再汇总,下限为 0
               -- 应付金额:逐合同「取(入库金额, 合同金额)较小者 - 封顶后付款金额 - 退货金额」后再汇总,下限为 0。
               -- 入库金额由 6 位小数的含税单价累加而来,会带出「厘」及以下的小数,
               -- 因此逐合同先四舍五入到分再汇总,保证「供应商应付金额 = 各合同应付金额之和」、且页面上只出现 2 位小数。
               c.payableAmount
        from (
            select pl.supplier_id,
                   sum(COALESCE(pl.contract_amount, 0)) as contractAmounts,
                   sum(LEAST(IFNULL(pay.paymentAmount, 0), COALESCE(pl.contract_amount, 0))) as paymentAmount,
                   sum(GREATEST(
                   sum(ROUND(GREATEST(
                       IFNULL(ib.InboundAmount, 0)
                           - IF(ib.InboundAmount <![CDATA[ > ]]> COALESCE(pl.contract_amount, 0), ib.InboundAmount - COALESCE(pl.contract_amount, 0), 0)
                       - LEAST(IFNULL(pay.paymentAmount, 0), COALESCE(pl.contract_amount, 0))
                       - IFNULL(rt.returnAmount, 0)
                   , 0)) as payableAmount
                   , 0), 2)) as payableAmount
            from purchase_ledger pl
            left join (
                select
@@ -150,12 +152,13 @@
              -- 应付金额 = 取(入库金额, 合同金额)的较小者 - 封顶后付款金额 - 退货金额
              -- 入库金额按合同金额封顶,避免入库流程重复提交导致应付金额大于合同金额;
              -- 已付款金额(回款/付款单)与退货金额均需从应付中扣减。
              GREATEST(
              -- 逐合同四舍五入到分(与 supplierTransactions 汇总口径一致),避免出现 3 位以上小数
              ROUND(GREATEST(
                  IFNULL(T2.InboundAmount, 0)
                      - IF(T2.InboundAmount <![CDATA[ > ]]> COALESCE(pl.contract_amount, 0), T2.InboundAmount - COALESCE(pl.contract_amount, 0), 0)
                  - LEAST(IFNULL(T1.paymentAmount, 0), COALESCE(pl.contract_amount, 0))
                  - IFNULL(T3.returnAmount, 0)
              , 0) AS payableAmount
              , 0), 2) AS payableAmount
       from purchase_ledger pl
       left join (
           select