Published on, Time to read
🕒 2 min read

Optimizely / Episerver: Generating a custom order number

Authors
  • avatar
    Name
    Dariusz Woźniak

In Optimizely Commerce, the order number is generated by the system. However, there might be a need to generate a custom order number. Here is how to do that.

The default way to generate an order number in Optimizely is done in the DefaultOrderNumberGenerator class. The process of generation of the number is as follows:

  • Prefix, a fixed-string: PO.
  • Order group ID.
  • Random, 3-digit number.

For example:

PO1007893
│ │   │
└─┼Fixed string: PO
  └─Order group ID: 1007
      └─Random number: 893

The order number is stored in the Commerce database → OrderGroup_PurchaseOrder table → TrackingNumber column. It is a nvarchar(512) type by default.

In case you need to write your own order number generator, you need to implement the IOrderNumberGenerator interface. The interface has only one method, GenerateOrderNumber which returns a string and has an IOrderGroup parameter.

Also, you need to register and replace the custom implementation in the IoC container. For example:

services.Intercept<IOrderNumberGenerator>((_, _) => new CustomOrderNumberGenerator());

If you need to increment the value of the order number and yet you need to guarantee the uniqueness of the number, you can use the SQL Server sequence. To create a sequence in conjunction with the Entity Framework Core, you need to add the following code to the OnModelCreating method of the DbContext:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.HasSequence<int>("OrderNumberSequence")
                .StartsAt(1000)
                .IncrementsBy(1);
}

...and to get the next sequence number:

public int GenerateOrderNumber()
{
    var result = new SqlParameter("@result", System.Data.SqlDbType.Int)
    {
        Direction = System.Data.ParameterDirection.Output
    };

    var query = $"SELECT @result = (NEXT VALUE FOR dbo.OrderNumberSequence)";

    Database.ExecuteSqlCommand(query, result);

    return (int)result.Value;
}

Please note that the above solutions may reveal a count of orders in your system. This might not be acceptable from a security point of view. For that reason, I would recommend using the random number or ID generator.

External links: