6

I have code that creates CaseShare records for the case based on some criteria from another class.

The code that creates the CaseShare is called both on update and creation of the case. It works smoothly when the case is updated, but not when it's created. When attempting to debug my issue I got confused because the debug logs apparently showed that the records were being inserted. In fact, the debug logs show the same exact things for when the case is inserted (the DML doesn't work then) as when the case is updated (the DML does work then).

Here is the debug log for both when the case is created (DML doesn't work then) and when the case is updated (DML does work) line 55 is where my insert is happening:

14:14:54.417 (656673502)|USER_DEBUG|[55]|DEBUG|Value of csShareList: (CaseShare:{CaseAccessLevel=Edit, CaseId=500180000050HSWAA2, UserOrGroupId=005E0000004JDY4IAO}, CaseShare:{CaseAccessLevel=Edit, CaseId=500180000050HSWAA2, UserOrGroupId=005E0000000dNNWIA2}, CaseShare:{CaseAccessLevel=Edit, CaseId=500180000050HSWAA2, UserOrGroupId=005E0000000dBqjIAE}, CaseShare:{CaseAccessLevel=Edit, CaseId=500180000050HSWAA2, UserOrGroupId=005E0000005aSlXIAU}) 14:14:54.417 (656680026)|SYSTEM_METHOD_EXIT|[55]|System.debug(ANY) 14:14:54.417 (656682834)|STATEMENT_EXECUTE|[56] 14:14:54.417 (656754459)|DML_BEGIN|[56]|Op:Insert|Type:CaseShare|Rows:4 14:14:54.417 (656778446)|HEAP_ALLOCATE|[EXTERNAL]|Bytes:20 14:14:54.417 (717863949)|DML_END|[56]

Additionally, here's the code that does the insert:

if (!csShareList.isEmpty()){

            try{ 
                System.debug('Value of csShareList: ' + csShareList);
                insert csShareList;
            }
            catch(exception e){

                system.debug('Value of e.getMessage: ' + e.getMessage());

            }

        }

I checked to see whether or not the CaseShare has been inserted in three ways:

  1. By querying the CaseShares related to the case I just inserted.
  2. I pressed the "Sharing" button on the case record to view the case shares
  3. I tried to view the record as one of the users I attempted to share it with

On create, the query shows no CaseShare records with the users the code is sharing with, the sharing button also shows no CaseShare records with the users the code is sharing with, and the user gets insufficient access when trying to access the record.

However, upon edit, the query shows the CaseShare records with the users the code is sharing with, the sharing button also shows the CaseShare records with the users the code is sharing with, and the user gets is able to view the record when trying to access the it.

EDIT: Thanks to the answer given by the Salesforce Fox I started looking into the owner and now have an answer to the question. The owner in my case was a queue.

  • Change Exception to DmlException, you may be able to catch it.. Also you are debugging the List that your inserting, that doesn't mean it actually inserted, if you really want to see if they are inserted query it back out after you insert it – EricSSH Apr 11 '16 at 22:34
  • @EricSSH Thanks for the suggestion. I tried to catch the exception with DmlException but I still don't see the debug statement from the catch scope written to the Debug file. Also, I as part of my check (number 1) I query the caseShares to see if they were inserted. Additionally, in the summary of the debug log it reads Number of DML rows: 5 out of 10000 for create (1 record is from other code that happens on create). – Sam Kamensky Apr 12 '16 at 4:24
7

One of your share entries is failing to insert, causing the entire DML to go through the exception handler. Odds are, you're trying to insert a share for the case owner, which isn't allowed. Here's the POC I wrote that demonstrates this:

trigger Cases on Case (after insert, after update) {
    User testUser = [SELECT Id FROM User WHERE Name = 'test user'];
    CaseShare[] shares = new CaseShare[0];
    for(Case record: Trigger.new) {
        shares.add(new CaseShare(CaseId=record.id, UserOrGroupId=testUser.Id, CaseAccessLevel='edit'));
    }
    insert shares;
}

Throw this code into a developer edition or spare sandbox, and make sure you have a single user that is named 'Test User' (first name Test, last name User), and try to change the owner to this user, and you'll come across a rather <sarcasm>specific</sarcasm> exception:

System.DmlException: Insert failed. First exception on row 0; first error: INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY, insufficient access rights on cross-reference id: []

If you try manually assigning a share to the case owner, you get the usual, friendly error message:

Error: Cannot manually share to the record owner.

Personally, I'd go with simply allowing any partial update to succeed instead of using the harsh all-or-none mechanism:

Database.insert(csShareList, false);

Duplicate shares are acceptable, as insert operations on share records are actually automatically upserts instead (they update a matching existing row when possible).

  • @sfdcfox, thanks for the input! I'm familiar with the restriction of being unable to share records with the owner of the record, but didn't think of that in this context, I'll have to account for that later on. However, in regards to this specific issue, I don't think that's the problem. The debug log shows me exactly which users the caseShare record is for. None of them are the owner at any point in the record instantiation. Interestingly, the owner is being switched from the running user (me) to a queue upon insert. Additionally, I tried the database.insert set to false to no avail :(. – Sam Kamensky Apr 12 '16 at 4:32
  • @sfdcfox I deactivated the workflow that sets the owner to a queue and the code works!! What? Why do you think that is? If it helps the queue has no members. – Sam Kamensky Apr 12 '16 at 4:43
  • I found out why :P. Thanks for pointing me in the right direction! – Sam Kamensky Apr 12 '16 at 5:29
2

When a queue owns a case record in SF and the sharing model for the case is private

Only queue members and their direct reports can view or take ownership of [those] cases.

Page 21 Case Management Implementation Guide

Here are two exceptions I learned about from this experience.

  1. Other users can view the case if they have 'view all' on the object level or are in role hierarchy above someone with 'view all.'
  2. The calculation for this specific sharing event happens when you change or initially set the owner to a queue but will not be calculated in for updates to the record that do not change the ownership from a user to a queue, or from one queue to another. For example, if you set the owner to a queue and simultaneously try to share it with users that are not queue members, direct reporters of queue members, or users with 'view all' permission, the sharing will fail. However, if you set the owner to a queue, and in a separate transaction share the record with users that are not queue members or direct reporters of queue members, your sharing will succeed.

EDIT:

The reason for the failure of inserts was confirmed by Salesforce support.

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.