The basic premise of this code, for those of you who have not seen my 600+ other posts about it, is that it creates a Contact whenever someone creates a User. Certain fields of the contact are then automatically populated using the same fields from the User.
I thought I finally finished this code, when I got the Mixed DML Operation error after some more extensive testing. When I create a new user with a "Chatter Free" license, no Role, and the "Chatter Free User" profile, it goes through perfectly, even brought a tear to my eye. However, when I create a User with any other license, a role, and any other profile, I get the above error (this brought many more tears to my eye).
I'm not sure if I actually need a workaround, or if there is some small, stupid problem with my code. Hopefully someone here can offer some insight. I tried using a @future class, as well as system.runas (Sorry about all the comments, I'm very new to this and that's how I keep my thought process straight while learning).
here is my CLASS
public class UserContact {
//Create the class and grab the IDs needed
public static void createUserContact(set<ID> recordIDs){
//Grab all the required fields from user, essential to test class
list<user> users = [SELECT ID, Firstname, Lastname, email, name, username, UserRoleId, CommunityNickname, TimeZoneSidKey, LocaleSidKey, EmailEncodingKey, ProfileId, LanguageLocaleKey
FROM user
WHERE ID in :recordIDs];
String accountName = 'Company Internal';
//In this query you want to "LIMIT 1" to avoid more than
//1 record returning
Account Accountx = [SELECT ID
FROM account
Where Name = :accountName
LIMIT 1];
//Create a list to hold the contacts being created
List<Contact> contactsToCreate = new List<Contact>();
//Iterate through each field we want to automatically populate
for (user x: users){
//Assign the email related to the user grabbed to a string so
//we can reference it later.
//If this was not done, we would get an error for trying to
//mix an SObject with a String.
String userEmail = x.Email;
//If statement containing the contact creation. If
//the parameters are not met, the user is still
//created, but a contact is not.
if(userEmail.endsWith('@company.com')){
Contact userCon = new contact(
AccountID = AccountX.id,
FirstName = x.FirstName,
LastName = x.LastName,
Username__C = x.Username,
email = userEmail);
contactsToCreate.add(userCon);
insert contactsToCreate;
}
else{
system.debug('Email not internal, Contact not created');
}}}}
Here is what I tried with the @Future method. The error I got was... "Variable does not exist: recordIDs" I played around with this for quite a while, so this example may not be the closest I got. If I remember correctly, my problem was referencing the lists I got in the first class.
public class UserContact {
//Create the class and grab the IDs needed
@future public static void createUserContact(set<ID> recordIDs){
//Grab all the required fields from user, essential to test class
list<user> users = [SELECT ID, Firstname, Lastname, email, name, username, UserRoleId, CommunityNickname, TimeZoneSidKey, LocaleSidKey, EmailEncodingKey, ProfileId, LanguageLocaleKey
FROM user
WHERE ID in :recordIDs];
String accountName = 'Company Internal'; //This is where you will provide your name (could be any other field)
//In this query you want to "LIMIT 1" to avoid more than 1 record returning
Account Accountx = [SELECT ID
FROM account
Where Name = :accountName
LIMIT 1];
public class insertContactClass{
public void insertContactMethod(){
//Create a list to hold the contacts being created
List<Contact> contactsToCreate = new List<Contact>();
UserContact.createUserContact(recordIDs);
//Iterate through each field we want to automatically populate
for (user x: users){
String userEmail = x.Email;
if(userEmail.endsWith('@company.com')){
Contact userCon = new contact(
AccountID = AccountX.id,
FirstName = x.FirstName,
LastName = x.LastName,
Username__C = x.Username,
email = userEmail);
contactsToCreate.add(userCon);
insert contactsToCreate;
}
else{
system.debug('Email not internal, Contact not created');
}}}}}
Here is the TRIGGER:
trigger NewUserCreatedTrigger on User (after insert) {
//Creates an array to hold the users caused by trigger firing
user[] users = trigger.new;
//Creates a map of records being inserted, then keyset returns the IDs for all records in the map
UserContact.createUserContact(Trigger.newMap.keySet());
}