Tuesday, February 27, 2024

Get sales line tax percent to calculate GST / TAX on sales line in D365 F&O

private Percent calcSalesLineTaxPercent(Salesline  _salesline)

{

    TaxOnItem       taxOnItem;

    TaxGroupData    taxGroupData;

    TaxValue        taxValue;

    if(_salesline.TaxItemGroup && _salesline.TaxGroup && _salesline.LineAmount != 0)

    {

       select firstonly TaxOnItem

            where TaxOnItem.TaxItemGroup == _salesline.TaxItemGroup

           join TaxGroupData

                    where TaxGroupData.TaxGroup == _salesline.TaxGroup

                    && TaxGroupData.TaxCode     == TaxOnItem.TaxCode;

        if(TaxGroupData)

        {

            TaxValue  =  TaxData::find(TaxOnItem.TaxCode, DateTimeUtil::getSystemDate(DateTimeUtil::getUserPreferredTimeZone()), 0).TaxValue;

        }

    }

    return TaxValue;

}


Monday, February 19, 2024

Working with change management enabled purchase orders using X++ in D365 Finance and Operations

 

  //Change the purchase order from confirmed status to draft.   

                        Args args=new Args();

                        args.record(purchTable);

                        args.parmEnum(VersioningAction::RequestChange);

                        VersioningPurchaseOrder::main(args);

//Do update on purchase order

// write your logic

 // Tax is needed to be calculated first or else the Accounting Distribution allocation factor will not be calculated correctly.

                        PurchTotals::newPurchTable(purchTableLocal).calc();

                        // Submit to source document processor to perform GL budget check before confirming the comment dialog.

                        // This gives the approver a chance to cancel their action if there is any budget error or warning.

                        SourceDocumentProcessorFacade::submitOnDemandSourceDocumentImpl(purchTableLocal);

                        VersioningPurchaseOrder versioningPurchaseOrder;

                        versioningPurchaseOrder = VersioningPurchaseOrder::newPurchaseOrder(purchTableLocal);

//Submit workflow after change.

                        versioningPurchaseOrder.submitChangeRequest();

//Auto approve workflow

                        versioningPurchaseOrder.approveChangeRequest();

//Once it's approved then confirm the purchase order. 

                        if (purchTableLocal.DocumentState == VersioningDocumentState::Approved)

                        {

                            //Auto confirm the purchase order.

                            PurchFormLetter purchFormLetter;

                            purchFormLetter = PurchFormLetter::construct(DocumentStatus::PurchaseOrder);

                            PurchaseOrderId purchOrderDocNum = strFmt('%1-%2', purchTableLocal.PurchId, VendPurchOrderJour::numberOfPurchaseOrderVersions(purchTableLocal)+1);

                            purchFormLetter.update(purchTableLocal, purchOrderDocNum);

                        }

Thursday, February 15, 2024

Auto confirm purchase order confirmation through X++ code in D365 F&O

                     //Auto confirm the purchase order.

                        PurchFormLetter purchFormLetter;


                        purchFormLetter = PurchFormLetter::construct(DocumentStatus::PurchaseOrder);

                        PurchaseOrderId purchOrderDocNum = strFmt('%1-%2', purchTable.PurchId, VendPurchOrderJour::numberOfPurchaseOrderVersions(purchTable)+1);

                        purchFormLetter.update(purchTable, purchOrderDocNum);

Wednesday, February 14, 2024

Enabling and disabling flight in Cloud Hosted VM, Sandbox and Production server in Dynamics 365 F&O

 

if you want to disable the flight in cloud hosted VM's then you need to run below command in SQL by replacing your flight name in place of <FlightName>. 

The "_KillSwitch" is important because this indicates turning of the flight.

INSERT INTO dbo.SYSFLIGHTING(FLIGHTNAME, ENABLED, FLIGHTSERVICEID) VALUES ('<FlightName>_KillSwitch', 1, 12719367)


if you want to enable the flight then if you just delete above entry then it will be enabled back(if you flight defaulted only). if not then you need to run below statement to enable your flight in SQL.

INSERT INTO dbo.SYSFLIGHTING(FLIGHTNAME, ENABLED, FLIGHTSERVICEID) VALUES ('<FlightName>', 1, 12719367)


In case of sandbox and Production servers, we will not be able to turn on or off by our self. we need to log a ticket with Microsoft support team and they can help you with the same. 


#Flight #X++ #Dynamics 365F&O #EnableFlightInSandbox #EnableFLightInProduction #DisableFlightInSandbox #DisableFLightInProduction

Wednesday, February 7, 2024

Applying custom filter to open excel template through X++ in Dynamics 365 F&O

In our recent project, we’ve developed a customized form that is rich with calculations. The data is retrieved and displayed on the form based on multiple checks. This form is part of an Excel Office Add-in that we’ve been working on.

Initially, when we opened the form using the Excel Office Add-in, it would fetch and display all the data by default. However, we received feedback from users who wanted to see only selected records in the grid.

This functionality worked fine if the parent data source had only one entry. But, when there were multiple entries in the parent data source, the default behavior was not sufficient.

To enhance the user experience, we decided to implement custom filters before exporting the data. This way, users can choose the records they want to see in the grid.

Here’s a code snippet that gives you an idea of how we applied custom filters.

 

<pre>

using Microsoft.Dynamics.Platform.Integration.Office;

[Form]

public class JPPurchTransferBudgets extends FormRun implements OfficeIMenuCustomizer, OfficeITemplateCustomExporter

{

    /// <summary>

    /// Customizes the options used to populate the Office Menu with the sales order entities.

    /// </summary>

    /// <param name = "_menuOptions">The menu options to be customized.</param>

    public void customizeMenuOptions(OfficeMenuOptions _menuOptions)

    {

        //Required by interface not important to this scenario

    }


    /// <summary>

    /// Update Tmplete setting.

    /// </summary>

    /// <param name = "_menuItem"> Menu item.</param>

    /// <param name = "_settingsManager"> Setting manager.</param>

    void updateTemplateSettings(OfficeTemplateExportMenuItem _menuItem, Microsoft.Dynamics.Platform.Integration.Office.SettingsManager _settingsManager)

    {

        //Required by interface not important to this scenario

    }


    /// <summary>

    /// Adds filters on exported records.

    /// </summary>

    /// <param name = "_menuItem"> Menu item name.</param>

    /// <returns> Map of filters.</returns>

    Map getInitialTemplateFilters(OfficeTemplateExportMenuItem _menuItem)

    {

        Map filtersToApply = new Map(Types::String, Types::Class);

        JPProjSelected    projSelected;

        if (_menuItem.dataEntityName() == tableStr(JPPurchTransferBudgetEntity))

        {

            var lineEntityName = tableStr(JPPurchTransferBudgetEntity);

            // Create lines filter

            ExportToExcelFilterTreeBuilder lineFilterBuilder = new ExportToExcelFilterTreeBuilder(lineEntityName);

            select firstonly projSelected;

            if (projSelected && !this.parmProjId())

            {

                var lineFilter = lineFilterBuilder.and(

                                                lineFilterBuilder.areEqual(fieldStr(JPPurchTransferBudgetEntity, FiscalYearName), JPPurchTransferBudget.FiscalYearName),

                    lineFilterBuilder.areNotEqual(fieldStr(JPPurchTransferBudgetEntity, SelectedProjId), SysQuery::valueEmptyString()));

                filtersToApply.insert(lineEntityName, lineFilter);

            }

            else if (!this.parmProjId())

            {

                var lineFilter = lineFilterBuilder.and(

                                                lineFilterBuilder.areEqual(fieldStr(JPPurchTransferBudgetEntity, FiscalYearName), JPPurchTransferBudget.FiscalYearName),

                    lineFilterBuilder.areEqual(fieldStr(JPPurchTransferBudgetEntity, DataAreaId), JPPurchTransferBudget.DataAreaId));

                filtersToApply.insert(lineEntityName, lineFilter);

            }

            if (this.parmProjId())

            {

                var lineFilter = lineFilterBuilder.or(

                                                lineFilterBuilder.areEqual(fieldStr(JPPurchTransferBudgetEntity, ProjId), this.parmProjId()),

                    lineFilterBuilder.areEqual(fieldStr(JPPurchTransferBudgetEntity, ParentId), this.parmProjId()));

                filtersToApply.insert(lineEntityName, lineFilter);

            }

        }

        return filtersToApply;

    }

</pre>


Enhancing User Experience with Custom Filters in Excel Office Add-in

Get party contact information based on the role type through X++ in Dynamics 365 F&O

 Get any party contact information based on the role type. 

// Phone

addressDetails = DirParty::electronicAddressLocatorsByRole(DirPartyTable::find(companyInfo::find().PartyNumber).RecId,

                                                               LogisticsElectronicAddressMethodType::Email,

                                                               enum2str(LogisticsLocationRoleType::None));

    info(strFmt("MailId: %1",conPeek(addressDetails, 1)));

    

// EmailId

addressDetails = DirParty::electronicAddressLocatorsByRole(DirPartyTable::find(companyInfo::find().PartyNumber).RecId,

                                                              LogisticsElectronicAddressMethodType::Phone,

                                                              enum2str(LogisticsLocationRoleType::None));

Thursday, February 1, 2024

Handling update conflict and capture standard error message to throw error to end user in D365 F&O

We can use follow sample code to handle update conflict in case of exceptions and then Method to capture the standard error and send it the particular catch of the method.

Hope this helps!

public void runOperation()

    {

        #OCCRetryCount

        try

        {

            ttsbegin;

            //Do something insert/update

            ttscommit;


        }

        catch(Exception::UpdateConflict)

        {

            if (appl.ttsLevel() == 0)

            {

                if (xSession::currentRetryCount() >= #RetryNum)

                {

                    throw Exception::UpdateConflictNotRecovered;

                }

                else

                {

                    retry;

                }

            }

        }

        catch

        {

            info(strFmt(this.getErrorStr()));

        }

    }


    /// <summary>

    /// Method to capture the standard error and send it the perticular catch of the method.

    /// </summary>

    /// <returns>error</returns>


    public str getErrorStr()

    {

        SysInfologEnumerator    enumerator;

        SysInfologMessageStruct msgStruct;

        Exception               exception;

        str                     error;


        enumerator = SysInfologEnumerator::newData(infolog.cut());


        while (enumerator.moveNext())

        {

            msgStruct = new SysInfologMessageStruct(enumerator.currentMessage());

            exception = enumerator.currentException();

            error = strfmt("@SYS82282"+ ' '+"@MCR26302", error, msgStruct.message());

        }

        return error;

    }


#D365F&O, #X++, #Exceptionhandling, #UpdateConflict