In this video, I look at how to change Business Central posting behaviour by subscribing to an event and write a single line of code.

In this video, Erik demonstrates how a single event subscriber in Business Central AL can change the posting behavior of the system — something that previously required direct modification of the base application. Specifically, he shows how to prevent G/L entry aggregation during invoice posting, ensuring each sales line creates its own distinct G/L entry.
The Problem: G/L Entry Aggregation
When you post a sales invoice in Business Central with multiple lines that hit the same G/L account and share the same dimensions, posting groups, and other key attributes, the system aggregates them into a single G/L entry. This is a feature that dates all the way back to the earliest versions of Navision — originally intended to reduce the number of G/L entries and save storage space.
Erik demonstrates this by creating a sales invoice with two G/L account lines:
- Line 1: G/L Account, Quantity 1, Amount $99
- Line 2: G/L Account (same), Quantity 1, Amount $88
After posting, using the Find Entries function (formerly known as “Navigate”), only four G/L entries are created instead of the expected five. The two sales lines have been combined into a single G/L entry of $187 because they share the same account and attributes.
A Side Note on “Navigate” vs “Find Entries”
Erik points out that in version 17, the function formerly known as “Navigate” — which used to appear in three different menu locations — has been renamed to Find Entries. The “Navigate” menu tab itself is now called Related. So Business Central went from three items labeled “Navigate” down to one clearly named function.
Understanding the Invoice Posting Buffer
To understand how to solve this, you need to understand how the posting routines work internally. Erik emphasizes that one of the most important things for AL developers to learn is the base construct of how the application works — reading through Codeunit 80, Codeunit 12, and others to understand data flow.
The key table here is the Invoice Post. Buffer (also known as Invoice Posting Buffer). This is essentially a temporary table that Codeunit 80 fills up during invoice posting. Instead of creating general journal lines on an ad-hoc basis, the posting routine populates this buffer, grouping records by the uniqueness of the primary key.
The primary key of this buffer table is a composite of many fields:
- G/L Account
- General Business Posting Group
- General Product Posting Group
- VAT Business Posting Group
- VAT Product Posting Group
- Tax Area Code
- Tax Group Code
- Tax Liable
- Use Tax
- Dimension Set ID
- Job Number
- Fixed Asset Line Number
- Deferral Code
- Additional Grouping Identifier
When a new sales line maps to a primary key combination that already exists in the buffer, the system simply updates the amount on the existing record rather than inserting a new one. At the end of posting, Codeunit 80 iterates through this buffer and creates the actual general journal entries.
The Hidden Field: Additional Grouping Identifier
The key insight is the last field in the primary key: Additional Grouping Identifier (Field No. 1000). It’s a Code 20 field that is part of the primary key but is never used anywhere in the base application. It sits there, waiting for someone to use it.
By putting a unique value into this field for each sales line, we force each line to create its own record in the buffer table — and consequently its own G/L entry when posted.
The Solution: One Event Subscriber, One Line of Code
The Invoice Post. Buffer table exposes an event called OnAfterInvPostBufferPrepareSales, which fires when the buffer record is being prepared from a sales line. By subscribing to this event, we can set the Additional Grouping Identifier to the line number, making each buffer entry unique per sales line.
Here’s the complete extension:
codeunit 50129 "Make sure all is posted"
{
[EventSubscriber(ObjectType::Table, Database::"Invoice Post. Buffer", 'OnAfterInvPostBufferPrepareSales', '', true, true)]
local procedure MyProcedure(var SalesLine: Record "Sales Line"; var InvoicePostBuffer: Record "Invoice Post. Buffer")
begin
InvoicePostBuffer."Additional Grouping Identifier" := format(SalesLine."Line No.", 0, 2);
end;
}
How It Works
- We subscribe to the
OnAfterInvPostBufferPrepareSalesevent on theInvoice Post. Buffertable. - The event gives us both the
SalesLinerecord and theInvoicePostBufferrecord by reference. - We set the
Additional Grouping Identifierto the formatted line number of the sales line. - Since line numbers are unique within a document, each sales line now produces a unique primary key in the buffer — preventing aggregation.
A Note on Event Subscriber Syntax
Erik highlights an important detail about how to reference a table in an event subscriber: while codeunits use ObjectType::Codeunit and pages use ObjectType::Page, for tables you use ObjectType::Table combined with Database::"Table Name".
He also notes that the order of parameters in the event subscriber procedure doesn’t need to match the order in the event publisher — you could put SalesLine first and InvoicePostBuffer second and it would still work correctly.
Purchase Documents Too
While this example focuses on sales documents, Erik points out that a similar event exists for purchase documents — OnAfterInvPostBufferPreparePurchase — so the same approach can be applied to purchase invoice posting.
The Result
After deploying the extension and posting the same type of invoice (two lines to the same G/L account with amounts of $99 and $88), the Find Entries function now shows five G/L entries instead of four. The two sales lines are posted as separate G/L entries instead of being aggregated into one.
Comparing the two posted invoices side by side:
- Before the extension: 4 G/L entries, with the two identical-key lines combined into a single entry of $187.
- After the extension: 5 G/L entries, with each sales line preserved as its own G/L entry ($99 and $88 separately).
Conclusion
This is a powerful example of how a single event subscriber with essentially one line of code can change the fundamental posting behavior of Business Central — something that used to require direct modification of core codeunits like Codeunit 80. The Additional Grouping Identifier field exists specifically as an extension point in the Invoice Posting Buffer’s primary key, allowing developers to control G/L entry aggregation without touching the base application. Understanding the base application’s data flow and architecture is essential for discovering these kinds of elegant solutions.