A flight plan for TMS in AX 2012 R3

Posted: June 5, 2014 in Dynamics AX 2012

One of the new modules in AX 2012 R3 is Transportation Management System (TMS). TMS allows us to shop for transportation rates based on mileage or weight for moving goods from point A to point B. However there is not a lot of documentation available yet on this subject. In this post I will try to give a short overview of TMS.

We all learn in different ways. For example if you have to remember the parts of an engine, some (people with good memory) can look at all the parts of an engine and that would be enough. However someone like me would need to see the engine as a whole together. Looking at the way the parts interact helps me remember better. So if you are like me and you want to understand TMS then i will try to draw a mental picture of the TMS engine so that you can remember it easily.

First I will list the different parts down and next i will show you how they connect. Since there are a lot of parts and some parts have a lot of sub-components i will try to give you a 100,000 ft and 30,000 ft overview first then dive in a little bit more and explode the pieces into their sub-components.

For the sake of making this post simple I am leaving out Routes, Freight charges, Carrier fuel index etc. I will try to cover them in later posts.

100,000 Ft View
Rate Route Workbench : The main form that allows a user to calculate a rate for transportation. You can do a rate shopping here that will list the rates from all the transportation carriers that have been setup in AX. The rate is based on your requirement which is usually say a sales order or a transfer order in moving goods from warehouse to customer or another warehouse location. The transportation charges are usually dependent on both Mileage and Weight. But since you cannot calculate on both simultaneously in AX, what you would do is make one of them constant.

Example for rate by mileage: When you want to rate by mileage you would like to keep weight constant. You can do this by saying you will send a full truck load. So if you order a full truck load then the rates are based on the number of miles the truck load of items have to be moved. What we would need to do is to populate a table (from a form in AX Client) with origin postal code, city, state and destination postal code, city, state and the miles. There is no calculation but basically based on the origin and destination of your transfer order or sales order we can pull out the miles.
MileageDetails

Example for rate by weight: When you want to rate by weight you can make mileage constant by specifying the origin and destination location. Then all you would need to do is for this combination of origin and destination fill in the rate for the different weight ranges. So the columns could be : origin postal code, destination postal code, weight <100 lbs, weight <500 lbs, weight < 1000 lbs, weight < 5000 lbs, Weight Over 5000 lbs. Once we have a table like this filled up then based on the weight of the items being shipped, origin and destination we can figure out the rate.
WeightDetails

30,000 Ft View
Shipping carrier : Shipping carriers are the ones providing service to transport your goods. To get any rate you need to set up shipping carriers first. To get a rate from the shipping carrier you need to check the “Activate carrier rating” and the “Use carrier” check boxes.

Service : Shipping carriers will supply services. Each shipping carrier’s service is made up of the mode of transportation, mode of delivery and the load template. When doing a rate shop the number of rates you will get back is equal to the sum of all the shipping carrier services from all shipping carriers.
ShippingCarrier

Rate Engine : This is the heart of the entire rating process and will calculate and return a rate. We create a rate engine in AX client and set its properties to an assembly (dll) and the class within the dll that will execute the code to figure out the rate based on all other selected parameters. A rate engine is composed of a number of components including Rate Base assigner, Mileage Engine, Apportionment engine etc..
RateEngines

Rate Master : The primary use of a rate master is to allow us to define all the origins and for each origin setup a list of destinations. If we do not setup a rate master, we will not be able to locate the rate because we cannot map an origin/destination address combination to a rate.

Rating Profile : A rating profile defines which rate master should be used by which shipping carrier.

So how does the rating process work?

  • Getting a rate is based on your origin and destination addresses
  • Addresses are composed of Country, City, State/Province, Postal code. You can use all or only a few of these address components to identify an origin/destination
  • Setup Shipping carriers and their services because rates are given by shipping carriers
  • Next you need to set up a rate engine. The rate engine is linked to the code/logic that will be used to arrive at a rate. The rate engine will also decide which of the components of the address it should use to arrive at the origin and destination combination.
  • Next Rate Master and Rate Base have to be setup. Rate Master will allow us to set up all the possible destinations (called Rate Base assignments) and Rate base will allow us to set up all the destinations. Typically for each origin we will setup a different rate base, which will essentially give us all the origin/destination combinations.
  • Finally a rating profile will connect a shipping carrier to Rate engine and Rate master
  • The rating process is in essence a 2 step process. The first step is to identify which origin record to pick. Next, based on the origin you picked you will get a list of destinations, so you need to now pick the correct destination record from the list of destinations.
  • To re-word this in TMS terms: Loop through each rating profile setup for a carrier and for each rating profile select the rate master. Under a rate master a list of rate base assignments are setup. You now need to pick the correct rate base assignment based on the origin address details. (Each rate base assignment record has fields like origin city, origin postal code and the corresponding rate base). From the rate base assignment selected you now need to take the rate base and loop through all the rate base details setup under the rate base. Each rate base detail has columns like destination city, destination postal code etc… and finally the rate. Once you have found a matching rate base detail you can now return the rate!!!
  • Rate Base assignments point to origins
  • Rate Base details point to destinations

Core Components
Rate Base Type : Think of Rate base type as metadata. You define the metadata for which you need to capture information. So what kind of metadata does this define? It allows you to define origin and destination address components like origin city, origin postal code, destination city, destination country etc… You can define two different types of metadata fields: “Rate base” and “Assignment“. The fields that are defined as Rate base are used in identifying the origin address components and the fields that are defined as Assignment can be used to identify the destination address components.
RateBaseType

Rate Base : Allows you to define the list of origins and link the list of destinations to each origin.
Break Master : This is a setup of the break-up of the Mileage or Weight. You use a break master with a destination to define the rate. For example a break master would be: <500 lbs, <1000 lbs, <10,000 lbs, Max lbs
Rate Base Assignment : Each rate base assignment points to an origin and links to the destination. Columns we see are the fields (of FieldType Assignment) from Rate Base Type selected against the Rate Master.
– Load Template : Defines the dimension of the load and also the max weight. This is linked to a carrier service to place restrictions on which services are available for rate shopping.

Code Components
– Rate Base Assigners (Always checks the table TMSRateBaseAssignment based on criteria. Common criteria are Carrier Service code, rate master code and scheduled ship date are matched)
– BaseRateAssigner (abstract class)
– MileageRateBaseAssigner : Nothing specific
– P2PRateBaseAssigner : Additional criteria is Dimension1 is equal to city, dimension2 is state, dimension3 is postalcode and dimension4 is countryregion, return first row.
– PieceRateBaseAssigner : Additional criteria is Dimension1 is pickup postal code, dropoff postal code is between dimension2 and dimension3, dimension4 is dropoff country
– PostalZoneWeightRateBaseAssigner : Nothing specific
– RailRateBaseAssigner
– LtlRateBaseAssigner
– LtlFakRateBaseAssigner

Issues
When i try to do a Rate shop, ran into the following issues

Issue 1: Rate base assignment cannot be found
Solution: This is typically because the Rate master for the service of the carrier is not setup or a matching rate base assignment was not found. To fix this go to Rate Master setup (for the carrier) and add a new rate base assignment for that particular carrier service and your origin address (and based on your rate engine parameters).

Issue 2: Rate base detail could not be found
Solution: The rate assignment is properly picked, however the rate base detail identifying the required info is not setup for passing to the rate base to figure out the rate is not setup. Create a proper rate base detail that matches your destination address.

Issue 3: Error processing BaseRateBroker, TMSException. When i dug deeper into the exception, the error was basically because of string to numeric conversion.
Solution: This was because of the setup of Rate Base Type. The rate base type had 3 fields of field type rate base. When i used this to create a rate base, 2 of these fields get added along with all the break master fields. I specified string values for these two new fields in the details row for rate base. Changed these to numbers and it worked. These values are stored in generic fields like Dimension1, Dimension2 etc in table TMSRateBaseDetail and the way these values are interpreted depends on the rating engine being used.

I also noticed the same issue when the mileage engine was not properly defined. Rather the mileage engine parameters. I had accidentally deleted the mileage engine, so i just set it up again and defined the mileage engine parameters and it worked. Again whenever we specify an assembly and a class, we have to define the parameters (with data types) exactly as required by the class.

Issue 4: Mileage detail could not be found.
Solution: The fix for this is in the Mileage engine. In Mileage engine -> Details section -> Add a new Pick-up postal code and drop-off postal code that match your load’s from and to postal codes.

Notes
Note 1: Rate base type can be specified at multiple points so that could lead to setup confusion. For example Rate base type has to be specified when you create a rate engine, you also need to specify the rate base type in Rate Master. However the rating profile brings together Rate Engine and Rate Master together and if they have different rate base types you would get validation errors.
Note 2: You can access rating profiles directly from the rating profile link under Setup->Rating or you can also go through the Shipping Carrier link under Setup->General. Rating profiles are essentially carrier specific and the combination of the carrier services and rating profiles under a carrier will give a list of all the possible rates. (Basically rate by carrier service).
Note 3: There is a little bit of hard-coding in TMS. For example the number of possible rate base assignment and rate base detail columns are limited to a maximum of 6. There are generic columns with names from Dimension1…Dimension6.
Note 4: You create a Rate base based on a Rate Base Type. The columns displayed in rate base detail are based on the fields of type Rate base defined in the Rate Base Type. Also additional columns displayed are based on the break master that is used to create the Rate base.
Note 5: You create a Rate base assignment (under rate master) based on the Rate Base Type defined under the rate master. The columns displayed in the Rate base assignment are based on the fields of type Assignment defined in the Rate Base Type.

Summary : There is so much more that I can write, for example about how to setup the Rate base detail or how to set the correct parameters for the rate engine. The parameters of rate engine are very important as this could potentially make or break your rate shop functionality for that carrier. Also there is the question of mileage engine. I think it is too much to cover in one blog, hopefully at least this blog post gives you a good jump-start.

Comments
  1. I found your article to be a very good overview of the TMS. I’m struggling with setting up Rate Masters that work. Your Summay statment regarding the rate engine being important is spot on. If you have any insights on that please share.

    We are early in the Design Phase of setting up AX R3 at Masonite for our global company.

  2. vgrandhi says:

    It is a question of chicken/egg situation. You need to know what information you can provide to help the rating engine provide you a rate. Let me try to explain it using an example.

    For example in our case we only have origin city, state and destination city, state information available to get a rate. The rate then is further broken down by weight.
    So the data would like
    Origin: Toronto, Ontario
    Destination1: Detroit, Michigan
    Rate by weight is: <1000lbs = $78, 1001lbs-2000lbs – $68, 2001lbs-5000lbs – $58, 5001lbs-10000lbs – $48
    Destination2: Montreal, Quebec
    Rate by weight is: <1000lbs = $50, 1001lbs-2000lbs – $40, 2001lbs-5000lbs – $30, 5001lbs-10000lbs – $20

    To get rate based on this information, what would you have to do, what do you need to create?
    1. You need to find the common factors in this information.
    1a. The common factors are the rate break (not rate) which is Rating and you should see a list of all rate engines and rate base assigners. I picked for example P2PByWeightRateEngine.cs. In that there are 2 important methods, Rate and RetrieveRateBaseDetail. If you look at the code in Rate method, it is trying to locate the RateBaseAssigner. And based on the rate base assigner it tries to retrieve the RateBaseDetail. The method RetrieveRateBaseDetail has the following code which it executes to retrieve the correct detail record
    public virtual TMSRateBaseDetail RetrieveRateBaseDetail(TransactionFacade transactionFacade, TMSRateBase rateBase, XElement dropOff, decimal weight)
    {
    var dropOffCity = dropOff.GetString(AddElementXmlConstants.City);
    var dropOffState = dropOff.GetString(AddElementXmlConstants.State);
    var dropOffPostal = dropOff.GetString(AddElementXmlConstants.PostalCode);
    var dropOffCountry = dropOff.GetString(AddElementXmlConstants.CountryRegion);

    var rbds = DIFactory.TmsRepository.GetRateBaseDetails()
    .Where(x =>
    x.RateBaseCode == rateBase.RateBaseCode
    && (x.Dimension1 == dropOffCity || x.Dimension1 == “”) // city
    && (x.Dimension2 == dropOffState || x.Dimension2 == “”) // state
    && (x.Dimension5 == dropOffCountry || x.Dimension5 == “”) // country
    && (dropOffPostal.CompareTo(x.Dimension3) >= 0 && dropOffPostal.CompareTo(x.Dimension4) (x.Dimension6.ToDecimal() > weight))
    .OrderBy(x => x.Dimension6.ToDecimal()).FirstOrDefault();

    return rbd;
    }
    From this we can see that it expects the fields City, State, PostalCode and CountryRegion to be defined. Also it is ok for city, state and country to be blank but it expects postalcode to be in a certain range. It also indicates in what position it expects the fields to be. The first fields should be city, second state, third the min postal code, fourth the max postal code, fifth the country region. So in your rate base detail you need to have these fields in the same order.

    The fields in your Rate base assigner and rate base detail come from the rate base type. The rate base type has fields of 2 types, Rate base and assignment. The fields of type assignment are displayed in rate base assignment screen, and the fields of type rate base are displayed on the rate base detail screen. Hope this helps.

  3. sundeep says:

    Error R004, Routing Guide cannot be found While running Route engine nothing is coming even though i setup & configured everything Need help

    • vgrandhi says:

      I don’t know what your setup is like, however from reverse engineering the code i can say that either the route guide setup on shipping template is not valid anymore Or the result for your route guide is not setup.

      Both of these shouldn’t really happen because there is form level validation. Unless i know more about your setup i cannot help you out more.

      You can always go through the code in the visual studio C# project Microsoft.Dynamics.AX.Tms.

      • sundeep says:

        Thanks Vishy its working ..my setup was wrong.. I just clear the fields in routing guide the hub destination & hub collection

  4. sundeep says:

    Now I am facing new issue I need to get rate as per my to address and from address If I am shipping via FedEX or UPS …How I should i get it via Rate shop . I provide all the website link and to and from address(e.g. postal code , country etc.) in this shipping carrier But how it will integrate with existing shipper.

  5. sundeep says:

    One more issue with container :I just need restriction based on container limit with my item volume or unit based e.g. My container size i should able to define can contain 10 boxes then it wont allow me to put 11 boxes in the same container and when i close the container it should through me error… Till now what i came to know i select me container and select item and in the quantity field i can enter any number of quantity and can pack and close ..it only check on the basis of container with weight limit not on unit based or volume based limit. Weight based limit cannot solve my problem as item may be heavy or light one but volume is same.. Need help

  6. Matteo says:

    Hi Vishi,
    First of all thanks for your post, it’s really hard to find out something about TMS!

    My problem is the issue number 3, so a TMS Exception: Errore RateShopBroker, TMSException.

    I can’t understand how to fix this problem and where I’ve not to put a string in the rate base type.

    Big thanks and it’ll be great if you can contact me with a PM 😉

    Matteo.

Leave a comment