(written by Grok and reviewed by Max Milbers)

Audience: Shop owners, implementers, and developers who configure taxes, shipment, and payment methods
Status: VirtueMart 3.x / 4.x / 5 — core behaviour (not plugin-specific except where noted)
Related: Methods, Shipment and Payment, Configuration → Checkout

VAT on products is already non-trivial. VAT on shipping and payment fees becomes a real problem as soon as the cart contains more than one VAT rate — food at 7 %, books at 7 %, electronics at 19 %, a free gift at 0 %. Which rate applies to the shipping line? One rate for the whole fee? Or a share of each rate?

VirtueMart answers this with a small, consistent set of rules: the tax field on the method, the shop config “Simplified VAT for shipping”, and — when you edit an order by hand — the same tax list you know from products. This article is the full map of that system.

Contents

1. Why shipping VAT is special

Product VAT is attached to a product (or category, country, shopper group — via calculation rules). Shipping and payment are order-level fees: one amount for the whole cart, not one amount per product line.

When every product uses the same VAT (e.g. only 20 %), shipping VAT is easy: apply 20 % to the shipping net. When products mix rates, shops and tax authorities still need a defined rule. Common approaches in the wild:

  • Fixed rate on shipping (always 20 %, always 0 %, …)
  • Majority / “highest basket share” — one rate wins for the whole shipping fee
  • Proportional split — shipping VAT is split across the product VAT rates according to their share of the goods total

VirtueMart supports all three. The method configuration chooses “fixed / none / follow cart”, and the shop config chooses majority vs proportional when the method follows the cart.

2. Product VAT in one paragraph

VirtueMart calculation rules of kind VatTax (and Tax) are applied to products according to published calc rules (countries, categories, shopper groups, etc.). On a finished order, each product line stores its own product_tax, and the order also stores calculation rules per line (and for the bill). That product-side story is the input for mixed shipping VAT: the cart knows which VAT amounts sit under which calc id, and what share of the goods total they represent.

This article does not cover the full tax/discount matrix (DBTax, DATax, bill rules). It only needs the idea: several VAT rates can be active on one order at once.

3. Tax on a shipment / payment method

On the shipment method (and similarly on many payment methods), the configuration tab has a Tax field. It uses the same tax list as products:

Value Label (English) Meaning for shipping / payment fee
-1 Apply no rule No tax is applied to the method fee. Net fee = gross fee from a tax point of view for that method.
0 (or empty / “default”) Apply default rules Do not force a fixed calc id. Take the VAT picture from the cart (majority or proportional — see below).
> 0 Name of a calc rule (e.g. “Tax 20%”) Always apply that single calculation rule to the whole method fee, independent of product mix.

So -1 is not a mysterious error code: it is the explicit choice “Apply no rule”, shown the same way in product and shipment method edit screens.

Examples

  • Domestic standard VAT shop, only one rate → method tax = that rate, or default rules (same result).
  • Shipping must be tax-free (some B2B / export setups) → method tax = Apply no rule (-1).
  • Shipping always at the standard rate even if the cart is mostly reduced-rate goods → method tax = fixed “Tax 20%”.
  • Shipping should track the goods → method tax = Apply default rules, then decide majority vs proportional in config.

Core implementation (conceptually): if tax_id === -1, no tax rules are loaded for the fee; if a positive id is set, that calc is used alone; otherwise the cart’s product VAT rules are merged and split according to config.

4. Majority vs proportional (shop config)

Under Configuration → Checkout (wording may vary slightly by version):

Config key English label Default
radicalShipPaymentVat Simplified VAT for shipping Enabled (yes)

English tip text (core language):
“The VAT rate for Shipping will be the same as the VAT rate of the items with the highest total net value in the cart.”

That is the majority (sometimes called “radical” / simplified) mode.

Setting Behaviour when method tax = default rules and the cart has mixed VAT
Simplified VAT for shipping = Yes (default) Majority: Find the product VAT rule with the largest subtotal of goods. Apply 100 % of the shipping (and, in the same logic path, often payment) tax at that rate. One shipping tax amount, one winning rate.
Simplified VAT for shipping = No Proportional: Split the shipping net across the product VAT rules by their share of the goods total. Each rate gets a slice of shipping tax. Invoice lines can show more than one tax component related to shipping.

When this config is ignored

  • Method tax is a fixed calc id → always that rate.
  • Method tax is Apply no rule (-1) → no shipping tax at all.

The config only matters when the method is told to follow the cart (default rules).

5. How the cart actually calculates

Simplified flow for a shipment (payment is analogous via the same plugin base):

  1. Plugin computes the net fee (shipment cost, package fee, weight rules, …).
  2. Plugin (or core setCartPrices path) resolves tax rules for that fee:
    • tax_id = -1 → no rules
    • tax_id > 0 → that calc only
    • else → cart product VAT / bill tax rules, with percentages either 100 % for the majority rule or shares for each rule
  3. Tax amounts are stored on the cart prices (shipmentTax, shipmentTaxPerID, …).
  4. On order creation, VirtueMart writes:
    • order_shipment / order_shipment_tax (and payment equivalents)
    • rows in #__virtuemart_order_calc_rules with calc_kind = shipment or payment

Those shipment/payment calc rules use virtuemart_order_item_id = 0. That is intentional: they belong to the order head, not to a product line. Do not “clean them up” as orphans.

6. What you see on the order

Where What it means
Order head order_shipment / order_shipment_tax Net shipping fee and tax amount for the shipment method
Order head order_payment / order_payment_tax Same for payment
Calc rules with calc_kind = shipment or payment and virtuemart_order_item_id = 0 Bill-level (mixed) tax model for fees — fixed rate, majority, or proportional slices as stored at order time
Calc rules with calc_kind = VatTax / Tax and a real item id Product line taxes

Backend order views and invoices summarise product taxes and may fold shipment/payment tax into the bill tax block. When you debug “wrong shipping VAT”, always check both the method’s tax_id and the shop’s simplified/majority switch — and whether the cart really mixed rates.

7. Editing tax on order product lines (backend)

Merchants also change product line tax after the order exists (corrections, reverse charge, goodwill). That is a different screen, but it reuses the same tax list language.

On the order item edit UI there are two supported paths — both must work:

Path What the merchant does What the system does
Automatic Leave Calculate checked; choose a rule in the tax dropdown (product_tax_id), including Apply no rule (-1) Recalculates product_tax from the selected rules (or clears tax when no rule applies)
Manual Uncheck Calculate; type the tax amount into the tax field Stores the entered value as-is (no overwrite from rate calculation)

Dropdown values (same idea as on the method):

  • 0 — Apply default rules
  • -1 — Apply no rule
  • > 0 — specific calc id

Editing product lines does not replace a full re-checkout: shipment tax already stored on the order is a separate head-level value. If you change product mix or VAT by hand and need shipping tax to match a new policy, review shipment/payment tax on the order head as well.

8. Practical recipes

Single VAT rate shop (most common)

  • One published VatTax rule for the shop domain.
  • Shipment method tax: default rules.
  • Simplified VAT for shipping: leave default (Yes) — irrelevant if only one rate exists.

Mixed VAT cart, shipping should follow the “main” goods

  • Shipment method tax: Apply default rules.
  • Config: Simplified VAT for shipping = Yes (majority by highest goods subtotal).

Mixed VAT cart, shipping tax split like the invoice goods

  • Shipment method tax: Apply default rules.
  • Config: Simplified VAT for shipping = No (proportional).
  • Expect multiple tax components related to shipping on detailed invoices.

Shipping always standard rate

  • Shipment method tax: fixed calc id of the standard rate (e.g. Tax 20%).
  • Config majority/proportional: ignored for that method.

No tax on shipping

  • Shipment method tax: Apply no rule (-1).

Correct a product line to tax-free after order

  • Order edit → enable item edit → either dropdown Apply no rule with Calculate on, or Calculate off and type 0.

9. Notes for plugin developers

  • Shipment and payment plugins that use the standard method parameters should expose tax_id via the shared tax list (including -1 / none and default).
  • Prefer the core price pipeline (setCartPrices / calculator) instead of inventing a second VAT model for fees. Merchants already configure majority vs proportional globally.
  • When writing order calc rules for fees, use calc_kind shipment or payment and virtuemart_order_item_id = 0.
  • Display code that labels method tax should treat -1 as “Apply no rule” (core already maps this via COM_VIRTUEMART_PRODUCT_TAX_NONE).

Payment methods that charge a percentage of the order total interact with tax slightly differently on the fee base (progressive vs simple fee formulas). That is about the fee amount, not about which VAT rate is chosen; see also the notes on fee calculation in the methods manual.

10. FAQ

Is a calc rule with item id 0 a bug?
No. For shipment and payment kinds it is the normal head-level tax model (including mixed mode).

Why does shipping use 19 % when half the cart is 7 %?
With default rules + simplified VAT enabled, the rate of the goods group with the higher net subtotal wins for the whole shipping fee. Switch simplified VAT off for proportional split, or set a fixed rate on the method.

What does -1 mean on the method?
Apply no rule — no tax on that fee.

Does payment use the same config?
Yes. The same simplified/majority switch and tax list logic apply to payment methods that go through the shared fee tax path.

Where is this documented in the UI?
Method edit → Tax field; Configuration → Checkout → Simplified VAT for shipping (tooltips). This article is the long-form explanation that the one-line manual entry could not hold.

Related reading

  • Methods, Shipment and Payment — method pattern, standard shipment fields, payment fee formula notes
  • Configuration → Checkout — radicalShipPaymentVat / Simplified VAT for shipping
  • Calculation rules (Taxes) — product-side VatTax setup

Core references for maintainers (not required for shop setup): method fee tax resolution in the shipment/payment plugin base (setCartPrices), bill summarisation (summarizeRulesForBill with shipment/payment handling), order item tax edit in the orders model.