1

I'm using objects Opportunity, OpportunityTeamMember, User, Opportunity_Team_Member, and Employee__c.

For me to create a member, i will choose an employee, checks if the email has match with user and if true, will create the standard OpportunityTeamMember but if false, will create the custom object.

Both the parent of course would be the Opportunity. I'm using a custom profile with read,create,edit permission on Opportunity, Opportunity_Team__c, and read only on Employee.

Question is why the error does the error appear when the profile is not given a modifyAll on Opportunity? Read/Create/Edit is not enough.

Other objects (employees, opportunity_team__c) doesn't affect it so even if read-only. It allows creation since it's done through apex. Also, even if I switch the field type (Master/Lookup) to parent Oppy, it doesn't seem to fix it. Sample test code is below:

    User user = sampleUser(OpportunityTeamUtils.PROFILE_TECH_ADMIN, 'tstz');
    User user1;
    User user2;
    User user3;
    User user4;
    Employee__c emp1;
    Employee__c emp2;
    Employee__c emp3;
    Employee__c emp4;
    Employee__c emp5;
    Product2 prod;
    Product2 prod2;
    Account acct;
    Opportunity opp;
    OpportunityTeamMember otm;
    Opportunity_Team__c otmC;
    List<OpportunityTeamMember> otmList;
    List<OpportunityTeamMember> otmList2;
    List<Opportunity_Team__c> otmClist;

    Test.startTest();
    System.runAs(user) {
        user1 = sampleUser(OpportunityTeamUtils.PROFILE_SR_MANAGEMENT, 'tsta');
        user2 = sampleUser(OpportunityTeamUtils.PROFILE_SR_MANAGEMENT, 'tstb');
        user3 = sampleUser(OpportunityTeamUtils.PROFILE_SR_MANAGEMENT, 'tstc');
        user4 = sampleUser(OpportunityTeamUtils.PROFILE_SR_MANAGEMENT, 'tstd');
        emp1 = sampleEmployee('tsta');
        emp2 = sampleEmployee('tstb');
        emp3 = sampleEmployee('tstc');
        emp4 = sampleEmployee('tstd');
        emp5 = sampleEmployee('tste');
        prod = sampleProductFamily('prodFam');
        prod2 = sampleProduct('prod', prod.Id);
    }
    System.runAs(user1) {
        acct = sampleAccount('test');
        insert acct;
    }
    System.runAs(user2) {
        opp = sampleOpportunity('testOpp', acct.Id, prod2.Id);
        insert opp;
        OpportunityTeamController.createTeamMember(opp.Id, emp3.Id, OpportunityTeamUtils.ROLE_FOREIGNEXCHANGEMARKETER);
    }       
    System.runAs(user3) { 
        //Create/update/delete an opportunity team member standard object
        OpportunityTeamController.createTeamMember(opp.Id, emp4.Id, OpportunityTeamUtils.ROLE_PRODUCT_PARTNER);
        otmList = [SELECT 
        Id, TeamMemberRole FROM OpportunityTeamMember WHERE OpportunityId=:opp.Id AND TeamMemberRole=:OpportunityTeamUtils.ROLE_PRODUCT_PARTNER AND UserId=:user4.Id];
        System.assert(otmList.size() == 1, 'createTeamMember failed');

        OpportunityTeamController.updateTeamMember(otmList[0].Id, user4.Id, opp.Id, OpportunityTeamUtils.ROLE_OTHERBUSINESSPARTNER, true, false, OpportunityTeamUtils.ROLE_PRODUCT_PARTNER, user4.FirstName+' '+user4.LastName);
        otmList = [SELECT Id, TeamMemberRole FROM OpportunityTeamMember WHERE OpportunityId=:opp.Id AND TeamMemberRole=:OpportunityTeamUtils.ROLE_OTHERBUSINESSPARTNER];
        System.assert(otmList.size() == 1, 'updateTeamMember failed');

        OpportunityTeamController.deleteTeamMember(otmList[0].Id, OpportunityTeamUtils.OBJECTAPINAME_STANDARD, opp.Id, OpportunityTeamUtils.ROLE_OTHERBUSINESSPARTNER, false, user4.FirstName+' '+user4.LastName);
        otmList = [SELECT Id, TeamMemberRole FROM OpportunityTeamMember WHERE OpportunityId=:opp.Id AND TeamMemberRole=:OpportunityTeamUtils.ROLE_OTHERBUSINESSPARTNER];
        System.assert(otmList.size() == 0, 'deleteTeamMember failed');

        //Create/update/delete an opportunity team member custom object
        OpportunityTeamController.createTeamMember(opp.Id, emp5.Id, OpportunityTeamUtils.ROLE_PRODUCT_PARTNER);
        otmClist = [SELECT Id, Team_Role__c FROM Opportunity_Team__c WHERE Opportunity__c=:opp.Id AND Team_Role__c=:OpportunityTeamUtils.ROLE_PRODUCT_PARTNER];
        System.assert(otmClist.size() == 1, 'createTeamMember failed');

        OpportunityTeamController.updateTeamMember(otmClist[0].Id, emp5.Id, opp.Id, OpportunityTeamUtils.ROLE_OTHERBUSINESSPARTNER, false, false, OpportunityTeamUtils.ROLE_PRODUCT_PARTNER, emp5.name);
        otmClist = [SELECT Id, Team_Role__c FROM Opportunity_Team__c WHERE Opportunity__c=:opp.Id AND Team_Role__c=:OpportunityTeamUtils.ROLE_OTHERBUSINESSPARTNER];
        System.assert(otmClist.size() == 1, 'updateTeamMember failed');

        OpportunityTeamController.deleteTeamMember(otmClist[0].Id, OpportunityTeamUtils.OBJECTAPINAME_CUSTOM, opp.Id, OpportunityTeamUtils.ROLE_OTHERBUSINESSPARTNER, false, emp5.name);
        otmClist = [SELECT Id, Team_Role__c FROM Opportunity_Team__c WHERE Opportunity__c=:opp.Id AND Team_Role__c=:OpportunityTeamUtils.ROLE_OTHERBUSINESSPARTNER];
        System.assert(otmClist.size() == 0, 'deleteTeamMember failed');
    }
    Test.stopTest();
  • What is the OWD of Opportunity? – Santanu Boral Apr 5 '17 at 18:28
  • It's PUBLIC READ ONLY. Let me review the answer – Jefferson Fernandez Apr 5 '17 at 19:46
0

I think in the Sharing Settings, OWD of Opportunity is either Private or Public Read Only.

And according to your configuration other objects have M-D relationship with the Opportunity.

There is a difference between record based sharing and Profile permission.

You have given Read/Create/Edit permissions to Opportunity. That's good. But who is the owner of the Opportunity record?

If the OWD is Private or Public Read Only then, only the owner can edit the Opportunity record. And that owner can create other child records under Opportunity.

According to your code,

System.runAs(user2) {
        opp = sampleOpportunity('testOpp', acct.Id, prod2.Id);
        insert opp;
        OpportunityTeamController.createTeamMember(opp.Id, emp3.Id, OpportunityTeamUtils.ROLE_FOREIGNEXCHANGEMARKETER);
    }  

User2 is creating the Opportunity and there will be no issue when that user creates TeamMembers.

Now, in this below code, user3 is trying to create TeamMember under that Opportunity which user2 has created. That user3 doesn't have Edit access to that Opportunity either by OWD or sharing rule. Thats why is failing.

 System.runAs(user3) { 
        //Create/update/delete an opportunity team member standard object
        OpportunityTeamController.createTeamMember(opp.Id, emp4.Id, OpportunityTeamUtils.ROLE_PRODUCT_PARTNER);

If you assign the profile as Modify All to Opportunity then it will supersede all the sharing settings and permissions. The user will have modify access to all the records created by all other users in the org.

Finally, in case of M-D relationship, Parent, that is Opportunity ownership will govern the ownership of child records (TeamMembers).

Other important part is With Sharing and Without Sharing in the Class. I think OpportunityTeamController is defined as with sharing thats why it is respecting the sharing settings of the user.

Suggest you to go through these videos Who Sees What Series

  • 1
    Thanks Santanu! I updated my classes to Without Sharing so not to mix up with the Org's sharing settings since i created my own way of giving permissions anyway. I understand now through the videos you suggested. Thanks – Jefferson Fernandez Apr 5 '17 at 22:05
  • Better, make classes with sharing and during preparation of data, the person is creating the opportunity, he should create child records. Your issue got solved – Santanu Boral Apr 5 '17 at 22:24

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.