Sunday, 25 October 2009

Setting up 'Last Viewed By' in salesforce

Every record created in salesforce includes some audit information as standard; such as the Created By and Last Modified By fields which display the username and date/time stamp to indicate who created or updated the record and when it took place. This can be useful when trying to trace modifications to a record, but what if you wanted to know who last Viewed a record? There's no way to do this in salesforce (as of Winter '10). It would be great if you could see on a record if anyone has recently viewed it, so I came up with this solution:

1. Decide which object to use
Firstly you'll need to decide which object you want to setup Last Viewed By on, you can set this up on both standard and custom objects. For the purposes of the demo I'm going to setup the functionality using the Account Object.

2. Create a new custom text field
On the Account object, create a new custom text field called Last Viewed By - I used the maximum characters (255) just in case there are any users with long names.



3. Create your Visualforce page
To create a new page go to Setup > App Setup > Develop > Pages and click New. Call it lastViewed, then use the code below in your page:




Note: The page uses a standard controller with an extension - this is so that we can drag it onto the Account page layout (were it a custom controller it would'nt be available for selection)

4. Create your Apex Class
Create an Apex class to populate the Last Viewed By text field when the visual force page is invoked. Go to Setup > App Setup > Develop > Apex Classes and click New. Call it lastViewed and populate it using the code below:

public class lastViewed{
    
    public Datetime cDT;
    public String LongDate;
    public String firstname;
    public String lastname;
    public String userid;
    
    private final Account acct;
    
    public lastViewed(ApexPages.StandardController stdController) {
        this.acct = (Account)stdController.getRecord();
    }

    public String getLongDate() {
        cDT = System.now();
        //Format the datetime value to your locale
        LongDate = cDT.format('dd/MM/yyyy HH:mm');
    return LongDate;
    }
    
    public void updateField() {
        
        //Get the user info from the current user
        firstname = System.Userinfo.getFirstName();
        lastname = System.Userinfo.getLastName();
        userid = System.Userinfo.getUserId();
        
        //Get the account record to be updated
        Account a = [select Last_Viewed_By__c from account where id = :acct.id limit 1];
        //Assign values to Last Viewed By field & update the record
        a.Last_Viewed_By__c = (firstname + ' ' + lastname + ', ' + getLongDate());
        update a;
    }

}

5. Edit the page layout
Next drop the Visualforce page onto the Account Page Layout so that when a user views an account record, the Visualforce page is invoked - calling the Apex class and updating the record. Click on Edit Page Layout and then select 'Visualforce Pages' from the left hand menu. You will see your page appear for selection, drag it over onto the page - you can put it wherever you like (see below).












Now alter the settings so that the page doesn't appear so large (it doesn't contain anything visual and we'd rather the users didn't know it was there). Click on the spaner in the top right hand side of the visualforce component for the settings menu to appear, then set the height in pixels to 0 and make sure the Show scrollbars and Show label options are deselected.











Now add the Last Viewed By field itself, so that the populated value is visible to the end user. Add the field to the page using the page layout editor as normal.

6. Try it out
The next step is to test it out. The Last Viewed By field will appear blank at first, this is because the visualforce page has not yet been invoked and therefore hasn't populated the field. Hit refresh on the record you're viewing and you will see the field populated with your name and the current date/time.
 

 
 



7. Notes
 
1) Last Modified By field will get updated along with the Last Viewed By field (as the record is being modified each time)
2) The username is not a hyperlink. This could be resolved using a formula field and some concatenation, update to follow perhaps?
3) Contribute! If there are areas that could be improved please add a comment. I'm aware this may not be the 'perfect' solution.
3) Any code provided on this site comes with no support or warranty whatsoever.

6 comments:

jeffdonthemic said...

This is awesome! I had never thought of doing a "last viewed" but it would come in handy. Great job!

frasuy said...

Never thought of this use case before but nice solution!

M. Smith said...

Absolutely Brilliant!

Amar Joshi said...

its nice stuff but i want to throw some lights on this
1. you must have to unable VF and Apex class in the user's profiles otherwise it will not work for that user and if the user view that page but VF page and apex class will not enable then ListViewBy field will not update.
2.now Lets assume u have enabled the VF page and Apex Class now some user have open that page to view the data but he is not editing anything though the Lastmodifiedby field will update coz the VF page will autometicaly run and data will update in LastViewBy Field

Hope you can get what i want to explain here but inspite of this its awesome idea i will do it for my customer

Thanks,
Amar
Salesforce.com Developer
ServiceMax,Inc
Bangalore,India

Hannes Ellerbrock said...
This post has been removed by the author.
Hannes Ellerbrock said...

The idea of a "last viewed" feature is great.

To work-around the "last edited" problem I would set up a new custom object "Last View" with three fields:
1. ID [Lookup Account] contains the ID of the related object, could probably also be a String field.
2. last_view_date [long date] contains the date when 'ID' was last viewed
3. name [String] holds the name of the person who viewed the object

And on the account you would have to add a lookup on "last view" which can be hidden.

When the VF element is opened and calls the action, the controller would try to select a "last view" object for this.account. When it finds one it updates the fields, if there is none yet it inserts it... Maybe an upsert would do the job even easier.

Not sure if there is any chance to write the controller so it works with any kind of sObject. Would come in handy.

On the Account you would put a formula field that displays "name" + "last view date" from the related "last view" object. This data can be easily derived via the lookup to to "last view"

Now, if you have a running org you would have a "last edit" == "last view" for the edit where the account gets a "last view" child, but for all new orgs you wouldn't have that problem.

Btw.: I've build something similar with leads: A field that displays for how long a lead has not been read by the current owner, e.g. after it has been transferred. This is a very interesting information for us and not yet a standard salesforce feature.

So far,
Hannes

P.S.: Deleted my previous post because I forgot something to add.

Post a Comment