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
KR_ForceKR_Force 

Batch Class Help?

Below is skipping the if  and else if condition line 25 and 29. and updating the zero records. any help will be much appriciated?

Note::Product_Subscriptions__c is a multi pick list field
  1. global class BatchAccountProductSubscriptions implements Database.Batchable<sobject>, Database.Stateful
  2. {
  3.     public String query;
  4.     global String error;
  5.     global database.queryLocator start(Database.BatchableContext BC)
  6.     {       String query = 'select AccountId, Id, Product_Family__c FROM Asset where Product_Family__c!=null limit 200';
  7.             return database.getQueryLocator(query);
  8.     }
  9.    
  10.     global void execute(Database.BatchableContext BC, List<sObject> scope)
  11.     {
  12.         List<asset> assetList =(List<Asset>)scope; 
  13.         set<id>acIDs=new set<Id>();
  14.         Map<Id,Set<String>> actPsubs = new Map<Id,Set<String>>();
  15.         Map<id,string> accProdFamily = new Map<id,string>();
  16.         Map<id,Asset> aidAssetMap = new Map<id,Asset>();
  17.         List<Account> updateAccountList = new List<Account>();
  18.         boolean isUpdate = false;
  19.         try
  20.         {   System.Debug('assetList ****'+assetList);
  21.             for(Asset a :assetList){aidAssetMap.put(a.AccountId,a);}
  22.             list<Account> act =[select Id, Product_Subscriptions__c FROM account where id in:aidAssetMap.keyset()];
  23.             for(Account ac:act){
  24.             string prodstring ='';
  25.             if(!ac.Product_Subscriptions__c.contains(aidAssetMap.get(ac.id).Product_Family__c) && (ac.Product_Subscriptions__c<>''|| ac.Product_Subscriptions__c!=null ))
  26.            {   System.Debug('Product_Subscriptions__c Match not Found ');
  27.                 prodstring=ac.Product_Subscriptions__c+';'+aidAssetMap.get(ac.id).Product_Family__c;
  28.             }
  29.             else if(!ac.Product_Subscriptions__c.contains(aidAssetMap.get(ac.id).Product_Family__c) && (ac.Product_Subscriptions__c=='' || ac.Product_Subscriptions__c==null))
  30.             {   System.Debug('Product_Subscriptions__c Match Found ');
  31.                 prodstring=aidAssetMap.get(ac.id).Product_Family__c;
  32.             }
  33.             updateAccountList.add(new Account(Id = ac.id, Product_Subscriptions__c = prodstring));
  34.             }
  35.              System.Debug('updateAccountList ****'+updateAccountList);
  36.             if(updateAccountList.size() != 0){
  37.                Database.SaveResult[] srList = Database.update(updateAccountList, false);
  38.                         for(Database.SaveResult sr : srList)
  39.                         {
  40.                             for(Database.Error e : sr.getErrors())
  41.                             error += '\n ' + e.getMessage();
  42.                         }
  43.                     }
  44.             }
  45.         catch(Exception e)
  46.         {
  47.             error += e.getMessage();
  48.         }
  49.     }
  50.     global void finish(Database.BatchableContext BC)
  51.     {
  52.         AsyncApexJob a = [Select Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email from AsyncApexJob where Id =: BC.getJobId()];
  53.         Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
  54.         String[] toEmailAddresses = new String[] {'XXXXXXXXXXXXXXXXXXXXX'};
  55.         mail.setToAddresses(toEmailAddresses);
  56.         mail.setSubject('BatchJob Status' + a.Status);
  57.         mail.setHTMLBody
  58.         ('Total No of Batch Apex job processed ' + a.TotalJobItems +
  59.         ' batches with '+ a.NumberOfErrors + ' failures.');
  60.         Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
  61.     }
  62. }
Best Answer chosen by KR_Force
Tony TannousTony Tannous
for(Account ac:act)
{
            string prodstring ='';
            if((ac.Product_Subscriptions__c!=null && ac.Product_Subscriptions__c !=''  ))
           {  
string productSub=ac.Product_Subscriptions__c;
                 if(!productSub.contains(aidAssetMap.get(ac.id).Product_Family__c) )
                 {.  
                 System.Debug('Product_Subscriptions__c Match not Found ');
                   prodstring=productSub+';'+aidAssetMap.get(ac.id).Product_Family__c;
                 }
                else
                 {
                      prodstring=aidAssetMap.get(ac.id).Product_Family__c;
                   }

           }
            else 

            {   System.Debug('Product_Subscriptions__c Match Found ');
                prodstring=aidAssetMap.get(ac.id).Product_Family__c;
            }
            updateAccountList.add(new Account(Id = ac.id, Product_Subscriptions__c = prodstring));
 
}

I didn't paid attention to the first if statement it should be &&

Try it now.

All Answers

logontokartiklogontokartik
Few questions.
  • I am not sure why you are having a limit of 200 in query? Start's Query Locator  will take care of splitting your query into batches of 200 or more. 
  • I dont understand the Else If as well. are you looking to find nulls? You will not find any nulls in Product_Family__c as your query eliminates them
  • Also your if conditions are in reverse. Check for nulls and check for contains next.
  • After you make changes if you are still having issues, can you post debug logs... Thank you
 
KR_ForceKR_Force
I Appreciate for your reply!
limit is just for testing purpose. i dont want the batch class execute for entire table fo size 600K.
answering to you next question: Yes im checking the null on account side not on Asset field(Product_Subscriptions__c is an Account field and Product_Family__c is on Asset)
logontokartiklogontokartik
Ok. I looked thru your logic, its seems like you are trying to compare the accounts' Product_Subscriptions__c. Why dont you get them in your Start query itself?

String query = 'select AccountId, Account.Product_Subscriptions__c, Id, Product_Family__c FROM Asset where Product_Family__c!=null limit 200';


In your execute method now you can do a compare during the for loop repeat and dont really need maps. Also I am not sure if I understand your contains logic..





KR_ForceKR_Force
Requirement is to get the Product_Family__c from asset and added it to Account.Product_Subscriptions__c which is a multi pick.  
i dont want to add the duplicate values so im just checking if the value is already selected in multi pick or not.  if it is already selected for that particular record then i dont want add it.

without map how are going to set the valu from asset to  Account field? if its possiable without map then can you please share code snippet?
Tony TannousTony Tannous
Hello,

you need to use the map to put the accountid/Asset,

and this the code where you need to replace 23/34.

for(Account ac:act)
{
            string prodstring ='';
            if((ac.Product_Subscriptions__c!=null ||ac.Product_Subscriptions__c !=''  )&& !ac.Product_Subscriptions__c.contains(aidAssetMap.get(ac.id).Product_Family__c) )
           {   System.Debug('Product_Subscriptions__c Match not Found ');
                prodstring=ac.Product_Subscriptions__c+';'+aidAssetMap.get(ac.id).Product_Family__c;
           }
            else if( ( ac.Product_Subscriptions__c==null || ac.Product_Subscriptions__c=='' )  )
            {   System.Debug('Product_Subscriptions__c Match Found ');
                prodstring=aidAssetMap.get(ac.id).Product_Family__c;
            }
            updateAccountList.add(new Account(Id = ac.id, Product_Subscriptions__c = prodstring));
  }

you was checking if ac.Product_Subscriptions__c==null || ac.Product_Subscriptions__c=='' so no need to the other condition 

Try it ,it should work 

Good Luck
KR_ForceKR_Force
Thanks Tony for your reply!

Unfortunately that didnt help , its still skipping the if condition.
 the reson for checking does not contain in IF condition is to make to sure the .Product_Subscriptions__c(Multi picklist field) field does not have the same  value to avoid duplicates in pick list.

Tony TannousTony Tannous
Remove the try catch and run the batch it should generate an error, it  seems there is an error somewhere that's why it is not passing in the if statement.


KR_ForceKR_Force
Thanks Tony..That actually helped to narrow down the issue. issue is im not able to check for null values for ac.Product_Subscriptions__c==null
System.NullPointerException: Attempt to de-reference a null object at line 25.

any suggestions ?
Tony TannousTony Tannous
       try this
for(Account ac:act)
{
            string prodstring ='';
            if((ac.Product_Subscriptions__c!=null ||ac.Product_Subscriptions__c !=''  ))
           {  
               if(!ac.Product_Subscriptions__c.contains(aidAssetMap.get(ac.id).Product_Family__c) )
{.  
System.Debug('Product_Subscriptions__c Match not Found ');
                prodstring=ac.Product_Subscriptions__c+';'+aidAssetMap.get(ac.id).Product_Family__c;
}
           }
            else 

            {   System.Debug('Product_Subscriptions__c Match Found ');
                prodstring=aidAssetMap.get(ac.id).Product_Family__c;
            }
            updateAccountList.add(new Account(Id = ac.id, Product_Subscriptions__c = prodstring));
 
}

Tony TannousTony Tannous
         try this
for(Account ac:act)
{
            string prodstring ='';
            if((ac.Product_Subscriptions__c!=null ||ac.Product_Subscriptions__c !=''  ))
           {  
                 if(!ac.Product_Subscriptions__c.contains(aidAssetMap.get(ac.id).Product_Family__c) )
                 {.  
                 System.Debug('Product_Subscriptions__c Match not Found ');
                   prodstring=ac.Product_Subscriptions__c+';'+aidAssetMap.get(ac.id).Product_Family__c;
                 }
                else
                 {
                      prodstring=aidAssetMap.get(ac.id).Product_Family__c;
                   }

           }
            else 

            {   System.Debug('Product_Subscriptions__c Match Found ');
                prodstring=aidAssetMap.get(ac.id).Product_Family__c;
            }
            updateAccountList.add(new Account(Id = ac.id, Product_Subscriptions__c = prodstring));
 
}

it should work

KR_ForceKR_Force
No luck Tony still getting null exception in second if condition ..if(!ac.Product_Subscriptions__c.contains(aidAssetMap.get(ac.id).Product_Family__c) )

System.NullPointerException: Attempt to de-reference a null object at  this line "if(!ac.Product_Subscriptions__c.contains(aidAssetMap.get(ac.id).Product_Family__c) )"
Tony TannousTony Tannous
for(Account ac:act)
{
            string prodstring ='';
            if((ac.Product_Subscriptions__c!=null && ac.Product_Subscriptions__c !=''  ))
           {  
string productSub=ac.Product_Subscriptions__c;
                 if(!productSub.contains(aidAssetMap.get(ac.id).Product_Family__c) )
                 {.  
                 System.Debug('Product_Subscriptions__c Match not Found ');
                   prodstring=productSub+';'+aidAssetMap.get(ac.id).Product_Family__c;
                 }
                else
                 {
                      prodstring=aidAssetMap.get(ac.id).Product_Family__c;
                   }

           }
            else 

            {   System.Debug('Product_Subscriptions__c Match Found ');
                prodstring=aidAssetMap.get(ac.id).Product_Family__c;
            }
            updateAccountList.add(new Account(Id = ac.id, Product_Subscriptions__c = prodstring));
 
}

I didn't paid attention to the first if statement it should be &&

Try it now.

This was selected as the best answer
KR_ForceKR_Force
Thank You so much for your help Tony. I was able to resolve the issue with your valuable inputs :-)