Content Latest Version Flag

Yesterday, I used Content Delivery to send a pdf to a client. Simple, right? Upload the Word document to Content, associate it with a record, and deliver the content. Surely if I upload a new version, the delivery will refer to the latest version, right? There’s no place to select that option, so I can assume, right?

Wrong.

This is the screen I see when I choose to deliver a given file. Note that I can choose whether to allow access to the original file or only to a pdf… but nothing about which version to deliver. (There are 4 versions right now.)

Options available when configuring a Content Delivery

Content Delivery Options

The document in question needed some changes, so I uploaded a new version and told the client that the old link would still work. Oops.

By default, Content Deliveries are set to refer to one specific version of a Content file. I can understand this, but surely I should be given the opportunity to change that?

To do this, view the Delivery record and see the following:

Content Delivery Record Detail View

Content Delivery Record Detail View

Click Edit and check the appropriate checkbox.

There you have it! A few extra clicks, but a Content Delivery can point to the latest version.

Do you use Content Deliveries? How do you like it?

 

PersonAccount Stay-In-Touch Gotcha

I make no secret that I’m a fan of PersonAccounts.  I think they’re  very handy when working with individuals instead of companies, and I  really like pairing them with the Relationship Groups app to make  households.

I’ve always considered them as mostly-contacts.  I put all Person  fields on the Contact object, reserving very few for the Account  object.  But for some reason, I’ve usually used Billing Address as the  primary address and Mailing as the secondary.  No reason – that’s just  how I’ve done it.

That all changed yesterday.  I was prepping to demo a system to a  company and decided to click the “Request Update” button to send a  Stay-In-Touch email.  This is not a customizable email (well, not much)  in terms of the fields from the Contact that it displays, so it used the  Mailing Address.  Oops!

From now on, I am using Mailing and Other addresses for PersonAccounts.  Billing, you’re reserved for BusinessAccounts.

Feel free to debate the merits and drawbacks of PersonAccounts below – I’ll respond to them in a future post.



 

Chatter BINGO Released Into The Wild

With Dreamforce 2010 behind us and Dreamforce 2011 fast approaching, the first ever crowdsourced conference application is publicly available!

Chatter BINGO has been released as an unmanaged package, meaning that all the source code is open and ready for customizing to your hearts’ content.

Chatter BINGO was conceived by Chris Shackelford and Brad Gross (@imperialstout) while chattering in the Dreamforce org, and they asked me to build it. Within two weeks, it had passed QA and was deployed to the org.

One of my favorite moments from Dreamforce was at the Tweetup (#df10tu – see you at #df11tu) when someone walked up to me with a printout of the PDF BINGO card she had generated, asking me to mark myself on the page. It always feels good to see people enjoying one’s work!

The listing is at http://www.x2od.com/getchatterbingo.

Enjoy!

 

Activity Type Field – Do Not Use

March 21, 2011 by David Schach · Leave a Comment
Filed under: Apex, salesforce.com, Tips and Tricks 
The field Event.Type (which is sort of the same as Task.Type) is a difficult field to use.  Here are a few reasons:
  • Type cannot be the controlling field for a dependent picklist.
  • On an Event list view (/007), even when specifying record type, the Type field cannot be edited.
  • Salesforce requires you to select a default value for this picklist, as well as a default value for inbound emails... yet when I bcc my Email-To-Salesforce address, the resulting tasks have no Type value.
A tweet by Andy Ognenoff of Manpower (@aognenoff) revealed another limitation: Type is not available in Custom Report Types. That does it!  I'm done with this field.  Here's my solution.
  1. Work in a sandbox (duh)
  2. Create a picklist field on Activity (ActivityType__c).
  3. Disable all Activity workflow rules, Chatter feeds, triggers, etc.
  4. Using DataLoader, copy values from Type to ActivityType__c.
  5. Using Field Level Security, hide Type from all profiles.  It's just not necessary.
  6. Edit/reactivate all your workflow, feeds, triggers, etc.
  7. Use/adapt the code below.
  8. Test thoroughly and deploy to production.
The Salesforce Mobile application (at least for Blackberry) defaults to a Subject "Call: (212) 555-1212" style.  This will account for that.  It also handles emails sent with Email-To-Salesforce, which starts the subject with "Email:"
trigger TaskTrigger on Task (before insert, before update) {
     ActivityHelper.UpdateTaskType(Trigger.new);
}
trigger EventTrigger on Event (before insert, before update) {
     ActivityHelper.UpdateEventType(Trigger.new);
}
This class isn't perfect, but it gets the job done. I should add try/catch statements in my test code (though I have heard recently that it's not a good idea to do so, as one may WANT the code to fail with an error if something doesn't go as expected).
// Written by David Schach, X-Squared On Demand
public with sharing class ActivityHelper {

    public static void UpdateEventType(Event[] events){
        for (Event e : events){
            if(e.ActivityType__c == '' || e.ActivityType__c == null){
                if(e.Subject.contains('Email'))
                    e.ActivityType__c = 'Email';
                else if(e.Subject.contains('Call'))
                    e.ActivityType__c = 'Call';
                else if (e.Subject.contains('Meet') || e.Subject.contains('Webinar'))
                    e.ActivityType__c = 'Meeting';
            }
        }
    }
    
    public static void UpdateTaskType(Task[] tasks){
        for (Task t : tasks){
            if(t.ActivityType__c == '' || t.ActivityType__c == null){
                if(t.Subject.contains('Email ') || t.Subject.contains('Email:'))
                    t.ActivityType__c = 'Email';
                else if(t.Subject.contains('Call'))
                    t.ActivityType__c = 'Call';
                else if (t.Subject.contains('Meet') || t.Subject.contains('Webinar'))
                    t.ActivityType__c = 'Meeting';
            }
        }
    }
    
    private static Event newTestEvent(string subject){
        Event e = new Event();
        e.Subject = subject;
        e.startdatetime = datetime.now();
        e.DurationInMinutes = 60;
        e.ActivityType__c = ''; // To account for default value.
        return e;
    }

    private static Task newTestTask(string subject){
        Task t = new Task();
        t.Subject = subject;
        t.Priority = 'Medium';
        t.Status = 'New';
        t.ActivityType__c = ''; // To account for default value.
        return t;
    }   

    static TestMethod void TestEvents(){
        test.starttest();
        List<Event> ourevents = new List<Event>();
        ourevents.add(newTestEvent('e1'));
        ourevents.add(newTestEvent('Email: Thank you'));
        ourevents.add(newTestEvent('Call: (212) 555-1212'));
        ourevents.add(newTestEvent('Webinar tomorrow'));
        ourevents.add(newTestEvent('Meet Jack'));
        ourevents.add(newTestEvent('Sales time'));
        insert ourevents;
        update ourevents;
        for (Event e : [SELECT id, Type from Event WHERE id in :ourEvents]){
            system.debug('EVENT TYPE: ' + e.ActivityType__c);
        }
        test.stoptest();
    }
    
    static TestMethod void TestTasks(){
        test.starttest();
        List<Task> ourTasks = new List<Task>();
        ourTasks.add(newTestTask('e1'));
        ourTasks.add(newTestTask('Email: Thank you'));
        ourTasks.add(newTestTask('Call: (212) 555-1212'));
        ourTasks.add(newTestTask('Webinar tomorrow'));
        ourTasks.add(newTestTask('Meet Jack'));
        ourTasks.add(newTestTask('Sales time'));
        insert ourTasks;
        update ourTasks;
        for (Task t : [SELECT id, Type from Task WHERE id in :ourTasks]){
            system.debug('TASK TYPE: ' + t.ActivityType__c);
        }
        test.stoptest();
    }
    
    static testMethod void IndividualActivityTest() {
      Event e = newTestEvent('e1');
      Task t = newTestTask('t1');
      test.starttest();
      insert e;
      insert t;
      e.subject = 'Meeting';
      update e;
      e.subject = 'Call: Geoff Peterson';
      update e;
      e.subject = 'Email: Here we go';
      update e;
      e.subject = 'Webinar';
      update e;
      t.subject = 'Meeting';
      update t;
      t.subject = 'Call';
      update t;
      t.subject = 'Email';
      update t;
      t.subject = 'Webinar';
      update t;
      test.stoptest();
    }
}
 

« Previous PageNext Page »

  • Recent Posts

  • Subscribe

  • Post Categories