7

I have the following validation rule:

AND( 
$Profile.Name <> 'System Administrator', 
OR( 
ISPICKVAL(PRIORVALUE(Level__c), "Archived"), 
ISPICKVAL(PRIORVALUE(Level__c), "Closed") 
) 
)

This validation rule is on the opportunity object, and what I want to achieve is, if the picklist Level__c is either set to Archived or Closed, the opportunity record can only be edited by the System Administrator.

For some reason though, the validation rule also triggers, when I want to set the Level__c to Archived or Closed. But this is not what I want.

Any idea what's wrong with the validation rule?

5
  • Should throw a validation when thepicklist is archived or close, i dont think you need priorvalue here, AND( $Profile.Name <> 'System Administrator', OR( ISPICKVAL((Level__c), "Archived"), ISPICKVAL((Level__c), "Closed") ) )
    – Anurag
    Jun 8, 2016 at 19:02
  • It doesn't work.Because if any user except system administrator is try to save record with Level Archived or Closed it throws validation rule to fire.Because we mention in the above rule is they can't edit record with Archived or Closed.So, how they save??@Lily
    – Pavan tej
    Jun 8, 2016 at 20:39
  • I deleted my answer as it was providing the right solution to what you were asking. The reason that VR is triggered could be that you have a WFR or trigger to update the record when Lever is set to Archived or Closed. We are using a standard record locking for closed opportunities and this could be set by Approval, Process Builder or in Apex code (e.g. in a trigger) - let me know if you are interested to get more details.
    – o-lexi
    Jun 10, 2016 at 16:41
  • Yes, if it is possible to lock a record using Process Builder, that would be good.
    – Lily
    Jun 13, 2016 at 8:21
  • We need to go the validation rule road. I still haven't managed to get this to work
    – Lily
    Jun 14, 2016 at 14:18

3 Answers 3

11
+100

Your problem is you want to lock the whole record for everyone except System Admins once the level is "Archived" or "Closed". Putting a prior value around your level field will thus not help you, since it is only checking if that specific field has changed.

I would suggest you implement something like this:

  1. Create a new checkbox "Record Locked".
  2. Create a workflow that sets the checkbox to true once the level is "Archived" or "Closed". Optionally, you'd want to also uncheck this when the level changes again to another value.
  3. Update your validation rule so it says:

    AND($Profile.Name <> 'System Administrator', Record_Locked__c = true)

2
  • 2
    Thank you for the solution. I can award the bounty in 23 hours.
    – Lily
    Jun 14, 2016 at 15:14
  • 1
    @Lily Mind awarding the bounty? :-) Jun 21, 2016 at 12:19
1

You can do that with a combination of two validation rules working on current fields

Vallidation Rule 1

Prevent making any changes when Level equals Archived or Closed unless User is a Sys Admin. Needed to exclude situation when changes are done to Level because otherwise it will not allow to enter Archived or Closed. PRIORVALUE seems to not work here so I used ISCHANGED function to capture that.

AND(
   $Profile.Name <> 'System Administrator',
   NOT(ISCHANGED(Level__c)),
   OR(
      ISPICKVAL(Level__c, 'Archived'),
      ISPICKVAL(Level__c, 'Closed')
   )
)

The thing is that this rules allows making changes if User at the same time changes Level__c. That's why we need second Validation rule.

Vallidation Rule 2

Prevents User from changing Level__c once it is Archived or Closed, unless he is a Sys Admin

AND(
   $Profile.Name <> 'System Administrator',
   ISCHANGED(Level__c),
   OR(
      ISPICKVAL(PRIORVALUE(Level__c), 'Archived'),
      ISPICKVAL(PRIORVALUE(Level__c), 'Closed')
   )
)
1
  • 2
    Or you can combine 2 into 1: AND( $Profile.Name <> 'System Administrator', OR( AND( NOT(ISCHANGED(Level__c)), OR( ISPICKVAL(Level__c, 'Archived'), ISPICKVAL(Level__c, 'Closed') ) ), AND( ISCHANGED(Level__c), OR( ISPICKVAL(PRIORVALUE(Level__c), 'Archived'), ISPICKVAL(PRIORVALUE(Level__c), 'Closed') ) ) ) )
    – o-lexi
    Jun 17, 2016 at 18:36
0

The validation looks correct, I've tested this in my dev org. If you want to make it more clever like to allow you to change the Level to "Archived" after it has been "Closed", you can add something like this:

AND( 
     $Profile.Name <> 'System Administrator',
     NOT(ISNEW()),
     OR(
         AND(
             ISPICKVAL(PRIORVALUE(Level__c), "Closed"),
             NOT(ISPICKVAL(Level__c, "Archived"))
         ),
         ISPICKVAL(PRIORVALUE(Level__c), "Archived") 
     )
 )

Also ensure that you have no other processes that run after you update the field, that in turn also update the opportunity record. If that is the case you will need to add the fields that are being updated as exceptions in the validation. (Or extent the process to also lock the record as advised above)

The system will evaluate custom validation rules and allow you to save the record. If after your changes are done an automated process runs and updates the same record, validation rules will fire again at which point PRIORVALUE() function is the current value. This could be confusing but everything happens at the same time you are waiting for it to be saved. https://architect.salesforce.com/fundamentals/architecture-basics

Also, to help with testing and reduce confusion, remove this line $Profile.Name <> 'System Administrator' from your validation and use the Active checkbox on your validation during testing. Once you have it working for all profiles then you can add the line back with the exception.

Hope this helps. Seems like you are on the correct track anyways.

You must log in to answer this question.

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