Working with dates in AL vs. C/AL

It’s friday afternoon and I’m goofing around a bit with the ForNAV AL Converter. I ran into something I want to share.

AL seems to be more strickt in hardcoded dates than C/AL.

Example

Constant value '99993112D' is outside the range for a Date. The syntax for defining Date format is yyyymmddD, where D is a mandatory letter. For example, 20180325D, read as the 25th of March, 2018.

This should be 99991231D but C/Side exports it using your regional settings.

Fortunately we can fix this in C/Side by changing the code to

DMY2DATE(31,12,9999)

I only have to replace 42 instances for the project/partner I’m currently working on. Thank god it’s friday afternoon. 😉

Mapping Codeunit 10201 “Transfer Custom Fields” to Events (NA Only)

By Steve Krisjanovs

Below is a list of all COD10201 external functions and where I believe their event equivalents live in. There were three functions in the list below that had me stumped so a second set of eyes would be helpful.

I do still believe that BC’s out of the box COD10201 should still have been modified by MS to indicate that all of these external functions are dead.

The problem I encountered, was because nothing has changed with this codeunit from NAV to BC (the codeunit exists, but all objects that used to call this codeunit no longer do that in BC), the NAV merge tools merged/upgraded our legacy modified cod10201 without any issues since it couldn’t find any conflicts. This could have been an avoidable scenario e.g. if the BC functions in this codeunit threw a runtime error at the beginning of each function call (e.g. “Depricated! Use {event pub object type} {event pub object ID}.{event pub name}”) our merge tools would have caught the conflict and I could have investigated much sooner in my merge/upgrade efforts.

  • [External] GenJnlLineTOGenLedgEntry(VAR GenJnlLine : Record “Gen. Journal Line”;VAR GenLedgEntry : Record “G/L Entry”)
    • maps to COD12.OnAfterInitGLEntry
  • [External] GenJnlLineTOTaxEntry(VAR GenJnlLine : Record “Gen. Journal Line”;VAR TaxEntry : Record “VAT Entry”)
    • maps to COD12.OnBeforeInsertVATEntry
  • [External] GenJnlLineTOCustLedgEntry(VAR GenJnlLine : Record “Gen. Journal Line”;VAR CustLedgEntry : Record “Cust. Ledger Entry”)
    • maps to COD12.OnAfterInitCustLedgEntry
  • [External] GenJnlLineTOVendLedgEntry(VAR GenJnlLine : Record “Gen. Journal Line”;VAR VendLedgEntry : Record “Vendor Ledger Entry”)
    • maps to COD12.OnAfterInitVendLedgEntry
  • [External] GenJnlLineTOBankAccLedgEntry(VAR GenJnlLine : Record “Gen. Journal Line”;VAR BankAccLedgEntry : Record “Bank Account Ledger Entry”)
    • maps to COD12.OnPostBankAccOnBeforeBankAccLedgEntryInsert
  • [External] BankAccLedgEntryTOChkLedgEntry(VAR BankAccLedgEntry : Record “Bank Account Ledger Entry”;VAR CheckLedgEntry : Record “Check Ledger Entry”)
    • maps to COD12.OnPostBankAccOnBeforeCheckLedgEntryInsert
  • [External] VendLedgEntryTOCVLedgEntryBuf(VAR VendLedgEntry : Record “Vendor Ledger Entry”;VAR CVLedgEntryBuf : Record “CV Ledger Entry Buffer”)
    • maps to TAB382.OnAfterCopyFromVendLedgerEntry
  • [External] CVLedgEntryBufTOVendLedgEntry(VAR CVLedgEntryBuf : Record “CV Ledger Entry Buffer”;VAR VendLedgEntry : Record “Vendor Ledger Entry”)
    • maps to TAB25.OnAfterCopyVendLedgerEntryFromCVLedgEntryBuffer
  • [External] CustLedgEntryTOCVLedgEntryBuf(VAR CustLedgEntry : Record “Cust. Ledger Entry”;VAR CVLedgEntryBuf : Record “CV Ledger Entry Buffer”)
    • maps to TAB21.OnAfterCopyCustLedgerEntryFromCVLedgEntryBuffer
  • [External] CVLedgEntryBufTOCustLedgEntry(VAR CVLedgEntryBuf : Record “CV Ledger Entry Buffer”;VAR CustLedgEntry : Record “Cust. Ledger Entry”)
    • couldn’t identify a suitable event mapping
  • [External] ItemJnlLineTOItemLedgEntry(VAR ItemJnlLine : Record “Item Journal Line”;VAR ItemLedgEntry : Record “Item Ledger Entry”)
    • COD22.OnAfterInitItemLedgEntry
  • [External] ItemJnlLineTOPhysInvtLedgEntry(VAR ItemJnlLine : Record “Item Journal Line”;VAR PhysInvtLedgEntry : Record “Phys. Inventory Ledger Entry”)
    • maps to COD22.OnBeforeInsertPhysInvtLedgEntry
  • [External] ItemJnlLineTOValueEntry(VAR ItemJnlLine : Record “Item Journal Line”;VAR ValueEntry : Record “Value Entry”)
    • maps to COD22.OnAfterInitValueEntry
  • [External] JobJnlLineTOResJnlLine(VAR JobJnlLine : Record “Job Journal Line”;VAR ResJnlLine : Record “Res. Journal Line”)
    • maps to TAB207.OnAfterCopyResJnlLineFromJobJnlLine
  • [External] JobJnlLineTOItemJnlLine(VAR JobJnlLine : Record “Job Journal Line”;VAR ItemJnlLine : Record “Item Journal Line”)
    • maps to TAB83.OnAfterCopyItemJnlLineFromJobJnlLine
  • [External] JobJnlLineTOGenJnlLine(VAR JobJnlLine : Record “Job Journal Line”;VAR GenJnlLine : Record “Gen. Journal Line”)
    • couldn’t identify a suitable event mapping
  • [External] JobJnlLineTOJobLedgEntry(VAR JobJnlLine : Record “Job Journal Line”;VAR JobLedgEntry : Record “Job Ledger Entry”)
    • legacy NAV called from this from COD1012.CreateJobLedgEntry(…) but there doesn’t appears to be any suitable event pub in BC
  • [External] ResJnlLineTOResLedgEntry(VAR ResJnlLine : Record “Res. Journal Line”;VAR ResLedgEntry : Record “Res. Ledger Entry”)
    • maps to COD212.OnBeforeResLedgEntryInsert

AppSource; Prefix, Suffix & Intellisense

This article was triggered by a discussion on Yammer yesterday that I felt went a bit sideways.

Business Central is a first class cloud citizen and it beats born in the cloud solutions easily but fact remains that it’s based on Navision, an ERP solution with a 30-some year legacy.

Part of that legacy is a requirement for unique names in the objects, also in the cloud.

Microsoft is working hard to remove this requirement hence it’s a temporary fix but the result is that every app on AppSource needs a three letter prefix or suffix.

You can register your TLA with Microsoft and when this is done nobody else can use it.

With Per-Tenant extensions you don’t need prefixing and I would actually recommend against it since there may be a fair change you’ll use one that is used by one of the apps.

At ForNAV I am primary responsible for the App we have on AppSource and we Prefix everything with ForNAV, hence we reserved “FOR” as a prefix.

I am probably a little autistic and I like stuff that looks clean, so my C/Side looks like this:

Had I suffixed everything it would have been so ugly to look at.

What about Intellisense?

If you watch my YouTube video’s or if you attended one of my classes you’ll have heard me say I recommend suffixing so this sticks into peoples heads.

However this is on a totally different topic. This recommendation is for people who are so stubborn that they want to cling on to Hungarian notation. This will affect Intellisense.

With an AppSource solution I would recommend (and use this myself) to leave our your Registered TLA of your variables all together.

Here is an example:

As a sidenote, Intellisense in Visual Studio Code works smarter than just the first characters, it would actually do a smart search and also suggest results that contain the characters even with small typos. It’s one of the things that make VSCode better than C/Side. (One of the few things though 😊).

Tip #64 | Show License Information in Business Central

With the retirement of C/Side we have a challenge we did not have before regarding the license.

We used to be able to see the license information from C/Side, upload the license and quickly create a new page that displays permissions.

With Business Central this is no longer possible and we now need PowerShell to upload a license.

On my GitHub you can find a repo you can clone to display the license information.

Challenge

I would also like to be able to change the license from this page. I hope one of my readers can put this in and do a pull request.

It will require DotNET but that’s fine, this extension is targeted for OnPrem anyway.

Enjoy!

Tip #63 | Export Warnings & Errors from Visual Studio Code

If I get asked the same question twice I am already tempted to blog about it. This one exceeds this number and is long overdue.

It looks like the whole world is now converting from C/AL to AL and running into challenges with that.

Right now I am analysing several databases and one thing you need after elliminating low hanging fruit and removing errors that crash the compiler is to find common errors and count them.

An Excel Pivot Table is perfect for that.

Normally Visual Studio Code is not nice in exporting errors and warnings. You can try to copy/paste them but the work to clean up is hard.

With the magic AL runner by Tobias Fenster it is prepared for you. You can download it here.

You can copy and paste this into Excel and use Data -> Text to Columns to use the | as a separator.

The only thing that you’ll miss is the object ID and type. You can add these with adding two columns using the formula like

=LEFT(C5;FIND(“.”;C5)-1)

After that you’ll spend several hours. or often days in C/Side fixing errors you could have fixed a long long time ago.

Enjoy!

Business Central & Nintendo

WARNING!! Personal opinion here!

Inspiration to write down idea’s are everywhere. Next week my youngest son has his birthday and we went out this evening with the train to the big city of Deventer to buy him (us) a Nintendo Switch.

I’ve been loyal to Nintendo since the 1980ies and bought many of their consoles. I’m also loyal to Mario and have most of the games.

When the Nintendo WII came out there was the option of buying NES games for 5 dollar and I bought Mario I and III. Again, because I already purchased them 20 or so years earlier.

Now what does this have to do with Business Central? It made me reflect to a talk I had a few hours earlier while driving back home in the car with some former collegueas. They wanted to pick my brains about upgrading customers from old Navision to Business Central. In this case one was on 3.70 and the other on 2009 classic.

With Navision upgrading was easy. It required common sense and discipline. Two qualities every Navision developer should have. Back in the days I did many upgrades fixed price for less than 5k.

60% of all Navision installations are on classic, or that is what my former collegues told me. The hold of upgrading because of the gap with RTC and something called a financial crisis that forces many people from sitting on their (flat) wallet for half a decade or more.

They wanted to know how to analyse if the customizations can be ported to Business Central. The idea was to install Business Central On Prem and keep running on the same version again for a decade or more.

I told them that this was a horrible idea and it should not be advised to customers. Nobody should want to run Business Central On Prem with a support window of only 6 monhts.

That’s right. Business Central only get’s cumulative updates for 6 months. After that you are on your own and if you want to do stuff like backporting a fix from a higher version it means making your own base app.

That’s horrible.

Business Central on AL Only has just officially become a cloud only solution because no SMB is qualified to install and maintain it on premises and upgrade every 6 months.

Because the Extension model in Business Central with AL is based on taking a dependency on metadata from Microsoft it’s very fragile for changes done my Microsoft.

A lot of things that are technically possible should be avoided with per-tenant extensions because you will be forced to refactor your changes every 6 months. Very, very expensive.

Business Central is a high volume product that should be perrsonalised with apps from AppSource. An AppSource app is only interesting from an economics perspective with one hundred paying customers or more as it requires a dedicated team focussing on high quality, automated testing and an intuitive user interface.

The partners who do not accept this and keep modifying Business Central with complex per-tenant extensions are a danger for our ecosystem.

If you require a complex module for your company, use a different platform like power platform or other Microsoft options. As long as you stick to Azure, MSFT does not care.

The days of easy upgrades with Navision are over. Welcome to the days of Nintendo where we have to constantly buy new consoles to use the new toys.

Directions EMEA 2019 Afterthoughts

It seems that when my blog posts appear some people hold their breath. Don’t worry, that won’t be nessesairy this time.

I am at the Vienna airport and just wanted to write some thoughts I have after the event.

When I look at 2.500 people wondering around I don’t see a community. I see individuals. We call it a community because we share the love of a product but we need to move to the next level of community.

Business Central Wave II is the first version of Navision without C/Side and a windows client after it was introduced in 1995. For almost 25 years C/Side made our carreers.

A lot has happened in 25 years and most solutions grew out to be monolyths. Not because you cannot write clean decoupled code in C/Side but because we lack knowledge and discipline.

Now with Extensions and AppSource we have a chance to start over, to do it in a better way. But it does not look like we are doing that.

Why did the concept of extensions see the light of day? Because it allows Microsoft a platform that allows Business Central to connect to AppSource. AppSource allows everyone in the world to find your solution without you doing much marketing effort.

This means we now have a platform to share repeatable small modules. But this is not what is happening.

Partners that did everything themselves in C/Side that led to solutions with thousands of objects that nobody understands anymore are still looking to convert these solutions to AL rather than looking at that is out there and reuse existing apps.

I’ve even heard that partners are now merging AL code because they modify the base app.

THIS IS HORRIBLE!

Giving up C/Side is only worth doing if we get back the repeatability of small reusable components with clear interfaces.

WE NEED TO BE A COMMUNITY THAT SHARES!

Start sharing IP! Don’t re-invent the wheel because you had to do this in C/Side. In Business Central having 10 ISV solutions in one database is a piece of cake.

This is my biggest takeaway.

The second thing that was interesting for me was having a conversation with Microsoft. I cannot remember having conversations like I did in the past few days with them in years.

We talked about the refactoring and challenges in the future. We agree that breaking changes should never happen again and still we need to continue breaking up the base app into smaller pieces.

For this to happen and to avoid future frustration they’ve invited me back to visit Lyngby every now and then in an informal role. I’ve agreed to try that and let’s see what will happen here.

I’ve also pushed Microsoft to have better involvement of MVP’s in the next interations. This group of people can give good feedback and seem to have been forgotten in the last 6 to 12 months.

The future is uncertain and a lot of decisions need to be made. The road is not paved, The road in many cases has to be created using heavy machinery.

Yet Business Central remains the BEST flexible cloud ERP product. The webclient team did a great job making this client on-par with the Windows client in the best way possible. Web development is so much more difficult than the old Win32 UI.

See you at NAVTechDays? Find me at the ForNAV or Global Mediator booth.