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

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;
}
  • 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? – Dan Wooding Apr 27 '17 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 – Santanu Boral Apr 27 '17 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. – Dan Wooding Apr 28 '17 at 13:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.