function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Ramanjot SidhuRamanjot Sidhu 

Counting Closed Activities

Hi, using a trigger I found online I tweeked to also count closed activities. I am a noob at apex, and  need this trigger to only count closed activities if the due date is within the current calender year.  Please let me know your thoughts. Thanks

 

Below is my Class:

public class ClosedActivityUtils {
 
//config
String fieldToUpdate = 'Closed_Activity_Count__c'; //this field must be added to each object we're updating

//state
set<id> accountIds;
set<id> contactIds;
set<id> opportunityIds;
set<id> leadIds;

public ClosedActivityUtils(sObject[] records) {
accountIds = new set<id>();
contactIds = new set<id>();
opportunityIds = new set<id>();
leadIds = new set<id>();
captureWhatAndWhoIds(records);
addAccountIdsFromRlatedObjects();
}

public void updateAccountActivityHistory() {
if(accountIds.size() == 0) return;
updateActivityHistory('Account','WhatId', getStringFromIdSet(accountIds));
}
public void updateContactActivityHistory() {
if(contactIds.size() == 0) return;
updateActivityHistory('Contact','WhoId', getStringFromIdSet(contactIds));
}
public void updateOpportunityActivityHistory() {
if(opportunityIds.size() == 0) return;
updateActivityHistory('Opportunity','WhatId', getStringFromIdSet(opportunityIds));
}
public void updateLeadActivityHistory() {
if(leadIds.size() == 0) return;
updateActivityHistory('Lead','WhoId', getStringFromIdSet(leadIds));
}
private void updateActivityHistory(String objToUpdate, String queryFld, String updateIds) 
string strQuery = 'SELECT Id, (SELECT Id FROM ActivityHistories) FROM ' + objToUpdate + ' WHERE Id IN (' + updateIds + ')'; 
System.debug(strQuery); sObject[] 
sobjects = new list<sobject>(); 
for(sObject so : database.query(strQuery)) {
ActivityHistory[] oActivities = so.getSObjects('ActivityHistories'); 
Integer closedActivityCount = oActivities == null ? 0 : oActivities.size(); 
sObject obj = createObject(objToUpdate, so.Id); 
obj.put(fieldToUpdate, closedActivityCount); 
sobjects.add(obj); 
system.debug('ActivityHistoryCount: ' + closedActivityCount);
}
update sobjects;
}}

private void captureWhatAndWhoIds(sObject[] objects) {
for(sObject o : objects) {
Id whatId = (Id)o.get('WhatId');
Id whoId = (Id)o.get('WhoId');
if(whatId != null) {
String objectName = getObjectNameFromId(whatId);
if(objectName == 'account') accountIds.add(whatId);
if(objectName == 'opportunity') opportunityIds.add(whatId);
}
if(whoId != null) {
String objectName = getObjectNameFromId(whoId);
if(objectName == 'contact') contactIds.add(whoId);
if(objectName == 'lead') leadIds.add(whoId);
}
}
}

private void addAccountIdsFromRlatedObjects() {
for(Opportunity o : [SELECT AccountId FROM Opportunity WHERE Id IN :opportunityIds]) accountIds.add(o.AccountId);
for(Contact c : [SELECT AccountId FROM Contact WHERE Id IN :contactIds]) accountIds.add(c.AccountId);
}

private String getObjectNameFromId(Id objId) {
String preFix = String.valueOf(objId).left(3).toLowercase();
if(prefix == '001') return 'account';
if(prefix == '003') return 'contact';
if(prefix == '006') return 'opportunity';
if(prefix == '00q') return 'lead';
return '';
}

private String getStringFromIdSet(set<id> idSet) {
string idString = '';
for(Id i : idSet) idString+= '\'' + i + '\',';
return idString == '' ? idString : idString.left(idString.length()-1); //If idString contains some ids we want to ensure we strip out the last comma
}

//The main part of the method below was taken from //Taken fromhttp://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dynamic_dml.htm
//However we've modified this to accept an object id
private sObject createObject(String typeName, Id objId) {
Schema.SObjectType targetType = Schema.getGlobalDescribe().get(typeName);
if (targetType == null) {
// throw an exception
}

// Instantiate an sObject with the type passed in as an argument
//  at run time.
return targetType.newSObject(objId);
}

}


Task Trigger:
trigger ClosedTaskTrigger on Task (after insert, after update, after delete, after undelete) {
 
    sObject[] triggerRecords;
    if(!trigger.isDelete) triggerRecords = trigger.new;
    else triggerRecords = trigger.old;
 
    //Update Closed Activity Count
    ClosedActivityUtils au = new ClosedActivityUtils(triggerRecords);
    au.updateAccountActivityHistory();
    au.updateContactActivityHistory();
    au.updateLeadActivityHistory();
    au.updateOpportunityActivityHistory();
 
}

Closed Event Trigger:
trigger ClosedEventTrigger on Event (after insert, after update, after delete, after undelete) {
 
    sObject[] triggerRecords;
    if(!trigger.isDelete) triggerRecords = trigger.new;
    else triggerRecords = trigger.old;
 
    //Update Closed Activity Count
    ClosedActivityUtils au = new ClosedActivityUtils(triggerRecords);
    au.updateAccountActivityHistory();
    au.updateContactActivityHistory();
    au.updateLeadActivityHistory();
    au.updateOpportunityActivityHistory();
 
}

Best Answer chosen by Ramanjot Sidhu
bob_buzzardbob_buzzard
You should be able to do this via an additional where clause on your subquery. There is a LAST_YEAR date literal that you can use in SOQL queries:
 
string strQuery = 'SELECT Id, (SELECT Id FROM ActivityHistories WHERE ActivityDate>LAST_YEAR) FROM ' + objToUpdate + ' WHERE Id IN (' + updateIds + ')';