Skip to main content

Notifications

Announcements

No record found.

Supply chain | Supply Chain Management, Commerce
Unanswered

How to add a priceEvent to the pricing engine

Posted on by 1,433

Because the standard rounding rule set up under the currencies isn't applied to the salesPrice, only to the LineAmount (It's by design according to Microsoft), I need to force a rounding on the salesPrice via custom.

Microsoft told me to add a priceEvent before the call to the pricing engine on the Retail side:

****

For the POS. 

1) Create custom handler with code copied from the out of box pricingservice.

CalculatePricesServiceRequest, 

CalculateDiscountsServiceRequest, 

 

2) In the request handler, add line before the call to PricingEngine:

            var priceEvents = PE.PricingEngineExtensionRepository.GetPriceEvents();
            priceEvents.PrePriceRoundingAdjustments = <a method which has SkipStandardRounding = false>.

****

I cannot see how to accomplish the above.

I decrypted the pricing engine DLL and search for the PrePriceRoundingAdjustment Microsoft suggested I add.

Looking at its signature in the PriceEvents class, I see the following:   public event EventHandler<PrePriceRoundingEventArgs> PrePriceRoundingAdjustments;

Looking at the signature of PrePriceRoundingEventArgs, I see the following:

public PrePriceRoundingEventArgs(PriceContext priceContext, SalesLine salesLine)
      : base(priceContext, salesLine)
    {
      this.SkipStandardRounding = true;
    }

I'm supposed to set the SkipStandardRounding to FALSE.

Now here my problem starts.

The pricing engine receives a SalesTransaction. This object has a collection of SalesLines. Looking at the signature of the PrePriceRoundingEventArgs, it wants a salesLine and it wants the pricecontext of the pricing engine. How do I give to this priceEvent the arguments it wants when I must add it before the call to the pricing engine.  There is something I clearly don't understand regarding the priceEvents.

So, has anybody added a priceEvent and can help me out here please?

I have asked Microsoft for an example because there is nothing in the  "RetailSDK\SampleExtensions\CommerceRuntime". But I don't know when I will hear back or if they even have an example.  So I thought to ask here as well , because it is a serious problem for our company that the salesPrice is not rounded to 2 decimals.

  • Retha Profile Picture
    Retha 1,433 on at
    RE: How to add a priceEvent to the pricing engine

    I heard back from Microsoft and this is how one adds it:

                    PricingEngineExtensionRepository.GetPriceEvents().PrePriceRoundingAdjustments  = (sender, args) =>
                    {
                        args.SkipStandardRounding = false;
                    };
    

    We are on v10.0.20 and have Omnichannel turned on which means our D365 call center orders and POS Retail/Commerce-online as I understand it, use the same pricing engine because we need the same price to come up everywhere, regardless if it is a call center order or a POS Retail order.

    Because the pricing engine itself on the call center side does not apply the rounding rule setup to the sales price, only to the line amount, I had to extend the RetailOrderCalculator setSalesPrice method:

     protected void setSalesPrice(Microsoft.Dynamics.Commerce.Runtime.DataModel.SalesLine _crtSalesLine, RetailOrderLineMap _retailOrderLineMap)
    
        {
            // CoC
            next setSalesPrice(_crtSalesLine, _retailOrderLineMap);
    
            Price vBefore = _crtSalesLine.get_Price();
            CurrencyCode vCurrency = _retailOrderLineMap.CurrencyCode;
            Price vRoundedPrice = CurrencyExchangeHelper::amount(vBefore, vCurrency);
            _retailOrderLineMap.SalesPrice = vRoundedPrice;
        }

    The above is called directly after the RetailOrderCalculator retunrs the price from the pricing engine.

    Then on the Retail side, you have to extend the handler in the CRT:

    namespace TMCSalesPriceRoundingCRT
    {
        using System;
        using System.Collections.Generic;
        using System.Threading.Tasks;
        using Microsoft.Dynamics.Commerce.Runtime;
        using Microsoft.Dynamics.Commerce.Runtime.DataModel;
        using Microsoft.Dynamics.Commerce.Runtime.DataServices.Messages;
        using Microsoft.Dynamics.Commerce.Runtime.Messages;
        using Microsoft.Dynamics.Commerce.Runtime.Services;
        using Microsoft.Dynamics.Commerce.Runtime.Services.Messages;
        using PE = Microsoft.Dynamics.Commerce.Runtime.Services.PricingEngine;
    
        public class PricingServiceRounding : IRequestHandlerAsync
        {
            public IEnumerable SupportedRequestTypes
            {
                get
                {
                    return new[] { typeof(CalculatePricesServiceRequest) };
                }
            }
            public async Task Execute(Request request)
            {
                ThrowIf.Null(request, "request");
    
                Response response;
                Type requestType = request.GetType();
    
                if(requestType == typeof(CalculatePricesServiceRequest)) {
    
                    response = await CalculatePricesAsync((CalculatePricesServiceRequest)request).ConfigureAwait(false);
                }
                else
                {
                    throw new NotSupportedException(string.Format("Request '{0}' is not supported.", request.GetType()));
                }
    
                return response;
            }
    
            private static async Task CalculatePricesAsync(CalculatePricesServiceRequest request)
            {
                ThrowIf.Null(request, nameof(request));
                ThrowIf.Null(request.RequestContext, "request.RequestContext");
                ThrowIf.Null(request.Transaction, "request.Transaction");
    
                /* tell the pricing engine not to skip the standard rounding on rounding
                 * the price after adjustments were applied
                 */
                PE.PricingEngineExtensionRepository.GetPriceEvents().PrePriceRoundingAdjustments  = (sender, args) => {
    
                    args.SkipStandardRounding = false;
    
                };
    
                // Call the pricing engine
                PE.CommerceRuntimePriceAndDiscount.CalculatePrices(
                    request.RequestContext,
                    new PricingDataServiceManager(request.RequestContext),
                    new ChannelCurrencyOperations(request.RequestContext),
                    request.Transaction,
                    await GetCustomerAsync(request.RequestContext, request.Transaction.CustomerId).ConfigureAwait(false),
                    request.PricingCalculationMode,
                    request.DateWhenActive.HasValue ? request.DateWhenActive.Value : request.RequestContext.GetNowInChannelTimeZone());
    
                return new GetPriceServiceResponse(request.Transaction);
            }
    
            private static async Task GetCustomerAsync(RequestContext context, string customerAccount)
            {
                Customer customer = null;
                if (!string.IsNullOrWhiteSpace(customerAccount))
                {
                    var getCustomerDataRequest = new GetCustomerDataRequest(customerAccount);
                    SingleEntityDataServiceResponse getCustomerDataResponse = await context.ExecuteAsync<SingleEntityDataServiceResponse>(getCustomerDataRequest).ConfigureAwait(false);
                    customer = getCustomerDataResponse.Entity;
                }
    
                return customer ?? (new Customer());
            }
    
        }
    }
    

    We only needed the salesPrice itself to round to 2 decimals as set up in the rounding rule under the currency US. The discount amount can have more decimal points. the line amount is already rounding to what ever is set up in the rounding rule.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

December Spotlight Star - Muhammad Affan

Congratulations to a top community star!

Top 10 leaders for November!

Congratulations to our November super stars!

Tips for Writing Effective Suggested Answers

Best practices for providing successful forum answers ✍️

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,280 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 230,214 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans