Monday 15 February 2016

Manual Sharing for Partner community using Apex



Salesforce

This topic is related to the sharing in communities. I need to setup the sharing on partner communities and there is no point and click option for sharing any object for partner communities object. First you should setup the communities in the ORG than go to the setupàcommunity settings and add a new sharing sets, see the below image 1


In above red highlighted box, you would not able to see the partner community profiles, so this is really a main point for which I used manual sharing by apex code. We can add a sharing rule for customer community user license. So if we are making customer community than this would be pretty mush simple to configure. Now moving forward, my task was to share a newly created case in the community only for same account, Means let’s say if I have created a Case1 and adding this case against any contact, obviously Account is there for that contact, so this Case1 should be share among all those community user which have that same Account Id and if another account user login to the community than that Case1 should not be seen for that User. So this is the user case which I need to follow here. So I have made a trigger on case and on that trigger, newly created case should be share with all those user which are of same account. Please keep this in mind if let’s say we update that case and link that case with another Account than we must un-share the case with previous users and that case would be share with new community user. So, I have just written a sample here which is perfect for the created case if we change the Account on updating than few more lines needs to be added here, please see the below trigger code here.

trigger trShareCase on Case (after insert, after update) 
{
    map<Id,Id> mCase_Account = new map<Id,Id>();
    map<Id,Id> mUser_Account = new map<Id,Id>();
    map<Id,List<Id>> mCase1 = new map<Id,List<Id>>();
    Map<Id,List<User>> mUser = new Map<Id,List<User>>();
            for(Case cs:trigger.new)
            {
                        if (cs.accountid != null)
                        {
                                    mCase_Account.put(cs.Id,cs.accountid);
                        }
            }

            for (user u : [select Id,AccountId from user where IsActive= true And AccountId in :mCase_Account.values()])
            {
              mUser_Account.put(u.Id,u.AccountId);
            }
           
            List<Id> liUser ;
            for(Id caseId: mCase_Account.keyset())
            {
                         for(Id userId: mUser_Account.keyset())
                         {
                                    if(mCase_Account.get(caseId) == mUser_Account.get(userId))
                                    {
                                        if (!mCase1.containsKey(caseId))
                                                {
                                                    liUser = new List<Id>();
                                                    liUser.add(userId);
                                                            mCase1.put(caseId,liUser);
                                                }
                                                else
                                                {
                                                    liUser = new List<Id>();
                                                            liUser = mCase1.get(caseId);
                                                            liUser.add(userId);
                                                            mCase1.put(caseId,liUser);
                                                }
                                    }
                         }

            }
            List<CaseShare> csShareList = new List<CaseShare>();
            Id TestId ;
            for(Case cs:trigger.new)
            {
              
               for (Id caseId: mCase1.keyset())
               {
                 if (cs.Id == caseId)
                         {
                            liUser = mCase1.get(caseId);
                                    for (Id UserId: liUser)
                                    {
                                                CaseShare csShare = new CaseShare();
                                                // Give Read write access to that user for this particular case record.
                                                csShare.CaseAccessLevel = 'Read';
                                                // Assign case Id of case record.
                                                csShare.CaseId = cs.id;
                                                // Assign user id to grant read write access to this particular case record.
                                                TestId = UserId;
                                                csShare.UserOrGroupId = TestId;
                                                //csShare.RowCause = Schema.Project__Share.RowCause.Manual;
                                                csShareList.add( csShare );
                                    }
                         
                         }

               }

              
            }
           
            insert csShareList;
}
In above code, first yellow highlighted code is showing a map which consist Case Id and Account Id, second green highlighted code showing map in which it is saving User Id and Account Id, and I used SOQL to fetched all those user which have Account Ids from first map value. In third gray highlighted code, it is than maintaining very important map. This map contains a signature of Case Id and List of user Ids. So I am using 2 for loops which actually maintain User list with single case, if the map do not contain any key than it would first add the value in the map with Case Id as key and List of User Id and in second if condition, if the same key exists than it is altering the map value against same key that is case id. Last but not least in the later part the case sharing object comes into play and adding the entries into the list having 1 to many relation means 1 case might contains one or multiple users.
The Community plus license also needs the same way of manual sharing but if you want to play the same game against customer community user license than go to setpàcommunity settings and define the sharing set and add the same rule means Case1 should be share against all those user which are under the umbrella of same Account, see below image for your help

So this is the case of adding any new case, let’s say if we are making any new partner community user than what should we do? Because we have earlier worked on Case object. So, for this we need to add a trigger on User as well but the important punch over here is that if we add a trigger on user and on that trigger if we are manually share the object like Case, so if User is added and then hit that trigger, it would give an exception of MIXED_DML_OPEARATION, reason being we are getting the exception because the same time we are using the System object that is user for DML operation and on the other way we are using non-system object which is CaseSharing object, so it would create an issue. So to handle this we should need some time difference between these 2 operation, so I have made a custom formula date time field in user and set the time 55 minutes before the created date. See below image


Why I added this field because I want to add a time base workflow and in time base workflow, it need minimum an hours to execute. I have also added a custom field in user object, a checkbox “Show in Community” , so if the workflow executes after 5 min than it would update this checkbox field and on update the user record than the trigger would execute on user. So the purpose of this so to give some time elapse between user object creation and case sharing object. See the below time dependent workflow snapshot.



The rule criteria is mentioned in red box which show that if the custom field is not checked than it would enter into the workflow. Secondly, the red box showing 1 hour after the custom date time formula field, we do not have any option to execute the workflow under an hour. Third one the field update, it would mark check on the custom checkbox field. Immediately if it mark the checkbox than it would hit the trigger and trigger will share the object with the newly created user. I am not writing the User trigger here as this trigger would be prettly kuch similar to the above trigger, only the difference would be that in this trigger, we should maintain the final map with User Id and list of case, the opposite logic to the above trigger, so happy coding guys J

6 comments:

  1. This is excellent information. It is amazing and wonderful to visit your site.Thanks for sharing this information,this is useful to me. I am reading your post from the beginning, it was so interesting to read & I feel thanks to you for posting such a good blog, keep updates regularly.
    Java Training in Chennai

    Java Training in Velachery

    Java Training in Tambaram

    Java Training in Porur

    Java Training in Omr

    Java Training in Annanagar


    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Nice Post! Your insight are very impressive and creative its very helpful.Thanks for sharing..
    Salesforce Online Training

    ReplyDelete