> Documentation index: [Saleor](/llms.txt) · [This section](/developer/llms.txt)
> Source: https://docs.saleor.io/developer/price-calculation

# Price Calculation

note

The calculations described in this section are applicable both to checkout and order.

<a id="introduction"></a>

## Introduction

There are multiple factors affecting the final price of an order. In a nutshell, Saleor first seeks the variant price and shipping cost for a specific channel, then applies all discounts, and finally calculates taxes.

```mermaid
sequenceDiagram
    Undiscounted price->>+Base price: apply catalogue promotion
    Undiscounted price->>+Base price: apply line-level voucher
    Undiscounted price->>+Base price: apply manual line discount
    Base price->>+ Untaxed price: apply order promotion
    Base price->>+ Untaxed price: apply order-level voucher
    Base price->>+ Untaxed price: apply manual order discount
    Untaxed price->>+ Final price: apply taxes
```

<a id="undiscounted-price"></a>

## Undiscounted price

​​Firstly, Saleor is looking for a variant price and shipping cost for a specific channel. There is an option to override the prices by providing a `price` argument in [orderLineCreateInput](/api-reference/orders/inputs/order-line-create-input.md), [checkoutLineInput](/api-reference/checkout/inputs/checkout-line-input.md) or [checkoutLineUpdateInput](/api-reference/checkout/inputs/checkout-line-update-input.md). In case of checkout mutations, overriding prices can be done only by app with `HANDLE_CHECKOUTS` permission. Whether the price was taken directly from the channel or overridden, it is reflected as an undiscounted price.

<a id="discount-application"></a>

## Discount application

<a id="base-price"></a>

### Base price

We first apply [`line-level discounts`](/developer/discounts/overview.md#level) which decrease unit prices, resulting in the so-called `base price`:

`base_unit_price` = `undiscounted_price` - (`manual_line_discount` or (`catalogue_promotion` + `line-level_voucher`))

`base_line_price` = `base_unit_price` \* `quantity`

`base_subtotal` = `Σ(base_line_prices)`

`base_shipping_price` = `undiscounted_shipping_price` - `shipping_voucher`

warning

Some of the line discounts are mutually exclusive:

-   manual line discount overrides all other line discounts
-   only one voucher can be applied

<a id="untaxed-price"></a>

### Untaxed price

Having line-level discounts applied, we can sum up all the lines and calculate the base subtotal, which will be the basis for applying [`order-level discounts`](/developer/discounts/overview.md#level):

`untaxed_subtotal` = `base_subtotal` - (`manual_order_discount` or `entire_order_voucher` or `order_promotion`)

`untaxed_shipping` = `base_shipping_price` - `manual_order_discount`

warning

All order-level discounts are mutually exclusive and can't be combined.

-   The entire order voucher decreases the subtotal price and doesn't affect the shipping price.
-   The order promotion can either decrease the subtotal or grant a gift, which will be added to the order as an extra order line with zero price.
-   The manual discount decreases both subtotal and shipping prices. If the fixed value is provided, Saleor proportionally computes the subtotal and shipping portion.

After the application, when using flat rates or Avatax plugin tax strategies, the discounts are proportionally propagated to the order lines, decreases the unit and total prices. When a custom tax app is used to calculate taxes, this is done by the app itself.

<a id="tax-calculation"></a>

## Tax calculation

After handling the discounts, Saleor calculates taxes to reflect gross prices (or net if [pricesEnteredWithTax](/developer/taxes.md#tax-configuration) is set to True). Tax calculation can be omitted by [chargeTaxes](/developer/taxes.md#tax-configuration) setting or [tax exemption API](/developer/taxes.md#tax-exemption). Saleor offers three tax calculation strategies.

<a id="assumptions"></a>

### Assumptions

-   The `line.totalPrice` is the primary source of truth for price calculations.
-   Taxes are applied at the line level, with `line.totalPrice` reflecting all applied discounts.
-   The `line.unitPrice` is calculated from `line.totalPrice` by dividing it by the `line.quantity`. However, due to rounding, the product of `line.unitPrice` and `line.quantity` may not exactly equal `line.totalPrice`.
-   The `order.total` is determined as the sum of all `line.totalPrice` values.

<a id="flat-rates"></a>

### Flat rates

When using [`flat rates`](/developer/taxes.md#flat-rates), all the calculations are done by Saleor itself. It applies static tax rates, defined by the user, associated with products, product types, shipping methods or countries. Taxes are applied to the line total prices. The taxed `unit_price` is calculated by dividing the taxed `total_price` by the line `quantity`.

<a id="tax-app"></a>

### Tax app

Over [CHECKOUT\_CALCULATE\_TAXES](/developer/extending/webhooks/synchronous-events/tax.md#checkout-taxes) and [ORDER\_CALCULATE\_TAXES](/developer/extending/webhooks/synchronous-events/tax.md#order-taxes) sync webhooks, Saleor serves [`TaxableObject`](/api-reference/taxes/objects/taxable-object.md), which can be used as a payload for [`custom tax apps`](/developer/extending/webhooks/synchronous-events/tax.md). In return, Saleor expects final line prices and shipping price, with all discounts included and tax rates applied. The prices obtained from the tax app are considered final and take precedence over both net and gross prices. The only thing Saleor calculates are undiscounted gross prices based on received tax rates.

<a id="avatax-plugin"></a>

### Avatax plugin

warning

The Avatax plugin will be removed in Saleor 4.0.

Avatax plugin is a built-in integration with Avalara. Similar to custom tax apps, final data relies on extrenal tax service, but in this case Saleor is responsible for handling Avalara response data and applying it to the prices.
