---
title: Customizing orders
related:
  - https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/orders.md
  - https://docs.kentico.com/13/custom-development/customizing-providers.md
  - https://docs.kentico.com/13/custom-development.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).

You can customize how the system creates, modifies or deletes [orders](https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/orders.md). That is suitable especially when you want to process additional actions while working with orders, or when you want to completely replace how the system works with orders.

To customize processes that work with orders, you need to implement a [custom provider](https://docs.kentico.com/13/custom-development/customizing-providers.md) that inherits from the **OrderInfoProvider** class:

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 in your project in Visual Studio (for example **CustomOrderInfoProvider.cs**) that inherits from the **OrderInfoProvider** class and [registers the custom InfoProvider](https://docs.kentico.com/13/custom-development/customizing-providers/registering-providers-using-assembly-attributes.md):

   ```csharp

   [assembly: RegisterCustomProvider(typeof(CustomOrderInfoProvider))]
   public class CustomOrderInfoProvider : OrderInfoProvider
   {
   }

   ```
3. Implement methods that override the default _OrderInfoProvider_ methods.
   - See [the list of virtual methods](#virtual-methods-in-the-orderinfoprovider) that you can override.
4. Save the file and Rebuild the solution.

The system now uses the custom _OrderInfoProvider_ class with the modified methods.

## Virtual methods in the OrderInfoProvider

The following list does not contain virtual methods related to [email notifications](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-e-commerce-email-notifications.md) for orders.

### Set

Creates or updates an order based on a specified order object (_OrderInfo info_).

> **Tip:** If you decide to completely override the order creation and update process without calling _base.Set(info)_, you also need to perform the following tasks:
>
> - Assign an order date
> - Assign an order status
> - Set the order as paid if necessary
> - Save the order by calling _SetInfo(info)_
>
> To ensure the database's integrity, you can use transactions:
>
> ```csharp
>
> using (var tr = BeginTransaction())
> {
>     // ... your code ...
>
>     tr.Commit();
> }
>
> ```

```csharp

public virtual void Set(OrderInfo info) { }

```

See an example [below](#example---adding-extra-credit-after-creating-new-orders).

### Delete

Deletes an order based on a specified order object (_OrderInfo info_).

> **Tip:** To ensure the database's integrity, you can use transactions:
>
> ```csharp
>
> using (var tr = BeginTransaction())
> {
>     // ... your code ...
>
>     tr.Commit();
> }
>
> ```

```csharp

public virtual void Delete(OrderInfo info) { }

```

### GenerateInvoiceNumberInternal

Returns an invoice number generated from a specified shopping cart.

```csharp

protected virtual string GenerateInvoiceNumberInternal(ShoppingCartInfo cart) { }

```

### UpdateOrderStatusHistoryInternal

Updates an order status of a specified order (_OrderInfo orderObj_), which already contains the new order status, from a specified original order status _(int originalStatusId_). If the order is new (_bool newOrder_), the method does not check the original order status.

If the original and new statuses are not the same, the system sends an email notification about the change as [configured](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-e-commerce-email-notifications.md).

```csharp

protected virtual void UpdateOrderStatusHistoryInternal(OrderInfo orderObj, int originalStatusId, bool newOrder) { }

```

### ProcessOrderIsPaidChangeInternal

By default, the method is called when an order is paid (during [theSetmethod](#set)).

Processes order items of the [membership](https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/products/managing-product-representations/managing-e-commerce-memberships.md) and [e-product](https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/products/managing-product-representations/managing-e-products.md) [product representations](https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/products/managing-product-representations.md) (see the **[ProcessMembershipInternal](#processmembershipinternal)** and [ProcessEProductInternal](#processeproductinternal) methods) of a specified order (_OrderInfo oi_) and then sends an email notification if the order is paid.

```csharp

protected virtual void ProcessOrderIsPaidChangeInternal(OrderInfo oi) { }

```

### ProcessMembershipInternal

By default, the method is called when an order is paid (during the [ProcessOrderIsPaidChangeInternal](#processorderispaidchangeinternal) method).

Creates or updates a record regarding a specified user (_UserInfo ui_) and a specified membership (_SKUInfo skui_) in a specified order (_OrderInfo oi_) as a specified order item (_OrderItemInfo oii_). Specify to when the membership is supposed to be prolonged (_DateTime now_).

```csharp

protected virtual void ProcessMembershipInternal(OrderInfo oi, OrderItemInfo oii, SKUInfo skui, UserInfo ui, DateTime now)

```

### ProcessEProductInternal

By default, the method is called when an order is paid (during the [ProcessOrderIsPaidChangeInternal](#processorderispaidchangeinternal) method).

Enables or disables downloading files of a specified e-product (_SKUInfo skui_) contained in a specified order (_OrderInfo order_) as a specified order item (_OrderItemInfo item_) from a specified date and time (_DateTime now_). Enabling or disabling is decided based on the payment status of the order.

```csharp

protected virtual void ProcessEProductInternal(OrderInfo order, OrderItemInfo item, SKUInfo skui, DateTime now)

```

## Example - Adding extra credit after creating new orders

The following example demonstrates how to [add extra credit](https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/customers/managing-customer-credit.md) to the [credit account](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-payment-methods/configuring-customer-credit.md) of every customer who creates an order with the total price higher than 1000 in the site's [main currency](https://docs.kentico.com/13/e-commerce-features/configuring-on-line-stores/configuring-currencies.md).

```csharp

using System;

using CMS;
using CMS.Ecommerce;
using CMS.SiteProvider;

[assembly: RegisterCustomProvider(typeof(CustomOrderInfoProvider))]

public class CustomOrderInfoProvider : OrderInfoProvider
{
    public override void Set(OrderInfo info)
    {
        if (info == null)
        {
            throw new ArgumentNullException(nameof(info));
        }

        // Indicates whether the set object is a new order
        bool newOrder = info.OrderID <= 0;

        // Updates the order or creates a new order using the default API
        base.Set(info);

        // Adds extra credit for each new order with the total price higher than 1000
        if (newOrder && (info.OrderTotalPriceInMainCurrency > 1000))
        {
            // Creates a new credit event
            CreditEventInfo extraCredit = new CreditEventInfo();

            // Sets the credit event's general properties
            extraCredit.EventName = string.Format("Credit for your order: {0}", info.OrderID);
            extraCredit.EventDate = DateTime.Now;
            extraCredit.EventDescription = "Thank you for your order.";
            extraCredit.EventCustomerID = info.OrderCustomerID;

            // Sets the credit event's value in the site main currency
            extraCredit.EventCreditChange = 10;

            // Sets credit as site credit or as global credit according to the settings
            extraCredit.EventSiteID = ECommerceHelper.GetSiteID(SiteContext.CurrentSiteID, ECommerceSettings.USE_GLOBAL_CREDIT);

            // Saves the credit event
            CreditEventInfo.Provider.Set(extraCredit);
        }
    }
}

```
