The implementation of the new No. Series was introduced a few months ago, but it hasn’t received much attention or discussion.

It’s crucial to address any customizations or use of the No. Series in your application promptly. If you don’t update and reimplement the necessary changes, you’ll likely encounter errors soon. Don’t forget about automated tests app if you have it.

💡Don’t wait last moment to do the reimplementation.

Before moving on, make sure you watched Microsoft YouTube video on topic Business Foundation and new No. Series:


Obsolete

So, starting with Business Central 2024 Wave 1 (BC24), using the same methods for No. Series will prompt the following warning:

Codeunit ‘NoSeriesManagement’ is marked for removal. Reason: Please use the “No. Series” and “No. Series – Batch” codeunits instead.

Additionally, the TestManual and InitSeries methods have similar warnings:

Method ‘TestManual’ is marked for removal. Reason: Please use method TestManual(NoSeriesCode: Code[20]) in codeunit “No. Series” instead.. Tag: 24.0.AL AL0432
Method ‘InitSeries’ is marked for removal. Reason: Please use AreRelated in the “No. Series” codeunit instead. Tag: 24.0.AL AL0432

All obsoleted things can be found on Microsoft Learn: https://learn.microsoft.com/en-us/dynamics365/business-central/application/business-foundation/obsoletion/obsolete_by_24.0


Business Foundation

Back then, Microsoft introduced the new Business Foundation app and announced plans to gradually transfer the code from the Base Application to the Business Foundation app. That is exactly what happened:

The No. Series module was first to make this transition.


UI

Before we move on to technical side, what new functionality brings us this change in terms of user experience.

On No. Series page, there is new Factboxes:

Also, new action to show expiring No. Series:

Really handy feature!


Let’s move to technical part!

Two new codeunits:

  1. No. Series
  2. No. Series – Batch

Make sure to use “No. Series – Batch”, when you require multiple No. series, this codeunit is optimized for performance. Use the “SaveState” method to apply the changes efficiently.

Examples

TryGetNextNo
TryGetNextNo is a function that gets and returns the next number, without modifying the No. Series. PeekNextNo does the same now and makes the code easier to understand.

Old:

DocNo := NoSeriesMgt.TryGetNextNo(GenJnlBatch."No. Series", EndDateReq);

New:

DocNo := NoSeries.PeekNextNo(GenJnlBatch."No. Series", EndDateReq);

GetNextNo with delayed modify
Old:

if DocNo = NoSeriesMgt.GetNextNo(GenJnlBatch."No. Series", EndDateReq, false) then
   NoSeriesMgt.SaveNoSeries();

New: You have two options here. Either you Peek the next number and update, or use a batch. This depends on the use case, but by using a batch you ensure that the number saved to the database is the DocNo.

if DocNo = NoSeries.PeekNextNo(GenJnlBatch."No. Series", EndDateReq) then
   NoSeries.GetNextNo(GenJnlBatch."No. Series", EndDateReq);

or

if DocNo = NoSeriesBatch.GetNextNo(GenJnlBatch."No. Series", EndDateReq) then
   NoSeriesBatch.SaveState();

InitSeries
InitSeries is a complex implementation because it handles multiple cases. In most cases that use InitSeries, we verify that the given number isn’t set, as shown in the following example. If it is, you’ll need to verify whether manual numbers are allowed (see IsManual or TestManual procedures in the No. Series codeunit).

Old:

if "No." = '' then begin
   GLSetup.Get();
   GLSetup.TestField("Bank Account Nos.");
   NoSeriesMgt.InitSeries(GLSetup."Bank Account Nos.", xRec."No. Series", 0D, "No.", "No. Series");
end;

New:

if "No." = '' then begin
   GLSetup.Get();
   GLSetup.TestField("Bank Account Nos.");
   "No. Series" := GLSetup."Bank Account Nos.";
   if NoSeries.AreRelated(GLSetup."Bank Account Nos.", xRec."No. Series") then
      "No. Series" := xRec."No. Series";
   "No." := NoSeries.GetNextNo("No. Series");
end;


The new style has a few more lines, but it also better describes what’s happening.


Document posting with delayed modify
During posting we often want to delay the update of No. Series. Currently the only way to do this for multiple No. Series is to use an array of NoSeriesManagement and find the correct one during posting. This is very confusing and not very readable. Using the new Batch codeunit, you only need to define a single codeunit, request new number for your different number series and posting dates. Finally, save the state and all records are updated.

Old:

var
NoSeriesMgt2: array[100] of Codeunit NoSeriesManagement;
…
with GenJnlLine2 do
   if not TempNoSeries.Get("Posting No. Series") then begin
   NoOfPostingNoSeries := NoOfPostingNoSeries + 1;
   if NoOfPostingNoSeries > ArrayLen(NoSeriesMgt2) then
      Error(Text025, ArrayLen(NoSeriesMgt2));
   TempNoSeries.Code := "Posting No. Series";
   TempNoSeries.Description := Format(NoOfPostingNoSeries);
   TempNoSeries.Insert();
end;
LastDocNo := "Document No.";
Evaluate(PostingNoSeriesNo, TempNoSeries.Description);
"Document No." := NoSeriesMgt2[PostingNoSeriesNo].GetNextNo("Posting No. Series", "Posting Date", true);
LastPostedDocNo := "Document No.";

New:

var
NoSeriesBatch: Codeunit "No. Series - Batch";
…
LastDocNo := GenJnlLine2."Document No.";
GenJnlLine2."Document No." := NoSeriesBatch.GetNextNo(GenJnlLine2."Posting No. Series", GenJnlLine2."Posting Date");
LastPostedDocNo := GenJnlLine2."Document No.";
…
NoSeriesBatch.SaveState();Simulating new numbers

Sometimes we want to simulate the use of No. Series without actually updating it, and we may want to start from a specific number. For this purpose, we added the SimulateGetNextNo function on the No. Series – Batch.

Old:

procedure IncrementDocumentNo(GenJnlBatch: Record "Gen. Journal Batch"; var LastDocNumber: Code[20])
var
   NoSeriesLine: Record "No. Series Line";
begin
if GenJnlBatch."No. Series" <> '' then begin
   NoSeriesManagement.SetNoSeriesLineFilter(NoSeriesLine, GenJnlBatch."No. Series", "Posting Date");
if NoSeriesLine."Increment-by No." > 1 then
   NoSeriesManagement.IncrementNoText(LastDocNumber, NoSeriesLine."Increment-by No.")
else
   LastDocNumber := IncStr(LastDocNumber);
end else
   LastDocNumber := IncStr(LastDocNumber);
end;

New:

"Document No." := NoSeriesBatch.SimulateGetNextNo(GenJnlBatch."No. Series", Rec."Posting Date", "Document No.");


This new function uses the details of the given number series to increment the document number. If the number series doesn’t exist, the document number increases by one.


No. Series and Copilot!!!

It’s still under development, thanks to Dimitry Katson!

It will be amazing possibility.

If you are interested in, you could add valuable insight or track the progress on Github issue: https://github.com/microsoft/BCApps/issues/659

Categorized in: