function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
JThomasJThomas 

Custom Object Sharing Rules

I have a custom object for placing orders that has a lookup to Account.  I want to expose these in a customer portal, so the customers can track the status of their orders.  The orders are entered by sales people (not the customer) and therefore are owned by people higher in the role heirarchy then the customers.  I need to create a sharing rule on the order object to allow sharing (read only) with the customer's User role if the associated account is the customer's account.  I see that I can go in and set a sharing rule on each record, but that seems very time consuming to manually set that for every new record.  Does anyone know of a good way to do this?  I'm guessing I'm going to use a trigger to add a record to the objects sharing table everytime an object is created.  Does this sound about right?  Does anyone have sample code to do this?

 

Thanks.

Best Answer chosen by Admin (Salesforce Developers) 
Starz26Starz26

here is an example i wrote for an object with a lookup to opportunity to allow access to the opportunity owner

 

the record creator sharing I use so anyone can submit the record (they may not be the owner after triggers. this access is removed at a later time using batch apex

 

the rowcause in this case is a custom apex sharing reason for the object

 

Public Static Void ShareOnCreate(Pre_Sales_Activity__c[] lPSA, Map<ID, Opportunity> mOpp){

        Pre_Sales_Activity__share[] psaShare = New Pre_Sales_Activity__share[]{};

        for(Pre_Sales_Activity__c oPSA : lPSA){

            //Record Creator Sharing
            //Used for temporary access to prevent errors
            //When the submitter is NOT the opportunity owner
            psaShare.add(New Pre_Sales_Activity__share(
                UserOrGroupID = oPSA.createdByID,
                ParentID = oPSA.ID,
                AccessLevel = 'Read',
                RowCause = 'Creator__c'
                )
            );
    
            //Opportunity Owner Sharing
            psaShare.add(New Pre_Sales_Activity__share(
                UserOrGroupID = mOpp.get(oPSA.Opportunity__c).OwnerID,
                ParentID = oPSA.ID,
                AccessLevel = 'Read',
                RowCause = 'Opportunity_Owner__c'
                )
            );
        }
            
            
            
           if(psaShare.size() > 0){
                system.debug(psaShare);
                insert psaShare;
           }
            
    }

}

All Answers

Starz26Starz26

here is an example i wrote for an object with a lookup to opportunity to allow access to the opportunity owner

 

the record creator sharing I use so anyone can submit the record (they may not be the owner after triggers. this access is removed at a later time using batch apex

 

the rowcause in this case is a custom apex sharing reason for the object

 

Public Static Void ShareOnCreate(Pre_Sales_Activity__c[] lPSA, Map<ID, Opportunity> mOpp){

        Pre_Sales_Activity__share[] psaShare = New Pre_Sales_Activity__share[]{};

        for(Pre_Sales_Activity__c oPSA : lPSA){

            //Record Creator Sharing
            //Used for temporary access to prevent errors
            //When the submitter is NOT the opportunity owner
            psaShare.add(New Pre_Sales_Activity__share(
                UserOrGroupID = oPSA.createdByID,
                ParentID = oPSA.ID,
                AccessLevel = 'Read',
                RowCause = 'Creator__c'
                )
            );
    
            //Opportunity Owner Sharing
            psaShare.add(New Pre_Sales_Activity__share(
                UserOrGroupID = mOpp.get(oPSA.Opportunity__c).OwnerID,
                ParentID = oPSA.ID,
                AccessLevel = 'Read',
                RowCause = 'Opportunity_Owner__c'
                )
            );
        }
            
            
            
           if(psaShare.size() > 0){
                system.debug(psaShare);
                insert psaShare;
           }
            
    }

}
This was selected as the best answer
JThomasJThomas

Thanks for the information Starz26.  I'm trying to create  a sharing record to share a Service_Order__c record with a role.  I've read  that we can set the UserOrGroupId field to a role id, but when I do this, I get the following error:

 

Apex trigger ServiceOrderStageTransition caused an unexpected exception, contact your administrator: ServiceOrderStageTransition: execution of BeforeInsert caused by: System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, User/Group ID: id value of incorrect type: 00EW0000000LierMAC: [UserOrGroupId]: Class.ServiceOrderManager.TransitionStage: line 940, column 1

 

Here's my code:

 

            List<Service_Order__share> shares = new List<Service_Order__share>();
            for (UserRole role : roles) {
                for (Service_Order__c so : soMap.keySet()) {
                    if (so.Account__c == role.PortalAccountId) {
                        shares.add(new Service_Order__share(
                            UserOrGroupID = role.Id,
                            ParentID = so.Id,
                            AccessLevel = 'Read',
                            RowCause = 'Manual')
                        );
                    }
                }
            }
            if (!shares.isEmpty()) {
                insert shares;
            }


Any idea why I can't do this?  I found this on developerforce that says I should be able to do this:

 

http://wiki.developerforce.com/page/Using_Apex_Managed_Sharing_to_Create_Custom_Record_Sharing_Logic

JThomasJThomas

I've found the solution.  You can't set the role id directly on the share record.  You have to look up the group related to the role, then use that Id on the share record.