Microsoft Dynamics 365 Business Central: Update your AL code to the new No. Series Module

In the recent 2024 Release Wave 1 update for Microsoft Dynamics 365 Business Central, Microsoft introduced the Business Foundation layer. This new foundation layer continues their ongoing effort to modularize and enhance the software architecture. They are breaking down the monolithic structure into smaller, more coherent, and related modules, which improves the system’s maintainability and scalability.

With the introduction of the Business Foundation layer, the Business Central architecture now operates on three distinct layers, each with its unique role and contribution to the system’s functionality.

The Business Foundation is a collection of standard ERP functionalities for various domains within the application. While not specific to any functional area, these functionalities are essential for the application’s overall operation. I relate these to “common libraries.”

The System Application in Dynamics 365 Business Central contains modules that interact with the platform and online ecosystem to support the business logic in the Base Application. I simplify this in my brain by labeling it as APIs and Azure communication.

The Base Application in Dynamics 365 Business Central refers to the core application, the foundation for the ERP software’s functional areas.

The first module added to the Business Foundation Layer is the No. Series Module. The existing NoSeriesManagement pattern has been around for as long as I can remember. To ensure compatibility, any existing code must be updated with the pattern’s update to the new module.

The existing NoSeriesManagement logic was marked obsolete in Business Central 2024 Wave 1, so there is still time to update your existing code. Here are a few examples of how the code changes to use the new pattern.

The first change, as noted, is that good old codeunit 396 NoSeriesManagement is going away. The new codeunit 310 “No. Series” manages number series.

Here are a few examples of coding the change:

Old Code

trigger OnInsert()
begin
    if ("No." = '') then begin
        "No. Series":= Rec.GetNoSeriesCode;
        NoSeriesManagement.InitSeries(NoSeriesCode , xRec."No. Series", 0D, "No.", "No. Series");	
    end;
end;

New Code

trigger OnInsert()
begin
    if ("No." = '') then begin	
        "No. Series" := Rec.GetNoSeriesCode;
        if NoSeries.AreRelated("No. Series", xRec."No. Series") then
            "No. Series" := xRec."No. Series";
        "No." := NoSeries.GetNextNo("No. Series", WorkDate());
    end;
end;

Old Code

procedure AssistEdit(OldCust: Record Customer): Boolean
var
    Cust: Record Customer;
begin
    with Cust do begin
        Cust := Rec;
        SalesSetup.Get();
        SalesSetup.TestField("Customer Nos.");
        if NoSeriesMgt.SelectSeries(SalesSetup."Customer Nos.", OldCust."No. Series", "No. Series") then begin
            NoSeriesMgt.SetSeries("No.");
            Rec := Cust;
            OnAssistEditOnBeforeExit(Cust);
            exit(true);
        end;
    end;
end;

New Code

procedure AssistEdit(OldCust: Record Customer): Boolean
    var
        Cust: Record Customer;
    begin
        Cust := Rec;
        SalesSetup.Get();
        SalesSetup.TestField("Customer Nos.");
        if NoSeries.LookupRelatedNoSeries(SalesSetup."Customer Nos.", OldCust."No. Series", Cust."No. Series") then begin
            Cust."No." := NoSeries.GetNextNo(Cust."No. Series");
            Rec := Cust;
            OnAssistEditOnBeforeExit(Cust);
            exit(true);
        end;
    end;

OldCode

procedure NewDocumentNo()
var
    [SecurityFiltering(SecurityFilter::Filtered)]
    GenJournalLine: Record "Gen. Journal Line";
    [SecurityFiltering(SecurityFilter::Filtered)]
    GenJnlBatch: Record "Gen. Journal Batch";
    LastDocNo: Code[20];
begin
    if Count = 0 then
        exit;
    GenJnlBatch.Get("Journal Template Name", CurrentJnlBatchName);
    GenJournalLine.Reset();
    GenJournalLine.SetCurrentKey("Document No.");
    GenJournalLine.SetRange("Journal Template Name", "Journal Template Name");
    GenJournalLine.SetRange("Journal Batch Name", "Journal Batch Name");
    if GenJournalLine.FindLast() then begin
        LastDocNo := GenJournalLine."Document No.";
        IncrementDocumentNo(GenJnlBatch, LastDocNo);
    end else
        LastDocNo := NoSeriesMgt.TryGetNextNo(GenJnlBatch."No. Series", "Posting Date");

    CurrentDocNo := LastDocNo;
    SetDocumentNumberFilter(CurrentDocNo);
end;

New Code

procedure NewDocumentNo()
var
    [SecurityFiltering(SecurityFilter::Filtered)]
    GenJournalLine: Record "Gen. Journal Line";
    [SecurityFiltering(SecurityFilter::Filtered)]
    GenJnlBatch: Record "Gen. Journal Batch";
    NoSeriesBatch: Codeunit "No. Series - Batch";
    LastDocNo: Code[20];
begin
    if Rec.Count = 0 then
        exit;
    GenJnlBatch.Get(Rec."Journal Template Name", CurrentJnlBatchName);
    GenJournalLine.Reset();
    GenJournalLine.SetCurrentKey("Document No.");
    GenJournalLine.SetRange("Journal Template Name", Rec."Journal Template Name");
    GenJournalLine.SetRange("Journal Batch Name", Rec."Journal Batch Name");
    if GenJournalLine.FindLast() then begin
        LastDocNo := GenJournalLine."Document No.";
        LastDocNo := NoSeriesBatch.SimulateGetNextNo(GenJnlBatch."No. Series", Rec."Posting Date", LastDocNo);
    end else
        LastDocNo := NoSeriesBatch.PeekNextNo(GenJnlBatch."No. Series", Rec."Posting Date");

    CurrentDocNo := LastDocNo;
    SetDocumentNumberFilter(CurrentDocNo);
end;

Leave a Reply

Your email address will not be published.