A Poor Man’s Product Configurator

I was recently contacted by one of my blog readers to help him with a project. It sounded like an interesting challenge, so I agreed to help him with a little guidance and also post an overview of what we did so others could learn as well.

The business problem: let’s say your company makes custom widgets. A part of the sales process is creating a quote request. You don’t want your sales people to have a generic quote request form to fill out. Instead, you want to only show them the options based on the type of  product for which they are creating the quote request.

There are a few ways to accomplish this. I originally proposed a fairly complicated, but extensible model using related lists so you could configure an unlimited number of options. It turned out that the product model was a bit simpler and we could do it with just the product object and some Visualforce and a controller extension. My example here also uses field sets to make it easily configurable once it is in production.

To set up for this, I created a custom product object and a quote request object. On the custom product, I created a picklist field with options such as Group1, Group2, etc. On the quote request object, I created all the options as fields and then created field sets to group them together for display on the quote request entry page. The benefit of using the field set is that if I decide I need to add a new option to a product group, I can do it without having to add code. I just add the field to the relevant field set.

Here’s the Visualforce page. You can see the repeaters with the field sets.

<apex:page standardController="QuoteRequest__c" extensions="QuoteRequestExtension">
  <apex:form >
    <apex:pageBlock >
      <apex:pageMessages />
      <apex:pageBlockButtons >
        <apex:commandButton value="Save" action="{!save}"/>
        <apex:commandButton value="Cancel" action="{!Cancel}"/>
      <apex:pageBlockSection title="Custom Product" collapsible="false">
        <apex:outputField value="{!QuoteRequest__c.CustomProduct__c}"/>
      <apex:pageBlockSection columns="1" title="Options" collapsible="false">
        <apex:repeat value="{!$ObjectType.QuoteRequest__c.FieldSets.Group1}" var="f" > 
            <apex:inputfield value="{!QuoteRequest__c[f]}" rendered="{!CustomProduct.ConfigGroup__c == 'Group1'}"/>
        <apex:repeat value="{!$ObjectType.QuoteRequest__c.FieldSets.Group2}" var="f" > 
            <apex:inputfield value="{!QuoteRequest__c[f]}" rendered="{!CustomProduct.ConfigGroup__c == 'Group2'}"/>

And here’s the Apex controller extension. It takes the product ID passed as a parameter to the page and queries the configuration group on the custom product to display on the Visualforce page.

public with sharing class QuoteRequestExtension {

    public CustomProduct__c CustomProduct {get; set;}
    private final QuoteRequest__c qr;

    public QuoteRequestExtension(ApexPages.StandardController controller) {
        this.qr = (QuoteRequest__c)controller.getRecord();
        try {
            CustomProduct = [select id, ConfigGroup__c from CustomProduct__c where id = :ApexPages.currentPage().getParameters().get('product')];
        } catch(Exception e) {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Error Getting Product Info'));
        if (CustomProduct != null)
            this.qr.CustomProduct__c = CustomProduct.Id;

The last ingredient to this is to add a lookup field on the Opportunity object. We can then add a custom button on to the Opportunity that takes the user to the quote request page and passes in the custom product ID from the opportunity.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s