web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

Community site session details

Community site session details

Session Id :

How to generate general ledger vouchers using Data Entities and X++ in Dynamics 365 For Operations

Hichem.Chekebkeb Profile Picture Hichem.Chekebkeb 3,371

I had a requirement to generate general ledger vouchers programmatically in Dynamics 365 for Operations. Since Axd classes were removed, and Data entities came into picture, I thought of using them to achieve my goal.

I tried to use LedgerJournalLineEntity but was disappointed finding that I can only use display values. Fortunately, the properties like Account and OffsetAccount exist but their access were set to Private, So, I decided to duplicate the entity to my own model and make the properties of Account and OffsetAccount public, changed the Public Entity Name, then I could use it perfectly =)

Hint: You can try the same with all kinds of journals.

class GenerateJournalVoucher
{
       public void generate()
    {
        DimensionDynamicAccount myMainAccount;
        DimensionDynamicAccount myDefaultDimension;
        DimensionDynamicAccount myOffsetMainAccount;
        DimensionDynamicAccount myOffsetDefaultDimension;
        LedgerJournalLineGen JvGen;
                    
             
        JvGen.initValue();
       
        //Common
              JvGen.JournalBatchNumber = 'JB-00123'; // You can use LedgerJournalTable Entity to generate the header
        // JvGen.Voucher no need to generate voucher sequence, AX will manage it for you
        JvGen.CurrencyCode = 'USD';
        JvGen.Text = 'Some description';
 
        //account
              JvGen.AccountType = LedgerJournalACType::Ledger;
        DimensionDynamicAccount ledgerDimension = this.findOrCreateDynamicDimension(myMainAccount, myDefaultDimension);
        JvGen.Account = ledgerDimension;
        JvGen.DebitAmount = 1000;
 
        //Offest account
        JvGen.OffsetAccountType = LedgerJournalACType::Ledger;
        DimensionDynamicAccount OffsetledgerDimension = this.findOrCreateDynamicDimension(myOffsetMainAccount, myOffsetDefaultDimension);
        JvGen.OffsetAccount = ledgerDimension;
               
        JvGen.insert();
 
              info('JV inserted sucessfully');
    }
 
    DimensionDynamicAccount  findOrCreateDynamicDimension(DimensionDynamicAccount _account, DimensionDynamicAccount _dimensions)
    {
        DimensionAttributeValueCombination  davc;
        DimensionAttributeValueSetItem      dimAttValueSetItem;
        DimensionAttributeValueSet          dimAttValueSet;
        DimensionAttributeValue             dimAttValue;
        DimensionAttribute                  dimAtt;
        DimensionDynamicAccount             dynamicDimension;
        AccountNum                          account;
 
        DefaultDimensionIntegrationValues   dimensionNames;
        DimensionDisplayValue               dimensionValues;
 
        davc = DimensionAttributeValueCombination::find(_account);
 
        if (davc.LedgerDimensionType == LedgerDimensionType::DefaultAccount)
        {
            dimensionNames = DimensionAttribute::find(DimensionAttribute::getWellKnownDimensionAttribute(DimensionAttributeType::MainAccount)).Name;
            dimensionValues = LedgerDynamicAccountHelper::getAccountNumberFromDynamicAccount(_account);
            str delimiter = DimensionParameters::getDimensionSegmentDelimiter();
 
            // Add order line dimensions
            while select dimAttValueSetItem
                join RecId from dimAttValueSet
                where dimAttValueSet.RecId                          == _dimensions &&
                      dimAttValueSetItem.DimensionAttributeValueSet == dimAttValueSet.RecId
                    join RecId, DimensionAttribute from dimAttValue
                    where dimAttValue.RecId == dimAttValueSetItem.DimensionAttributeValue
                        join RecId, Name from dimAtt
                        where dimAtt.RecId == dimAttValue.DimensionAttribute
            {
                // Add the dimension name and dimension value
                dimensionNames += delimiter;
                dimensionValues += delimiter;
 
                dimensionNames += dimAtt.Name;
                dimensionValues += strReplace(dimAttValueSetItem.DisplayValue, delimiter, '\\' + delimiter);
            }
 
            LedgerAccountDimensionResolver ledgerAccountDimensionResolver = LedgerAccountDimensionResolver::newResolver(dimensionValues);
            ledgerAccountDimensionResolver.parmDimensionFormat(dimensionNames);
            dynamicDimension = ledgerAccountDimensionResolver.resolve();
        }
 
        return dynamicDimension;
    }
 
}
 
Hope this helps!

Comments

*This post is locked for comments

  • Community Member Profile Picture Community Member
    Posted at

    good one, but when I tried to use standard excel integration to import journal via excel I received an error '

    LedgerJournalLineEntity is not a public data entity'

  • Community Member Profile Picture Community Member
    Posted at

    @Hichem, Ok I see what you mean, thanks :).

    However as i'm a newer Dynamics 365 developer...I dn't know if what you write here is what i need :).

    Please check this question i've put online.

    Is it what you did here?!

    Thanks in Advance,

    community.dynamics.com/.../264465

  • Hichem.Chekebkeb Profile Picture Hichem.Chekebkeb 3,371
    Posted at

    Good question @Ramzi, Don't worry I am aware that I am breaking DRY principle but here in D365FO I tried to extend the entity but I was not able to modify the access right of those properties from private to public, if it was protected I would have tried to inherit and build public properties but it wasn't the case. So, I ended up duplicating the whole entity in my extension model. So I am using extension model not over-layering. Now you can understand I had not choice but duplicating the code.

  • Community Member Profile Picture Community Member
    Posted at

    @Hichem, I'm new Dynamics 365 Developer.

    You said "Right-Click > Duplicate to project" means you had a new copy?!

    You duplicate code, Really I don't understand! where's oriented object programming?!

    And for this example do you create a new model as extension or overlaying?!

    Thanks in Advance

  • Hichem.Chekebkeb Profile Picture Hichem.Chekebkeb 3,371
    Posted at

    For BP rules you can go to Visual studio setting & disable Checking best practices.

    For the LedgerDefaultDimensionValueSet error check to which model it belongs and reference it to you model. This will resolve the last two errors & you are ready to go.

  • Community Member Profile Picture Community Member
    Posted at

    Hi Hichem,

                I have used to duplicate ledger journal data entity with same code and made access specifiers ans public and tired your code.  But i am getting lot of errors regarding

    ****************

    1:     BP Rule: [DataEntityDimensionFieldIncorrectAccessModifier]:Path: [dynamics://DataEntityView/ModifiedLedgerJournalLineEntity/DataEntityViewMappedField/Account]:The 'Account' entity field must have the Access Modifier property set to Private or Internal.

    2:     BP Rule: [DataEntityDimensionFieldIncorrectAccessModifier]:Path: [dynamics://DataEntityView/ModifiedLedgerJournalLineEntity/DataEntityViewMappedField/OffsetAccount]:The 'OffsetAccount' entity field must have the Access Modifier property set to Private or Internal.

    3:     BP Rule: [DataEntityFieldLabelPropertyCheck]:Path: [dynamics://DataEntityView/ModifiedLedgerJournalLineEntity/DataEntityViewMappedField/ItemSalesTaxGroup]:DataEntityFieldLabelPropertyCheck: The field 'ItemSalesTaxGroup' has the same label '@SYS21932' as the backing data source 'LedgerJournalTrans' field 'TaxItemGroup'.

    4:     BP Rule: [DataEntityFieldLabelPropertyCheck]:Path: [dynamics://DataEntityView/ModifiedLedgerJournalLineEntity/DataEntityViewMappedField/OffsetAccountType]:DataEntityFieldLabelPropertyCheck: The field 'OffsetAccountType' has the same label '@SYS23950' as the backing data source 'LedgerJournalTrans' field 'OffsetAccountType'.

    5.   BP Rule: [DataEntitySecurityPrivilegeCheck]:Path: [dynamics://DataEntityView/ModifiedLedgerJournalLineEntity]:DataEntitySecurityPrivilegeCheck: The data entity 'ModifiedLedgerJournalLineEntity' is not assigned to a security privilege.

    6:  The name 'LedgerDefaultDimensionValueSet' does not denote a class, a table, or an extended data type.

    7:  The underlying type 'LedgerDefaultDimensionValueSet ' or its base type for table 'ModifiedLedgerJournalLineEntity' field 'OffsetDefaultDimension' does not exist.

    *******////

    I am getting these types of error.can you suggest me an solution.

    Thanks & regards ,

    padmapriya.v

  • Hichem.Chekebkeb Profile Picture Hichem.Chekebkeb 3,371
    Posted at

    @Padma varatharajan 123

    I copied the out-of-box data entity  LedgerJournalLineEntity to my model (Right-Click > Duplicate to project) and renamed it. Also rename the public name as I mentioned.

  • Community Member Profile Picture Community Member
    Posted at

    Hi  Hichem ,

                what is meant by LedgerJournalLineGen .

    Thanks & regards,

    padmapriya.v

  • Hichem.Chekebkeb Profile Picture Hichem.Chekebkeb 3,371
    Posted at

    Hi Abdel Fatah,

    Are you sure the all GL setup is correct? Are you using demo VM or your own plateform?

    Check also this post:

    community.dynamics.com/.../data-management-financial-dimensions-import

  • Abdel Fatah Ahmed Profile Picture Abdel Fatah Ahmed
    Posted at

    nice one but i have problem everything is ok but the account and the offset account they're not inserted into the lines so i cannot continue with posting the GJ can u help me with that