Design your price structure

Currencies and tax

Markets, currencies, tax classes — and the net-or-gross question that decides whether a stored amount can be invoiced at all.

An import file arrives from your ERP with 4711-A at 19.90. Nobody wrote down whether that is net or gross, or whether the column for the Swiss subsidiary is CHF or EUR. A stored amount is meaningless until somebody says what currency it is in and whether tax is inside it. This page is about making both of those explicit, and it is the page German B2B teams should read most carefully.

Before you start: you need at least one market. Markets carry the currency and the tax rates. See Languages and markets.

Net or gross: the one fact a price cannot be without

In German B2B, prices are quoted net, zzgl. MwSt. Buyers are businesses, they reclaim input tax, and every catalogue, offer and framework agreement is in net terms. In B2C the same country quotes gross, because consumers must be shown the price they pay.

If you sell to both, or you migrated from a webshop that was built for consumers, you have both conventions in your data. The part that hurts: 19.90 looks identical whether it means "€19.90 plus 19 % tax" or "€19.90 including 19 % tax". The difference is €3.18 per piece, 16 % of the line price.

So the basis has to be stated, not assumed.

Where the basis comes from

The platform answers the question in a fixed order:

OrderSourceSet it in
1The list's own Prices are field (Net / Gross)Order Management › Prices › Price lists › list › Edit list
2The legacy tax_included flag on the listNot editable in the Cockpit; leave it alone
3The tenant setting Stored prices areThe Prices app settings

Because a list is created without a stated basis, the tenant setting is what answers for every list that stays silent. A list with no basis shows a warning banner saying so.

State the basis on every list explicitly. Relying on the tenant default works until the day somebody creates one gross list among your net ones, or changes the tenant setting for a good reason. Then every silent list changes meaning at once. The amounts do not move; only their meaning does. That is the kind of error that reaches invoices.

The practical rule

  • Net lists for everything B2B. Set Prices are to Net (excl. tax).
  • Never mix bases inside one list. If you need gross amounts for a consumer-facing channel, that is a second list, not a second convention in the same one.
  • What the storefront displays is a presentation decision: a net-priced shop may still show "€19.90 zzgl. MwSt." and a gross line in the cart. What must never vary is what the stored number means.

Markets, currencies and rates

A market is the container for a selling territory. It carries:

  • an accounting currency (ISO 4217: EUR, CHF),
  • its locales (language and country combinations),
  • any additional currencies it trades in,
  • and its tax classes with their rates.

Create and edit markets under Configuration › Markets. The market code is a stable slug (de, at, ch) that other apps key on; do not rename it once anything refers to it.

Tax classes

Tax classes live per market under Configuration › Tax classes. Each has a code, a name and a rate in percent. A typical German market:

CodeNameRate
standardStandardsatz19.00
reducedErmäßigter Satz7.00
zeroNullsatz0.00
exemptSteuerbefreit0.00

Keep zero and exempt separate even though both compute to nothing. They are different things on an invoice and different things to your accountant.

The class a given article uses comes from the product's tax class in the catalogue, and the rate for that class comes from the buyer's market. That separation is the point: one product, correct rate in every country, without a per-country price field.

The rate is per market, so the market must be known. If a price call cannot determine the buyer's market, the tax rate comes back as unknown, not as zero. Do not let an integration quote a gross price from an unknown rate; it will be the net price, and it will be on a document.

Multiple currencies

Currency is a property of the price list, and resolution only ever considers lists in the buyer's currency. There is no conversion at read time.

This means: to sell in CHF you create a CHF price list and put CHF amounts in it. You do not convert EUR at runtime.

That is the right behaviour for B2B. A converted price moves every day with the exchange rate, which no procurement department will accept in a framework agreement, and it produces prices like 18.4732. A Swiss price list is a separate price book with its own numbers, its own rounding and its own review date.

What that costs you: foreign-currency lists do not maintain themselves. When you raise EUR prices, the CHF list does not move. Put every currency list in the same annual price round, and write the review date somewhere you will see it.

To add a currency to a market, go to Configuration › Markets, open the market and add it under its currencies. Then create the matching price list.

Decimals and rounding

Two settings decide how computed amounts land. Set them once rather than arguing about them later:

  • Price decimals: how many places every derived amount (net, gross, line total) is rounded to. Two is normal. Stored catalogue prices are returned exactly as typed, so a price per 1,000 pieces keeps its four decimals.
  • Rounding mode: half up is the commercial default; half to even (banker's rounding) is required on invoices in some jurisdictions and cannot be reproduced by rounding twice.

Both are covered in Rounding, defaults and resolution rules.

What to check

  • Every market has a currency, and at least one tax class marked as its default.
  • Every price list shows a value in the Net / gross column, with no blanks.
  • Your rates are current. German rates change rarely; Austrian, Swiss and reduced rates for specific goods change more often than anyone expects.
  • Your products carry a tax class. Articles without one fall back to the market's default class, which may not be the one you want; check this with whoever owns your product import.

Next