How to integrate into a new routine of posting in Business Central version 19

Since BC version 19, Microsoft has introduced a new posting interface, as a result, you might have to refactor your code depending on how you conceived your integration into a routine of posting in Business Central version 19. Let’s start by looking into what has changed.

 

What we have now from Microsoft is a codeunit 825 “Sales Post Invoice Events”. In this codeunit you can find a bunch of publishers that will enable you to integrate into a function from codeunit 80 (for newbies, this is the codeunit that handles posting in Sales, transferring Sales Order to a Posted Sales Invoice, for example). So, to integrate your logic into posting for any new application you are developing, you can use these publishers and find a specific point that suits you the most. Alternatively, you can implement the interface “Invoice Posting” if it better suits you.

Another change is that table 49 “Invoice Post. Buffer” is discontinued. Yap! A bit about this table: generally, it is a preparation table for the lines to be grouped. GL lines are grouped standardly by Line Type, G/L Account, Gen. Bus. Posting Group, Gen. Prod. Posting Group, VAT Bus. Posting Group, VAT Prod. Posting Group, Tax Area Code, Tax Group Code, Tax Liable, Use Tax, Dimension Set ID, Job No., Fixed Asset Line No, Deferral Code and last but not least, Additional Grouping Identifier. And by now, you only had this field to use for any additional grouping you would need. This presented a problem since many applications can modify this field, which creates a mess in the routine of posting in Business Central v19, so it had to be changed. Let’s see how.

There is a new posting buffer table 55 “Invoice Posting Buffer” and the major difference is the Primary Key, the Primary Key has been changed. Now it is just one Field “Group ID” of Type Text, and there is a function that builds this primary key called BuildPrimaryKey(). At the end of this function is a publisher OnAfterPrepareSales(Rec), which enables you to add your own grouping field value. To do this, you must first extend the Invoice Posting Buffer table and add your field.

Okay, I know too much text. Let’s make it like this, and I will show how to do this by covering the two most common requests I had over the years. Transfer value from the Sales Header to GL Entry and Customer Ledger entry and Group and transfer Value from the Sales Lines to GL Entry. And I won’t use codeunit 825 “Sales Post Invoice Events” or implement “Invoice Posting” interface. I will go deep into a fundament.

So, we add fields to Sales Header, Sales Lines, General Journal Line, Customer Ledger Entry, G/L Entry, Invoice Posting Buffer.

 

posting routine in business central v19

posting routine in business central v19

posting routine in business central v19

 

And, of course, add it to all related tables Sales Invoice, Archives with the same ID, and TRANSFERFIELDS will do the rest.

You can look for the complete code in my GitHub repository.

Ok, let’s move on now. First, we need to transfer all those fields values, so we subscribe to the following events.

 

codeunit 50100 "MS Posting Subscribers"

{

    [EventSubscriber(ObjectType::Table, Database::"Invoice Posting Buffer", 'OnAfterPrepareSales', '', true, true)]

    local procedure InvoicePostingBufferOnAfterPrepareSales(var InvoicePostingBuffer: Record "Invoice Posting Buffer"; var SalesLine: Record "Sales Line")
    begin

        //Transfer for the GL Value

        InvoicePostingBuffer."MS New Posting Line" := SalesLine."MS New Posting Line";

    end;

    [EventSubscriber(ObjectType::Table, Database::"Invoice Posting Buffer", 'OnAfterBuildPrimaryKey', '', true, true)]

    local procedure InvoicePostingBufferOnAfterBuildPrimaryKey(var InvoicePostingBuffer: Record "Invoice Posting Buffer")

    begin

        //Group G/L lines by value from the field "MS New Posting Line"

        InvoicePostingBuffer."Group ID" += InvoicePostingBuffer.PadField(Format(InvoicePostingBuffer."MS New Posting Line"), StrLen(Format(InvoicePostingBuffer."MS New Posting Line")));

    end;

    [EventSubscriber(ObjectType::Table, Database::"Invoice Posting Buffer", 'OnUpdateOnBeforeModify', '', true, true)]

    local procedure InvoicePostingBufferOnAfterUpdate(var InvoicePostingBuffer: Record "Invoice Posting Buffer"; FromInvoicePostingBuffer: Record "Invoice Posting Buffer")

    begin

        //Update the value for the line

        InvoicePostingBuffer."MS New Posting Line" += FromInvoicePostingBuffer."MS New Posting Line";

    end;

    [EventSubscriber(ObjectType::Table, Database::"Invoice Posting Buffer", 'OnAfterCopyToGenJnlLine', '', true, true)]

    local procedure InvoicePostingBufferOnAfterCopyToGenJnlLine(var GenJnlLine: Record "Gen. Journal Line"; InvoicePostingBuffer: Record "Invoice Posting Buffer")

    begin

        //Transfer Value to General Journal Line

        GenJnlLine."MS New Posting Line" := InvoicePostingBuffer."MS New Posting Line";

    end;

    [EventSubscriber(ObjectType::Table, Database::"Gen. Journal Line", 'OnAfterCopyGenJnlLineFromSalesHeader', '', true, true)]

    local procedure GenJournalLineOnAfterCopyGenJnlLineFromSalesHeader(SalesHeader: Record "Sales Header"; var GenJournalLine: Record "Gen. Journal Line")

    begin

        //Transfer Value to General Journal Line

        GenJournalLine."MS New Posting Header" := SalesHeader."MS New Posting Header";

    end;

    [EventSubscriber(ObjectType::Table, Database::"G/L Entry", 'OnAfterCopyGLEntryFromGenJnlLine', '', true, true)]

    local procedure GenJournalLineOnAfterOnAfterCopyGLEntryFromGenJnlLine(var GLEntry: Record "G/L Entry"; var GenJournalLine: Record "Gen. Journal Line")

    begin

        //Transfer Value from General Journal Line

        GLEntry."MS New Posting Header" := GenJournalLine."MS New Posting Header";

        GLEntry."MS New Posting Line" := GenJournalLine."MS New Posting Line";

    end;

    [EventSubscriber(ObjectType::Table, Database::"Cust. Ledger Entry", 'OnAfterCopyCustLedgerEntryFromGenJnlLine', '', true, true)]

    local procedure GenJournalLineOnAfterCopyCustLedgerEntryFromGenJnlLine(var CustLedgerEntry: Record "Cust. Ledger Entry"; GenJournalLine: Record "Gen. Journal Line")

    begin

        //Transfer Value from General Journal Line

        CustLedgerEntry."MS New Posting Header" := GenJournalLine."MS New Posting Header";

    end;

}



 

OnAfterPrepareSales – on Invoice Posting Buffer will transfer our value to the buffer so we can have a value for the grouping of the lines.

OnAfterBuildPrimaryKey – on Invoice Posting Buffer will add our value for the grouping into the Primary Key, and the standard code will take care of the rest.

OnUpdateOnBeforeModify – on Invoice Posting Buffer, we use to sum the values by the group. So that is why I use “+=” so that the values of the groups are summed.

OnAfterCopyToGenJnlLine – on Invoice Posting Buffer is used to transfer the value of the line groups to the General Journal for posting.

OnAfterCopyGenJnlLineFromSalesHeader – on Gen. Journal Line takes the value from the header field to be posted further.

OnAfterCopyGLEntryFromGenJnlLine – on G/L Entry table takes the values of our fields from the Journal to the G/L Entry.

OnAfterCopyCustLedgerEntryFromGenJnlLine– on Cust. The Ledger Entry table takes the value of our field from the header from the Journal to the Cust. Ledger Entry.

 

And let’s review the result:

First, we create a sales order and fill in the values:

posting in bc v19

 

Since as you can see in Subscribers above, I used the same field for grouping and summing, and we should expect to have lines split additionally into 2 groups 1 for the value of 5 with a value of 10 in GL Entry, and 1 for the Value of 15 with value 15 since we only have 1. And, of course, a value from the header will also be transferred.

 

G/L Entry:

posting in bc v19

posting in bc v19

 

I know this example does not make much sense from the accounting perspective but feel free to use it however you like.