Skip to Content

Tax (VAT)

Hoikka uses a gross pricing strategy where all prices include VAT. This follows Finnish e-commerce conventions.

Key Concepts

  • Gross prices: All stored prices include VAT
  • Back-calculation: Net prices are calculated from gross at checkout
  • Group-based exemption: Customers in a tax-exempt group pay net prices

Tax Rates

Finnish VAT rates are supported:

CodeRateDescription
standard25.5%Default (most products)
food13.5%Food items
books13.5%Books, newspapers
zero0%Exports, exempt

Unknown tax codes fall back to the standard rate (0.255). Rates are stored in the database as integer basis points with 4 decimals (0.255 → 2550); business logic works with decimals.

Product Tax Code

Tax codes live on categories. A product’s tax code is resolved from its first assigned category at cart/checkout time; products without a category use standard:

import { categoryService } from "$lib/server/services/categories.js"; const taxCode = await categoryService.getProductTaxCode(productId); // e.g. "food"

Tax Calculation

Tax is back-calculated from the gross price:

import { taxService } from "$lib/server/services/tax.js"; // Calculate tax breakdown const result = taxService.calculateTax(2510, 0.255); // { gross: 2510, net: 2000, tax: 510 } // Formula: // net = gross / (1 + taxRate) // tax = gross - net

Order Tax Fields

Orders track tax information:

order = { subtotal: 5020, // Gross subtotal (VAT-inclusive) taxTotal: 1020, // Total VAT amount totalNet: 4000, // Subtotal minus VAT isTaxExempt: false, // Group-based exemption flag total: 6020 // Final total };

Order Line Tax Fields

Each order line stores tax details:

orderLine = { unitPrice: 2510, // Gross unit price unitPriceNet: 2000, // Net unit price lineTotal: 5020, // Gross line total lineTotalNet: 4000, // Net line total taxCode: "standard", taxRate: 2550, // basis points, 4 decimals (0.255) taxAmount: 1020 };

B2B Tax Exemption

Tax exemption is group-based. A customer group with isTaxExempt = true makes all its members tax-exempt:

// Check exemption — looks up customer's groups for isTaxExempt flag const isExempt = await taxService.isCustomerTaxExempt(customerId); // For exempt customers: // - Prices shown without VAT // - taxTotal = 0 // - order.isTaxExempt = true

To make customers tax-exempt: create a customer group with isTaxExempt enabled in Admin > Customers > Groups, then add the customer to that group.

Admin: Setting Tax Code

Tax codes are set on categories:

  1. Admin > Categories, edit a category
  2. Select the “Tax Rate” dropdown
  3. Choose: Standard VAT (25.5%), Food VAT (13.5%), Books VAT (13.5%), or Zero VAT (0%)

Checkout Display

The checkout shows tax breakdown:

Subtotal: 50.20 EUR VAT (included): 10.20 EUR Shipping: 5.00 EUR ───────────────────────── Total: 55.20 EUR

For tax-exempt customers:

Subtotal: 40.00 EUR VAT: Tax exempt (B2B) Shipping: 5.00 EUR ───────────────────────── Total: 45.00 EUR Net amount: 45.00 EUR (VAT 0%)

Tax Service API

import { taxService } from "$lib/server/services/tax.js"; // Get rate for a tax code const rate = await taxService.getTaxRate("standard"); // 0.255 // Get all available rates const rates = await taxService.getAllTaxRates(); // Calculate tax from gross price const { gross, net, tax } = taxService.calculateTax(2510, 0.255); // Calculate line item tax const lineTax = taxService.calculateLineTax(grossUnitPrice, quantity, taxRate, isTaxExempt); // Check customer exemption (group-based) const exempt = await taxService.isCustomerTaxExempt(customerId); // Seed default rates (run once) await taxService.seedDefaultRates();
Last updated on