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
brozinickrbrozinickr 

Illegal assignment from LIST<Opportunity> to LIST <AM_Performance__c>

Hi,

 

I've been tasked to create an opportunity roll up on one of our custom objects AM_Performance__c.  I need to put the number of opportunitites owned by the certain user.

 

I figured what I could do is get a list of owner ids, then get query opportunity to get all of the opportuities owned by that owner id, then write size of that list to the AM_Performance__c object.  Problem is that I am getting this illegal assignment error on the line that's marked in red.  Can someone help?

 

Thanks!

 

 

trigger AMPROppCount on Opportunity (after insert, after update, after delete, after undelete) {

    //Create a Set to hold Acct Ids of opps in trigger and a List to hold accts which will be updated
    
    Set<Id> ownerIdSet = new Set<Id>();
    List<AM_Performance__c> amprUpdateList = new List<AM_Performance__c>();

    //Create ths set of Owner IDs.  If this is a delete trigger, pull them the trigger.old,
    //otherwise use trigger.new
    
    if(Trigger.isDelete)
        for(Opportunity o : trigger.old)
            ownerIdSet.add(o.OwnerId);
    else
        for(Opportunity o : trigger.new)
            ownerIdSet.add(o.OwnerId);

    //Query for all of the opportunities 
    List<AM_Performance__c> amprOpptyList = [select Id, OwnerId, IsWon, IsClosed from Opportunity where ownerId IN :ownerIdSet];

    //loop through all of the AM_Performance__cs in the map and get the counts for total number of opps,
    //count of closed and count of won opps.
    
    for(AM_Performance__c a : amprOpptyList){
        //initialize our counters
        Integer wonOpps = 0;
        Integer closedOpps = 0;

        //loop through the associated opportunities and count up the opportunities
        for(Opportunity o : a.Opportunities){
            if(o.IsClosed){
                closedOpps++;
                
            if(o.IsWon) wonOpps++;
            }
        }

        //set the counts
        a.Opportunities_Owned_This_Month__c = a.Opportunities.size();

        //add the AM_Performance__c to the update list
        amprUpdateList.add(a);
    }

    //update all of the AM_Performance__c's if the list isn't empty
    if(!amprUpdateList.IsEmpty())
update amprUpdateList; }

 

Best Answer chosen by Admin (Salesforce Developers) 
Zach CarterZach Carter

Well you can't because you never cached the result set returned from the query to get the opportunities.

 

Soooo... Instead of -

 

for(Opportunity o : [SELECT Id, IsWon, IsClosed FROM Opportunity where Id in :ownerIdSet]){
            if(o.IsClosed){
                closedOpps++;
                
            if(o.IsWon) wonOpps++;
            }
        }

 

Do this - 

 

List<Opportunity> opportunities = new List<Opportunity>([SELECT Id, IsWon, IsClosed FROM Opportunity where Id in :ownerIdSet]);

for(Opportunity o : opportunities) {

...

}

 

Now you can do -

 

a.Opportunities_Owned_This_Month__c = opportunities.size();

 

All Answers

Zach CarterZach Carter

That's not going to work for several reasons...

 

First of all, AM_Performance__c is a custom field on your Opportunity object I'm guessing. When you declare a list, you must declare a type for the objects that list will hold. AM_Performance__c is not a type (unless it's a custom object). If it is a field like I am thinking, it is a field of some type - like String, Boolean, Integer etc... so you should be declaring your list like :

 

List<String> (replace string with whatever type the AM_Performance__c field is of.

 

Your query is not going to return a list of fields, it's going to return a list of Opportunity objects.

 

Try doing something like this :

 

List<String> amprOpptyList = new List<String>();
 
for(Opportunity o : [SELECT Id, OwnerId, IsWon, IsClosed from Opportunity where ownerId IN :ownerIdSet]) {
    amprOpptyList .add(o.AM_Performance__c);
}

 

 

-Zach

brozinickrbrozinickr

AM_Performance__c is a custom object, not a field on the Opportunity.  There is no lookups/masterdetail relationships between these two objects, so the only relationship I can work with the OwnerId of each record of the object.  That's why I figured I could use this to link these together.

Zach CarterZach Carter

Wait so AM_Performance__c references the owner ID? In that case why don't you just query against the AM_Performance__c table?

brozinickrbrozinickr

Sorta.  Sorry, I didn't really explain it that well.  These are two the objects that I am using:

 

There is no relationship between any of these at all.  No lookup to from Opportunity to AM_Performance and vice versa.  But one thing they do have in common is a lookup to the User object by OwnerId.  I figured that I could create a set of AM_Performance__c OwnerIds, then in list in the red that failed, then query all opportunities that are owned by ownerids created in the set AM_Performance_c ownerids. 

 

AM_Performance_C           user                      Opportunity

 

id                                                                              id

OwnerId       -->                    id                    <---   OwnerId

Goal Name                                                            LeadSource

Amount                                                                  Type

% to Goal                                                               ..etc

...etc

 

Will that work, or do I need to create some type of map or something?

 

Zach CarterZach Carter

Okay in that case it shouldn't be difficult at all.

 

You have a set of owner Ids and from that list, you want to find any any AM_Performance__c objects which reference said owner Ids.

 

To do that you can just query against the AM_Performance__c table.

 

Your code would look like this now - 

 

trigger AMPROppCount on Opportunity (after insert, after update, after delete, after undelete) {

    //Create a Set to hold Acct Ids of opps in trigger and a List to hold accts which will be updated
    
    Set<Id> ownerIdSet = new Set<Id>();
    List<AM_Performance__c> amprUpdateList = new List<AM_Performance__c>();

    //Create ths set of Owner IDs.  If this is a delete trigger, pull them the trigger.old,
    //otherwise use trigger.new
    
    if(Trigger.isDelete)
        for(Opportunity o : trigger.old)
            ownerIdSet.add(o.OwnerId);
    else
        for(Opportunity o : trigger.new)
            ownerIdSet.add(o.OwnerId);

    //Query for all of the opportunities 
    List<AM_Performance__c> amprOpptyList = [select Id, OwnerId, ... from AM_Performance__c where ownerId IN :ownerIdSet];

    //loop through all of the AM_Performance__cs in the map and get the counts for total number of opps,
    //count of closed and count of won opps.
    
    for(AM_Performance__c a : amprOpptyList){
        ...
    }

    //update all of the AM_Performance__c's if the list isn't empty
    if(!amprUpdateList.IsEmpty())
       update amprUpdateList;
}

 

brozinickrbrozinickr

Okay, I think that fixed my problem with my list, yay.  Thanks for your help.  I am now I am getting this error with my code though...

 

 Error: Compile Error: Loop must iterate over a collection type: Decimal at line 28 column 29

 

 

trigger AMPROppCount on Opportunity (after insert, after update, after delete, after undelete){

//Create a Set to hold Acct Ids of opps in trigger and a List to hold accts which will be updated

Set<Id> ownerIdSet = new Set<Id>();
List<AM_Performance__c> amprUpdateList = new List<AM_Performance__c>();

//Create ths set of Owner IDs. If this is a delete trigger, pull them the trigger.old,
//otherwise use trigger.new

if(Trigger.isDelete)
for(Opportunity o : trigger.old) ownerIdSet.add(o.OwnerId);
else for(Opportunity o : trigger.new) ownerIdSet.add(o.OwnerId);

//Query for all of the opportunities

List<AM_Performance__c> amprOpptyList = [select Id, OwnerId from AM_Performance__c where ownerId IN :ownerIdSet];

//loop through all of the AM_Performance__cs in the map and get the counts for total number of opps,
//count of closed and count of won opps.

        for(AM_Performance__c a : amprOpptyList){
        //initialize our counters
        Integer wonOpps = 0;
        Integer closedOpps = 0;

        //loop through the associated opportunities and count up the opportunities
        for(Opportunity o : a.Opportunities_Owned_This_Month__c){
            if(o.IsClosed){
                closedOpps++;
                
            if(o.IsWon) wonOpps++;
            }
        }

        //set the counts
        a.Opportunities_Owned_This_Month__c = a.Opportunity.size();

        //add the AM_Performance__c to the update list
        amprUpdateList.add(a);
    }

//update all of the AM_Performance__c's if the list isn't empty

if(!amprUpdateList.IsEmpty()) update amprUpdateList; }

 

Zach CarterZach Carter

I'm not sure what the type of the field Opportunities_Owned_This_Month__cc is, but the error is related to you trying to loop over an object which is not a type of collection.

 

What does Opportunities_Owned_This_Month__c hold? If it is supposed to be a collection, make sure you are grabbing it in your query - 

List<AM_Performance__c> amprOpptyList = [select Id, OwnerId, Opportunities_Owned_This_Month__c from AM_Performance__c where ownerId IN :ownerIdSet];
brozinickrbrozinickr

Opportunities_Owned_This_Month__c is the field that I want to put the total amount of opportunities owned by that user.  So what I have completely incorrect.  What I am trying to do in that loop is count up all of the opportunities that are associated with the ownerid, and then put in the Opportunities_Owned_This_Month__c field.

Zach CarterZach Carter

Okay if that's the case then something like - 

 

  for(AM_Performance__c a : amprOpptyList){
        //initialize our counters
        Integer wonOpps = 0;
        Integer closedOpps = 0;

        //loop through the associated opportunities and count up the opportunities
        for(Opportunity o : [SELECT Id, IsWon, IsClosed FROM Opportunity where Id in :ownerIdSet]){
            if(o.IsClosed){
                closedOpps++;
                
            if(o.IsWon) wonOpps++;
            }
        }

        //set the counts
        a.Opportunities_Owned_This_Month__c = a.Opportunity.size();

        //add the AM_Performance__c to the update list
        amprUpdateList.add(a);
    }

 

should work. Once again these objects do not hold reference to each other so the only way to retrieve them and establish a relationship is based on a common field - in this case the ownerId field.

 

Hope this solves your problem. You could def tune that trigger to perform less SOQL queries / script statements but since you're new to Apex it seems I think you should get it working and then go over the code to understand how it works. After doing that check out maps and lists.

 

-Zach

brozinickrbrozinickr

When I get to this part, this no longer works since that collection doesn't exist anymore.  How do I reference the size of the records found in the collection so it writes the field correctly?

 

 

a.Opportunities_Owned_This_Month__c = a.Opportunity.size();
Zach CarterZach Carter

Well you can't because you never cached the result set returned from the query to get the opportunities.

 

Soooo... Instead of -

 

for(Opportunity o : [SELECT Id, IsWon, IsClosed FROM Opportunity where Id in :ownerIdSet]){
            if(o.IsClosed){
                closedOpps++;
                
            if(o.IsWon) wonOpps++;
            }
        }

 

Do this - 

 

List<Opportunity> opportunities = new List<Opportunity>([SELECT Id, IsWon, IsClosed FROM Opportunity where Id in :ownerIdSet]);

for(Opportunity o : opportunities) {

...

}

 

Now you can do -

 

a.Opportunities_Owned_This_Month__c = opportunities.size();

 

This was selected as the best answer
brozinickrbrozinickr

Perfect.  Just tested it manually and it works great.  Thanks for helping me with this, I really appreciate it!

 

Happy Holidays!

 

Rachel