The Ad Hoc Approval feature allows an approver to add a new approval step in an active approval process. For example, if, while approving a request, the Deal Desk concludes that a quote will require additional approvals from Legal and the CFO, creates those approval steps for a quote, decides the sequence for approval, and creates a new approval step. You can create and modify an ad hoc approval process in runtime. 

API flow for an ad hoc approval runtime process:

This sample code shows how you can use the following 7 APIs to create, read, update, and retrieve ad hoc approval runtime process info and be able to add comments and attachments to it.

/**
 *  Apttus Approvals Management
 *  ApprovalsWebServiceTestSample
 *   
 *  @2019 Apttus Inc. All rights reserved.
 */
public with sharing class AdhocApprovalsWebServiceTestSample {
    
    /**
     * Class Constructor
     */
    public AdhocApprovalsWebServiceTestSample() {

    }
    
    // test webservice API calls by running as anonymous apex from developer console
    //AdhocApprovalsWebServiceTestSample.TestCreateRuntimeAdhocApprovalProcess('Apttus__APTS_Agreement__c','a07q000000EZfki');
    //AdhocApprovalsWebServiceTestSample.TestUpdateRuntimeAdhocApprovalProcess('Apttus__APTS_Agreement__c','a07q000000EZfki');
    //AdhocApprovalsWebServiceTestSample.TestGetRuntimeAdhocApprovalProcess('Apttus__APTS_Agreement__c','a07q000000EZfki');
    //AdhocApprovalsWebServiceTestSample.TestAddCommentToRuntimeAdhocApprovalProcess('Apttus__APTS_Agreement__c','a07q000000EZfki');
    //AdhocApprovalsWebServiceTestSample.TestAddAttachmentsToRuntimeAdhocApprovalProcess('Apttus__APTS_Agreement__c','a07q000000EZfki');
    //AdhocApprovalsWebServiceTestSample.TestDeleteAttachmentsFromRuntimeAdhocApprovalProcess('Apttus__APTS_Agreement__c','a07q000000EZfki');
    //AdhocApprovalsWebServiceTestSample.TestDeleteRuntimeAdhocApprovalProcess('Apttus__APTS_Agreement__c','a07q000000EZfki');

    /**
     * Create a runtime ad hoc approval process
     * @param sObjectType the approval context sobject type 
     * @param sObjectId the approval context sobject identifier
     * @return the runtime adhoc approval process structure for the created process
     */
    public static void TestCreateRuntimeAdhocApprovalProcess(String sObjectType, ID sObjectId) {

        // create insert structure
        Apttus_Approval.AdhocApprovalProcessDTO adhocProcessDTO = new Apttus_Approval.AdhocApprovalProcessDTO();
        
        // get users to add as approvers
        List<User> users = [SELECT Id,Name
                            FROM User 
                            WHERE UserType != 'AutomatedProcess' 
                            LIMIT 2];
        User userSO1 = users[0];
        User userSO2 = users[1];
        
        // add process
        Apttus_Approval__AdhocApprovalProcess__c adhocProcessSO = new Apttus_Approval__AdhocApprovalProcess__c(
            Id = null,
            Apttus_Approval__AttachmentIds__c = null,
            Apttus_Approval__BusinessObjectId__c = sObjectId,
            Apttus_Approval__BusinessObjectType__c = sObjectType,
            Apttus_Approval__DisplayFields__c = null,
            Apttus_Approval__DisplayHeaderFields__c = null,
            Apttus_Approval__ProcessComments__c = null
        );
        adhocProcessDTO.setAdhocApprovalProcessSO(adhocProcessSO);
        // create group 1
        Apttus_Approval__AdhocApprovalGroup__c adhocGroupSO1 = new Apttus_Approval__AdhocApprovalGroup__c(
            Apttus_Approval__AdhocApprovalProcessId__c = null,
            Apttus_Approval__DependsOn__c = null,
            Apttus_Approval__GroupName__c = 'Group 1',
            Apttus_Approval__GroupSequence__c = 1
        );
        // add group 1 to process
        Apttus_Approval.AdhocApprovalProcessDTO.AdhocApprovalGroupDTO adhocGroupDTO1 = new Apttus_Approval.AdhocApprovalProcessDTO.AdhocApprovalGroupDTO(adhocGroupSO1);
        adhocProcessDTO.addAdhocApprovalGroup(adhocGroupDTO1);
        // create group 1 approver 1
        Apttus_Approval__AdhocApprover__c adhocApproverSO1 = new Apttus_Approval__AdhocApprover__c(
            Apttus_Approval__AdhocApprovalGroupId__c = null,
            Apttus_Approval__ApproverSequence__c = 1,
            Apttus_Approval__DependsOn__c = null,
            Apttus_Approval__AssigneeId__c = userSO1.Id,
            Apttus_Approval__AssigneeType__c = 'User',
            Apttus_Approval__AssigneeValue__c = userSO1.Name,
            Apttus_Approval__AutoReapprovalEnabled__c = true,      
            Apttus_Approval__IsReviewer__c = false       
        );
        // add group 1 approver 1
        Apttus_Approval.AdhocApprovalProcessDTO.AdhocApproverDTO adhocApproverDTO1 = new Apttus_Approval.AdhocApprovalProcessDTO.AdhocApproverDTO(adhocApproverSO1);
        adhocGroupDTO1.addAdhocApprover(adhocApproverDTO1);
        // create group 1 approver 2
        Apttus_Approval__AdhocApprover__c adhocApproverSO2 = new Apttus_Approval__AdhocApprover__c(
            Apttus_Approval__AdhocApprovalGroupId__c = null,
            Apttus_Approval__ApproverSequence__c = 2,
            Apttus_Approval__DependsOn__c = null,
            Apttus_Approval__AssigneeId__c = userSO2.Id,
            Apttus_Approval__AssigneeType__c = 'User',
            Apttus_Approval__AssigneeValue__c = userSO2.Name,
            Apttus_Approval__AutoReapprovalEnabled__c = true,      
            Apttus_Approval__IsReviewer__c = false       
        );
        // add group 1 approver 2
        Apttus_Approval.AdhocApprovalProcessDTO.AdhocApproverDTO adhocApproverDTO2 = new Apttus_Approval.AdhocApprovalProcessDTO.AdhocApproverDTO(adhocApproverSO2);
        adhocGroupDTO1.addAdhocApprover(adhocApproverDTO2);
        // create group 2
        Apttus_Approval__AdhocApprovalGroup__c adhocGroupSO2 = new Apttus_Approval__AdhocApprovalGroup__c(
            Apttus_Approval__AdhocApprovalProcessId__c = null,
            Apttus_Approval__DependsOn__c = null,
            Apttus_Approval__GroupName__c = 'Group 2',
            Apttus_Approval__GroupSequence__c = 2
        );
        // add group 2 to process
        Apttus_Approval.AdhocApprovalProcessDTO.AdhocApprovalGroupDTO adhocGroupDTO2 = new Apttus_Approval.AdhocApprovalProcessDTO.AdhocApprovalGroupDTO(adhocGroupSO2);
        adhocProcessDTO.addAdhocApprovalGroup(adhocGroupDTO2);
        // create group 2 approver 1
        adhocApproverSO1 = new Apttus_Approval__AdhocApprover__c(
            Apttus_Approval__AdhocApprovalGroupId__c = null,
            Apttus_Approval__ApproverSequence__c = 1,
            Apttus_Approval__DependsOn__c = null,
            Apttus_Approval__AssigneeId__c = userSO1.Id,
            Apttus_Approval__AssigneeType__c = 'User',
            Apttus_Approval__AssigneeValue__c = userSO1.Name,
            Apttus_Approval__AutoReapprovalEnabled__c = true,      
            Apttus_Approval__IsReviewer__c = false       
        );
        // add group 2 approver 1
        adhocApproverDTO1 = new Apttus_Approval.AdhocApprovalProcessDTO.AdhocApproverDTO(adhocApproverSO1);
        adhocGroupDTO2.addAdhocApprover(adhocApproverDTO1);
        // create group 2 approver 2
        adhocApproverSO2 = new Apttus_Approval__AdhocApprover__c(
            Apttus_Approval__AdhocApprovalGroupId__c = null,
            Apttus_Approval__ApproverSequence__c = 2,
            Apttus_Approval__DependsOn__c = null,
            Apttus_Approval__AssigneeId__c = userSO2.Id,
            Apttus_Approval__AssigneeType__c = 'User',
            Apttus_Approval__AssigneeValue__c = userSO2.Name,
            Apttus_Approval__AutoReapprovalEnabled__c = true,      
            Apttus_Approval__IsReviewer__c = false       
        );
        // add group 2 approver 2
         adhocApproverDTO2 = new Apttus_Approval.AdhocApprovalProcessDTO.AdhocApproverDTO(adhocApproverSO2);
        adhocGroupDTO2.addAdhocApprover(adhocApproverDTO2);

        // call API to create process
        Apttus_Approval.AdhocApprovalProcessDTO adhocProcessDTOResult = Apttus_Approval.ApprovalsWebService.CreateRuntimeAdhocApprovalProcess(adhocProcessDTO);
        system.debug('adhocProcessDTOResult='+adhocProcessDTOResult);
        
    }

    /**
     * Update a runtime adhoc approval process
     * @param sObjectType the approval context sobject type 
     * @param sObjectId the approval context sobject identifier
     * @return the runtime adhoc approval process structure for the edited process
     */
    public static void TestUpdateRuntimeAdhocApprovalProcess(String sObjectType, ID sObjectId) {

        // create update structures
        Apttus_Approval.AdhocApprovalProcessDTO adhocProcessDTO = new Apttus_Approval.AdhocApprovalProcessDTO();
        Apttus_Approval.AdhocApprovalProcessDTO.AdhocApprovalGroupDTO adhocGroupDTO = null;
        Apttus_Approval.AdhocApprovalProcessDTO.AdhocApproverDTO adhocApproverDTO = null;
        
        // get users to add as approvers
        List<User> users = [SELECT Id,Name
                            FROM User 
                            WHERE UserType != 'AutomatedProcess' 
                            LIMIT 5];
        User userSO1 = users[0];
        User userSO2 = users[1];
        User userSO3 = users[2];
        User userSO4 = users[3];
        User userSO5 = users[4];
        
        // get process
        Apttus_Approval__AdhocApprovalProcess__c processSO = [SELECT Id,Name,
                                                Apttus_Approval__BusinessObjectType__c,
                                                Apttus_Approval__BusinessObjectId__c
                                             FROM Apttus_Approval__AdhocApprovalProcess__c
                                             WHERE Apttus_Approval__BusinessObjectType__c = :sObjectType AND
                                                   Apttus_Approval__BusinessObjectId__c = :sObjectId 
                                             LIMIT 1];
        system.assert(processSO != null);

        // update process
        Apttus_Approval__AdhocApprovalProcess__c adhocProcessSO = new Apttus_Approval__AdhocApprovalProcess__c(
            Id = processSO.Id,
            Apttus_Approval__AttachmentIds__c = null,
            Apttus_Approval__BusinessObjectId__c = processSO.Apttus_Approval__BusinessObjectId__c,
            Apttus_Approval__BusinessObjectType__c = processSO.Apttus_Approval__BusinessObjectType__c,
            Apttus_Approval__DisplayFields__c = null,
            Apttus_Approval__DisplayHeaderFields__c = 'Apttus__Total_Contract_Value__c',
            Apttus_Approval__ProcessComments__c = 'new comment added'
        );
        adhocProcessDTO.setAdhocApprovalProcessSO(adhocProcessSO);
        
        // get groups and approvers
        List<Apttus_Approval__AdhocApprovalGroup__c> groups = [SELECT Id,
                                                     Name,
                                                     Apttus_Approval__AdhocApprovalProcessId__c,
                                                     Apttus_Approval__AdhocApprovalProcessId__r.Apttus_Approval__BusinessObjectId__c,
                                                     Apttus_Approval__GroupName__c,
                                                     Apttus_Approval__GroupSequence__c,
                                                     Apttus_Approval__DependsOn__c,
                                                     (SELECT Id,
                                                             Name,
                                                             Apttus_Approval__AdhocApprovalGroupId__c,
                                                             Apttus_Approval__ApproverSequence__c,
                                                             Apttus_Approval__DependsOn__c,
                                                             Apttus_Approval__AssigneeId__c,
                                                             Apttus_Approval__AssigneeType__c,
                                                             Apttus_Approval__AssigneeValue__c,
                                                             Apttus_Approval__AutoReapprovalEnabled__c,
                                                             Apttus_Approval__IsReviewer__c,
                                                             Apttus_Approval__SendEmail__c
                                                      FROM Apttus_Approval__AdhocApprovers__r
                                                      ORDER BY Apttus_Approval__ApproverSequence__c)
                                              FROM Apttus_Approval__AdhocApprovalGroup__c
                                              WHERE Apttus_Approval__AdhocApprovalProcessId__c = :processSO.Id 
                                              ORDER BY Apttus_Approval__GroupSequence__c 
                                              LIMIT 100];
        
        // iterate over groups to update
        for (Apttus_Approval__AdhocApprovalGroup__c groupSO : groups) {
            Apttus_Approval__AdhocApprovalGroup__c adhocGroupSO = null;
            if (groupSO.Apttus_Approval__GroupSequence__c == 1) {
                // create group 1
                adhocGroupSO = new Apttus_Approval__AdhocApprovalGroup__c(
                    Id = groupSO.Id,
                    Apttus_Approval__AdhocApprovalProcessId__c = processSO.Id,
                    Apttus_Approval__DependsOn__c = null,
                    Apttus_Approval__GroupName__c = 'Group 1 - Edited',
                    Apttus_Approval__GroupSequence__c = 1
                );
                // update group 1
                adhocGroupDTO = new Apttus_Approval.AdhocApprovalProcessDTO.AdhocApprovalGroupDTO(adhocGroupSO);
                adhocProcessDTO.addAdhocApprovalGroup(adhocGroupDTO);
                
                // iterate over approvers to update
                for (Apttus_Approval__AdhocApprover__c approverSO : groupSO.Apttus_Approval__AdhocApprovers__r) {
                    Apttus_Approval__AdhocApprover__c adhocApproverSO = null;
                    if (approverSO.Apttus_Approval__ApproverSequence__c == 1) {
                        // create group 1 approver 1
                        adhocApproverSO = new Apttus_Approval__AdhocApprover__c(
                            Id = approverSO.Id,
                            Apttus_Approval__AdhocApprovalGroupId__c = groupSO.Id,
                            Apttus_Approval__ApproverSequence__c = 1,
                            Apttus_Approval__DependsOn__c = null,
                            Apttus_Approval__AssigneeId__c = userSO1.Id,
                            Apttus_Approval__AssigneeType__c = 'User',
                            Apttus_Approval__AssigneeValue__c = userSO1.Name,
                            Apttus_Approval__AutoReapprovalEnabled__c = true,      
                            Apttus_Approval__IsReviewer__c = false       
                        );
                        
                    } else if (approverSO.Apttus_Approval__ApproverSequence__c == 2) {
                        // create group 1 approver 2
                        adhocApproverSO = new Apttus_Approval__AdhocApprover__c(
                            Id = approverSO.Id,
                            Apttus_Approval__AdhocApprovalGroupId__c = groupSO.Id,
                            Apttus_Approval__ApproverSequence__c = 2,
                            Apttus_Approval__DependsOn__c = '1',
                            Apttus_Approval__AssigneeId__c = userSO2.Id,
                            Apttus_Approval__AssigneeType__c = 'User',
                            Apttus_Approval__AssigneeValue__c = userSO2.Name,
                            Apttus_Approval__AutoReapprovalEnabled__c = true,      
                            Apttus_Approval__IsReviewer__c = false       
                        );
                        
                    }
                    
                    // update approver
                    adhocApproverDTO = new Apttus_Approval.AdhocApprovalProcessDTO.AdhocApproverDTO(adhocApproverSO);
                    adhocGroupDTO.addAdhocApprover(adhocApproverDTO);
                    
                }
                
            } else if (groupSO.Apttus_Approval__GroupSequence__c == 2) {
                // create group 2
                adhocGroupSO = new Apttus_Approval__AdhocApprovalGroup__c(
                    Id = groupSO.Id,
                    Apttus_Approval__AdhocApprovalProcessId__c = processSO.Id,
                    Apttus_Approval__DependsOn__c = null,
                    Apttus_Approval__GroupName__c = 'Group 2 - Edited',
                    Apttus_Approval__GroupSequence__c = 2
                );
                // update group 2
                adhocGroupDTO = new Apttus_Approval.AdhocApprovalProcessDTO.AdhocApprovalGroupDTO(adhocGroupSO);
                adhocProcessDTO.addAdhocApprovalGroup(adhocGroupDTO);
                
                // iterate over approvers to update
                for (Apttus_Approval__AdhocApprover__c approverSO : groupSO.Apttus_Approval__AdhocApprovers__r) {
                    Apttus_Approval__AdhocApprover__c adhocApproverSO = null;
                    if (approverSO.Apttus_Approval__ApproverSequence__c == 1) {
                        // create group 2 approver 1
                        adhocApproverSO = new Apttus_Approval__AdhocApprover__c(
                            Id = approverSO.Id,
                            Apttus_Approval__AdhocApprovalGroupId__c = groupSO.Id,
                            Apttus_Approval__ApproverSequence__c = 1,
                            Apttus_Approval__DependsOn__c = null,
                            Apttus_Approval__AssigneeId__c = userSO3.Id,
                            Apttus_Approval__AssigneeType__c = 'User',
                            Apttus_Approval__AssigneeValue__c = userSO3.Name,
                            Apttus_Approval__AutoReapprovalEnabled__c = true,      
                            Apttus_Approval__IsReviewer__c = false       
                        );
                        
                    } else if (approverSO.Apttus_Approval__ApproverSequence__c == 2) {
                        // create group 2 approver 2
                        adhocApproverSO = new Apttus_Approval__AdhocApprover__c(
                            Id = approverSO.Id,
                            Apttus_Approval__AdhocApprovalGroupId__c = groupSO.Id,
                            Apttus_Approval__ApproverSequence__c = 2,
                            Apttus_Approval__DependsOn__c = '1',
                            Apttus_Approval__AssigneeId__c = userSO4.Id,
                            Apttus_Approval__AssigneeType__c = 'User',
                            Apttus_Approval__AssigneeValue__c = userSO4.Name,
                            Apttus_Approval__AutoReapprovalEnabled__c = true,      
                            Apttus_Approval__IsReviewer__c = false       
                        );
                        
                    }
                    
                    // update approver
                    adhocApproverDTO = new Apttus_Approval.AdhocApprovalProcessDTO.AdhocApproverDTO(adhocApproverSO);
                    adhocGroupDTO.addAdhocApprover(adhocApproverDTO);
                    
                }
                
                // create group 2 approver 3
                Apttus_Approval__AdhocApprover__c adhocApproverSO = new Apttus_Approval__AdhocApprover__c(
                    Id = null,
                    Apttus_Approval__AdhocApprovalGroupId__c = groupSO.Id,
                    Apttus_Approval__ApproverSequence__c = 3,
                    Apttus_Approval__DependsOn__c = '2',
                    Apttus_Approval__AssigneeId__c = userSO5.Id,
                    Apttus_Approval__AssigneeType__c = 'User',
                    Apttus_Approval__AssigneeValue__c = userSO5.Name,
                    Apttus_Approval__AutoReapprovalEnabled__c = true,      
                    Apttus_Approval__IsReviewer__c = false       
                );
                // update group 2 approver 3
                adhocApproverDTO = new Apttus_Approval.AdhocApprovalProcessDTO.AdhocApproverDTO(adhocApproverSO);
                adhocGroupDTO.addAdhocApprover(adhocApproverDTO);
                
            }
            
        }

        // print input structure
        PrintAdhocApprovalProcess(adhocProcessDTO);

        // call API to update process
        Apttus_Approval.AdhocApprovalProcessDTO adhocProcessDTOResult = Apttus_Approval.ApprovalsWebService.UpdateRuntimeAdhocApprovalProcess(adhocProcessDTO);
        
        // print output structure
        PrintAdhocApprovalProcess(adhocProcessDTOResult);
        
    }

    /**
     * Retrieve a runtime adhoc approval process
     * @param sObjectType the approval context sobject type 
     * @param sObjectId the approval context sobject identifier
     * @return the runtime adhoc approval process structure
     */
    public static void TestGetRuntimeAdhocApprovalProcess(String sObjectType, ID sObjectId) {
        
        // call API to get process
        Apttus_Approval.AdhocApprovalProcessDTO adhocProcessDTOResult = Apttus_Approval.ApprovalsWebService.GetRuntimeAdhocApprovalProcess(sObjectType, sObjectId);
        
        // print output structure
        PrintAdhocApprovalProcess(adhocProcessDTOResult);
        
    }

    /**
     * Delete a runtime adhoc approval process
     * @param sObjectType the approval context sobject type 
     * @param sObjectId the approval context sobject identifier
     * @return <code>true</code> if the process is deleted, <code>false</code> otherwise 
     */
    public static void TestDeleteRuntimeAdhocApprovalProcess(String sObjectType, ID sObjectId) {
        
        // call API to delete process
        Boolean ok = Apttus_Approval.ApprovalsWebService.DeleteRuntimeAdhocApprovalProcess(sObjectType, sObjectId);
        system.assertEquals(ok, true);
        
    }

    /**
     * Add comment to a runtime adhoc approval process
     * @param sObjectType the approval context sobject type 
     * @param sObjectId the approval context sobject identifier
     * @return <code>true</code> if the comment was added, <code>false</code> otherwise 
     */
    public static void TestAddCommentToRuntimeAdhocApprovalProcess(String sObjectType, ID sObjectId) {
        
        // call API to add comment
        Boolean ok = Apttus_Approval.ApprovalsWebService.AddCommentToRuntimeAdhocApprovalProcess(sObjectType, sObjectId, 'MY NEW comment');
        system.assertEquals(ok, true);

        // call API to get process
        Apttus_Approval.AdhocApprovalProcessDTO adhocProcessDTOResult = Apttus_Approval.ApprovalsWebService.GetRuntimeAdhocApprovalProcess(sObjectType, sObjectId);
        // get comment from process
        Apttus_Approval__AdhocApprovalProcess__c adhocProcessSO = adhocProcessDTOResult.getAdhocApprovalProcessSO();
        String comment = adhocProcessSO.Apttus_Approval__ProcessComments__c;
        system.assertEquals(comment, 'MY NEW comment');
        
    }

    /**
     * Add attachments to a runtime adhoc approval process
     * @param sObjectType the approval context sobject type 
     * @param sObjectId the approval context sobject identifier
     * @return <code>true</code> if the attachments were added, <code>false</code> otherwise 
     */
    public static void TestAddAttachmentsToRuntimeAdhocApprovalProcess(String sObjectType, ID sObjectId) {
        
        // create list of attachments to add
        List<ID> attachmentIds = new List<ID>{sObjectId, sObjectId};
        // call API to add attachments
        Boolean ok = Apttus_Approval.ApprovalsWebService.AddAttachmentsToRuntimeAdhocApprovalProcess(sObjectType, sObjectId, attachmentIds);
        system.assertEquals(ok, true);
        
        // call API to get process
        Apttus_Approval.AdhocApprovalProcessDTO adhocProcessDTOResult = Apttus_Approval.ApprovalsWebService.GetRuntimeAdhocApprovalProcess(sObjectType, sObjectId);
        // get attachments from process
        Apttus_Approval__AdhocApprovalProcess__c adhocProcessSO = adhocProcessDTOResult.getAdhocApprovalProcessSO();
        String attachmentIdsStr = adhocProcessSO.Apttus_Approval__AttachmentIds__c;
        String attachmentIdsStrExpected = sObjectId + ',' + sObjectId;
        system.assertEquals(attachmentIdsStr, attachmentIdsStrExpected);

    }

    /**
     * Delete attachments from a runtime adhoc approval process
     * @param sObjectType the approval context sobject type 
     * @param sObjectId the approval context sobject identifier
     * @return <code>true</code> if the attachments were removed, <code>false</code> otherwise 
     */
    public static void TestDeleteAttachmentsFromRuntimeAdhocApprovalProcess(String sObjectType, ID sObjectId) {
        
        // create list of attachments to delete
        List<ID> attachmentIds = new List<ID>{sObjectId};
        // call API to delete attachments
        Boolean ok = Apttus_Approval.ApprovalsWebService.DeleteAttachmentsFromRuntimeAdhocApprovalProcess(sObjectType, sObjectId, attachmentIds);
        system.assertEquals(ok, true);
        
        // call API to get process
        Apttus_Approval.AdhocApprovalProcessDTO adhocProcessDTOResult = Apttus_Approval.ApprovalsWebService.GetRuntimeAdhocApprovalProcess(sObjectType, sObjectId);
        // get attachments from process
        Apttus_Approval__AdhocApprovalProcess__c adhocProcessSO = adhocProcessDTOResult.getAdhocApprovalProcessSO();
        String attachmentIdsStr = adhocProcessSO.Apttus_Approval__AttachmentIds__c;
        system.assertEquals(attachmentIdsStr, sObjectId);

    }

    /**
     * Prints an adhoc process definition
     * @param approvalProcessDTO the adhoc approval process definition
     */
    public static void PrintAdhocApprovalProcess(Apttus_Approval.AdhocApprovalProcessDTO approvalProcessDTO) {
        
        // print process info
        Apttus_Approval__AdhocApprovalProcess__c processSO = approvalProcessDTO.getAdhocApprovalProcessSO();
        system.debug('processSO='+processSO);
        
        // print approval groups and approvers
        for (Apttus_Approval.AdhocApprovalProcessDTO.AdhocApprovalGroupDTO groupDTO : approvalProcessDTO.getAdhocApprovalGroups()) {
            Apttus_Approval__AdhocApprovalGroup__c groupSO = groupDTO.getAdhocApprovalGroupSO();
            system.debug('groupSO='+groupSO);
            
            // get approvers
            for (Apttus_Approval.AdhocApprovalProcessDTO.AdhocApproverDTO approverDTO : groupDTO.getAdhocApprovers()) {
                Apttus_Approval__AdhocApprover__c approverSO = approverDTO.getAdhocApproverSO();
                system.debug('approverSO='+approverSO);
                
            }
            
        }
        
    }

}
CODE