1

I have an @future class, SubmitOnApproval which is called when an opportunity is approved. This class is below:

public without sharing class SubmitOnApproval {

@future 
public static void oppRecordsToSubmit(id oppId){        
        Opportunity o = [select id, recordtype.DeveloperName from Opportunity where id = : oppId];
        if(o.recordtype.DeveloperName!='PIP_Finished_Product'){
            List<GT_Quote__c> oppQuote = new List<GT_Quote__c>();
            oppQuote = [Select id, opportunity__c, Submit_Request_Picklist__c, Product__c
                          from GT_Quote__c
                          where opportunity__c = :oppId 
                          and Submit_Request_Picklist__c = 'Draft'
                          and Product__c != ''
                          and Quote_Stage__c = 'Request Pending'];

            if(oppQuote.size()>0){            
                for(GT_Quote__c quote : oppQuote){
                    quote.Submit_Request_Picklist__c = 'Submit';
                }   
                database.update(oppQuote, True);
            }
        }
        else{
            List<Opportunity_Application__c> oppAppsToSubmit = new List<Opportunity_Application__c>();

            oppAppsToSubmit = [select id, Submit_Request__c 
                               from Opportunity_Application__c
                               where Submit_Request__c = 'Draft' 
                               and Opportunity__c = :oppId];

            if(oppAppsToSubmit.size()>0){
                for(Opportunity_Application__c oa : oppAppsToSubmit){
                    oa.Submit_Request__c = 'Submit';
                }
                database.update(oppAppsToSubmit, True);
            }
        }                               

}


@future 
public static void oppRecordsToCancel(id oppId){
        Opportunity ocancel = [select id, StageName, recordtype.DeveloperName from Opportunity where id = : oppId];
        system.debug('rtrtrt'+ ocancel.recordtype.DeveloperName);           

            List<GT_Quote__c> cancelledQuotes = new List<GT_Quote__c>();  

            cancelledQuotes = [Select id, opportunity__c, Submit_Request_Picklist__c
                                from GT_Quote__c
                                where opportunity__c = :oppId and Submit_Request_Picklist__c = 'Draft'];


            for(GT_Quote__c quote : cancelledQuotes){
                quote.Quote_Stage__c = 'Request Cancelled';
            }   
            if(cancelledQuotes.size()>0){             
                database.update(cancelledQuotes, True);

}

I am trying to use an @future class, QuoteRestCallouts, to generate some XML and then make POST call to an external webservice (Vendavo). That class is below:

public class QuoteRestCallouts{

    @future (callout=true)
    public static void makePostCallout(List<Id> quoteRecords) {
        String body = ''; //data to send to external service
        String xmlstring = '';

        String xmlns = 'http://schemas.xmlsoap.org/soap/envelope/';
        String soapNS = 'http://schemas.xmlsoap.org/soap/envelope/';
        String tns = 'http://www.vendavo.com/ws/types';
        String xsd = 'http://www.w3.org/2001/XMLSchema';
        String xsi = 'http://www.w3.org/2001/XMLSchema-instance';

        for (Id quoteId : quoteRecords) {       
            GT_Quote__c q = [SELECT Id, 
                             Name
                             //MORE FIELDS HERE
                             FROM GT_Quote__c WHERE id=:quoteId];

            //GENERATE SOME XML HERE

            HttpRequest req = new HttpRequest();
            req.setTimeout(120000); 
            req.setEndpoint('callout:Vendavo_Integration');
            req.setMethod('POST');

            req.setHeader('content-type', 'application/text');        
            req.setBodyDocument(doc);
            Http http = new Http();
            HttpResponse res;

            try {
                res = http.send(req);

                if (res.getStatusCode() < 200 || res.getStatusCode() > 300) {
                    displayResponseAndSendErrorEmail();

                } else {
                    displayResponseAndSendErrorEmail();
                }
            }
            catch (System.CalloutException e) {
                displayResponseAndSendErrorEmail();
            } 
        }
    }

My QuoteAfterUpdate trigger generates the quoteRecords list used in QuoteRestCallouts. The problem is that SubmitOnApproval triggers QuoteAfterUpdate which tries to call QuoteRestCallouts and I run into the problem of calling 2 @future methods in the same transaction.

Can I use queueable apex in some way? I have looked for some examples but I can't figure out how to pass a parameter i.e. quoteRecords to the execute method. I want the below ideally:

public void execute(QueueableContext context, List<Id> quoteRecords) {
    doSomething();
}

Also we are using a custom quote object as SFDC didn't have the standard object when ours was implemented.

Thanks for any help

1
  • N.B. if(oppQuote.size()>0) and if(oppAppsToSubmit.size()>0){ and if(cancelledQuotes.size()>0){ are all superfluous; no DML is burned on empty lists
    – cropredy
    Dec 11, 2019 at 21:08

1 Answer 1

2

https://trailhead.salesforce.com/en/content/learn/modules/asynchronous_apex/async_apex_queueable

The trailhead really does go over this well in terms of understanding utilizing parameters in future and Queueable.

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.