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

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).

  • Works Perfectly... just as i wanted... Thank u soo much Sfdcfox.... – Abraham Nov 4 '15 at 6:15
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');
            }   
        }
    }
  • 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 '15 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 '15 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 '15 at 17:14
  • Is there any other way this can be done.. – Abraham Nov 3 '15 at 17:22
  • @Abraham A simple recursive DML update will solve your problem. I've provided an example for you. – sfdcfox Nov 3 '15 at 17:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.