In Microsoft Dynamics NAV we don’t have Abstract Classes or Inheritance. These are modern technologies that make sure that objects in your application have similar elements and signatures.
Despite the lack of these modern concepts NAV does have many tables and codeunits that follow similar structures by design. This has been like this ever since the early days in the 1980s.
This concept is what I refer to as Transaction Mirroring in my books and workshops. It is what makes NAV easy to learn. If you are familiar with Sales-Post you have no issues with Purchase-Post and once you are familiar with Items you probably understand Vendors very easily.
This synchronization is not enforced by anything in the designer. It only exists by the grace of discipline and having smart people working on the core product.
Before you continue reading this, I don’t want to doubt that we have less smart people working on the core product, but a few things in NAV2016 caught my attention when I looked at the details.
If Transaction Mirroring is gets lost, I am afraid this will cause a huge bump in simplicity, design patterns and the learning curve of our developers.
The codeunits that I looked at were Sales-Post and Purchase-Post. Both routines that have been in the system forever and are both loved and hated by many developers.
For the sake of simplicity I will focus on the main part of the codeunit, the OnRun trigger.
Codeunit 80 has 1264 lines in NAV2016, Codeunit 90 has 1258. Long live the line numbers in the new editor.
If you compare these codeunits in a standard tool like Beyond Compare you will see that it matches remarkably well.
If we open the same codeunits in NAV2015, codeunit 80 has 1549 lines and codeunit 90 has 1682. So something has happened and caused both codeunits to reduce in size. 300 lines in one codeunit and 400 lines in the other have been moved.
Personally I think this is a good thing. The codeunits are monsters and not designed according to modern design principles. Also I think a slow refactoring process is better than one big bang.
What has changed?
Let’s take Codeunit 80 first. Most of the changes are done at the beginning of the code.
This is a new function that does the “test near” of the fields in the Sales Header. Used to be 5 lines of code, now 1.
This function checks if the Select fields are properly set. We don’t want “receive” to be active on a Sales Order for example. 17 Lines of code, now 1.
Checking Blocked on Sell and Bill-to customer. 3 lines of code, now 1
The function does that it says (don’t you love readable code). 25 lines of code.
Same as previous, but for receipts. 13 lines of code.
CheckICPartnerBlocked, SendICDocument, UpdateHandledICInboxTransaction
Handling Intercompany. 21 lines of code, now 3
InsertShipmentHeader, InsertReturnReceiptHeader, InsertInvoiceHeader, InsertCrMemoHeader
One of my favorites, moving some of the INSERT statements to their own functions. Over 100 lines of code replaced by 4 readable lines.
Then, a lot of code is unchanged… until…
Creating the Resource Journal Line
SalesShptLine.InitFromSalesLine, WhseShptLine.GetWhseShptLine, WhseRcptLine.GetWhseRcptLine, ReturnRcptLine.InitFromSalesLine, WhseRcptLine.GetWhseRcptLine, WhseShptLine.GetWhseShptLine, SalesInvLine.InitFromSalesLine, SalesCrMemoLine.InitFromSalesLine
Some other great ones, moving code to be a member of the table. Someone is watching my videos. 😉
This is the last one, clearing variables. 8 lines replaced by 1.
Now let’s look at codeunit 90. Here we see a lot of similar changes, but not all changes that are done to 80 are done to 90. This is where I have an issue. Let me highlight some differences
SetShipInvoiceReceiveFlags does not exist in 90, it is in 80. Why? I see no reason to make a difference.
CheckTrackingAndWarehouseForShip & CheckTrackingAndWarehouseForReceive same issue.
Codeunit 90 has a function SetupGenJnlLine. This does not exist in codeunit 80 while 80 has a function for creating a balance entry, 90 has not.
These are just a few examples. I don’t want to bore you with too many details.
In general the team has made a great start in cleaning up codeunit 80 and 90, and some of the differences have started in earlier versions. In general I would like to ask to be careful with refactoring and preserve the transaction mirroring. This is a great concept and makes it easier for new developers to learn the application.
Test Near, Test Far, Do It, Clean Up
You might recognize this from one of my videos or from my book. This is another core principle of Dynamics NAV, part of our DNA. Something that also is getting lost in these codeunits, but more about that in another post.
Are there different versions of Nav 2016. The one which I downloaded from MIBUSO still has codeunit 80 looking pretty much the same as in previous versions. Check how codeunit 80 starts on my Nav 2016 …
OnRun(VAR Rec : Record “Sales Header”)
IF PostingDateExists AND (ReplacePostingDate OR (“Posting Date” = 0D)) THEN BEGIN
“Posting Date” := PostingDate;