1

The below trigger is working fine on insert and update operations but on delete it gives me the below error. can you please help me. i guess im trying to update the status__c field to inactive once contact is deleted but getting below error as in Trigger.old the values are read only can you please help me overcome this error and update the field on delete.Many Thanks

Validation Errors While Saving Record(s) There were custom validation error(s) encountered while saving the affected record(s). The first validation error encountered was "Apex trigger Contactcallout caused an unexpected exception, contact your administrator: Contactcallout: execution of BeforeDelete caused by: System.FinalException: Record is read-only: Trigger.Contactcallout: line 11, column 1".

Click here to return to the previous page.

Trigger:-

trigger Contactcallout on Contact (after insert, after update, before delete) {
Id RecordType1= [SELECT Id FROM RecordType WHERE SOBJECTTYPE=:'Contact' AND DeveloperName=:'Commercial'].Id;
Map<Id, String> m = new Map<Id, String>();
list<Contact> validContacts = new list<Contact>();
set<ID> accIds = new set<ID>();
if(Trigger.isDelete)
    {
        for (contact c : Trigger.old) 
        {
            if(c.RecordTypeId == RecordType1 && c.Registered_on_ITV_Media__c == TRUE)    //012D0000000BaFA
            c.Status__c='Inactive';
            {
                validContacts.add(c);
                accIds.add(c.accountid);
            }   
        }
    }
    else
    {
for (contact c : Trigger.new) {
    if(c.RecordTypeId == RecordType1 && c.Registered_on_ITV_Media__c == TRUE){
    if(Trigger.isUpdate){
        contact old = Trigger.oldMap.get(c.Id);
        if (c.Email != old.Email||c.FirstName!=old.FirstName||c.LastName!=old.LastName||c.phone!=old.phone||c.Title__c!=old.Title__c||c.status__c!=old.status__c||c.AccountID!=old.AccountID||c.Registered_on_ITV_Media__c == TRUE)
    //  if (c.Email != old.Email||c.FirstName!=old.FirstName||c.LastName!=old.LastName||c.phone!=old.phone||c.Title__c!=old.Title__c||c.status__c!=old.status__c||c.AccountID!=old.AccountID)
         {
             validContacts.add(c);
                accIds.add(c.accountid);
         }
         }else{
         validContacts.add(c);
                accIds.add(c.accountid);
                }
                }
         }   
}
map<ID, Account> accMap;
if(!accIds.IsEmpty()) // guard condition for SOQL
    accMap = new map<ID, Account>([select name from account where id in :accIds]);

for (contact c : validContacts) {
    Account acc = accMap.get(c.AccountID);
    string accName = acc == null ? null : acc.Name;
    WebServiceCallout.sendNotification(c.Id,c.Email,c.FirstName,c.LastName,c.phone,c.Title__c,accName,c.status__c);
              }
}

Many Thanks in advance Abraham

2 Answers 2

3

You can modify the values of the record before their final deletion in a Before Delete trigger event, but you need a separate DML statement for this. Example follows:

if(Trigger.isDelete) {
    Contact[] contacts = new Contact[0];
    for(Contact record: Trigger.old) {
        if(record.RecordTypeId == RecordType1 && record.Registered_on_ITV_Media__c) {
            contacts.add(new Contact(Id=record.Id, Status__c='Inactive'));
        }
    }
    update contacts;
}

Notice how I construct a new instance of the record using new Contact so it doesn't trigger the "record is read-only" error. Note that your before/after update logic will also be called, meaning the inactive status will be sent to your webservice automatically without handling this explicitly in your before delete trigger event (in other words, don't call the web service explicitly in your delete trigger event).

3
  • Works Perfectly... just as i wanted... Thank u soo much Sfdcfox....
    – Abraham
    Nov 4, 2015 at 6:15
  • if we need to keep the records in the system, Do we need to restore the records from recycle bin in the trigger itself? Jun 21, 2021 at 3:20
  • @Hariprasath It's been a while since I've tried, but yes, you should be able to restore the record in an after delete record.
    – sfdcfox
    Jun 21, 2021 at 4:25
2

You cannot modify the values of trigger.old

if(Trigger.isDelete)
    {
        for (contact c : Trigger.old) 
        {
            if(c.RecordTypeId == RecordType1 && c.Registered_on_ITV_Media__c == TRUE)
            c.Status__c='Inactive';

Besides, if the record is being deleted, why would you want to modify it?

Suggested solution?

Make the users change the status to Inactive before they can delete it

if(Trigger.isDelete)
    {
        for (contact c : Trigger.old) 
        {
            if(c.RecordTypeId == RecordType1 && c.Registered_on_ITV_Media__c == TRUE)    //012D0000000BaFA
            if(c.Status__c !='Inactive';
            {
                 c.addError('Only Inactive Records can be deleted');
            }   
        }
    }
5
  • HI Eric.. I am sending a notification to an external webservice upon delete action so once the contact is deleted i want the status to change to inactive and then im sending the some fields to an external system...This solution is fine for single records but if delete is done in bulk it would cause issues right? what do u think? Many Thanks.
    – Abraham
    Nov 3, 2015 at 17:05
  • 1
    @Abraham - You CANNOT change the field value in trigger.old. Period. What is the value of changing the status? If the record is deleted it is deleted. Unless the external service is querying using ALL ROWS they cannot query for the record. Rethink your solution knowing that you CANNOT change the values in a delete trigger
    – Eric
    Nov 3, 2015 at 17:07
  • HI Eric..Its like upon delete of contact in salesforce only if the status is "inactive" it will delete the same contact in the external database system by sending a notification as contact status="inactive" both are in a sync.. That i why i am trying to do this..Many Thanks
    – Abraham
    Nov 3, 2015 at 17:14
  • Is there any other way this can be done..
    – Abraham
    Nov 3, 2015 at 17:22
  • @Abraham A simple recursive DML update will solve your problem. I've provided an example for you.
    – sfdcfox
    Nov 3, 2015 at 17:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .