Skip to main content

Create Custom Quote Wizard Pages

Zuora

Create Custom Quote Wizard Pages

Overview

Developers can create custom quote wizard pages that an administrator can add when configuring a quote wizard. For example, suppose you want to add a custom page that displays a subscription agreement as the last step in the quote creation process. Built on Visualforce framework, Zuora Quotes provides the logic and supporting resources to assist in the development of custom pages for quote wizards.

This topic identifies the required resources, describes the logic, and provides sample code to help you build a custom page that integrates with the quote wizard.

This topic assumes that the developer is experienced with the Visualforce environment.

Custom Quote Wizard Resources

Zuora Quotes provides the following resources: 

  • QuoteWizardManager.cls: An Apex controller class that provides global navigation methods and easy access to Quote Wizard metadata. See QuoteWizardManager class for more information on these methods.
  • BaseQuoteWizardController.cls: A virtual Apex controller class that handles the global navigation while providing virtual methods that can be overridden  when it is necessary to insert custom business logic before navigating from the current page.  Use this class to simplify calls to the QuoteWizardManager class navigation methods. It is not required for developing custom quote wizard pages. See BaseQuoteWizardController Class for more information on these virtual methods.
  • QuoteWizardTemplate.page: A Visualforce page that displays the content of a custom page along with the Progress Bar component and pre-built button bar. Use this template for use the out-of-the-box navigation and button bard control. This option requires less integration effort.
  • QuoteWizardTemplateNoForm.page: A Visualforce page that displays the content of a custom page without the <apex:form> tag or pre-built button bar. Use this template if you want to build and implement your own button bar that gives you more control over navigation. This option requires more integration effort.

About the Quote Standard Controller

A Visualforce page requires the zqu__Quote__c standard controller to integrate with the configurable quote wizard. This logic is built into the quote wizard templates. 

To use the zqu__Quote__c standard controller, indicate standardController="zqu__Quote__c" in the <apex: page> tag at the top of the Visualforce page, and pass an ApexPages.StandardController object as a constructor parameter for the page's controller extensions.

For example, when creating a page called MyCustomPage with a controller called MyCustomPageController, specify <apex: page standardController="zqu__Quote__c" extensions="MyCustomPageController" > in the page tag in the Visualforce markup, and specify a constructor with the following signature in the page's controller:

public MyCustomPageController(ApexPages.StandardController QuoteStandardController)

Refer to Salesforce documentation for more information on standard controllers.

Quote Wizard Template with Pre-built Navigation

Template: QuoteWizardTemplate.page

This template includes the following JavaScript functions and CSS classes to further customize wizard pages:

JavaScript functions

By default, the pre-built button bar calls the global navigation methods without updating any database objects based on information entered by the user.

To insert custom code before these navigation methods are called, implement the JavaScript methods beforeNavigateNext() and beforeNavigateBack(). Apex methods can be exposed as JavaScript using actionFunctions or JavaScript Remoting.

CSS classes

By default, the pre-built button bar is styled by the standard Salesforce.com style sheets. To further customize the look and feel of the button bar, you can override the quoteWizardButtonBar style class.

Sample Code: Custom page with navigation

MyCustomPage1Controller.cls

This sample code creates the custom page that includes form tags and pre-built navigation.

global class MyCustomPageController extends zqu.BaseQuoteWizardController {
    //Page Constructor
    public MyCustomPageController(ApexPages.StandardController StandardController) {
        super(StandardController);//NOTE: This line is necessary
        thisQuote = (zqu__Quote__c)StandardController.getRecord();
    }
    //Custom logic to update quote (called before navigating to next page)
    global override Map<String, String> processNextAction() {
        //Update the quote in the database
        thisQuote.MyCustomField__c = 'Next Value';
        upsert thisQuote;
        //Add the Id of the updated quote to the URL parameters of the next page
        return new Map<String, String>{'Id' => thisQuote.Id};
    }
    //Custom logic to update quote (called before navigating to next page)
    global override Map<String, String> processBackAction() {
        //Update the quote in the database
        thisQuote.MyCustomField__c = 'Previous Value';
        upsert thisQuote;
        //Add the Id of the quote's opportunity to the url parameters of the previous page
        return new Map<String, String>{
            'Id' => thisQuote.Id,
            'oppId' => thisQuote.zqu__Opportunity__c
        };
    }
    //Custom cancel action to redirect to the account of the quote's associated opportunity
    global override String processCancelAction() {
        zqu__Quote__c quote = [SELECT zqu__Opportunity__r.AccountId FROM zqu__Quote__c WHERE Id = :quoteId LIMIT 1];
        return '/' + quote.zqu__Opportunity__r.AccountId;
    }
}

Sample Code: Custom page using QuoteWizardTemplate

MyCustomPage1.page

This sample code uses the QuoteWizardTemplate.page template to build custom content with logic for the progress bar and button bar.

<apex:page StandardController="zqu__Quote__c" extensions="MyCustomPageController" >
  <!-- Override the quoteWizardButtonBar style class to center the button bar -->
  <style>
    .quoteWizardButtonBar {
      text-align: center;
    }
  </style>
  <!-- QuoteWizardTemplate -->
  <apex:composition template="zqu__QuoteWizardTemplate" >
    <!-- Define the page body, including form and button bar -->
    <apex:define name="PageBody" >
      <!-- Action functions to call navigation methods of BaseQuoteWizardController-->
      <apex:actionFunction action="{!navigateNext}" name="onNavigateNext" />
      <apex:actionFunction action="{!navigateBack}" name="onNavigateBack" />
      <apex:actionFunction action="{!cancel}" name="onCancel" immediate="true" />
      <!-- Make sure quote standard controller has access to opportunity Id -->
      <apex:outputField value="{!zqu__Quote__c.zqu__Opportunity__c}" rendered="false" />
    </apex:define>
  </apex:composition>
</apex:page>

Quote Wizard Template Without Pre-built Navigation

Template: QuoteWizardTemplateNoForm.page

Sample code: Custom page without navigation

MyCustomPage2Controller.cls 

This sample code creates the custom page without form tags and pre-built navigation.

public class MyCustomPageController {
    
    //Quote object
    zqu__Quote__c thisQuote {get; set;}
    //Page Constructor
    public MyCustomPageController(ApexPages.StandardController StandardController) {
        thisQuote = (zqu__Quote__c)StandardController.getRecord();
    }
    
    //Global method to retrieve back button text
    public String BackButtonText {
        get {
            if(BackButtonText == null) BackButtonText = zqu.QuoteWizardManager.getBackButtonText();
            return BackButtonText;
        }
        private set;
    }

    //Global method to retrieve next button text
    public String NextButtonText {
        get {
            if(NextButtonText == null) NextButtonText = zqu.QuoteWizardManager.getNextButtonText();
            return NextButtonText;
        }
        private set;
    }

    //Navigation methods
    public PageReference navigateNext() {
        upsert thisQuote;
        Map<String, String> customUrlParameters = new Map<String, String>{'Id' => thisQuote.Id};
        return zqu.QuoteWizardManager.navigateNext(customUrlParameters);
    }

    public PageReference navigateBack() {
        upsert thisQuote;
        Map<String, String> customUrlParameters = new Map<String, String>{'Id' => thisQuote.Id,
                                                                     'oppId' => thisQuote.zqu__Opportunity__c};
        return zqu.QuoteWizardManager.navigateBack(customUrlParameters);
    }

    //If the user clicks cancel, use global method to delete all quote information and navigate back to the Opportunity page
    public PageReference cancel() {
        return zqu.QuoteWizardManager.cancel('/' + thisQuote.zqu__Opportunity__c);
    }

}

Sample Code: Custom page using QuoteWizardTemplateNoForm

MyCustomPage2.page

This sample code uses the QuoteWizardTemplateNoForm.page template for building custom content after the progress bar.

<apex:page StandardController="zqu__Quote__c" extensions="MyCustomPageController" >

  <!-- QuoteWizardTemplate -->
  <apex:composition template="zqu__QuoteWizardTemplateNoForm" >

    <!-- Define the page body, including form and button bar -->
    <apex:define name="PageBody" >
      <apex:form>

        <apex:PageBlock>

          <apex:pageBlockSection>
            <!-- Custom page content here -->
          </apex:pageBlockSection>

          <!-- Custom button bar -->
          <apex:pageBlockButtons>
            <apex:commandButton action="{!navigateBack}" value="{!BackButtonText}" />
            <apex:commandButton action="{!navigateNext}" value="{!NextButtonText}" />
            <apex:commandButton action="{!cancel}" value="Cancel" />
          </apex:pageBlockButtons>

        </apex:PageBlock>
      </apex:form>
    </apex:define>
  </apex:composition>
</apex:page>