Create General Journals in D365 fo using X++


Below is the code to create general journals in D365 using X++. In this implementation, we utilize the LedgerJournalEngine, which can handle both single- and multi-voucher journal creation scenarios. This approach increases the likelihood that the resulting lines will match those created manually.

public class CreateGeneralJournalService
{
    ledgerJournalTable      ledgerJournalTable;
    ProjParameters          projParameters;
    LedgerJournalEngine     ledgerJournalEngine;

    /// <summary>
    /// Method Used to create the Journal Header
    /// </summary>
    /// <returns>ledgerJournalTable</returns>
    public ledgerJournalTable createGeneralJournalHeader()
    {
        projParameters = ProjParameters::find();

        ledgerJournalTable.clear();
        ledgerJournalTable.initValue();
        ledgerJournalTable.initFromLedgerJournalName(projParameters.DaxJournalNameId);
        ledgerJournalTable.JournalNum = JournalTableData::newTable(ledgerJournalTable).nextJournalId();
        ledgerJournalTable.insert();

        ledgerJournalEngine = LedgerJournalEngine::construct(ledgerJournalTable.JournalType);
        ledgerJournalEngine.newJournalActive(ledgerJournalTable);

        return ledgerJournalTable;
    }

    /// <summary>
    ///Method Used to create the journal Lines
    /// </summary>
    /// <param name = "_StagingTrans"></param>
    public void createGeneralJournalLine(DaxStagingTrans    _StagingTrans)
    {
        ledgerJournalTrans  ledgerJournalTrans;

        // DeptCC-ProfitCenter-PRODGRP-UnifiedProductID-Customer-Vendor
        container           conAttribute            = CreateGeneralJournalService::getFDFromParameters();
        container           convalue                = [_StagingTrans.Costcenter, projParameters.DaxProfitCenter];
        RecId               defaultDimensionRecId   = CreateGeneralJournalService::createDefaultDimension(conAttribute, convalue);

        ledgerJournalTrans.clear();
        ledgerJournalTrans.initValue();
        ledgerJournalEngine.initValue(ledgerJournalTrans);

        ledgerJournalTrans.JournalNum             = ledgerJournalTable.JournalNum;
        ledgerJournalTrans.TransDate              = _StagingTrans.JournalDate;
        ledgerJournalTrans.AccountType            = LedgerJournalACType::Ledger;
        ledgerJournalTrans.modifiedField(fieldNum(LedgerJournalTrans, AccountType));
        ledgerJournalTrans.LedgerDimension        = LedgerDimensionFacade::serviceCreateLedgerDimension(this.getDefaultAccount(_StagingTrans.Expensecategory), defaultDimensionRecId);;
        ledgerJournalTrans.modifiedField(fieldNum(LedgerJournalTrans, LedgerDimension));
        ledgerJournalEngine.accountModified(LedgerJournalTrans);

        ledgerJournalTrans.OffsetAccountType        = LedgerJournalACType::Ledger;
        ledgerJournalTrans.modifiedField(fieldNum(LedgerJournalTrans, OffsetAccountType));
        ledgerJournalTrans.OffsetLedgerDimension    = LedgerDimensionFacade::serviceCreateLedgerDimension(projParameters.DaxReimbursableEmpExpensePayAccount, defaultDimensionRecId);
        ledgerJournalTrans.modifiedField(fieldNum(LedgerJournalTrans, OffsetLedgerDimension));
        ledgerJournalEngine.offsetAccountModified(ledgerJournalTrans);

        ledgerJournalTrans.CurrencyCode             = _StagingTrans.Currency;
        ledgerJournalEngine.currencyModified(LedgerJournalTrans);
        ledgerJournalTrans.AmountCurDebit           = _StagingTrans.Costamount;
        ledgerJournalTrans.DaxTransID               = _StagingTrans.TransID;
        ledgerJournalTrans.DaxOrderItemID           = _StagingTrans.OrderItemId;
        ledgerJournalTrans.DaxExpenseCategory       = _StagingTrans.Expensecategory;
        ledgerJournalTrans.Approved = NoYes::Yes;
        ledgerJournalTrans.SkipBlockedForManualEntryCheck = true;

        ledgerJournalTrans.defaultRow();
        ledgerJournalTrans.TaxItemGroup = nullValueFromType(Types::String);
        ledgerJournalTrans.TaxGroup     = nullValueFromType(Types::String);

        if (ledgerJournalTrans.validateWrite())
        {
            ledgerJournalTrans.insert();

            ledgerJournalEngine.write(ledgerJournalTrans);
        }
    }

    /// <summary>
    /// A construct method to Create an object
    /// </summary>
    /// <returns></returns>
    public static CreateGeneralJournalService construct()
    {
        return new CreateGeneralJournalService();
    }

    /// <summary>
    /// Gets the default dimension from Proj posting setup
    /// </summary>
    /// <param name = "_categoryRelation">Str</param>
    /// <returns>LedgerDimensionDefaultAccount</returns>
    public LedgerDimensionDefaultAccount getDefaultAccount(str _categoryRelation)
    {
        ProjPosting   projPosting;

        select firstonly projPosting
            where projPosting.ProjAccountType       == ProjAccountType::CostAccount
               && projPosting.ProjCategoryRelation  == _categoryRelation;

        return projPosting.LedgerDimension;
    }

    /// <summary>
    /// It will returns the format of finanicaial dimensions
    /// </summary>
    /// <returns>container</returns>
    public static container getFDFromParameters()
    {
        DimensionHierarchy              dimensionHierarchy;
        DimensionHierarchyIntegration   dimensionHierarchyIntegration;

        select firstonly DisplayString from dimensionHierarchyIntegration
            exists join dimensionHierarchy
                where dimensionHierarchy.RecId == dimensionHierarchyIntegration.DimensionHierarchy
                    && dimensionHierarchy.StructureType == DimensionHierarchyType::DataEntityDefaultDimensionFormat
                    && dimensionHierarchyIntegration.IsDefault == true;

        return str2con(dimensionHierarchyIntegration.DisplayString, DimensionParameters::getDimensionSegmentDelimiter());
    }

    /// <summary>
    /// Method Used to create the default Dimension
    /// </summary>
    /// <param name = "conAttribute"></param>
    /// <param name = "convalue"></param>
    /// <returns></returns>
    public static  DimensionDefault createDefaultDimension(container conAttribute , container convalue)
    {
        DimensionAttributeValueSetStorage   valueSetStorage = new DimensionAttributeValueSetStorage();
        DimensionAttribute                  dimensionAttribute;
        DimensionAttributeValue             dimensionAttributeValue;
        str                                 dimValue;

        for (int i = 1; i <= conLen(conAttribute); i++)
        {
            dimensionAttribute = dimensionAttribute::findByName(conPeek(conAttribute,i));
            if (dimensionAttribute.RecId == 0)
            {
                continue;
            }

            dimValue = conPeek(convalue,i);
            if (dimValue != "")
            {
                dimensionAttributeValue = dimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute, dimValue, false, true);
                valueSetStorage.addItem(dimensionAttributeValue);
            }
        }

        return valueSetStorage.save();
    }

}


Additionally, to post the above created Journals we can use LedgerJournalcheckpost class as below

LedgerJournalCheckPost ledgerjournalcheckpost = LedgerJournalCheckPost::newLedgerJournalTable(ledgerJournalTable,NoYes::Yes);
    if (ledgerjournalcheckpost.validate())
    {
        ledgerjournalcheckpost.run();
    }

Thanks !!

No comments:

Post a Comment