Attaching a copy of an email alert in Salesforce

Standard

How long has it been? A long freaking time!
Long timeBetween summer vacations, coaching soccer and cub scouts, there has not been much idle time for this boy to blog, which stinks because there has been so much fun stuff figured out!

But, here I am, eating a turkey sammich, listing to some EDM on Slacker Radio and trying to get a blog post cranked out for you all.

What I am going to blog about is an annoyance that has been going on for quite some time… the issue of workflow email alerts. In fact, this idea is over 5 years old!

See, when you build out an email alert and it fires…well…it just fires. You can do a work around that involves carbon copys to an email to salesforce box or creating activities, but those workarounds are either not scaleable or they don’t give you much more information than “this email was sent!”.

But, I did find a work around that is scalable using my favoritest thing ever, flows*. Now, did you see that little thing there? That Asterix? Yep, that is there for a reason. It is there because I wrote this out using flow triggers. I am sure you can do this with process builder, but I am just documenting the flow trigger function here. I like process builder, but in this case, I just need to crank something out quick, so I am using triggers.

The “Too Long; didn’t read” version is this. I created a flow that runs via the workflow (remember, I am using flow triggers!). When that flow trigger runs, it will do two things. It will send off the email alert AND create an emailmessage record. Yeppers, I said create an emailmessage. What I have found is that within salesforce you can create an email record through a flow and it will happily sit there. The trick is that you will need to pass the record ID from where you are starting and use that ID for the “parent ID” field on the emailmessage record.

This is a good jumping off point if you want to venture forth and tinker around yourself. For those of you that want more details, here ya go!

My assumptions at this point are that you are comfortable creating your own method of running this flow. As long as you can pass variables over from the record, you should be good to go. This flow only has two elements. The email alert (which is already built) and the record create for the email message. There are a bunch of things you can build out when you create the email message, but I am just going to cover the basics.

  • Parent ID – this should be the record you want this emailmessage living under. In my case, it was, well, case.
  • Status – Status is a funny one. It is displayed in plain English but the value is actually numeric. In my case, I am recording a copy of a sent email, so I used a status of 3, which is “sent”.
  • EmailMessageBody – An interesting thing about this method is how the text is displayed. You will actually be creating the emailmessage.body by using the field “HTMLbody” and to make it so the text looks nice, you will need to do the following:
  • Create a text template called “LineBreak”. This text template will just have the HTML value for break “<BR>”

Line break

  • Create a text template called “Email body”. Enter your data and insert the text template “linebreak” wherever there should be a line break. If you need to get values from the parent record, insert them here. I choose to pass them all over via the flow trigger, but you could just as easily do it with a requrery.

Linebreak being used

The end result is that the emailmessage you created via the flow will have a similar look / feel to the email that was sent out via the alert. Actually, it will look way more like the Text version, but really the point is to have this copy not so much to look pretty.

As I said before, I will leave the method of running this flow up to you, so let’s talk about the results.

By doing this, I was able to get a copy of the alert email attached to the parent. I was then able to remove the activity creation on the workflow since that was how we were noting that an email was sent out. The email copy is an actual copy, so we know what was sent out, which you couldn’t do through the activity. As an added benefit, running this via the flow allowed me to do some extra shenanigans that you really cannot do through a workflow, like running queries on other objects and adding them to the email.

The last benefit is crazy obvious, this is a LOW maintenance function. If a new value is added to the email alert, I (or another admin) just needs to add it to the record creation function…no dev time needed!

As always, let me know if there are questions / comments

 

andrew

 

 

Lego, Salesforce and a den of Tigers!

Standard

I am privileged to be an assistant den leader for my local Boy Scout Pack (shout out, Mt. Baker Council!) . My son is a Tiger Cub in Den 2 and I recently gave a talk to the den around the topic of communications.

Tiger Cub!

Too Much Fun!

I volunteered to talk because I have a means of communicating ideas to the masses, which you are reading at this time.

It was a load of fun and I was able to hold their interest for an impressive (IMHO) amount of time even though my blog is just 1’s and 0’s instead of a printing press or antenna.

At the conclusion of my talk, I asked the cubs to pick my next topic. The topics were…interesting, but we finally nailed it down to Lego (Followed by Minecraft! Shocking Topics, I know!).

Honestly, it didn’t make me too sad to talk about Lego because really, there are a few things that I can distinctly identify as being huge influence’s on my life and career, and Lego is one of them.

I had quite a few Lego sets growing up, though nowhere near as much as my kiddos do. I can still remember a few of them, and will sometimes take a trip down memory lane (AKA, Ebay) and lament over selling them. I had some of the original space sets and I can still remember how proud I was when I completed the space shuttle set.

Oh man, how awesome was this set?

That scaffolding almost killed me!

But how can Lego’s be connected to Salesforce? Well, glad you asked! Here are some of the lessons I have learned:

  • To get from Point A to Point B, just follow instructions.
  • Always be (preparing to) improve(ing)
  • Have Fun!

Alright then, EVERYTHING looks AWESOME so let’s expand on this!

  • To get from Point A to Point B, just follow instructions.

READ the MANUAL! Salesforce has some CRAZY good instructions and guides that are accessible in a variety of ways. I have found that as long as you read the given guides you should be OK!

  • Always be (preparing to) improve(ing)
000124.0013174.tif

You will STICK (ha) to your requirements docs!

Things are going to change! I am one of those types that don’t get bothered by my Lego sets breaking. In fact, I am usually thinking about the next thing I can build while I am building. Everything breaks…even if you do manage to kraggle

your sets together, you cannot stop time…eventually the plastic breaks down.

  • Have Fun

I love working in Salesforce, don’t you?

Oh Yeah!

Ready for Casual Friday!

Reducing the amount of email while sending email

Standard

In my post titled “Cleaning the data that matters – and not all data matters” I finished the post up with the following:

“PS – For bonus points, create a nice email alert telling the reps their data is bad, and make it so it sends them that notice every time they edit the account OR opportunity…just put on a timer so it only sends once per day!”

To which, JaneIsaac replied:

“nice detective work. Could you share What the timer formula look like?”

Well JaneIsaac, this post if for you!

Not that type of request

I take requests…just not freebird!

The scenariois that we wanted to send out alerts if an account scored low data grade points and that account OR an opportunity related to that account was updated. After some quick research I saw that the updates were clustered, often receiving multiple updates in a short period of time. I didn’t want the alerts constantly kicking out.

So I built out a function so that prevent multiple alerts from being sent out in a given set of time. My functionality treats account and opportunity updates as two different actions, so I broke them out on this blog as such. Listing out the ingredients below and I will dissect the basic functionality after.

Must be about snack time...

Ingredients for tasty food, not tasty Workflows

For the Account alerts:

1 – Date field on Account “Data Alert Sent Date”

1 – Workflow rule for the Account Object “Data Grade Alert”:

Evaluation Criteria = “Evaluate the rule when a record is created, and any time it’s edited to subsequently meet criteria”

Rule Criteria =

Account WorkFlow Criteria

AND(
AND(Account_Data_Grade__c <>”Acceptable”,Account_Data_Grade__c <>”Excellent”),
Open_Pipeline__c < 1,
AND(LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “,LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “,LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “, LastModifiedBy.ProfileId <>”xxxxxxxxxxxxxxx”),
(DATEVALUE(CreatedDate)<>Today()),
OR(ISBLANK(Data_Alert_Sent_Date__c),(Data_Alert_Sent_Date__c) <> today()))

2 – Immediate Workflow Actions

All about that (Account Workflow) action Boss

1 – Workflow email alert Sendemail to “Last Modified By”

Account Workflow Alert

       1 – Field Update “Data Alert Sent Date” with Today()

Account Field Update

 For the Opportunity alerts:

1 – Date field on Opportunity “Data Alert Sent Date”

1 – Workflow rule for the Opportunity Object “Data Grade Alert”:

Evaluation Criteria = “Evaluate the rule when a record is created, and any time it’s edited to subsequently meet criteria”

Rule Criteria =

Opportunity Workflow Criteria

AND(
AND(Account.Account_Data_Grade__c <>”Acceptable”,Account.Account_Data_Grade__c <>”Excellent”),
AND(LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “,LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “,LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “, LastModifiedBy.ProfileId <>” xxxxxxxxxxxxxxx “),
Record_Type__c =”Open Opportunity”,
(DATEVALUE( Account.CreatedDate )<>Today()),
or(ISBLANK( Data_Alert_Sent_Date__c ), (Data_Alert_Sent_Date__c)<>TODAY()))

2 – Immediate Workflow Actions

All about that (Opportunity Workflow) action Boss

1 – Workflow email alert Send email to “Last Modified By”

Opportunity Email Alert

          1 – Field Update = “Data Alert Sent Date” with Today()

Opportunity Field Update

Taking a look at the mechanics:

I wish my cube was this cool...or that I had a flying monkey!

I wish my cube was this cool…or that I had a flying monkey!

The rule criteria’s are similar enough that we won’t have to dissect them both and since the interest is in the timer components, that is what I am going to focus on:

1)      (DATEVALUE( Account.CreatedDate )<>Today()) –  Ignore if the account is newly created

2)      But, the following situations are OK:

  1. (ISBLANK( Data_Alert_Sent_Date__c ) – The data alert sent date is Null (Never triggered before)
  2. (Data_Alert_Sent_Date__c)<>TODAY() – The data alert sent date does not equal Today()

This last line is what ensures that an alert will only send once per day. If the rule runs, (Data Quality = Poor and “Data Alert Sent Date” <>Today()), then the email alert gets sent out and the “Data Alert Sent Date” gets updated with the current day. If that record was updated ANY OTHER TIME during that day, the rule will not fire. I know I say this all the time, but what I really (Really) like about salesforce is that when it comes down to it, you can do some crazy cool stuff with zero code.

Clicks Not Code!

In other CRM’s, the above functionality takes 6 weeks and 2 developers.

 

Looking at this functionality now, I think a couple neat additions would have been:

1)      A rollup summary on opportunity.Data_Alert_Sent_Date__c (MAX), this way, you could have the account rule also looking at the last time an alert was sent out on ANY opportunity.

2)      A counter field update on the opportunity rule with a corresponding rollup on accounts. This would allow for reporting on ignored updates and thresh holding of the alerts.

But, the fun with Salesforce is the ability to rapidly prototype and tinker, so if I wanted to add in some new stuff, it is easy – peasy – lemon squeezy.

Well, hope you enjoyed this. I certainly had fun taking a look at something that was built out quite some time ago but continues to keep ticking! If there are any special requests, just let me know!

Don’t start cleansing data yet!

Standard

Data is a fickle beast.

One minute, you have amazing dashboards and reports… your finance nerds are seeing into the future with clarity a weather man can only wish to have…the next minute, you have gremlins everywhere causing chaos in the most basic of processes and you can only give accurate forecasts for five minutes in the past.

Don't feed data analysts after midnight!

All your data are belong to us!

I suspect this has been happening since mankind developed the first CRM, which was on Oracle Clay Tablets.

Oracle V1

You should see the servers needed for this!

Having been on many data cleansing projects in the past, with many more in my future, I decided to sketch out some ideas I have picked up along the way. Don’t worry, I will go back to my techie salesforce nerd stuff next week!

“It is a never ending story”

Cleansing data is not a project with a start and an end, it is a process that needs to be ongoing. If you have data coming in, you will have data that needs to be cleaned. Build it into your budget, chant the mantra, do whatever it takes, but embrace the fact that as long as you are around any CRM you will be doing data clean up.

“Business Involvement”

Even though dirty data and data cleansing will never go away, it will become a smaller task once you get your users sold on the idea of clean data. At the very least, you need your users to care about the system at the best they will become advocates of clean data. Boeing used to have a program called “FOD FREE”. FOD is “Foreign Object Damage” and it prompted their employees to be active in keeping the work environment clean. It was a huge success through marketing and  engagement, AKA, Business Involvement.

“Clean with a Purpose”

There are two methods to getting business involvement in data cleansing, carrot and stick. Personally, I prefer the carrot approach. Know why you are doing it, and be able to explain that to the business. Tell them in “What’s In It For Me” (WIFM) terminology why their data is changing and what outcomes they can expect. Have them involved in any process modifications or validation rule building. If you get them at least interested in clean data the process will be much less contentious.

“Know your Data”

Seriously, run some DANG reports. Know the numbers because someone will ask. Know the up and downstream impacts of dirty data. Know use cases. Have a really nice power point set explaining this things, and gear the presentations to different user levels. If you do not  know your data, how can you clean it???

On a side note, I swear by “You suck at powerpoint” as a great learning aid around presentations!

“Classify your Data”

Classifying data is just chunking up your data into sound bite groupings. The key here is “Sound Bite”. You can say something awesome like “Customers with an account that has at least 3 contacts that all have been sent an email in the past three years”, but after the first couple words, all anyone will hear is “blah blah blah”. Instead, have sound bite ready classifications. Thinking in “Sound Bite” terms will also help with reporting and formula writing, covered next week!

Here are some suggestions for accounts:

Primary = Customer, Non Customer

Secondary = Active (Open Pipeline), Non Active (No Pipeline)

Tertiary = Marketable (Contacts with Email), Non Marketable (Contacts without Email)

It’s looking a lot like Christmas (Sigh)

What really gets me excited about classifications is that it helps you NOT boil the ocean. It is not unrealistic to have hundreds of thousands of account records, and if you were to set about trying to clean them ALL, you would be wasting time and money on records that really are the equivalent to that fruitcake you got last year. It is just taking up space, but you don’t want to throw it out because someday you might have a reason to use (re-gift) it.

fruitcake

Yes, I did just compare your data to an old fruitcake

The above tips are not the end all be all, just things I have picked up along my career. But, if you are rolling into the discussion on data clean up just keeping these in mind you will be at a point where you have the business engaged in the ongoing process of data cleansing on a known set of data that involve a set of agreed upon classifications…or, in other words, you will be setup for success!

Oh, and now that this stuff is out of the way, we can get back to more techie stuff next week!

 

Andrew

Add followers with Flows

Standard

Chatter (in my opinion) is one of the really neat features of salesforce, allowing users to follow records that might be important to them is just one of the “Killer Apps” of this functionality. Ironically enough, being that this is a social network, is the request for that one can just add followers automagically if  “X” condition is met. There are even a couple apps on the appexchange for that.

Automated Networking, Jumbo Shrimp, Stop / Keep Moving, OxyMoron

Automated Networking, Jumbo Shrimp, Stop / Keep Moving, OxyMoron

To me, this takes a bit of the social out of “social networking”, so I am going to sketch out a solution that is a bit more personable but still makes it easy to add a follower

In a nutshell, it goes a little something like this:

1)      Within a record, the current user feels that another user (or themselves) should be on the follow list

2)      The current user clicks a button. In this case, I have called it “Pied Piper”

3)      A flow is launched that does the following:

1. Looks up a user based information given

2.Attaches that user to the current record as a follower

As usual, I am just sketching going to provide the foundation for this functionality. The magic here is that you can flows to do some neat stuff like attaching multiple users, adding comments, tags, etc. You don’t have to add this stuff in, but I would encourage playing around with it to see what you can / can’t do. Also, a quick Caveat. I found that a user will have to have “Modify All” permissions on the object you are pushing this out to. 

That aside, now we get to the Nuts & Bolts of the matter. I have got a couple of components that I am going to be using:

  1. A visual flow
  2. A custom button driven by a URL
  3. A nice cup of Coffee (Optional, or not)

This flow function sounds exciting and awesome (Follower Updates, Magic!), but is really basic. There are four components to this flow, Entry screen, Record lookup, Record Create and the confirmation screen (optional). There is however a critical variable, varAccountID. This is the variable that houses the ID that is passed over via URL. Just be aware when you are building this out!

The Components

Salesforce Flows, How awesome

On the entry screen, there is a text box for entry of a person’s name. The text box value is passed to the Record Lookup. One of the easiest improvements would be making this multi search (name, ID, email), just something to keep in mind.

Search Box

The flow does a look up on name, and returns the userID.

2014-05-13 13_15_27-Flow Designer_ public_FlowFromFlow

 

 

Next up is the Record Create on the object Entity Subscription. In this case, the parentID is the accountID, but it can be anything. SubscriberID is just the UserId pulled above.

2014-05-13 12_49_55-Flow Designer_ public_FlowFromFlow

Once the record is created, there is a confirmation screen. This is an optional step, but something I like to do.

Confirmation

Now that I have a flow in place, I create a button (Pied Piper) on the account layout.

Pied Piper Button

1 story point was spent on the clever name

This button is nothing fancy, just running a hyperlink that will open up the flow AND push over the accountID of the record the user is currently in. I did add the retURL on the end so that instead of a loop, the user is returned to the accounts page.

Behind the Curtain

Just to reiterate, this is the foundational work. You could implement this into production and have something that works but it isn’t going to be awesome. Here are the required proof shots!

 

As always, questions or comments, hit me up!

 

andrew

Delegation Made Awesome (Salesforce1Selfie Number2)

Standard

With my first salesforce1 selfie I took on user setup and reduced my “Click Load” when it comes to setting up users.

For this salesforcesforce1selfie, I am taking a swipe at the delegate process.

The org I support has quite a few approval processes and within these processes are a mix of related user (manager, for example) and named user approvals. Supporting these processes can be quite a challenge, especially around summer time since we are not using the delegate functionality. We have tried to roll out delegates, but never quite get off the ground with adoption. After taking a close look at the delegate function, reviewing notes from our last attempt and talking to the SFDC_IT team member I believe the lack of adoption is due to:

1)      No obvious click path to delegated approver screen (Click on Name, Click on Drop Down, Select “My Setttings”, Click on “Approver Settings”, enter delegate )

2)      Unable to start / stop time delegates

3)     Can’t turn on via mobile

4)     Too much mail if the Delegate is left “on” (See #2)

I believe that if I can add functionality that will help with the above, I can increase adoption of delegates. At the very least, like my clone user app, I can use it myself during the summer holiday season!

Hold on tight, here we go!

images

We got a long way to go and a short time to get there!

First things first, I needed to create an input method for my users that could be both easy to use and upfront. Therefore, I built out a custom object / tab combination, which I named “Out of Office”.

Out of Office

Can’t miss that!

I have as few entry fields as possible, both to speed the time to release but to also make it as easy as possible for the user:

1)      Start Time – Defaulted to current date

2)      End Time – User selectable date fieldThree Fields, one defaults

3)      Delegated Approver – Lookup field to user table

*Now, you might be reading this and shouting / typing furiously/ muttering about missed opportunities. I agree with you, and I feel certain that future revisions will get new / better functionality (Filtered Lookups, Approvals, On behalf of…etc), but this is about a good foundation to build on.

A quick look at workflows and I can see that I will have to do this with a combination of workflows and flows since I cannot update the Delegated Approver field with workflows, and

Narf

You know what I am talking about

In the interest of time, I am going to give an outline of the methods used to get this functionality up and running rather than the step by step.

Step 1, FUNctions used to update the delegate:

Workflow “OOTO Created” is triggered up on record creation. This workflow has two immediate actions, an email alert to both the delegate and the record owner and a flow trigger that runs a flow in the background that handles the actual update to the delegate. The flow really is basic, just a record update. I threw in a lookup out of habit.

2014-04-29 07_56_00-Presentation1.pptx - PowerPoint

The workflow also has a timed based action, which is the secret sauce. This time based action is based on “return date” – 0 and ticks the box “Back in Office”. Do not overlook the re-evaluate workflow rules after field change check box!

2014-04-30 08_30_30-Field Update_ Mark as returned ~ salesforce.com - Unlimited Edition

Step 2, FUNctions used to remove the delegate

Workflow “Remove Delegate” is ran when the field “Back in Office” is set to TRUE. This worklow has two elements (as I wrote it), but could get away with one. The main element is the flow trigger. This trigger launches another basic trigger that just deletes out the delegate from the record owner. The only thing special I did on this was to put in an extra field update in the flow so I can tell if it ran. I have a similar field update in my workflow. I found these to be very helpful when testing because I could visually observe how my updates were working.

2014-04-30 08_42_16-Workflow Rule_ Remove Delegate ~ salesforce.com - Unlimited Edition

Move along, nothing to see here

Now, for the brass tacks, how does it work? Well, it works pretty dang good. I have been monkeying around with this for a couple weeks now and I can attest to the basic functionality. The only real weak link in the process is that I cannot directly influence the field “Receive Approval Request Emails” setting via the flows. That, however, can be handled with business process.

2014-04-30 08_45_27-User Edit_ Andy Johnson ~ salesforce.com - Unlimited Edition

Curse You!

Now, for the 10,000 dollar question. How does it look on Mobile? Well my friends, it looks pretty darn good. Salesforce1 does such a nice job of packaging up the objects created that you get a very nice experience out of the box. This is such a nice contrast to previous mobile versions. I can focus now on making the user experience that much better.

2014-04-29 07_56_56-Presentation1.pptx - PowerPoint

Yeah, that is awesome

For example, I built out a field that shows a message based on a couple parameters: “if(Back_in_Office__c =FALSE,”Out of Office, returning “& text(Return_Date__c) ,”In Office”)”

I added this field to a new compact layout, and viola, the user can now, at a glance, see if they are in office or out of office, and if they are out of office, when they are coming back (NEVER!)

In OFfice

Awwww

Out of Office

Woo Hoo!

 

So there you have it, another piece of adminsitrivia solved with Salesforce, Visual Flows, and Salesforce1

 

Andrew

 

 

One (Flow) field to rule them all

Standard

I love it when in the course of an average day you have that moment when the light bulb gets turned to on, the heavens part and there in front of you is something new and exciting.

Image This is how my light bulb moments look, don’t judge me

For example, I was building out my clone user flow for #salesforce1selfies and started thinking about how I had my search page set up. It was fairly standard with a text box where I would enter in a user ID but like Freddy Mercury, I want it all.

I wanted to be able to search on name,email and user ID and I wanted to do it from within one text box.

Image“One field to rule them all, and in the flow logic bind them”

Really, it sounded pretty simple, but then again, you can sum up the lord of the rings trilogy by saying it was just about taking out the trash.

“All we have to do is throw the ring away, easy – peasy”.Image

 

Actually, it was easy…I mean, this was something I did while on my first cup of coffee. I started with my flow Mirepoix, input screen, query, output screen.

ImageIt’s just the base! You have to liven it up yourself!

To that base, I added in a decision with three outcomes:

Image

1)      Input Text “Starts With” “005”

Image

2)      Input Text Contains “@”

Image

3)      Else assume text is name

Image

These outcomes are each linked to a unique query and assignment:

1)      Input Text “Starts With” “005” –> Query ID with Input Text –> varMatchType = “UserID”

Image

2)      Input Text Contains “@” –> Query Email with Input Text –> varMatchType  = “Email”

Image

3)      Else assume text is name –> Query Name with Input Text –> varMatchType  = “Name”

Image

I put the varMatchType on as a visual debugger because I only have one output screen and I want to be able to see visually how I got there. Image

Fun and games aside, how does this work? Well, it works great! Here are some screen shots to prove it:

ImageImage

 

I would like to think it is because of my super ninja / bow / stealth / flow skills, but the reality is this is just a really good piece of functionality. I really like the potential here. Imagine creating one flow that does this type of analysis and routing…you could use it all over the place!

Hope you enjoyed this…questions or comments, let me know!

 

Andrew

Using a Salesforce formula to determine if a date is current or previous fiscal year

Standard

I wrote out this formula because there was a need for our customers to be able to quickly see if a date was in or out of a current fiscal year. The key component of this formula is to have a way of thinking that doesn’t think of a year as January 1 to December 31st but rather from “First day of Fiscal” to “Last day of Fiscal”.

 This formula could be used as a base if your company had a narrow criteria. The particular requirement I had was for plain text results for easier reporting.

CASE(
(if(Month(today())>9,Year(today())+1,Year(today())))-(if(
Month( <<YOURDATEHERE>> )>9,Year(<<YOURDATEHERE>>)+1,Year(<<YOURDATEHERE>>)
)),
1,”Previous FY”,
0,”Current FY”,
“Out of Scope”)

 

The nice thing with the plain text is that you get a data set that makes reporting SUPER easy because you can then group on that field and have subtotals running.

 

Enjoy the weekend!