I have some fields in case object which are filling from web-to-case form.
when we submit the case form, if email is found in contacts associated contact and account will be auto populated.
My requirement is :
- I have to create new Account and its child contact if email is not in contacts
- I have to fill accountId,contactId fields with above data in case record.
For this I tried in two ways,
1. I have written a before insert trigger on Case and tried to create account and it's child contact. Both account and contact are created, but accountId,ContactId are not filled in case.
2. I have written a schedule class which is scheduled after one minute of current time from after insert trigger. In that class I implemented the above logic and tried to update the case record. But I got Record is read-only error.
Please help me to achieve this.
Trigger:
trigger CaseTrigger on Case (after insert)
{
if(Trigger.isAfter && Trigger.isInsert)
{
CaseAutoFill ca = new CaseAutoFill(Trigger.New);
DateTime nextRun = system.now().addMinutes(1);
String cron = nextRun.second()+' '+nextRun.minute()+' '+nextRun.hour()+' ? '+nextRun.month()+' * '+nextRun.year();
String jobID = system.schedule('ca-'+system.now(), cron, ca);
}
}
Schedule class:
global class CaseAutoFill implements Schedulable
{
list<Case> newCases;
global CaseAutoFill(list<Case> newCases)
{
this.newCases = newCases;
}
global void execute(SchedulableContext SC)
{
system.debug('newCases..!'+newCases);
Set<String> accEmails = new Set<String>();
Set<String> contactEmails = new Set<String>();
for(Case c : newCases)
{
accEmails.add(c.PR_Email__c);
contactEmails.add(c.ContactEmail);
}
system.debug('accEmails..!'+accEmails);
system.debug('contactEmails..!'+contactEmails);
//Account map
list<Account> accounts = [select Id,PO_Email__c from Account where PO_Email__c IN: accEmails];
map<String,Account> accountMap = new map<String,Account>();
for(Account acc : accounts){
accountMap.put(acc.PO_Email__c,acc);
}
//Contact map
list<Contact> contacts = [select Id,Email from Contact where Email IN: contactEmails];
map<String,Contact> contactMap = new map<String,Contact>();
for(Contact con : contacts){
contactMap.put(con.Email,con);
}
//looping accounts
list<Account> newAccounts = new list<Account>();
for(Case c : newCases)
{
Account acc = new Account();
acc.Name = c.Name_of_Organization__c;
acc.PO_Email__c = c.PR_Email__c;
newAccounts.add(acc);
}
insert newAccounts;
for(Account acc : newAccounts){
accountMap.put(acc.PO_Email__c,acc);
}
//looping contacts
list<Contact> newContacts = new list<Contact>();
for(Case c : newCases)
{
if(!contactMap.containsKey(c.ContactEmail))
{
Contact con = new Contact();
if(accountMap.containsKey(c.PR_Email__c)){
con.accountId = accountMap.get(c.PR_Email__c).Id;
}
con.Email = c.ContactEmail;
con.lastName = c.User_First_and_Last_Name__c;
con.firstName = c.User_First_and_Last_Name__c;
con.MobilePhone = '1234568790';
con.Phone = '1234568790';
newContacts.add(con);
}
}
insert newContacts;
for(Contact con : newContacts){
contactMap.put(con.Email,con);
}
system.debug('accountMap..!'+accountMap);
system.debug('contactMap..!'+contactMap);
//final verification
for(Case c : newCases)
{
if(String.isBlank(c.AccountId) && accountMap.containsKey(c.PR_Email__c))
{
c.AccountId = accountMap.get(c.PR_Email__c).Id;
}
if(String.isBlank(c.contactId) && contactMap.containsKey(c.ContactEmail))
{
c.contactId = contactMap.get(c.ContactEmail).Id;
}
}
system.debug('newCases..!'+newCases);
update newCases;
}
}
Best Answer
Record is read-only in
after trigger
context.So, you need to fetch case records again and update those cases.
Here is the approach:
or
this way, without SOQL query