The upcoming Dynamics 365 Business Central 2020 Wave 1 release (version 16) introduces the concept of Interfaces in AL.
An interface is used when you want to decide which capabilities need to be available for an object, while allowing actual implementations to differ, as long as they comply with the defined interface. This allows for writing code that reduces the dependency on implementation details, makes it easier to reuse code, and supports a polymorphing way of calling object methods, which again can be used for substituting business logic.
With the new AL language version, you can use the new interface object to declare an interface name along with its methods, and apply the implements keyword along with the interface names on objects that implement the interface methods. The interface object itself does not contain any code, only signatures, and cannot itself be called from code, but must be implemented by other objects. The compiler checks to ensure implementations adhere to assigned interfaces.
A great post that describes interfaces in AL was written by Tobias Fenster some weeks ago and you can find it here.
As I’ve described in my previous post, Microsoft is using the interface object in the new version 16 codebase on different places and the first place that comes to my eyes when building my apps for version 16 was on the sales price calculation module.
Dynamics 365 Business Central 2020 Wave 1 (or version 16) has a totally new way of handling sales prices based on AL Interfaces. If you check for example the OnValidate event of the Quantity field of the Sales Line table, now you can see that the new Interface “Price Calculation” object is used:
In this OnValidate trigger, to retrieve the price for the Sales Line record the AL code calls a GetPriceCalculationHandler procedure as follows:
Inside this procedure, there’s a call to a GetHandler method (defined in the Price Calculation Mgt. codeunit) by passing the interface:
The GetHandler method retrieves from the Price Calculation Setup table the value of the Implementation field and then call the Init method defined in the interface itself:
This field is an enum field type called Price Calculation Handler:
and the enum is defined as follows:
As you can see, you can extend it with your own implementation’s values.
The PriceCalculation interface is defined as follows (contract):
What happens in the new 2020 Wave 1 codebase? A marvellous thing… the new price calculation implementation based on interfaces permits you to define your custom price logic by implementing the PriceCalculation interface on a separate codeunit. If you want to add your custom price management logic to Dynamics 365 Business Central, now you don’t have to modify code or interact with events raised by the standard, but simply add your new interface implementation (codeunit) and add it on the Price Calculation Setup table.
The standard codebase has two implementations for the PriceCalculation interface: Price Calculation – V15 (logic until Dynamics 365 Business Central version 15) and Price Calculation – V16 (the new logic for Dynamics 365 Business Central version 16). This is how Price Calculation – V16 is implemented:
and this is the the implementation for Price Calculation – V15 (as you can see, it’s declared as ObsoleteState = Pending):
To create your custom price calculation in your extension, just add a new value in the Implementation field in the Price Calculation Setup table with an enumextension object:
and then create a new codeunit inside your extension by implementing the Price Calculation interface and add your custom logic in the ApplyDiscount and ApplyPrice methods:
Very clean and elegant… 😉
Are there any shortcuts to implement the interface members? Or do we need to look them up one by one based on the error output window? 🙂
There are no shortcuts actually for this…
I saw some comments about a quick action “implement interface”, discussed here:
But I do not see that quick action anywhere? I must be missing something?
I’m not at my machine for testing. I was not aware of this feature in standard AL language. Maybe it’s related to standard VS Code Quick Actions (CTRL + . ) where there’s the “Implement Interface” action.
Sadly I checked, it says no action available.
If/When you check it out, can you please come back to this comment? There is so little info online…
Enjoy the weekend, and stay safe.
Hi Stefano, thank you for the nice article. I tried to implement my own Price Calculation interface based on your suggestion above – so I created Enum for Price Calculation Handler, new codeunit in order to implement new calculation and at the end I’ve added new line into Price Calculation Setup table with new implementation. Unfortunately the program still don’t use my new implementation and still use standard V15 calculation. I checked the code and found the problematic part in codeunit 7001 – in procedure FindSetup where the program exited because of IsExtendedPriceCalculationEnabled() method which is false in my case and then V15 is used. Did you experience the same problem or do you have some idea how to set ExtendedPriceCalculationEnabled to true in order to leave the program to use my own implementation? Thanks in advance for any help. Have a good day.
Price calculation are based on the Price Calculation Setup table. I suggest to check this new page that explains how to extend it:
Subscribe to this event and set to true
[EventSubscriber(ObjectType::Codeunit, codeunit::”Price Calculation Mgt.”, ‘OnIsExtendedPriceCalculationEnabled’, ”, false, false)]
local procedure HandlePriceCalculationMgtOnIsExtendedPriceCalculationEnabled(var Result: Boolean)
Result := true;