DAX2012 R3 – Playing with Retail CRT

The Microsoft Dynamics AX commerce runtime (CRT) serves as the engine for a retail channel. It connects to a CRT database that stores business data for the channel.. Dynamics AX uses the CRT Architecture in the Retail ePOS, mPOS and in the Sharepoint based eCommerce solution. Also the SiteCore eCommerce solution uses the CRT as the integration to Dynamics AX.

Let’s look at some of the interesting things with CRT.

1. It is a well-documented framework supported by Microsoft. More details on it is available here.

2. It can make it easier to integrate business logics to other eCommerce solutions. Like Magento.

3. We can create CRT web-services that handles information like very advanced retail prices, on-hand shipment, check-outs etc.

4. And MUCH more. This CRT we will have almost everything we need to interact with external system. It Rocks !

Let’s take an example. I would like to utilize the CRT to calculate a sales price with discounts. Price/discounts in AX is very flexible and almost all options you can imagine. Here is a small example of the possibilities we get in Dynamics AX 2012 R3 CU 8.

Let’s say we would like to expose this price/discount structure as a web-service to external parties. Since the CRT is relying on it’s own channel database, it means that the much of the integration is actually not creating a heavy load on the Dynamics AX database. We also have the possibility to “scale out” on the architecture.

The CRT is developed in Visual Studio, and is basically just a bunch of dll’s. I have to admit, that Visual studio, Web-services and is not my strongest side. So I decided to see it I could access and use the CRT framework directly from Dynamics AX. The new call-center module in AX 2012 R3 CU8 is using this, and I wanted to create a very simple job that exemplifies how CRT operates and can be used. Basically I’m looking for this:

I use the standard AX 2012 R3 CU8 contoso demo data, but added the following quantity discount to the Houston store;

Since I know X++, I’ll use X++ job to try this. The infolog I got was the following:

Here we see that the CRT returned the sales price, discounted price, and also information like total amount. Surely it can give everything else, but I wanted to keep the example easy to understand.

I created the following job to play with the framework, and it gives you an idea of how to interact with the CRT from AX.

static void demo_CRT_GetSalesPrice(Args _args)
{
    //To test this code, use the AX 2012 R3 CU8, and use the USRT company
    Microsoft.Dynamics.Commerce.Runtime.Data.IPricingDataManagerV2                pricingManager;
    Microsoft.Dynamics.Commerce.Runtime.Services.PricingEngine.DiscountParameters priceParameters;
    Microsoft.Dynamics.Commerce.Runtime.DataModel.SalesLine                       crtSalesLine;
    Microsoft.Dynamics.Commerce.Runtime.DataModel.SalesTransaction                crtSalesTransaction;
    System.Object                                                                 roundingRule, currencyConverter;
    CLRObject                                                                     clrSalesLines, enumeratorSalesLine;
    CLRObject                                                                     clrObjectSalesLines;
    System.DateTimeOffset                                                         activeDateTimeOffset;
    System.String                                                                 lineIdString;
    System.String                                                                 customerPriceGroup = "";
    Price                                                                         price;
    Qty                                                                           qty;
    InventDim                                                                     inventdim;

    RetailStoreTable    storeTable = RetailStoreTable::find("HOUSTON");   //Lets use houston as an example here
    RetailChannelRecId  channelId = storeTable.RecId;                     //This is the recid for a retail channel. A retail store is an extension of a retail channel.
    CurrencyCode        currencyCode = storeTable.Currency;
    appl.setDefaultCompany(storeTable.company(), false);                  //Setting default company to houstons company

    //Creating a unique line ID
    lineIdString = System.Guid::NewGuid().toString();

    InventDim.InventLocationId = storeTable.inventLocation;
    InventDim.InventSiteId     = InventLocation::find(storeTable.inventLocation).InventSiteId;
    InventDim                  = InventDim::findOrCreate(InventDim);

    //Pricing manager : Encapsulates data access to pricing information.
    pricingManager          = Microsoft.Dynamics.Commerce.Headquarters.RetailProxy.AxPricingDataManager::BuildDataManager(channelId);

    //Price parameters : types of AX discounts (aka trade agreement discounts, aka not Retail Periodic Discounts) are currently activated and should be allowed on the transaction
    priceParameters         = Microsoft.Dynamics.Commerce.Runtime.Services.PricingEngine.DiscountParameters::CreateAndInitialize(pricingManager);
    roundingRule            = Microsoft.Dynamics.Commerce.Headquarters.RetailProxy.ServiceHelpers::GetRoundingMethod(currencyCode);
    currencyConverter       = Microsoft.Dynamics.Commerce.Headquarters.RetailProxy.ServiceHelpers::GetCurrencyConverter(currencyCode);
    activeDateTimeOffset    = RetailPricingEngineHelper::getSessionDateTimeInChannelTimeZone(channelId);

    //Next we create a crtSalesLine, that represents a channel agnostic sales line.
    crtSalesLine = new Microsoft.Dynamics.Commerce.Runtime.DataModel.SalesLine();

    crtSalesLine.set_ItemId("0001");        //Lets use product 0001 as our example
    crtSalesLine.set_InventoryDimensionId(InventDim.inventDimId);
    crtSalesLine.set_Quantity(10);          //Lets use quantity 10 as our example
    crtSalesLine.set_LineId(lineIdString);  //Let give this line a uniqe ID

    crtSalesLine.set_UnitOfMeasureSymbol("ea"); //Let use 'ea' as the unit

    //We then create a sales transaction, and add the salesline to this.
    crtSalesTransaction = new Microsoft.Dynamics.Commerce.Runtime.DataModel.SalesTransaction();
    clrObjectSalesLines = crtSalesTransaction.get_SalesLines();
    clrObjectSalesLines.Add(crtSalesLine);                      //This is where the we add the salesLine to the sales transaction

    //Lets calculate the prices
    Microsoft.Dynamics.Commerce.Runtime.Services.PricingEngine.PricingEngine::CalculatePricesForTransaction(
        crtSalesTransaction,
        pricingManager,
        roundingRule,
        currencyConverter,
        customerPriceGroup,
        currencyCode,
        false,
        activeDateTimeOffset);

    //Lets calculate the discounts
    Microsoft.Dynamics.Commerce.Runtime.Services.PricingEngine.PricingEngine::CalculateDiscountsForLines(
        pricingManager,
        crtSalesTransaction,
        roundingRule,
        currencyConverter,
        currencyCode,
        '',
        '',
        '',
        true,
        Microsoft.Dynamics.Commerce.Runtime.DataModel.DiscountCalculationMode::CalculateAll,
        activeDateTimeOffset);

    //And, let's show what the CRT can give us.
    qty   = crtSalesLine.get_Quantity();
    Price = crtSalesLine.get_Price();
    info(strFmt("Normal sales price is %1 when buying %2", price, qty ));

    Price = crtSalesLine.get_DiscountAmount();
    info(strFmt("Discount amount pr unit is %1, when buying %2", price/qty, qty ));

    Price = crtSalesLine.get_NetAmountPerUnit();
    info(strFmt("Net amount pr unit is %1, when buying %2", price, qty ));

    Price = crtSalesLine.get_TotalAmount();

    info(strFmt("Total amount is %1 when buying %2", price, qty ));

Maybe some of you can teach me how to expose the CRT in a web-service, so that we can easily

 

 

 

15 thoughts on “DAX2012 R3 – Playing with Retail CRT

  1. Pingback: Dynamics AX / 365 Retail Links | zeeans

  2. Hi,

    Do you have experience on modify the CRT PricingEngine?
    I modified the project as well as Commerce.Runtime.Services and Commerce.Runtime.Services.PricingEngine. And deployed to EPOS.

    However, the debugger can only hit Runtime.Services, but not Runtime.Services.PricingEngine.

    Runtime.Services.PricingEngine was already added to the reference of Runtime.Services.

    Thanks.

    Like

    • Hi Jeff. I have experienced the same, when I tried to debug and look into the code. It can be that you need to debug using the MPOS, and not the EPOS. Not all of the EPOS code is available to us.

      //Kurt

      Like

  3. Hello Waldemar,

    Appreciate your inputs. Just one question, why do you say that you will avoid using AIF? Won’t consuming AIF for integration be faster than using CRT? I mean, I understand that with AIF you will have to write a lot of code to replicate the logic that Microsoft has already done incorporated in CRT. Are there any other reasons?

    Regards,
    Vishnu

    Like

    • Hi Vishnu,

      You recognised the first reason: yes, because CRT is a Retail specific integration layer.
      The second reason is that AIF is getting deprecated in some future version.
      It feels that CRT (at least in context of Retail) is the future.

      Like

  4. Hello Kurt,

    Great post. I have couple of questions and will appreciate your inputs on them.
    1) Is there a single CRT component associated with all channels (retail store, ecommerce store, etc. – because the whole idea behind CRT was to add omni-channel capability to Dynamics AX) or a separate CRT component for each store.
    2) If I have to build an integration solution then what is the advantage of using CRT (Your Integration –> CRT –> Commerce data exchange service –> AOS –>MS AX DB) over AIF (Your Integration –> AIF –> AOS –> MS AX DB), that AX provides by default?
    3) You had talked about using CRT to integrate say Magento with Dynamics AX. When using SharePoint for eCommerce, SharePoint consumes data directly from the CRT database and does not maintain its own database. But with applications like Magento you will end up maintaining data at multiple places (AX DB, CRT Database and Magento Database).

    Looking forward to your response.

    Regards,
    Vishnu

    Like

    • Hi Vishnu,

      We have similar challanges with our eCommerce system. I think it will be more or less for any eCommerce system out there: you have to decide whether you synchronise the data between the system or get them real time.
      For example Products (and related data) most likely have to be stored in the eCommerce’s native database because for fast search. And also because usually the data being “enriched” by the merchandisers.
      However, in example of Customers data (e.g. displaying the Customer’s profile or allowing them to update their own address) you can fetch it directly from the Channel Database via CRT as it is something that happens rarely and you only need to read/write little data.

      If your eCommerce does not have this flexibility and dictates that all the data has to be stored locally in it’s own database, then you have no choice but to synchronize the data periodically (Every 10 minutes? Every night?) between AX ChannelDatabase / CRT eCommerce.
      Here you have to decide whether going through all the layers of CRT/API calls is fast enough or you have to come up with more direct synchronisation between AX and eCommerce. At least initial upload of the data can result in moving millions of records between AX and eCommerce.

      Re AIF: I would avoid using that

      Like

  5. Hi Kurt,

    Do you have an example of code for connect to CRT (retail database / realtime) from external application write on C# ? An projet visual studio?

    I have the retail sdk cu8 but how implement the demo_CRT_GetSalesPrice ?

    Merci beaucoup

    Like

  6. Hi Kurt,

    This is something that still is unclear to me: how much does CRT offer out of the box to allow you to integrate third part non-.NET eCommerce systems?
    How easy it is for example to let’s say update the Customer information (e.g. change the address) via CRT from a PHP web shop? Or to create a sales order?
    I haven’t looked into CRT that much, but I have the feeling that you will still have to write quite a lot of code on top of CRT if your shop is not based on .NET.

    Then there are the bulk synchronisation of master data like products or initial customer synchronisation. In my understanding CRT is not really suited for that.

    Liked by 1 person

    • Hi again. The entire CRT is documented on TechNet, https://technet.microsoft.com/en-us/library/jj916620.aspx

      Does it require any additional coding : Yes.

      The CRT is not a “out-of-the-Box” solution, but the tool that ISV/Partners use to create “out-of-the-Box” solutions. Like a Magento integration. The CRT to provide a DataAccess layer that allows you to Access the CRT database.

      The more you look into it, the better it will look.

      Happy DAX’ing

      Like

      • Hi Kurt,

        Well, I mean sure it is not an out of the box solution for Magento or any other eCommerce.
        What I mean is rather: can I for example give a WSDL to a eCommerce developer (who is not familiar with .NET) and tell him “here is everything you need to integrate our PHP webshop with AX”.
        Obviously he still needs to know all the AX functions (business logic), but purely from technology perspective, do you still need to write code in C# to expose CRT as SOAP / RESTful web services?

        I like the direction Microsoft takes to use more of cross-platform widely adopted technologies, but in this case it still feels like you have to stay in Windows world to easily integrate with CRT. Or write a lot of wrapper code to allow non-Windows world to talk with AX via CRT.

        (again, I didn’t dig into CRT that deep, so I am just finding out myself).

        Thank,
        Waldemar

        Like

      • You are right that the next step with CRT is to wrap the CRT as webservices. This is the right direction to use it with none-Windows systems. 🙂

        Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.