I Wanna Flow Clone!

tumblr_mva7uoLfIh1sn7lxto1_1280

Brian and I talked about this on this week’s WizardNews WizardCast, but we thought perhaps a text-based walkthrough might be in order. So let’s talk about clones, baby.

The clone button on Salesforce records is great, for obvious reasons. But it has one major shortcoming: it brings over EVERYTHING.

Let’s say you want to clone a case, because a second client is having the exact same problem 3 months later. For one, it’s probably not going onto the same account, or have the same contact. For another, the Case Status probably needs to be reset to its earliest setting, since the original Case is (hopefully) closed.

But keep in mind that a mature Case object may have many fields that are NOT on the page layout, but nonetheless important to maintain. You may have an Approval Status that keeps track of approval steps but is hidden to prevent modification. You may have date fields that log when certain events occurred, but again, are hidden for security. You may have checkboxes or other fields verified by validation rules to ensure changes go through proper channels, like API or Flow.

These are all data points that you would NOT want to be brought over in a clone, because they are probably not going to be accurate for your new Flow.

So how to clone while still ensuring that existing data doesn’t become bad data? Simple! Flow!

Flows can be fired off of buttons, just like cloning, so that makes it an excellent candidate, plus Flow has the ability to read existing records and create new ones. Let’s take a quick look at what needs to be done.

We’re going to assume, to start with, that we’re going to be passing in the ID of the case we are cloning. We only need to pass that one piece of data in, because we can get the rest later. Let’s make a new variable: varCaseID. Don’t forget to make its Input/Output Type “Input Only”, so it can receive that data. If you leave it as Private, it’ll never be able to receive data passed to it.

Screen Shot 2015-04-08 at 14.10.32

Now that the Flow has a place to store which Case we are cloning, let’s get the rest of our fields. Create a Record Lookup, and set the filter to look on the Case object for a record where the Id is equal to our new variable, varCaseID. This is all you need to define, because you’ll only ever get one record with that ID!

Screen Shot 2015-04-08 at 14.13.34

In the section below, you will need to manually define which fields should get brought over in the clone. Yes, this may get tedious if you have a lot of fields that need to come over. But I would highly advise confirming with your stakeholders which data is truly needed. You’ll find most of your fellow employees or executives only want the data they really need, and are happy to let the rest go. You will need to store each of these data points in its own variable, and those variables can remain set as Private, because the Lookup will go and get the data; it’s not the same as having data pushed to it.

Screen Shot 2015-04-08 at 14.23.32

For the sake of this example, let’s assume the Account and Contact are the same; this is a whole other can of worms that would practically take a whole other article to examine properly.

Now that you have your old data brought over, we can begin creating our clone. All we need to do is add a Record Create to the Flow, and set it to create a new Case. Then, in the fields below, you can assign all of your variables to the proper case fields, like so:

Screen Shot 2015-04-08 at 14.29.12

That’s it! Draw an arrow between from the Lookup to the Create, and click the Start icon (the green arrow circle in the top right) on your Record Lookup so the Flow knows where to begin. You can now save your Flow, and create your Clone button.

Screen Shot 2015-04-08 at 14.38.16

Once you’ve saved your Flow, close it to get to the Flow’s information screen. On this screen, you’ll see a URL; copy this to your clipboard, you’ll need it in a second.

Screen Shot 2015-04-08 at 14.38.30

Now on to the button itself. I prefer calling the button something else, to reduce confusion. Something like SmartClone, to let you and the users know that this button is smarter than the average Clone. Before actually defining the button itself, I suggest changing the Behavior to “Display in Existing Window without Sidebar or Header”. This will effectively replace the contents of the users’ open tab when they click the button.

Now the URL for the button. Paste the URL you saved from your Flow, and add the following:

?varCaseID={!Case.Id}&retURL=/{!Case.Id}

Screen Shot 2015-04-08 at 14.44.05

Here’s the breakdown.

  • The ? is important because it lets Salesforce know to expect settings to be set in the URL. Each element we pass is essentially something we are setting this URL to do.
  • varCaseID – This is the variable we created, remember? Putting this here tells Salesforce we need to send something to this variable when the flow is started.
  • {!Case.Id} – This is a merge field that turns into the Case ID itself. You can generate this via the merge field operators right above the URL window, as always.
  • & – We can pass more than one piece of information, but we need to separate each one with a & symbol.
  • retURL – Here you can set where the Flow should go when it is done. If you do not set this, the Flow will just repeat over and over. By passing it / then the Case ID again, it knows to go back to the Case that started this.

It may help to put your varCaseID and your retURL on separate lines in the URL window. Adding line breaks won’t cause any problems, as they get ignored, and it makes your URL a lot more readable when you have to support/troubleshoot it later.

Voila! Put this on your case page layout, and you’ve got a SmartClone!

Advertisements

The New Way to Socialize at Dreamforce 2014

Influenza. Enterovirus. Ebola.

Ok, come back, it’s alright. Just reading the names won’t make you sick, alright?

It’s no secret that 2014 has been a bit of a banner year for infectious disease. And, not to scare anybody, but a LOT of us are about to all gather in a location with 150,000 other people from around the world, all at the same time. I don’t know about you, but that gives me just a liiiiittle pause.

But there is a solution! And it is a good one. Recently, the Harvard Medical School published its findings on the nature of hand-to-hand communications, and the likelihood of transmission of diseases in its different forms. The short version: fist bumps are a safer and cleaner alternative to handshakes.

That’s right, you read correctly. Harvard has officially stated that we should all be fist bumping.

fistbumpforhealth

Absurd as it sounds, there is a very strong logic to it. When we shake hands, anything that is in our palms or on our fingers is instantly transferred to the receiving hand, and vice versa. The slight amount of moisture we always have on our hands practically ensures that the transfer occurs, too. There’s no “10-second rule” either; those bugs move instantly as they are practically shoved into waiting hands.

With the fist bump, however, the likelihood of transfer is much lower, because the contact is not so wide-spread, there is less moisture and pressure being applied, and because of the drastically-reduced amount of microorganisms on the outside of our fingers.

So I propose this, fellow Dreamforce attendees: the (un)official greeting of Dreamforce 2014 should be the Fist Bump.

Now I know what you’re thinking. “But Mark, that’s so unprofessional!” Ah, my friends, “professional” is what you make it. “Professional” is basically another way of saying “extremely polite”, and what could be more polite than not passing on the DreamPox?

No no, hear me out! We can make the Fist Bump professional, right? Let’s set some guidelines, ok? Nothing says “professional” like rules and guidelines, am I right?

The Professional Bump is straight-trajectory, no-frills, and quick contact.

fist-slide

However, do not “explode” afterwards. This is tacky, and is therefore right out.

fist-explosion

Unless you’re doing it with a bald eagle.

fist-eagle

Maintain low velocity when jewelry is present. It is not professional to cause contusions.

fist-rings

The “guided strike” is inadvisable, as it defeats the purpose and further invades personal space.

fist_bush1016595i

Bumping in gloves is acceptable, so as to not facilitate the awkward pause of waiting for removal of said glove.

fist-wolvspid

Welp, here you have it, folks. If that doesn’t convince everyone to be slow-punchin’ at DF14, I don’t know what will. Just don’t be offended if I keep a bottle of Purell handy, ok? Love you.

Getting Record Type IDs in Flow without Hardcoding (UPDATED!)


check-yourself-before-you-wreck-yourself

Have you ever migrated your Salesforce data or fields into another org? Do you develop your new features in a Sandbox first? (And if not, WHY?)

If you answered “no” to both of these questions, ask yourself if you can safely say you will NEVER do so.

Chances are that any given admin will, at some point in their admin career, have to either migrate at least some part of your Salesforce, or at the very least be REQUIRED to build something complex in the Sandbox first, so as not to impact current process. If your company gets acquired, there’s a very good chance you’ll have to merge orgs.  One way or another, you’re probably going to be beholden to this fact of life. The business world necessitates preparedness for just such an eventuality.

Previously, I had thought this would never be a problem. I’d never had to release anything that was so impactful that I couldn’t build in production and delay its effect (pardon me a moment while I slap my own wrists). I didn’t anticipate a full org merge with another Salesforce org, though I really should have. So I didn’t foresee the pain that would be, the horror known as: HARD-CODED RECORD TYPE IDs.

hardcode

THEHORRROR

You may think that using hard-coded IDs is not a big deal, and if you only have one or two uses, it’s probably not. But over time, the practice can become pervasive in your admin methodology, and it will then grow well beyond those happy few. I mean, let’s face it, most of the time it’s a lot easier to deploy than other solutions, right? Just referencing a single ID is a lot simpler than writing the formulas, workarounds and methods needed to not use them, right?

The trick is, this trap has two kinds of cheese. The first is the fact that it’s usually easier, but the second is the fact that we as admins and developers often come to the conclusion that there is no workaround. Years ago this used to be the case, but today we have a lot more tools at our disposal, and many of the cases where we would be forced to use a hard-coded ID are not actually cases where we are truly forced, if we just keep working and digging at a solution.

Then I had an org merge to work. Because of our long-standing practices in our 5-year-old org, we had hundreds of single hard-coded IDs in our system. The trap had closed. In order to merge our system into theirs, we would have to reconcile ALL of those. We had a mountain of work ahead of us, because we had not looked ahead.

In working on solutions, I have developed a way to avoid hard-coded Record Type IDs in Visual Workflow. This has traditionally been a place which is widely considered to be inescapable for hard-coded IDs, but today I say thee NAY. There is a way!

(UPDATE: I had previously published a kludgey way of doing this, but it turns out there is a better way to do it that Salesforce has provided! Special thank you to MVP Aiden Martin for pointing out this exists!)

Screen Shot 2014-06-17 at 12.50.33

Create a Record Lookup, and when choosing what object you’re looking at, choose “RecordType“. Many an admin have glossed over that picklist choice, not even realizing it’s there, but this is an object usually referenced by Apex or API for the purposes of finding RecordType information. Because it’s in the API, we can use it in the Flow!

In your filters, choose “SobjectType” and set this to the object whose record type you are looking up. To determine which record type to use, I recommend using DeveloperName instead of just Name; the Name is the equivalent to the Record Type’s label, and is more likely to change. By basing it on the DeveloperName, you’re less likely to have issues with the name changing and breaking your flow.

Assign the Id value into a variable for use later and BOOM! You now have your Record Type ID stored in a variable for using later in your flow, and you didn’t have to manually enter it into the Flow. If the Record Type changes to a different ID in the future (and odds are it will), you will not be screwed. I REPEAT: you will NOT be screwed.