Use Case:
Write a trigger, to achieve the following:
- Create a new Opportunity whenever an account is created/updated for Industry – Agriculture.
- Opportunity should be set as below:
- Stage = ‘Prospecting’, Amount = $0, CloseDate = ’90 days from today’.
trigger AccountTrigger on Account (after insert, after update) {// Condition that the code should run only after account is insertedif(Trigger.isInsert && Trigger.isAfter) {List<Opportunity> listOfOpportunities = new List<Opportunity>();// we will use for loop to handle bulk insertionfor(Account acc : Trigger.new) {// If 'Industry' field on Account has the values as 'Agriculture', add new Opportunity in the list 'listOfOpportunities'if(acc.Industry == 'Agriculture') {listOfOpportunities.add(new Opportunity(Name = acc.Name+' Opp',AccountId = acc.Id,StageName = 'Prospecting',Amount = 0,CloseDate = System.today() + 90));}}// Insert 'listOfOpportunities' if the list is not emptyif(listOfOpportunities.isEmpty() == false) {insert listOfOpportunities;}}// Condition that the code should run only after account is updatedif(Trigger.isUpdate && Trigger.isAfter) {List<Opportunity> listOfOpportunities = new List<Opportunity>();// we will use for loop to handle bulk updationfor(Account acc : Trigger.new) {// Check if the new updated value is different from old in Industry field and is 'Agriculture'if(acc.Industry != Trigger.oldMap.get(acc.Id).Industry && acc.Industry == 'Agriculture') {listOfOpportunities.add(new Opportunity(Name = acc.Name+' Opp',AccountId = acc.Id,StageName = 'Prospecting',Amount = 0,CloseDate = System.today() + 90));}}// Insert 'listOfOpportunities' if the list is not emptyif(listOfOpportunities.isEmpty() == false) {insert listOfOpportunities;}}}
Test Class:
Positive Scenario – We will insert/update an account with Industry as ‘Agriculture’ and then verify that opportunity should be created.
Negative Scenario – We will insert/update an account with Industry other than ‘Agriculture’ and then verify that opportunity should not be created.
@isTestprivate class AccountTriggerTest {// Validate the positive test scenario for insertion// Insert an account which has the Industry as 'Agriculture'// Assert that Opportunity should be created// Assert the values in Opportunity fields.@isTeststatic void test_afterInsert_positive() {Account newAcc = new Account(Name='TestAccount', Industry='Agriculture');Test.startTest();insert newAcc;Test.stopTest();List<Opportunity> insertedOpp = [Select Id, Account.Name, CloseDate, AmountFrom Opportunity Where AccountId = :newAcc.Id];System.assertEquals(1, insertedOpp.size(), 'Only 1 opportunity should be inserted for the Account');System.assertEquals(newAcc.Name, insertedOpp[0].Account.Name, 'Inserted Opportunity does not have the expected account.');System.assertEquals(System.today() + 90, insertedOpp[0].CloseDate, 'Close Date is not as expected.');System.assertEquals(0, insertedOpp[0].Amount, 'Amount in the inserted opportunity should be 0');}// Validate the negative test scenario for insertion// Insert an account which does not have the Industry as 'Agriculture'// Assert that Opportunity should not be created@isTeststatic void test_afterInsert_negative() {Account newAcc = new Account(Name='TestAccount', Industry='Biotechnology');Test.startTest();insert newAcc;Test.stopTest();List<Opportunity> insertedOpp = [Select Id, Account.Name, CloseDate, AmountFrom Opportunity Where AccountId = :newAcc.Id];System.assertEquals(0, insertedOpp.size(), '0 opportunity should be inserted for the Account');}// Validate the positive test scenario for updation// Update an account which has the Industry as 'Agriculture'// Assert that Opportunity should be created// Assert the values in Opportunity fields.@isTeststatic void test_afterUpdate_positive() {Account newAcc = new Account(Name='TestAccount', Industry='Biotechnology');insert newAcc;// Check that there should not be any opportunity created for the above accountList<Opportunity> insertedOpp = [Select Id, Account.Name, CloseDate, AmountFrom Opportunity Where AccountId = :newAcc.Id];System.assertEquals(0, insertedOpp.size(), '0 opportunity should be inserted for the Account');// Update the account Industry to 'Agriculture' and assert that opportunity should be createdTest.startTest();newAcc.Industry = 'Agriculture';update newAcc;Test.stopTest();List<Opportunity> newInsertedOpp = [Select Id, Account.Name, CloseDate, AmountFrom Opportunity Where AccountId = :newAcc.Id];System.assertEquals(1, newInsertedOpp.size(), 'Only 1 opportunity should be inserted for the Account');System.assertEquals(newAcc.Name, newInsertedOpp[0].Account.Name, 'Inserted Opportunity does not have the expected account.');System.assertEquals(System.today() + 90, newInsertedOpp[0].CloseDate, 'Close Date is not as expected.');System.assertEquals(0, newInsertedOpp[0].Amount, 'Amount in the inserted opportunity should be 0');}// Validate the negative test scenario for updation// Update an account when the field Industry is not updated to 'Agriculture'// Assert that Opportunity should not be created@isTeststatic void test_afterUpdate_negative() {Account newAcc = new Account(Name='TestAccount', Industry='Biotechnology');insert newAcc;// Check that there should not be any opportunity created for the above accountList<Opportunity> insertedOpp = [Select Id, Account.Name, CloseDate, AmountFrom Opportunity Where AccountId = :newAcc.Id];System.assertEquals(0, insertedOpp.size(), '0 opportunity should be inserted for the Account');// Update the account Industry to 'Agriculture' and assert that opportunity should be createdTest.startTest();newAcc.Industry = 'Education';update newAcc;Test.stopTest();List<Opportunity> newInsertedOpp = [Select Id, Account.Name, CloseDate, AmountFrom Opportunity Where AccountId = :newAcc.Id];System.assertEquals(0, newInsertedOpp.size(), '0 opportunity should be inserted for the Account');}}
Code Coverage: 100%
Hi,
Thanks for sharing the Trigger code, It is much useful.
The code you have written for update is not right I guess, Without querying we can not update the corresponding child records.
I hope below code works for update Trigger:
if(Trigger.isAfter && Trigger.isUpdate){
set accIds = new Set();
for(Account ac:Trigger.New){
if(ac.Industry != Trigger.oldMap.get(ac.Id).Industry && ac.Industry == ‘Agriculture’){
accIds.add(ac.Id);
}
}
List oppList = [Select Id, Name, StageName, Amount, CloseDate, AccountId from Opportunity where AccountId IN:accIds];
List optList = new List();
for(Opportunity opp: oppList){
opp.StageName = ‘Prospecting’;
opp.Amount = 0;
opp.CloseDate = system.today()+90;
optList.add(opp);
}
if(!optList.isEmpty()){
update optList;
}
}
Please check and let me know if any correction is required here. Thank you
For more better code maintainability, created a helper class and called that class in the trigger. Something like this
trigger OppCreationTrigger on Account (after insert, after update) {
if (Trigger.isInsert) {
OppCreationTriggerHelper.createOpportunities(Trigger.new);
} else if (Trigger.isUpdate) {
List updatedAccounts = new List();
for (Account newAccount : Trigger.new) {
Account oldAccount = Trigger.oldMap.get(newAccount.Id);
if (newAccount.Industry != oldAccount.Industry && newAccount.Industry == ‘Agriculture’) {
updatedAccounts.add(newAccount);
}
}
if (!updatedAccounts.isEmpty()) {
OppCreationTriggerHelper.createOpportunities(updatedAccounts);
}
}
}
public class OpportunityTriggerHelper {
public static void createOpportunities(List accounts) {
List listOfOpps = new List();
for (Account a : accounts) {
if (a.Industry == ‘Agriculture’) {
listOfOpps.add(new Opportunity(
Name = a.Name + ‘ Opp’,
AccountId = a.Id,
StageName = ‘Prospecting’,
Amount = 0,
CloseDate = System.today() + 90
));
}
}
if (!listOfOpps.isEmpty()) {
insert listOfOpps;
}
}
}