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
Cha YangCha Yang 

Apex Trigger to update a field

I'm new to apex trigger so bear with me. I have Account and a custom object (InvsetigationContact). On the custom object I created a text field call CheckID that I want to use it for duplicate checking. I want to create the Before Trigger to filling in with combine of First+last Name + ContactID from the Account. 

Not sure how to get started. Please help. 
 
Best Answer chosen by Cha Yang
Steven NsubugaSteven Nsubuga
My fault, here is the right trigger.
trigger DupCheckID on Investigation_Contact__c (Before insert, before update) {
	Set<Id> accountIds = new Set<Id>();
    for (Investigation_Contact__c ic : trigger.new){
        accountIds.add(ic.Client_Potential_Name__c);
	}
	
    Map<Id, Account> accountsMap = new Map<Id, Account> ([SELECT Id, Salesforce_ID__pc FROM Account where Id IN :accountIds]);
	for (Investigation_Contact__c ic : trigger.new){
		Account icAccount  = accountsMap.get(ic.Client_Potential_Name__c);
        ic.DupCheckID__c = icAccount.Salesforce_ID__pc + '-'+ic.Investigation_ID__c;
	}
}

 

All Answers

Steven NsubugaSteven Nsubuga
Is there a relationship between Account and InvsetigationContact?  Are these fields "First+last Name + ContactID" on Account or on InvsetigationContact? You need to provide more details on what exactly you are trying to do.
Neha AggrawalNeha Aggrawal
Hi Cha,

You can get started from this trailhead unit: https://trailhead.salesforce.com/en/modules/apex_triggers/units/apex_triggers_intro
Your requirement looks quite straightforward, so it should not be difficult. Give it a shot and if you face any issues, post the code here, so we can help. 
Thanks.
 
Cha YangCha Yang
@Steven Nsubuga Yes Account is a lookup field in the investigationContact object. As I said above first+lastname+contactid are on the Account object. 
 
Steven NsubugaSteven Nsubuga
Then you can use a formula field on the investigationContact object. It is the easiest way to meet your requirement.
If the name of the lookup to Account is Account__c then your formula would be
​Account__r.first+ Account__r.lastname+Account__r.contactid
Assuming that first, lastname and contactid are the API names of those fields on the Account object.
Cha YangCha Yang
Formula field can’t be use in duplicate rules that’s why I’m looking into trigger. Let me know if I’m wrong about this.
Steven NsubugaSteven Nsubuga
I had missed that detail, apologies.
You can use this formula syntax in Process Builder to create a process that updates that field as required.
Cha YangCha Yang
Process builder and workflow won’t work because I want to use the field in a duplicate rule during the creation of the record. Process and workflow run after the duplicate rule so it won’t work for my requirement. It has to be apex trigger – before insert.
Steven NsubugaSteven Nsubuga
Some thing along these lines should get the job done.
trigger checkIdTrigger on investigationContact (before insert, before update) {
	Set<Id> accountIds = new Set<Id>();
	for (investigationContact ic : trigger.new){
		accountIds.add(ic.Account__c)
	}
	Map<Id, Account> accountsMap = new Map<Id, Account> ([SELECT Id, first, lastname, contactId FROM Account where Id IN :accountIds]);
	for (investigationContact ic : trigger.new){
		Account icAccount  = accountsMap.get(ic.Account__c);
		ic.CheckID__c = icAccount.first		+	icAccount.lastname	+	icAccount.contactid;
	}
}

 
Cha YangCha Yang
Got the trigger to work as expected but stuck on the test class. 
trigger DupCheckID on Investigation_Contact__c (Before insert, before update) {
Set<Id> accountIds = new Set<Id>();
    for (Investigation_Contact__c ic : trigger.new){
        accountIds.add(ic.Client_Potential_Name__c)
    ;
    Map<Id, Account> accountsMap = new Map<Id, Account> ([SELECT Id, Salesforce_ID__pc FROM Account where Id IN :accountIds]);

        Account icAccount  = accountsMap.get(ic.Client_Potential_Name__c);
        ic.DupCheckID__c = icAccount.Salesforce_ID__pc + '-'+ic.Investigation_ID__c;
    
}


}
Below is the test class. 0061C00000XZCW2 and 0011C00001vIHgM are two existing record and i'm trying to link them. 
@IsTest
public class TestDupcheckID {

    static testmethod void insertic() {
      Investigation_Contact__c ic = new Investigation_contact__c();
     ic.Investigation__c = '0061C00000XZCW2';
     ic.Client_Potential_name__c= '0011C00001vIHgM';
      Insert ic;
     }
 }
Time Started5/23/2018 5:14 PM
ClassTestDupcheckID
Method Nameinsertic
Pass/FailFail
Error MessageSystem.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, DupCheckID: execution of BeforeInsert

caused by: System.NullPointerException: Attempt to de-reference a null object

Trigger.DupCheckID: line 9, column 1: []
Stack TraceClass.TestDupcheckID.insertic: line 8, column 1
Steven NsubugaSteven Nsubuga
You need an account as part of the test code. In test classes you are required to create the records for use in testing. That means you have to create an Account, and insert it into Salesforce. Then you create an Investigation Contact, link it to the created Account and then insert the Investigation Account.
Then your test must inspect the DupCheckID__c field to ensure that it was properly populated.
@IsTest
public class TestDupcheckID {

    static testmethod void insertic() {
    	Account testAccount = new Account();
    	testAccount.Name = 'testAccount';
    	testAccount.Salesforce_ID__pc ='someId';
    	insert testAccount;

	    Investigation_Contact__c ic = new Investigation_contact__c();

	    // linking uc to test account
	    ic.Client_Potential_name__c= testAccount.id;
	    Insert ic;

        // check that the trigger logic worked
        Investigation_Contact__c ic2 = [SELECT DupCheckID__c, Investigation_ID__c FROM Investigation_Contact__c WHERE Id =:ic.id];
        System.assertEquals(ic2.DupCheckID__c, testAccount.Salesforce_ID__pc + '-'+ic2.Investigation_ID__c);
    }
 }

Something like this is what is required.
Cha YangCha Yang
Salesforce_ID__pc is an auto number field. @IsTest public class TestDupcheckID { static testmethod void insertic() { Account testAccount = new Account(); testAccount.FirstName = 'iPhone'; TestAccount.LastName = 'Apple'; //TestAccount.Salesforce_ID__pc ='SomeId'; insert testAccount; Investigation_Contact__c ic = new Investigation_contact__c(); // linking uc to test account ic.Client_Potential_name__c= testAccount.id; ic.Investigation__c ='0061C00000XZCW2'; // ic.DupCheckID__c = TestAccount.Salesforce_ID__pc+'-'+ic.Investigation_ID__c; Insert ic; // check that the trigger logic worked Investigation_Contact__c ic2 = [SELECT DupCheckID__c, Investigation_ID__c FROM Investigation_Contact__c WHERE Id =:ic.id]; System.assertEquals(ic2.DupCheckID__c, testAccount.Salesforce_ID__pc + '-'+ic2.Investigation_ID__c); } } And I’m getting the this error. Time Started 5/24/2018 11:11 AM Class TestDupcheckID Method Name insertic Pass/Fail Fail Error Message System.AssertException: Assertion Failed: Expected: 11150393-0061C00000XZCW2, Actual: null-0061C00000XZCW2 Stack Trace Class.TestDupcheckID.insertic: line 21, column 1
Cha YangCha Yang
@IsTest public class TestDupcheckID { static testmethod void insertic() { Account testAccount = new Account(); testAccount.Name = 'testAccount'; //testAccount.Salesforce_ID__pc ='someId'; insert testAccount; testAccount = [SELECT Id, Salesforce_ID__pc, Name FROM Account WHERE id =:testAccount.Id]; Investigation_Contact__c ic = new Investigation_contact__c(); // linking uc to test account ic.Client_Potential_name__c= testAccount.id; ic.Investigation__c ='0061C00000XZCW2'; Insert ic; // check that the trigger logic worked Investigation_Contact__c ic2 = [SELECT DupCheckID__c, Investigation_ID__c FROM Investigation_Contact__c WHERE Id =:ic.id]; System.assertEquals(ic2.DupCheckID__c, testAccount.Salesforce_ID__pc + '-'+ic2.Investigation_ID__c); } } Now this error. Time Started 5/24/2018 2:04 PM Class TestDupcheckID Method Name insertic Pass/Fail Fail Error Message System.DmlException: Insert failed. First exception on row 0; first error: FIELD_FILTER_VALIDATION_EXCEPTION, Value does not exist or does not match filter criteria.: [Client_Potential_Name__c] Stack Trace Class.TestDupcheckID.insertic: line 17, column 1
Cha YangCha Yang
[Client_Potential_Name__c] is the lookup field on the Investigation Contact object. From: Yang, Cha Sent: Thursday, May 24, 2018 2:08 PM To: 'reply' Subject: RE: (Salesforce Developers): New reply to your question. @IsTest public class TestDupcheckID { static testmethod void insertic() { Account testAccount = new Account(); testAccount.Name = 'testAccount'; //testAccount.Salesforce_ID__pc ='someId'; insert testAccount; testAccount = [SELECT Id, Salesforce_ID__pc, Name FROM Account WHERE id =:testAccount.Id]; Investigation_Contact__c ic = new Investigation_contact__c(); // linking uc to test account ic.Client_Potential_name__c= testAccount.id; ic.Investigation__c ='0061C00000XZCW2'; Insert ic; // check that the trigger logic worked Investigation_Contact__c ic2 = [SELECT DupCheckID__c, Investigation_ID__c FROM Investigation_Contact__c WHERE Id =:ic.id]; System.assertEquals(ic2.DupCheckID__c, testAccount.Salesforce_ID__pc + '-'+ic2.Investigation_ID__c); } } Now this error. Time Started 5/24/2018 2:04 PM Class TestDupcheckID Method Name insertic Pass/Fail Fail Error Message System.DmlException: Insert failed. First exception on row 0; first error: FIELD_FILTER_VALIDATION_EXCEPTION, Value does not exist or does not match filter criteria.: [Client_Potential_Name__c] Stack Trace Class.TestDupcheckID.insertic: line 17, column 1
Cha YangCha Yang
Finally got it to work. @IsTest public class TestDupcheckID { static testmethod void insertic() { Account testAccount = new Account(); testAccount.FirstName = 'Apple'; testAccount.lastName = 'iPhone'; //testAccount.Salesforce_ID__pc ='someId'; insert testAccount; testAccount = [SELECT Id, Salesforce_ID__pc, Name FROM Account WHERE id =:testAccount.Id]; Investigation_Contact__c ic = new Investigation_contact__c(); // linking uc to test account ic.Client_Potential_name__c= testAccount.id; ic.Investigation__c ='0061C00000XZCW2'; Insert ic; // check that the trigger logic worked Investigation_Contact__c ic2 = [SELECT DupCheckID__c, Investigation_ID__c FROM Investigation_Contact__c WHERE Id =:ic.id]; System.assertEquals(ic2.DupCheckID__c, testAccount.Salesforce_ID__pc + '-'+ic2.Investigation_ID__c); } }
Cha YangCha Yang
I thought it was over but not quick yet. When I update record via dataloader it error out: ERROR: ccDupCheckID: System.LimitException: Too many SOQL queries: 101 It works fine if I changed the batch to 100. Is there any workaround?
Steven NsubugaSteven Nsubuga
You misplaced the closing brace of the for loop. See updated trigger below.
trigger DupCheckID on Investigation_Contact__c (Before insert, before update) {
Set<Id> accountIds = new Set<Id>();
    for (Investigation_Contact__c ic : trigger.new){
        accountIds.add(ic.Client_Potential_Name__c);
	}
    Map<Id, Account> accountsMap = new Map<Id, Account> ([SELECT Id, Salesforce_ID__pc FROM Account where Id IN :accountIds]);

	Account icAccount  = accountsMap.get(ic.Client_Potential_Name__c);
	ic.DupCheckID__c = icAccount.Salesforce_ID__pc + '-'+ic.Investigation_ID__c;
}

 
Cha YangCha Yang
I got Compile Error. [cid:image001.png@01D3F9AD.4FA99A90]
Steven NsubugaSteven Nsubuga
My fault, here is the right trigger.
trigger DupCheckID on Investigation_Contact__c (Before insert, before update) {
	Set<Id> accountIds = new Set<Id>();
    for (Investigation_Contact__c ic : trigger.new){
        accountIds.add(ic.Client_Potential_Name__c);
	}
	
    Map<Id, Account> accountsMap = new Map<Id, Account> ([SELECT Id, Salesforce_ID__pc FROM Account where Id IN :accountIds]);
	for (Investigation_Contact__c ic : trigger.new){
		Account icAccount  = accountsMap.get(ic.Client_Potential_Name__c);
        ic.DupCheckID__c = icAccount.Salesforce_ID__pc + '-'+ic.Investigation_ID__c;
	}
}

 
This was selected as the best answer
Cha YangCha Yang
Issue fixed. Thanks so much!!