One thing that every user cares about on every single sales order is the totals. After adding all of the items to a sales order in Microsoft Dynamics 365 for Finance and Operations, the totals show you how much tax, shipping, sub-total and overall total money is owed. In this article I will show you how to view the D365 sales order totals. As well as how to access these values through x++ code.
View The Sales Order Totals
To start, I will show you what many of you may already know. How to view the D365 sales order totals on the sales order form.
First, in D365, go to Accounts Receivables > Orders > All sales order.
Alternatively, you can just search for ‘all sales orders’ in the search bar. I tend to use the search box for most things. This approach just requires you to remember the name of forms.
Next, you can access the totals from this grid of all sales orders. Or, you can drill into the details form. The steps are the same. In this example, I am going to view the details. Click on the sales order number, to drill into the sales order details.
Finally, on the action pane, on the Sales order tab, in the ‘View‘ group, click the ‘Totals‘ button.
Additionally, you can view Microsoft’s documentation here.
Call Center Sales Order Summary
There is another common way that D365 sales order totals are shown. The sales order form can be setup in a few different ways. One way, is to use it for a call center.
In this article, I will not go through the details. However, you can follow this Microsoft documentation to setup a call center. Then, add your users to the list of call center users.
Afterwards, any sales orders you create, will have a ‘Complete‘ button on the sales order details form.
When a user clicks the ‘Complete’ button, the system will show an order recap screen. Also known as the Sales order summary screen. This screen will also show you the totals of a sales order.
This is a useful workflow for users who may be on the phone with a customer. And they need to share the totals details before accepting payment, and submitting the order for picking, packing, then invoicing.
Access Sales Order Totals In Code
So far, you have learned how to view the totals using the user interface of the system. Now, I will show you how you can access the D365 sales order totals information using x++ code.
Create Runnable Class (Job)
To demonstrate, first create a D365 runnable class (job). This will allow us to write x++ code, run it, and see it work. If you are unfamiliar with how to create a job, please see my article on How To Write A D365 Runnable Class (Job).
First, in Visual Studio, create a new project. I named mine ‘D365_Sales_OrderTotals‘.
Second, right click on your project in the Solution Explorer and select ‘Add New>Item‘. Then select ‘Runnable class (job)‘ from the list of Dynamics 365 Items. Next, enter a name for the name. I named mine ‘TestSalesOrderTotals‘.
The system creates a class named ‘TestSalesOrderTotals‘, with a ‘main‘ method. We will enter code in the ‘main‘ method to demonstrate how to get the D365 sales order totals. You can then copy this code to wherever you need it.
Calculate The Totals
In order to get any specific order total, we need to start with the same three steps.
First, retrieve the sales order you are interested in seeing the totals for, and put it into a salesTable buffer. In this example, I used the sales ID “012517”. Replace this with a sales order ID that exists in your environment. The code for this looks like this:
class TestSalesOrderTotals
{
public static void main(Args _args)
{
SalesTable salesTable;
SalesId salesId = "012517";
salesTable = SalesTable::find(salesId);
if (salesTable)
{
//calculate totals
}
}
}
Second, instantiate the class named SalesTotals. Namely, this class, and its parent class TradeTotals, and its child classes, contain the code needed to calculate the D365 sales order totals. Pass the salesTable table buffer into the construct method. See the code below.
class TestSalesOrderTotals
{
public static void main(Args _args)
{
SalesTable salesTable;
SalesId salesId = "012517";
salesTable = SalesTable::find(salesId);
if (salesTable)
{
//calculate totals
SalesTotals salesTotals;
salesTotals = SalesTotals::construct(salesTable, SalesUpdate::All);
}
}
}
Thirdly, add this code “salesTotals.calc();” to the ‘calc‘ method on the salesTotal class. This will run all of the needed code to calculate the order totals. Then, it will store each total in class variables that we can read from.
//calculate totals
SalesTotals salesTotals;
salesTotals = SalesTotals::construct(salesTable, SalesUpdate::All);
salesTotals.calc();
Next, I will explain how to read out a specific total.
Read Total Amount
As part of the sales order calculation, the system will store in memory many different components that make up the D365 sales order totals. For example, the order total, the tax amount, the total line discounts, and many more.
After selecting a sales order, instantiating the SalesTotals class, and calling the ‘calc’ method, we can now read whichever values we are interested in.
First, I will show you an example. Then, I will show you how to find all of the other totals.
Add the following code to the Runnable Class (Job).
class TestSalesOrderTotals
{
public static void main(Args _args)
{
SalesTable salesTable;
SalesId salesId = "012517";
salesTable = SalesTable::find(salesId);
if (salesTable)
{
//calculate totals
SalesTotals salesTotals;
salesTotals = SalesTotals::construct(salesTable, SalesUpdate::All);
salesTotals.calc();
AmountCur totalAmount;
totalAmount = salesTotals.totalAmount();
Info(strFmt("Total amount: %1", totalAmount));
}
}
}
To explain, the above example, creates a variable named ‘totalAmount‘. It is of type ‘AmountCur‘, which is an extended data type that can store decimal values.
Next, the code calls the method totalAmount on the salesTotals class. This method reads from this class the total balance remaining on the sales order.
Finally, the code calls the ‘info‘ method to print out the value of totalAmount so we can see it.
Other Totals
Additionally, there are many other D365 sales order totals that can be viewed relating to a sales order. The best place to see them, is to open the parent class named ‘TradeTotals‘.
First, go to the Application Explorer, and type ‘Trade Totals’. Second, right click on the TradeTotals class, and select ‘Open designer’. Third, look through the names of the methods. Many of these methods return different totals relating to the sales order.
For example, I have added the code to calculate the total tax amount, the total line discount amount, and the total miscellaneous charge amount. (The total miscellaneous charge is often referred to the total shipping amount, though these are not necessarily the same thing).
class TestSalesOrderTotals
{
public static void main(Args _args)
{
SalesTable salesTable;
SalesId salesId = "012517";
salesTable = SalesTable::find(salesId);
if (salesTable)
{
//calculate totals
SalesTotals salesTotals;
salesTotals = SalesTotals::construct(salesTable, SalesUpdate::All);
salesTotals.calc();
AmountCur totalAmount;
totalAmount = salesTotals.totalAmount();
Info(strFmt("Total amount: %1", totalAmount));
AmountCur totalTaxAmount;
totalTaxAmount = salesTotals.totalTaxAmount();
Info(strFmt("Total tax amount: %1", totalTaxAmount));
AmountCur totalLineDiscount;
totalLineDiscount = salesTotals.totalLineDisc();
Info(strFmt("Total line discount amount: %1", totalLineDiscount));
AmountCur totalMarkup;
totalMarkup = salesTotals.totalMarkup();
Info(strFmt("Total shipping amount: %1", totalMarkup));
}
}
}
Now, let us see this in action. First, right click on the Runnable Class (job), and select ‘Set as Startup Object’. Then click the ‘Start‘ button in Visual Studio. A browser will open, and display the info messages.
There are many more methods on the TradeTotals class that can provide you with the specific total you are looking for.
Invoice Totals
Importantly, the above code will calculate the totals for the un-invoiced portions of the sales order. After invoicing a sales order, the status of the invoiced quantities and invoices sales lines change. And then, they are no longer included in the same totals.
If you consider, this makes sense. Typically, when looking at the order totals, you are interested in how much is on the order that you are paying to have shipped to you right now. You are no longer interested in the totals of the portion of the order that was shipped to you earlier.
That said, there are methods on the salesTable table that can return the invoiced totals. Hence, these can be combined with the un-invoiced totals, to always return the full order totals. See the below code as an example.
// totalAmount is the sales order balance due amount
//+ previously invoiced amounts
totalAmount = salesTotals.totalAmount()
+ salesTable.amountInvoiced();
// totalTaxAmount is the sales order tax amount
//+ any previously invoiced tax amounts. Same applies to charges and discounts.
totalTaxAmount = salesTotals.totalTaxAmount()
+ salesTable.taxAmountInvoiced();
totalLineDiscount = salesTotals.totalLineDisc()
+ salesTable.lineDiscInvoiced();
totalMarkup = salesTotals.totalMarkup()
+ salesTable.markupInvoiced();
Summary
Whether you are writing code that needs to read the D365 sales order totals, or you need to add a new order total, the SalesTotals class is where you need to start. After selecting a sales order, instantiating the SalesTotals class, and calling the ‘calc‘ method, the order totals can be read. The TradeTotals parent class contains most of the methods you need to view any order total. Since the sales order form is probably the single most used and customized form in Microsoft Dynamics 365, I thought it was worth explaining.
Hi Peter
We need to send this sales totals to a third to a third party
How can we utilize computed column.
There are a few options. You can use a computed column on a data entity. Though that might hinder performance. You might consider staging the data in a custom table using a batch job that loops through the orders. Then have a data entity for that table. There are quite a few good and bad things with each approach. So it will definitely depend on your scenario and how much data you are exporting as to the best approach.
Thank you Peter for your work! You are always helpful 🙂
Thank you for your kind words!
Hey Peter,
In the sales order line, there is field called lineAmount and also the CalcLineAmount() function.
public AmountCur calcLineAmount(Qty _qty = this.SalesQty)
{
return this.salesPurchLineInterface().calcLineAmount(_qty);
}
this is the standard method in salesline table, could you please suggest me where it is getting stored
Hey Peter,
public AmountCur calcLineAmount(Qty _qty = this.SalesQty)
{
return this.salesPurchLineInterface().calcLineAmount(_qty);
}
this is the standard method in salesline table, could you please suggest me where it is getting stored
There is a lineAmount field on the sales line that stores this result, I believe. You can right click on the method in visual studio and select “find all references”. This will show you were this method is called from and you can see where is code the lineamount field is set using this method.