+ Start a Discussion
Michele ToscanoMichele Toscano 

Invalid initial value type List for List

 I've tried to put my query directly in a list and then loop through the list but I'm getting an error invalid value type list for list.

Map<String,string> maprecTypewithId = new Map<String,String>();
           List<Price_Authorization_Request__c> listPARToUpdate = new List<Price_Authorization_Request__c>([select id,Name from recordType where SObjectType = 'Price_Authorization_Request__c']);
           for(RecordType rec : listPARToUpdate)
           {
               maprecTypewithId.put(rec.Name,rec.id);
           }

However, If I try it this way - I get the aggregrate query FOR loop error (due to large recrod set) 

Map<String,string> maprecTypewithId = new Map<String,String>();
           List<Price_Authorization_Request__c> listPARToUpdate = new List<Price_Authorization_Request__c>();
           for(RecordType rec : [select id,Name from recordType where SObjectType = 'Price_Authorization_Request__c'])
           {
               maprecTypewithId.put(rec.Name,rec.id);
           }

What is the best way to achieve this - without exceeding governor limits?
Best Answer chosen by Michele Toscano
badibadi
Here is the updated If statement 
 
if( (childRecCount.get(parObj.Id) == updatedCount.get(parObj.Id) && childRecCount.get(parObj.Id) > 0) || (parObj.Expiration_Date__c < System.today() && childRecCount.get(parObj.Id)  == 0 )){ //problem

as you can see we I have added childRecCount.get(parObj.Id) == 0 at the end of the if condition in the OR section. I thought we had already added it in there. I probably missed that. The idea being

If number of child records is equal to the number of child records that are expired, expire the PAR 
Or
If number of child records for PAR is equal to zero and PAR expiration is less than today then expire PAR

Hope this helps
 

All Answers

badibadi
You are trying to query recordType object and assign it to list of type Price_Authorization_Request__c

try this,
 
Map<String,string> maprecTypewithId = new Map<String,String>();
           List<RecordType> listPARToUpdate = [select id,Name from recordType where SObjectType = 'Price_Authorization_Request__c'];
           for(RecordType rec : listPARToUpdate)
           {
               maprecTypewithId.put(rec.Name,rec.id);
           }

 
badibadi
I have fixed some of the issues I noticed.
1. List and maps needs to be specified with type like List<Price_Authorization_Request__c> and Map<String, Id>
2. SOQL query is used within the loop
3. since you are querying the child records you can use subquery, inner query to query child records,
4. maprecTypewithId does not seems to be used anywhere

I have not tested the code, so there might be some errors. try this and let me know. 
Hope this helps
global class Batch_ExpDate_PricIn implements Database.Batchable,Database.Stateful { 
 
 	 global Database.QueryLocator start(Database.BatchableContext BC) { 
		string manualExpStr = 'Manually Expired'; //correct the status name -10/31/16 MT 
		string expiredStr = 'Expired'; 
		string query= 'select Id,RecordTypeId,RecordType.Name,Par_Status__c,Effective_date__c,Expiration_Date__c,
						(select Id,Expiration_Date_Change_To__c,Effective_date__c from Pricing_Input__r) 
						from Price_Authorization_Request__c 
						where Par_Status__c !=:manualExpStr and Par_Status__c !=:expiredStr'; 
		return Database.getQueryLocator(query); 
	}
	
	global void execute(Database.BatchableContext BC, List<Price_Authorization_Request__c> Parlist) { 
		if(Parlist != null && !Parlist.isEmpty()) { 
			//Needs review here: 11/2/16 MT--------------------------- 
			
			Map<String, Id> maprecTypewithId = new Map<String, Id>(); 
			List<RecordType> recTypeRecords = [select id,Name from recordType where SObjectType = 'Price_Authorization_Request__c']; 
			List<Price_Authorization_Request__c> listPARToUpdate= new List<Price_Authorization_Request__c>();
			
			//for(RecordType rec : recTypeRecords) { 
			//	maprecTypewithId.put(rec.Name,rec.id); } //end review: 11/2/16 MT---------------------------------- 
				
				for(Price_Authorization_Request__c parObj : Parlist) { 
					//no longer need this line as we are using sub-query
					//List prList = [select Id,Expiration_Date_Change_To__c,Effective_date__c from Pricing_Input__c 
					//Where Price_Authorization_Request__c =: parObj.Id]; 
					//if(prList != null && prList.size() > 0) { 
						Integer count = 0; 
						for(Pricing_Input__c PrcInputObj : parObj.Pricing_Inputs__r) { 
							if(PrcInputObj.Expiration_Date_Change_To__c != null && PrcInputObj.Expiration_Date_Change_To__c < system.today()) { 	
								count = count + 1; 
							} 
						} 
						if(count == (parObj.Pricing_Inputs__r).size()) { 
							parObj.Par_Status__c = 'Expired'; 
							listPARToUpdate.add(parObj); 
						} 
					//} 
				} 
				if(!listPARToUpdate.isEmpty()) 
					update listPARToUpdate; 
		} 
	} 
 	
 	global void finish(Database.BatchableContext BC) {}
 }

 
badibadi
Michele,

I replied to your other question, I realised that using inner query we will run into too many rows assigned error so here is the mofied query, should work though I did not test.
let me know 
global class Batch_ExpDate_PricIn implements Database.Batchable<sObject>,Database.Stateful
{
   global Database.QueryLocator start(Database.BatchableContext BC)
   {
        string manualExpStr = 'Manually Expired'; //Correct Status -11/2/16 MT
        string expiredStr = 'Expired'; 
        
        string query= 'select Id,RecordTypeId,RecordType.Name,Par_Status__c,Effective_date__c,Expiration_Date__c from Price_Authorization_Request__c where Par_Status__c !=:manualExpStr  and Par_Status__c !=:expiredStr';
             return Database.getQueryLocator(query);
   }

   global void execute(Database.BatchableContext BC, List<Price_Authorization_Request__c> Parlist) {
            
       if(Parlist != null && !Parlist.isEmpty())
       {
              Map<String,string> maprecTypewithId = new Map<String,String>();
           List<Price_Authorization_Request__c> listPARToUpdate = new List<Price_Authorization_Request__c>();
           for(RecordType rec : [select id,Name from recordType where SObjectType = 'Price_Authorization_Request__c']) //-->system does not like this
           {
               maprecTypewithId.put(rec.Name,rec.id);
           }
		   
		   Map<Id, Integer> childRecCount= new Map<id, Integer>();
		   Map<Id, Integer> updatedCount= new Map<Id, Integer>();
		   Set<Id> prI= new Set<Id>();
		   for(Price_Authorization_Request__c parObj : Parlist){
			prI.add(parObj.Id);
			childRecCount.put(parObj.Id, 0);
			updatedCount.put(parObj.Id, 0);
		   }
		   List<Pricing_Input__c> pInput= [select Id,Expiration_Date_Change_To__c,Effective_date__c, Price_Authorization_Request__c from Pricing_Input__c WHERE Price_Authorization_Request__c IN :prI];  
		   
		   //get original count 
		   for(Pricing_Input__c pi :pInput){
				childRecCount.put(pi.Price_Authorization_Request__c, childRecCount.get(pi.Price_Authorization_Request__c)+1);
				updatedCount.put(pi.Price_Authorization_Request__c, updatedCount.get(pi.Price_Authorization_Request__c)+1);
		   }
		   
		    for(Price_Authorization_Request__c parObj : Parlist){
				if(childRecCount.get(parObj.Id) == updatedCount.get(parObj.Id)){
					parObj.Par_Status__c = 'Expired'; 
					if(parObj.RecordType.Name == 'Standard PAR' && maprecTypewithId.get('ReadOnlyStandard PAR') != null)
                      parObj.RecordTypeId = maprecTypewithId.get('ReadOnlyStandard PAR');
                    else if(parObj.RecordType.Name == 'Formula PAR' && maprecTypewithId.get('ReadOnlyFormula PAR') != null)
                      parObj.RecordTypeId = maprecTypewithId.get('ReadOnlyFormula PAR');
                    listPARToUpdate.add(parObj);
				}
		   }
           
           if(!listPARToUpdate.isEmpty())
               update listPARToUpdate;
       }
   }
    
    global void finish(Database.BatchableContext BC)
    {}
 }


 
badibadi
Yes I see what you mean, I am thinking replacing the if statement 
if(childRecCount.get(parObj.Id) == updatedCount.get(parObj.Id)){

with
 
if(childRecCount.get(parObj.Id) == updatedCount.get(parObj.Id) && childRecCount.get(parObj.Id) > 0){

should resolve that issue. Now we are also making sure that we are not updating PAR when there are no child records. 
I am sorry you had to redo this number of times, but this should fix the problem.
badibadi
I did not get the second part about the   price_authorization__c field = Expiration_Date__c  so I am assuming we can do Expiration date, we can add Expiration_Date__c < System.today() to the same if condition. like
 
IF( (childRecCount.get(parObj.Id) == updatedCount.get(parObj.Id) && childRecCount.get(parObj.Id) > 0) || (parObj.Expiration_Date__c < System.Today()))

 
badibadi
Michele, I think I finally got the issue.  see the code section below
List pInput= [select Id,Expiration_Date_Change_To__c,Effective_date__c, Price_Authorization_Request__c from Pricing_Input__c WHERE Price_Authorization_Request__c IN :prI]; //get original count 
			for(Pricing_Input__c pi :pInput){ 
				if(pi.Expiration_Date_Change_To__c != null && pi.Expiration_Date_Change_To__c < system.today()){ //--> I think from here below needs consideration  
					childRecCount.put(pi.Price_Authorization_Request__c, childRecCount.get(pi.Price_Authorization_Request__c)+1); updatedCount.put(pi.Price_Authorization_Request__c, updatedCount.get(pi.Price_Authorization_Request__c)+1); 
				} 
			}
the if  inside of for loop is the problem, since it is around childreccount and updatedcount, the count will be always be same for both. The condition should be only around updatedcount

So, here is the corrected version, just replace this section and try again
 
List pInput= [select Id,Expiration_Date_Change_To__c,Effective_date__c, Price_Authorization_Request__c from Pricing_Input__c WHERE Price_Authorization_Request__c IN :prI]; //get original count 
			for(Pricing_Input__c pi :pInput){ 
				 childRecCount.put(pi.Price_Authorization_Request__c, childRecCount.get(pi.Price_Authorization_Request__c)+1); 
				 if(pi.Expiration_Date_Change_To__c != null && pi.Expiration_Date_Change_To__c < system.today()){ //--> I think from here below needs consideration 
					updatedCount.put(pi.Price_Authorization_Request__c, updatedCount.get(pi.Price_Authorization_Request__c)+1); 
				} 
			}



 
Michele ToscanoMichele Toscano
The problem is with the evaluation of this:

 for(Pricing_Input__c pi :pInput){
                childRecCount.put(pi.Price_Authorization_Request__c, childRecCount.get(pi.Price_Authorization_Request__c)+1); 
                     if(pi.Expiration_Date_Change_To__c != null && pi.Expiration_Date_Change_To__c < system.today()) {  
                    updatedCount.put(pi.Price_Authorization_Request__c,  
                    updatedCount.get(pi.Price_Authorization_Request__c)+1);
                } 
            }
           
            for(Price_Authorization_Request__c parObj : Parlist){
                if( (childRecCount.get(parObj.Id) == updatedCount.get(parObj.Id) && childRecCount.get(parObj.Id) > 0) || (parObj.Expiration_Date__c < System.today())){ //problem 
                    parObj.Par_Status__c = 'Expired'; 

Since the expiration date resides on both the header and on the pricing input level- the pricing input level always wins.  Meaning, if there is ANY product pricing inputs with a changed expiration date to the future- even if the PAR's header expiration is in the past- it should NOT be expired. Only when there are no product pricing inputs should the main PAR's expiration be considered when it's in the past- then, in that case- it should mark it fully expired.
badibadi
Here is the updated If statement 
 
if( (childRecCount.get(parObj.Id) == updatedCount.get(parObj.Id) && childRecCount.get(parObj.Id) > 0) || (parObj.Expiration_Date__c < System.today() && childRecCount.get(parObj.Id)  == 0 )){ //problem

as you can see we I have added childRecCount.get(parObj.Id) == 0 at the end of the if condition in the OR section. I thought we had already added it in there. I probably missed that. The idea being

If number of child records is equal to the number of child records that are expired, expire the PAR 
Or
If number of child records for PAR is equal to zero and PAR expiration is less than today then expire PAR

Hope this helps
 
This was selected as the best answer
Michele ToscanoMichele Toscano
Yes, you know what?  I had just found that same thing and had added that into my code right before you replied.  I am in the process of testing that now.  Very good!  Good to know we are both finding the same issue!