+ Start a Discussion
SCRSCR 

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; } }

 

jkucerajkucera

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

SCRSCR
Thanks for the response, John.  That is an interesting capability, but I don't think it will help me get to the end result I'm trying to achieve.  I probably didn't do a very good job of explaining what I'm trying to do.  Let me give it another shot. The goal is to allow a registered Job Candidate User who has already applied for a job previously to apply for another job without having to reenter their candidate information (and thus avoid creating a duplicate candidate record in the Candidate__c object).  Records are created in the User, Account and Contacts objects as part of the Sites User Registration process when the Job Candidate registers to the Site for the first time.  Once registered, the Job Candidate can apply for a Job Position that they select from a list of Job Search results by clicking on the Position ID for a record in the list which takes them to the Job Detail (VF Page: PublicJobDetails) which has an "Apply" button which takes them to the Job Application form (VF Page: PublicJobApplication).  The Job Candidate User fills out the form and clicks on the "Save" button to submit the job application.  This action creates both a new Job Application record (in the Job_Application__c object) and a candidate record (in the Candidate__c object).  This works fine for a Job Candidate User who registers and only submits a job application for 1 job.  However, if the Job Candidate User returns to the site or elects to submit a job application for another job, then a new candidate record is created.  I'm trying to understand how to avoid the creation of a new candidate record (which is in effect a duplicate). My thinking is that the email for the candidate can be used to check for an existing candidate record (or Contact record... not sure which makes the most sense) and then return the existing candidate information wherein the Job Candidate User could update the information, but not have to completely re-enter it.  Sorry for the long winded explanation.  I hope this more clearly explains my issue. Thanks,

SCR

jkucerajkucera

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

SCRSCR

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

 

jkucerajkucera

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.

 

 

SCRSCR

Thanks very much for your help.  I'll give this a try and post my results.

-SCR

SCRSCR

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

jkucerajkucera

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);

 


 

SCRSCR

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:

 

11:20:49 DEBUG - Executing: ApexPages.CurrentPage().getParameters().put('id', candidateId);
11:20:49 INFO - Cumulative profiling information:
No profiling information for SOQL operations.
No profiling information for SOSL operations.
No profiling information for DML operations.
No profiling information for method invocations.
11:20:49 ERROR - Compile error: Variable does not exist: candidateId
The complete Apex Class code for the controller extension (checkExistingCandidate method highlighted in RED):

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

 

jkucerajkucera

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?

SCRSCR

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

jkucerajkucera
Looks like you're reusing the string CandidateID trying to again cast it as an ID 4 lines down.  Make then 2 different variables and you should be ok.  Also, I'm guessing you only wnat to use 1 of ID or the email address to match, so I put in the check if candidateID is null before querying for candidates

// 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; } }

 

SCRSCR

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