Parsing Stuff with Flows (Part 2)

Standard

In part 1, I built out the change of thinking that we will need in this blog post to amp up our data parsing using flows. For a quick recap:

  1. The scenario is that we have questions and answers
  2. The flow does the parsing by treating questions as keys
  3. We are using a text input in a flow to simulate the action of a user copy / pasting question answers into a text field

As demonstrated in the last post, this works within the context of a flow, but now in this post, I am going to show you how to apply this. To demonstrate this, I am going to add a text box onto both the lead record and contact record to receive data, two text boxes that will receive the parsed answers and a checkbox to display an error state. To launch this flow I am going to use a process builder on the lead and contact.

The process builder functionality is the same on leads and contacts. The ID will be passed to a variable in your flow. This variable is used by the flow to determine which update action to use. The input is also passed over to a variable. This does mean that for those following along at home that they will need to change their formulas from using a text box to using the formula. This is in addition to the changes needed to make it an autolaunched flow (Removing screens, etc).

Now, I did mention the whole error checking thing in my last post, so baked that in as well. The key here is to first check for errors THEN figure out which record needs to be flagged.

The end result will be something like this:

with error check

So, how does this work? Fan-Tas-Tic. With just two processes and a flow, I am able to do parsing on each record.

end results

Adding this parsing logic to a new record would just be adding a new process and updating your flow. This is a great example of how you can use flows to harness the power of apex with the ease and lower support cost of configuration.

Now, this is setup for a pretty specific example…A rep would be pasting in data from an external source, but the methodology would be the same as long as you had a source of text. So, with tweeking you could use this on fun stuff like inbound emails or maybe even chatter posts!

How does it feel? Not quite like this, but close.

I have the power.gif

 

 

Parsing Stuff with Flows (Part 1)

Standard

Salesforce is really good at a lot of things, but digesting or looking for bits of data within large chunks of text is not a particular strong suite, though to be fair, not may systems can brag about how awesome it’s parsing ability is. I was thinking about this subject since there seems to be two camps, the configuration camp backing workflows and formulas and the code camp backing apex. I am going to propose a bit different way…an adminveloper way.

To start with, we are going to use flows for this. The reason I am going to use a flow is that I want this as object agnostic as possible and I don’t want to be constrained by any of the formulaic limitations (Looking at you char limit of related formulas!). Using a flow will also let me do some fun stuff later on (cough, next blog post, cough), but the biggest reason I want to use flows is the variables.

But, before we get into the nuts and bolts, I need to first talk about how I changed my thinking about this. Let’s say I have some questions in a text field and I want to parse out the answers to these questions. In the past, I might have tried to hard code in some right / left functions, but that is rigid and leads to stuff like “Answer this question in less than 255 char…”, ugh. Instead of trying to build out left / right stuff that ignores questions, you need to think of questions as keys in your document. They are a unique set of text / numbers that should only occur once in your doc, and because we are thinking like this, we can use the FIND function to locate their specific points within the text.

For testing purposes, I am just building out a basic flow with a long text input field that will be parsed.

The flow will look for my “keys” (AKA, questions) and determine how much distance (in char) between the LAST CHAR of a question and the FIRST CHAR of the next question. For the last question, we are going to use a footer as the marker (“Thanks for your time!”).

I am going to do this with a series of formulas, one for each question:

  1. Find out how long the whole piece of text is (This is just a LEN(your text here), not going to expand it out.)
  2. Find out where each question ends
  3. Find out how long each answer is
  4. Build out the answer

Formula number two is finding out where the questions ends. To do this, you use the “find” function, looking for the variable within your text. Now, you need to ADD to this the length of the question since you are looking for the END of the question and FIND returns the char location. Here is what the formula looks like:

find({!varQuestion1},{!Enter_Sample_Text_Here})+len({!varQuestion1})

Now that we know where the first question ends, we need to find out how long the answer is. We do this by subtracting the value from the first formula from where the value of where the next question (or text) starts. I did it this way, though you could have also just used a new find function. In a nutshell, at this point, we have determined that the end of question 1 is X and the start of question 2 is Y and that the answer is Y-X long.

({!FindQuestion2}-len({!varQuestion2}))-{!FindQuestion1}

Knowing this, we are going to go ahead and build out the formula that strips out the answer from the text. It is going to use a combination of left and right functions. We are essentially grabbing all text to the RIGHT of the end of question1 and then taking just LEFT text of that in the length of the Answer

left(
right({!Enter_Sample_Text_Here},{!GetLen}-{!FindQuestion1}),{!Question1Length}-1)

For the last question, you would just use the footer location:

{!FindQuestion4}-{!FindFooter}

FindFooter = find(“Thanks for your time!”,{!Enter_Sample_Text_Here})

This is how this function would look just running it from a flow:

So yeah, with just a few formulas inside of a flow, parsing can be easy – peasy if you adjust your thinking. Now, before I leave you all hanging for part 2 of this blog post, let’s also take a look at something fun. What happens if someone starts to monkey with the questions? Well, through a little bippity boppity boo we can do something about it, without any more formulas. See we are using the FIND function already in the first formula that finds the end point of the question…and if the find function doesn’t get a match it returns a zero, thus, we know that if the formula that finds the end point of a question returns the length of the key variable something is off. This can be done with just a decision!

Alrighty, that is it for now! Part 2 is going to expand on this FUNctionalitye even more, so stay tuned!
As always, let me know if there are any questions / comments / or you just want to buy me coffee and pick my brain.

 

 

Quotable Quotes for 500 or how I learned to love SFDC CPQ.

Standard

Boy Howdy! It has certainly been a while since I have posted here! Hope everyone was missing me. I have a particularly interesting blog post for you all today…it explains my truancy AND talks about some neat stuff I have been doing!

51kdgksaudl

But, first, we have to go back in time to August 1…You see, on August 1, 2016, I made the jump from where I was to a funky little place called Auth0. There I was, admiring a shiny new macbook and an almost pure like driven snow org when my boss interrupted my revelry by saying:”Hey, glad to have you, we just got Steelbrick and you will be configuring it”. Jump forward to August 10th and I am installing into Sandbox. The next 55 days were a blur (Oh yeah, we went live last Friday, 55 business days after starting!) …taking training, reviewing documentation, asking questions, redoing, redoing and redoing… The net result is, however, that on October 28th we went live with Salesforce CPQ.

Now that you know the setup, let’s get on with the rest of the blog. First off, some high level process orientated goodies.

  • Have someone who knows the company build out the smartsheet workbook…and it should not be the sys admin. I am SUPER fortunate in that my boss was able to crank out the smartsheet doc for me to start with. If I had to do this myself, it would have been a huge timesuck.
  • As a sys admin, figure on 100% participation on this one. I am estimating an easy 400+ hours to get this puppy up and running. Of course, if you read this blog post and follow some of my suggestions, you should be able to shave at least 10% off that total. But, long story short, make it widely known that this is your priority.
  • Simplify where you can. Do you really need that approval step? Do you really want a listing for Product X that makes you no money and you only sell once per year?
  • Embrace the Chaos – things will change. Stay flexible, learn the tool and prepare!

OK –  think those are some good pieces of advice to start with. Now, let’s get into some fun stuff. Here are my top pieces of actual technical advice.

  • If you are running with basic approvals, build out your approval steps as formulas that can be referenced by the approval process. This is perhaps one of my favorite all around tips for salesforce, but super applicable here. Let’s say that you have an approval process that looks at a specific percentage field and you only want an approval to happen if that field is above 50%. IF you have activated that approval process and then need to make a change, you will have to clone / activate / test etc… However, if you make the approval step a yes / no formula that looks at your fields, you can adjust the formula without having to monkey with your approval steps.

~ What? You want SFDC specific stuff? OK – fine!~

  • Create an admin layout for quotes / quote lines. Seriously, go in there RIGHT NOW and do it. Then, add all the SFDCcPQ fields to that layout. This will save you a bunch of time.
  • On the topic of new things. Go forth and create a CPQ ADMIN App. You will then need to create a bunch of new tabs for it. I created tabs for block prices, line columns, actions (products / price), dimensions (products / price) and template sections. Throw that stuff along with the OOTB tabs on the admin app..you will thank me later.screen-shot-2016-10-31-at-1-43-50-pm
  • Replace the “New Quote” button. So, just for a good exercise, after installing the package, create a quote with the out of the box new quote button. It is brutal. I replaced this with a “Create Quote” button that uses a flow to bring over all the fields I need and also to ask any questions. The net result is that I get less confusion and a way faster process.
  • I also want to call out the field “Watermark Shown” on the quote layout. This field is what controls if a watermark is shown or not. Add it to your layout and be aware that it defaults to unchecked, so will have to devise a mechanism to default it to checked (Cough, flow, cough).

I think this covers the basic stuff. I will try to write more as I think of it. Overall, the experience was a good one. I would HIGHLY recommend that if you are a small shop and you can spare your sys admin for a couple weeks that you try and do this yourself. It is totally doable and as an upside, you get to know where all the dark corners are and how to fix stuff on your own.

Anyone else mess with SDFC CPQ? What has been your experience? Any specific section of the above post you want me to expand on?

Fuzzy Searching in Salesforce Flows

Standard

Salesforce flows are a magical thing, like good coffee at work and unicorns.

coffee unicorn.jpg

This is how I want my coffee delivered.

 

I have come to realize that there are limits to even the most magical things (BOOO!).

The limitation I have found in flows is around how you search for records…but, let me be clear, it really isn’t a big deal. For most people, finding records using the typical “equals”, “contains”, “starts with” and “ends with” functions will work just fine. I however, found myself going down a path where that wasn’t going to quite cut it. The challenge is how to search on a text input in a manner that is more google like. I don’t know what the kids now a days call it, but back in my day, we might call if “Fuzzy Matching”.

Fozzie_bear.png

Fuzzy, Not Fozzie!

For example, let’s revisit my Jaeger Dispatching System (Special Note, Pacific Rim 2 is scheduled). This system uses dynamic drop downs for the Jaegers, but, what happens when you have a bunch of Jaegers’?  You can build out a record search based on a text box, but, as mentioned before, you are limited to “equals”, “contains”, “starts with” and “ends with” functions. At this point, you might be saying, fine, just use a “contains” operator…and that would work, except what happens when the user spells something wrong? Contains is just two wild cards, so if you entered in “Dangur” instead of “Danger” you would not get a hit.

 

What happened next is pretty funny. I started thinking about how there are patterns in words…and then started thinking about how the pairs of letters could work. Spoiler alert, it totally worked. I proved it in Excel by just using a vlookup and some formulas, so I got pretty excited. It was then that I googled this matching pairs thing and found out that yep, some one wrote about all the fancy math behind it.

http://www.catalysoft.com/articles/StrikeAMatch.html

So, after building out the proof in Excel that this would work, I set about trying to get this to work in Salesforce…specifically a flow. I want to be able to enter in some characters into a text box and see returned results based on how well they matched my search term.

The first thing I did is create a field that removes the spaces from the Jaegers’ names and made them lower case. I don’t want it being “Cherno Alpha”, I wanted “chernoalpha”. This is done via formula field. If doing this in real life, I would build out my formula to also remove punctuation, but this is just for my Jaeger dispatch and my blog, so I am just removing spaces.

Thus, concludes the non flow part of this blog…what follows next is like 100% awesome, you have been warned.

TAKETHISCAT.jpg

Woot! FINALLY got to use this meme!

The first couple things are pretty basic, I have a start screen that has a text box. Next, I have a fast lookup on my Jaeger object. This gets all the Jaegers and puts them all in a collection. Next up is my loop, where I go through each Jaeger record. The only “gotcha” is that when you do the fastlookup, you need to bring over your formatted text from the record. Screen shots of this would be pretty boring, so here is a picture of all the giant robot toys.Jaeger Toys.jpg

Within the loop, I start with two assignments that copy the formatted Jaeger Name (no spaces) and the search string to variables.
I am going to use these variables for the rest of the functions, including the formulas. I take the search string that was entered and format it up.  I remove the spaces, count how many pairs I have and if the value has a remainder, I also remove the last character. I do this because otherwise the matched pair logic would be searching on a single digit, which would skew the results. The formula also checks if the search string is just 3 char, and if it is, it will treat these three char as one “pair”. Pictures and Text!

Formatted Search String

if(len(substitute({!Search_String},” “,””))<>3,
if(
mod(len(substitute({!Search_String},” “,””)),2)<>0,
left(substitute({!Search_String},” “,””),len(substitute({!Search_String},” “,””))-1),
substitute({!Search_String},” “,””)),substitute({!Search_String},” “,””))

Now I have to compare my first matched pair to the formatted name. of the search string that was formatted. I use a formula to get my matched pair:assignment - formatted search string.png

if(len(substitute({!Search_String},” “,””))<>3,
lower(left({!varSearchStringUseCopy},2)),lower(left({!varSearchStringUseCopy},3)))

 

The flow will next do a name check via the decision function. If the Formatted Jaeger Name contains the current matched pair, the flow adds a value of 1 to the counter variable and adds the current pair to a variable that will show the matches and the ID of the current record to another variable. Ugh, that was hard to read, here is a picture:assignment - match found

If the pair is NOT a match, well, I don’t really do anything with it but you might want to shove it to a debug variable. In fact, if you are starting this from scratch, I would HIGHLY suggest you do this!

Next up is yet another assignment, this time though, we are removing the pair was just searched on. This is done with, you guessed it, a formula:

if(len(substitute({!Search_String},” “,””))<>3,
substitute({!varSearchStringUseCopy},left({!varSearchStringUseCopy},2),””),substitute({!varSearchStringUseCopy},left({!varSearchStringUseCopy},3),””))

remove search string

Once that is completed, we check to see if there are more pairs to check. This is done by looking at the number of pairs left after the current pair is removed. This is in a formula I like to call “DisappearingSearchString”:

len({!varSearchStringUseCopy})

The whole process looks like this:

match process

If all the pairs have been used, the flow then checks to see if there were any matches with a decision point on the counter variable. If yes, then we add the matching data into a variable and then start the loop all over again. Because we will want to display some results in a table like format, be sure to append a text template that has a line break at the end of the string. To do this, create a text template with <br> in it.

build out result line.png

One of the things I really wanted was a way to see how many of the pairs were found in a given record. I do this with this formula:

({!varTripCount}/{!frmSearchStringPairs})*100

 

Before the loop starts all over again, any used variables are reset:

clear counters.png

So, enough talk! Let’s see how this works! For comparison purposes, I put in an alternate lookup that will use the “Contains” search function of what was entered in the input.

I also added more Jaegers, 8 in total!

Jaeger List.png

boom

 

First search string is going to be “Eureka”:

Eureka.png

and here are the results:Search Results - Eureka.png

The “Contains” function did what I expected and returned two records, “Striker Eureka” and “Eureka Smack”. However, it did not find “Striker Eurek”, but the matched pairs function did!

Let’s try this on another scenario. Suppose there is someone new in the Jaeger Dispatching Center and they forgot that it is “Cherno Alpha” and they enter in “Alpha Cherno”.

Search String.png

The “contains” search function would literally return ZERO results, whereas the matched pairs function would show an 80% match with Cherno Alpha.Results - Cherno Alpha.png

So, there you have it. With a bit of work, you can do fozzie…err…fuzzy search results with in a flow with Zero coding!

As always, if you have any questions, comments, or suggestions, please let me know!

Andrew

Cleaner Page Layouts using Flows and Formulas (1 of 3)

Standard

Back in the day, when I was just a transfer student at Everett Community College, “one week” was a hit single and I was a newbie coder taking visual basic.

(Your welcome for this ear worm)

During this class, we had a discussion on page layouts, that went a little something like this:

If you design a layout that has a bad tab order, and it reduces the speed of a transaction by one second, is it a big deal? Well, consider it this way: If your software is bought by a million people, and they can complete 500 transactions a day, your one second reduction of efficiency is costing the consumer 500000000 seconds per day…which is 8,333,333 minutes or 138,888 hours. If the average wage of those users is ten dollars an hour, your one second in efficiency now has cost 1.3million dollars per day.

Not even a Lego Calculator could make that discussion cool

With guilt trip thusly set to “argh”, I focused my efforts on UI design and making things work efficiently. Even now, I can remember the tab order of one of my first CRM’s I worked on…because it was out of order.

The stakes have changed since I was taking Visual Basic. I (we) support sales, and lost productivity is not simply about lost time, but about what your sales teams COULD have been doing. The math is pretty easy…and pretty scary:

Time spent clicking / scrolling / using salesforce in an inefficient manner

X by Number of times

X by Number of Users

X by days in year

= Time wasted = Money Lost = No free coffee

For the sake of this blog post, I am going to clean up the contact layout. I have sat with my users and estimated that they waste about 2 seconds every time they hit the layout  because of a section that Marketing has requested. This section consists of four check boxes, three text boxes and one URL field in a two column layout. This section was created for marketing and was placed near to the top of the layout in return for the data not being required. This section pushed a much more used section down below the scroll line (IE, users would have to scroll to see it). Marketing has given the OK on making this section not visible as long as there is some visual refernce to these fields still on the page layout.

A user will typically hit the contact layout 25 times per day and I have 25 users. If I can compact the layout, I should be able to reduce scroll time by about half, which should save about 45 (sales) hours per year. Notice, I didn’t just say hours, I said sales hours. Sure, saving 45 regular hours might not be much in the whole scheme of things, but sales hours is like a force multiplier. If you enabled your sales teams to have even a few more minutes per week, they can make a few more calls, make a few more emails, make a few more dollars.

Take a minute to enjoy this worn out cat.

Phew

I am beat just writing about this!

I am going to break this whole thing out into three distinct chunks:

1)      Create the Summarizing Formulas (In this blog)

2)      Create the Visual Prompts (Next Blog)

3)      Make Data Entry awesome with Flows (Next Next Blog)

Summarizing Formulas

Personally, I tend to write smaller, nested formulas that analyze bits and pieces of data. This makes it a bit easier (in my opinion) to write that final formula that presents the results to the user. While you could probably write this all in one huge formula, for the sake of troubleshooting and scalability, I am going to create the following fields:

1)      Create a formula to look at the 3 text fields (Return Type is Text)

Text(

if(len(Test_Text_1__c)>0,1,0)+

if(len(Test_Text_2__c)>0,1,0)+

if(len(Test_Text_3__c)>0,1,0))&” out of 3 populated; ”

Text Box Formula

2)      Create a formula to look at the URL field (Return Type is Text)

if(len(Test_URL__c)>0,”URL Present”,”URL Not Present”)

URL Formula

3)      Create a formula to look at the check box fields (Return Type is Text)

Text(

if(Example_Check_Box1__c=TRUE,1,0)+

if(Example_Check_Box_2__c=TRUE,1,0)+

if(Example_Check_Box_3__c=TRUE,1,0)+

if(Example_Check_Box_4__c=TRUE,1,0))&” out of 4 set to True; “Check Box Formula

4)      Create a formula to aggregate the above

Check_Example_CheckBox__c &” “& Check_Test_Text__c &” “& Check_Test_URL__cAggregate Formula

The net result is a field that will present the user with data facts not data entry points. Aside from having a cleaner layout, I a firm believer that if presented with text, most humans brains at least acknowlege that text before moving on. By reducing the clutter, you are making your overall page layout less fatiguing.

End Result

Individual Results

In the next post, I am going to discuss how we are going to visually prompt the user to give us data, but until then consider the other benefits of this type of functionality:

1) You could use these fields in reports to give better summaries

2) You could write validation rules off of these formulas rather than the individual fields

3) You could write workflows off of these formulas

See you all next week, same BatTime, same BatChannel where I will show you all how to kick it up a notch and grab your users attention!

Kick it up a notch

You totally thought I was doing Batman pic, weren’t you?

Andrew

Cleaning the data that matters…and not all data matters!

Standard

In my previous post, I alluded to a list of 5 concepts that make data cleansing a bit easier (Not fun, not easy – peasy but easier). In this post, I am going to expand on the concepts of “Knowing your data” and “Classify your data”

It's about half the battle

GI Joe talks about knowing

.But, before we get into the methodology and the doing, let’s talk about tools used. We are actually only using two tool to build out the functionality found with in this post, reports and formulas. However, because the methodologies discussed below is different than most organizations approach to cleaning data (Ocean…Boiling) there will be work on you to get folks bought into the ideas of not just trying to clean everything. So, I guess if you want to get technical, a third tool is the soft grey matter inside your noggin!

First things first. To help me “Know” and “Classify” my data, I am going to write a report that has two bucket fields, “Customer” and “Pipeline”. The bucket fields are looking at two custom field that are rollups counting the number of booked opportunities and the number of open opportunities. These are my two primary classifications because I am going to use a combination of these two classifications to score the value of an account to my company.

1)      Non Customer, No Pipeline (Least Valuable)

2)      Non Customer, Pipeline

3)      Customer, No Pipeline

4)      Customer, Pipeline (Most Valuable)

My fictional org for “Kramerica” wants all 481k of their accounts cleaned. Before jumping in and just starting to cleanse, I set up a report that breaks down an account based on past purchases and pipeline. Just by using two bucket fields, I can see that 14,000 accounts (About 3%) that are high value (Customer with Pipeline), 13,000 (3%) are medium value (Non Customer with Pipeline) and 54,000 accounts (11%) that are medium value (Customer No Pipe or Non Customer Pipe). I have just reduced the pool of accounts that should be cleansed by nearly 83%.

Numbers don't lie

Dry those eyes, it is not as bad as it seems

Unfortunately, there is still a number that is not very friendly standing between us and Maragriatville.

Margaritaville is real, google maps told me!

Which is just outside of Dallas apparently.

So, we are going to take things up a notch and write a set of formulas that will score the data that is entered on our account records. The folks in charge of data management (and that might be you), decided that Address, Phone and Website were most important. Yeah, I didn’t put state / country, but that is because of the change making it a picklist field, and we will just assume Kramerica is using the picklists. I am going to end up creating four formula fields. Three formulas will look at the data contained in the three fields. The fourth field will sum the scores of the three fields and then based on the totals, grade the data “Good”, “Acceptable” and “Poor”. The formulas don’t have to be complex, even something basic like if(len(FIELD=0,1,0), which will check for the presence of any data in those fields.

Just the ones that matter

In this case, red is good because red = less work!

That was a fun diversion, now, go back to the original reports with primary / secondary classifications. We add in the data grading field. Now, you can see how many of your most valuable accounts actually need the most help. In the case of Kramerica, we want to distil down that 14% (68k accounts) even further so we can focus on valuable accounts that have a data score of zero (no values in any of the fields) or one (at least one field has some data in it). Applying the formulas and the buckets to my data set reduces the amount of accounts I need to look at from 54,000 to 18,000.

I think this deserves a quick, bullet pointed recap:

–        Initial data set, 480k accounts

–        Valuable Accounts:

o   Customer / Pipeline (Most) 14,000

o   Pipeline / Non Customer 13,000

o   Customer / No Pipeline 54,000

–        Data scoring of valuable accounts:

o   Zero data score = 5,000

o   One data score = 13,000

–        Reduced my “need to clean” by nearly 90+%

My SFDC admin is amazing

I get this way whenever I shake loose a bit more time in the day.

Yeah, that is pretty awesome. However, there is the question of what do to with all those “other” accounts. Here is where it goes from awesome to AWESOME (in a monster truck voice). Since you have already established what makes an account valuable, once an account meets a certain threshold (gets pipeline), you know that it then needs to be cleaned up…and of course, you know what needs to be cleaned up because you are already scoring it.

2014-06-01 20_51_21-awesome monster truck - Google Search

 

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!

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