You need to sign in to do that
Don't have an account?
How to check for existing related record using Sites Page with user registration
Hello - I am trying to figure out a way to check if a custom object record already exists or not when a Sites user either registers or logs into the Sites Page and attempts to create a new record (in this case Job Application). The Custom Object is Candidate, and I want to accompish two things:
1) Check for an existing Candidate record in force.com based on the email address prompted for in the Job Application form (or perhaps the Username in the registration form); or
2) Allow a registered user to login and create a new Job Application record in force.com using their existing Candidate record (if they already applied for another position).
Currently a registered user can apply for a job position. However, if the same user comes back to the site, logs in and applies for another position then a new Candidate record is created. I would like to check if a Candidate record already exists and return all of the existing Candidate fields so as to avoid duplicate records and unnecessary data input.
Any help is greatly appreciated.
- SCR
The Controller Extension for the PublicJobApplication as it exists:
public class PublicJobApplicationExtension { // This controller extends the standard controller // overwrites the actions // creates a candidate record // creates attachment on the candidate record based on the uploaded file // creates a job application record that links the candidate record and the related position private final Candidate__c candidate; private ID positionid = ApexPages.currentPage().getParameters().get('jobid'); private Job_Application__c jobapplication {get; private set;} public Blob resume {get; set;} public String contentType {get; set;} public String fileName {get; set;} // Extends the standard controller for the candidate object public PublicJobApplicationExtension(ApexPages.StandardController stdController) { candidate = (Candidate__c)stdController.getRecord(); } public Position__c getPosition() { return [SELECT id, name, Position_type__r.Name, Job_Description__c FROM Position__c WHERE id = :positionid]; } public PageReference saveApplication() { // Creates the candidate record try { insert(candidate); } catch(System.DMLException e) { ApexPages.addMessages(e); return null; } jobapplication = new Job_Application__c(); jobapplication.Candidate__c = candidate.id; jobapplication.Position__c = positionid; // Creates an attachment to the candidate record if a resume file is uploaded if (resume != null) { Attachment attach = new Attachment(); attach.Body = resume; attach.Name = fileName; attach.ContentType = contentType; attach.ParentId = candidate.id; try { insert(attach); } catch(System.DMLException e) { ApexPages.addMessages(e); return null; } } // Creates the job application record to link the candidate and the related position try { insert(jobapplication); } catch(System.DMLException e) { ApexPages.addMessages(e); return null; } PageReference p = Page.PublicJobApplicationConfirmation; p.setRedirect(true); return p; } }
If you're looking for the VF, you can fire an action upon load that redirects the page if conditions are different:
For example, this VF page header redirects the page if the URL doesn't contain a key that matches the campaign member ID:
<apex:page standardController="CampaignMember" extensions="UpdateCampaignMemberClass" sidebar="false" showHeader="false" action="{!checkEncryptionKey}">
Full code here:
http://blog.sforce.com/sforce/2009/08/more-secure-sites-webforms-with-encrypted-keys.html
SCR
I'm still a bit fuzzy how the flow works, but it sounds like you know the email address but not the applicant ID when the user logs in?
If that's accurate, you should be able to query by email address (assuming you enforce uniqueness on email), return the ID, put the ID in the URL, and have conditional code such as my encryption example to redirect the page if there's an ID in the URL.
New person:
Deafult page = new edit page & page does not reload
Existing person:
Page redirects upon load & they see detail page with their information
John - Your solution sounds like it is on the right track. If I'm understanding it correctly, there are two parts to the solution:
1) Add a method into the controller extension (PublicJobApplicationExtension) that uses a SOQL query to return the Candidate ID based on the email address.
2) Use the "action" attribute on the apex:Page tag (in the PublisJobApplication Page) to call the method and redirect to an instance that has the existing record upon load.
Am I understanding this correctly? Do you have any code fragments as an example that I could study to better understand this?
As you may have deduced, I am not a programmer by trade. I am in the process of teaching myself Apex, VF and Sites. I appreciate your patience.
Thanks,
SCR
Yes - that's what I meant.
For code examples, the encryption post has details around how that redirect works.
It's effectively a method that returns a different URL if your conditions are met, which in this case means the SOQL returns a row, and does nothing if the coditions aren't met.
For the soql-It should be pretty straightforward to create the query & check if it has any rows.
Thanks very much for your help. I'll give this a try and post my results.
-SCR
Hello - I tried to follow your code example. I'm getting stuck on the PageReference. I'm just not sure how to set this up so that it will do what I want it to do. I have scoured the dev force site and found nothing that seems to help. My query seems to work correctly, but I think that I am setting up the PageReference incorrectly.
Added the following method to the PublicJobApplication Controller:
// Checks to see if a Candidate record for the applicant already exists public PageReference checkExistingCandidate() { string candidateId = ApexPages.currentPage().getParameters().get('id'); string candidatePageRef='http://stratasaas-developer-edition.na6.force.com/apex/PublicJobApplication?id='; Candidate__c[] candidates = [Select ID FROM Candidate__c WHERE email__c = :candidate.email__c LIMIT 1]; candidateId = candidates[0].id; string urlCandidateRecord = candidatePageRef + candidateId; if (candidateId!= null) { return new PageReference(urlCandidateRecord); } else { return null; } }
Then I added the action="{!checkExistingCandidate}" attribute to the page tag. Clicking on the "Apply" button on the PublicJobDetails Sites page (after you login or register) takes you to this URL:
http://stratasaas-developer-edition.na6.force.com/PublicJobApplication?jobid=a018000000MfFpwAAF
The jobid "01p80000000BwAt" is the correct positionId from the PublicJobDetails Sites Page.
This renders the following error on the PublicJobApplication Sites Page:
Error: Error occurred while loading a Visualforce page.
I'm sure that I have done this entirely wrong (but I seem to be getting closer). Any help would be greatly appreciated. Learning this stuff is painful without a programming background (but Apex, VF and Sites are awesome DaaS technology and it is all starting to make sense).
Thanks in advance.
- SCR
The syntax for your pagereference url is a bit off. For vf pages, the format has to be:
url?id=00013204230423042
Something like this should work:
string urlCandidateRecord = candidatePageRef +'?Id='+ candidateId;
This syntax is what you can then use for testing the controller:
ApexPages.CurrentPage().getParameters().put('id', candidateId);
John - I really apprecaite all of your suiggestions. I'm still unable to get this to work. I made the changes to the URL string variable per your reply and I used the syntax you suggested to test the controller, and got the following message using the Execute Apex function in the System Log window:
public class PublicJobApplicationExtension { // This controller extends the standard controller // overwrites the actions // creates a candidate record // creates attachment on the candidate record based on the uploaded file // creates a job application record that links the candidate record and the related position private Candidate__c candidate; private ID positionid = ApexPages.currentPage().getParameters().get('jobid'); private Job_Application__c jobapplication {get; private set;} public Blob resume {get; set;} public String contentType {get; set;} public String fileName {get; set;} // Extends the standard controller for the candidate object public PublicJobApplicationExtension(ApexPages.StandardController stdController) { this.candidate = (Candidate__c)stdController.getRecord(); } public Position__c getPosition() { return [SELECT id, name, Position_type__r.Name, Job_Description__c FROM Position__c WHERE id = :positionid]; } // Checks to see if a Candidate record for the applicant already exists public PageReference checkExistingCandidate() { string candidateId = ApexPages.currentPage().getParameters().get('id'); string candidatePageRef='http://stratasaas-developer-edition.na6.force.com/apex/PublicJobApplication'; Candidate__c[] candidates = [Select ID FROM Candidate__c WHERE email__c = :candidate.email__c LIMIT 1]; candidateId = candidates[0].id; string urlCandidateRecord = candidatePageRef +'?Id='+ candidateId; if (candidateId!= null) { return new PageReference(urlCandidateRecord); } else { return null; } } // Creates the candidate record public PageReference saveApplication() { try { insert(candidate); } catch(System.DMLException e) { ApexPages.addMessages(e); return null; } jobapplication = new Job_Application__c(); jobapplication.Candidate__c = candidate.id; jobapplication.Position__c = positionid; // Creates an attachment to the candidate record if a resume file is uploaded if (resume != null) { Attachment attach = new Attachment(); attach.Body = resume; attach.Name = fileName; attach.ContentType = contentType; attach.ParentId = candidate.id; try { insert(attach); } catch(System.DMLException e) { ApexPages.addMessages(e); return null; } } // Creates the job application record to link the candidate and the related position try { insert(jobapplication); } catch(System.DMLException e) { ApexPages.addMessages(e); return null; } PageReference p = Page.PublicJobApplicationConfirmation; p.setRedirect(true); return p; } }
The VF Page redirects to an error message Page (noted in previous message). The only clue to this problem that I can see is that the URL that you are redirected to uses "jobid?" to reference the positionId rather than "Id?" which tells me that the method is not being invoked properly (or at all), otherwise the URL would contain "Id?" in it instead. I would like to think that I am close to solving this, but I am stuck. Any help is really appreciated.
- SCR
Wierd that you're getting a compiler error yet you can save the record.
When exactly are you seeing the failure? Is it from the test method, when you save the controller extension, or another time?
You are an extremely patient person (approaching Saint status). I really do appreciate all of your assistance.
The quick answer to your 1st question is that I see the failure when I add the action attribute on the PublicJobApplication VF Page to the Apex Page Tag that points to the checkExistingCandidate method in the PublicJobApplicationExtension Apex class. I will do my best to answer your questions in a more detailed manner.
I have tested the actual VF Sites Page a couple of ways:
1) Insert the Candidate. Remove the action="{!checkExistingCandidate}" attirbute on the Page Tag and save a Job Application record (which also creates a Candidate record). Once removed (and the PublicJobApplication VF Page is saved) I am able to access the PublicJobApplication Page by clicking on the "Apply" button in the PublicJobDetails Page, which uses the OnClick attribute to redirect to browser to the PublicJobApplication Site Page which references the
{!$Site.Prefix}/PublicJobApplication?jobid={!Position__c.Id}.
Then I'm able to fill in the information and save the record by calling the saveApplication method by clicking on the "Save" button (commandButton tag in VF markup) in the PublicJobApplication Page.
2) Try to call the existing Candidate. Reinsert the action="{!checkExistingCandidate}" attirbute on the Page Tag in the PublicJobApplication Page. Login as the user (who is now also has a Candidate record), select a job poisiton to apply for and click on the apply button... I get the error.
The App flows I'm trying to achieve:
A) Registered User who already has a Candidate record in force.com and searchs jobs first
Job Applicant Visits Job Search site (PublicJobs Page)
(http://stratasaas-developer-edition.na6.force.com/PublicJobs)
Job Applicant selects a job position they wish to apply for (clicks on Position ID link)
Browser is redirect to the Job Detail Page (PublicJobDetails)
(http://stratasaas-developer-edition.na6.force.com/PublicJobDetails?id=a018000000MfFppAAF)
User clicks on the "Apply" button and is redirected to the User Login where they login and proceed
(http://stratasaas-developer-edition.na6.force.com/SiteLogin)
Browser is redirected to the Job Application form (PublicJobApplication Page). All of the Candidate
inforamtion that was previously captured is saved (or updated then saved).
with URL like (http://stratasaas-developer-edition.na6.force.com/PublicJobApplication?jobid=<???>)
B) Registered User who already has a Candidate record in force.com and logs into the site first
Job Applicant Visits Job Search site (PublicJobs Page)
(http://stratasaas-developer-edition.na6.force.com/PublicJobs)
Visitor clicks on Login link and they login and proceed
(http://stratasaas-developer-edition.na6.force.com/SiteLogin)
Job Applicant selects a job position they wish to apply for (clicks on Position ID link)
Browser is redirect to the Job Detail Page (PublicJobDetails)
(http://stratasaas-developer-edition.na6.force.com/PublicJobDetails?id=a018000000MfFppAAF)
User clicks on the "Apply" button and the Browser is redirected to the Job Application form
PublicJobApplication Page). All of the Candidate inforamtion that was previously captured is saved (or
updated then saved).
with URL like (http://stratasaas-developer-edition.na6.force.com/PublicJobApplication?jobid=<???>)
I hope this helps you to help me.
Thanks,
SCR
// Checks to see if a Candidate record for the applicant already exists public PageReference checkExistingCandidate() { ID candidateIdFromEmailAddress =new ID(); string candidateId = ApexPages.currentPage().getParameters().get('id'); string candidatePageRef='http://stratasaas-developer-edition.na6.force.com/apex/PublicJobApplication'; string urlCandidateRecord = candidatePageRef +'?Id='+ candidateId;
if (candidates.size()!=0 && CandidateID!=null){ candidate__c[] candidates = [Select ID FROM Candidate__c WHERE email__c=:candidate.email__c LIMIT 1];
candidateIdFromEmailAddress = candidates[0].id; urlCandidateRecord += candidateIdFromEmailAdderess; } if (candidateId!= null) { return new PageReference(urlCandidateRecord); }else { return null; } }
I unable to get the code for the checkExistingCandidate method (as you've written it below) to work. I running into two problems, and I am uncertain of the logical flow of the method as you've coded it.
Problem 1: The candidateIdFrom EmailAddress variable fails to compile. I get the error "Compile Error: Type cannot be constructed: ID at line 27 column 39". My understanding is that this is coded as a variable that I'm declaring of type ID, not a method. I can fix this by simply declaring the variable and not setting its value, but I think that undermines the logic of what you've suggested.
Problem 2: In the test "if (candidates.size()!=0 && CandidateId!=null)" I get an error "Compile Error: Method does not exist or incorrect signature: candidates.size() at line 32 column 11". This makes sense to me because there is no size parameter to reference. I believe that records need to be queried for a variable that is of type Array before you can reference the size() parameter for what is returned. I think I understand the intention of what you've suggested, but I don't understand how to get there (another SELECT statement for a candidates variable of type Array to return records before referencing the size() parameter?).
Uncertainty Explained: I do not understand why the if tests are testing for candidateId != null in both cases. It seems to drive the result to the same outcome. Is this intentional? What am I missing?
In an attempt to understand the logic of what your code example seems to suggest (to me), I rewrote the method in the following manner (differences highlighted in Red Bold):
// Checks to see if a Candidate record for the applicant already exists public PageReference checkExistingCandidate() { ID candidateIdFromEmailAddress; string candidateId = ApexPages.currentPage().getParameters().get('id'); string candidatePageRef='http://stratasaas-developer-edition.na6.force.com/apex/PublicJobApplication'; string urlCandidateRecord = candidatePageRef +'?Id='+ candidate.Id; if (this.candidate!=null && candidateId!=null){ candidate__c[] candidates = [Select ID FROM Candidate__c WHERE email__c=:candidate.email__c LIMIT 1]; candidateIdFromEmailAddress = candidates[0].id; urlCandidateRecord += candidateIdFromEmailAddress; } if (candidateId!= null) { return new PageReference(urlCandidateRecord); }else { return null; } }
To test this I logged in as an existing User with and existing Candidate record. The functionality still behaves as if you are entering a new Candidate into the Job Application form. In otherwords, I am still unable to get the existing Candidate record to be returned into the form for a Candiate that already exists who is applying for another job position. Its as if the action attribute is ignored (though I believe it is working per the logic).
[Note: The URL for the Job Application form (PublicJobApplication Page) has the "?jobid=" in it rather than the "?Id=" as specified by calling the method.
http://stratasaas-developer-edition.na6.force.com/PublicJobApplication?jobid=a018000000MfFpsAAF
This leads me to believwe that (part of) the problem lies here.]
I have to believe that this is really close. I cannot believe how hard it has been to accmpolish this seemingly simply functionlaity.
Your continued help is greatly appreciated.
- SCR