Tuesday, June 28, 2022

How to use vendor disbursement journal workflow for vendor creation

Hi D365Fo Community,
Welcome to my new blog, This is a common requirement to have workflow for Vendor Creation process but standard does not support this. so lets learn how can we utilize vendor disbursement journal workflow for vendor creation by doing small customization.

Requirement : All the new vendors should go through approval process.

Solution
1) Use vendor amendment workflow during vendor creation.
2) Put Vendor on Hold until it is approved.  
3) Restrict original submit to workflow functionality until user provide approval for Creation workflow.
4) Not allow to create record in proposed changes table during creation workflow.
5) Restrict to call amendment workflow in case you modify the field which is enabled in AP parameter > Vendor approval tab

Prerequisite - Need to have Vendor amendment workflow setup. Please click on vendor workflow setup.

Step by step implementation -

 Step 1 : Add new enum type of field in VendTable :
            fieldname - DemoCreationWorkflowApproved
            EDT          - NoYesId    

Step 2 : Write COC for VendTable method insert().
Description : Assign No during record creation.

[ExtensionOf(tableStr(VendTable))]
final class DemoVendTable_Extension
{
   //Assign No during record creation.
    public void insert()
    {
         if(!this.RecId)
        {
            this.DemoCreationWorkflowApproved= NoYes::No;
         }
         next insert();
    }

    // Update blocked to No once it is approved by User and set DemoCreationWorkflowApproved to Yes
     
      public static void updateWorkflowState(RecId _recId, VendTableChangeProposalWorkflowState _state)
     {
            next updateWorkflowState( _recId,  _state);
            ttsbegin;
            VendTable vendTable = VendTable::findRecId(_recId, true);
            if( _state == VendTableChangeProposalWorkflowState::Approved)
            {
                  vendTable.Blocked               =  CustVendorBlocked::No;
                  vendTable.DemoCreationWorkflowApproved= NoYes::Yes;
                  vendTable.update();
            }
            ttscommit;

      }

}

Step 3: Block the vendor for all area till it is approved.
Create new class to keep event handlers for table methods. Copy the post event handler of insert method and add below code.

class DemoVendTableEventHandler
{
    [PostHandlerFor(tableStr(VendTable), tableMethodStr(VendTable, insert))]
    public static void VendTable_Post_insert(XppPrePostArgs args)
    {
        VendTable vendTable = args.getThis() as VendTable;

        if(vendTable)
        {
            ttsbegin;
            vendTable.selectForUpdate(true);
            vendTable.Blocked = CustVendorBlocked::All;
            vendTable.update();
            ttscommit;
            vendTable.reread();

        }
    }

}

Step 4 :  Create COC for main method of class VendTableChangeProposalWorkflowSubmitManager and add below code.
This is to not allow user to use standard workflow during vendor creation.

[ExtensionOf(classStr(VendTableChangeProposalWorkflowSubmitManager))]
final class DemoVendTableChangeProposalWorkflowSubmitManager_Extension
{
    public static void main(Args _args)
    {
        if (!_args.record() || !_args.caller())
        {
            throw error(Error::wrongUseOfFunction(funcName()));
        }

        VendTable  vendTable = _args.record();
        if(vendTable.DemoCreationWorkflowApproved== NoYes::No)
        {
            throw error("Creation workflow not yet approved.");
        }
        next main(_args);
    }
}

}

Step 5 : Create COC for init() method of form VendChangeProposal
We will not allow to open proposed changes form on modification of any standard field which is enabled for amendment workflow, and delete the record if exists for vendor if not approved and workflow state is Not Submitted.

[ExtensionOf(formstr(VendChangeProposal))]
final class DemoVendChangeProposalForm_Extension
{
    public void init()
    {
        VendTableChangeProposal vendProposal;
         next init();
        if(!callerRecord.DemoCreationWorkflowApproved)
        {
            if(callerRecord.Workflowstate == VendTableChangeProposalWorkflowState::NotSubmitted)
            {
                delete_from vendProposal
                where vendProposal.VendTable == callerRecord.RecId;
            }
            this.close(); // code the close the open form
        }        

    }

}

Step 6 : Create new class to call amendment workflow and add below code.

class DemoCallVendorDisbursementWFHelper
{
    public static void main(Args _args)
    {

        FormDataSource ds =  _args.caller().datasource();
        VendTable                      vendTable = ds.cursor();

        if(vendTable)
        {
            DemoCallVendorDisbursementWFHelper ::submitToVendWorkflow(vendTable);
            ds.research(true);
            ds.refresh();
        }
    }

    public static void submitToVendWorkflow(VendTable _vendTable)
    {

        WorkflowCorrelationId      workflowCorrelationId;
        if(_vendTable.DemoCreationWorkflowApproved)
        {
            throw error("Vendor creation workflow is already approved.");
        }

        Notes note = strFmt("%1 Vendor changes",_vendTable.AccountNum);
        workflowCorrelationId =      Workflow::activateFromWorkflowType(WorkflowTypestr(VendTableChangeProposalWorkflow),     _vendTable.RecId,note , NoYes::No);        

        _vendTable.selectForUpdate(true);
        _vendTable.WorkflowState = VendTableChangeProposalWorkflowState::Submitted;
        _vendTable.update();
        _vendTable.reread();       
        VendTableChangeProposal vendTableChangeProposal =                       VendTableChangeProposal::findByVendRecId(_vendTable.RecId);

        if(!vendTableChangeProposal)
        {
            //Need to have one record created with vendor recId or else it will throw the error during approval.
            vendTableChangeProposal.Name        = _vendTable.name();

            vendTableChangeProposal.VendTable   = _vendTable.RecId;
            vendTableChangeProposal.insert();
        }       
    }
}

Step 7 : Create new menu item button on form and set below property
Menu item type - Action
object = DemoCallVendorDisbursementWFHelper



Note - By above button we can only submit the workflow rest other workflow operation can be handled by standard workflow button i.e. Approve, delegate, workflow history.

That's it!!!, Please implement this and let me know if you face any issues.
Please add comment and like if you like this blog.

Next Blog - How to add custom field in Vendor amendment workflow. 

No comments:

Post a Comment

How to Post Partial Product Receipt in D365FO Using X++ Code

How to Post Partial Product Receipt in D365FO Using X++ Code How to Post Partial Product Receipt in D365FO Using X++...