Custom Promotion Criteria
Promotion criteria in Ucommerce are used to determine when to trigger a discount on an order.
Ucommerce has built-in criteria for handling most use cases. However, if the need arises, it's quite easy to create a custom criterion.
Create a Custom Criterion
Creating a Definition
To create a definition, follow these steps:
Create a definition and add it to your database. The definition must be of the criterion definition type.
Add appropriate definition fields to it. Built-in Ucommerce data types will work out of the box.
If you wish to be able to reuse the criterion for future projects we recommend you create a background service to automate this process.
Example: buy-less-than Criterion
Below is an example of setting up a criterion that triggers only when a customer is buying less than a given quantity.
public class SetupCustomCriterion : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
/// <inheritdoc />
public SetupCustomCriterion(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
/// <inheritdoc />
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await using var asyncScope = _serviceProvider.CreateAsyncScope();
var dbContext = asyncScope.ServiceProvider.GetRequiredService<UcommerceDbContext>();
if (dbContext.Set<DefinitionEntity>().Any(x => x.Name == "Buy At Most"))
{
return;
}
// Set up data using dbContext
// Find the TargetOrderLine data type
var dataType = dbContext.Set<DataTypeEntity>()
.FirstOrDefault(x => x.Guid.ToString() == "b5295545-5583-41e1-8c93-7bc921c09e27");
var defFields = new List<DefinitionFieldEntity>();
defFields.Add(new DefinitionFieldEntity
{
Name = "Max Amount",
DataTypeId = 3,
DisplayOnSite = true,
DefaultValue = "0",
RenderInEditor = true,
Guid = Guid.Parse("42085d44-3e81-4d94-aad8-8699ae7d35b0")
});
defFields.Add(new DefinitionFieldEntity
{
Name = "Target Orderline",
DefaultValue = "0",
DisplayOnSite = true,
RenderInEditor = true,
DataType = dataType,
Guid = Guid.Parse("aa793b3f-2baf-45fb-a162-cb675e8d9b64")
});
dbContext.Set<DefinitionEntity>()
.Add(new DefinitionEntity
{
BuiltIn = false,
Description = "buy at Most criterion definition",
Name = "Buy At Most",
DefinitionTypeId = 5434834, //Id of the Criterion Definition Type
DefinitionFields = defFields,
Guid = Guid.Parse("99ab73d5-22ee-425c-97f8-f9794ed01944")
});
await dbContext.SaveChangesAsync(stoppingToken);
}
}Implementing a Pipeline Task for Satisfaction Check
To trigger a criterion we need to extend the SatisfiedCriteria pipeline with a pipeline task that checks whether the criterion is satisfied. There are four unique concepts to be aware of regarding this task:
CriterionDTOis a DTO connecting a criterion with its properties.context.Output.CriterionDtosis a dictionary ofCriterionDTOgrouped by their definition.Context.Output.SatisfiedOrderLineCriteriais a dictionary of lists containing criteria grouped by the order line that satisfied them. Use this for order line-level criteria.context.Output.SatisfiedOrderCriteriais a list of criteria that are satisfied by the order. Use this for order-level criteria.
Example
Here's an example of a pipeline task for checking if the buy-at-most criterion is triggered by an order. Since it can target both line- and order-level this task can handle both cases. This will not be necessary in most cases.
Validation (Optional)
It is possible to set validation rules for a criterion using FluentValidation. To make this easier, inherit from UpdateCriteriaInputValidatorBase in namespace Ucommerce.Web.BackOffice.Validators.Promotions.Criteria.UpdateCriteria to set rules for your custom criteria.
UpdateCriteriaInputValidatorBase contains the method RuleForUpdatePropertyValue(string propertyName) where propertyName is the definition field´s name.
After creating a validator it needs to be registered as a service in the program.cs file.
Example
Here's an example of custom rules for the Buy-At-Most criterion that was created earlier.
Tips for Reusability
To facilitate reuse of a custom criterion across projects, it is recommended to create an extension method that registers the needed services.
This is an example of a method for registering the different parts of a custom criterion:
That way, it is now possible to add the criterion to any Ucommerce solution like this:
Last updated
Was this helpful?