1

I am working on an requirement to assign users to chatter groups when they are new or edited to meet a criteria. One part is looking for existing CollaborationGroupMembers to see if there is an existing group member as you cannot insert members that already exist.

The problem is I cannot figure out how to return records and then send only the ids for the ones that do not exist to the method to create the member record.

I have this bit that works for one group at a time but with my expected 3 groups it errors in the future method if the user is already in one of the group.

First error: Insert failed. First exception on row 1; first error: DUPLICATE_VALUE, User is already a Member of this group.: [MemberId]

public static void matchExisting(Set<Id> userIds)
{
    // Find the Chatter group Ids from the names of the custom setting "Chatter Auto Follow"
    List<CollaborationGroup> chatterGroups = [SELECT Id 
                                              FROM CollaborationGroup 
                                              WHERE Name in :Chatter_Auto_Follow__c.getall().keySet()];

    // Query for existing chatter group records
    List<CollaborationGroupMember> cGMember = [SELECT   Id, 
                                                        MemberId,
                                                        CollaborationGroupId
                                               FROM     CollaborationGroupMember 
                                               WHERE    MemberId IN :userIds AND 
                                                        CollaborationGroupId IN :chatterGroups];

    System.debug('member size is:: ' + cGMember.size());

    if(cGMember.size() == 0)
    {
        addToGroups(userIds);
    }
}

EDIT:

Once I have a list of users to add to the group then I have this method to do the work of adding the group:

@future
public static void addToGroups(Set<Id> userIds)
{
    // The users that will be added to the group
    List<User> users = [SELECT id, Username FROM User WHERE id in :userIds];

    // Find the Chatter group Ids from the names of the custom setting "Chatter Auto Follow"
    List<CollaborationGroup> chatterGroups = [SELECT Id, Name 
                                              FROM CollaborationGroup 
                                              WHERE Name in :Chatter_Auto_Follow__c.getall().keySet()];

    // Get Chatter values
    List<Chatter_Auto_Follow__c> settings = [SELECT Name, Frequency__c FROM Chatter_Auto_Follow__c];

    // Create blank lists for inserting new records
    List<CollaborationGroupMember> chatterGroupMembers = new List<CollaborationGroupMember>();
    List<FeedItem> feedPosts = new List<FeedItem>();

    // loop the users that have been created
    for (User u : users)
    {
        // loop the custom setting records
        for(Chatter_Auto_Follow__c s : settings)
        {
            // loop the groups
            for (CollaborationGroup c : chatterGroups)
            {
                // add the user to the group
                CollaborationGroupMember cMember = new CollaborationGroupMember(
                    CollaborationGroupId = c.id,
                    MemberId = u.Id,
                    CollaborationRole = 'Standard',
                    NotificationFrequency = s.Frequency__c
                    );
                chatterGroupMembers.add(cMember);
            }
        }
    }

System.debug('chatter members to insert is:: ' + chatterGroupMembers);
insert chatterGroupMembers;

}
1

1 Answer 1

1

This is my logic. I have put the comments in the code. You can refactor the code based on your need.

First, create a map mapCollabrUser which will store collaborationGroupId and List of Members retrieved from the query.

Then, loop through userIds to find out for each Collaboration Group, user does not exist as a member in the group and if that satisfies then add the new user for that Collaboration Group.

public static void matchExisting(Set<Id> userIds)
{
    // Find the Chatter group Ids from the names of the custom setting "Chatter Auto Follow"
    List<CollaborationGroup> chatterGroups = [SELECT Id 
                                              FROM CollaborationGroup 
                                              WHERE Name in :Chatter_Auto_Follow__c.getall().keySet()];
    Set<Id> settingsChatterGroupId = new Set<Id>();
    for(CollaborationGroup cgroup:chatterGroups)
    {
        settingsChatterGroupId.add(cgroup.Id);
    }

    // Query for existing chatter group records
    List<CollaborationGroupMember> cGMember = [SELECT   Id, 
                                                        MemberId,
                                                        CollaborationGroupId
                                               FROM     CollaborationGroupMember 
                                               WHERE    MemberId IN :userIds AND 
                                                        CollaborationGroupId IN :chatterGroups];

    System.debug('member size is:: ' + cGMember.size());

    //this will store existing members belong to each group.
    Map<Id, Set<Id>> mapCollabrUser = new Map<Id, Set<Id>>();

    if(cGMember.size()>0)
    {
        //loop through the group members
        for(CollaborationGroupMember gm:cGMember)
        {
            if(mapCollabrUser.containsKey(gm.CollaborationGroupId))
            {
                Set<Id> lst = mapCollabrUser.get(gm.CollaborationGroupId);
                lst.add(gm.MemberId);
                mapCollabrUser.put(gm.CollaborationGroupId,lst);                      
            }
            else
            {
                Set<Id> lst = new Set<Id>();
                lst.add(gm.MemberId);
                mapCollabrUser.put(gm.CollaborationGroupId,lst);    
            }
        }
    }

    List<CollaborationGroupMember> chatterGroupMembers = new List<CollaborationGroupMember>();

    for(Id userId:userIds)
    {
        //loop through the custom settings value
        for(Id cgroupSettingId: settingsChatterGroupId)
        {
            //check if this is existing CollaborationGroup
            if(mapCollabrUser.containsKey(cgroupSettingId))
            {
                //loop through the user list and find out user does not exist.
                for(CollaborationGroupId grpId:mapCollabrUser.keySet())
                {
                    //retrieve existing user list
                    Set<Id> setExistingUser = mapCollabrUser.get(grpId);

                    //if user does not belong to userlist of the group then add him.
                    if(!setExistingUser.contains(userId))
                    {
                        CollaborationGroupMember cMember = new CollaborationGroupMember(
                            CollaborationGroupId = grpId,
                            MemberId = userId,
                            CollaborationRole = 'Standard',
                            NotificationFrequency = s.Frequency__c
                            );
                        chatterGroupMembers.add(cMember);
                    }

                }
            }
            else
            {
                //this is of new entries which doesn't exist in database and add the new user
                CollaborationGroupMember cMember = new CollaborationGroupMember(
                    CollaborationGroupId = cgroupSettingId,
                    MemberId = userId,
                    CollaborationRole = 'Standard',
                    NotificationFrequency = s.Frequency__c
                    );
                chatterGroupMembers.add(cMember);
            }
        }
    }
    insert chatterGroupMembers;
}
3
  • This is a lot to digest and with other things I've just had a bit to review. I get a compile error here: //this will store existing members belong to each group. Map<CollaborationGroupId, Set<Id>> mapCollabrUser = new Map<CollaborationGroupId, Set<Id>>(); The error is Invalid type collaborationgroupid It looks like we're setting the field in a map. Is there another way to do this? Commented Apr 27, 2017 at 20:02
  • That will be Map<Id, Set<Id>> mapCollabrUser = new Map<Id, Set<Id>>(); I have tried to build the logic this way, you can do at your own suitable way Commented Apr 27, 2017 at 20:25
  • So far, I have to refactor it a bit so I can separate it down to more manageable and make it @future for inserts but the updates works as I expect. Thanks a lot. Commented Apr 28, 2017 at 13:46

You must log in to answer this question.

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