Wednesday, June 26, 2024

How to use crosscompany in Query in D365 F&O | X++

Sometimes, we receive requirements to fetch data across all legal entities. In such cases, cross-company functionality can be utilized. Below is an example demonstrating this approach     

Query query = new Query();

QueryBuildDataSource queryBuildDataSource;

QueryBuildRange queryBuildRange;

queryBuildDataSource = query.addDataSource(tableNum(InventLocation));

query.allowCrossCompany(true);


This query will return all warehouses across legal entities. 


How to cancel sales line in D365 F&O using X++

If there's a requirement to cancel a sales line through code X++ in D365 F&O, the following code can be used to achieve it. In this example, I’ve created an extension of the SalesLine table and added a new method that can be called to cancel the selected sales line.

[ExtensionOf(tableStr(SalesLine))]

final class SalesLine_Extension

{

    public void gauCancelSalesOrderLine()

    {

        ttsbegin;

        this.selectForUpdate(true);

        SalesUpdateRemain::construct().updateDeliverRemainder(this, 0, 0);

        ttscommit;

    }

}

How to call Runbase batch job using X++ in D365 F&O

If there's a requirement to call a RunBaseBatch class using X++ code, the following example demonstrates how to do it. In this case, we’re using the GUPItemBasePriceCalcJob class, which is a RunBaseBatch class, and calling it by setting the appropriate parameters.        

        BatchHeader         header;

        SysRecurrenceData   sysRecurrenceData;

        Batch               batch;

        BatchJob            batchJob;

        BatchInfo           processBatchInfo;

        BatchRetries        noOfRetriesOnFailure = 4;

        GUPItemBasePriceCalcJob GUPItemBasePriceCalcJob; // RunBase batch class

        #define.timeInSecondsDelay(20)

      

        select forupdate batch

        join batchJob

        where batchJob.RecId == batch.BatchJobId

                && batch.ClassNumber == classnum(GUPItemBasePriceCalcJob)

                && batchJob.Status == BatchStatus::Waiting

                && batch.Company == curext();

        if (!batch)

        {

            // Setup the RunBaseBatch Job

            header = BatchHeader::construct();

            GUPItemBasePriceCalcJob= GUPItemBasePriceCalcJob::construct();

            GUPItemBasePriceCalcJob.parmItemId(ItemId); // pass Item Id 

            GUPItemBasePriceCalcJob.parmSiteId(SiteId); // pass Site 

            processBatchInfo = GUPItemBasePriceCalcJob.batchInfo();

            processBatchInfo.parmRetriesOnFailure(noOfRetriesOnFailure);

            header.addTask(GUPItemBasePriceCalcJob);            


            // Set the recurrence data

            sysRecurrenceData = SysRecurrence::defaultRecurrence();

            sysRecurrenceData = SysRecurrence::setRecurrenceStartDateTime(sysRecurrenceData,                             DateTimeUtil::addSeconds(DateTimeUtil::utcNow(), #timeInSecondsDelay));

            sysRecurrenceData = SysRecurrence::setRecurrenceNoEnd(sysRecurrenceData);

            sysRecurrenceData = SysRecurrence::setRecurrenceEndAfter(sysRecurrenceData, 1); 


            header.parmRecurrenceData(sysRecurrenceData);

            // Set the batch alert configurations

            header.parmAlerts(NoYes::No, NoYes::Yes, NoYes::No, NoYes::Yes, NoYes::No);

            header.save();

Tuesday, May 14, 2024

How to call SysOperation batch job using X++ in D365 F&O

ChangeItemController     controller  = ChangeItemController ::construct();

ChangeItemContract       contract    = controller ? controller.getDataContractObject() : null;


if (!contract)

        throw error(Error::wrongUseOfFunction(funcName()));


// Set contract fields

contract.parmItemId(this.ItemId);

contract.parmInventSiteId(this.SiteId );


controller.parmExecutionMode(SysOperationExecutionMode::ScheduledBatch); // Set execution mode

controller.parmShowDialog(false); 

controller.parmLoadFromSysLastValue(false); 

controller.parmInBatch(true);

controller.parmDialogCaption('Change Item');

controller.startOperation();

Friday, April 26, 2024

Create ledger journals in D365FO using X++

 Below code will help to create record in JedgerJournalTable and LedgerJournalTrans in D365FO using x++.

// 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);


//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();


How to create LedgerDimension in D365 F&O using x++

 The code below will help out to generate Ledger Dimension using x++ in D365 FO

   


 public RefRecId  generateLedgerDimension(MainAccountNum     _mainAccountId,

                                             DimensionValue     _businessUnit, 

                                             DimensionValue     _department,

                                             DimensionValue     _branchCode,

                                             DimensionValue     _employeeCode)

    {

        container                           conData;

        int                                 hierarchyCount;

        int                                 hierarchyIdx;

        LedgerRecId                         ledgerRecId;

        MainAccount                         mainAccount;

        RefRecId                            recordvalue;

        DimensionAttribute                  dimensionAttribute;

        DimensionAttributeValue             dimensionAttributeValue;

        DimensionSetSegmentName             DimensionSet;

        DimensionStorage                    dimStorage;

        DimensionAttributeValueContract     ValueContract;

        LedgerAccountContract               LedgerAccountContract;

        DimensionAttributeValueCombination  dimensionAttributeValueCombination;

        List                                valueContracts;


        #define.MainAccount('MainAccount')

        #define.Department('Department')

        #define.BusinessUnit('BusinessUnit')

        #define.BranchCode('BranchCode')

        #define.EmployeeCode('EmployeeCode')

        



        LedgerAccountContract   = new LedgerAccountContract();

        valueContracts          = new List(Types::Class);


        conData = [_mainAccountId];



        mainAccount     =   MainAccount::findByMainAccountId(_mainAccountId);

        recordvalue     =   DimensionHierarchy::getAccountStructure(mainAccount.RecId,Ledger::current());

        hierarchyCount  =   DimensionHierarchy::getLevelCount(recordvalue);

        DimensionSet    =   DimensionHierarchyLevel::getDimensionHierarchyLevelNames(recordvalue);


        if (recordvalue)

        {

            for(hierarchyIdx = 1;hierarchyIdx<=hierarchyCount;hierarchyIdx++)

            {

                if(hierarchyIdx == 1)

                {

                    continue;

                }

                dimensionAttribute = DimensionAttribute::findByLocalizedName(DimensionSet[hierarchyIdx],false);

                                

                if (dimensionAttribute.Name == #Department)

                {

                    conData += [_department];

                }

                else if (dimensionAttribute.Name == #BusinessUnit)

                {

                    conData += [_businessUnit];

                }

                else if (dimensionAttribute.Name == #BranchCode)

                {

                    conData += [_branchCode];

                }

                else if (dimensionAttribute.Name == #EmployeeCode)

                {

                    conData += [_employeeCode];

                }



                if(dimensionAttribute)

                {

                    dimensionAttributeValue = DimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,conPeek(conData,hierarchyIdx));


                    if(dimensionAttributeValue)

                    {

                        ValueContract = new DimensionAttributeValueContract();

                        ValueContract.parmName(dimensionAttribute.Name) ;

                        ValueContract.parmValue(dimensionAttributeValue.CachedDisplayValue);

                        valueContracts.addEnd(ValueContract);

                    }

                }


            }

            LedgerAccountContract.parmMainAccount(_mainAccountId);

            LedgerAccountContract.parmValues(valueContracts);


            dimStorage = DimensionServiceProvider::buildDimensionStorageForLedgerAccount(LedgerAccountContract);

            dimensionAttributeValueCombination = DimensionAttributeValueCombination::find(dimStorage.save());

            ledgerRecId = dimensionAttributeValueCombination.RecId;

        }

        else

        {

            warning (strfmt('Ledger dimension Issue for main account %1', _mainAccountId));

        }


        return  ledgerRecId;

    }