SaaS CMS has officially launched! Learn more now.

B2B -% of order depending on spent amout for company


New to Epi Server Commerce and struggling to create a business rule to handle B2B sales.

Our rule is that if a certain company buys for a certain amount the get a % discount on future purchases.

This total amount spent from company, not per cart.

For example;

1 USD to 100 USD get 10% on order

101 USD - 200 USD get 15% on order

201 USD and above get 20% on order

Any tips on how to build this, can I do it form existing rules in Campaigns our must I custom build it? smile

Oct 16, 2018 22:07

How do you store your customers (companies)? Do you have one Organization setup per company that has several CustomerContacts in them that all can place orders independently and they all count towards this order total? Or is it simpler with one company being one CustomerContact?

There's no built in promotion that can handle this exact case. But you can create a custom one that can handle it rather simply.

Documentation on how to create your own promotion processor can be found here:

The reason why I'm asking about how you deal with CustomerContacts and Organizations is that the biggest issue is not creating the promotion, but rather how you're going to retrieve the accumulated order total for a company. Especially if you're working with Organizations and also want to keep track of which specific employee (CustomerContact) that placed the orders.

It could be a very taxing operation, but I can give some pointers on what you can do depending on which scenario you're dealing with. smile

Edited, Oct 17, 2018 2:21

That's a good pointing Jafet. And yes as you say it is a heavy operation. 

What I think can work is

  • Add a metafield to Organization metaclass. If a contact belongs to an organization, then when he or she places an order, increase that field with the order total
  • Create an order promotion
  • For the evaluation for that processor, check if the current contact belong to an organization or not. 
  • If yes, check that that spent value and set the discount amount.

Pretty high level suggestions, but if I have time I will write about it in more details in my book later :) 

Oct 17, 2018 8:47

Good points, I will check in to it.

One idea to get accumulated order, is to get it from Salesfoce where we keep the data today.

Thanks for quick and good answers!laughing

Oct 17, 2018 9:21

Yeah, getting it from SalesForce is probably the best in that case.

Here's a sample, in pseudocodish, that can get you going:


    [ContentType(GUID = "84D18E50-C3AF-4E99-B792-F0099B61306B")]
    public class PermanentCustomerDiscount : OrderPromotion
        // Add whatever properties you deem necessary.
        // for example add properties where an editor can set which ranges give what percentage of discount


[ServiceConfiguration(Lifecycle = ServiceInstanceScope.Singleton)]
// We inherit from OrderPromotionProcessor, because this is intended to give discount on the entire order.    
public class PermanentCustomerDiscountProcessor : OrderPromotionProcessorBase<PermanentCustomerDiscount>
        private readonly IMySalesForceService _salesForceService;

        public PermanentCustomerDiscountProcessor(IMySalesForceService salesForceService)
            _salesForceService = salesForceService;

        protected override PromotionItems GetPromotionItems(PermanentCustomerDiscount promotionData)
            // No catalog items affect this promotion.
            var emptyResult = new CatalogItemSelection(
            return new PromotionItems(promotionData, emptyResult, emptyResult);

        protected override RewardDescription Evaluate(PermanentCustomerDiscount promotionData, PromotionProcessorContext context)
            // The field that you're working with needs to be set on the Cart before you run the PromotionEngine
            var customerId = context.OrderGroup.CustomerId;
            // or
            var organizationId = context.OrderGroup.Organization;

            var orderTotal = _salesForceService.GetCustomerOrderTotal(organizationId);

            if (orderTotal < 1m) // Get the "1m" from a place where the discount cutoffs are configured
                return RewardDescription.CreateNotFulfilledDescription(promotionData, FulfillmentStatus.NotFulfilled);

            var discountPercentage = 10m; // Do your checks for which discount percentage it should be from wherever you've configured the discount cutoffs and percentages

            return RewardDescription.CreatePercentageReward(
                new List<RedemptionDescription> { CreateRedemptionDescription(context.OrderForm) },
Edited, Oct 17, 2018 15:27

You don't have to decorating the processor with the ServiceConfiguration, do you?

Hmm - I think the processor is resolved by some reflection manner, but apparently our promotions are decorated with this attribute. I am not sure what I am missing, will check 

EDIT: the attribute is not really needed. The point was to cache the instance but we now have a better cache mechanism for that...

Edited, Oct 17, 2018 16:00

Ok, good to know. I haven't created my own processor in a project since the new promotion system was in beta. :D

But the ServiceConfiguration part of it I took from the example in the documentation here:

So the example might need to be updated if it's no longer needed. smile

Oct 17, 2018 16:46

There is an alternative solution to a custom promotion processor and that is to write a custom visitor group criterion that compares with the salesforce value.

Then it is just a question of setting up three visitor groups and three normal promotions for the 10%, 15%, 20% discounts.

Oct 18, 2018 15:10
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.