gaoluyang
7 小时以前 174b16450916d3e5c18b23911844c4165b9113bf
fix(erp/crm): 单据明细单价口径由「不含税单价」改为「含税单价」

含税金额 = 含税单价 × 数量;税额 = 含税金额 × 税率;不含税金额 = 含税金额 − 税额
覆盖销售订单、采购订单、采购申请、销售报价的明细推导(新增/修改/Excel 导入/转采购订单/SRM 中标)。

DO 字段语义不变(totalPrice 仍为不含税金额、taxPrice 为税额),故主表聚合
(Σ不含税 + Σ税额 − 折扣 = 含税合计)与 fillItemPrice、来票额度均无需改动。
同步明细/主表 DO 字段注释。

Co-Authored-By: Claude Code <noreply@anthropic.com>
已修改11个文件
93 ■■■■■ 文件已修改
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/quotation/CrmSaleQuotationProductDO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderDO.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseRequestDO.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseRequestItemDO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseRequestServiceImpl.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/quotation/CrmSaleQuotationProductDO.java
@@ -51,7 +51,7 @@
     */
    private BigDecimal itemPrice;
    /**
     * 报价单价,单位:元
     * 报价含税单价,单位:元
     */
    private BigDecimal quotationPrice;
    /**
@@ -59,9 +59,10 @@
     */
    private BigDecimal count;
    /**
     * 小计金额,单位:元
     * 不含税金额,单位:元
     *
     * totalPrice = quotationPrice * count
     * 含税金额 = quotationPrice * count
     * totalPrice = 含税金额 - taxPrice
     */
    private BigDecimal totalPrice;
    /**
@@ -70,6 +71,9 @@
    private BigDecimal taxPercent;
    /**
     * 税额,单位:元
     *
     * 含税金额 = quotationPrice * count
     * taxPrice = 含税金额 * taxPercent
     */
    private BigDecimal taxPrice;
    /**
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java
@@ -181,10 +181,14 @@
            // 物料原价,如果 MDM 中没有则默认为 0
            item.setItemPrice(mdmItem.getSalesPrice() != null ? mdmItem.getSalesPrice() : BigDecimal.ZERO);
            if (item.getQuotationPrice() != null && item.getCount() != null) {
                item.setTotalPrice(MoneyUtils.priceMultiply(item.getQuotationPrice(), item.getCount()));
                // 报价为含税单价:含税金额 = 单价 × 数量;税额 = 含税金额 × 税率;不含税金额 = 含税金额 - 税额
                BigDecimal taxInclusivePrice = MoneyUtils.priceMultiply(item.getQuotationPrice(), item.getCount());
                BigDecimal taxPrice = null;
                if (item.getTaxPercent() != null) {
                    item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent()));
                    taxPrice = MoneyUtils.priceMultiplyPercent(taxInclusivePrice, item.getTaxPercent());
                }
                item.setTaxPrice(taxPrice);
                item.setTotalPrice(taxPrice != null ? taxInclusivePrice.subtract(taxPrice) : taxInclusivePrice);
            }
        }));
    }
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderDO.java
@@ -62,14 +62,15 @@
     */
    private BigDecimal totalCount;
    /**
     * 最终合计价格,单位:元
     * 最终合计价格(含税),单位:元
     *
     * totalPrice = totalProductPrice + totalTaxPrice - discountPrice
     * 等价于 Σ(含税单价 * 数量) - discountPrice
     */
    private BigDecimal totalPrice;
    /**
     * 合计产品价格,单位:元
     * 合计产品价格(不含税),单位:元
     */
    private BigDecimal totalProductPrice;
    /**
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java
@@ -54,7 +54,7 @@
    private Long productUnitId;
    /**
     * 产品单位单价,单位:元
     * 产品单位含税单价,单位:元
     */
    private BigDecimal productPrice;
    /**
@@ -62,9 +62,10 @@
     */
    private BigDecimal count;
    /**
     * 总价,单位:元
     * 不含税金额,单位:元
     *
     * totalPrice = productPrice * count
     * 含税金额 = productPrice * count
     * totalPrice = 含税金额 - taxPrice
     */
    private BigDecimal totalPrice;
    /**
@@ -74,7 +75,8 @@
    /**
     * 税额,单位:元
     *
     * taxPrice = totalPrice * taxPercent
     * 含税金额 = productPrice * count
     * taxPrice = 含税金额 * taxPercent
     */
    private BigDecimal taxPrice;
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseRequestDO.java
@@ -75,12 +75,15 @@
    private BigDecimal totalCount;
    /**
     * 合计价格
     * 合计价格(含税)
     *
     * totalPrice = totalProductPrice + totalTaxPrice - discountPrice
     * 等价于 Σ(含税单价 * 数量) - discountPrice
     */
    private BigDecimal totalPrice;
    /**
     * 合计产品价格
     * 合计产品价格(不含税)
     */
    private BigDecimal totalProductPrice;
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseRequestItemDO.java
@@ -44,7 +44,7 @@
    private Long productUnitId;
    /**
     * 产品参考单价
     * 产品参考含税单价
     */
    private BigDecimal productPrice;
@@ -54,7 +54,10 @@
    private BigDecimal count;
    /**
     * 总价
     * 不含税金额
     *
     * 含税金额 = productPrice * count
     * totalPrice = 含税金额 - taxPrice
     */
    private BigDecimal totalPrice;
@@ -65,6 +68,9 @@
    /**
     * 税额
     *
     * 含税金额 = productPrice * count
     * taxPrice = 含税金额 * taxPercent
     */
    private BigDecimal taxPrice;
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java
@@ -76,14 +76,15 @@
     */
    private BigDecimal totalCount;
    /**
     * 最终合计价格,单位:元
     * 最终合计价格(含税),单位:元
     *
     * totalPrice = totalProductPrice + totalTaxPrice - discountPrice
     * 等价于 Σ(含税单价 * 数量) - discountPrice
     */
    private BigDecimal totalPrice;
    /**
     * 合计产品价格,单位:元
     * 合计产品价格(不含税),单位:元
     */
    private BigDecimal totalProductPrice;
    /**
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java
@@ -48,7 +48,7 @@
    private Long productUnitId;
    /**
     * 产品单位单价,单位:元
     * 产品单位含税单价,单位:元
     */
    private BigDecimal productPrice;
    /**
@@ -56,9 +56,10 @@
     */
    private BigDecimal count;
    /**
     * 总价,单位:元
     * 不含税金额,单位:元
     *
     * totalPrice = productPrice * count
     * 含税金额 = productPrice * count
     * totalPrice = 含税金额 - taxPrice
     */
    private BigDecimal totalPrice;
    /**
@@ -68,7 +69,8 @@
    /**
     * 税额,单位:元
     *
     * taxPrice = totalPrice * taxPercent
     * 含税金额 = productPrice * count
     * taxPrice = 含税金额 * taxPercent
     */
    private BigDecimal taxPrice;
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java
@@ -486,13 +486,17 @@
    private List<ErpPurchaseOrderItemDO> validatePurchaseOrderItems(List<ErpPurchaseOrderSaveReqVO.Item> list) {
        // 转化为 ErpPurchaseOrderItemDO 列表(产品验证已移除)
        return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseOrderItemDO.class, item -> {
            item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount()));
            if (item.getTotalPrice() == null) {
            // 单价为含税单价:含税金额 = 单价 × 数量;税额 = 含税金额 × 税率;不含税金额 = 含税金额 - 税额
            BigDecimal taxInclusivePrice = MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount());
            if (taxInclusivePrice == null) {
                return;
            }
            BigDecimal taxPrice = null;
            if (item.getTaxPercent() != null) {
                item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent()));
                taxPrice = MoneyUtils.priceMultiplyPercent(taxInclusivePrice, item.getTaxPercent());
            }
            item.setTaxPrice(taxPrice);
            item.setTotalPrice(taxPrice != null ? taxInclusivePrice.subtract(taxPrice) : taxInclusivePrice);
        }));
    }
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseRequestServiceImpl.java
@@ -363,10 +363,14 @@
    private List<ErpPurchaseRequestItemDO> validatePurchaseRequestItems(List<ErpPurchaseRequestSaveReqVO.Item> list) {
        return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseRequestItemDO.class, item -> {
            if (item.getProductPrice() != null && item.getCount() != null) {
                item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount()));
                // 单价为含税单价:含税金额 = 单价 × 数量;税额 = 含税金额 × 税率;不含税金额 = 含税金额 - 税额
                BigDecimal taxInclusivePrice = MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount());
                BigDecimal taxPrice = null;
                if (item.getTaxPercent() != null) {
                    item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent()));
                    taxPrice = MoneyUtils.priceMultiplyPercent(taxInclusivePrice, item.getTaxPercent());
                }
                item.setTaxPrice(taxPrice);
                item.setTotalPrice(taxPrice != null ? taxInclusivePrice.subtract(taxPrice) : taxInclusivePrice);
            }
        }));
    }
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java
@@ -625,13 +625,17 @@
    private List<ErpSaleOrderItemDO> validateSaleOrderItems(List<ErpSaleOrderSaveReqVO.Item> list) {
        // 转化为 ErpSaleOrderItemDO 列表(产品验证已移除)
        return convertList(list, o -> BeanUtils.toBean(o, ErpSaleOrderItemDO.class, item -> {
            item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount()));
            if (item.getTotalPrice() == null) {
            // 单价为含税单价:含税金额 = 单价 × 数量;税额 = 含税金额 × 税率;不含税金额 = 含税金额 - 税额
            BigDecimal taxInclusivePrice = MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount());
            if (taxInclusivePrice == null) {
                return;
            }
            BigDecimal taxPrice = null;
            if (item.getTaxPercent() != null) {
                item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent()));
                taxPrice = MoneyUtils.priceMultiplyPercent(taxInclusivePrice, item.getTaxPercent());
            }
            item.setTaxPrice(taxPrice);
            item.setTotalPrice(taxPrice != null ? taxInclusivePrice.subtract(taxPrice) : taxInclusivePrice);
        }));
    }