The IPricingBasePriceCallback interface provides you a mechanism to define a custom logic to be executed before, during, and after Base Price calculation. The IPricingBasePriceCallback is executed in batches which consists of the batch line items. TurboPricing calls this interface for every batch.

The following methods are available in the IPricingBasePriceCallback interface:

Method SignatureDescription
Task BeforePricingBatchAsync(IBatchPriceRequest batchPriceRequest)You can use this method to define custom logic that must be executed before Base Price is calculated.
Task OnPricingBatchAsync(IBatchPriceRequest batchPriceRequest)You can use this method to define custom logic that must be executed during the Base Price calculation. You can use the price list items to write the custom logic.
Task AfterPricingBatchAsync(IBatchPriceRequest batchPriceRequest)You can use this method to define custom logic that must be executed after the Base Price is calculated.

Task OnProductOptionPriceAsync(IBatchPriceRequest batchPriceRequest, IDictionary<string, IProductOptionPrice> productOptionPrice)

You can use this extension point to modify product option prices for the given line item.

Extension Points

The following extension points are added to the default template. 

Method SignatureDescription

Task OnPriceMatrixAsync(IBatchPriceRequest batchPriceRequest, IDictionary<string, IEnumerable<IPriceMatrixEntry>> priceMatrixEntries)

You can use this extension point to modify resolved price matrix for the given line item if required.

The below code snippet is for reference purposes only.
/// <summary>
/// On Price Matrix
/// </summary>
/// <param name="batchPriceRequest"></param>
/// <param name="priceMatrixEntries"></param>
/// <returns></returns>
public async Task OnPriceMatrixAsync(IBatchPriceRequest batchPriceRequest, IDictionary<string, IEnumerable<IPriceMatrixEntry>> priceMatrixEntries)
{
    var batchLineItems = batchPriceRequest.GetLineItems().SelectMany(x => x.GetChargeLines()).Select(s => new LineItem(s)).ToList();
    var cartLineItems = batchPriceRequest.GetCartContext().GetLineItems().SelectMany(x => x.GetChargeLines()).Select(s => new LineItem(s)).ToList();

    var batchLineItem = batchLineItems[0];
    if(priceMatrixEntries.ContainsKey(batchLineItem.Id)) 
    {                   
        var priceMatrixEntriesEnumerable = priceMatrixEntries[batchLineItem.Id];                    
        foreach(var pMatrixEntry in priceMatrixEntriesEnumerable) 
        {
          	pMatrixEntry.AdjustmentAmount = 20;                                                
        }
    }
    await Task.CompletedTask;
}
CODE

Task OnPriceRuleAsync(IBatchPriceRequest batchPriceRequest, IDictionary<string, IEnumerable<IPriceRuleEntry>> priceRuleEntries)

You can use this extension point to modify the resolved price rule entries for the given line item if required.

The below code snippet is for reference purposes only.

/// <summary>
/// On PriceRule
/// </summary>
/// <param name="batchPriceRequest"></param>
/// <param name="priceRuleEntries"></param>
/// <returns></returns>
public async Task OnPriceRuleAsync(IBatchPriceRequest batchPriceRequest, IDictionary<string, IEnumerable<IPriceRuleEntry>> priceRuleEntries)
{
    var batchLineItems = batchPriceRequest.GetLineItems().SelectMany(x => x.GetChargeLines()).Select(s => new LineItem(s)).ToList();
    var cartLineItems = batchPriceRequest.GetCartContext().GetLineItems().SelectMany(x => x.GetChargeLines()).Select(s => new LineItem(s)).ToList();
          
    var batchLineItem = batchLineItems[0];
    if(priceRuleEntries.ContainsKey(batchLineItem.Id)) 
    {
        var priceRuleEntriesEnumerable = priceRuleEntries[batchLineItem.Id];        
        foreach(var pRuleEntry in priceRuleEntriesEnumerable) 
        {
           	pRuleEntry.AdjustmentAmount = 20;                                                                   
        }
    }
  await Task.CompletedTask;
}
CODE

Task OnPipelinePriceRuleAsync(IBatchPriceRequest batchPriceRequest, IDictionary<string, IEnumerable<IPriceRuleEntry>> pipelinePriceRuleEntries)

You can use this extension point to modify the resolved price pipeline rule entries for the given line item if required

The below code snippet is for reference purposes only.

/// <summary>
/// On Pipeline PriceRule
/// </summary>
/// <param name="batchPriceRequest"></param>
/// <param name="pipelinePriceRuleEntries"></param>
/// <returns></returns>
public async Task OnPipelinePriceRuleAsync(IBatchPriceRequest batchPriceRequest, IDictionary<string, IEnumerable<IPriceRuleEntry>> pipelinePriceRuleEntries)
{
    var batchLineItems = batchPriceRequest.GetLineItems().SelectMany(x => x.GetChargeLines()).Select(s => new LineItem(s)).ToList();
    var cartLineItems = batchPriceRequest.GetCartContext().GetLineItems().SelectMany(x => x.GetChargeLines()).Select(s => new LineItem(s)).ToList();
                
    var batchLineItem = batchLineItems[0];
    if(pipelinePriceRuleEntries.ContainsKey(batchLineItem.Id)) 
    {
        var pipelinePriceRuleEntriesEnumerable = pipelinePriceRuleEntries[batchLineItem.Id];                  
        foreach(var ppRuleEntry in pipelinePriceRuleEntriesEnumerable) 
        {                    	
                        ppRuleEntry.AdjustmentAmount = 20;                   
        }
    }     
    await Task.CompletedTask;
}
CODE

Task OnPriceEscalatorAsync(IBatchPriceRequest batchPriceRequest, List<IPriceEscalator> priceEscalators)

You can use this extension point to modify the resolved price escalators if required.


Example Code

The below code snippet is for reference purposes only.

namespace Apttus.Lightsaber.Customer.Pricing 
{
    public class PricingBasePriceCallback : CodeExtensibility, IPricingBasePriceCallback 
    {
        public async Task AfterPricingBatchAsync(IBatchPriceRequest batchPriceRequest)
        {
            await Task.CompletedTask;
        }

        public async Task BeforePricingBatchAsync(IBatchPriceRequest batchPriceRequest)
        {
            var batchLineItems = batchPriceRequest.GetLineItems().SelectMany(x => x.GetChargeLines()).Select(s => new LineItem(s)).ToList();

            //Example, setting custom field on line item before PLI resolution
            foreach(var batchLineItem in batchLineItems) {
                decimal extendedQuantity = batchLineItem.GetQuantity();
                decimal quantity = batchLineItem.GetQuantity();

                if(batchLineItem.IsOptionLine()) {
                    LineItem rootBundleLineItemModel = new LineItem(batchLineItem.GetRootParentLineItem().GetPrimaryLineItem());
                    decimal bundleQuantity = rootBundleLineItemModel.GetQuantity();
                    extendedQuantity = bundleQuantity * batchLineItem.GetQuantity();
                }

                batchLineItem.APTS_Extended_Quantity__c = extendedQuantity;
            }
            
            //You can also query DB here, and perform initial setup such as creating required Dictionary, List and so on for later use in the callback code.

            await Task.CompletedTask;
        }

        public async Task OnPricingBatchAsync(IBatchPriceRequest batchPriceRequest)
        {
            var batchLineItems = batchPriceRequest.GetLineItems().SelectMany(x => x.GetChargeLines()).Select(s => new LineItem(s)).ToList();

            foreach(var batchLineItem in batchLineItems) {
                IPriceListItemModel priceListItemModel = batchLineItem.GetPriceListItem();
                IPriceListItem priceListItemEntity = priceListItemModel.GetEntity();

                if(batchLineItem.PriceListId != priceListItemEntity.PriceListId) {                   
                       batchLineItem.APTS_Is_Contract_Pricing__c = true;                   
                }
            }                
            await Task.CompletedTask;
        }
    }
}
CODE