11.2 Document Standards: Header, Line, History & Journal Architectures
Key Takeaways
- Business documents adhere to the two-tier Header-Line architectural pattern, where Headers use a composite primary key of ("Document Type", "No.") and Lines use ("Document Type", "Document No.", "Line No.").
- The Document Type enum allows a single pair of Header and Line tables to support multiple commercial document stages (Quote, Order, Invoice, Credit Memo, Blanket Order, Return Order) while reusing business validation logic.
- Setting AutoSplitKey = true on subpage ListParts automatically calculates intermediate Line No. integer values (10,000-step increments or midpoint division) during user line insertion.
- Document lifecycle governance is enforced via status state machines (Open, Released, Pending Approval, Pending Prepayment), release routines (Codeunit 414), and version snapshot archiving (Codeunit 5063 ArchiveManagement).
11.2 Document Standards: Header, Line, History & Journal Architectures
Transactional business documents—such as Sales Orders, Purchase Invoices, Service Contracts, and Transfer Orders—are the core operational instruments of Business Central. These entities follow the Header-Line Design Pattern, a battle-tested relational model designed to handle complex commercial logic, taxes, line discounts, currency conversions, and inventory tracking. For developers preparing for the MB-820 exam, deep knowledge of document primary keys, journal staging architectures, line numbering mechanics, status lifecycle pipelines, and document archiving is essential.
1. Header-Line Relational Architecture
A business document is split into two distinct table layers:
- Document Header (
Sales Header,Purchase Header): Captures transaction-wide metadata that applies to the entire document. This includes the customer/vendor identifier, posting dates, currency codes, shipping addresses, payment terms, salesperson codes, and overall document status. - Document Line (
Sales Line,Purchase Line): Represents itemized line items comprising the transaction. Each line defines an item, G/L account, resource, fixed asset, or charge item, along with quantities, unit prices, line discounts, location codes, and line-specific dimension combinations.
+-----------------------------------------------------------------------------------------+
| DOCUMENT HEADER TABLE |
| Primary Key: [ "Document Type", "No." ] |
| Fields: Customer No., Posting Date, Currency Code, Status, Dimension Set ID |
+-----------------------------------------------------------------------------------------+
│ 1 (One)
│
▼ N (Many: Cascade Relation)
+-----------------------------------------------------------------------------------------+
| DOCUMENT LINE TABLE |
| Primary Key: [ "Document Type", "Document No.", "Line No." ] |
| Fields: Type, No., Quantity, Unit Price, Line Discount %, Dimension Set ID |
+-----------------------------------------------------------------------------------------+
Primary Key Formats & The Document Type Enum
Both Header and Line tables share an extensible enum as their first primary key field:
Document TypeEnum: Contains values such asQuote,Order,Invoice,Credit Memo,Blanket Order,Return Order.- Header Primary Key:
key(PK; "Document Type", "No.") { Clustered = true; } - Line Primary Key:
key(PK; "Document Type", "Document No.", "Line No.") { Clustered = true; }
By including "Document Type" as the leading key component, Business Central reuses identical table structures, business validation logic, and UI forms across entirely different commercial document stages (e.g., converting a Quote into an Order, or an Order into an Invoice).
Cascade Deletion Mechanics
In the Document Header's OnDelete trigger, the table enforces referential integrity by deleting all associated child lines, comments, and document attachments:
// Standard cascade deletion pattern on Sales Header OnDelete trigger
SalesLine.LockTable();
SalesLine.SetRange("Document Type", "Document Type");
SalesLine.SetRange("Document No.", "No.");
SalesLine.DeleteAll(true); // Executes OnDelete trigger on each Sales Line
SalesCommentLine.SetRange("Document Type", "Document Type");
SalesCommentLine.SetRange("No.", "No.");
SalesCommentLine.DeleteAll();
2. Journal Table Architecture vs. Document Architecture
In addition to transactional documents, Business Central relies on Journal Tables for batch staging and unposted transaction queues. Understanding the architectural differences between documents and journals is critical for system design.
The Three-Tier Journal Hierarchy
Journals are structured in a three-tier hierarchy:
- Journal Template (Table 80
Gen. Journal Template): Defines the operational characteristics, window layout, default posting report, and source code of the journal (e.g.,General,Sales,Purchases,Cash Receipts,Payment Journal). - Journal Batch (Table 232
Gen. Journal Batch): Represents an isolated work queue or user workspace within a template (e.g.,DEFAULT,MONTHEND,PAYROLL). Batches define default number series, reason codes, and balancing accounts. - Journal Line (Table 81
Gen. Journal Line): Stores individual transactional debit and credit lines prior to posting.
// Primary Key definition on Table 81 "Gen. Journal Line"
keys
{
key(PK; "Journal Template Name", "Journal Batch Name", "Line No.")
{
Clustered = true;
}
}
Documents vs. Journals Comparison
| Architectural Dimension | Document Architecture (Sales Header/Line) | Journal Architecture (Gen. Journal Line) |
|---|---|---|
| Primary Key Structure | ("Document Type", "No.") and ("Document Type", "Document No.", "Line No.") | ("Journal Template Name", "Journal Batch Name", "Line No.") |
| User Interaction | Form-oriented card pages with subform line grids representing single business contracts. | Worksheet-oriented grids designed for high-speed multi-row transactional batch entry. |
| Lifecycle on Posting | Replaced by immutable posted documents (Sales Invoice Header/Line) and deleted from active tables. | Verified, posted to ledgers via Codeunit 12, and lines are deleted immediately from the active batch. |
| Recurring Processing | Not natively supported on standard documents. | Supported via Recurring Journals (Recurring = true) with recurring methods (Fixed, Variable, Balance) and calculation formulas. |
3. Subform Line Numbering Mechanics & AutoSplitKey
In document subpages (e.g., Sales Order Subform), users frequently insert new lines between existing lines. Rather than renumbering every subsequent line in SQL Server (which would cause severe table locking and slow I/O), Business Central uses integer gaps and the AutoSplitKey property.
How AutoSplitKey Operates:
- Page Configuration: On the subform page object, set
AutoSplitKey = true;,DelayedInsert = true;, andMultipleNewLines = true;. - Default Step Increments: When lines are appended sequentially at the bottom of the grid, the client assigns
"Line No."in increments of 10,000 (10000,20000,30000, etc.). - Intermediate Insertion (Midpoint Division): When a user inserts a line between
10000and20000, the runtime calculates the midpoint: - Subsequent Midpoint Splitting: If another line is inserted between
10000and15000, the new line is assigned12500. If repeated insertions exhaust the integer gap (difference between adjacent lines becomes 1), the platform triggers an automatic line renumbering routine.
page 50110 "Custom Order Subform"
{
PageType = ListPart;
SourceTable = "Custom Order Line";
AutoSplitKey = true;
DelayedInsert = true;
MultipleNewLines = true;
layout
{
area(Content)
{
repeater(Group)
{
field(Type; Rec.Type) { ApplicationArea = All; }
field("No."; Rec."No.") { ApplicationArea = All; }
field(Quantity; Rec.Quantity) { ApplicationArea = All; }
field("Unit Price"; Rec."Unit Price") { ApplicationArea = All; }
field("Line Amount"; Rec."Line Amount") { ApplicationArea = All; }
}
}
}
}
4. Header-to-Line Cascade Updates
When a header field is modified after lines have already been entered (for example, the user changes the "Posting Date", "Currency Code", "Payment Terms Code", or "Ship-to Address"), the change must cascade to all existing child lines to maintain transaction consistency.
Cascade Mechanics in AL:
- In the
OnValidatetrigger of header fields, AL invokes dedicated update procedures (such asUpdateSalesLinesByFieldNoorUpdateSalesLines). - A dialog frequently prompts the user: "You have modified %1. Do you want to update the lines?" (
Confirmdialog). - If confirmed, the code iterates through lines using
SalesLine.LockTable(); SalesLine.SetRange("Document Type", "Document Type"); SalesLine.SetRange("Document No.", "No."); if SalesLine.FindSet(true) then repeat ... SalesLine.Modify(true); until SalesLine.Next() = 0;. - Passing
truetoSalesLine.Modify(true)ensures that line-level triggers recalculate item unit prices, discounts, taxes, and currency conversions.
5. Document Status Lifecycle & Release/Reopen Engine
Document data integrity is governed by a strict state machine represented by the Status field on the Document Header.
Status Enum Values
Open: The draft state. Users can freely add lines, modify quantities, change prices, and update header values.Released: The certified state. Indicates the document is finalized, credit limits are verified, and warehouse operations (creating warehouse shipments, inventory picks) can proceed.Pending Approval: Set when an active approval workflow is triggered. Prevents further modifications until the designated approver signs off.Pending Prepayment: Set when a prepayment invoice has been posted but not yet paid, blocking shipment until customer funds clear.
The Release Pattern (Codeunit 414 "Release Sales Document")
Releasing a document executes comprehensive validation logic before transitioning state:
- Line Existence Verification: Ensures at least one non-empty line exists.
- Mandatory Field Checks: Verifies
"Sell-to Customer No.","Posting Date","Document Date", and payment terms. - Dimension Combination Validation: Invokes
DimensionManagement.CheckDimCombandCheckDimValuePostingto ensure header and line dimension combinations comply with corporate rules. - Status Enforcement in Line Triggers: Every line validation trigger includes guard clauses that block edits when released:
// Standard guard clause pattern in Sales Line table triggers
procedure TestStatusOpen()
var
SalesHeader: Record "Sales Header";
DocumentLockedErr: Label 'The document %1 %2 cannot be modified because it is %3.', Comment = '%1 = Doc Type, %2 = Doc No, %3 = Status';
begin
if "Document No." = '' then
exit;
SalesHeader.Get("Document Type", "Document No.");
if SalesHeader.Status <> SalesHeader.Status::Open then
Error(DocumentLockedErr, "Document Type", "Document No.", SalesHeader.Status);
end;
If modifications are required after release, the user must explicitly run the Reopen action (which calls ReleaseSalesDoc.Reopen(Rec)), returning Status to Open and invalidating any downstream warehouse documents.
6. The Document Archiving Pattern
Organizations require auditability of commercial negotiations across document revisions (e.g., tracking changes made to a Sales Quote or Purchase Order across multiple iterations). Business Central accomplishes this via the Document Archiving Pattern.
Archive Table Architecture
- Archive Tables:
Sales Header Archive(Table 5107) andSales Line Archive(Table 5108). - Primary Key Structure:
Sales Header Archive:"Document Type","No.","Doc. No. Occurrence","Version No.".Sales Line Archive:"Document Type","Document No.","Doc. No. Occurrence","Version No.","Line No.".
"Doc. No. Occurrence": An integer tracking how many times the same document number has been reused (e.g., if a number series is reused or blanket order instances are created)."Version No.": An auto-incrementing integer (1,2,3...) incremented on each archive event.
The ArchiveManagement Engine (Codeunit 5063)
Archiving is orchestrated by Codeunit 5063 ArchiveManagement. Key API procedures include:
ArchiveSalesDocument(SalesHeader): Archives the sales document after displaying a UI confirmation prompt.ArchSalesDocumentNoConfirm(SalesHeader): Performs automated background archiving without user interaction.StoreSalesDocument(SalesHeader, InteractionExist): Core low-level engine that clones active header and lines into archive tables and increments"Version No.".RestoreSalesDocument(SalesHeaderArchive): Restores an archived snapshot back into activeSales HeaderandSales Linetables.
// Example: Triggering automated archiving before modifying a high-value order
codeunit 50115 "Order Modification Handler"
{
procedure ModifyAndArchiveOrder(var SalesHeader: Record "Sales Header")
var
ArchiveManagement: Codeunit ArchiveManagement;
begin
// Create snapshot in Sales Header Archive / Sales Line Archive
ArchiveManagement.ArchSalesDocumentNoConfirm(SalesHeader);
// Proceed with custom batch modification
SalesHeader."Special Instructions" := 'Priority Handling Approved';
SalesHeader.Modify(true);
end;
}
Automated Archiving Triggers
In Sales & Receivables Setup and Purchases & Payables Setup, administrators configure archiving policies for Quotes, Orders, Blanket Orders, and Return Orders via the "Archive Quotes" and "Archive Orders" enums (Never, Question, Always). Standard codeunits automatically invoke ArchiveManagement upon printing, releasing, or deleting documents.
A developer is configuring a custom document line subform page in AL. The user must be able to insert new lines between existing lines seamlessly without encountering primary key collision errors. Which subform page properties must be configured?
In the standard Business Central document architecture, what is the composite primary key structure of the Sales Header and Sales Line tables?
When a sales document undergoes version archiving via Codeunit 5063 ArchiveManagement, which fields form the composite primary key of the Sales Header Archive table to distinguish multiple historical versions?
How is the data tier structured for unposted batch transactions in the General Journal (Table 81 'Gen. Journal Line') compared to document tables?