tag:blogger.com,1999:blog-24406292472243753102024-02-07T14:22:04.723-08:00Steve Fouracre BlogEmail me at sfouracre@selfevolvingsoftware.com
<br>
<a href="https://appexchange.salesforce.com/listingDetail?listingId=a0N3000000B5NNmEAN">My App</a>
<br>
<a href="http://success.salesforce.com/profileIdeas?type=Idea&u=00530000003aVmxAAE">Salesforce Ideas</a>
<br>
<a href="https://www.linkedin.com/profile/view?id=5749762&trk=nav_responsive_tab_profile">LinkedIn</a>
<br>
<a href="https://success.salesforce.com/profile?u=00530000003aVmxAAE">Salesforce Profile</a>Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.comBlogger64125tag:blogger.com,1999:blog-2440629247224375310.post-78650575378262922952017-08-11T11:15:00.001-07:002017-08-11T11:18:16.636-07:00<span style="background-color: white; font-family: Calibri, Helvetica, sans-serif, serif, EmojiFont; font-size: 16px;">A quick note to warn anyone that is planning to use the </span><span style="font-family: Calibri, Helvetica, sans-serif, serif, EmojiFont;">Salesforce Marketing Cloud and the affect on your data storage costs.</span><br />
<span style="font-family: Calibri, Helvetica, sans-serif, serif, EmojiFont;"><br /></span>
<span style="background-color: white; font-family: Calibri, Helvetica, sans-serif, serif, EmojiFont; font-size: 16px;">If you are setting up Marketing cloud watch out the affect it can have on data storage costs if you use Marketing Cloud connect. Marketing Cloud connect allows you to use data from Sales and Service cloud, however it also can store huge amounts of data on the Sales and Service cloud when you run your campaigns. You should look at configuring the Marketing cloud to only store aggregated email data in the Sales and Service cloud otherwise you may cause the customer to hit their data limits.</span>Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-1517868438984330662016-12-26T03:58:00.001-08:002016-12-26T04:02:05.308-08:00A Great Example Of What Can Be Made on Salesforce For Estate Agents<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibNnPhl2UO8YY36zhKl886NzZ2wVzgymTAZ3Yz6FObt61ej374d8CIN84KQJ-2lFcyMcOlm2x0WykCXKh4Z-gixqn0nAfKBbg1Qnhpl_WYGfnjISMjyRzY3skpk6ovBhO_VLfGHwy4IKmL/s1600/blinklogo.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="81" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibNnPhl2UO8YY36zhKl886NzZ2wVzgymTAZ3Yz6FObt61ej374d8CIN84KQJ-2lFcyMcOlm2x0WykCXKh4Z-gixqn0nAfKBbg1Qnhpl_WYGfnjISMjyRzY3skpk6ovBhO_VLfGHwy4IKmL/s200/blinklogo.jpg" width="200" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<h3>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Watch the introduction video to blink </span></h3>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/P3nLlwQ1n2s/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/P3nLlwQ1n2s?feature=player_embedded" width="320"></iframe></div>
<h3>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">More information can be found at <a href="http://www.selfevolvingsoftware.com/">www.selfevolvingsoftware.com</a></span></h3>
<br />Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-78994875660285792482016-05-31T00:08:00.002-07:002016-05-31T00:08:35.904-07:00Useful Summer 16 Features<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="background: white; color: red; font-family: Calibri; font-size: 14.0pt;">Cloning Sandboxes</span></b><span style="color: red; font-size: 14.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">You
can now create a sandbox by cloning an existing sandbox rather than using
your production org as your source. Save time by populating any type of
sandbox with a previously chosen set of data and metadata. (Sandbox
templates, which serve a similar purpose, are available only for Full or
Partial Copy Sandboxes.) Sandbox-to-sandbox cloning facilitates iterative
development, allowing you to freeze development in one sandbox and pick up
where you left off in a new one. This feature is available in both Lightning
Experience and Salesforce Classic.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="background: white; color: red; font-family: Calibri; font-size: 14.0pt;">Simplify Development of Asynchronous Callouts by
Using Named Credentials<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">You
can now use named credentials in long-running asynchronous callouts from a
Visualforce page’s controller. A named credential specifies the URL of a
callout endpoint and its required authentication parameters in one
definition. Salesforce manages all authentication for callouts that specify a
named credential as the callout endpoint so that your Apex code doesn’t have
to. You can also skip remote site settings, which are otherwise required for
callouts to external sites, for the site defined in the named credential.
This feature is available in both Lightning Experience and Salesforce Classic.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="background: white; color: red; font-family: Calibri; font-size: 14.0pt;">Get a Map of Populated SObject Fields<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">We’ve
added a method on the Apex SObject class that makes it more efficient to
iterate over fields that have been populated in memory. Previously, iterating
over just the populated the fields of an SObject involved some complicated
programming. For example, if you queried an SObject using SOQL, it wasn’t
easy to tell which fields were returned. In Summer ’16, we’ve introduced a
new method on the SObject class that returns a map of populated field names
and their corresponding values:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">Account
a = new Account();<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">a.name
= 'TestMapAccount1';<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">insert
a;<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">a
= [select Id,Name from Account where id=:a.Id];<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">Map
fieldsToValue = a.getPopulatedFieldsAsMap();<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">for
(String fieldName : fieldsToValue.keySet()){<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;"> System.debug('field name is ' + fieldName
+ ', value is ' <o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;"> + fieldsToValue.get(fieldName));<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">}<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">Admittedly
the example by Salesforce above isn’t amazing but if the SOQL was a dynamic
SOQL I can see a lot of benefit in this<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">You
can also perform without a SOQL<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">Account
a = new Account();<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">a.name
= 'TestMapAccount1';<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">insert
a;<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">Map
fieldsToValue = a.getPopulatedFieldsAsMap();<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">for
(String fieldName : fieldsToValue.keySet()){<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;"> System.debug('field name is ' + fieldName
+ ', value is ' + <o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;"> fieldsToValue.get(fieldName));<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">}<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="background: white; color: red; font-family: Calibri; font-size: 14.0pt;">EmailTemplate Functions<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<b><u><span style="font-family: "Courier New"; font-size: 10.0pt;">RenderEmailTemplateBodyResult
Class<o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<b><span style="font-family: "Courier New"; font-size: 10.0pt;">getMergedBody()</span></b><span style="font-family: "Courier New"; font-size: 10.0pt;"> Returns the rendered body
text with merge field references replaced with the corresponding record data.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<b><u><span style="font-family: "Courier New"; font-size: 10.0pt;">System.Messaging Class<o:p></o:p></span></u></b></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<b><span style="font-family: "Courier New"; font-size: 10.0pt;">renderEmailTemplate(whoId,
whatId, bodies)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">Returns
an array of RenderEmailTemplateBodyResult objects, each of which corresponds
to an element in the<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">supplied
array of text bodies. Each RenderEmailTemplateBodyResult provides a success
or failure indication<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">along
with either an error code or the rendered text.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<b><span style="font-family: "Courier New"; font-size: 10.0pt;">renderStoredEmailTemplate(templateId,
whoId, whatId)<o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">Renders
a text, custom, HTML, or Visualforce email template that exists in the
database into an instance of<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">Messaging.SingleEmailMessage.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="background: white; color: red; font-family: Calibri; font-size: 14.0pt;">$Resource Global Value Provider And Lightning<o:p></o:p></span></b></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<span style="font-family: "Courier New"; font-size: 10.0pt;">The
$Resource global value provider lets you reference images, style sheets, and
JavaScript code you’ve uploaded in static resources. Using $Resource lets you
reference assets by name, without worrying about the gory details of URLs or
file paths. You can use $Resource in Lightning components markup and within
JavaScript controller and helper code. To reference a specific resource in
component markup, use $Resource.resourceName within an expression. Include
CSS style sheets or JavaScript libraries into a component using the tag. To
obtain a reference to a static resource in JavaScript code, use <b>$A.get('$Resource.resourceName')</b>.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0cm; margin-left: 18.0pt; margin-right: 19.3pt; margin-top: 0cm; mso-layout-grid-align: none; text-align: justify; text-autospace: none;">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<br /></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com2tag:blogger.com,1999:blog-2440629247224375310.post-30108716425962752732016-05-21T14:37:00.001-07:002016-05-21T14:37:52.117-07:00Get a Map of Populated SObject Fields<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">We’ve added a method on the Apex SObject class that makes it more
efficient to iterate over fields that have been populated in memory.
Previously, iterating over just the populated the fields of an SObject involved
some complicated programming. For example, if you queried an SObject using
SOQL, it wasn’t easy to tell which fields were returned. In Summer ’16, we’ve
introduced a new method on the SObject class that returns a map of populated
field names and their corresponding values:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> Account a = new Account();<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> a.name = 'TestMapAccount1';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> insert a;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> a = [select Id,Name from Account where
id=:a.Id];<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> Map<String, Account>
fieldsToValue = a.getPopulatedFieldsAsMap();<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> for (String fieldName :
fieldsToValue.keySet()){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> System.debug('field name is ' +
fieldName + ', value is ' + <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> fieldsToValue.get(fieldName));<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="xmsonormal" style="background: white;">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">Admittedly the example by Salesforce
above isn’t amazing but if the SOQL was a dynamic SOQL I can see a lot of
benefit in this<o:p></o:p></span></div>
<div class="xmsonormal" style="background: white;">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">You can also perform without a SOQL</span><span style="color: #212121; font-family: Calibri; font-size: 11.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="color: #212121; font-family: Calibri; font-size: 11.0pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">ld names and their corresponding values:<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> Account a = new Account();<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> a.name = 'TestMapAccount1';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> insert a;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> Map<String, Account>
fieldsToValue = a.getPopulatedFieldsAsMap();<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> for (String fieldName : fieldsToValue.keySet()){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> System.debug('field name is ' +
fieldName + ', value is ' + <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> fieldsToValue.get(fieldName));<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="xmsonormal" style="background: white; margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<br />
<div class="MsoNormal">
<br /></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-8856007776037744152016-03-20T01:45:00.001-07:002016-03-20T01:45:12.624-07:00Salesforce PageBlockSections Styling ProblemsWhen you want to render displays of parts of a PageBlockSection because PageBlockSections and PageBlockSectionItems do not take the attribute Rendered you have to use Outputpanels to turn on and off the display of the PageBlockSection.<br />
<br />
The problem with this is that the Outputpanel interferes with the styling of the PageBlockSection and the PageBlockSection does not display properly.<br />
<br />
This can be seen in this example<br />
( you will need to create a controller class with the visualforce page ):<br />
<br />
The aim of this visualforce page is to simply display a button and when the button is pressed the entire Outputpanel is displayed.<br />
<div>
<div>
<br /></div>
</div>
<div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 635.4pt;" valign="top" width="847">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><apex:form><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlock</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> id="<span style="color: teal;">Results</span>"<span style="color: teal;">><o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"> <</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSection</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">title</span>=<i><span style="color: #2a00ff;">""</span></i>
<span style="color: #7f007f;">columns</span>=<i><span style="color: #2a00ff;">"1"</span></i> <span style="color: #7f007f;">collapsible</span>=<i><span style="color: #2a00ff;">"false"</span></i><span style="color: teal;">></span> <o:p></o:p></span></div>
<div class="MsoNormal">
<b><span style="font-family: 'Courier New'; font-size: 14pt;"> </span></b><b><span style="color: teal; font-family: "Courier New"; font-size: 14.0pt;"><</span></b><b><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 14.0pt;">apex:outputPanel</span></b><b><span style="font-family: "Courier New"; font-size: 14.0pt;"> <span style="color: #7f007f;">rendered</span>=<i><span style="color: #2a00ff;">"{!displaySelectedFrame}"</span></i> <span style="color: teal;">></span><o:p></o:p></span></b></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputLabel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">value</span>=<i><span style="color: #2a00ff;">"A Label"</span></i>
<span style="color: teal;">/></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">h1</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: 'Courier New'; font-size: 10pt;">{! frameworkName}</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">h1</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputLabel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">value</span>=<i><span style="color: #2a00ff;">"Description"</span></i>
<span style="color: teal;">/></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> {! description}</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<b><span style="color: teal; font-family: "Courier New"; font-size: 14.0pt;"> </</span></b><b><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 14.0pt;">apex:outputPanel</span></b><b><span style="color: teal; font-family: "Courier New"; font-size: 14.0pt;">></span></b><b><span style="font-family: "Courier New"; font-size: 14.0pt;"><o:p></o:p></span></b></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"> <apex:commandButton
value="Display Section" action="{!doSomething}"
rerender="Results" /><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSection</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"> </</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlock</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"> </apex:form><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
If you move the rendered to inside the PageBlockSectionItems it solves the styling issue but the entire section of the intended rendered area no longer collapses the PageBlockSectionItems so when the page starts there is a large white space created by the PageBlockSectionItems and so the styling is still not correct. This is shown in the following:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 635.4pt;" valign="top" width="847">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><apex:form><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlock</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> id="<span style="color: teal;">Results</span>"<span style="color: teal;">><o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSection</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">title</span>=<i><span style="color: #2a00ff;">""</span></i>
<span style="color: #7f007f;">columns</span>=<i><span style="color: #2a00ff;">"1"</span></i> <span style="color: #7f007f;">collapsible</span>=<i><span style="color: #2a00ff;">"false"</span></i><span style="color: teal;">></span> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> </span><b><span style="color: #7f007f; font-family: "Courier New"; font-size: 14.0pt;">rendered</span></b><b><span style="font-family: 'Courier New'; font-size: 14pt;">=</span></b><b><i><span style="color: #2a00ff; font-family: "Courier New"; font-size: 14.0pt;">"{!displaySelectedFrame}"</span></i></b><b><span style="color: teal; font-family: "Courier New"; font-size: 14.0pt;">></span></b><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputLabel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">value</span>=<i><span style="color: #2a00ff;">"A Label"</span></i>
<span style="color: teal;">/></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">h1</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: 'Courier New'; font-size: 10pt;">{! frameworkName}</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">h1</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">rendered</span>=<i><span style="color: #2a00ff;">"{!displaySelectedFrame}"</span></i>
<span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputLabel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">value</span>=<i><span style="color: #2a00ff;">"Description"</span></i>
<span style="color: teal;">/></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> {! description}</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"> <apex:commandButton
value="Display Section" action="{!doSomething}" rerender="Results" /><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSection</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"> </</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlock</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"> </apex:form><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<span style="font-family: "Courier New"; font-size: 10.0pt;"> </span> </div>
<div>
To solve both situations use a PageBlockSection inside the Outputpanel that renders the section that we are wanting to turn on/off the display. By having 2 PageBlockSections the problem is solved.</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 635.4pt;" valign="top" width="847">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><apex:form><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlock</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> id="<span style="color: teal;">Results</span>"<span style="color: teal;">><o:p></o:p></span></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSection</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">columns</span>=<i><span style="color: #2a00ff;">"1"</span></i>
<span style="color: #7f007f;">collapsible</span>=<i><span style="color: #2a00ff;">"false"</span></i><span style="color: teal;">></span> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">layout</span>=<i><span style="color: #2a00ff;">"block"</span></i>
<span style="color: #7f007f;">rendered</span>=<i><span style="color: #2a00ff;">"{!displaySelectedFrame}"</span></i> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<b><span style="font-family: 'Courier New'; font-size: 14pt;"> </span></b><b><span style="color: teal; font-family: "Courier New"; font-size: 14.0pt;"><</span></b><b><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 14.0pt;">apex:pageBlockSection</span></b><b><span style="font-family: "Courier New"; font-size: 14.0pt;"> <span style="color: #7f007f;">columns</span>=<i><span style="color: #2a00ff;">"1"</span></i>
<span style="color: #7f007f;">collapsible</span>=<i><span style="color: #2a00ff;">"false"</span></i><span style="color: teal;">></span><o:p></o:p></span></b></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">h1</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputLabel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">value</span>=<i><span style="color: #2a00ff;">"A Label"</span></i>
<span style="color: teal;">/></</span><span style="color: #3f7f7f;">h1</span><span style="color: teal;">><</span><span style="color: #3f7f7f;">br</span><span style="color: teal;">/></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> {!
frameworkName}</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">h1</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputLabel</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: #7f007f;">value</span>=<i><span style="color: #2a00ff;">"Description"</span></i>
<span style="color: teal;">/></</span><span style="color: #3f7f7f;">h1</span><span style="color: teal;">><</span><span style="color: #3f7f7f;">br</span><span style="color: teal;">/></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> {!
description}</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<b><span style="font-family: 'Courier New'; font-size: 14pt;"> </span></b><b><span style="color: teal; font-family: "Courier New"; font-size: 14.0pt;"></</span></b><b><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 14.0pt;">apex:pageBlockSection</span></b><b><span style="color: teal; font-family: "Courier New"; font-size: 14.0pt;">></span></b><b><span style="font-family: "Courier New"; font-size: 14.0pt;"><o:p></o:p></span></b></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">></span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"><</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="font-family: "Courier New"; font-size: 10.0pt;"> <span style="color: teal;">></span><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"> <apex:commandButton
value="Display Section" action="{!doSomething}"
rerender="Results" /><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSectionItem</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlockSection</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"> </</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:outputPanel</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"></</span><span style="color: #3f7f7f; font-family: "Courier New"; font-size: 10.0pt;">apex:pageBlock</span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;"> </apex:form><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
</div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-89939067189636336202016-03-05T00:05:00.003-08:002016-03-05T00:05:50.275-08:00Trigger Pattern Framework - session 2<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 90.0pt; mso-list: l0 level1 lfo1; tab-stops: list 90.0pt; text-indent: -18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 90.0pt; mso-list: l0 level1 lfo1; tab-stops: list 90.0pt; text-indent: -18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 90.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 90.0pt;">
<span style="text-indent: -24px;">In my last blog I introduced my Trigger Pattern Framework, now I will cover Trigger Control, which is one of the main improvements to other well documented frameworks.</span></div>
<div class="MsoNormal" style="margin-left: 90.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 90.0pt;">
DMLs are very processor intensive
and conserving this precious resource in a multitenant environment is ever more
so important.</div>
<div class="MsoNormal" style="margin-left: 90.0pt;">
So I built into my framework a
capability using a Custom Setting to activate / deactivate per trigger for any
User, Profile, or the entire Organization; or with a separate Custom Setting to
be able to activate / deactivate ALL triggers for any User, Profile, or the
entire Organization. This was great in situations where companies require
migrating data from 1 system to another and you want to safeguard that no
unwanted actions occur through the execution of code in the trigger.</div>
<div class="MsoNormal" style="margin-left: 90.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 90.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 90.0pt;">
However there are also many
situations such as in unit tests where we create test data, to avoid running
through all the code in triggers which is not necessary unless we are testing
specifically the triggers to disable the triggers using the Custom Settings
above will require running a DML and since we are trying to avoid DMLs because
they are expensive to run we need another mechanism to bypass the code in the
trigger, therefore we introduce a static variable to do this work. Here is a
section in the TriggerFactory class that controls the execution using these
methods and also the code from the calling classes that are used in this part
of the framework.</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">boolean notriggerSetting; <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> boolean
noTriggersPerObject;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> try{<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">
notriggerSetting = TriggerController.globalTriggerControlSetting(); <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">
noTriggersPerObject =
TriggerController.globalTriggerPerObjectControlSetting(objType); <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> catch
(Exception ex){system.debug('error in trigger controller ' + ex); }<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> Type soType = Type.forName(objType);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if (!notriggerSetting &&
!noTriggersPerObject &&
!TriggerController.getTriggerControlValue(soType,
TriggerController.TRIGGER_ALL)) { <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if (Trigger.isBefore){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if
(Trigger.isUpdate && !TriggerController.getTriggerControlValue(soType,
TriggerController.TRIGGER_UPDATE)){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> handler.beforeUpdate(Trigger.oldmap,
Trigger.newmap); <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(soType, TriggerController.TRIGGER_UPDATE), true); <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> else if
(Trigger.isDelete &&
!TriggerController.getTriggerControlValue(soType,
TriggerController.TRIGGER_DELETE)){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> handler.beforeDelete(Trigger.oldmap);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(soType, TriggerController.TRIGGER_DELETE), true); <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> else if
(Trigger.isInsert &&
!TriggerController.getTriggerControlValue(soType,
TriggerController.TRIGGER_INSERT)){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> handler.beforeInsert(Trigger.newmap); <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(soType, TriggerController.TRIGGER_INSERT), true);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> else if
(Trigger.isUnDelete &&
!TriggerController.getTriggerControlValue(soType,
TriggerController.TRIGGER_UNDELETE)){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> handler.beforeUnDelete(Trigger.oldmap);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(soType, TriggerController.TRIGGER_UNDELETE), true); <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> else{<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if
(Trigger.isUpdate &&
!TriggerController.getTriggerControlValue(soType,
TriggerController.TRIGGER_UPDATE)){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> handler.afterUpdate(Trigger.oldmap,
Trigger.newmap); <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(soType, TriggerController.TRIGGER_UPDATE), true);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> else if
(Trigger.isDelete && !TriggerController.getTriggerControlValue(soType,
TriggerController.TRIGGER_DELETE)){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> handler.afterDelete(Trigger.oldmap);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(soType, TriggerController.TRIGGER_DELETE), true);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> else if
(Trigger.isInsert &&
!TriggerController.getTriggerControlValue(soType,
TriggerController.TRIGGER_INSERT)){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> handler.afterInsert(Trigger.newmap); <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(soType, TriggerController.TRIGGER_INSERT), true);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> else if
(Trigger.isUnDelete &&
!TriggerController.getTriggerControlValue(soType,
TriggerController.TRIGGER_UNDELETE)){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> handler.afterUnDelete(Trigger.oldmap,
Trigger.newmap);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(soType, TriggerController.TRIGGER_UNDELETE), true);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">public class
TriggerController {<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static map<TriggerControlKeyValue,
boolean> triggerDisableMap = new map<TriggerControlKeyValue,
boolean>();<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static map<TriggerControlKeyValue,
boolean> triggerSuccessMap = new map<TriggerControlKeyValue,
boolean>();<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static final String TRIGGER_ALL = 'ALL';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static final String TRIGGER_INSERT =
'INSERT';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static final String TRIGGER_UPDATE =
'UPDATE';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static final String TRIGGER_DELETE =
'DELETE';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static final String TRIGGER_UNDELETE =
'UNDELETE';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static Boolean
getTriggerControlValue(System.Type objType, String triggerType){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerControlKeyValue tkv = new
TriggerControlKeyValue(objType ,triggerType);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> Boolean triggerDisable = false;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if (triggerDisableMap != null
&& triggerDisableMap.containskey(tkv))<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> triggerDisable =
triggerDisableMap.get(tkv);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> return triggerDisable; <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static void setTriggerControlValue(System.Type
objType, String triggerType, Boolean triggerDisable){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerControlKeyValue tkv = new
TriggerControlKeyValue(objType ,triggerType);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> for (TriggerControlKeyValue eachtk
: triggerDisableMap.keyset()){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if (eachtk == tkv){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> tkv
= eachtk; <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> break;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> triggerDisableMap.put(tkv,
triggerDisable); <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static Boolean
getTriggerSuccessValue(System.Type objType, String triggerType){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerControlKeyValue tkv = new
TriggerControlKeyValue(objType ,triggerType);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> Boolean triggerSuccess = false;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> for (TriggerControlKeyValue eachtk
: triggerSuccessMap.keyset()){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if (eachtk == tkv){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> triggerSuccess
= triggerSuccessMap.get(eachtk);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> break;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> return triggerSuccess; <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">public static boolean globalTriggerControlSetting(){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> return (((Triggers_Off__c.getOrgDefaults() != null)
? Triggers_Off__c.getOrgDefaults().value__c : false) ||
Triggers_Off__c.getInstance(UserInfo.getUserId()).value__c ||
Triggers_Off__c.getInstance(UserInfo.getProfileId()).value__c) ;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">}<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">public static boolean
globalTriggerPerObjectControlSetting(String obj){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if (obj != null && obj != '') {<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if (!obj.endswith('__c')) obj +=
'__c';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> boolean s = false;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if
(Trigger_Per_Object__c.getOrgDefaults() != null) s = (boolean)Trigger_Per_Object__c.getOrgDefaults().get(obj);<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> boolean t = false;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if
(Trigger_Per_Object__c.getInstance(UserInfo.getUserId()) != null) t =
(boolean)Trigger_Per_Object__c.getInstance(UserInfo.getUserId()).get(obj);<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> boolean u = false;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if (Trigger_Per_Object__c.getInstance(UserInfo.getProfileId())
!= null) u =
(boolean)Trigger_Per_Object__c.getInstance(UserInfo.getProfileId()).get(obj);<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if (s == null) s = false;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if (t == null) t = false;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if (u == null) u = false;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> return (s || t ||
u);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }else <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> return false;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">}<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">}<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">public class
TriggerControlKeyValue {<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">public system.type
objectType;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">public string triggerType;<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public TriggerControlKeyValue(system.type
thisObjectType, string thisTriggerType) {<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> objectType = thisObjectType;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> triggerType = thisTriggerType; <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public boolean equals(object obj){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> if (obj instanceof
TriggerControlKeyValue){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerControlKeyValue
t = (TriggerControlKeyValue)obj;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> return
(objectType.equals(t.objectType) && triggerType.equals(t.triggerType));<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> return false;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public integer hashCode(){<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> return system.hashCode(objectType)
* system.hashCode(triggerType);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">}<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 90.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 90.0pt;">
We also need to be able to unit
test the framework to test the trigger control has been built correctly and remains
operational. To test this part of the framework we don’t want to test the
outcomes from running each individual part of the trigger as the outcomes will
be different per trigger, instead we just need to test that the code passed
through the track of code we expect. For this purpose, another map is used.</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">@istest<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">public class
TriggerControllerTest {<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static TestDataCreation td = new
TestDataCreation();<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static Account acc;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static Triggers_Off__c trig; <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> public static Trigger_Per_Object__c trigPerObject; <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> static{<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> acc = td.insertAccount(null);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> static testMethod void AccountTriggerGlobalCSTest()
{<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //test global CS on/off<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> trig = td.insertTriggersOff(null);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> Test.startTest();<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //record should be
inserted <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //system.assert([Select
id From Account where Name=:defaultCusName].size() == 1);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.assert(TriggerController.getTriggerSuccessValue(Account.class,TriggerController.TRIGGER_INSERT)
== true);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //should change<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> acc.Name =
'ChangeCusName';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> update acc; <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.assert(TriggerController.getTriggerSuccessValue(Account.class,TriggerController.TRIGGER_UPDATE)
== true);<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //reset <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(Account.class, TriggerController.TRIGGER_UPDATE),
false);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> trig.value__c =
true;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> update trig;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //should not change<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> acc.Name =
'DefaultCusName';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> update acc; <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.assert(TriggerController.getTriggerSuccessValue(Account.class,TriggerController.TRIGGER_UPDATE)
== false);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //disable insert<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> test.stopTest();<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> static testMethod void
AccountTriggerPerObjectCSStaticTest() {<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //test trigger control using Per
Object CS<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> trigPerObject =
td.insertTriggersPerObject(null);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> Test.startTest();<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //reset<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(Account.class, TriggerController.TRIGGER_INSERT),
true);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //record should be
inserted but shouldnt set
Account_Insert_Succeeded <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> trigPerObject.Account__c
= true;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> update trigPerObject;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //reset <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(Account.class, TriggerController.TRIGGER_INSERT),
false);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.assert([Select
id From Account].size() == 1);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> Account acc2 =
td.insertAccount(null);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.assert([Select
id From Account].size() == 2);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.assert(TriggerController.getTriggerSuccessValue(Account.class,TriggerController.TRIGGER_INSERT)
== false);<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> test.stopTest();<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> } <o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> static testMethod void AccountTriggerGlobalStaticTest()
{<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //test trigger control using static
variables<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> Test.startTest();<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //disable update<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerDisableMap.put(new
TriggerControlKeyValue(Account.class, TriggerController.TRIGGER_ALL), true);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> acc.Name =
'ChangeCusName';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> update acc; <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.assert(TriggerController.getTriggerSuccessValue(Account.class,TriggerController.TRIGGER_UPDATE)
== false);<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //reset<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerDisableMap.put(new
TriggerControlKeyValue(Account.class, TriggerController.TRIGGER_ALL), false);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerDisableMap.put(new
TriggerControlKeyValue(Account.class, TriggerController.TRIGGER_UPDATE),
true);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> acc.Name =
'DefaultCusName';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> update acc; <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //should not change<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.assert(TriggerController.getTriggerSuccessValue(Account.class,TriggerController.TRIGGER_UPDATE)
== false);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //update should run<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(Account.class, TriggerController.TRIGGER_UPDATE),
false);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerDisableMap.put(new
TriggerControlKeyValue(Account.class, TriggerController.TRIGGER_UPDATE),
false);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> acc.Name =
'DefaultCusName';<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> update acc;<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.debug('##
TriggerController ' + TriggerController.triggerSuccessMap); <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.assert(TriggerController.getTriggerSuccessValue(Account.class,TriggerController.TRIGGER_UPDATE)
== true);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //test insert
trigger code off<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerSuccessMap.put(new
TriggerControlKeyValue(Account.class, TriggerController.TRIGGER_INSERT),
false);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> TriggerController.triggerDisableMap.put(new
TriggerControlKeyValue(Account.class, TriggerController.TRIGGER_INSERT),
true);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.assert([Select
id From Account].size() == 1);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> Account acc2 =
td.insertAccount(null);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.assert([Select
id From Account].size() == 2);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> //should not change<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> system.assert(TriggerController.getTriggerSuccessValue(Account.class,TriggerController.TRIGGER_INSERT)
== false);<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> test.stopTest();<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;"> }<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 10.0pt;">}<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal" style="margin-left: 90.0pt;">
<br /></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-8119370635791736012016-02-21T09:55:00.002-08:002016-02-27T02:17:53.581-08:00The Complete Unified Trigger Framework<div class="MsoNormal">
It has been a while since I wrote a blog for my readers but
Ive been working hard in developing a framework to improve your organisations
in a big way.</div>
<div class="MsoNormal">
I decided to turn my attention to triggers. There are many
well published trigger frameworks and all have merits in that they improve the
manageability of code, correctly orders execution, however as with everything
good technologists will continually evolve a model. I was impressed with Tony
Scotts <a href="http://developer.force.com/cookbook/recipe/trigger-pattern-for-tidy-streamlined-bulkified-triggers">http://developer.force.com/cookbook/recipe/trigger-pattern-for-tidy-streamlined-bulkified-triggers</a>
pattern as it simplifies the trigger.</div>
<div class="MsoNormal">
Independent to Hari Krishnan <a href="https://krishhari.wordpress.com/tag/apex-trigger-design-pattern/">https://krishhari.wordpress.com/tag/apex-trigger-design-pattern/</a>
I too noticed some room for improvement because Tony’s framework would require
continual adaption of the TriggerFactory for every new trigger that is
developed. The solution that I came up with was basically the same as Hari.</div>
<div class="MsoNormal">
However, I was concerned that all frameworks to date have
only been designed to solve the old problem of code manageability and order of
execution, but I always incorporated far more into my frameworks, notably the
following additional features:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 90.0pt; mso-list: l0 level1 lfo1; text-indent: -18.0pt;">
<!--[if !supportLists]-->1.<span style="font-size: 7pt; font-stretch: normal;">
</span><!--[endif]-->Trigger Control</div>
<div class="MsoNormal" style="margin-left: 90.0pt; mso-list: l0 level1 lfo1; text-indent: -18.0pt;">
<!--[if !supportLists]-->2.<span style="font-size: 7pt; font-stretch: normal;">
</span><!--[endif]-->Monitoring</div>
<div class="MsoNormal" style="margin-left: 90.0pt; mso-list: l0 level1 lfo1; text-indent: -18.0pt;">
<!--[if !supportLists]-->3.<span style="font-size: 7pt; font-stretch: normal;">
</span><!--[endif]-->DML Consolidation</div>
<div class="MsoNormal" style="margin-left: 72.0pt;">
<br /></div>
<br />
<div class="MsoNormal">
We will later explore these 3 facets of the framework in
more detail. Lets first of all have an overview of the building blocks of the
framework</div>
<div class="MsoNormal">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicpC0u3hfKBkMSmz16KEtXfkKwv7I4DbqWknsYjkz3WLZOEiUFSjCdKE-nQmgaqU5DuehtB2SpSxDGYgRyUseoSpNlOWDg9qYjv29m4nOIBYagxG-5bo1SIe-WjxCGxQagO1h5lShYVu_i/s1600/Trigger+Pattern+Framework.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="384" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicpC0u3hfKBkMSmz16KEtXfkKwv7I4DbqWknsYjkz3WLZOEiUFSjCdKE-nQmgaqU5DuehtB2SpSxDGYgRyUseoSpNlOWDg9qYjv29m4nOIBYagxG-5bo1SIe-WjxCGxQagO1h5lShYVu_i/s640/Trigger+Pattern+Framework.png" width="640" /></a></div>
<br /></div>
<div class="MsoNormal">
The classes in Red make up the baseline of the framework.
These classes do not need to be changed. The classes in Blue are classes that
will be created for each Trigger. You can create as many "Logic" classes
as you wish depending on the number of separate business areas and complexity
of codebase in your organisation. The "Account Helper" class is also
optional, this just aids the Logic classes and provides better modularised
code.</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
Of course we must have
the starting Trigger as well, shown as "AllAccountTrigger"
above.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="background-color: white; color: #373737; font-family: "helvetica neue" , "helvetica" , "arial" , sans-serif; font-size: 15px; line-height: 24.375px;">In the next blog I will go into details of each class.</span></div>
<div class="MsoNormal">
<span style="background-color: white; color: #373737; font-family: "helvetica neue" , "helvetica" , "arial" , sans-serif; font-size: 15px; line-height: 24.375px;"><br /></span></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-24415921983138163132016-02-19T11:11:00.001-08:002016-02-19T11:11:26.656-08:00Watch out for Time Based Workflows<div style="background-color: white; border: 0px; color: #373737; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; line-height: 22.1591px; margin-bottom: 1.625em; outline: 0px; padding: 0px; vertical-align: baseline;">
Time Based Workflows are very useful to action something in the future, which saves you writing scheduled jobs. But be careful, very careful.</div>
<div style="background-color: white; border: 0px; color: #373737; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; line-height: 22.1591px; margin-bottom: 1.625em; outline: 0px; padding: 0px; vertical-align: baseline;">
I will tell you a story. I had a very critical Time Based Workflow which if it didnt fire as expected it would severely affect revenue, but it had always run very smoothly so there was no expectation of that changing.</div>
<div style="background-color: white; border: 0px; color: #373737; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; line-height: 22.1591px; margin-bottom: 1.625em; outline: 0px; padding: 0px; vertical-align: baseline;">
Well we ended up creating a number of Time Based Workflows and typically each record would fire about 6 at different times. But since orders are coming in from many agents there were a lot of workflows firing. Unfortunately we not only hit our limit of 1000 per hour, but a large number were queueing up to enter the 1000 queue and so we could only see in monitoring section the same orders queueing and we thought that the Time Based Workflow had broken somehow.</div>
<div style="background-color: white; border: 0px; color: #373737; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; line-height: 22.1591px; margin-bottom: 1.625em; outline: 0px; padding: 0px; vertical-align: baseline;">
So, if you want to control when your actions will fire relative to say the creation or update of a record of course Time Based Workflow are ideal, but if the queue is clogged your actions wont fire as expected. So what do you do?</div>
<div style="background-color: white; border: 0px; color: #373737; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; line-height: 22.1591px; margin-bottom: 1.625em; outline: 0px; padding: 0px; vertical-align: baseline;">
You can take various actions, I will try to provide most cost effective methods to avoid coding which will be expensive:</div>
<ol style="background-color: white; border: 0px; color: #373737; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; line-height: 22.1591px; margin: 0px 0px 1.625em 2.5em; outline: 0px; padding: 0px; vertical-align: baseline;">
<li style="border: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Create a scheduled report to keep a track of how many records you expect will be in the queue. This will match the criteria clause of your Time Based Workflow. If the report shows there are too many queued make sure you have a script that manually process any remaining records.</li>
<li style="border: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">Carefully calculate how many you expect to be entering the queue at any specific time so you can plan if you will be well within your limits or not. If you expect the limit to be broken simply put in a business case to Salesforce for this to be increased. They will listen</li>
<li style="border: 0px; font-family: inherit; font-style: inherit; font-weight: inherit; margin: 0px; outline: 0px; padding: 0px; vertical-align: baseline;">If its not 100% necessary for all actions to occur at specific times relative to the workflow criteria then you can create a scheduled job to process any other records</li>
</ol>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-49822034100866167812015-11-15T02:46:00.000-08:002015-11-15T02:46:29.806-08:00How Should a Company Decide What Projects To Do<div class="MsoPlainText">
<span lang="X-NONE">This
could be achieved simply from having discussions between fellow employees, but
as more people become involved reaching consensus is often difficult.<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">Or to
a reach a consensus through analysis of ROI. However to derive accurate ROI you
will need to produce accurate estimates of work to deliver a project and derive
expected monetary benefits from projects, both of which will include
assumptions. Such assumptions need to be assessed for their reliability and are
themselves difficult to reach a consensus opinion.<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">Often
companies attempt to run with the former approach because it is easy to
implement, with varying degrees of success. In the early years of a company the
leadership of the company can often have enough knowledge of every aspect of
the company to make informed decisions of which projects to warrant. However as
the company grows this becomes increasingly difficult and so keeping with same
model brings less success. Companies eventually conclude that they must embrace
the latter approach of a more scientific analysis of ROI etc.<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">However
the difficulty to transition to such a model is huge.<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">A
company must first estimate ROI, many factors can influence this making it
difficult to estimate accurately. Such influencers include, how much will a
company make from a new product when released and this can be influenced in
turn by many factors such as how well a product is received by customers. <o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE"><br /></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">Once
an ROI is estimated, the team needs to also estimate how much work is required
to delivery the product. Companies and people vary on how accurate they are at
estimating this, often caused by many influences such as employee turnover, or
the business changing direction etc. <o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE"><br /></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">Lets
say a company can fairly accurately estimate both ROI and the required work
effort for ALL proposed projects. The business also needs to decide how it
should allocate money to individual areas of the company. Lets say this is
achieved as well, we now need to decide what work to do. Should this be solely
based on the difference between the cost and ROI as a ratio. Well if 1 project
will cost such a huge percentage of the overall budget many parts of the
company will be neglected which will be detrimental to those parts of the company
and good people may leave the company resulting in a long term sharper decline
in ROI. Also if reputation building projects are declined in father of other
higher ROI projects in the long term this can also have a huge negative affect,
as the retention rate of customers drops. Then there are projects that can lead
to the loss of important accreditations such as ISO, or projects which avoid
the company receiving fines, or projects that are enablers for future expansion
but provide little or no ROI now, and projects that reduces risk for the
company but produces no ROI such as producing data backups of systems.<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE"><br /></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">As you
can see even if a company moves to a more ROI decision based model a company
still needs to make many cognitive decisions that are not based on scientific
analysis of numbers, and in actual fact the number of overall decisions can
escalate.<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE"><br /></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">Can a
company even remove these decisions from the process. It is certainly possible
if you decide how much of a percentage of the overall budget a project can
consume, use some mathematical hypotheses testing of the assumptions, decide if
you want to spread projects throughout the company rather than concentrating
the budget on a select few projects; if you spread budgets throughout the
company the approach of doing this affectively must be decided, either based on
department size or department importance to the company or a mixture.<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE"><br /></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">Dividing
projects into logical groups can allow the company to select a diverse set of
projects to provide benefit in various ways and not simply to solely focus on
ROI, such as:<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">1.
Positive ROI projects<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">2.
Reputation building projects<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">3.
Accreditation projects<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">4.
Employee well being projects<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">5.
Business risk reducing projects<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">6.
Future positioning projects<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">As a
company you can decide on percentage weightings of importance of the above
categories.<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">Then
you also need to decide on the spread of budgets to the departments, broadly
speaking split into the following categories, but this will vary per company:<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">1. Finance<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">2. IT<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">3.
Sales and Marketing<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">4. HR<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">5.
Property<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">6.
Legal<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">7.
Customer Service<o:p></o:p></span></div>
<div class="MsoPlainText">
<span lang="X-NONE">8.
Media<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">Each
of the above are usually sub-divided many times<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">Now
you can start deciding what budgets can be provided to teams, making sure that
the projects decided produce the even distribution of budget for the 6 type of
projects outlined above.<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">Once
you have run a year long or even longer sequence of releases analyse if the ROI
produced is as expected and then further refine your model based on this input.<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">Since
following the ROI approach requires a huge amount of analysis it requires a lot
of resource to effectively derive to reliable decision making, consequently the
cost of which can often prohibit smaller companies adopting this approach. And
a company must decide during its natural evolution what is the appropriate
stage when it should transgress to an ROI approach.<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">Also
since the ROI approach is vastly more complex than the approach of simply
trusting in the leadership to make the right decisions, and unless every aspect
outlined above is scrutinised and analysed to a minute detail, for all proposed
projects, the effectiveness of this decision approach is undermined. In summary
if a company follows the ROI approach it must do it very well to make it
effective.<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">The
drawback of following this model of giving autonomy to departments to decide
where and how to spend their budget is employees rarely consider that they will
remain with their company in 5 or 10 years, so following this model employees will
naturally have a more short term viewpoint when deciding where and how to spend
their departments' budget.<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">There
is however another model that a company can follow which takes a more
democratic approach, taking everyone's voting of vision cards ( basic
blueprints of ideas ). Only issues with this model is that very good ideas may
not get supported and can become more of an employee popularity contest than an
idea contest. Secondly, employees may simply not understand all vision cards
and the benefits because a finance executive will have little understanding of
the issues faced in IT and so how can that person vote on ideas presented by
IT; of course you can limit what employees can vote on; but this then really
drifts towards the 2nd model rather than this model. Thirdly, this model
doesn't address employees having a more short term view, and only the 1st model
addresses this.<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<span lang="X-NONE">What I
am demonstrating here is that the simple decision of what should a company do
is never simple, but actually is the most important decisions that a company
makes, and inherently the approach it takes to make these decisions is crucial
to the success of the company. And importantly the approach should be
continually assessed and improved per year.<o:p></o:p></span></div>
<div class="MsoPlainText">
<br /></div>
<br />
<div class="MsoPlainText">
<br /></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-6745883876701610632015-10-25T02:17:00.001-07:002015-10-25T02:17:43.666-07:00A Useful Winter 16 Function<div class="MsoNormal">
Not many people will notice a small function in the winter
16 release which has potential to help the performance considerable of the
entire platform, if we all use this function wisely.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
System.SObject Class</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
recalculateFormulas()</div>
<div class="MsoNormal">
Recalculates all formula fields on an sObject, and sets
updated field values. Rather than inserting or updating objects each time you
want to test changes to your formula logic, call this method and inspect your
new field values. Then make further logic</div>
<div class="MsoNormal">
changes as needed.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
For example :</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
You want to insert an Account in a testmethod and you are
wanting to test that your formulas will be calculated correctly. Previously you
would have to perform a DML. And we all know how expensive DMLs are for the
platform. This little formula bypasses the need to do the DML.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Say your Account is quite basic and has several formula
fields.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Account acc = new Account(Name='Steves Test');</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
//Now test a formula field StevesFormula__c to have the
"This is a test" as the value without doing a DML</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
acc. recalculateFormulas();</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
system.assert(acc.StevesFormula__c == ' This is a test');</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<br /></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-85677812965456903562015-10-24T08:12:00.004-07:002015-10-24T08:19:20.763-07:00The New World Of Debugging<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="background: white; color: #333333; font-family: Helvetica; font-size: 9.0pt; mso-bidi-font-family: Helvetica;">I cannot begin to describe how Im feeling. Im just so excited. Have you
seen the new debugging capabilities in Eclipse and the Developer Console. If
you havent stop what you are doing now. If you are drinking a nice bottle of Moet,
or you are digging into some nice chocolate cake. Stop! Open up Salesforce and
have a look.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="background: white; color: #333333; font-family: Helvetica; font-size: 9.0pt; mso-bidi-font-family: Helvetica;">But is this exciting, is this thrilling, well for some it isnt, but for
me god damn it is. Why?<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="background: white; color: #333333; font-family: Helvetica; font-size: 9.0pt; mso-bidi-font-family: Helvetica;">With these tools you will be able to develop faster and so release
faster and so satisfy your stakeholders and keep them happy.<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<span style="background: white; color: #333333; font-family: Helvetica; font-size: 9.0pt; mso-bidi-font-family: Helvetica;">You can now do the following:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 54.0pt; mso-list: l0 level1 lfo1; tab-stops: list 54.0pt; text-indent: -18.0pt;">
<h2>
<span style="color: red;"><span style="color: red; font-family: Helvetica; font-size: 14.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: Helvetica;">1.<span style="font-family: 'Times New Roman'; font-size: 7pt; font-stretch: normal;">
</span></span><!--[endif]--></span><span style="background: white; color: red; font-family: Helvetica; font-size: 14.0pt; mso-bidi-font-family: Helvetica;"><span style="color: red;">You can run
individual test methods in a test class</span><o:p></o:p></span></h2>
</div>
<div class="MsoNormal">
<span style="font-family: MyriadPro-LightSemiCn; font-size: 10.0pt; mso-bidi-font-family: MyriadPro-LightSemiCn;"> <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: MyriadPro-LightSemiCn; font-size: 10.0pt; mso-bidi-font-family: MyriadPro-LightSemiCn;"> You can
now select individual test methods from your test classes to<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<span style="font-family: MyriadPro-LightSemiCn; font-size: 10.0pt; mso-bidi-font-family: MyriadPro-LightSemiCn;">include
in a run. You can also choose whether to run tests synchronously, and you can
rerun only the failed tests<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj32CkL8v9AMi2JSyQFCNKF-UJjsh-UoltDsbT8sMne1SeSnKJPcdYSs9O-HDwZfCbqavVeVKXJPlOhiDd4I-xGElzHTJFz7fXmWfdMrgb3CM41vgJBJnKdHL2diJafAem7FH7XQHrKvzhy/s1600/testmethods.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj32CkL8v9AMi2JSyQFCNKF-UJjsh-UoltDsbT8sMne1SeSnKJPcdYSs9O-HDwZfCbqavVeVKXJPlOhiDd4I-xGElzHTJFz7fXmWfdMrgb3CM41vgJBJnKdHL2diJafAem7FH7XQHrKvzhy/s320/testmethods.png" width="320" /></a></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<span style="font-family: MyriadPro-LightSemiCn; font-size: 10.0pt; mso-bidi-font-family: MyriadPro-LightSemiCn;">Oh
I was 1 of the people suggesting this many years ago on IdeasExchange<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 54.0pt; mso-list: l0 level1 lfo1; tab-stops: list 54.0pt; text-indent: -18.0pt;">
<h2>
<span style="color: red;"><span style="color: red; font-family: Helvetica; font-size: 14.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: Helvetica;">2.<span style="font-family: 'Times New Roman'; font-size: 7pt; font-stretch: normal;">
</span></span><!--[endif]--></span><span style="background: white; color: red; font-family: Helvetica; font-size: 14.0pt; mso-bidi-font-family: Helvetica;"><span style="color: red;">If you have hit
debugging levels regardless of what logging level you set, you can now start
your debugging at a specific point in your code to prevent this</span><o:p></o:p></span></h2>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
Trace flags now include a
customizable duration. You can also reuse debug levels across trace flags and
control which debug logs to generate more easily than ever before. This feature
is available in both Lightning Experience and Salesforce Classic. A debug level
is a set of log levels for debug log categories: Database, Workflow,
Validation, and so on. A trace flag includes a debug level, a start time, an
end time, and a log type. The log types are DEVELOPER_LOG, USER_DEBUG, and
CLASS_TRACING. When you open the Developer Console, it sets a DEVELOPER_LOG
trace flag to log your activities. USER_DEBUG trace flags cause logging of an
individual user’s activities. CLASS_TRACING trace flags override logging levels
for Apex classes and triggers, but don’t generate logs.</div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
Debug > Change Log Levels</div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 54.0pt; mso-list: l0 level1 lfo1; tab-stops: list 54.0pt; text-indent: -18.0pt;">
<h2>
<span style="color: red;"><span style="color: red; font-family: Helvetica; font-size: 14.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: Helvetica;">3.<span style="font-family: 'Times New Roman'; font-size: 7pt; font-stretch: normal;">
</span></span><!--[endif]--></span><span style="background: white; color: red; font-family: Helvetica; font-size: 14.0pt; mso-bidi-font-family: Helvetica;"><span style="color: red;">Of course there are
other features you should check out. Such as all the Analysis features, go to </span></span></h2>
<h2>
<span style="background: white; color: red; font-family: Helvetica; font-size: 14.0pt; mso-bidi-font-family: Helvetica;">Debug > Switch Perspective > Analysis<o:p></o:p></span></h2>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
You can check any limits that you
may be approaching. </div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
You can check how long it takes
to run certain functions and what actions occur when during execution.</div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
You can see the order of
execution in a tree diagram and other various ways</div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
You can trace variables as they
change in your code</div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 54.0pt; mso-list: l0 level1 lfo1; tab-stops: list 54.0pt; text-indent: -18.0pt;">
<h2>
<span style="color: red;"><span style="color: red; font-family: Helvetica; font-size: 14.0pt; mso-bidi-font-family: Helvetica; mso-fareast-font-family: Helvetica;">4.<span style="font-family: 'Times New Roman'; font-size: 7pt; font-stretch: normal;">
</span></span><!--[endif]--><span style="background: white; color: red; font-family: Helvetica; font-size: 14.0pt; mso-bidi-font-family: Helvetica;">Eclipse debugging<o:p></o:p></span></span></h2>
</div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
Use the Apex Debugger to complete
the following actions. </div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
• Set breakpoints in Apex classes
and triggers. </div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
• View variables, including
sObject types, collections, and Apex System types. • View the call stack,
including triggers activated by Apex Data Manipulation Language (DML),
method-to-method calls, and variables. </div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
• Interact with global classes,
exceptions, and triggers from your installed managed packages. When you inspect
objects that have managed types that aren’t visible to you, only global
variables are displayed in the variable inspection pane.</div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
• Complete standard debugging actions,
including step into, over, and out, and run to breakpoint. </div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
• Output your results to the
Console window.</div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<!--[if gte vml 1]><v:shape id="_x0000_i1026"
type="#_x0000_t75" style='width:415.5pt;height:357pt'>
<v:imagedata src="file:///C:\Users\Steve\AppData\Local\Temp\msohtml1\01\clip_image003.png"
o:title="Eclipse debug"/>
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU1_z6wepgP5N0c-hEWcVrd_qt6N8YYazzoWbru6iiBsVet70Uyga37oWVhD2X9T6yklEl7rjViIRCiu0RqUByaFxdxHUNJgm4NvxrzkdWgSLcndevQVTPcsaT4vjKFm8JZZkt-UK1wU1x/s1600/Eclipse+debug.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="275" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU1_z6wepgP5N0c-hEWcVrd_qt6N8YYazzoWbru6iiBsVet70Uyga37oWVhD2X9T6yklEl7rjViIRCiu0RqUByaFxdxHUNJgm4NvxrzkdWgSLcndevQVTPcsaT4vjKFm8JZZkt-UK1wU1x/s320/Eclipse+debug.png" width="320" /></a></div>
<br />
<br />
<div class="MsoNormal" style="margin-left: 36.0pt;">
<br /></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-56287245269262500542015-10-03T10:54:00.002-07:002015-10-03T10:54:18.360-07:00The Importance Of Estimating Requirements <div class="MsoNormal" style="margin-top: 12.0pt;">
<b><span style="color: red; font-family: Arial; font-size: 16.0pt;">The Importance Of Estimating Requirements <o:p></o:p></span></b></div>
<div class="MsoNormal" style="margin-top: 12.0pt;">
<b><span style="color: red; font-family: Arial; font-size: 16.0pt;"><br /></span></b></div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
I havent been blogging for a while mainly because Ive been doing some DIY work in my house, so although my blogging and my readers have suffered my kitchen is looking much better<strong> .</strong></div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
In this blog Id like to talk about Estimation, something developers dont like much.</div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
Estimating requirements and estimating accurately is more important than most developers think it is. Most think it is just another administration task that stops them developing, but without it companies struggle to operate correctly.</div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
There are different types of estimating such as using story points http://scrummethodology.com/scrum-effort-estimation-and-story-points/. Or using estimating by time.</div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
Personally I suggest it doesnt really matter which method you chose to estimate stories. Remember a story at this stage has the basic outline of the work and not the detail, so the estimate is a very approximate one.</div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
<br /></div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
But if I were to chose a method I would chose estimate by time. The reasons are, time is a universally known gauge and doesnt need to be calibrated; when new members enter your team with story points they need to be taught what your story base point is, whereas with time you dont; if you have more than 1 team in your company each team may have a different story base point and so if you move staff around teams this can be confusing for the team members and lead to inaccuracies. Another benefit of using time is that this can be used to calculate forecasted budgets much easier, whereas if you use story points you first need to translate this into its equivalent time then to work out the forecasted budgets. Of course you could argue if you are working on a set sprint length of say 2 weeks and you can complete 5 story points per person in that 2 weeks then this is the only translation into time that you need.</div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
As it comes closer to the project development start date more finer detail of the requirements are gathered and the stories are broken down into small individual tasks.</div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
Some teams believe they only need to refine the story points they gave at the beginning and then calculate how many stories they can fit into a sprint, based on the priority of the stories.</div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
I agree on the overall concept of this but I believe the individual tasks should be sized themselves. The only issue here if you use story points you can a scenario where you have 0.1 story points and so this undermines the value of using story points on Tasks of the Stories.</div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
<br /></div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
Many teams dont bother entering their actual time spent on Tasks or Stories. Is it really required if you say you are going to deliver 15 Story points in a 2 week sprint and that is exactly what you do deliver, does it really matter if you log your actual time. Well I would argue it does.</div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
Say for example you have 2 Stories and say you use time to size Stories, if you estimate that both Story 1 and 2 will take 1 week each to complete, but in reality Story 1 took just 2 days to complete but Story 2 took 8 days. Both Stories were still completed exactly on time that was estimated, but actually in reality the team is very bad at estimating and this should be improved.</div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
In the next sprint the team could get it very wrong and grossly under-estimate both Stories and only deliver 1 of them.</div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
The trade-off however is the extra administration time required to enter actual time worked.</div>
<div style="color: #333333; font-family: 'Helvetica Neue', Helvetica, Arial, 'Nimbus Sans L', sans-serif; font-size: 15px; line-height: 24.375px; margin-bottom: 1.625em;">
So on balance I would suggest use time to estimate both Stories and Tasks. Start with entering Actual time until you prove the accuracy of your estimating at both the Story and Task level. Once you prove a consistently high % accuracy level across all team members you can remove the extra administration required to log actual time. Of course if new your team changes considerably you may need to restart the actual time logging for a period.</div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-24014039968124369932015-08-16T03:41:00.001-07:002015-08-16T03:41:03.898-07:00A Generic Recursive Runtime Decision Making Batch Class<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Previously you could only execute 5 batches jobs from any
single context </div>
<div class="MsoNormal">
But one of my ideas on IdeasExchange was included in a recent Salesforce Release now you execute up to 100 batches which become queued in the AsyncApexJob object</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
What I'd like to cover in this blog, <b>a generic recursive runtime decision making batch class</b>. </div>
<div class="MsoNormal">
We will make a class that requires little change and can
serve and batch processing for any batch. </div>
<div class="MsoNormal">
There are situations whereby once a batch has fully executed
you want to initiate another batch:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 39.0pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]-->1.<span style="font-size: 7pt; font-stretch: normal;"> </span><!--[endif]-->The
first batch executes as many operations as it can and then initiates a decision
process that either executes the same batch process again or ends the
executions</div>
<div class="MsoNormal" style="margin-left: 21.0pt;">
<br /></div>
<div class="MsoNormal">
Situations
where this scenario can be used:</div>
<div class="MsoNormal" style="margin-left: 75.0pt; mso-list: l0 level2 lfo1; tab-stops: list 75.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]-->a.<span style="font-size: 7pt; font-stretch: normal;"> </span><!--[endif]-->A
callout to a 3rd party system and you dont know how many records exist in the
3rd party system</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal" style="margin-left: 21.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 39.0pt; mso-list: l0 level1 lfo1; tab-stops: list 39.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]-->2.<span style="font-size: 7pt; font-stretch: normal;"> </span><!--[endif]-->After
the first batch executes, records are set into a state that now allows a
different batch to execute. Of course the second batch could be scheduled for a
certain time but there is no way of knowing when the 1st batch will complete
and so you have to space batches apart. If it is important to complete the
operations in a timely fashion you will want to execute the 2nd batch
immediately when the 1st batch completes</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Situations
where this scenario can be used:</div>
<div class="MsoNormal" style="margin-left: 75.0pt; mso-list: l1 level2 lfo2; tab-stops: list 75.0pt; text-indent: -18.0pt;">
<!--[if !supportLists]-->a.<span style="font-size: 7pt; font-stretch: normal;"> </span><!--[endif]-->The
1st batch updates a field on the Account which fires a trigger and workflows.
This sets conditions on say the Contact object by updating various fields. The
2nd batch now picks up records on the Contact where this field has been
updated. So we need the 1st batch to complete for the 2nd to process.</div>
<div class="MsoNormal" style="margin-left: 57.0pt;">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Lets consider a situation where a batch makes a call to a
3rd party system requesting for a number of records, but due to payload limitations
the 3rd party can only return a certain number of records and the 3rd party
doesn't provide a means of identifying how many records there are in the 3rd
party because such a call drains system resources on the 3rd party. </div>
<div class="MsoNormal">
So we need to setup a batch class that makes a call to the
3rd party and retrieves X number of records. When the batch falls into the
Finish() we call a decision method which identifies how many records were
processed which tells us if we have processed the last batch or not.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public with sharing class Constants {</div>
<div class="MsoNormal">
public
static final string CONST_DOWNLOAD = 'DOWNLOAD 3rd PARTY'; </div>
<div class="MsoNormal">
}<span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
global class batchProcess implements
Database.Batchable<sObject>, Database.Stateful,
Database.AllowsCallouts{</div>
<div class="MsoNormal">
global
integer mx; //number
of records to process</div>
<div class="MsoNormal">
global
String batchType; //identifies
which batch processing to call</div>
<div class="MsoNormal">
global
String soql; //the
soql query if the batch is to make a query to feed records into the Execute()</div>
<div class="MsoNormal">
global
Map<String,String> vars; //this
holds any arguments that are to be passed to the batch function in the
Execute()</div>
<div class="MsoNormal">
global
Boolean success; //determines
if the last batch execution was successful, if it wasnt we might decide to
stop any further batch processing since there is a possibly a fault has been
encountered</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
global
batchDownloadCurrentGlobals(String thisbatchType){</div>
<div class="MsoNormal">
batchType
= thisbatchType;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
global
batchProcessing (String thisbatchType, Map<String,String> thisvars,
String thissoql){</div>
<div class="MsoNormal">
batchType
= thisbatchType;</div>
<div class="MsoNormal">
vars
= thisvars;</div>
<div class="MsoNormal">
soql
= thissoql;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
global
Database.QueryLocator start(Database.BatchableContext bc) {</div>
<div class="MsoNormal">
if
(soql == null || soql == '')</div>
<div class="MsoNormal">
return
Database.getQueryLocator('Select id From User limit 1'); else</div>
<div class="MsoNormal">
return
Database.getQueryLocator(soql);</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
global
void execute(<st1:place w:st="on"><st1:city w:st="on">Database.BatchableContext</st1:city>
<st1:state w:st="on">BC</st1:state></st1:place>, List<sObject> glbs){</div>
<div class="MsoNormal">
if
(batchType == Constants.CONST_DOWNLOAD){//identifies the batch type we are
calling, for a different batch you simply introduce another if statement </div>
<div class="MsoNormal">
if
(vars.containskey('Max') && vars.get('Max') != '0'){</div>
<div class="MsoNormal">
List<ApexClass>
apxCls = (List<ApexClass>)glbs;</div>
<div class="MsoNormal">
String
maxCls = vars.get('Max');</div>
<div class="MsoNormal">
mx
= integer.valueof(maxCls)-1; </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
//call
method that retrieves "mx" number of records from the 3rd party, if
the callout can be made and is successful this returns true to
"success". You could introduce a for loop here to make the callout
a maximum of 10 times to reduce on the number of batch operations</div>
<div class="MsoNormal">
success
= Utils.<b>retrieveData</b>(mx);</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
global
void finish(<st1:place w:st="on"><st1:city w:st="on">Database.BatchableContext</st1:city>
<st1:state w:st="on">BC</st1:state></st1:place>){</div>
<div class="MsoNormal">
if
(batchType == Constants.CONST_DOWNLOAD ){</div>
<div class="MsoNormal">
if
(success)//identifies the last callout was successul</div>
<div class="MsoNormal">
Utils.<b>decideToRunAgain</b>(mx);</div>
<div class="MsoNormal">
else</div>
<div class="MsoNormal">
//do
something when last batch didnt process and encountered an issue</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
This is the decision method:</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public
static void <b>decideToRunAgain</b>
(integer mx){</div>
<div class="MsoNormal">
//This
custom setting is set in <b>retrieveData()
</b>for the number of records retrieved from the 3rd party in the last
callout made in the batch Execute() if this number is less than
"mx" the last callout was the last callout required</div>
<div class="MsoNormal">
Configurations__c
latestCall = Configurations__c.getinstance(Constants.CONST_MAX);</div>
<div class="MsoNormal">
integer
newlatestCallInt = (latestCall != null) ?
integer.valueof(latestCall.Value__c) : 0;</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
if
(newlatestCallInt == mx){</div>
<div class="MsoNormal">
//the
last callout retrieved the same number of records as was requested so this
cannot be the last callout to make so a new batch can be created</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
//we
also need to check that the number of queued batches is less than 100
otherwise the maximum in the queue has been reached</div>
<div class="MsoNormal">
//unfortunately
we cannot halt execution for a time or even continually check AsyncApexJob in
a for loop waiting for the queue to drop because that would hit governor
limits</div>
<div class="MsoNormal">
<span style="background: white; font-family: Arial; font-size: 8pt;">//Note:</span>JobType ='Batch
Apex' identifies a batch being processed, the JobType ='Batch Apex
Worker' identifies the latest record being processed in the batch and so is
constantly changing</div>
<div class="MsoNormal">
if
([Select id From AsyncApexJob where JobType ='Batch Apex' and Status =
'Holding'].size() < 100){ </div>
<div class="MsoNormal">
batchProcessing
batch = new batchProcessing (Constants.CONST_DOWNLOAD, <<specify the
other parameters>>);</div>
<div class="MsoNormal">
Database.executeBatch( batch, 1 );</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
} </div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
The are various different themes you can employ on this
concept, such as all the logic could be pulled completely outside of the batch
into separate classes, keeping the batch class lightweight and actually never needs
to change</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Further information </div>
<div class="MsoNormal">
http://releasenotes.docs.salesforce.com/en-us/spring15/release-notes/rn_apex_flex_queue_ga.htm?edition=&impact=
</div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<br /></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-22252093194080341622015-07-18T13:24:00.003-07:002015-07-18T13:24:31.997-07:00Object Definition Capture<div class="MsoNormal">
I launched my 2nd app last week, which is a free app; so Id
like to take the opportunity in this newsletter to do a bit of self promotion.
Hopefully my readers will like this free app.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
I don't want to send you to sleep but I'd like to tell you a
short story. </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In every company Ive worked in so far Product Owners,
Business Analysts etc often have different styles of capturing requirements and
recording them. Unfortunately often is the case that requirements are not captured accurately or
completely. The net affect is that the developer or administrator does not
produce what is expected and the tester is not sure of what to test. The
developers and administrators have to have additional multiple meetings until
the full requirements are captured completely and recorded, which results in a
lot of wasted time.</div>
<div class="MsoNormal">
This frequently occurs when capturing requirements for
objects and fields, but this should be the easiest of all types of requirements
to capture because the number of different permutations that could be captured
in the requirements is actually finite, unlike that of a code related project.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
So I decided to create an app that would solve 4 main issues
when capturing requirements for Objects and Fields.</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="pre-line" style="background: white; line-height: 14.65pt; margin-bottom: .0001pt; margin: 0cm; mso-list: l0 level1 lfo1; tab-stops: 36.6pt; text-indent: -18.0pt;">
<span style="color: #555555; font-family: Symbol; font-size: 10.0pt; mso-bidi-font-family: Symbol; mso-bidi-font-size: 8.0pt; mso-fareast-font-family: Symbol;"><span style="font-family: 'Times New Roman'; font-size: 7pt; font-stretch: normal; line-height: normal;"> </span></span><!--[endif]--><span class="multi-line-to-fix"><span style="color: #555555; font-family: Helvetica; font-size: 8.0pt;">Capture object
and field requirements in a consistent way for all Product Owners, Business
Analysts</span></span><span style="color: #555555; font-family: Helvetica; font-size: 8.0pt;"><o:p></o:p></span></div>
<div class="pre-line" style="background: white; line-height: 14.65pt; margin-bottom: .0001pt; margin: 0cm; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span class="multi-line-to-fix"><span style="color: #555555; font-family: Symbol; font-size: 10.0pt; mso-bidi-font-family: Symbol; mso-bidi-font-size: 8.0pt; mso-fareast-font-family: Symbol;"><span style="font-family: 'Times New Roman'; font-size: 7pt; font-stretch: normal; line-height: normal;"> </span></span></span><!--[endif]--><span class="multi-line-to-fix"><span style="color: #555555; font-family: Helvetica; font-size: 8.0pt;"> </span></span></div>
<div class="pre-line" style="background: white; line-height: 14.65pt; margin-bottom: .0001pt; margin: 0cm; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="color: #555555; font-family: Symbol; font-size: 10.0pt; mso-bidi-font-family: Symbol; mso-bidi-font-size: 8.0pt; mso-fareast-font-family: Symbol;"><span style="font-family: 'Times New Roman'; font-size: 7pt; font-stretch: normal; line-height: normal;"> </span></span><!--[endif]--><span class="multi-line-to-fix"><span style="color: #555555; font-family: Helvetica; font-size: 8.0pt;">Save time for Product
Owners and Business Analysts when capturing requirements</span></span><span style="color: #555555; font-family: Helvetica; font-size: 8.0pt;"><o:p></o:p></span></div>
<div class="pre-line" style="background: white; line-height: 14.65pt; margin-bottom: .0001pt; margin: 0cm; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span class="multi-line-to-fix"><span style="color: #555555; font-family: Symbol; font-size: 10.0pt; mso-bidi-font-family: Symbol; mso-bidi-font-size: 8.0pt; mso-fareast-font-family: Symbol;"><span style="font-family: 'Times New Roman'; font-size: 7pt; font-stretch: normal; line-height: normal;"> </span></span></span><!--[endif]--><span class="multi-line-to-fix"><span style="color: #555555; font-family: Helvetica; font-size: 8.0pt;"> </span></span></div>
<div class="pre-line" style="background: white; line-height: 14.65pt; margin-bottom: .0001pt; margin: 0cm; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span class="multi-line-to-fix"><span style="color: #555555; font-family: Symbol; font-size: 10.0pt; mso-bidi-font-family: Symbol; mso-bidi-font-size: 8.0pt; mso-fareast-font-family: Symbol;"><span style="font-family: 'Times New Roman'; font-size: 7pt; font-stretch: normal; line-height: normal;"> </span></span></span><!--[endif]--><span class="multi-line-to-fix"><span style="color: #555555; font-family: Helvetica; font-size: 8.0pt;">Developers and
testers are given a consistent approach and so requirements are easily
understood<o:p></o:p></span></span></div>
<div class="pre-line" style="background: white; line-height: 14.65pt; margin-bottom: .0001pt; margin: 0cm;">
<br /></div>
<div class="pre-line" style="background: white; line-height: 14.65pt; margin-bottom: .0001pt; margin: 0cm; mso-list: l0 level1 lfo1; tab-stops: list 36.0pt; text-indent: -18.0pt;">
<span style="color: #555555; font-family: Symbol; font-size: 10.0pt; mso-bidi-font-family: Symbol; mso-bidi-font-size: 8.0pt; mso-fareast-font-family: Symbol;"><span style="font-family: 'Times New Roman'; font-size: 7pt; font-stretch: normal; line-height: normal;"> </span></span><!--[endif]--><span class="multi-line-to-fix"><span style="color: #555555; font-family: Helvetica; font-size: 8.0pt;">Product Owners
and Business Analysts accurately capture all relevant requirements</span></span><span style="color: #555555; font-family: Helvetica; font-size: 8.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
15
companies have already installed my app in just 4 days since it was launched.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
The
link to the app is <a href="https://appexchange.salesforce.com/listingDetail?listingId=a0N30000000qF2bEAE">https://appexchange.salesforce.com/listingDetail?listingId=a0N30000000qF2bEAE</a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
You
need to add your org to Remote Site Settings, so if your org is say https://<b>na12</b>.salesforce.com, you would add this
URL to Remote Site Settings. The bold part is the part which will be different
for your Salesforce org.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Another
benefit that the app could provide for you is that it will find all the Report
Types and Page Layouts that you have in your system and enter them into 2
Custom Objects. You may be able to use this data for other purposes.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
I
hope you find the app beneficial.</div>
<br />
<div class="MsoNormal">
<br /></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-1299021387855872032015-07-18T13:22:00.001-07:002015-07-18T13:22:33.851-07:00Structuring Salesforce Invocable Methods <div class="MsoNormal">
<div class="MsoNormal">
Invocable Methods are an important addition to the platform
and Ive been calling for a complete overhaul of the Salesforce workflow engine
for a long time and finally Process Builder was introduced a couple of releases
back. </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
There a few issues and limitations of Invocable Methods
however: </div>
<div class="MsoNormal">
<br /></div>
<ol start="1" style="margin-top: 0cm;" type="1">
<li class="MsoNormal">Passing
Sobject lists appears not to work and instead you have to pass Ids of the
Sobjects and then perform a SOQL to get the Sobjects, so you have to be
mindful of SOQL limits. I would expect Salesforce to fix this issue in
future releases, so this might go away.</li>
</ol>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
<ol start="2" style="margin-top: 0cm;" type="1">
<li class="MsoNormal">Another
limitation is that you can only have 1 Invocable Method per class, which
means you can end up having many classes. There is a neat way to get
around this however: </li>
</ol>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Lets consider 2 examples. One Invocable Method sends an
email introducers customers to The Self Evolving Software app, the 2nd
Invocable Method updates a field on the Account to make post codes correctly
formatted. </div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">@InvocableMethod(label='Setup_Salesforce_To_Salesforce_Email'
</span><span style="font-family: 'Courier New'; font-size: 10pt;">description=</span><span style="color: green; font-family: "Courier New"; font-size: 10.0pt;">'Sends a Email
To Explain Setup Of Salesforce To Salesforce'</span><span style="font-family: 'Courier New'; font-size: 10pt;">) </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">public</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">static</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">void</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">
sendBenefitsEmail(ID[] emls){ </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> Attachment[] att = [</span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">Select</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> id,Body, Name
</span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">From</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> Attachment </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">where</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> name=</span><span style="color: green; font-family: "Courier New"; font-size: 10.0pt;">'SES
Introduction.pdf'</span><span style="font-family: 'Courier New'; font-size: 10pt;">]; </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> UtilEmail.sendEmail(emls,</span><span style="color: green; font-family: "Courier New"; font-size: 10.0pt;">'How To Use The
Self Evolving Software App'</span><span style="font-family: 'Courier New'; font-size: 10pt;">, att); </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;">} </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">@InvocableMethod(label='Format </span><span style="font-family: 'Courier New'; font-size: 10pt;">postcode </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">on</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> Account</span><span style="color: green; font-family: "Courier New"; font-size: 10.0pt;">'
description='</span><span style="font-family: 'Courier New'; font-size: 10pt;">Format postcode </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">on</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> Account</span><span style="color: green; font-family: "Courier New"; font-size: 10.0pt;">') </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">public</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">static</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">void</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">
formatPostcode(ID[] accs){ </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> Account[] acc = [</span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">Select</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">
BillingPostalCode </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">From</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> Account </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">where</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> Id In :accs];
</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">for</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> (Account
eachacc : acc){ </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> eachacc.BillingPostalCode = </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> UtilFormats.postcodeFormatting(eachacc.BillingPostalCode);
</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> } </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">update</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> acc; </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;">}<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
The issue here is that we would have to create 2 classes with
1 Invocable Method in each.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
The solution is to combine all Invocable Methods into an
InvocableMethodHandler class and call to separate classes where the actions
will take place </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568">
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;">We first need
to create a wrapper class to hold our data<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: "Courier New"; font-size: 10.0pt;">In the labels for each InvocableVariable
you probably want to display something a bit shorter as this will appear in
the process builder.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">public</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">with</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">sharing</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">class</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> KeyValueInv {</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">@InvocableVariable(label='Optional key
if you want to represent a collection' </span><span style="font-family: 'Courier New'; font-size: 10pt;">required=</span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;"> false</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">)</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">public</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> String key;</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">@InvocableVariable(label='Stores the
value' </span><span style="font-family: 'Courier New'; font-size: 10pt;">required=</span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;"> true</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">)</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">public</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> String value;</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">@InvocableVariable(label='The data type
of the value' </span><span style="font-family: 'Courier New'; font-size: 10pt;">required=</span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">true</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">)</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">public</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> String
fieldtype;</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">@InvocableVariable(label='This
identifies the function to call' </span><span style="font-family: 'Courier New'; font-size: 10pt;">required=</span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">true</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">)</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">public</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> String </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">type</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">;</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">public</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">
KeyValueInv(String thiskey, String thisvalue, String thisfieldtype, String
thistype){</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">this</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">.key =
thiskey;</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">this</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">.value =
thisvalue;</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">this</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">.fieldtype =
thisfieldtype;</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">this</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">.</span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">type</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> =
thistype.toUpperCase();</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> }</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;">}</span> </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Below
is the only invocable class and method you will ever need to create as we can
send to it any type of data to the KeyValueInv class, plus in the InvocableMethodHandler
we identify the function to call</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">public</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">with</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">sharing</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">class</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">
InvocableMethodHandler {</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="color: teal; font-family: "Courier New"; font-size: 10.0pt;">@InvocableMethod(label='' </span><span style="font-family: 'Courier New'; font-size: 10pt;">description=</span><span style="color: green; font-family: "Courier New"; font-size: 10.0pt;">''</span><span style="font-family: 'Courier New'; font-size: 10pt;">)</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">public</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">static</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">void</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">
processType(KeyValueInv[] kvLst){</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">if</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> (kvLst[0].</span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">type</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> == </span><span style="color: green; font-family: "Courier New"; font-size: 10.0pt;">'Send Benefits
Email'</span><span style="font-family: 'Courier New'; font-size: 10pt;">){</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> UtilClass.sendBenefitsEmail(kvLst);</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> }</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> else </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">if</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> (kvLst[0].</span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">type</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> == </span><span style="color: green; font-family: "Courier New"; font-size: 10.0pt;">'Format Postcode'</span><span style="font-family: 'Courier New'; font-size: 10pt;">){</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> UtilClass.formatPostcode(kvLst);</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> }</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> }</span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;">}<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">public</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">static</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">void</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">
sendBenefitsEmail(kvLst[] kvs){ </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> //code ..... </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> } </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">public</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">static</span></b><span style="font-family: 'Courier New'; font-size: 10pt;"> </span><b><span style="color: #7f0055; font-family: "Courier New"; font-size: 10.0pt;">void</span></b><span style="font-family: 'Courier New'; font-size: 10pt;">
formatPostcode(kvLst[] kvs){ </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;"> //code ..... </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: 'Courier New'; font-size: 10pt;">} </span><span style="font-family: "Courier New"; font-size: 10.0pt;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
Now when you create your <span style="font-family: "Courier New"; font-size: 10.0pt;">process builder you will be able to set the <span style="color: green;">'Send Benefits Email' </span>as or <span style="color: green;">'Format
Postcode' </span>and this will decide which function to ultimately to call.</span></div>
</div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-43320904308088574552015-06-13T01:17:00.000-07:002015-06-13T01:17:54.303-07:00Intro to Unit Test Data Creation Framework continued…….<br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In my last blog <a href="http://stevefouracre.blogspot.co.uk/2015/06/intro-to-unit-test-data-creation.html">http://stevefouracre.blogspot.co.uk/2015/06/intro-to-unit-test-data-creation.html</a> I gave examples of how the framework
can be used. I also introduced rapidProcessing. Now we will expand the
framework making use of rapidProcessing.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Reminder:</div>
<div class="MsoNormal">
rapidProcessing
allows you to bypass the code in triggers, allowing the test data to be created much faster ( this
can also be useful when you are migrating data
into Salesforce ). In both of these situations you are telling Salesforce exactly what data to create and you
don't want the system to manipulate the data
further or to perform any actions within the triggers that may do all kind of things such as creating additional
business process data like Tasks, Events and
Cases etc, or sending out emails to customers etc ( however the latter wont happen in unit tests as emails are
not sent from unit tests ).</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Lets take our previous example which will bypass both the
Account and Contact triggers:</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
KeyValue[] kvsA = new KeyValue[]{};</div>
<div class="MsoNormal">
KeyValue[] kvsC = new KeyValue[]{};</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Map<System.Type, KeyValueBulk> keyMap = new
Map<System.Type, KeyValueBulk>();</div>
<div class="MsoNormal">
keyMap.put(Account.class, new KeyValueBulk(1, kvsA)); </div>
<div class="MsoNormal">
keyMap.put(Contact.class, new KeyValueBulk(5, kvsC)); </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TriggerController.rapidProcessing = new
Map<System.Type, Boolean>{ Account.class => true, Contact.class
=> true};</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
//now rapidProcessing has been turned on for both objects
the code in the triggers will be bypassed. You will need to build into your
triggers the Trigger Control Framework:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataComplexData dataCl = new TestDataComplexData ();</div>
<div class="MsoNormal">
dataCl.insertAccountAndContacts(keyMap);</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Ok for the above example for triggers to be bypassed we need
to first create 2 Hierarchical custom settings:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Triggers_Off__c</div>
<div class="MsoNormal">
This custom
settings needs to have the following fields:</div>
<div class="MsoNormal">
</div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; border: none; margin-left: 41.4pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="background: teal; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-pattern: solid teal; mso-shading: teal; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="color: #ffff99;">Field Name<o:p></o:p></span></div>
</td>
<td style="background: teal; border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-pattern: solid teal; mso-shading: teal; padding: 0cm 5.4pt 0cm 5.4pt; width: 162.0pt;" valign="top" width="216"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="color: #ffff99;">Data Type<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
value</div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 162.0pt;" valign="top" width="216"><div align="center" class="MsoNormal" style="text-align: center;">
Boolean</div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Trigger_Per_Object__c</div>
<div class="MsoNormal">
This custom
settings needs to have the following fields:</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; border: none; margin-left: 41.4pt; mso-border-alt: solid windowtext .5pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="background: teal; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-pattern: solid teal; mso-shading: teal; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="color: #ffff99;">Field Name<o:p></o:p></span></div>
</td>
<td style="background: teal; border-left: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-pattern: solid teal; mso-shading: teal; padding: 0cm 5.4pt 0cm 5.4pt; width: 162.0pt;" valign="top" width="216"><div align="center" class="MsoNormal" style="text-align: center;">
<span style="color: #ffff99;">Data Type<o:p></o:p></span></div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
Account</div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 162.0pt;" valign="top" width="216"><div align="center" class="MsoNormal" style="text-align: center;">
Boolean</div>
</td>
</tr>
<tr>
<td style="border-top: none; border: solid windowtext 1.0pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 140.4pt;" valign="top" width="187"><div align="center" class="MsoNormal" style="text-align: center;">
Contact</div>
</td>
<td style="border-bottom: solid windowtext 1.0pt; border-left: none; border-right: solid windowtext 1.0pt; border-top: none; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 162.0pt;" valign="top" width="216"><div align="center" class="MsoNormal" style="text-align: center;">
Boolean</div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
For each
additional trigger you create you will need to create an additional field in this custom setting for
that trigger and you will need to add a new <i>else
if</i> {} statement to the
globalTriggerControlSetting() function in the TriggerController
class. An example of this will be shown next for the Account and Contact</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
The 2 custom settings above can be used to bypass the
triggers typically when either you are making a deployment to Production or if
you are performing a data migration. They will allow you to disable individual
or all triggers per person, per Profile or the entire system.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In the TriggerController class we created a number of
variables to bypass the Account trigger, now create a similar set of variables
for the Contact trigger. We also need to add 2 functions into the class
globalTriggerControlSetting() and globalTriggerPerObjectControlSetting():</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoNormalTable" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
//Contact
- Only for testing to check if the code ran or not</div>
<div class="MsoNormal">
public
static boolean Contact_Update_Succeeded = false;</div>
<div class="MsoNormal">
public
static boolean Contact_Insert_Succeeded = false;</div>
<div class="MsoNormal">
public
static boolean Contact_Delete_Succeeded = false;</div>
<div class="MsoNormal">
public
static boolean Contact_UnDelete_Succeeded = false;</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
//Contact
- Disable / Enable parts of trigger</div>
<div class="MsoNormal">
public
static boolean Contact_DisableAllTypes = false;</div>
<div class="MsoNormal">
public
static boolean Contact_DisableInsert = false;</div>
<div class="MsoNormal">
public
static boolean Contact_DisableUpdate = false;</div>
<div class="MsoNormal">
public
static boolean Contact_DisableDelete = false;</div>
<div class="MsoNormal">
public
static boolean Contact_DisableUnDelete = false;</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public static boolean globalTriggerControlSetting(){</div>
<div class="MsoNormal">
return
(((Triggers_Off__c.getOrgDefaults() != null) ?
Triggers_Off__c.getOrgDefaults().value__c : false) ||
Triggers_Off__c.getInstance(UserInfo.getUserId()).value__c ||
Triggers_Off__c.getInstance(UserInfo.getProfileId()).value__c) ;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public static boolean globalTriggerPerObjectControlSetting(String
obj){</div>
<div class="MsoNormal">
Trigger_Per_Object__c.getInstance(UserInfo.getProfileId()));</div>
<div class="MsoNormal">
if (obj
== 'Account__c') return (((Trigger_Per_Object__c.getOrgDefaults() != null) ?
(boolean)Trigger_Per_Object__c.getOrgDefaults().Account__c : false) ||
(boolean)Trigger_Per_Object__c.getInstance(UserInfo.getUserId()).Account__c
|| (boolean)Trigger_Per_Object__c.getInstance(UserInfo.getProfileId()).Account__c)
;</div>
<div class="MsoNormal">
else if
(obj == 'Contact__c') return (((Trigger_Per_Object__c.getOrgDefaults() !=
null) ? (boolean)Trigger_Per_Object__c.getOrgDefaults().Contact__c : false) ||
(boolean)Trigger_Per_Object__c.getInstance(UserInfo.getUserId()).Contact__c
|| (boolean)Trigger_Per_Object__c.getInstance(UserInfo.getProfileId()).Contact__c)
;</div>
<div class="MsoNormal">
else
return false;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
The Disable variables eg: Contact_DisableAllTypes allows you
to disable all of a trigger or individual parts of a trigger, commonly will be
used within the body of the code including unit tests. We could have used the
custom settings but that would involve using DMLs to turn the triggers on and
off.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
In the next blog we will create the code for the
trigger.</div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-21893196612232431972015-06-05T12:24:00.002-07:002015-06-05T12:32:03.318-07:00Intro to Unit Test Data Creation Framework continued…….<br />
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="background-color: white; color: #373737; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; line-height: 24.375px;">Read the last blog at <a href="http://stevefouracre.blogspot.co.uk/2015/05/intro-to-unit-test-data-creation.html">http://stevefouracre.blogspot.co.uk/2015/05/intro-to-unit-test-data-creation.html</a></span></div>
<div class="MsoNormal">
<span style="background-color: white; color: #373737; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; line-height: 24.375px;"><br /></span></div>
<div class="MsoNormal">
In my last blog I laid out the codebase required for
the framework.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Now you have created the structure of the framework, lets
run some examples.</div>
<div class="MsoNormal">
But before we do I'd like to point out 1 thing, in the
framework you have various options depending how you personally feel you would
like to structure the framework. You can make the TestDataComplexData class
extend the TestDataBulkData class instead of the TestDataInsertData and you may
want to rename the TestDataComplexData class to something like TestDataCreation
class and so it is more generic. These are just options for you to play around
with.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
To perform no DML and just return a new Contact using the
standard json string you can add a returnContact function in the TestDataReturnData
class:</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
The new function will look like:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public Contact
returnContact(KeyValue[] kVals){</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
return
(Contact) (super.returnAnyObject(new
TestDataFramework_JsonLibrary.Standard().M.get('CONTACT'), kVals,
Contact.class)[0]);</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
An example of using this new function:</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataComplexData dataCl = new TestDataComplexData ();</div>
<div class="MsoNormal">
dataCl.returnContact(null);</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
To simply create a new Contact using the standard json
string:</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataComplexData dataCl = new TestDataComplexData ();</div>
<div class="MsoNormal">
dataCl.insertContact(null, null);</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
To add some values into certain fields:</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
KeyValue[] kvs = new KeyValue[]{};</div>
<div class="MsoNormal">
//this will overwrite the Email field with a new email</div>
<div class="MsoNormal">
kvs.add(new KeyValue('Email', 'myemail@yahoo.com',
'String'));</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataComplexData dataCl = new TestDataComplexData ();</div>
<div class="MsoNormal">
dataCl.insertContact(null, kvs);</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
To simply create a new Account and Contact using the
standard json string and to add a value into a field:</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
Map<System.Type, List<KeyValue>> keyMap = new
Map<System.Type, List<KeyValue>>();</div>
<div class="MsoNormal">
KeyValue[] kvs = new KeyValue[]{};</div>
<div class="MsoNormal">
//this will overwrite the Email field with a new email</div>
<div class="MsoNormal">
kvs.add(new KeyValue('Email', 'myemail@yahoo.com',
'String'));</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
kMaps.put(Contact.class, kvs);</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataComplexData dataCl = new TestDataComplexData ();</div>
<div class="MsoNormal">
dataCl.insertContactAndAccount(kMaps);</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
To create 1 Account and 5 Contacts linked using the standard
json string#</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
KeyValue[] kvsA = new KeyValue[]{};</div>
<div class="MsoNormal">
KeyValue[] kvsC = new KeyValue[]{};</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Map<System.Type, KeyValueBulk> keyMap = new
Map<System.Type, KeyValueBulk>();</div>
<div class="MsoNormal">
keyMap.put(Account.class, new KeyValueBulk(1, kvsA)); </div>
<div class="MsoNormal">
keyMap.put(Contact.class, new KeyValueBulk(5, kvsC)); </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataBulkData dataCl = new TestDataBulkData ();</div>
<div class="MsoNormal">
dataCl.insertAccountAndContacts(keyMap);</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
If your framework is setup so that TestDataComplexData class
extends the TestDataBulkData class instead just change the code above to</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
KeyValue[] kvsA = new KeyValue[]{};</div>
<div class="MsoNormal">
KeyValue[] kvsC = new KeyValue[]{};</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Map<System.Type, KeyValueBulk> keyMap = new
Map<System.Type, KeyValueBulk>();</div>
<div class="MsoNormal">
keyMap.put(Account.class, new KeyValueBulk(1, kvsA)); </div>
<div class="MsoNormal">
keyMap.put(Contact.class, new KeyValueBulk(5, kvsC)); </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataComplexData dataCl = new TestDataComplexData ();</div>
<div class="MsoNormal">
dataCl.insertAccountAndContacts(keyMap);</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
If you now want to bypass the triggers to speed up
processing time because you want to upload a lot of records to be used in your
testmethod:</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
KeyValue[] kvsA = new KeyValue[]{};</div>
<div class="MsoNormal">
KeyValue[] kvsC = new KeyValue[]{};</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Map<System.Type, KeyValueBulk> keyMap = new
Map<System.Type, KeyValueBulk>();</div>
<div class="MsoNormal">
keyMap.put(Account.class, new KeyValueBulk(1, kvsA)); </div>
<div class="MsoNormal">
keyMap.put(Contact.class, new KeyValueBulk(5, kvsC)); </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TriggerController.rapidProcessing = new Map<System.Type,
Boolean>{ Account.class => true, Contact.class => true};</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
//now rapidProcessing has been turned on for both objects
the code in the triggers will be bypassed. You will need to build into your
triggers the Trigger Control Framework which will be the next thing I will
cover in my next post:</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataComplexData dataCl = new TestDataComplexData ();</div>
<div class="MsoNormal">
dataCl.insertAccountAndContacts(keyMap);</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
If you want to insert an Account using the standard json
string and then update that Account:</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataUpdateData dataCl = new TestDataUpdateData();</div>
<div class="MsoNormal">
KeyValue[] kvsUpdate = new KeyValue[]{};</div>
<div class="MsoNormal">
//this will overwrite the BillingPostalCode field with a
new post code</div>
<div class="MsoNormal">
kvsUpdate.add(new KeyValue('BillingPostalCode', 'EC1 2CV',
'String'));</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
//first argument is null because this overrides the fields
for the insert part</div>
<div class="MsoNormal">
dataCl.updateAccount(null, kvsUpdate);</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
If you want to insert an Account using the standard json
string and then update that Account:</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataUpdateData dataCl = new TestDataUpdateData();</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
KeyValue[] kvsInsert = new KeyValue[]{};</div>
<div class="MsoNormal">
//this will overwrite the BillingPostalCode field with a
new post code</div>
<div class="MsoNormal">
kvsInsert.add(new KeyValue('BillingPostalCode', 'SE1 2SG',
'String'));</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
KeyValue[] kvsUpdate = new KeyValue[]{};</div>
<div class="MsoNormal">
//this will overwrite the BillingPostalCode field with a
new post code</div>
<div class="MsoNormal">
kvsUpdate.add(new KeyValue('BillingPostalCode', 'EC1 2CV',
'String'));</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
dataCl.updateAccount(kvsInsert, kvsUpdate);</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
If you want to create a new insert function and add this to
the framework, here are the steps you will need to follow:</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<ol start="1" style="margin-top: 0cm;" type="1">
<li class="MsoNormal">Create
a new constant in the Constant class</li>
<li class="MsoNormal">Add
a new json string to the libraryMap variable in the json library class</li>
<li class="MsoNormal">Create
a new insert function in the TestDataInsertData class similar to the insertContact()
function just replacing with the new Sobject type</li>
<li class="MsoNormal">You
can now use this function in the other classes TestDataComplexData,
TestDataBulkData and TestDataUpdateData to build more complex data
structures if you require</li>
</ol>
<div class="MsoNormal" style="margin-left: 18.0pt;">
<br /></div>
</td>
</tr>
</tbody></table>
<br />
<div class="MsoNormal">
<br /></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-61983230406907295082015-05-30T06:55:00.000-07:002015-06-05T11:37:27.502-07:00Intro to Unit Test Data Creation Framework continued.......<br />
<div class="MsoNormal">
Read the first blog at <a href="http://stevefouracre.blogspot.co.uk/2015/05/unit-test-data-creation-framework.html">http://stevefouracre.blogspot.co.uk/2015/05/unit-test-data-creation-framework.html</a><br />
<br />
In my last blog I introduced my Unit Test Data
Creation Framework, now we will start building the classes of the framework.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
First create the Constants class</div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public class Constants {</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public static final String CONST_Account = 'ACCOUNT'; </div>
<div class="MsoNormal">
public static final String CONST_Contact = 'CONTACT'; </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Now, in the ITestData class add</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public interface ITestData {</div>
<div class="MsoNormal">
List<sObject> returnAnyObject(String jsonStr, KeyValue[]
kVals);
</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Next, in the TestDataJsonLibrary class add</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public class TestDataJsonLibrary {</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public static String referenceKey = 'ReferenceID';</div>
<div class="MsoNormal">
public class Standard{</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public final Map<String, String> libraryMap = new
Map<String, String>{</div>
<div class="MsoNormal">
Constant.CONST_Account =>
'{"attributes":{"type":"Account"},"Field1__c":"Value
1","Field2__c":"Value 2"}',</div>
<div class="MsoNormal">
Constant.CONST_Contact =>
'[{"attributes":{"type":"Contact"},"'+referenceKey+'":"Reference
Value","Field1__c":"Value 1"}</div>
<div class="MsoNormal">
};</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In the Return Data class add</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public abstract class TestDataReturnData implements
ITestData{</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public Boolean bulkModeOn = false;</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public Map<System.Type, String> overrideJson = new
Map<System.Type, String>();</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public
List<sObject> returnAnyObject(String jsonStr, KeyValue[] kVals){</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
List<sObject> sobj;</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
if(jsonStr.contains(TestDataJsonLibrary.referenceKey))</div>
<div class="MsoNormal">
jsonStr
= getFilteredJsonString(jsonStr, kVals);</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
if(jsonStr.startsWith('['))</div>
<div class="MsoNormal">
sobj =
(List<sObject>) System.Json.deserialize(jsonStr,
List<sObject>.class);</div>
<div class="MsoNormal">
else</div>
<div class="MsoNormal">
sobj = (List<sObject>)
System.Json.deserialize('['+jsonStr+']', List<sObject>.class);</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
if(kVals !=
null){</div>
<div class="MsoNormal">
for(sObject obj : sobj)</div>
<div class="MsoNormal">
obj = UtilDML.setObjData(obj,
kVals);</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
return sobj;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
private String
deserialJson(String jsonStr, KeyValue[] kVals){ </div>
<div class="MsoNormal">
List<Object> deserialLst =
(List<Object>) JSON.deserializeUntyped(jsonStr.unescapeEcmaScript());</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
String aReferenceKey;</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
//when
setting the fields from the KeyValues if 1 is the lookup field set to aReferenceKey </div>
<div class="MsoNormal">
for(KeyValue kv : kVals){ </div>
<div class="MsoNormal">
if(kv.key ==
TestDataJsonLibrary.referenceKey){ </div>
<div class="MsoNormal">
aReferenceKey
= kv.value;</div>
<div class="MsoNormal">
break;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
List<sObject> serialLst = new
List<sObject>();</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
for(Object obj : deserialLst){</div>
<div class="MsoNormal">
Map<String, Object>
objMap = (Map<String, Object>) obj;</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
if(aReferenceKey ==
objMap.get(TestDataJsonLibrary.referenceKey)){ </div>
<div class="MsoNormal">
objMap.remove(TestDataJsonLibrary.referenceKey);</div>
<div class="MsoNormal">
serialLst.add(UtilDML.convertToSobject(objMap));</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
return JSON.serialize(serialLst);</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In the Insert Data class add</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public virtual class TestDataInsertData extends
TestDataReturnData{</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
private sObject
insertAnyObject(String jsonStr, KeyValue[] kVals, System.Type objType){</div>
<div class="MsoNormal">
if(overrideJson != null && overrideJson.containsKey(objType))</div>
<div class="MsoNormal">
jsonStr
= overrideJson.get(objType);</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
sObject sobj
= super.returnAnyObject(jsonStr, kVals)[0];</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
// set to
true if inserting multiple records</div>
<div class="MsoNormal">
if(bulkModeOn == false)</div>
<div class="MsoNormal">
insert
sobj;</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
return sobj;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public Contact
insertContact(String jsonstr, KeyValue[] kVals){ </div>
<div class="MsoNormal">
return
(Contact) insertAnyObject((jsonstr != null && jsonstr != '') ?
jsonstr : new
TestDataFramework_JsonLibrary.Standard().M.get(Constants.CONST_Contact),
kVals, Contact.class); </div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In the Update Data class add</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public virtual class TestDataUpdateData extends
TestDataInsertData{</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public Account
updateAccount(KeyValue[] insertkVals, KeyValue[] updatekVals){ </div>
<div class="MsoNormal">
Account acc
= super.insertAccount(insertkVals);</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
if(updatekVals != null)</div>
<div class="MsoNormal">
acc = (Account) UtilDML.setObjData(acc,
updatekVals); </div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
update acc; </div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
return acc;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In the ComplexData class add</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public virtual class TestDataComplexData extends
TestDataInsertData{</div>
<div class="MsoNormal">
public Account
acc{get;set;}</div>
<div class="MsoNormal">
public Contact
cont{get;set;}</div>
<div class="MsoNormal">
public <st1:place w:st="on">Opportunity</st1:place> opp{get;set;}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public Account
insertContactAndAccount(Map<System.Type, List<KeyValue>> keyMap){</div>
<div class="MsoNormal">
//inserts
just 1 Account and 1 Contact and links them together, using the map in the argument
means you only need to use 1 argument </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
//stops a
null exception occurring later in the code</div>
<div class="MsoNormal">
if(keyMap ==
null){ </div>
<div class="MsoNormal">
keyMap =
new Map<System.Type, List<KeyValue>>();</div>
<div class="MsoNormal">
kMaps.put(Contact.class, new List<KeyValue>());</div>
<div class="MsoNormal">
}else
if(keyMap.containsKey(Contact.class) == false)</div>
<div class="MsoNormal">
keyMap.put(Contact.class, new
List<KeyValue>());</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
this.acc =
super.insertAccount(keyMap.get(Account.class));</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
// now
provide the Id into the KeyValues to link the Objects together</div>
<div class="MsoNormal">
keyMap.get(Contact.class).add(new KeyValue('AccountId', this.acc.id,
'ID'));</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
this.cont =
super.insertContact(keyMap.get(Contact.class));</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
return
this.acc;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public Account insertContactOpportunityAndAccount(Map<System.Type,
List<KeyValue>> keyMap){</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
insertContactAndAccount(keyMap);</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
if(keyMap.containsKey(Opportunity.class)
== false)</div>
<div class="MsoNormal">
keyMap.put(Opportunity.class,
new List<KeyValue>());</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
keyMap.get(Opportunity.class).add(new KeyValue('AccountId',
this.acc.id, 'ID'));</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
this.opp =
super.insert<st1:place w:st="on">Opportunity</st1:place>(keyMap.get(Opportunity.class));</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
return
this.acc;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In the BulkData class add</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public virtual class TestDataBulkData extends
TestDataInsertData{</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public Account
insertAccountAndContacts(Map<System.Type, KeyValueBulk> keyMap){</div>
<div class="MsoNormal">
//This
inserts 1 Account and a number of Contacts</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
//stops a
null exception occurring later in the code</div>
<div class="MsoNormal">
if(keyMap ==
null){</div>
<div class="MsoNormal">
keyMap =
new Map<System.Type, KeyValueBulk>();</div>
<div class="MsoNormal">
keyMap.put(Contact.class, new KeyValueBulk()); </div>
<div class="MsoNormal">
}else
if(kMaps.containsKey(Contact.class) == false)</div>
<div class="MsoNormal">
kMaps.put(Contact.class, new
KeyValueBulk());</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
this.conts = new List<Case>();</div>
<div class="MsoNormal">
Account acc
= super.insertAccount(keyMap.get(Account.class) .keyValueBulkLst); </div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
bulkModeOn =
true; // stops records being inserted</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
//link records together</div>
<div class="MsoNormal">
(keyMap.get(Contact.class)).keyValueBulkLst.add(new
KeyValue('AccountId', acc.id, 'ID'));</div>
<div class="MsoNormal">
List<KeyValueBulk> kVals =
(keyMap.get(Contact.class)).keyValueBulkLst;</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
for(Integer i = 0; i <
(keyMap.get(Contact.class)).insertRecs; i++)</div>
<div class="MsoNormal">
this.conts.add(super.insertContact(kVals));</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
insert this.conts;</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
bulkModeOn =
false; //resets flag</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
return
this.acc;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
KeyValue class looks like this</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public class KeyValue{</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public
String key{get; set;}</div>
<div class="MsoNormal">
public
String value{get; set;}</div>
<div class="MsoNormal">
public
String fieldType{get; set;}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public
KeyValue(String key, String value, String fieldType){</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
this.key
= key;</div>
<div class="MsoNormal">
this.value
= value;</div>
<div class="MsoNormal">
this.fieldType
= fieldType.toUpperCase();</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public
KeyValue(String key, String value){</div>
<div class="MsoNormal">
this.key
= key;</div>
<div class="MsoNormal">
this.value
= value;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public
KeyValue(){</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
KeyValueBulk class looks like this</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public class KeyValueBulk{</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public integer insertRecs;</div>
<div class="MsoNormal">
public KeyValue[] keyValueBulkLst;</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public KeyValueBulk(integer insRecs, KeyValue[] kys){</div>
<div class="MsoNormal">
insertRecs = (insertRecs != null && insertRecs
> 0) ? insertRecs : 1;</div>
<div class="MsoNormal">
keyValueBulkLst
= kys;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Also if you have any triggers, for rapid transactional
processing create the TriggerController class</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
To bypass code in triggers which often fire workflows and
process builders, which in turn fire triggers again; all of which takes extra
processing time. But when you are simply creating test data you are implicitly
telling the system to create an exact data set and if you are not actually
testing the trigger there is no need when you are creating the test data to run
through the code in the trigger.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In the TriggerController class add</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public class TriggerController {</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
//used
specifically in unit test data framework</div>
<div class="MsoNormal">
public
static Map<System.Type, Boolean> rapidProcessing;</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
//Account
- Disable / Enable parts of trigger</div>
<div class="MsoNormal">
public
static boolean Account_DisableAllTypes = false;</div>
<div class="MsoNormal">
public
static boolean Account_DisableInsert = false;</div>
<div class="MsoNormal">
public
static boolean Account_DisableUpdate = false;</div>
<div class="MsoNormal">
public
static boolean Account_DisableDelete = false;</div>
<div class="MsoNormal">
public
static boolean Account_DisableUnDelete = false;</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
//used to
unit test the trigger control to ensure the correct parts of the trigger were
triggered</div>
<div class="MsoNormal">
public
static boolean Account_Insert_Succeeded = false;</div>
<div class="MsoNormal">
public
static boolean Account_Update_Succeeded = false;</div>
<div class="MsoNormal">
public
static boolean Account_Delete_Succeeded = false;</div>
<div class="MsoNormal">
public
static boolean Account_UnDelete_Succeeded = false;</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In the UtilDML class add</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: none; mso-border-alt: solid blue 2.25pt; mso-border-insideh: 2.25pt solid blue; mso-border-insidev: 2.25pt solid blue; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-yfti-tbllook: 480;">
<tbody>
<tr>
<td style="border: solid blue 2.25pt; padding: 0cm 5.4pt 0cm 5.4pt; width: 426.1pt;" valign="top" width="568"><div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public class UtilDML {</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public
static Sobject setObjData(Sobject aobj, KeyValue[] kVals){</div>
<div class="MsoNormal">
Sobject
thisobj;</div>
<div class="MsoNormal">
if (kVals != null){</div>
<div class="MsoNormal">
for (KeyValue eachval : kVals){</div>
<div class="MsoNormal">
try{</div>
<div class="MsoNormal">
thisobj =
setFieldVal(aobj, eachval);</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
catch(Exception
ex){system.debug('## ex ' + ex); }</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
return
thisobj;</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
public
static Sobject setFieldVal(Sobject obj, KeyValue thisKeyVal){</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
system.debug('##
thisKeyVal ' + thisKeyVal); </div>
<div class="MsoNormal">
if
(thisKeyVal.fieldtype == 'DATE'){ </div>
<div class="MsoNormal">
String
tmpDt = thisKeyVal.value;</div>
<div class="MsoNormal">
Date
dt = Date.valueOf(tmpDt.substring(0,9).trim());</div>
<div class="MsoNormal">
system.debug('##
dt ' + dt); </div>
<div class="MsoNormal">
obj.put(thisKeyVal.key,
dt);</div>
<div class="MsoNormal">
}else
if (thisKeyVal.fieldtype == 'DATETIME'){</div>
<div class="MsoNormal">
system.debug('##
Datetime.valueOf(tmpDt) ' + Datetime.valueOf(thisKeyVal.value));</div>
<div class="MsoNormal">
obj.put(thisKeyVal.key,
Datetime.valueOf(thisKeyVal.value));</div>
<div class="MsoNormal">
system.debug('##
obj ' + obj);</div>
<div class="MsoNormal">
}else
if (thisKeyVal.fieldtype == 'DECIMAL')</div>
<div class="MsoNormal">
obj.put(thisKeyVal.key,
decimal.valueof(thisKeyVal.value));</div>
<div class="MsoNormal">
else
if (thisKeyVal.fieldtype == 'INTEGER')</div>
<div class="MsoNormal">
obj.put(thisKeyVal.key,
integer.valueof(thisKeyVal.value));</div>
<div class="MsoNormal">
else
if (thisKeyVal.fieldtype == 'LONG')</div>
<div class="MsoNormal">
obj.put(thisKeyVal.key,
long.valueof(thisKeyVal.value));</div>
<div class="MsoNormal">
else
if (thisKeyVal.fieldtype == 'DOUBLE')</div>
<div class="MsoNormal">
obj.put(thisKeyVal.key,
Double.valueof(thisKeyVal.value));</div>
<div class="MsoNormal">
else
if (thisKeyVal.fieldtype == 'BOOLEAN')</div>
<div class="MsoNormal">
obj.put(thisKeyVal.key,
((thisKeyVal.value).toUpperCase() == 'TRUE') );</div>
<div class="MsoNormal">
else
if (thisKeyVal.fieldtype == 'BLOB')</div>
<div class="MsoNormal">
obj.put(thisKeyVal.key,
Blob.valueof(thisKeyVal.value));</div>
<div class="MsoNormal">
else
if (thisKeyVal.fieldtype == 'ID'){</div>
<div class="MsoNormal">
obj.put(thisKeyVal.key,
((ID)thisKeyVal.value));</div>
<div class="MsoNormal">
}else</div>
<div class="MsoNormal">
obj.put(thisKeyVal.key,
thisKeyVal.value);//String</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
system.debug('##
obj ' + obj); </div>
<div class="MsoNormal">
return
obj;</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
}<br />
<br />
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
public static sObject convertToSobject(Map<String, Object> objMap){</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<br style="line-height: 21.2999992370605px;" /></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>sObject sObj = Schema.getGlobalDescribe().get((String)((Map<String, Object>)objMap.get('attributes')).get('type')).newSObject();</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>Map<String, Schema.SObjectField> sObjMap = sObj.getSObjectType().getDescribe().fields.getMap();</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<br style="line-height: 21.2999992370605px;" /></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>for(String key : objMap.keySet()){</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span> <span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>if(sObjMap.containskey(key)){</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>Schema.DescribeFieldResult field = sObjMap.get(key).getDescribe();</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>String fieldType = field.getType().Name();</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span> <span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>String value = (String) objMap.get(key);</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span> <span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>if(fieldType == 'DATE'){ </div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>sObj.put(key, Date.valueOf(value));</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>}else if(fieldType == 'DATETIME'){</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>sObj.put(key, Datetime.valueOf(value));</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>}else if(fieldType == 'DECIMAL'){</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>//sObj.put(key, Decimal.valueof(value));</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>sObj.put(key, Decimal.valueOf(value));</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>}else if(fieldType == 'INTEGER'){</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>sObj.put(key, Integer.valueOf(value));</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>}else if(fieldType == 'LONG'){</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>sObj.put(key, Long.valueOf(value));</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>}else if(fieldType == 'DOUBLE'){</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>sObj.put(key, Double.valueOf(value));</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>}else if(fieldType == 'BOOLEAN'){</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>sObj.put(key, (value.toUpperCase() == 'TRUE'));</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>}else{// String</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>sObj.put(key, value);</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>}</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>}</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>}</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span></div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<span class="ecxApple-tab-span" style="line-height: 21.2999992370605px; white-space: pre;"> </span>return sObj;</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
}</div>
<div style="background-color: white; color: #444444; font-family: Calibri, sans-serif; font-size: 15px; line-height: 21.2999992370605px;">
<br /></div>
</div>
<div class="MsoNormal">
}</div>
<div class="MsoNormal">
<br /></div>
</td>
</tr>
</tbody></table>
<div class="MsoNormal">
<br /></div>
<br />
<div class="MsoNormal">
<o:p> In my next blog we will start building some examples of using the framework. If you have any questions about the framework please add comments on my blog</o:p></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-44294144478777053542015-05-24T00:26:00.001-07:002015-05-24T00:26:55.262-07:00Unit Test Data Creation Framework<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Ive worked in so many companies where developers copy and
paste code from 1 unit test to another to create test data for the testmethod.
Then when they need to add a new field because it is a new required field that
is failing tests they realise they've got to copy to all classes.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Some companies improve by having a central class but the
functions they make have passed in arguments for each field, so for each field that
needs to be passed in requires a change to this class.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Some improve this by passing in a list of a key value pair
classes. This will become clearer later when we start coding in my follow on blog to this one.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Some may improve even further by having a for loop to create as
many records as you like.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
But Ive never seen a company to have all the benefits above
plus using json to serialise and de-serialise to / from generic sobjects. Use OOP to provide a logical framework separating
functionality that provide only returning Casted Sobjects, inserting single
objects, inserting multiple objects for bulk testing, updating objects,
inserting multiple objects of different types and linking them together, and
inserting multiple objects creating complex linked data structures.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Building into the framework a highly flexible capability so
whatever type of test data is required the framework can easily create.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Also to provide an option for rapid transactional processing to
speed up unit tests and also speed up deployments.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
The Framework can also be used to create data in Salesforce
for many purposes such as data migration, exposing for web services etc.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
So lets get started.</div>
<div class="MsoNormal">
First create a number of classes</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
ITestData</div>
<div class="MsoNormal">
This is the
interface class </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataJsonLibrary</div>
<div class="MsoNormal">
Provides
the json strings that will be serialised into sobjects</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataReturnData</div>
<div class="MsoNormal">
Serialises
json strings from TestDataJsonLibrary or custom json strings</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataInsertData</div>
<div class="MsoNormal">
DML
transactions of the serialised json strings occurs here, but only inserts 1 record</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataUpdateData</div>
<div class="MsoNormal">
Inserts and
then updates a record</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataComplexData</div>
<div class="MsoNormal">
Inserts
multiple records of different Sobjects and links the records together</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TestDataBulkData</div>
<div class="MsoNormal">
Inserts
multiple records</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
UtilDML</div>
<div class="MsoNormal">
A utility
class used to assign values to any fields of any Sobject</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
KeyValue</div>
<div class="MsoNormal">
This
contains information of fields, their api name, value and data type</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
KeyValueBulk</div>
<br />
<div class="MsoNormal">
This
contains information in KeyValue, how many records to create for each object and whether or not to bypass
code in triggers for rapid transactional processing
( the default is not to bypass triggers )</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
TriggerController</div>
<div class="MsoNormal">
</div>
<div class="MsoNormal">
If you have
any code in triggers also create this class</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In my next blog I will start showing you the coding</div>
<div class="MsoNormal">
<br /></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-83020775818312616292015-05-22T13:39:00.001-07:002015-05-22T13:39:56.561-07:00Whats good about Salesforce Summer 15 Release<b>Duplicate Management</b><br />
Im sure you are now aware of this, if not you need to be it will be invaluable to every organisation.<br />
Maintaining clean and accurate data is one of the most important things you can do to help your organization get the most out of<br />
Salesforce. With Data.com Duplicate Management, you can control whether and when you allow users to create duplicate records<br />
inside Salesforce; customize the logic that’s used to identify duplicates; and create reports on the duplicates you do allow users to<br />
save.<br />
<br />
<b>DML Options</b><br />
runAsCurrentUser()<br />
Set to true to make sure that sharing rules for the current user are enforced when duplicate rules run. Set to false to use<br />
the sharing rules specified in the class for the request. If no sharing rules are specified, Apex code runs in system context and<br />
sharing rules for the current user are not enforced.<br />
<br />
<b>Search Namespace</b><br />
System.Search.find(String) method, which performs dynamic SOSL queries<br />
Example<br />
getSObject() - Returns an sObject from a SearchResult object.Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com6tag:blogger.com,1999:blog-2440629247224375310.post-43908117764404551062015-05-22T13:37:00.002-07:002015-05-22T13:37:39.341-07:00Generic Model For Daisy Chain Batches<b><br /></b>
<br />
In the Winter 15 release Salesforce released my idea allowing daisy chaining batch jobs, so when 1 batch job finishes a new batch can be started. Now if you have say 3 different batch jobs and at the end of the batch a new batch must be started, or you need a decision making process to decide if to start a new batch or not, you would need to create 3 separate batch classes. So, I've created a design model where only 1 batch class needs to be created, this provides a generic and flexible batch model, as shown below:<br />
<br />
<br />
global class batchclass implements Database.Batchable<sObject>, Database.Stateful, Database.AllowsCallouts{<br />
global String batchType;<br />
global String soql;<br />
global Boolean success;<br />
<br />
<br />
//each time you would normally want to create a new batch class instead simply add a new else if statement in execute() and finish()<br />
global batchclass(){<br />
//default batch type<br />
batchType = Constants.CONST_TYPE1;<br />
}<br />
<br />
global batchclass(String thisbatchType){<br />
//pass the batch type to run<br />
batchType = thisbatchType;<br />
}<br />
<br />
global batchclass(String thisbatchType, String thissoql){<br />
//pass the batch type to run and batch requires a soql <br />
batchType = thisbatchType;<br />
soql = thissoql;<br />
}<br />
<br />
global Database.QueryLocator start(Database.BatchableContext bc) {<br />
//Some batches will need to retrieve data from the database, use soql for this<br />
if (soql == null || soql == '')<br />
return Database.getQueryLocator('Select id From User limit 1');//data will not be used in the execute but User is used because there will always be at least 1 user in the org<br />
else<br />
return Database.getQueryLocator(soql);<br />
}<br />
<br />
global void execute(Database.BatchableContext BC, List<sObject> glbs){<br />
//decide which function to call depending on the type<br />
if (Limits.getLimitCallouts() > (Limits.getCallouts() -10) ) {<br />
if (batchType == Constants.CONST_TYPE1)//Constants just contains static variable strings<br />
success = Utils.callFunction1();<br />
else if (batchType == Constants.CONST_TYPE2)<br />
success = Utils.callFunction2();<br />
}<br />
//success variable deecides whether the batch will be run again<br />
}<br />
<br />
global void finish(Database.BatchableContext BC){<br />
//if success = true decideToRunFunction1Again is called which will either call a different batch job, or the same. It may contain a decision process as well<br />
//such as each time the execute() runs a custom setting is incremented and the decide functions look at this custom setting to decide if to run the batch again<br />
if (batchType == Constants.CONST_TYPE1 && success){<br />
Utils.decideToRunFunction1Again();<br />
}<br />
else if (batchType == Constants.CONST_TYPE2 && success){<br />
Utils.decideToRunFunction2Again();<br />
}<br />
}<br />
<br />
}<br />
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-43992478170785657322015-05-22T13:35:00.001-07:002015-05-22T13:35:09.780-07:00More Salesforce Spring 15 Release<b>Set Up Test Data for an Entire Test Class </b><br />
Use test setup methods (methods that are annotated with @testSetup) to create test records once and then access them in every test method in the test class. Test setup methods can be time-saving when you need to create reference or prerequisite data for all test methods, or a common set of records that all test methods operate on.<br />
<br />
@testSetup static void setup() {<br />
// Create common test accounts<br />
List<Account> testAccts = new List<Account>();<br />
<br />
for(Integer i=0;i<2;i++) {<br />
testAccts.add(new Account(Name = 'TestAcct'+i));<br />
}<br />
<br />
insert testAccts;<br />
}<br />
<br />
//The Accounts created in setup() are automatically available in testMethod1() and testMethod2() which makes our test methods easier to make and the tests will run faster and more efficient<br />
<br />
static void testMethod1() {<br />
}<br />
<br />
static void testMethod2() {<br />
}<br />
<br />
<br />
<b>Chain More Jobs with Queueable Apex </b><br />
Queueable Apex was introduced in Winter ’15 and enables you to easily start and manage asynchronous processes. Previously, you could chain a queueable job to another job only once. You can now chain a job to another job an unlimited number of times. For Developer Edition and Trial organizations, your chain can have up to five queueable jobs.<br />
<br />
public class AsyncExecutionExample implements Queueable {<br />
<br />
public void execute(QueueableContext context) {<br />
// Your processing logic here<br />
// Chain this job to next job by submitting the next job<br />
<br />
System.enqueueJob(new SecondJob()); //2nd job queued<br />
}<br />
<br />
}Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-86121213462475782212015-05-22T13:33:00.001-07:002015-05-22T13:33:11.722-07:00More Salesforce Spring 15 Release<b>Import Accounts and Contacts with Ease</b><br />
Your Name > My Settings > Import > Import My Accounts & Contacts,<br />
and import from loads of source outlook, linkedin, excel, yahoo, zoho etc<br />
<br />
<b>Educate Users with Salesforce Adoption Manager</b><br />
send tips by email to users to encourage good working processes<br />
<br />
<b>Call an Apex Method from a Process</b><br />
When no other process action can get the job done, add customized functionality to your Salesforce processes by calling an Apex<br />
method.<br />
To call an Apex method, add the Call Apex action to your process and select an Apex class with an invocable method.<br />
<br />
<b>Monitor Your Users’ Login and Logout Activity</b><br />
This could be used to identify user activity and if a user is getting most out of Salesforce and possibly identify user to remove and save on licenses.<br />
<br />
<b>ISVs</b><br />
Streamline Managed Packages by Deleting Unused Components<br />
<br />
<b>Develop Deployable Custom Metadata Types (Pilot)</b><br />
You can now create custom metadata types and can then create custom metadata that uses these<br />
types’ characteristics. ISVs and enterprise IT departments have in the past emulated custom metadata<br />
types by using list custom settings and in some cases custom objects, but the rows on these items<br />
are data, not metadata, and data can’t be deployed to different organizations.<br />
<br />
Also, other features....<br />
<br />
<b>Mass Submit for Approval</b><br />
<br />
<b>Creation of Any Object via Workflow Rule</b> - using the new Process Builder<br />
<br />
<b>Submit for Approval Through Workflow Rules</b> - using the new Process Builder<br />
<br />
<b>Apex Called by Workflow</b><br />
<br />
<b>Allow Changes in Formula Field Value to Trigger Workflow</b><br />
<br />
<b>Implement an "Apex Queue" for Async Processing</b> - Create your own queues for whatever you like<br />
<br />
<b>Submit More Batch Jobs with Apex Flex Queue (Generally Available)</b> - Now allows potentially unlimited sequential batches to run<br />
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-87082872544343983222015-05-22T12:57:00.003-07:002015-05-22T12:57:46.114-07:00Whats good about Salesforce Spring 15 Release<br />
<b>Open CTI</b><br />
http://releasenotes.docs.salesforce.com/spring15/spring15/release-notes/rn_open_cti.htm<br />
I'd expect the likes of New Voice Media are not going to be happy about this, but now developers will be able to easily integrate with whatever CTI system you like.<br />
<br />
<b>Outages and business continuity</b><br />
http://releasenotes.docs.salesforce.com/spring15/spring15/release-notes/rn_organization_sync.htm<br />
This uses the Salesforce to Salesforce fetaure<br />
Some of the issues I see with this Salesforce to Salesforce only works from a Production /Dev to Production / Dev org, so you wont be able to copy data to say your full sandbox. So you will need a separate Production / Dev org which has the same size of data storage as your Production org, which means a lot of extra cost.<br />
You will also need to make sure that all your meta data is up-to-date across both orgs and to constantly be updating Salesforce to Salesforce subscribe settings. Otherwise your data will not transfer across correctly. All of which will introduce extra work for your company to maintain.<br />
But on a positive note, if you can easily select specific records / objects and export subsets of data then this could be beneficial<br />
For good business continuity do use the current Data Export ability that can schedule objects to be exported in a csv file<br />
<br />
<br />
<b>Important Fix</b><br />
A useful feature was released in winter 15 that allows you to Deploy without deleting Scheduled jobs by ticking a box in Deployment Settings<br />
For some orgs when you go to Deployment Settings you will see Insufficient Privileges<br />
This is a known error but there is a workaround here<br />
https://success.salesforce.com/issues_view?id=a1p30000000eJZlAAM<br />
<br />
<b>Quick Deploy</b><br />
Also I can confirm that Quick Deploy now fully works and is a great addition for deploymentsAnonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0tag:blogger.com,1999:blog-2440629247224375310.post-21982222564287410262014-07-15T09:47:00.002-07:002014-07-15T09:47:29.140-07:00Frameworks or Processes<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-size: 13.5pt;"><br />
Frameworks or Processes<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<br /></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-size: 13.5pt;">I was discussing our processes at work 1
day with my manager, Bruce Heard. You notice I automatically said processes.
The question is do we have processes or frameworks. Bruce said to me, “if you
stood in front of a classroom and write a load of facts on a whiteboard the
pupils will remember about 10℅ of what you said. If instead you tell them the
subject and that they must use the tools available, eg the internet, books etc
to find out what they can about the subject. The pupils will ultimately
remember more and learn more.” This principal can be extended to the workplace
by providing not a hard rigid set of rules but a more flexible framework to
allow the employee some degrees of freedom to investigate, experiment, adapt
and learn.<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<br /></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-size: 13.5pt;">First a business needs to decide if to
adopt a Framework or Process approach.<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-size: 13.5pt;">Whichever you choose between using Frameworks
or Processes which will be specific to your business its important to have a
coherent approach throughout your business so if its Frameworks or Processes it
should be a value held throughout your business so all departments fully adopt
the approach selected.<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-size: 13.5pt;">Now its equally important for your
Frameworks or Processes to evolve but its equally important that your Frameworks
dont become Processes or vice versa, to ensure this doesnt happen its necessary
to define what your business defines as a Framework and a Process, which will
be specific for your business.<o:p></o:p></span></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-size: 13.5pt;">This will allow you to govern your Frameworks or Processes and
ensure that they don’t gravitate too far away from becoming its opposite force.<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<br /></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-size: 13.5pt;">Your business should continually monitor
your Frameworks or Processes, whichever you have selected as your core value
for your business to ensure that they remain steadfast to their definition. A
department should be accountable to ensuring all departments adhere to this, if
you like, internal auditors of your Frameworks or Processes ( whichever is
selected for your business )<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-size: 13.5pt;">It is imperative that each department buys
into the core values because if some departments adopt a Framework approach and
other departments Processes, since departments rarely act as silos in a
business or shouldn’t act as silos and should communicate across their borders
you will consequently develop poor communications and tensions will arise
between departments<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-size: 13.5pt;">A separate dimension that we’ve not discussed are the tools to use
which act as enablers for your Frameworks or Processes. You should have a consistent
approach to the tools you use and the tools should be specified in your
Frameworks or Processes. Defining tools to use ensures a consistent approach. If
tools are not specified in your then the user can select any tool they wish to
do their work<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-size: 13.5pt;">which may not be safe, may not following
industry standards, could cause issues when you are being audited, may not be
efficient, may result in losing business ISO accreditations, difficult to
manage, train and support etc<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<br /></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-size: 13.5pt;">When would you use a Framework or Process.
To answer this there are a few things to take into account. If you adopt Frameworks
you would not make statements, such as "click here now click there, enter
this and then jump up and down", you simply state read this article in the
event you need to do X, in other words signpost the user and let them go and
work it out for themselves exactly what they need to do.<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-size: 13.5pt;">For processes, you will consider every
possibility without the possibility of any other permutation and specifically
state the steps the user needs to perform which could be references to other
articles and online tutorials etc but the difference to frameworks is that all
possibilities are considered and accounted for with a process to explain to the
reader what they should do in such events.<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<br /></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-size: 13.5pt;">Frameworks foster an environment of
creativity, empowers employees, saves time in producing exhaustive reams of
process material and is more adaptable, and makes employees accountable as they
cannot hide behind a process and blame the process when something goes wrong;
they know what their role is, they know what their duties are and they are
given the tools, training and a framework to achieve their duties.<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-size: 13.5pt;">Frameworks work well in ever changing
environments, but not as well in environments were control is necessary where
consequences of error is catastrophic.<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<br /></div>
<div style="margin-bottom: .0001pt; margin: 0cm;">
<span style="font-size: 13.5pt;">Processes allow strict control with little chance of anomalies
occurring. In businesses were roles and responsibilities and duties rarely
change, well defined processes can work well and where it is 100% critical that
an exact process is followed; organisations such as hospitals, military and
where the consequences of deviating from a strict set of processes can result
in catastrophic failure.<o:p></o:p></span></div>
<div style="margin: 0cm 0cm 0.0001pt;">
<br /></div>
<br />
<div style="margin: 0cm 0cm 0.0001pt;">
<span style="font-size: 13.5pt;">Processes can lead to personnel avoiding
accountability when errors occur because they are able to blame the process.
The only exception for this is if the organisation does not adopt good tools to
support the framework, and doesn't allow freedom to develop and experiment with
the framework.<o:p></o:p></span></div>
Anonymoushttp://www.blogger.com/profile/00481337545073165642noreply@blogger.com0