fix(erp/crm): 单据明细单价口径由「不含税单价」改为「含税单价」
含税金额 = 含税单价 × 数量;税额 = 含税金额 × 税率;不含税金额 = 含税金额 − 税额
覆盖销售订单、采购订单、采购申请、销售报价的明细推导(新增/修改/Excel 导入/转采购订单/SRM 中标)。
DO 字段语义不变(totalPrice 仍为不含税金额、taxPrice 为税额),故主表聚合
(Σ不含税 + Σ税额 − 折扣 = 含税合计)与 fillItemPrice、来票额度均无需改动。
同步明细/主表 DO 字段注释。
Co-Authored-By: Claude Code <noreply@anthropic.com>
| | |
| | | */ |
| | | private BigDecimal itemPrice; |
| | | /** |
| | | * 报价单价,单位:元 |
| | | * 报价含税单价,单位:元 |
| | | */ |
| | | private BigDecimal quotationPrice; |
| | | /** |
| | |
| | | */ |
| | | private BigDecimal count; |
| | | /** |
| | | * 小计金额,单位:元 |
| | | * 不含税金额,单位:元 |
| | | * |
| | | * totalPrice = quotationPrice * count |
| | | * 含税金额 = quotationPrice * count |
| | | * totalPrice = 含税金额 - taxPrice |
| | | */ |
| | | private BigDecimal totalPrice; |
| | | /** |
| | |
| | | private BigDecimal taxPercent; |
| | | /** |
| | | * 税额,单位:元 |
| | | * |
| | | * 含税金额 = quotationPrice * count |
| | | * taxPrice = 含税金额 * taxPercent |
| | | */ |
| | | private BigDecimal taxPrice; |
| | | /** |
| | |
| | | // 物料原价,如果 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); |
| | | } |
| | | })); |
| | | } |
| | |
| | | */ |
| | | private BigDecimal totalCount; |
| | | /** |
| | | * 最终合计价格,单位:元 |
| | | * 最终合计价格(含税),单位:元 |
| | | * |
| | | * totalPrice = totalProductPrice + totalTaxPrice - discountPrice |
| | | * 等价于 Σ(含税单价 * 数量) - discountPrice |
| | | */ |
| | | private BigDecimal totalPrice; |
| | | |
| | | /** |
| | | * 合计产品价格,单位:元 |
| | | * 合计产品价格(不含税),单位:元 |
| | | */ |
| | | private BigDecimal totalProductPrice; |
| | | /** |
| | |
| | | private Long productUnitId; |
| | | |
| | | /** |
| | | * 产品单位单价,单位:元 |
| | | * 产品单位含税单价,单位:元 |
| | | */ |
| | | private BigDecimal productPrice; |
| | | /** |
| | |
| | | */ |
| | | private BigDecimal count; |
| | | /** |
| | | * 总价,单位:元 |
| | | * 不含税金额,单位:元 |
| | | * |
| | | * totalPrice = productPrice * count |
| | | * 含税金额 = productPrice * count |
| | | * totalPrice = 含税金额 - taxPrice |
| | | */ |
| | | private BigDecimal totalPrice; |
| | | /** |
| | |
| | | /** |
| | | * 税额,单位:元 |
| | | * |
| | | * taxPrice = totalPrice * taxPercent |
| | | * 含税金额 = productPrice * count |
| | | * taxPrice = 含税金额 * taxPercent |
| | | */ |
| | | private BigDecimal taxPrice; |
| | | |
| | |
| | | private BigDecimal totalCount; |
| | | |
| | | /** |
| | | * 合计价格 |
| | | * 合计价格(含税) |
| | | * |
| | | * totalPrice = totalProductPrice + totalTaxPrice - discountPrice |
| | | * 等价于 Σ(含税单价 * 数量) - discountPrice |
| | | */ |
| | | private BigDecimal totalPrice; |
| | | |
| | | /** |
| | | * 合计产品价格 |
| | | * 合计产品价格(不含税) |
| | | */ |
| | | private BigDecimal totalProductPrice; |
| | | |
| | |
| | | private Long productUnitId; |
| | | |
| | | /** |
| | | * 产品参考单价 |
| | | * 产品参考含税单价 |
| | | */ |
| | | private BigDecimal productPrice; |
| | | |
| | |
| | | private BigDecimal count; |
| | | |
| | | /** |
| | | * 总价 |
| | | * 不含税金额 |
| | | * |
| | | * 含税金额 = productPrice * count |
| | | * totalPrice = 含税金额 - taxPrice |
| | | */ |
| | | private BigDecimal totalPrice; |
| | | |
| | |
| | | |
| | | /** |
| | | * 税额 |
| | | * |
| | | * 含税金额 = productPrice * count |
| | | * taxPrice = 含税金额 * taxPercent |
| | | */ |
| | | private BigDecimal taxPrice; |
| | | |
| | |
| | | */ |
| | | private BigDecimal totalCount; |
| | | /** |
| | | * 最终合计价格,单位:元 |
| | | * 最终合计价格(含税),单位:元 |
| | | * |
| | | * totalPrice = totalProductPrice + totalTaxPrice - discountPrice |
| | | * 等价于 Σ(含税单价 * 数量) - discountPrice |
| | | */ |
| | | private BigDecimal totalPrice; |
| | | |
| | | /** |
| | | * 合计产品价格,单位:元 |
| | | * 合计产品价格(不含税),单位:元 |
| | | */ |
| | | private BigDecimal totalProductPrice; |
| | | /** |
| | |
| | | private Long productUnitId; |
| | | |
| | | /** |
| | | * 产品单位单价,单位:元 |
| | | * 产品单位含税单价,单位:元 |
| | | */ |
| | | private BigDecimal productPrice; |
| | | /** |
| | |
| | | */ |
| | | private BigDecimal count; |
| | | /** |
| | | * 总价,单位:元 |
| | | * 不含税金额,单位:元 |
| | | * |
| | | * totalPrice = productPrice * count |
| | | * 含税金额 = productPrice * count |
| | | * totalPrice = 含税金额 - taxPrice |
| | | */ |
| | | private BigDecimal totalPrice; |
| | | /** |
| | |
| | | /** |
| | | * 税额,单位:元 |
| | | * |
| | | * taxPrice = totalPrice * taxPercent |
| | | * 含税金额 = productPrice * count |
| | | * taxPrice = 含税金额 * taxPercent |
| | | */ |
| | | private BigDecimal taxPrice; |
| | | |
| | |
| | | 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); |
| | | })); |
| | | } |
| | | |
| | |
| | | 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); |
| | | } |
| | | })); |
| | | } |
| | |
| | | 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); |
| | | })); |
| | | } |
| | | |