---
title: Customizing price rounding
related:
  - https://docs.kentico.com/13/configuring-xperience/managing-sites/configuring-settings-for-sites/settings-e-commerce.md
  - https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-currencies.md
  - https://docs.kentico.com/13/e-commerce-features/customizing-on-line-stores/customizing-tax-calculation.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

When performing operations with price values (for example calculation of [taxes](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-taxes.md) and [discounts](https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/discounts.md), [currency conversions](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-currencies/configuring-exchange-rates.md), etc.), the system rounds the result according to the number of decimal places allowed by the [configuration of each currency](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-currencies.md).

By default, you can configure the type of price rounding via settings:

1. Open the **Store configuration** or **Multistore configuration** application.
2. Navigate to the **Store settings -> General** tab.
3. Select one of the **Price rounding** options:
   - **Mathematical** – standard rounding to the nearest number, with midpoint values rounded up (toward the nearest number that is away from zero).
   - **Truncate** – all values are rounded down (decimal numbers beyond the allowed limit are discarded).
   - **Financial** – standard rounding to the nearest number, with midpoint values rounded toward the nearest even number.
4. Click **Save**.

If the default options do not fulfill the requirements of your store, you need to customize the Xperience rounding functionality.

## Customizing rounding globally

To customize the price rounding used throughout the entire system:

1. Prepare an assembly (_Class Library_ project) with class discovery enabled in your Xperience solution (or use an existing one). See [Adding custom assemblies](https://docs.kentico.com/13/custom-development/adding-custom-assemblies.md).
   - Reference the project from both your live site and Xperience administration (_CMSApp_) projects.
2. Create a new class that implements the **IRoundingService** interface (found in the _CMS.Ecommerce_ namespace).
3. Implement the **Round** method according to your requirements.
4. Create a new class that implements the **IRoundingServiceFactory** interface (found in the _CMS.Ecommerce_ namespace).
5. Implement the **GetRoundingService** method for the factory class.
6. Register your _IRoundingServiceFactory_ implementation using the **RegisterImplementation** assembly attribute.

The customized rounding affects both price values displayed in product catalogs on the live site (when using the [appropriate API](https://docs.kentico.com/13/e-commerce-features/developing-on-line-stores/displaying-product-listings.md)) and price calculations during the checkout process.

### Example – Custom cash rounding

The following example demonstrates how to implement custom [cash rounding](https://en.wikipedia.org/wiki/Cash_rounding) of all price values. The example rounds values to the number of decimal places allowed by the [configuration of each currency](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-currencies.md), with the last digit always rounded to the nearest multiple of **5**.

Prepare an assembly (_Class Library_ project) with class discovery enabled in your Xperience solution (or use an existing one). See [Adding custom assemblies](https://docs.kentico.com/13/custom-development/adding-custom-assemblies.md).

- Reference the project from both your live site and Xperience administration (_CMSApp_) projects.

Continue by creating custom implementations of the **IRoundingService** and **IRoundingServiceFactory** interfaces:

1. Add a new class under the custom project, implementing the _IRoundingService_ interface.

   ```csharp

   using System;

   using CMS.Ecommerce;

   public class CustomRoundingService : IRoundingService
   {
       public decimal Round(decimal price, CurrencyInfo currency)
       {
           // Gets the number of allowed decimal places for the requested currency
           int numberOfDecimalPlaces = currency.CurrencyRoundTo;

           // Prepares a basic multiplier that ensures rounding to the required number of decimal places
           decimal multiplier = Convert.ToDecimal(Math.Pow(10, numberOfDecimalPlaces));

           // Prepares a "cash rounding" multiplier that ensures rounding to either '5' or '0' for the last decimal place
           decimal cashRoundingMultiplier = multiplier / 5m;

           // Returns the rounded price values
           return Math.Round((price * cashRoundingMultiplier), MidpointRounding.AwayFromZero) / cashRoundingMultiplier;
       }
   }

   ```
2. Add a new class under the custom project, implementing the _IRoundingServiceFactory_ interface.

   ```csharp

   using CMS;
   using CMS.Ecommerce;

   // Registers the custom implementation of IRoundingServiceFactory
   [assembly: RegisterImplementation(typeof(IRoundingServiceFactory), typeof(CustomRoundingServiceFactory))]

   public class CustomRoundingServiceFactory : IRoundingServiceFactory 
   {
       // Provides an instance of the custom rounding service
       public IRoundingService GetRoundingService(int siteId)
       {
           // This basic sample does not parameterize the rounding service based on the current site
           // Use the method's 'siteId' parameter if you need different rounding behavior for each site
           return new CustomRoundingService();
       }
   }

   ```
3. Save all changes and **Build** the custom project.

The registered **CustomRoundingServiceFactory** class provides an instance of **CustomRoundingService**. The customized rounding service ensures that all price values are rounded to the required number of decimal places, with the last digit being a multiple of 5.

## Customizing rounding of tax values

The e-commerce API allows you to customize rounding specifically for tax values, without affecting rounding in other locations.

> **Note:** **Note**
>
> The scenario described below is a customization of the default tax calculation functionality. It is not compatible with other custom implementations of the **ITaxEstimationService** or **ITaxCalculationService** interface. If you already have such customizations, you need to perform the required rounding of the tax results within the given implementations.
>
> For more details, see: [Customizing tax calculation](https://docs.kentico.com/13/e-commerce-features/customizing-on-line-stores/customizing-tax-calculation.md)

1. Prepare an assembly (_Class Library_ project) with class discovery enabled in your Xperience solution (or use an existing one). See [Adding custom assemblies](https://docs.kentico.com/13/custom-development/adding-custom-assemblies.md).
   - Reference the project from both your live site and Xperience administration (_CMSApp_) projects.
2. Create a new class that inherits from the **DefaultTaxEstimationService** class (found in the _CMS.Ecommerce_ namespace).
3. Override the **RoundTax** method and implement your required rounding logic.
4. Use the **RegisterImplementation** assembly attribute to register the custom class as the implementation of the **ITaxEstimationService** interface.

The customization only changes the rounding of calculated tax values, while leaving the remaining tax functionality in its default state. The custom rounding applies both to tax values in checkout process calculations and when displaying tax values on the live site (using the [appropriate API](https://docs.kentico.com/13/e-commerce-features/developing-on-line-stores/displaying-product-listings.md)).

For all price values other than taxes, rounding is not affected and behaves according to the site's _Price rounding_ setting (or the custom [IRoundingService implementation](#customizing-rounding-globally) if one exists).

### Example – Rounding tax values up

The following example demonstrates how to customize the system to always round tax values up (even if the rounded fractional number is closer to the lower number). The example rounds values to the number of decimal places allowed by the [configuration of each currency](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-currencies.md).

1. Recreate or reuse the custom project from the [global rounding customization example](#example-custom-cash-rounding).
2. Create a new class under the custom project, inheriting from the _DefaultTaxEstimationService_ class.

   ```csharp

   using System;

   using CMS;
   using CMS.Ecommerce;

   // Registers the custom implementation of ITaxEstimationService
   [assembly: RegisterImplementation(typeof(ITaxEstimationService), typeof(CustomTaxRoundingService))]

   public class CustomTaxRoundingService : DefaultTaxEstimationService
   {
       // Constructor that passes instances of required interface implementations to the base DefaultTaxEstimationService constructor
       public CustomTaxRoundingService(ICountryStateTaxRateSource rateSource, IRoundingServiceFactory roundingServiceFactory)
           : base(rateSource, roundingServiceFactory)
       {
       }

       protected override decimal RoundTax(decimal price, TaxEstimationParameters parameters)
       {
           // Gets the number of allowed decimal places for the requested currency
           int numberOfDecimalPlaces = parameters.Currency.CurrencyRoundTo;

           // Rounds the tax value up to the requested number of decimal places
           decimal multiplier = Convert.ToDecimal(Math.Pow(10, numberOfDecimalPlaces));
           return Math.Ceiling(price * multiplier) / multiplier;
       }
   }

   ```
3. Save all changes and **Build** the custom project.

The customization ensures that values are always rounded up for tax calculation results that have more decimal places than allowed by the given currency. Other types of rounding are not affected.
