[SalesForce] How to upsert multiple new records based on a multi-value field

I'm a total newbie who is essentially trying to write his first trigger.

Right now, I have a multi-value field in an object. I would like to create a new record for each value in that field.

This is the closest code I could find to try and show my intention :

trigger AutoCreateInterviewer on Position__c (after insert) {
    List<Interviewer__c> interviewers = new List<Interviewer__c>();

    //For each position processed by the trigger, add a new  

    //interviewer record for the specified hiring manager.  

    //Note that Trigger.New is a list of all the new positions  

    //that are being created.  

    for (Position__c newPosition: Trigger.New) {
        if (newPosition.Hiring_Manager__c != null) {
            interviewers.add(new Interviewer__c(
                        Name = '1',
                        Position__c = newPosition.Id,
                        Employee__c = newPosition.Hiring_Manager__c,
                        Role__c = 'Managerial'));
        }
    }
    insert interviewers;
}

Basically, imagine the Hiring_Manager_c field had multiple values in it ( [John, Stacy, Robert] ) . I would like to create a new Interviewer_c record for each one of those people.

Somehow I have to figure out a way to get it to iterate through the values in the Hiring_Manager__c field. I guess I need to use something like this :

Iterate through a list

…but I'm having trouble figuring out how to apply that to the trigger.

Thank you very much for any help you can supply. I'm very grateful for your time and effort.

UPDATE – USING THE UPSERT INSTEAD OF THE INSERT :

In order to use this as an Upsert instead of an Insert I will need to do something like this :

Account[] acctsList = [SELECT Id, Name, BillingCity
    FROM Account WHERE BillingCity = 'Bombay'];
for (Account a : acctsList) {
    a.BillingCity = 'Mumbai';
}

Account newAcct = new Account(Name = 'Acme', BillingCity = 'San Francisco');
acctsList.add(newAcct);
try {
    upsert acctsList ;
}  catch (DmlException e)  {
    System.debug(e.getMessage());
}

So, in the example which Jesse showed below, would I be able to just replace this line :

insert interviewers;

with this ? :

try {
        upsert interviewers Hiring_Manager__c ;
    }  catch (DmlException e)  {
        System.debug(e.getMessage());
    }

Can I still use the Test code which Jesse included, or does it actually have to be re-written just to account for an Upsert instead of an Insert ?

Thank you again for all of your effort and time.

Best Answer

Multi-select picklists are stored as value1;value2;value3;etc. Knowing that, you can get a List of these values using the String split() method. You can also view this string splitting example. To access it, you would then tweak your code as:

trigger AutoCreateInterviewer on Position__c (after insert) {
    List<Interviewer__c> interviewers = new List<Interviewer__c>();

    //For each position processed by the trigger, add a new  

    //interviewer record for the specified hiring manager.  

    //Note that Trigger.New is a list of all the new positions  

    //that are being created.  

    for (Position__c newPosition: Trigger.New) {
        if (newPosition.Hiring_Manager__c != null) {
            // split out the multi-select picklist using the semicolon delimiter
            for(String hiringManager: newPosition.Hiring_Manager__c.split(';')){
                interviewers.add(new Interviewer__c(
                        Name = '1',
                        Position__c = newPosition.Id,
                        Employee__c = (Id)hiringManager,
                        Role__c = 'Managerial'));
            }
        }
    }
    insert interviewers;
}

@isTest
public with sharing class AutoCreateInterviewerTriggerTest {

    static testMethod void testGetAdvisor() {
        // First, set up your test User.
        User testUser = generateTestUser();

        // Generate your position but don't perform DML yet
        Position__c pos = new Position(Hiring_Manager__c = testUser.Id);

        // Start your test and insert your position
        Test.startTest();
        insert pos;
        Test.stopTest();

        // Get the interviewers from the DB to ensure they were created
        List<Interviewer__c> interviewers = [SELECT
                                                 Id
                                             FROM
                                                 Interviewer__c
                                             WHERE
                                                 Position__c = :pos.Id
        ];

        // There should be 1 interviewer because only one user ID was provided
        System.assert(1, interviewers.size(), 'One interviewer object is expected');
    }

    private User generateTestUser(){
        // We use the System Admin profile because it will always be there
        Profile sysAdmin = [SELECT 
                               Id 
                            FROM 
                               Profile 
                            WHERE 
                               Name = 'System Administrator'
                            LIMIT 1
        ];

        // Generate the user
        User newUser = new User(
            UserName = 'unit.tester@example.com',
            LastName = 'Test',
            FirstName = 'Jane',
            Email = 'unit.tester@example.com',
            phone = '555-555-5555',
            MobilePhone = '555-555-5554',
            Street = '123 Fake Street',
            City = 'Los Angeles',
            State = 'CA',
            PostalCode = '12345',
            CommunityNickName = 'unit.test',
            Alias = 'abcd',
            ProfileId = sysAdmin.Id,
            emailencodingkey = 'UTF-8',
            languagelocalekey = 'en_US',
            localesidkey = 'en_US',
            timezonesidkey = 'America/Los_Angeles'
        );

        // Insert that user
        insert user;

        return user;
    }
}
Related Topic