# Configuring Sales Taxes in ERPNext - Kategorie: ERPNext - Autor: Raffael Meyer - Veröffentlicht am: April 29, 2026 This guide walks through the five DocTypes involved in sales tax configuration and the order in which to set them up. It covers how to configure the tax engine from the UI. For developers who need to extend behaviour beyond what data and settings can express, see the companion post [Customizing Sales Tax Calculation in ERPNext](/blog/erpnext/customizing-sales-tax-calculation). ## The Big Picture ERPNext picks the right tax in two stages: 1. **Resolution** — for a given customer, address, item, and date, ERPNext decides *which* tax template applies and *which* per-item rate overrides kick in. 2. **Calculation** — once the tax rows and per-item rates are stamped onto the document, the engine applies the formulas. Five DocTypes drive resolution: | DocType | Purpose | |---|---| | **Tax Category** | A label that groups customers, addresses, items, and templates by jurisdiction or scenario (e.g. "Domestic", "EU B2B", "Export"). | | **Sales Taxes and Charges Template** | The reusable header-level tax table that gets copied onto a **Sales Invoice**, **Sales Order**, **Quotation**, or **Delivery Note**. | | **Item Tax Template** | A per-item rate map that overrides individual rates from the header template (e.g. reduced VAT on books). | | **Tax Rule** | A routing rule that maps `(party, address, item, date) → template`. | | **Accounts Settings** | Global switches that change resolution behaviour. | ## Recommended Setup Order 1. Create your **Tax Category** records first. 2. Build the GL **Account** records you need (under "Duties and Taxes" or "Tax Assets"). 3. Create one or more **Sales Taxes and Charges Template** per scenario. 4. Create **Item Tax Template** records for special-rate items (reduced VAT, exempt, zero-rated). 5. Attach **Item Tax Template** rows to **Item** or **Item Group** masters. 6. Optionally create **Tax Rule** records for automatic routing. 7. Tune the global behaviour in **Accounts Settings**. --- ## 1. Tax Category Open **Tax Category** and create one record per tax scenario you need to distinguish. Typical entries for a German company: - "Inland" (domestic sales) - "EU B2B" (intra-community supply) - "Export" (third-country export) Fields: - _Title_ (`title`) — the user-facing name, e.g. "EU B2B". - _Disabled_ (`disabled`) — leave unchecked. Tax Category is a pure tag with no logic of its own. It propagates from **Customer** → **Address** → document → tax routing. --- ## 2. Sales Taxes and Charges Template This is the header-level table that gets copied onto a **Sales Invoice**. ### Header fields - _Title_ (`title`) — descriptive name, e.g. "Inland 19% — My Co". - _Company_ (`company`) — the company this template belongs to. - _Tax Category_ (`tax_category`) — link to the **Tax Category** this template serves. Only one *enabled* template per `(company, tax_category)` is allowed. - _Is Default_ (`is_default`) — check exactly one template per company as the fallback when no **Tax Rule** matches. Saving with this checked clears the flag on every other template for the same company. - _Disabled_ (`disabled`) — mutually exclusive with _Is Default_. ### Tax row fields (the _Taxes_ child table) Each row in _Taxes_ (`taxes`) represents one tax line that will appear on the invoice. - _Type_ (`charge_type`) — pick one of: - "On Net Total" — percentage VAT/GST. Use this for almost all standard tax rows. - "On Previous Row Amount" — percentage applied to a prior tax row's amount (surcharge on a surcharge). - "On Previous Row Total" — percentage applied to net + all prior tax rows (compound tax, e.g. Canadian PST on top of GST). - "Actual" — a fixed amount distributed proportionally across items. - "On Item Quantity" — per-unit excise/duty. - _Account Head_ (`account_head`) — the GL **Account** to post to. Must have _Account Type_ set to "Tax". - _Rate_ (`rate`) — the percentage (e.g. 19 for 19 %), or per-unit amount for "On Item Quantity", or fixed sum for "Actual". - _Description_ (`description`) — what appears on the printed invoice, e.g. "USt. 19%". - _Reference Row #_ (`row_id`) — only for "On Previous Row Amount" / "On Previous Row Total"; the 1-based row number to reference. - _Considered Tax Included in Basic Rate_ (`included_in_print_rate`) — check when item prices are gross (tax-inclusive). The engine then back-extracts the net. Only the *first* tax row in a contiguous sequence may be inclusive. - _Add or Deduct_ (`add_deduct_tax`) — "Add" or "Deduct". Mostly relevant on **Purchase Taxes and Charges Templates** for reverse-charge / _innergemeinschaftlicher Erwerb_ scenarios, where you pair an "Add" row on the output VAT account with a "Deduct" row on the input VAT account at the same rate; the GL postings happen but the net P&L impact is zero. Rarely useful on the sales side — see the EU intra-community pattern below. - _Consider Tax or Charge for_ (`category`) — "Total", "Valuation", or "Valuation and Total". For sales documents leave on "Total". - _Cost Center_ (`cost_center`) — the cost center that receives the GL allocation. ### Common patterns **Domestic 19 % VAT (Germany)**: one row, _Type_ "On Net Total", _Rate_ "19", _Account Head_ "Umsatzsteuer 19 % - My Co". **Tax-inclusive prices**: same row, plus _Considered Tax Included in Basic Rate_ checked. **EU intra-community supply — _innergemeinschaftliche Lieferung_** (sales side): no tax rows at all. The supply is tax-free under §4 Nr. 1b UStG; the recipient self-accounts VAT in their own country. The invoice carries both VAT IDs and a reverse-charge note ("Steuerschuldnerschaft des Leistungsempfängers") in the print format — not in the tax math. Optionally add a single 0 % row pointing at a "Tax-free EU sale" account head if your accountant prefers a visible reporting line. **Reverse-charge paired Add/Deduct rows** belong on a **Purchase Taxes and Charges Template** for _innergemeinschaftlicher Erwerb_, where the buyer self-accounts VAT: one row "Add" on the output VAT account and one row "Deduct" on the input VAT account, same rate. Net P&L impact zero, GL audit trail preserved. This pattern does not apply to a Sales Taxes and Charges Template. **Compound tax (Canada GST + PST)**: row 1 GST "On Net Total" 5 %, row 2 PST "On Previous Row Total" 7 % with _Reference Row #_ "1". --- ## 3. Item Tax Template Use this when *some* items inside an invoice need a different rate than the header template provides — e.g. books at reduced VAT, exempt services, zero-rated exports. ### Header fields - _Title_ (`title`) — e.g. "Reduced 7%" or "Exempt". - _Company_ (`company`) — owning company. - _Disabled_ (`disabled`). ### Tax row fields (the _Taxes_ child table) Each row maps a single GL **Account** to a rate: - _Tax Type_ (`tax_type`) — link to a tax **Account**. Must match an _Account Head_ that appears in the **Sales Taxes and Charges Template**. - _Tax Rate_ (`tax_rate`) — the rate to use for this item, e.g. "7" or "0". - _Is Not Applicable_ (`not_applicable`) — check if this account head should be entirely skipped for the item (different from rate "0", which still posts a zero-amount line). ### How it overrides the header template The header template defines *which tax accounts exist* on the invoice. The Item Tax Template defines *which rate* each account uses *for the matched item*. So if a German invoice has both "USt. 19 %" and "USt. 7 %" rows in the header template, an item bound to Item Tax Template "Ermäßigt 7 %" applies rate 0 to the 19 % row and rate 7 to the 7 % row. ### Attaching to items Open the **Item** master and scroll to the _Item Tax_ table (or do the same on **Item Group** to apply to a whole group). Each row holds: - _Item Tax Template_ (`item_tax_template`) — which template to apply. - _Tax Category_ (`tax_category`) — which **Tax Category** this binding is for. Leave empty to match any. - _Valid From_ (`valid_from`) — optional start date. - _Minimum Net Rate_ (`minimum_net_rate`) — optional price-band lower bound. - _Maximum Net Rate_ (`maximum_net_rate`) — optional price-band upper bound. ERPNext walks the Item's table first, then the **Item Group** hierarchy, picking the most specific row whose validity window and price band match. --- ## 4. Tax Rule A **Tax Rule** automatically picks the right **Sales Taxes and Charges Template** when a **Customer** and **Address** are entered. Without rules, ERPNext falls back to the company default template. ### Header fields - _Tax Type_ (`tax_type`) — "Sales" or "Purchase". - _Sales Tax Template_ (`sales_tax_template`) — for sales rules. - _Purchase Tax Template_ (`purchase_tax_template`) — for purchase rules. - _Tax Category_ (`tax_category`) — must match exactly. Leave empty to match documents without a tax category. - _Use for Shopping Cart_ (`use_for_shopping_cart`) — controls whether this rule applies to webshop checkout. Default checked. - _Priority_ (`priority`) — tie-breaker when multiple rules match equally specifically. Lower number wins. - _Valid From_ (`from_date`) and _Valid Upto_ (`to_date`) — date window. - _Company_ (`company`) — restrict to one company. ### Filter fields You can scope the rule to any combination of: - _Customer_ (`customer`), _Customer Group_ (`customer_group`) - _Supplier_ (`supplier`), _Supplier Group_ (`supplier_group`) (purchase rules only) - _Item_ (`item`), _Item Group_ (`item_group`) - Billing address: _Billing City_ (`billing_city`), _Billing County_ (`billing_county`), _Billing State_ (`billing_state`), _Billing Country_ (`billing_country`), _Billing Zipcode_ (`billing_zipcode`) - Shipping address: _Shipping City_ (`shipping_city`), _Shipping County_ (`shipping_county`), _Shipping State_ (`shipping_state`), _Shipping Country_ (`shipping_country`), _Shipping Zipcode_ (`shipping_zipcode`) ### How matching works ERPNext picks the rule with the most populated filter fields that match the document. Specificity always beats _Priority_. _Priority_ only breaks ties between rules with the same number of matching filters. Two enabled rules with the same priority, identical filter values, and overlapping date ranges produce a `ConflictingTaxRule` error on save. ### Practical examples **EU intra-community sale**: - _Tax Type_ "Sales" - _Tax Category_ "EU B2B" - _Billing Country_ left empty (the **Tax Category** on the **Address** is what carries the routing) - _Sales Tax Template_ "EU Intra-Community — My Co" **Domestic invoice catch-all**: - _Tax Type_ "Sales" - _Tax Category_ "Inland" - _Sales Tax Template_ "Inland 19% — My Co" - _Priority_ "10" **Specific large customer overrides everything**: - _Tax Type_ "Sales" - _Customer_ "Acme GmbH" - _Tax Category_ "Inland" - _Sales Tax Template_ "Inland 19% — Acme — My Co" - _Priority_ "1" --- ## 5. Accounts Settings Open **Accounts Settings** for the global switches that affect tax behaviour. - _Determine Address Tax Category From_ (`determine_address_tax_category_from`) — "Billing Address" (default) or "Shipping Address". Decides which **Address** the document inherits its **Tax Category** from when both are present. Important for shipped goods where the tax follows the destination. - _Automatically Add Taxes and Charges from Item Tax Template_ (`add_taxes_from_item_tax_template`) — default on. When an item references a tax account that isn't yet in the document's _Taxes_ table, ERPNext auto-appends a row so the rate from the **Item Tax Template** can be applied. - _Automatically Add Taxes and Charges from Master_ (`add_taxes_from_taxes_and_charges_template`) — default off. When on, an empty taxes table is auto-populated from the resolved template. Mutually exclusive with the above setting. - _Round Tax Amount Row-wise_ (`round_row_wise_tax`) — default off. When on, each per-item tax contribution is rounded before being summed; useful where local rules require rounded line items but may cause sub-cent drift on totals. - _Book Tax Loss on Early Payment Discount_ (`book_tax_discount_loss`) — splits early-payment discount loss into income vs tax components. Tick if your jurisdiction requires the VAT portion of an early-payment discount to be reversed separately. Also set on the **Company** record: - _Cost Center_ (`cost_center`) — used as the default _Cost Center_ on auto-appended tax rows. - _Round Off Account_ (`round_off_account`) and _Round Off Cost Center_ (`round_off_cost_center`) — destination for the rounding adjustment GL entry. - _Default Currency_ (`default_currency`) — anchors all base-currency conversions. --- ## How They Work Together When a user creates a **Sales Invoice**: 1. The user picks the **Customer**. ERPNext reads the **Customer**'s _Tax Category_, then checks the chosen **Address** (per _Determine Address Tax Category From_) and lets the **Address**' _Tax Category_ override the customer's. 2. ERPNext searches **Tax Rule** records for the most specific match given the customer, addresses, **Tax Category**, item group, and posting date. The winning rule's _Sales Tax Template_ is copied onto the invoice's _Sales Taxes and Charges Template_ field, and its _Taxes_ rows are copied into the document. 3. If no rule matches, ERPNext falls back to the company default template (the one with _Is Default_ checked). 4. For each item the user adds, ERPNext walks the **Item**'s _Item Tax_ table (then the **Item Group** hierarchy) to find the matching **Item Tax Template**, filtered by the document's **Tax Category**, the posting date, and the price band. 5. The matched **Item Tax Template** rates are stamped onto the item row. 6. On save, the calculation engine applies each tax row's _Type_ formula to each item, honouring _Considered Tax Included in Basic Rate_, _Add or Deduct_, and rounding settings. --- ## Worked example: Reduced VAT on a specific item Goal: customer **"Acme GmbH"** with _Tax Category_ "Inland" should pay 7 % VAT on item _"Reduced-Rate Widget"_ (`reduced_rate_widget`) instead of the standard 19 %. This is a pure-data problem — no code, no scripts, no overrides: 1. Confirm the standard **Sales Taxes and Charges Template** "Inland 19% — My Co" already includes a row for both _Umsatzsteuer 19 %_ and _Umsatzsteuer 7 %_. If not, add the 7 % row with _Type_ "On Net Total" and _Rate_ "7". 2. Create an **Item Tax Template** with _Title_ "DE Reduced 7%" and two rows in its _Taxes_ child table: - _Tax Type_ "Umsatzsteuer 19 %", _Is Not Applicable_ checked. - _Tax Type_ "Umsatzsteuer 7 %", _Tax Rate_ "7". 3. Open the **Item** "reduced_rate_widget" and add an _Item Tax_ row with _Item Tax Template_ "DE Reduced 7%" and _Tax Category_ "Inland". When you create a **Sales Invoice** for "Acme GmbH" with this item, ERPNext applies the standard "Inland 19% — My Co" template at the header level, then overrides per-item: the 19 % row is skipped entirely for this line, and the 7 % row uses rate 7. The breakdown shows _Umsatzsteuer 7 %_ populated and _Umsatzsteuer 19 %_ untouched by this item — exactly the behaviour you wanted, with no code written. If you also need "Acme GmbH" to *automatically* default to a different header template than other customers, add a **Tax Rule** with _Customer_ "Acme GmbH" and the alternative _Sales Tax Template_. Customer specificity beats the company-default fallback. ### How the override actually works Think of the **Item Tax Template** as a **partial mask** over the header template's rates: - The header template defines *which* tax accounts appear on the invoice and the **default rate** for each. - For each item line, ERPNext overlays the matched **Item Tax Template** on top: any account head listed in the template uses the template's rate; any account head **not** listed falls through to the header rate. Without an entry for _Umsatzsteuer 19 %_ in the Item Tax Template, the 19 % header rate would still apply to the line and you'd get both 19 % *and* 7 % VAT on this item. So you need a row that suppresses the default — and you have two ways to do it, with different reporting consequences: | Approach | Engine behaviour | Tax breakup | 19 % taxable base | |---|---|---|---| | _Is Not Applicable_ checked | Short-circuits the row for this item; no posting at all under that account head | No entry for the item under _Umsatzsteuer 19 %_ | Item is **excluded** from the 19 % row's net total | | _Tax Rate_ "0" | Runs the formula with rate 0 | A zero-amount entry under _Umsatzsteuer 19 %_ | Item **is included** in the 19 % row's net total | For a reduced-rate or exempt item, _Is Not Applicable_ is almost always the right choice: the 19 % tax simply does not apply, and you don't want VAT reports or per-account net totals to count this revenue under the 19 % bucket. Reach for _Tax Rate_ "0" only when the item really *is* taxable under that account but the rate happens to be zero (e.g. zero-rated exports tracked under the same account head as standard sales) — i.e. when the item should still appear in that account's reporting base. Two configuration patterns follow from the mask model: 1. **Header-as-default** (used in the example above) — the header carries realistic default rates; Item Tax Templates list only the accounts they want to override or suppress. 2. **Header-as-skeleton** — set every header row to rate "0" and let Item Tax Templates be the sole source of truth. Useful when essentially every item has a template; risky otherwise, because an item without a template silently gets zero tax. If you enable _Automatically Add Taxes and Charges from Item Tax Template_ (`add_taxes_from_item_tax_template`) in **Accounts Settings**, ERPNext also auto-appends any account head referenced by an item's template that is missing from the header — as a row with _Type_ "On Net Total" and _Rate_ "0", marked `set_by_item_tax_template`. The actual rate then comes entirely from the item template. This effectively materializes pattern 2 on demand. --- ## Special Scenarios ### Inclusive (gross) prices Tick _Considered Tax Included in Basic Rate_ on the relevant tax row in the **Sales Taxes and Charges Template**. Item prices entered on the invoice are then treated as gross. Only the first tax row in a sequence may be inclusive. ### EU intra-community supply (Germany / France / etc.) Two distinct flows that are often confused — handle them separately. **Sales side — _innergemeinschaftliche Lieferung_ (you ship to an EU B2B customer):** 1. Create a dedicated **Tax Category** "EU B2B". 2. Build a **Sales Taxes and Charges Template** with **no tax rows** (or a single 0 % row pointing at a "Tax-free EU sale" account head for reporting hygiene). 3. Create a **Tax Rule** that maps **Tax Category** "EU B2B" to this template. 4. Tag EU customer **Address** records with _Tax Category_ "EU B2B". 5. Add the reverse-charge note to the print format and ensure both VAT IDs are visible. The Zusammenfassende Meldung (EC Sales List) is a separate reporting concern: it filters on _Tax Category_ + customer VAT ID, not on tax rows. **Purchase side — _innergemeinschaftlicher Erwerb_ (you receive from an EU supplier):** build a **Purchase Taxes and Charges Template** with paired _Add or Deduct_ rows on the same rate so the self-accounted VAT posts to both output and input VAT accounts and the grand total does not change. This is the only place the paired-row pattern applies. ### Reduced rate items (books, food, medical) Create an **Item Tax Template** "Reduced" containing the reduced-rate account at the lower rate and the standard-rate account at "0". Attach this template to the relevant **Item** or **Item Group** records. ### Tax-exempt items Use _Is Not Applicable_ on every account-head row inside the **Item Tax Template** so those tax rows are skipped entirely for the item. ### Country-mandated integer tax amounts (India, etc.) Configure a **Round Off Tax Account** record on the company so the engine rounds those tax accounts to integer values. ### Recurring invoices via Subscription Subscriptions snapshot the **Sales Taxes and Charges Template** when they are created. Changes to **Tax Rule** or default templates do **not** propagate to existing subscriptions — open the **Subscription** record and update _Sales Tax Template_ manually if rates change. --- ## Validation Errors and What They Mean - "Conflicting Tax Rule" — two **Tax Rule** records have the same priority, the same filters, and overlapping date ranges. Adjust _Priority_ or tighten one of the filter fields. - "Only one default Sales Taxes and Charges Template per company allowed" — uncheck _Is Default_ on the older template before saving the new one. - "Cannot enable both _Disabled_ and _Is Default_" — they are mutually exclusive. - "First Row Type cannot be 'On Previous Row Amount/Total'" — the first row of _Taxes_ has nothing to reference; switch its _Type_ to "On Net Total" or "Actual". - "Inclusive tax must be in the first row" — uncheck _Considered Tax Included in Basic Rate_ on later rows or move the row to the top. --- ## Quick Checklist Before going live with sales tax in a new ERPNext company: - All required GL **Account** records exist with _Account Type_ "Tax". - **Tax Category** records cover every distinct tax scenario. - At least one **Sales Taxes and Charges Template** has _Is Default_ checked. - Reduced-rate / exempt items have **Item Tax Template** rows attached at the **Item** or **Item Group** level. - **Tax Rule** records cover the routing scenarios that cannot be expressed as company defaults. - **Accounts Settings** _Determine Address Tax Category From_ matches your jurisdiction's place-of-supply rule. - **Company** has _Round Off Account_ and _Round Off Cost Center_ set. - A test **Sales Invoice** for each scenario produces the expected _Taxes_ table and grand total. --- Full, layouted page for human readers: https://www.alyf.de/blog/erpnext/configuring-sales-taxes