Sample code for creating a custom page
This document provides sample code for creating a custom page in Salesforce using Apex.
PrepareNewQuote.page
<apex:page showHeader="true" sidebar="true" standardController="Opportunity" extensions="PrepareNewQuoteController" action="{!onload}">
<apex:form >
<apex:pageMessages id="pageErrors"/>
<apex:pageBlock rendered="{!!initFailed}">
<apex:pageBlockSection columns="1" id="accountsection">
<apex:outputLabel rendered="{!billingAccountList.size != 0}" value="There is one or more Z-Billing Account corresponding to this Salesforce Account." />
<apex:outputLabel value="Please select the account to use:" style="font-weight:bold"></apex:outputLabel>
<apex:selectRadio layout="pageDirection" id="accTypeRadio" value="{!selectedAccountType}">
<apex:actionSupport event="onclick" action="{!onSelectAccountType}" reRender="accListRadio, subscriptionSection, pageErrors"/>
<apex:selectOption itemEscaped="false" itemlabel="New billing account" itemValue="new" id="new_billingaccount"/>
<apex:selectOption itemEscaped="false" itemLabel="Existing billing account" itemValue="existing" itemDisabled="{!billingAccountList.size == 0}" id="existing_billingaccount"></apex:selectOption>
</apex:selectRadio>
<apex:outputPanel id="accListRadio">
<apex:selectRadio layout="pageDirection" value="{!selectedAccount}" style="position:relative;left:5%" rendered="{!selectedAccountType == 'existing' && billingAccountList.size > 0 }">
<apex:actionSupport event="onclick" action="{!onSelectAccount}" reRender="subscriptionSection, pageErrors"/>
<apex:selectOptions value="{!billingAccountList}" ></apex:selectOptions>
</apex:selectRadio>
</apex:outputPanel>
</apex:pageBlockSection>
<apex:pageBlockSection columns="1" id="subscriptionSection">
<apex:outputLabel value="Create quote for:" style="font-weight:bold"></apex:outputLabel>
<apex:selectRadio layout="pageDirection" id="subTypeRadio" value="{!selectedSubscriptionType}" >
<apex:actionSupport event="onclick" action="{!onSelectSubscriptionType}" reRender="existingSubscriptionOptions, pageErrors"/>
<apex:selectOption itemEscaped="false" itemLabel="New subscription for this account" itemValue="new"> </apex:selectOption>
<apex:selectOption itemEscaped="false" itemLabel="Existing subscription" itemValue="existing" itemDisabled="{!subscriptionList.size == 0}" rendered="{!selectedAccountType == 'existing'}"></apex:selectOption>
</apex:selectRadio>
<apex:outputPanel id="existingSubscriptionOptions">
<apex:selectList value="{!selectedSubscription}" style="position:relative;left:3%;background:#fbfbd7" size="1" rendered="{!selectedSubscriptionType == 'existing' && subscriptionList.size > 0}">
<apex:selectOptions value="{!subscriptionList}"></apex:selectOptions>
</apex:selectList>
<apex:outputPanel style="position:relative;left:5%" rendered="{!selectedSubscriptionType == 'existing' && subscriptionList.size > 0}">
<apex:selectRadio style="position:relative;left:5%" layout="pageDirection" value="{!selectedAmendmentType}">
<apex:selectOption itemescaped="false" itemLabel="Amend this subscription" itemValue="amend"></apex:selectOption>
<apex:selectOption itemescaped="false" itemLabel="Renew this subscription" itemValue="renew" ></apex:selectOption>
</apex:selectRadio>
</apex:outputPanel>
</apex:outputPanel>
</apex:pageBlockSection>
<apex:pageBlockButtons location="bottom">
<apex:commandButton value="Continue" action="{!goNewQuote}"/>
<apex:commandButton value="Cancel" action="{!cancel}"/>
</apex:pageBlockButtons>
</apex:pageBlock>
</apex:form>
</apex:page>
====================================================================
PrepareNewQuoteController.cls
public with sharing class PrepareNewQuoteController{
private Zuora.zApi api = new Zuora.zApi();
private final Opportunity opp;
private final String CRMId;
private final Map <String,List<SelectOption>> cachedSubOptions = new Map <String,List<SelectOption>>();
public Boolean initFailed {get; private set;}
public String selectedAccountType {get;set;}
public String selectedAccount {get;set;}
public String selectedSubscription {get;set;}
public String selectedSubscriptionType {get;set;}
public String selectedAmendmentType {get;set;}
public List<SelectOption> billingAccountList {get;set;}
public List<SelectOption> subscriptionList {get;set;}
public PrepareNewQuoteController(ApexPages.StandardController controller) {
this.initFailed = true;
final String oppId = controller.getId();
if (null == oppId || '' == oppId) {
appendErrorMessage('Need to specify the id of opportunity to create a quote.');
return;
}
final List<Opportunity> oppList = [SELECT Id, Account.Id FROM Opportunity WHERE Id = :oppId limit 1];
if (oppList.size() != 1) {
appendErrorMessage('Invalid opportunity specified to create a quote.');
return;
}
this.opp = oppList[0];
this.CRMId = this.opp.Account.Id;
try {
api.zlogin();
} catch (Zuora.zAPIException e) {
appendErrorMessage(e.getMessage());
return;
}
this.initFailed = false;
}
public PageReference onload() {
try {
this.loadBillingAccountList();
} catch (Zuora.zAPIException e) {
appendErrorMessage(e.getMessage());
return null;
}
return null;
}
public PageReference onSelectAccount() {
try {
this.loadSubscriptionList();
} catch (Zuora.zAPIException e) {
appendErrorMessage(e.getMessage());
return null;
}
return null;
}
public PageReference goNewQuote() {
PageReference newQuotePage = Page.NewQuote;
String quoteType = 'New';
if ('amend' == selectedAmendmentType ) {
quoteType = 'Amend';
} else if ('renew' == selectedAmendmentType) {
quoteType = 'Renew';
}
newQuotePage.getParameters().put('quoteType', quoteType);
newQuotePage.getParameters().put('billingaccountid', this.selectedAccount);
newQuotePage.getParameters().put('existsubscriptionid', this.selectedSubscription);
newQuotePage.getParameters().put('oppid', String.valueOf(this.opp.Id).substring(0,15));
newQuotePage.setRedirect(true);
return newQuotePage;
}
public PageReference onSelectAccountType() {
if ('new' == this.selectedAccountType) {
this.selectedSubscriptionType = 'new';
} else {
try {
this.loadBillingAccountList();
} catch (Zuora.zAPIException e) {
appendErrorMessage(e.getMessage());
return null;
}
this.selectDefaultAccount();
}
return null;
}
private void selectDefaultAccount() {
if (this.billingAccountList != null && this.billingAccountList.size() > 0) {
this.selectedAccount = this.billingAccountList[0].getValue();
}
this.onSelectAccount();
}
public PageReference onSelectSubscriptionType() {
if ('existing' == this.selectedSubscriptionType) {
try {
this.loadSubscriptionList();
} catch (Zuora.zAPIException e) {
appendErrorMessage(e.getMessage());
return null;
}
this.selectDefaultSubscription();
}
return null;
}
private void selectDefaultSubscription() {
if (this.subscriptionList.size() > 0) {
this.selectedAmendmentType = 'amend';
this.selectedSubscription = this.subscriptionList[0].getValue();
}
}
private void loadBillingAccountList() {
if (this.CRMId == null) return;
//already queried from Zuora, no need to query again
if (this.billingAccountList != null)
return;
else{
//query from Zuora and build the billing account picklist
this.billingAccountList = new List<SelectOption> ();
String acczoql = 'SELECT AccountNumber, Name FROM Account WHERE Status = \'Active\' AND CrmId LIKE \'' + this.CRMId.substring(0, 15) + '%\'';
List <Zuora.zObject> acclist;
try {
acclist = api.zquery(acczoql);
} catch (Zuora.zAPIException e) {
throw e;
}
for(Zuora.zObject acc: acclist) {
String accvalue = (String)acc.getValue('Id');
String acclabel = acc.getValue('Name') + ', Acct#:' + acc.getValue('AccountNumber');
SelectOption accso = new SelectOption (accvalue, acclabel);
this.billingAccountList.add(accso);
}
}
}
//query the subscription from zuora and build the picklist
private void loadSubscriptionList() {
this.subscriptionList = new List<SelectOption>();
if (this.selectedAccount == null) return;
List<SelectOption> suboptionlist = this.cachedSubOptions.get(this.selectedAccount);
if (suboptionlist != null) this.subscriptionList = suboptionlist;
else{
suboptionlist = new List<SelectOption> ();
String subzoql = 'SELECT Id, Name, ContractEffectiveDate, TermType, Status FROM Subscription WHERE TermType= \'TERMED\' AND Status = \'Active\' AND AccountId = \'' + this.selectedAccount + '\'';
List<Zuora.zObject> subscriptionList;
try {
subscriptionList = api.zquery(subzoql);
} catch (Zuora.zAPIException e) {
throw e;
}
for(Zuora.zObject sub : subscriptionList) {
String subvalue = (String)sub.getValue('Id');
DateTime cedatetime = (DateTime)sub.getValue('ContractEffectiveDate');
String sublabel = (String)sub.getValue('Name') + ', Status: ' + (String)sub.getValue('Status') + ', Contract Effective Date: ' + cedatetime.date().format();
SelectOption subso = new SelectOption (subvalue,sublabel);
suboptionlist.add(subso);
}
if (suboptionlist.size() > 0){
this.cachedSubOptions.put(this.selectedAccount, suboptionlist);
this.subscriptionList = suboptionlist;
}
}
}
static private void appendErrorMessage(String message) {
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, message));
}
}
Considerations
-
Order Builder code should be used to get the customer account information from Z-Billing. See Order Builder for more information.
-
The login information should be properly put into the Order Builder configuration and the Z-Billing connection should be configured.
-
The parameter name can be different from the one that is specified in the sample page and controller, but the values must be the same.