0

I have a situation whereby I do not want non admin users to be able to delete Activity History records. What I currently have is a before delete trigger that queries all activity history records for the give object i.e. Case and if the Activity/Event is part of the activity history, raise an exception. The bolow code for me doesnt seem effective as one of the errors I get is:

There is an implementation restriction on ActivityHistories. When you query this relationship, security evaluation is implemented for users who don't have administrator permissions, and you must specify a LIMIT with a maximum of 500

What would be the best practice for this, effectively this means when you create an Activity or Event on a given record, you wont be able to delete it, which is what business wants

EventBeforeDeleteTriggerHandler:

/**
* Before Delete Trigger handler class for Events
*
* @author   Nelson Chisoko
* @created  2019/08/22
*/
public class EventBeforeDeleteTriggerHandler extends TriggerHandlerBase {


    public override void mainEntry(TriggerParameters tp) {

        //Prevent deletion of events if not System Administrator profile
        checkDeleteEvent((Map<Id, Event>)tp.oldMap);


    }

    private static void checkDeleteEvent(Map<Id, Event> eventsMap) {

        if (UserInfo.getProfileId() != Sys_Utilities_General.getUserProfileId('System Administrator')) {

            Set<Id> opportunityIds = new Set<Id>();
            Set<Id> caseIds = new Set<Id>();

            for (Event e : eventsMap.values()) {

                if (e.WhatId != null) {

                    if (e.WhatId.getSobjectType().getDescribe().getName() == 'Opportunity')
                        opportunityIds.add(e.WhatId);

                    else if (e.WhatId.getSobjectType().getDescribe().getName() == 'Case')
                        caseIds.add(e.WhatId);
                }

            }

            Set<Id> activityHistories = new Set<Id>();

            if (!opportunityIds.isEmpty()) {

                List<Opportunity> opportunities = [SELECT (SELECT Id, ActivityDate, Description FROM ActivityHistories) FROM Opportunity WHERE Id IN : opportunityIds];

                for (Opportunity o : opportunities)
                    for (ActivityHistory a : o.ActivityHistories)
                        activityHistories.add(a.Id);

            }

            if (!caseIds.isEmpty()) {

                List<Case> cases = [SELECT (SELECT Id, ActivityDate, Description FROM ActivityHistories) FROM Case WHERE Id IN : caseIds];
                System.debug(cases);
                for (Case c : cases) {
                    System.debug(c);
                    for (ActivityHistory a : c.ActivityHistories) {
                        activityHistories.add(a.Id);
                    }
                }

            }

            System.debug(activityHistories);
            for (Event e : eventsMap.values()) {

                if (activityHistories.contains(e.Id))
                    e.addError('You have insufficient rights to delete ActivityHistory records');

            }

        }

    }

}

1 Answer 1

2

Query only the records you want and apply the limit, as described in the error:

List<Opportunity> opportunities = [
    SELECT (SELECT Id FROM ActivityHistories WHERE Id = :eventsMap.values() LIMIT 500) 
    FROM Opportunity WHERE Id IN :opportunityIds];

...

List<Case> cases = [
    SELECT (SELECT Id FROM ActivityHistories WHERE Id = ::eventsMap.values() LIMIT 500) 
    FROM Case WHERE Id IN : caseIds];

This will also drastically improve performance for processing records with lots of activity history.


As an aside, you can optimize your code, too:

for (Event e : eventsMap.values()) {
    sObjectType whatType = e.WhatId == null? null: e.WhatId.getSObjectType();
    if(whatType == Opportunity.sObjectType) {
        opportunityIds.add(e.WhatId);
    } else if(whatType == Case.sObjecttype) {
        caseIds.add(e.WhatId);
    }
}
0

You must log in to answer this question.

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