Product EU VAT
Applies destination-based EU VAT to product prices for all 27 member states. Only activates when the resolved delivery destination is an EU member state.
Registration
import { pluginRegistry } from '@unchainedshop/core';
import { ProductEuTaxPlugin } from '@unchainedshop/plugins/pricing/product-eu-tax';
pluginRegistry.register(ProductEuTaxPlugin);
Or register both EU tax adapters (product + delivery) via the country preset:
import { registerEuTaxPlugins } from '@unchainedshop/plugins/presets/countries/eu';
registerEuTaxPlugins();
How It Works
- Resolves the destination country (delivery address → billing address → order country)
- Skips orders whose destination is not an EU member state
- Determines the tax category from:
- Product tags (e.g.,
eu-tax-category:reduced) - Delivery provider configuration (
eu-tax-category) - Falls back to the destination country's standard rate
- Product tags (e.g.,
- Resolves the rate valid at order time from the bundled per-country era tables and adds tax amounts to the pricing sheet
Tax Categories
Category names follow the EU VAT Directive. Every country has standard; the other categories exist only where a member state uses them:
| Category | Example (DE) | Example (FR) |
|---|---|---|
standard | 19% | 20% |
reduced | 7% | 5.5% |
reduced2 | — | 10% |
super_reduced | — | 2.1% |
parking | — | — |
Requesting a category a country does not have falls back to that country's standard rate — never silently to zero. Greece resolves under both GR (ISO) and EL (EU convention).
Rate Data
Rates for all 27 member states are bundled in eu-tax-rates.json as era lists ({ validFrom, rate }), verified against the European Commission's VAT database. The applicable rate follows the order date, so historical recalculations stay correct (including temporary cuts such as Germany's 16% in H2 2020). Rates are never fetched at runtime — updates land as reviewed diffs via the repository's update-tax-rates skill.
Configuration
Via Product Tags
eu-tax-category:reduced
eu-tax-category:super_reduced
Via Delivery Provider
mutation ConfigureDeliveryProvider {
updateDeliveryProvider(
deliveryProviderId: "provider-id"
deliveryProvider: {
configuration: [
{ key: "eu-tax-category", value: "reduced" }
]
}
) {
_id
}
}
Net vs Gross Prices
The adapter handles both net and gross prices:
- Net prices: Tax is added on top (
amount * taxRate) - Gross prices: Tax is extracted from the total (
amount - amount / (1 + taxRate))
Scope
Cross-border regimes are intentionally out of scope: OSS registration thresholds, B2B reverse charge and exemptions should be modeled with dedicated adapters if needed.
Adapter Details
| Property | Value |
|---|---|
| Key | shop.unchained.pricing.product-eu-tax |
| Version | 1.0.0 |
| Order Index | 80 |
| Source | pricing/product-eu-tax/adapter.ts |
Related
- Delivery EU VAT - EU VAT for delivery fees
- Product Swiss Tax - Swiss VAT for products
- Product Pricing - Custom product pricing