1

Requirement1 --- A profile with Normal user should be able to edit only his records but not the other Users Records.
Requirement2 --- Irrespective of the User Assigned To field should be editable by Everyone

My Validation Rule is

(OwnerId != $User.Id && $Profile.Name='Normal User') && NOT( ISCHANGED( OwnerId ) )

My VF Page and class

<apex:PageBlock title="Letters" mode="inlineEdit" id="theIn" >
<apex:pageBlockButtons location="top" rendered="{!IF(TasklstI.size>0,true,false)}" >
    <apex:commandButton value="Save" action="{!saveTaskI}" rerender="theMsg"/>
    <apex:commandButton value="Cancel" action="{!cancelTask}" immediate="true"/> 
</apex:pageBlockButtons>
<apex:outputPanel rendered="{!IF(TasklstI.size>0,true,false) && Csedt==true}" >
<apex:pageblockTable value="{!TasklstI}" var="tsk" id="table">
<apex:column headerValue="Verification Status"> <apex:Outputfield value="{!tsk.Verification_Status__c}"/></apex:column>
<apex:column headerValue="Verified"><apex:Outputfield value="{!tsk.Task_Verified__c}"/></apex:column>
<apex:column headerValue="Assigned To"> 
        <apex:commandLink value="{!tsk.owner.name}" action="{!editOwner}"  reRender="table" rendered="{!tsk.Id<>tempTask.Id}">
            <apex:param assignTo="{!ownerEditId}" name="" value="{!tsk.Id}" />
        </apex:commandLink>
        <apex:inputfield value="{!tsk.ownerId}" rendered="{!tsk.Id=tempTask.Id}" />
</apex:column>
<apex:inlineEditSupport event="ondblClick"   /> 
</apex:pageblockTable>
</apex:PageBlock>



    Public pagereference saveTaskI(){  
  try{  
    Upsert tasklstI;

        pagereference pp = new pagereference('/apex/taskDetails');
        pp.setredirect(true);    
        pp.getparameters().put('id',apexPages.currentpage().getparameters().get('id'));
        return pp;
}catch(exception ex){
      if(ex.getmessage().contains('FIELD_CUSTOM_VALIDATION_EXCEPTION')){
             String[] errorMsg = ex.getMessage().split('FIELD_CUSTOM_VALIDATION_EXCEPTION,');
             String[] errorMsgOnly = errorMsg[1].split(':');
             apexPages.addMessage(new apexPages.Message(ApexPages.Severity.ERROR,+errorMsgOnly[0].trim()));             
         }else{
             apexPages.addMessage(new apexPages.Message(ApexPages.Severity.ERROR,'An unexpected error occurred. Please contact the support group with the error message'+ex.getmessage()));
         } 
         return null;
  } 
    }

My Problem here is if I'm having multiple Owners With different profiles.Say Suppose

Ist Record -- User 1 -- Normal User Profile

2nd Record -- User 2 -- System Admin profile

When I logged in as a normal user and try to edit the first record and save it, that has access to getting the Error message as

System.DmlException: Upsert failed. First exception on row 1. Task can't be edited by the owner

The root cause of this error is since here I'm upserting the total Task List 'Tasklisti' where the Normal user is not having the access to the user2 record with the system admin profile, the validation rule is triggering out. How should I overcoe this. Ideas please

7
  • Hi Eagerin, what is your use case? what are you trying to do, please tell, then accordingly we can help write the validation rule. May 25, 2017 at 8:13
  • added the requirement please check
    – Eagerin Sf
    May 25, 2017 at 8:17
  • To clarify, users should only be able to edit their own records; however, anyone is able to take ownership? Also, are you getting the validation error when you try to change ownership? May 25, 2017 at 8:35
  • Correct. When I try to change ownership i'm not getting any error message
    – Eagerin Sf
    May 25, 2017 at 8:39
  • Ok so users are able to take ownership without issue. When a normal user then tries to edit an item that they own, they trigger the validation rules. If you try to edit a single record are you running into an issue or only on your VF Page? If the latter, are there any tasks in the upsert command that are not owned by the normal user? e.g. you have 3 tasks tasklstI. One of the tasks is owned by the admin and the other two are owned by the normal user. May 25, 2017 at 8:46

1 Answer 1

0

Since you're doing the complete upsert in a all or none context (which is the default), that's why it's triggering.

What your describing is something like this:

tasklstI {
 Task(Owner=currentUser),
 Task(Owner=SomeoneElse)
};

When you run the upsert command it's doing an update against the second task, which the validation rule catches. If the person is not the owner of the record, then an update is always going to fail if the person has the normal user profile.

You have a couple of options. Option 1:

Use the following

Database.UpsertResult[] results = Database.Upsert(tasklstI,false);

That will disable the all or none and allow the upsert to take place regardless of the result. Then you can evaluate against the results. This is probably the easiest solution; however, I don't believe it goes towards what you're looking for.

Option 2: Adjust the validation rule to look for specific changes. This can be come a bit of a pain to maintain but it works:

(OwnerId != $User.Id && $Profile.Name='Normal User') && NOT( ISCHANGED( OwnerId ) ) && (OR(ISCHANGED(Verification_Status__c),ISCHANGED(Task_Verified__c))

The other problem with that approach is that if you need the validation rule to be enforced for any other updates, then it would essentially be useless.

Option 3: Run a validation in your save method. This is the most complicated but would probably be the stablest without causing changes to your validation rule that may cause issues elsewhere.

To do this without a wrapper class you'll need to initialize a second variable when you query. What mean is something like this:

Map<Id,Task> origianlTasks = new Map<Id,Task>(tasklstI);

That should create a copy of the tasks with a new pointer so you can compare the original version of the task against the updated version:

List<Task> tasks2Upsert = new List<Task>();
Set<String> flds2Check = new Set<String>{'Verification_Status__c','Task_Verified__c','OwnerId'};
for(Task tsk : tasklstI) {
    //Checking if any of the fields on the page have changed
    //Doing the check here will prevent errors if the person does not own the task and did not make a change
    for (String fld : flds2Check) {
        if (tsk.get(fld) != origianlTasks.get(tsk.Id).get(fld)) {
            tasks2Upsert.add(tsk);
            break;
        }
    }
}
//Execute existing save logic with the tasks2Upsert instead of tasklstI

I didn't test that code but it's essentially something that I would write if I needed the validation rule to remain unchanged. It would simply not upsert the records that didn't change. You could also institute something similar with a wrapper class using a map of field name to original value, but if you want to do that you'll need to code it yourself :)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .