Our journal is now ready to be posted. We've implemented all business logic, except the posting code.
The posting process of a journal in Microsoft Dynamics NAV has several codeunits for the structure:
Jnl.-Check Line
: This codeunit checks if the journal line is valid for posting.Jnl.-Post Line
: This codeunit does the actual creation of the ledger entry and register tables and calls other Jnl.-Post Line
codeunits if necessary to provide the transaction structure in Chapter 1, Introduction to Microsoft Dynamics NAV.Jnl.-Post Batch
: This codeunit loops though all journal lines in a journal batch and posts all the lines.Jnl.-Post
: This is the codeunit that is called from the page. It calls the Jnl.-Post Batch
codeunit and takes care of some user messaging.Jnl.-Post+Print
: This is the codeunit that is called when you click on Post + Print. It does the same as the Jnl.-Post
codeunit but with the additional printing of a report defined in the journal template.Jnl.-B.Post
: This posts all the journal lines that have no errors and marks the ones that have errors.Jnl.-B.Post+Print
: This does the same as Jnl.-B.Post
but with the additional printing of a report defined in the journal template.Let's have a look at the check line codeunit. When it comes to testing, Microsoft Dynamics NAV has a simple rule:
Test near, Test far, Do it, Clean up
First, we need to test the field in the journal line table, then read external data tables to check if all is good, and then post the lines and delete the data from the journal table.
It does not make sense to read the G/L setup table from the database if the document no. in our own table is blank, or to start the posting process and error out because the posting date is outside of a valid range. This would cause a lot of unnecessary I/O from the database to the client.
RunCheck()
WITH SquashJnlLine DO BEGIN
IF EmptyLine THEN
EXIT;
TESTFIELD("Squash Player No.");
TESTFIELD("Squash Court No.");
TESTFIELD("Posting Date");
TESTFIELD("Gen. Prod. Posting Group");
TESTFIELD("From Time");
TESTFIELD("To Time");
TESTFIELD("Reservation Date");
TESTFIELD("Bill-to Customer No.");
IF "Entry Type" = "Entry Type"::Invoice THEN
TESTFIELD("Applies-to Entry No.");
IF "Applies-to Entry No." <> 0 THEN
TESTFIELD("Entry Type", "Entry Type"::Invoice);
IF "Posting Date" <> NORMALDATE("Posting Date") THEN
FIELDERROR("Posting Date",Text000);
IF (AllowPostingFrom = 0D) AND (AllowPostingTo = 0D) THEN
...
END;
...
IF NOT DimMgt.CheckDimIDComb("Dimension Set ID") THEN
...
TableID[1] := DATABASE::"Squash Player";
No[1] := "Squash Player No.";
...
IF NOT DimMgt.CheckJnlLineDimValuePosting(JnlLineDim,
TableID,No)
THEN
IF "Line No." <> 0 THEN
..................
In the preceding code, we can clearly see that fields in our table are checked first, and then the date validation, and lastly the dimension checking.
The actual posting code turns out to be quite simple. The values are checked and then a register is created or updated.
Code()
WITH SquashJnlLine DO BEGIN
IF EmptyLine THEN
EXIT;
SquashJnlCheckLine.RunCheck(SquashJnlLine,TempJnlLineDim);
IF NextEntryNo = 0 THEN BEGIN
SquashLedgEntry.LOCKTABLE;
IF SquashLedgEntry.FIND('+') THEN
NextEntryNo := SquashLedgEntry."Entry No.";
NextEntryNo := NextEntryNo + 1;
END;
IF SquashReg."No." = 0 THEN BEGIN
SquashReg.LOCKTABLE;
IF (NOT SquashReg.FIND('+') OR ... THEN BEGIN
SquashReg.INIT;
SquashReg."No." := SquashReg."No." + 1;
...
SquashReg.INSERT;
END;
END;
SquashReg."To Entry No." := NextEntryNo;
SquashReg.MODIFY;
SquashPlayer.GET("Squash Player No.");
SquashPlayer.TESTFIELD(Blocked,FALSE);
IF (GenPostingSetup."Gen. Bus. Posting Group" <>
"Gen. Bus. Posting Group") OR
(GenPostingSetup."Gen. Prod. Posting Group" <>
"Gen. Prod. Posting Group")
THEN
GenPostingSetup.GET("Gen. Bus. Posting Group",
"Gen. Prod. Posting Group");
SquashLedgEntry.INIT;
SquashLedgEntry."Entry Type" := "Entry Type";
SquashLedgEntry."Document No." := "Document No.";
...
SquashLedgEntry."No. Series" := "Posting No. Series";
SquashLedgEntry.INSERT;
All the fields are simply moved to the ledger entry table. This is what makes Microsoft Dynamics NAV simple and powerful.
Here, we can clearly see how easy it is to add a field to a posting process. Just add the fields to the journal line, the ledger entry, and add one line of code to the posting process.