When a field is populated on an Opportunity record I want to alert a team of users of that. I don't want to spam them with emails so I thought to make a chatter group and then post chatter feed items with the details that they can review whenever.
I wrote this method and it seems to work posting the link to the Opportunity:
public static void competitionAlert(Map<Id, Opportunity> newMap, Map<Id, Opportunity> oldMap)
{
// Find the Chatter group Id
CollaborationGroup chatterGroup = [ SELECT Id, Name
FROM CollaborationGroup
WHERE Name = 'Competitive Intelligence'];
List<FeedItem> feedPost = new List<FeedItem>();
// loop the Opportunities to see if the compeitition field changed.
for (Opportunity oppy : newMap.values())
{
if(
oppy.Competition__c != oldMap.get(oppy.Id).Competition__c &&
oppy.Competition__c != null
)
{
// create a chatter feed post alerting the team
FeedItem fpost = new FeedItem();
fpost.ParentId = chatterGroup.Id;
fpost.LinkURL = URL.getSalesforceBaseUrl().toExternalForm() + '/' +oppy.Id;
fpost.Title = oppy.Name;
fpost.Body = 'An Opportunity was flagged as "Closed Lost" to ' + oppy.Competition__c + ' please review.';
feedPost.add(fpost);
}
}
insert feedPost;
}
The challenge is that the chatter group needs to be private, so when I lock the group down I get errors when a user who does not have access triggers the method and tries to create the post.
Is there a way to post into groups without having access to the group or a way to post as a user who does?
FINAL Solution:
Handler Class:
public static List<Opportunity> competitionAlertFilter(Map<Id, Opportunity> newMap, Map<Id, Opportunity> oldMap)
{
List<Opportunity> oppy = new List<Opportunity>();
// loop the Opportunities to see if the compeitition field changed.
for (Opportunity o : newMap.values())
{
if(
o.Competition__c != oldMap.get(o.Id).Competition__c &&
o.Competition__c != null
)
{
oppy.add(o);
}
}
return oppy;
}
public static void competitionAlert(List<Opportunity> chatFilter)
{
ChatterPosts.createCompetitiveIntelligencePost(chatFilter);
}
}
Extender Class
public without sharing class ChatterPosts {
public static void createCompetitiveIntelligencePost(List<Opportunity> chatFilter)
{
// Find the Chatter group Id
CollaborationGroup chatterGroup = [ SELECT Id, Name
FROM CollaborationGroup
WHERE Name = 'Competitive Intelligence'];
List<FeedItem> feedPost = new List<FeedItem>();
// loop the Opportunities to see if the compeitition field changed.
for (Opportunity oppy : chatfilter)
{
// create a chatter feed post alerting the team
FeedItem fpost = new FeedItem();
fpost.ParentId = chatterGroup.Id;
fpost.LinkURL = URL.getSalesforceBaseUrl().toExternalForm() + '/' +oppy.Id;
fpost.Title = oppy.Name;
fpost.Body = 'An Opportunity was flagged as "Closed Lost" to ' + oppy.Competition__c + ' please review.';
feedPost.add(fpost);
}
insert feedPost;
}
}
I'm excited about this methodology because for future use cases I can pass whatever data to the ChatterPosts class and not run into this issue again.