function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
symantecAPsymantecAP 

Change in child should should change parent in batch

Hi All

 

I am trying to write a class where change in child object field will change a field on Parent Object .

I will have to then schedule the same.

 

I am not sure if my logic is right. I am first querying all the Child records. and putting if statement in my database.execute to check for the field change.

Child object : BigMachines__Quote__c looks up to Opportunity

if  BigMachines__Quote__c.status__c = *unison* then Opportunity.stagename = closed won.

I have written following so far. Kindly help .

global class updateOpportunityStage implements Database.Batchable<sObject>,Schedulable{
global string query = 'SELECT id,BigMachines__Status__c from BigMachines__Quote__c ';



global database.querylocator start(Database.BatchableContext BC){


     //List<BigMachines__Quote__c> quoteList= new List<BigMachines__Quote__c>();
//BigMachines__Quote__c bmq = [Select id,BigMachines__Status__c from BigMachines__Quote__c where BigMachines__Status__c = '*unison*'];
    return Database.getQueryLocator(query);    
}
    global void execute(SchedulableContext SC){
        updateOpportunityStage stg = new updateOpportunityStage();
        database.executebatch(stg);
        
    }

global void execute(Database.BatchableContext BC, List<sObject> scope){

     
                List <Opportunity> oppList = new List<Opportunity>() ;
        for(sObject s : scope){
        
        BigMachines__Quote__c quote = (BigMachines__Quote__c)s;
        System.debug('Adil'+quote);
        
        for (List< BigMachines__Quote__c> bmq :[SELECT id,BigMachines__Status__c from BigMachines__Quote__c ]){
        
         if(quote.BigMachines__Status__c.contains ('unison') &&  quote.BigMachines__Is_Primary__c == true ){

        Opportunity opp = [select id, StageName from Opportunity where id=:quote.id];
         opp.stageName = 'Closed Won' ;
        
    }
    update oppList;
    }
    
    }
    }
  global void finish(Database.BatchableContext BC){}  

}

 Thanks in Advance

Best Answer chosen by Admin (Salesforce Developers) 
yvk431yvk431
global void execute(Database.BatchableContext BC, List<sObject> scope){
Set<id> liOppIds = new Set<id>();
//List <Opportunity> oppList = new List<Opportunity>() ;
for(sObject s : scope){

BigMachines__Quote__c quote = (BigMachines__Quote__c)s;
// System.debug('Adil'+quote);
if(quote.BigMachines__Status__c == 'unison' && quote.BigMachines__Is_Primary__c == true)
liOppIds.add(quote.BigMachines__Opportunity__c);

}


//query all the opportunities in a single query
List<Opportunity> opp = new List<Opportunity>();
opp = [select id, StageName from Opportunity where id in :liOppIds and stagename != 'Closed Won'];
for ( Opportunity opps : opp)
{
opps.StageName = 'Closed Won' ; 
}
//update all opportunities in a single DML
if(opp.size() > 0)
update opp;
 
} 

 Try this

 

 

--yvk


All Answers

yvk431yvk431

How are you determining the change. I mean what if the parent is modified instead of child then you still need to update the parent with the child.  If the parent have different childs and different values how we know which is modified?

symantecAPsymantecAP

Thank yoy for the reply

usually only one child record goes in to status called unison. so if any 1 of the child records is unison then that updates opportunity.stagename field.

And if the parent gets edited then there is no change either to parent or child records.

Hope i am clear this time.

yvk431yvk431

What is the need of the batch, why not trigger on child.

 

using trigger you can retirive only those parents which needs to be modified. 

 

 

--yvk

symantecAPsymantecAP

yes right but the child object is a managed package Big_Machine_Quote__c and we dont want to use a trigger and we want to schedule it in a such a way that it runs every 15 mins and check the logic and update field on Opportunity .

 

Thanks

Adil

symantecAPsymantecAP

Hi

 

Here is my modified code

global class updateOpportunityStage implements Database.Batchable<sObject>,Schedulable{
global string query ;

global updateOpportunityStage(){

Query = 'Select Name,Id from BigMachines__Quote__c' ;

}

global database.querylocator start(Database.BatchableContext BC){
return Database.getQueryLocator(query);    
}
    global void execute(SchedulableContext SC){
        updateOpportunityStage stg = new updateOpportunityStage();
        database.executebatch(stg);
        
    }

global void execute(Database.BatchableContext BC, List<sObject> scope){

     
          //      List <Opportunity> oppList = new List<Opportunity>() ;
        for(sObject s : scope){
        
        BigMachines__Quote__c quote = (BigMachines__Quote__c)s;
       // System.debug('Adil'+quote);
       
       List<id> liOppIds;
       
       for (BigMachines__Quote__c bmq :[ SELECT id,BigMachines__Status__c from BigMachines__Quote__c where BigMachines__Status__c = '*unison*' and BigMachines__Is_Primary__c = true ])
{
        
//collect opportunity Ids in a list
liOppIds.add(bmq.BigMachines__Opportunity__c);
  
  
}
//query all the opportunities in a single query

List<Opportunity> opp = [select id, StageName from Opportunity where id in :liOppIds];
for ( Opportunity opps : opp)
{
  opps.StageName = 'Closed Won' ;   
}
//update all opportunities in a single DML

update opp;

       } 

    }
  global void finish(Database.BatchableContext BC){}  

}

 Now i get error in my Apex job that is

 

" First error: Attempt to de-reference a null object”

Thanks

Adil

yvk431yvk431
global void execute(Database.BatchableContext BC, List<sObject> scope){
Set<id> liOppIds = new Set<id>();
//List <Opportunity> oppList = new List<Opportunity>() ;
for(sObject s : scope){

BigMachines__Quote__c quote = (BigMachines__Quote__c)s;
// System.debug('Adil'+quote);
if(quote.BigMachines__Status__c == 'unison' && quote.BigMachines__Is_Primary__c == true)
liOppIds.add(quote.BigMachines__Opportunity__c);

}


//query all the opportunities in a single query
List<Opportunity> opp = new List<Opportunity>();
opp = [select id, StageName from Opportunity where id in :liOppIds and stagename != 'Closed Won'];
for ( Opportunity opps : opp)
{
opps.StageName = 'Closed Won' ; 
}
//update all opportunities in a single DML
if(opp.size() > 0)
update opp;
 
} 

 Try this

 

 

--yvk


This was selected as the best answer
symantecAPsymantecAP

Thanks

 

I have scheduled the code its says status as Completed but total batches are only 1 and batch processed 1. failures zero.

why is it procesing only 1 record.

 

Thanks

Adil

symantecAPsymantecAP

Can you tell my why the total batch processed is only 1 ?

yvk431yvk431

That we cannot say, it depends on the records and all. 

Try to run the query you are passing from system log or some thing and verify.

 

--yvk

symantecAPsymantecAP

Thanks for the reply.. i am checking the data as to y only one record is being processed.

Now the real concern is it doesnot update the Opportunity..

 

Thanks

Adil