Migrating Contacts to Salesforce Person Accounts (Part 2)In Part 1 of this series we lightly covered the core concepts of the Person Account feature within Salesforce.com as well as began presenting some helpful utility classes to aid in the programmatic conversion of traditional Contacts & Accounts into a Person Account. Part 2 of this series will dive deeper into some additional utility classes global class personAccounts { Notice that the class is declared as global. In next month’s blog, we’ll be adding some WebService methods that require the class to be global in scope. Since Person Accounts have a separate RecordTypeId from other Accounts, we’ll need a few utilities to return the IDs. You can use the IsPersonAccount field on the Account object to determine if an Account is a Person Account or not, but you’ll see that when we go to migrate to a Person Account, you actually need to update the RecordTypeId on the Account from that of a non-Person Account to that of a Person Account. // Return the Record Type ID for a Person Account public static ID personAccountRecordTypeId() { return [SELECT Id FROM RecordType WHERE SobjectType = 'Account' AND Name = 'Person Account'].Id; } // Return the Record Type ID for a (any) NON Person Account public static ID NONpersonAccountRecordTypeId() { return [SELECT Id FROM RecordType WHERE SobjectType = 'Account' AND Name != 'Person Account' LIMIT 1].Id; } Now, there’s one more utility method that we need for our migration and I’m including it in the personAccounts class because it’s too specialized (it selects fields that we specifically need for the Person Account migration from an Account) to be placed generically in an AccountUtilities class. // Return a Map of IDs to Accounts for a Set of AccountIDs private static Map<ID, Account> AccountMap(Set<ID> AccountIDs) { Map<ID, Account> newMap = null; if ((AccountIDs != null) && (AccountIDs.size() > 0)) newMap = new Map<ID, Account>([SELECT Id, OwnerId FROM Account WHERE Id IN :AccountIDs]); return newMap; } Now that we have covered the utility classes, Part 3 of this series will begin to present the actual migration classes that will be responsible for the logic required to perform the actual conversion. Review / Post Comments >>
|
Migrating Contacts to Salesforce Person Accounts (Part 1)Out of the box, Salesforce is configured to be used as a Business to Business (or ‘B2B’) solution for managing Accounts and Contacts (among other things). Your Contacts are either linked to an Account using the AccountId field or they are standalone Contacts, which I like to refer to as ‘orphans’. If your business does business directly with customers in a Business to Customer (or ‘B2C’) relationship, managing your customers using Accounts and Contacts can be cumbersome because some information you want to retain about your customer, such as an account number, makes sense to exist at on the Account object and some information, such as an email address, makes sense to exist on the Contact object. Fortunately, a feature exists in Salesforce called Person Accounts which, depending on your Salesforce edition, may be enabled upon request for your org. Person Accounts are really a marriage of an Account record to a Contact record so that you have the appropriate fields available in a B2C model. Person Accounts use Record Types to differentiate between a Business Account and a Person Account. For more information about Person Accounts, click the Help Link from within your Salesforce org and search for ‘B2C Overview’. You’ll want to read up on Person Accounts and familiarize yourself with them before having Person Accounts enabled in your org. A common thing to want to do in Salesforce once you have Person Accounts enabled is to convert or migrate a Contact to a Person Account. The only way to do this is through the API so you will either have to create a custom button or link that uses an OnClick JavaScript to do the work through the AJAX toolkit, or you will need to do so in Apex code. I have seen an OnClick JavaScript button that attempts to do this by simply updating the RecordTypeId of the Account, but there was no error checking in that script and as you will see in the sample Apex code provided, there are many requisite steps required in order to successfully migrate a Contact to a Person Account, one of which is to have a Contact whose AccountId is set to an Account where the Contact and the Account are in a 1 TO 1 relationship with each other. While we will cover this topic in three parts, this first article will help set the stage by covering a number of utility classes that are used by the class we will create for handling Person Accounts. Parts two and three of this series will build off of the topics presented here, by leveraging them within the migration methods themselves. The ContactUtilities Class contains the method AccountIdSet which returns a set of Account IDs given a list of contacts. public class ContactUtilities { // Return a Set of Account IDs that a List of Contacts belong to public static Set<ID> AccountIdSet(List<Contact> Contacts) { Set<ID> AccountIDs = new Set<ID>(); if ((Contacts != null) && (Contacts.size() > 0)) for (Contact c : Contacts) if (c.AccountId != null) AccountIDs.add(c.AccountId); return AccountIDs; } } The UserUtilities Class contains the method InactiveUserIdSet which returns a set of User IDs where the User IsActive checkbox is false. public class UserUtilities { // Return a Set of User IDs that are Inactive public static Set<ID> InactiveUserIdSet() { Set<ID> UserIDs = new Set<ID>(); List<User> Users = new List<User>([SELECT Id FROM User WHERE IsActive = false]); if ((Users != null) && (Users.size() > 0)) for (User u : Users) UserIDs.add(u.Id); return UserIDs; }
Part two of this series will continue our discussion on utility classes, rounding out the supporting cast before moving onto the migration classes themselves in Parts three and four. |
Saving a Dynamically Generated PDF as an AttachmentOK, so you already know that you can create PDF output for a Visualforce page by using the renderAs attribute of the page standard component. Did you also know that with Apex code you can save that rendered page as an attachment or a document without requiring the user to save the PDF file to their computer locally and then uploading that file back up to Salesforce?
First, start by creating your PDF. Here's a sample Visualforce page that renders as a PDF file:
<apex:page renderAs="PDF">
<h1>Congratulations: This is your PDF file.</h1>
</apex:page>
Customize and save your page as myPDFpage and you can view it in Salesforce using the url: https://loc.salesforce.com/apex/myPDFpage where loc is your Salesforce instance.
As with other Visualforce pages, you can create a custom controller to handle the page, or use a standard controller with or without controller extensions. We used the standard controller for a Salesforce Quote and an extension that allowed us to create a customized Quote PDF instead of the one that comes with Salesforce.
Next, you'll need some code to save the PDF as an attachment. We can do this by using the getContentAsPDF() method of the PageReference to the PDF page as follows:
public static void GenerateAttachmentPDF(Id ParentId) {
// System.Debug('Generating a PDF Attachment for : ' + ParentId);
ApexPages.PageReference pRef = Page.myPDFpage;
pRef.getParameters().put('id',ParentId);
Attachment pdfAttachment = newAttachment();
pdfAttachment.Name = 'Attachment.pdf';
pdfAttachment.ParentId = ParentId;
pdfAttachment.Body = pRef.getContentAsPDF();
pdfAttachment.ContentType = 'pdf';
insert pdfAttachment;
// System.Debug('pdfProposal: ' + pdfProposal);
}
You'll need to call getParameters.put() only if your PDF page needs the Id of an object in order to render properly. When we built ours, we used slightly different code to save the PDF file as a PDF Quote as follows:
public static void GenerateQuotePDF(Id QuoteId) {
// System.Debug('Generating a PDF for Quote: ' + QuoteId);
ApexPages.PageReference pRef = Page.myPDFpage;
pRef.getParameters().put('id',QuoteId);
QuoteDocument pdfQuote = new QuoteDocument();
pdfQuote.QuoteId = QuoteId;
pdfQuote.Document = pRef.getContentAsPDF();
insert pdfQuote;
// System.Debug('QuoteDocument: ' + pdfQuote);
}
Save this code in an Apex Class with a name like CustomClass.
Finally, you'll need to call one of the Generate methods that you created. We did this by creating another Visualforce page that used the standard Quote controller with an extension that generated the PDF. We then overrode the standard Generate PDF button with our new page.
The following controller extension contains an action method which calls GenerateQuotePDF:
public class ExtQuoteCreatePDF {
private ApexPages.StandardController sctrl;
private Quote sq; // From the Standard Controller
// The main action method ...
public PageReference ExtGenerateQuote() {
CustomClass.GenerateQuotePDF(sq.Id);
return sctrl.cancel(); // We are done!
}
public ExtQuoteCreatePDF(ApexPages.StandardController controller) {
sctrl = controller;
sq = (Quote)sctrl.getRecord();
}
}
The following Visualforce page uses the action attribute of the page standard component to call the action method in the extension:
<apex:page
standardController="Quote"
extensions="ExtQuoteCreatePDF"
tabStyle="Quote"
id="QuoteCreatePDF"
title="Quote Create PDF"
action="{!ExtGenerateQuote}">
</apex:page>
You might want to do other things in the page and controller like a verification step, or a progress indicator, but now you have the tools required to save your PDF file directly to Salesforce.
|
Force.com Developer Training for BeginnersAs a salesforce.com authorized instructor and contributor to salesforce.com’s developer training classes, I work with a lot of developers who are new to the Force.com Platform. Traditionally developers have had 2 primary options to get up to speed on the platform. They can either 1) attend one of salesforce.com's developer classes, or 2) teach themselves using the documentation and other available resources on developer.force.com. Just recently, and luckily for all newcomers, there are now some new options provided by salesforce.com's fantastic education department.
The first new resource is the availability of video podcasts on iTunes of ALL of the DEV-401 and DEV-501 class modules being taught to a live classroom! If you're short on time or on training budget you can download them for FREE! The video podcasts allow you to see & hear one of salesforce.com's authorized instructors as he presents to a live class. While I haven’t gone through each and every video, the few I have taken a look at were high quality productions. I think they’d be great for people brushing up on select topics before they take the certification exams as well. The second resource is this link, http://salesforce.acrobat.com/fdclaunch/, to some online flash-based training courses. You can even sign-up for a 30-day trial of one of the developer class’ training instances. So for example, you can sign up for the 401 training class org and then use it as you follow along with the 401 video podcasts! While these resources will never be able to fully replace the value received from having a live authorized instructor guiding you through a course and answering your questions live, they are great for those with little time or money to spare. Kudos to salesforce.com for providing them! |
Welcome - Coming Soon...Welcome to the first of what will hopefully be many more posts to come.
The intent of our tech blog here at Etherios LLC is to spend time spotlighting new and innovative techniques that leverage the force.com platform both on its own as well as in conjunction with other technologies and cloud-based services. Here is a look ahead to posts that are coming to a theatre near you:
In addition to interesting topics we hope that this blog will also serve as an example of how Force.com Sites can be leveraged to present a public facing web property as we continue to update this blog and our site with new features & functionality. We look forward to fostering some interesting conversations on Force.com, and thank you in advance for your participation in what we hope will become a great source of information for the Force.com development community. |