Monday, September 20, 2021

CUSTOMER CHANGE APPROVALS IN DYNAMICS 365 FINANCE AND OPERATIONS.

CUSTOMER CHANGE APPROVALS IN DYNAMICS 365 FINANCE AND OPERATIONS

In certain scenarios, few organizations may need approval process for changing the existing customer master data such as Name, Bank account etc. D365 F&O has brought a new workflow approval feature named as “Proposed customer change workflow” to meet this requirement.

By inculcating this feature, the user can configure the approval mechanism to have a hands on control on the updates to the specified business critical customer master data fields. This feature enables the change request to be approved before the changes get committed to the customer master record. 

PARAMETERS SETUP 

Below are the parameters that are required to enable this feature. Mark the Enable customer approvals check box under Accounts receivable > Setup > Accounts receivable parameters > General (Tab) > Customer approval (Tab), as shown below.

Allocate the Data entity behaviour value under Accounts receivable > Setup > Account receivable parameters > General (Tab) > Customer approval (Tab), from one of the 3 available lookup options, as appropriate, to control the data import behaviour through data entities.

·         Allow changes without approval - Customer record can be updated without approval.

  • Reject changes – Changes cannot be made to customer record.
  • Create change proposals – Changes to the fields will be treated as proposed changes and subject to required approvals. 
 

Enable the check box against each field that needs approval, under Accounts receivable > Setup > Account receivable parameters > General (Tab) > Customer approval (Tab), as shown below. In this example, Test field is enabled to illustrate the process.    

 

WORKFLOW CONFIGURATION

Configure a new workflow by selecting the workflow type named Proposed customer change workflow under Accounts receivable > Setup > Accounts receivable workflows, as shown below and setup the workflow as per business need.

UPDATE CUSTOMER DATA

Once the workflow is configured, try to update the Test for the existing customer from Accounts receivable > Customers > All customers > Edit.

Change the Test and observe that system will pop up a dialog by showing the current and proposed Test, for your review. And one can discard the changes if required.


 
Close the Proposed change dialog and submit the change to workflow.

 

Approver can click on the proposed change button on the customer master record, to view the proposed changes in the customer data before taking an appropriate action.

 

If the workflow is approved by the approver, then the changed data will get updated in Test field.

                                            

 

 

Once the workflow approval request is completed then the system will update the Test in the customer master with the proposed field value.

 

Add new field for Proposed customer changes workflow 

  • Step1. Create extension for CustTableChangeProposalField and an Enum.  add an element with name Test. 

  • Step2. Create post event handler or COC for CustTableChangeProposalFieldEnablement/InitializeAll method and add this line for your field

 

[ExtensionOf(tableStr(CustTableChangeProposalFieldEnablement))]

final class CustTableChangeProposalFieldEnablement _Extension

{

    /// <summary>

    /// Creates entries for all fields if they do not already exist.

    /// </summary>

    public static void initializeAll()

    {

        next initializeAll();

        CustTableChangeProposalFieldEnablement::findOrCreate(CustTableChangeProposalField::Test);

    }

}

  • Step 3. Create extension of CustTableChangeProposal table and add Test field and an enum filed IsChangedTest.
  

  • Step 4. Create cust change proposal form extension and add a new group for Test. This will enable to see your changes to Test filed in the proposal changes form from Customer form when workflow is activated


 
Step 5 . Create extension for CustChangePraposal form write the below code in disableDiscardbutton() method and ShowHideGroups() method

[ExtensionOf(formStr(custChangeProposal))]

final class CustTableChange_Extension

{

    /// <summary>

    /// Controls the visibility of groups representing the individual grid rows

    /// </summary>

     public void showHideGroups()

    {

        next showHideGroups();

        TestGroup.visible(CustTableChangeProposal.IsChangedTest);

    }

    /// <summary>

    /// Disable all the DiscardTest button on the form

    /// </summary>

    protected void disableDiscardButtons()

    {

        next disableDiscardButtons();

        DiscardTest.enabled(false);

    }

}

  • Step 6. Write the below code in Onclicked DiscardTestChange button of form CustChangeProposal

/// <summary>

    /// used to create new field and update the tabel CustTableChangeProposal

    /// </summary>

    /// <param name="sender">DiscardTest</param>

    /// <param name="e">Clicked</param>

    [FormControlEventHandler(formControlStr(CustChangeProposal, DiscardTest), FormControlEventType::Clicked)]

    public static void DiscardTest_OnClicked(FormControl sender, FormControlEventArgs e)

    {

        CustTableChangeProposal CustTableChangeProposal = sender.formRun().dataSource(1).cursor();

        ttsbegin;

        CustTableChangeProposal localRecord = CustTableChangeProposal::findByCustRecId(CustTableChangeProposal.CustTable, true);

        localRecord.IsChangedTest= NoYes::No;

        localRecord.update();

        ttscommit;

    } 

  • Step 7 : Create extension for table CustTableChangeProposal and extend methods like isRedundant() and setFlagForChangedField()

 

[ExtensionOf(tableStr(CustTableChangeProposal))]

final class CustTableChangeProposal_Extension

{

    /// <summary>

    /// Sets the flag marking a change for a specific field.

    /// </summary>

    /// <param name = "_controlledField">CustTableChangeProposalField</param>

   public void setFlagForChangedField(CustTableChangeProposalField _controlledField)

    {

        next setFlagForChangedField(_controlledField);

        switch (_controlledField)

        {

            case CustTableChangeProposalField::Test :

                this.IsChangedTest = NoYes::Yes;

                break;

        }

    }

 

/// <summary>

/// Checks if the record contains no active changes, and is therefore redundant.

/// </summary>

/// <returns>True if the record contains no changed field information;false    otherwise.</returns>

    public boolean isRedundant()

    {

        boolean ret = next isRedundant();

        boolean Ischanged;

        if (ret)

        {

            Ischanged = !(ret || this.IsChangedTest);

                if(! Ischanged)//Do not delete the change

            {

                ret = false;

            }

        }

        return ret;

    }

}

 

and create event handler to update IsChangedTest field  

   

/// <summary>

/// Adjusts values to keep track of changes and executes the update

/// </summary>

/// <param name="args">CustTableChangeProposal</param>

    [PostHandlerFor(tableStr(CustTableChangeProposal),tableMethodStr(CustTableChangeProposal, update))]

    public static void CustTableChangeProposal_Post_update(XppPrePostArgs args)

    {

        CustTableChangeProposal changeProposal = args.getThis();

        if (changeProposal.Test != changeProposal.orig().Test)

        {

            changeProposal.IsChangedTest = NoYes::Yes;

        }

    } 

} 

  • Step 8: Create extension for CustTable form and place the below code. Modified event on the Test would be captured and created as a change proposal for workflow

     /// <summary>

    /// This method is used for modify the newly added test control.

    /// </summary>

    /// <param name="sender">CustTable_Test</param>

    /// <param name="e">Modified</param>

    [FormControlEventHandler(formControlStr(CustTable, CustTable_Test), FormControlEventType::Modified),SuppressBPWarning('BPParameterNotUsed', "Parameter e is required")]

    public static void CustTable_Test_OnModified(FormControl sender, FormControlEventArgs e)

    {

        FormRun  formRunCustTable = sender.formRun() as FormRun;

        FormDataSource CustTableFD=sender.dataSourceObject();

        CustTable    custTableRecord=CustTableFD.cursor();

       

        formRunCustTable.modifiedControlledField(

                    fieldNum(CustTable, Test),

                    fieldNum(CustTableChangeProposal, Test),

                    custTableRecord,

            CustTableChangeProposalField::Test);

    } 

  • Step 9: The last step would to update the currency filed in the Customer table after the workflow, So create extension for CustTableChangePraposalApply and write the below code

 

[ExtensionOf(classStr(CustTableChangeProposalApply))]

final class CusttableChangeProposalApply_Extension

{

    /// <summary>

    /// Sets values of <c>CustTable</c> fields based on change proposal data.

    /// </summary>

    /// <param name = "_custTableToUpdate">CustTable</param>

    /// <param name = "_dirPartyToUpdate">DirPartyTable</param>

    protected void initializeCustTable(CustTable _custTableToUpdate, DirPartyTable _dirPartyToUpdate)

    {

        if(proposal.IsChangedTest)

        {

            _custTableToUpdate.Test = proposal.Test;

        }

        next initializeCustTable(_custTableToUpdate,_dirPartyToUpdate);

    } 

}

Keep Daxing !!

No comments:

Post a Comment