Magento 2商品价格/小计保留4位小数 VAT与总计保留2位小数问题咨询
Magento 2 价格舍入误差修复方案
你之前修改数值后被系统自动还原,是因为Magento会在quote更新、地址保存、税费计算等多个环节自动触发默认的价格计算逻辑,仅修改数据库值无法覆盖所有触发场景,需通过自定义插件拦截核心计算逻辑实现需求:
前置准备:创建自定义模块
- 新建模块目录
app/code/Vendor/PriceRounding - 创建注册文件
app/code/Vendor/PriceRounding/registration.php:
<?php use Magento\Framework\Component\ComponentRegistrar; ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Vendor_PriceRounding', __DIR__);
- 创建模块配置文件
app/code/Vendor/PriceRounding/etc/module.xml:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Vendor_PriceRounding" setup_version="1.0.0"> <sequence> <module name="Magento_Quote"/> <module name="Magento_Tax"/> <module name="Magento_Sales"/> </sequence> </module> </config>
第一步:实现小计先舍入到2位的逻辑
创建依赖注入配置文件app/code/Vendor/PriceRounding/etc/di.xml,拦截小计计算类:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <!-- 拦截小计计算逻辑 --> <type name="Magento\Quote\Model\Quote\Address\Total\Subtotal"> <plugin name="vendor_subtotal_rounding" type="Vendor\PriceRounding\Plugin\SubtotalRoundingPlugin" sortOrder="10"/> </type> <!-- 拦截税费计算逻辑 --> <type name="Magento\Tax\Model\Calculation\AbstractAggregateCalculator"> <plugin name="vendor_tax_rounding" type="Vendor\PriceRounding\Plugin\TaxCalculationPlugin" sortOrder="10"/> </type> </config>
创建小计处理插件app/code/Vendor/PriceRounding/Plugin/SubtotalRoundingPlugin.php:
<?php namespace Vendor\PriceRounding\Plugin; use Magento\Quote\Model\Quote\Address\Total\Subtotal; use Magento\Quote\Model\Quote\Address; class SubtotalRoundingPlugin { public function afterCollect(Subtotal $subject, $result, Address $address) { // 获取4位精度计算出的原始小计 $rawSubtotal = $address->getSubtotal(); $baseRawSubtotal = $address->getBaseSubtotal(); // 舍入到2位 $roundedSubtotal = round($rawSubtotal, 2); $baseRoundedSubtotal = round($baseRawSubtotal, 2); // 覆盖地址的小计值,后续所有计算均读取该舍入后的值 $address->setSubtotal($roundedSubtotal); $address->setBaseSubtotal($baseRoundedSubtotal); $address->setSubtotalInclTax($roundedSubtotal); return $result; } }
第二步:修改税费计算逻辑,基于舍入后的小计计算VAT
创建税费处理插件app/code/Vendor/PriceRounding/Plugin/TaxCalculationPlugin.php:
<?php namespace Vendor\PriceRounding\Plugin; use Magento\Tax\Model\Calculation\AbstractAggregateCalculator; use Magento\Tax\Api\Data\QuoteDetailsInterface; class TaxCalculationPlugin { public function aroundCalculate(AbstractAggregateCalculator $subject, callable $proceed, QuoteDetailsInterface $quoteDetails, $storeId = null) { $result = $proceed($quoteDetails, $storeId); // 读取已舍入到2位的小计 $roundedSubtotal = $quoteDetails->getSubtotal(); $taxRate = $result->getAppliedTaxes()[0]['percent'] / 100; // 基于舍入后的小计重新计算VAT $calculatedTax = round($roundedSubtotal * $taxRate, 2); $baseCalculatedTax = round($roundedSubtotal * $taxRate, 2); // 覆盖税费计算结果 $result->setTaxAmount($calculatedTax); $result->setBaseTaxAmount($baseCalculatedTax); $result->setGrandTotal($roundedSubtotal + $calculatedTax); $result->setBaseGrandTotal($roundedSubtotal + $baseCalculatedTax); return $result; } }
第三步:部署生效
执行以下命令启用模块并生效:
bin/magento setup:upgrade bin/magento setup:di:compile bin/magento cache:clean
验证注意事项
- 测试边缘场景:例如商品单价1.0004元,购买3件时4位精度小计为3.0012元,按逻辑会先舍入为3.00元,VAT按3.00元计算,小计+VAT与总金额不会出现1分差额
- 如需兼容多税率、折扣等场景,可在对应插件中扩展逻辑,统一基于舍入后的2位小计计算即可
内容的提问来源于stack exchange,提问作者Aurel
相关产品推荐
相关产品推荐

