+ Start a Discussion
Shahab KhanShahab Khan 

Future method cannot be called from a future or batch method

Hello,

I have a scheduled class of managed package which insert paymnets i have added trigger after insert of payment and i want to add opportunity and opportunity contact role.
This works fine in Sandbox but in live i am getting following error and due to that error my opportunities not added.

"Future method cannot be called from a future or batch method: npo02.OpportunityRollups.rollupContactsandHouseholdsForTrigger(Set<Id>)"

Here is my scheduled apex class.
 
/*** ScheduleRebillingCycle: ***/ 

public with sharing class ScheduleRebillingCycle implements Schedulable{

    List<Rebilling_Cycle__c> rebillingCycles = new List<Rebilling_Cycle__c>();
    List<List<Rebilling_Cycle__c>> cycleList = new List<List<Rebilling_Cycle__c>>(); 
    List<Rebilling_Cycle__c> cycleTest = new List<Rebilling_Cycle__c>();
    List<String> transactionIDs = new List<String>();
    Boolean isFromBatchFile = false;
    
    public ScheduleRebillingCycle(List<Rebilling_Cycle__c> cycles, Boolean isBatchFile){
        if (cycles != null)
            cycleTest = cycles;
        isFromBatchFile = isBatchFile;
    }
     public ScheduleRebillingCycle(){
    } 
    /* Executes the rebilling cycle that has been set up inside of SalesForce. If approved, create a Payment record.
    //
    */
    public void execute(SchedulableContext ctx) {
         if (cycleTest.IsEmpty()) {
            try {
              rebillingCycles = [SELECT Id, Name, Account_Name__c, Contact_Name__c, Transaction_ID__c, Account_Type__c, 
                  Routing_Number__c, Rebill_Next_Date__c,Rebill_Frequency__c, Rebill_Frequency_Number__c, Payment_Type__c, 
                  Card_Number__c, Expiration_Month__c, Expiration_Year__c, Account_Number__c, Rebill_Cycles_Remaining__c,
                  Rebill_Status__c, Rebill_Amount__c, Campaign_Name__c FROM 
                  Rebilling_Cycle__c WHERE Rebill_Next_Date__c = TODAY AND (Rebill_Cycles_Remaining__c = 'Infinite' OR  
                  Rebill_Cycles_Remaining__c != '0') AND Rebill_Status__c = 'Active'];
            } catch(Exception e){System.debug('ERROR' + e);}
      
            for(Rebilling_Cycle__c c: rebillingCycles){ 
                cycleTest.add(c);
            }
        }
              if ([SELECT count() FROM AsyncApexJob WHERE JobType='BatchApex' AND (Status = 'Processing' OR 
                  Status = 'Preparing' OR Status = 'Holding' OR Status = 'Queued')] < 5){
                  BatchRebillingCycles cycle = new BatchRebillingCycles(cycleTest, isFromBatchFile);
                  ID batchprocessid = Database.executeBatch(cycle);
              } else {
                  ScheduleRebillingCycle sch = new ScheduleRebillingCycle(cycleTest, isFromBatchFile);
                  Datetime dt = Datetime.now().addMinutes(2);
                  String timeForScheduler = dt.format('s m H d M \'?\' yyyy');
                  Id schedId = System.Schedule('BluePayRetry'+timeForScheduler,timeForScheduler,sch);   
              }
              cycleTest.clear();
              
    }   
    
}

And here is my trigger code.
 
trigger BpRCTrigger on BluePay_DNA__Payment__c (after insert)
{
	try
    {
        List < Opportunity > oppList = new List<Opportunity>();
        List < String > contact_ids = new List<String>();
        List < OpportunityContactRole > roleList = new List<OpportunityContactRole>();
        oppList.clear();
        roleList.clear();
        Opportunity opportunity = new Opportunity();
        OpportunityContactRole role = new OpportunityContactRole();
        Contact prev_contact_rec;
        Account prev_account_rec;
        Datetime cDT = System.now();
        String current_date = cDT.format('MM/d/yyyy');
        Date re_today_date = Date.today();
        
        
        for (BluePay_DNA__Payment__c bpp : trigger.new)
        {
            if(bpp.BluePay_DNA__Is_Recurring__c == 'Yes' && bpp.BluePay_DNA__Transaction_Result__c == 'APPROVED')
            {
                String contact_id = String.valueOf(bpp.BluePay_DNA__Contact_Name__c);
                String campaign_id = String.valueOf(bpp.BluePay_DNA__Campaign_Name__c);
                String rebilling_cycle_id = String.valueOf(bpp.BluePay_DNA__Rebilling_Cycle_Reference_ID__c);
                
                if(contact_id != null && contact_id != '' && campaign_id != null && campaign_id !='')
                {
                    System.debug('test: 1');
                    prev_contact_rec = null;
                    prev_account_rec = null;
                    prev_contact_rec = [select AccountId, Donation_Type__c, Other_Gift_Type__c from Contact where Id=:contact_id limit 1];
                    prev_account_rec = [select Name from Account where id=:prev_contact_rec.AccountId limit 1];
                    opportunity = null;
                    role = null;
                    opportunity = new Opportunity();
                    role = new OpportunityContactRole();
                    
                    System.debug('test: 2');
                    opportunity.accountId = prev_contact_rec.AccountId;
                    opportunity.name = prev_account_rec.Name + ' $' + bpp.BluePay_DNA__Amount__c + ' Recurring Donation ' + current_date;
                    opportunity.Donation_Type__c = prev_contact_rec.Donation_Type__c;
                    opportunity.BluePay_DNA__Donation_Type__c = (prev_contact_rec.Donation_Type__c != null) ? prev_contact_rec.Donation_Type__c : '';
                    opportunity.Other_Donation_Type__c = prev_contact_rec.Other_Gift_Type__c;
                    opportunity.Donation_Source_Type__c = 'Via Website';
                    opportunity.CampaignId = campaign_id;
                    opportunity.amount = Double.valueof(bpp.BluePay_DNA__Amount__c);
                    opportunity.CloseDate = re_today_date;
                    opportunity.stageName = 'Posted';
                    
                    if(rebilling_cycle_id != null && rebilling_cycle_id !='')
                    {
                        BluePay_DNA__Rebilling_Cycle__c reb_cycle = [select BluePay_DNA__Recurring_Donation_ID__c from BluePay_DNA__Rebilling_Cycle__c where Id=:rebilling_cycle_id limit 1];
                        if(reb_cycle.BluePay_DNA__Recurring_Donation_ID__c != null && reb_cycle.BluePay_DNA__Recurring_Donation_ID__c !='')
                        {
                            opportunity.npe03__Recurring_Donation__c = reb_cycle.BluePay_DNA__Recurring_Donation_ID__c;
                        }
                    }
                    
                    oppList.add(opportunity);
                    contact_ids.add(contact_id);
                    System.debug('test: 4');
                }
                    
            }
        }
        if (oppList != null && oppList.size() > 0)
        {
            insert(oppList);
            Integer count = 0;
            for(Opportunity opp: oppList)
            {
                role = null;
                role = new OpportunityContactRole();
                role.contactId = contact_ids[count];
                role.Role = '10';
                role.opportunityId = opp.id;
                roleList.add(role);
                count++;
            }
            insert(roleList);
        }
    }
    catch (exception ex)
    {
        System.debug('Error occurd: ' + ex);
    }
}

Can some body help me how to fix that error so that trigger works fine.

Thanks,
Faraz
Shashikant SharmaShashikant Sharma
Hi,

As the error says this issue is that in code execution for a future method calling another future execution. To resolve it you should add a condition
// call future only if current execution is not future 
if( !System.isFuture()) {
     // call future method
}

Just to know what is npo02 which is shown in the error message
npo02.OpportunityRollups.rollupContactsandHouseholdsForTrigger(Set<Id>)

if it is namespace name and it is managed package code then you should contact to product support.
Shahab KhanShahab Khan
Thanks for quick reply.

npo02 is managed package.

You mean to say i should change my code to this.
 
if(!System.IsFuture())
{

insert(oppList);
            Integer count = 0;
            for(Opportunity opp: oppList)
            {
                role = null;
                role = new OpportunityContactRole();
                role.contactId = contact_ids[count];
                role.Role = '10';
                role.opportunityId = opp.id;
                roleList.add(role);
                count++;
            }
            insert(roleList);
}

In this way opportunities and opportunity conatact roles will be added or not?

Thanks,
Shahab
Shahab KhanShahab Khan
Shashikant Sharma can you please reply to my comments?

Thanks,
Shahab
Shahab KhanShahab Khan
Please can somebody help me regarding my question?

Thanks,
Shahab