Magento 2

Critical Magento 2 Tax Glitch: Double Shipping Tax on Invoices & Credit Memos Explained

Magento 2 Data Flow: Shipping Tax Inconsistency Impacting Invoices and Credit Memos
Magento 2 Data Flow: Shipping Tax Inconsistency Impacting Invoices and Credit Memos

Critical Magento 2 Tax Glitch: Double Shipping Tax on Invoices & Credit Memos Explained

As e-commerce migration experts at Shopping Mover, we are dedicated to ensuring the stability and accuracy of your online store. Our continuous monitoring of the Magento ecosystem recently brought a significant issue to our attention: a critical tax calculation bug in Magento Open Source 2.4.9 (and potentially the 2.4-develop branch) that could severely impact financial reporting and lead to incorrect refunds. This isn't just a minor display error; it's a fundamental inconsistency that can have real financial consequences for merchants.

The Core Problem: Shipping Tax Duplication on Invoices

The issue, detailed in GitHub issue #41031 by simonmaass, arises under a very specific, yet common, configuration: when Magento is set to calculate shipping prices "Including Tax" (found under Stores > Configuration > Sales > Tax > Calculation Settings). Under these conditions, the system incorrectly persists the shipping_amount as a tax-inclusive value, even though the shipping_tax_amount is stored separately. This fundamental inconsistency leads to a critical flaw: when an invoice is generated, the shipping tax is effectively added twice, inflating the invoice's grand total.

Let's illustrate with an example. Imagine a shipping method costing €4.95, which includes 19% VAT. The correct breakdown, adhering to Magento's tax contract, should be:

shipping_amount      = 4.16 (tax-exclusive) 
shipping_tax_amount  = 0.79 
shipping_incl_tax    = 4.95 (tax-inclusive)

However, due to this bug, Magento persists the following inconsistent values on both quote_address and sales_order:

shipping_amount      = 4.95 (incorrectly tax-inclusive) 
shipping_tax_amount  = 0.79 
shipping_incl_tax    = 4.95

While the order grand total might initially appear correct on the frontend and in the order view (because internal quote aggregation uses the tax-exclusive shipping total), the problem manifests during invoice creation. Magento adds both the incorrectly tax-inclusive shipping_amount (€4.95) and the separate shipping_tax_amount (€0.79), resulting in an invoice grand total that is higher by exactly the shipping tax amount. For instance, an expected invoice grand total of €10.90 could become €11.69 – a difference of €0.79, precisely the shipping tax.

Unpacking the Root Cause: A Data Inconsistency

The root cause lies in how Magento's quote and tax collectors interact. Initially, the shipping collector correctly stores the configured shipping rate. However, when shipping prices include tax, the CommonTaxCollector::processShippingTaxInfo() method correctly recalculates the tax-exclusive shipping total for internal use but fails to update the ordinary shipping_amount and base_shipping_amount data properties. Later, the TotalsCollector copies these stale, tax-inclusive values back to the quote address, overwriting the correct tax-exclusive amount.

This means that while the internal calculations for the order grand total are correct, the persisted data in the database (which is then used for invoicing) is flawed. This malformed data tuple is then carried over from the quote to the order, and subsequently, to the invoice generation process, where the double-counting occurs.

Expanded Impact: Over-Refunds on Credit Memos

The implications of this bug extend beyond just invoices. Further investigation confirmed that this malformed shipping data tuple also impacts credit memo generation. For affected orders, creating a full credit memo results in an over-refund. Using our previous example, an expected refund total of €44.90 could become €45.69, again with the difference being exactly the shipping tax amount.

This happens because Magento\Sales\Model\Order\Creditmemo\Total\Shipping adds the shipping_amount (which is incorrectly tax-inclusive) to the credit memo grand total, and then Magento\Sales\Model\Order\Creditmemo\Total\Tax adds the shipping_tax_amount separately. This double-counting directly leads to merchants refunding more than they should have, impacting cash flow and financial reconciliation.

Are You Affected? Identifying the Issue in Your Magento Store

Merchants running Magento Open Source 2.4.9 (and potentially other 2.4.x versions where the relevant code is present) with the "Shipping Prices: Including Tax" setting enabled are most likely affected. To check if your store is experiencing this issue:

  • Review Recent Invoices: Compare the shipping amount on your invoices with the actual shipping cost and tax breakdown. Look for discrepancies where the invoice grand total seems higher than expected by the shipping tax amount.
  • Inspect Database Records: For a specific order, query the sales_order table for shipping_amount, shipping_tax_amount, and shipping_incl_tax. If shipping_amount equals shipping_incl_tax, and shipping_tax_amount is greater than zero, your order data is likely malformed.
  • Test Credit Memos: Create a credit memo for an affected order and verify the refund total.

The Proposed Fix and Backward Compatibility

The proposed fix involves a small but crucial change: synchronizing the ordinary shipping amount properties with the authoritative tax calculation result within CommonTaxCollector::processShippingTaxInfo(). This ensures that the shipping_amount and base_shipping_amount are correctly set as tax-exclusive values.

$total->setTotalAmount('shipping', $shippingTaxDetails->getRowTotal());
$total->setBaseTotalAmount('shipping', $baseShippingTaxDetails->getRowTotal());
+$total->setShippingAmount($shippingTaxDetails->getRowTotal());
+$total->setBaseShippingAmount($baseShippingTaxDetails->getRowTotal());

While this fix prevents malformed data on newly collected quotes and orders, it's crucial to understand its backward compatibility implications. Orders created before applying this fix will still contain the inconsistent shipping tuple. This means that existing affected orders will continue to generate incorrect invoices and credit memos unless their data is repaired or invoice/credit memo collection processes are defensively updated to handle this specific inconsistency.

Shopping Mover's Expertise: Ensuring Your Magento Store's Financial Health

At Shopping Mover, we understand that such intricate bugs can undermine the financial integrity of your e-commerce operations. Whether you're considering a Magento migration, need a comprehensive system audit, or require expert development to address critical issues like this, our team is equipped to help. We can:

  • Audit Your Current Magento Setup: Identify if your store is affected by this or other hidden financial inconsistencies.
  • Implement Patches and Custom Fixes: Apply necessary code changes and develop robust solutions to correct existing data.
  • Ensure Data Integrity During Migrations: Prevent the transfer of corrupted or inconsistent data when moving to a new Magento version or platform.
  • Provide Ongoing Development & Support: Keep your Magento instance optimized, secure, and financially accurate.

Don't let hidden tax calculation errors impact your bottom line or compromise your financial reporting. Proactive identification and resolution are key to maintaining a healthy and profitable e-commerce business. Contact Shopping Mover today for a consultation and ensure your Magento store operates with precision and accuracy.

Share:

Start with the tools

Explore migration tools

See options, compare methods, and pick the path that fits your store.

Explore migration tools