While working on Dynamics 365 Finance & Operations, there are many situations where we need to create ledger journals through X++ code instead of entering them manually from the UI.
This usually comes up when data is coming from an external system, a staging table, or when we want to automate accounting entries.
In this post, I’m sharing a simple approach I used to create ledger journals and journal lines programmatically using X++.
High-Level Approach
The process is straightforward:
-
Create the journal header
-
Initialize LedgerJournalEngine
-
Create journal lines
-
Set account, dimensions, debit/credit
-
Insert the records
Step 1: Create Journal Header
// Header creation
ledgerJournalTable.JournalNum = NumberSeq::newGetNum(LedgerParameters::numRefJournalNum()).num();
ledgerJournalTable.initFromLedgerJournalName(ledgerJournalTrans_Buffer.JournalName);
ledgerJournalTable.insert();
ledgerJournalEngine = LedgerJournalEngine::construct(ledgerJournalTable.JournalType);
ledgerJournalEngine.ledgerJournalTable(ledgerJournalTable);
ledgerJournalEngine.newJournalActive(ledgerJournalTable);
Step 2: Prepare for Journal Line Creation
//Line creation
ledgerJournalEngine.preCreate(ledgerJournalTrans);
ledgerJournalTrans.clear();
ledgerJournalTrans.initValue();
ledgerJournalTrans.JournalNum = ledgerJournalTable.JournalNum;
ledgerJournalTrans.TransDate = stagingTable.TransactionDate;
ledgerJournalTrans.modifiedField(fieldNum(LedgerJournalTrans, TransDate));
ledgerJournalTrans.Voucher = stagingTable.Voucher;
ledgerJournalTrans.CurrencyCode = stagingTable.CurrencyCode;
ledgerJournalTrans.Due = stagingTable.DueDate;
ledgerJournalTrans.DocumentDate = stagingTable.DocumentDate;
ledgerJournalTrans.ExchRate = stagingTable.ExchRate;
ledgerJournalTrans.ReportingCurrencyExchRate = stagingTable.ExchRate;
ledgerJournalTrans.Txt = stagingTable.Description;
ledgerJournalTrans.AccountType = str2Enum(ledgerJournalACType,stagingTable.AccountTypeStr);//stagingTable.AccountType;
ledgerJournalTrans.modifiedField(fieldNum(LedgerJournalTrans, AccountType));
if (stagingTable.AccountTypeStr == "Ledger")
{
ledgerJournalTrans.LedgerDimension = this.generateLedgerDimension(stagingTable.AccountDisplayValue,stagingTable.BU,'',stagingTable.BranchCode,stagingTable.EmployeeCode);
}
else if (stagingTable.AccountTypeStr == "Vendor")
{
ledgerJournalTrans.LedgerDimension = LedgerDynamicAccountHelper::getDynamicAccountFromAccountNumber(stagingTable.AccountDisplayValue,LedgerJournalACType::Vend);// stagingTable.Account;
ledgerJournalTrans.PostingProfile = vendParameters.PostingProfile;
}
else if (stagingTable.AccountTypeStr == "Customer")
{
ledgerJournalTrans.LedgerDimension = LedgerDynamicAccountHelper::getDynamicAccountFromAccountNumber(stagingTable.AccountDisplayValue,LedgerJournalACType::Cust);// stagingTable.Account;
ledgerJournalTrans.PostingProfile = custParameters.PostingProfile;
}
else if (stagingTable.AccountTypeStr == "Bank")
{
ledgerJournalTrans.LedgerDimension = LedgerDynamicAccountHelper::getDynamicAccountFromAccountNumber(stagingTable.AccountDisplayValue,LedgerJournalACType::Bank);// stagingTable.Account;
}
ledgerJournalTrans.modifiedField(fieldNum(LedgerJournalTrans, LedgerDimension));
ledgerJournalTrans.DefaultDimension = this.createDefaultDimension( stagingTable.LobCode,stagingTable.Department,stagingTable.BranchCode);
if (stagingTable.Credit)
{
ledgerJournalTrans.AmountCurCredit = stagingTable.Credit;
ledgerJournalTrans.modifiedField(fieldNum(LedgerJournalTrans, AmountCurCredit));
}
else if (stagingTable.Debit)
{
ledgerJournalTrans.AmountCurDebit = stagingTable.Debit;
ledgerJournalTrans.modifiedField(fieldNum(LedgerJournalTrans, AmountCurDebit));
}
ledgerJournalTrans.OffsetAccountType = LedgerJournalACType::Ledger;
ledgerJournalTrans.modifiedField(fieldNum(LedgerJournalTrans, OffsetAccountType));
ledgerJournalTrans.insert();