Find your content:

Search form

You are here

"Lock" Old Opportunities so They Can't Be Edited


For auditing purposes, we'd like to lock Opportunities that have been closed for 90 or more days so that they can't be edited anymore, (except perhaps for a super-user profile, but you don't need to address that in your answer).

I know that I could enforce this with the following process, but I'm curious whether there's a simpler or more elegant way to do this:

  1. Create a custom field called "Date First Closed." This field is updated by workflow the first time the opportunity is closed. (Can't use Close Date b/c users can change that).
  2. Validation rule on Opportunity that blocks saving if Date First Close is 90 days ago or more, unless the user is in one of the allowed profiles.


  • I'd prefer to avoid using multiple Record Types, because we already have several different Record Types for different sales processes, and it would be cumbersome to maintain Active and Locked versions of each one.
  • Our default sharing mode is Private, so it would be great to do something with Sharing Rules... but I don't see how I could block the Owner from editing, since Owner always has read/write permissions.

Attribution to: Benj

Possible Suggestion/Solution #1

We have done this using a simple validation rule on the oppty object, this checks if the Close date is 90 days old, and if true on the oppty status [Closed, Closed Won, whatever] - returns an error.

OR(ISPICKVAL(PRIORVALUE(StageName),"Selected - PO Received"), 
ISPICKVAL(PRIORVALUE(StageName),"Closed Won")), 
CloseDate + 90 < TODAY() 

Off course, you can add the profile check as well (we use the administrator profile ID for allowing changes)

NOT ($Profile.Id = "00e20000004456")

Always remember to tune your query as much as possible for better performance.

Attribution to: Saariko

Possible Suggestion/Solution #2

The best non-record type solution I can think of is to have a time-based workflow change the owner. You could then use sharing rules to give other users read-only access to the records.

In addition, while extra record types might be cumbersome to maintain they still might prove to be the simplest and cleanest solution in the end.

Attribution to: Mike Chale

Possible Suggestion/Solution #3

We did something similar, however we created a specific boolean field for this purpose: "locked__c".

The benefit of using this field instead of a 'first closed date', is it can be used in multiple ways and remains true to its meaning. For example, you may want to lock an Opportunity for a reason other than it was closed 90 days ago, such as based on the Amount value or the Client. By having a generic 'locked' field, the same field is used and it's easy to report on, otherwise you'd have to create multiple fields to achieve the same result.

Our use was slightly different. We wanted certain profiles to have the ability to edit a record in a very small number of situations. We made it possible for those profiles to untick the 'locked' field, then edit it, and workflow would re-tick the field.
We wanted these users to be able to help themselves, but we also wanted to monitor it, so we had emails sent to the sys admins whenever the 'locked' field was unticked for auditing purposes. This approach worked out quite well as the users could perform their tasks, but we could also control it.

Attribution to: Nick Cook

Possible Suggestion/Solution #4

I recently wrote a blog post about locking records using approval processes. It is a pretty big hack, but it allows you to lock a record without having to use separate page layouts or record types. Here's how it could work:

  1. Set a time-based workflow rule to update a boolean field called "Lock Record" 90 days after the Opportunity is closed.
  2. Have a trigger that fires when the "Lock Record" field is checked.
  3. The trigger invokes a simple approval process that when finished leaves the record locked.

Admins can unlock the record by clicking the Unlock button at the top of the page, but they can also edit the record without unlocking it.

Attribution to: Daniel Hoechst

Possible Suggestion/Solution #5

I have used this syntax in a validation which has seemed to work well.

PRIORVALUE(LastModifiedDate) <> NOW()

Attribution to: Jonathan Jenkins
This content is remixed from stackoverflow or stackexchange. Please visit

My Block Status

My Block Content