[SalesForce] Check if Text Field Contains Picklist Value

I have a trigger that is designed to write unique values of a Picklist from a child object (VIP_Type__c) to the associated Account record. I am having trouble figuring out how to convert the picklist value to a string value to check if the Account field contains the picklist value. The line of code I have is:

if(!a.VIP_Types__r.contains(vip.VIP_Type__c))

Where vip.VIP_Type__c is the picklist field and VIP_Types__r is the text field on the Account. I am getting an error:

"Method does not exist or incorrect signature: void contains(String) from the type List<VIP_Type__c>"

Any ideas? My full trigger is below:

    trigger UpdateAcctVIP on VIP_Type__c (after insert, after update, after delete){
        
        Set<Id> acctIds = new Set<ID>();
        
        // Get all the Account Ids in the Set
        if (Trigger.isDelete)
        {
            for(VIP_Type__c vip : Trigger.old){
                acctIds.add(vip.Account__c);
            }

        }
        else
        {
            for(VIP_Type__c vip : Trigger.new){
                acctIds.add(vip.Account__c);
            }
        }
        // QUery the Accounts
        List<Account> acct = new List<Account>();
        // Use the VIP Types to get all the related Types for the Account
        acct = [SELECT Id, VIP_Types__c,(Select VIP_Type__c FROM VIP_Types__r)
                FROM Account
                WHERE Id in :acctIds];
    
    // Iterate over each Account and VIP record
        for(Account a : acct){

//               for(VIP_Type__c vip: a.Id){
               for(VIP_Type__c vip: a.VIP_Types__r){

                if(!a.VIP_Types__c.contains(vip.VIP_Type__c) || a.VIP_Types__c == null){ // Check if the Type is already in the Account Field. if not add it otherwise skip

                    a.VIP_Types__c += vip.VIP_Type__c + ';';
                }
            }
        }
        // Update the Account
        update acct;
    }

Best Answer

As far as Apex is concerned, a picklist is just a string.

Your provided code has some issues with it. You're not querying your accounts for the child VIP_Type__c records (which would would do here by using a parent-child subquery, a nested SELECT clause inside another SELECT clause).

The bigger issue though is that you seem to misunderstand what your query is giving you (or would be giving you).

If your query were something like [SELECT Id, (SELECT Id, VIP_Type__c FROM VIP_Types__r) FROM Account], then account.VIP_Types__r is a List of SObjects, specifically, a List<VIP_Type__c>.

The subquery doesn't give you just a single string, it gives you a list. Hence your error.

That aside, I think you're going about this the hard(er) way. The way I'd approach this would be something like (in pseudo-code)

// manual rollups like this which need to be updated when a child record is deleted
//   need to have special care taken with the deletion bits
// In a nutshell, if we delete the last child record, the parent record's rollup should 
//   end up being blank
// We need to prepare to do that by default, since the second query won't return any results
//   if the last related child is being deleted.
Map<Id, Account> accountsToUpdate = new Map<Id, Account>();
for each VIP_Type__c record{
    add account id to a list
    accountsToUpdate.put(accountId, new account(Id = accountId, VIP_Types__c = ''));
}

// A set naturally contains only unique values, so it's a better fit for what you're
//   trying to do
Map<Id, Set<String>> accountIdToPicklistVals = new Map<Id, Set<String>>();

// I think querying the child object makes more sense here
// The single vs nested loop thing wouldn't really matter, but since I don't think
//   there's really any benefit to having SOQL group the child records under each parent
//   here, I'd opt for simplicity and brevity
for(vip_type :[SELECT AccountId, picklistField FROM VIP_Type__c WHERE AccountId IN :accountIds]){
    if(account Id not in accountIdToPicklistVals map){
        accountIdToPicklistVals.put(accountId, new Set<String>());
    }

    grab the set from the accountIdToPicklistVals map, and add vipType.picklistField to the set
}

for each id in the accountIdToPicklistVals map{
    // String.join only works on lists, but we used a set to prevent duplicate values
    // Lucky for us, there is a list constructor that takes a set
    String uniqueVals = String.join(new List<String>(accountIdToPicklistVals.get(accountId)), ';');
    accountsToUpdate.get(accountId).VIP_Types__c = uniqueVals;
}

update accountsToUpdate;