[SalesForce] Post into chatter group without access to the group

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.

Best Answer

It's a very common problem. I have already faced the same issue.the solution is to move the same functionality in the trigger. As the trigger run on system mode,then there will be no issue regarding access.Then error what you get will be resolve. I have tried and it is working fine for me.

Related Topic