Visualforce Wizard: Contract Standard Object

In this example, I am using the Contract standard object and in this enterprise edition org we have the “Contract” standard object renamed as “Lease”. Therefore, as you review the code samples below, you have to use “Contract” and “Lease” interchangeably.

The business case here is to provide a visualforce wizard to help speed up data entry and also make the data entry more “bite size”. The Lease record, in this case, has near 80 fields to gather user input and spreading that data entry out over 5 steps in the wizard makes each step a little more manageable.

In total, there are:

  1. 5 visualforce pages
  2. 1 apex class
  3. 1 apex test class
  4. 1 static resource – a javascript file

Here is a short video demo of what the end user sees:
Unable to display content. Adobe Flash is required.

NOTE: For background reference on what I’m doing on step 3 and 4 (where I allow the end user to enter a custom expression), please refer to this post for more details on how I’m using the javascript on the page.

Here is the custom controller:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
public class LeaseWizardController {
 
    // This variable maintains the state of the wizard. 
    // When users enter data into the wizard, their input is stored in this object. 
    Contract lease;
 
    // Properties of this class
    // These variable values are used to pre-populate fields throughout the wizard with data from an associated Opportunity
    public String opptyID {get;set;}
    public String opptyOwnerID {get;set;}
    public String acctID {get;set;}
    public String propID {get;set;}
    public String suiteID {get;set;}
    public Decimal opptyTerm {get;set;}
 
    // Create a new List<> that will hold all Suites for this property
    public List<Suite__c> allSuites = new List<Suite__c>();    
    public List<SelectOption> options = new List<SelectOption>();
    public String[] selectedSuiteIds = new String[]{};
    public String[] getselectedSuiteIds() {
        return selectedSuiteIds;
    }
 
    public void setSelectedSuiteIds(String[] selectedSuiteIds) {
        this.selectedSuiteIds = selectedSuiteIds;
    }    
 
 
    // Constructor with no args
    public LeaseWizardController(){
        this.lease = new Contract();
        if ( ApexPages.currentPage().getParameters().get('opptyID') != null ) {
            OpptyValues();
        }
    }
 
    // Constructor with 1 arg
    public LeaseWizardController(ApexPages.StandardController stdController) {
        this.lease = (Contract)stdController.getRecord();
        if ( ApexPages.currentPage().getParameters().get('opptyID') != null ) {
            OpptyValues();
        }
    }
 
    // Constructor for test methods
    public LeaseWizardController(Contract testLease){
        this.lease = testLease;
        if ( ApexPages.currentPage().getParameters().get('opptyID') != null ) {
            OpptyValues();
        }
    }   
 
    // This method returns a Contract variable. If this is the first time the method is called, it creates an empty record for the variable.    
    public Contract getContract() {
        if(lease == null) lease = new Contract(); 
        return lease;
    }
 
    // This methods consumes the opptyID URL parmeter and then sets the public properties equal to the values from the Opportunity
    public void OpptyValues() {
        // Keep the Oppty ID in a variable
        opptyID = ApexPages.currentPage().getParameters().get('opptyID');
        // Use the Oppty ID variable to query the database for all the Oppty field values we need later
        // See "Using SOQL Queries That Return One Record" in the Apex Code Developer Guide for this practice
        // http://www.salesforce.com/us/developer/docs/apexcode/index.htm
        List<Opportunity> o = [Select o.Transaction_Type__c, o.Total_K_W__c, o.Term__c, o.Tenant_Broker_Contact__c, o.Tenant_Broker_Account__c, o.Rentable_sf__c, o.Raised_Floor_sf__c, o.Property__c, o.Product_Type__c, o.OwnerId, o.Landlord_Broker_Contact__c, o.Landlord_Broker_Account__c, o.Id, o.Commencement_Date__c, o.CloseDate, o.AccountId From Opportunity o Where o.Id = :opptyID];
        // Set the public properties of this controller equal to a field value from the associated Oppty
        // Begin with all the relationships to other objects: Account, Contact, Opportunity, Property, Suite and Users already selected on the Opportunity 
                lease.Opportunity__c = opptyID;
                acctID = o[0].AccountId;
                lease.AccountId = acctID;
                propID = o[0].Property__c;
                lease.Property__c = propID;
                opptyOwnerID = o[0].OwnerId;
                lease.Sales_Director__c = opptyOwnerID;
                lease.VP_Sales__c = [Select u.ManagerId, u.Id From User u Where u.Id = :opptyOwnerID].ManagerId;
                lease.Landlord_Broker_Account__c = o[0].Landlord_Broker_Account__c;
                lease.Landlord_Broker__c = o[0].Landlord_Broker_Contact__c;
                lease.Tenant_Broker_Account__c = o[0].Tenant_Broker_Account__c;
                lease.Tenant_Broker__c = o[0].Tenant_Broker_Contact__c;                 
        // Now, prepopulate as many fields as possible from data on the associated Opportunity
                lease.Rent_Start__c = o[0].Commencement_Date__c;
                lease.Transaction_Type__c = o[0].Transaction_Type__c;
                lease.Unit_Type__c = o[0].Product_Type__c;
                lease.NRSF__c = o[0].Rentable_sf__c;
                lease.kW_per_Lease__c = o[0].Total_K_W__c;
                lease.Raised_sf__c = o[0].Raised_Floor_sf__c;
                opptyTerm = o[0].Term__c;
                lease.ContractTerm = opptyTerm.intValue();
                lease.Contractual_Term__c = opptyTerm;
                lease.Term__c = opptyTerm;
                lease.StartDate = o[0].CloseDate;
    }
 
    // These methods control navigation through the wizard. Each returns a PageReference for one of the vf pages 
    // in the wizard. Note that the redirect attribute does not need to be set on the PageReference because the URL does not need to change 
    // when users move from page to page.    
 
    public PageReference step1() {
        return Page.LeaseStep1;
    }
 
    public PageReference step2() {
        return Page.LeaseStep2;
    }
 
    public PageReference step3() {
        return Page.LeaseStep3;
    }   
 
    public PageReference step4() {
        return Page.LeaseStep4;
    }  
 
    // This query will return all child Suite records of the user-selected Property
    // The user entering the new Lease will choose from these records to make the association between the Lease and the Property / Suite(s)
    public List<SelectOption> getSuiteRecords() {
        // Query the db for all Suites related to the user-selected property record
        allSuites = [Select s.Id, s.Name, s.Property__c, s.Property__r.Name, s.Total_Raised_Floor_sqft__c, s.Total_Rentable_sqft__c, s.RecordType.Name From Suite__c s Where (s.Property__c = :propID) Order By s.Name];
        // Create an integer variable that we can increment in our for loop
        Integer i = 0;
        // Iterate over all the related Suite records and add them as SelectOptions to our public List<> variable named 'options'
        if(allSuites != null) {
            for(Suite__c s : allSuites) {
                options.add(new SelectOption(allSuites[i].Id, allSuites[i].Name));
                i++;
            }
        }
        return options;
    }
 
    public void clearOptions(){
        // If the user changes the property record, we need to empty the list if there are any elements in it
        allSuites.clear();
        options.clear(); 
        // Empty the propID variable
        propID = null;
        // Capture the ID of the new user-selected property record
        propID = lease.Property__c;                
    }   
 
    // This method cancels the wizard, and returns the user to the Lease tab
    public PageReference cancel() {
        return new PageReference('/800/o');
    }
 
    public PageReference save() {
        // Save the new lease to the database so that all validation rules and formula fields are evaluated.
        if(lease != null) {
            lease.Status = 'Draft';
            upsert lease;
        }
        // Create a new LeaseSuiteAssociation for each Suite records chosen by the user
        if(selectedSuiteIds != null && lease != null) {
            for (String s : selectedSuiteIds) {
                LeasedSuite__c leasedSuite = new LeasedSuite__c();
                leasedSuite.Lease__c = lease.Id;
                leasedSuite.Suite__c = s;
                insert leasedSuite;                
            }
        }
        // After the new lease is saved to the database, send the user to last step in the wizard and provide the ID of the new lease record.
        if (lease != null){
                String lid = lease.Id;
                return new PageReference('/' + lid);
                // Change the PageReference above to '/apex/LeaseStep5?id=' + lid if you want the wizard to end on the LeaseStep5 vf page
        }else{
                return new PageReference('/800/o');
        }
    }   
}

Here is the apex test class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
@IsTest
private class TestLeaseWizard{
 
    private final Contract contract;
 
    public TestLeaseWizard(ApexPages.StandardController LeaseWizardController) {
        this.contract = (Contract)LeaseWizardController.getRecord();
    }
 
    static testmethod void testOpptyValues(){
        // Create an Account, Property, Suite and Opportunity record to use as test data.
        // Add all necessary field values to pass validation rules and field requirements for each object.
        Account acct = new Account(name='foobar');
            acct.Vertical__c = 'Internet Enterprise';
            insert acct;
        Property__c prop = new Property__c();
            prop.name = 'foo';
            insert prop;
        Suite__c suite = new Suite__c();
            suite.name = 'bar';
            suite.Property__c = prop.id;
            suite.RecordTypeId = '012800000006Kgh';
            insert suite;
        Opportunity opp = new Opportunity();
            opp.Name = 'TEST - TEST - TEST';
            opp.StageName = 'Initial Inquiry';
            opp.Property__c = prop.id;
            opp.Suite_Lookup__c = suite.id;
            opp.AccountId = acct.id;
            opp.RecordTypeId = '012300000004r5k';
            opp.Product_Type__c = 'Turn-Key Datacenter';
            opp.Lease_Type__c = 'NNN';
            opp.Lease_Category__c = 'Technical Space';
            opp.Transaction_Type__c = 'New';
            opp.LeadSource = 'Word of Mouth';
            date d = Date.today();
            opp.CloseDate = d + 100;
            opp.Commencement_Date__c = d + 200;
            opp.Term__c = 120;
            opp.Total_K_W__c = 1125;
            opp.Raised_Floor_sf__c = 5000;
            opp.Month_1_Rent__c = 123.45;
            opp.Annual_Increase__c = '3';
            opp.Avg_Monthly_Rent_per_Square_Foot__c = 123.45;
            opp.Starting_kW__c = 123.45;
            opp.Broker_Representation__c = 'Yes'; 
            insert opp;
        PageReference pageRef = Page.LeaseStep1;
        Test.setCurrentPage(pageRef);         
        test.startTest();
        // Set the 'opptyID' URL parameter equal to the id value of our test Opportunity
        ApexPages.currentPage().getParameters().put('opptyID',opp.Id);
        // Instantiate the controller for the Lease Wizard
        LeaseWizardController controller = new LeaseWizardController();
        if (opp.Id != null){
            controller.OpptyValues();
            System.assertEquals(controller.opptyID, opp.Id);
        }
        test.stopTest();
    }
 
    static testmethod void testStep1(){
        PageReference pageRef = Page.LeaseStep2;
        Test.setCurrentPage(pageRef);
        Account s = new Account(name='test');
        insert s;         
        date d = Date.today();        
        Contract contTest = new Contract();
        contTest.Status = 'Draft';
        contTest.StartDate = d + 7;
        contTest.AccountId = s.Id;
        contTest.NRSF__c = 5000;
        contTest.Raised_sf__c = 4500;
        contTest.kW_per_Lease__c = 1125;        
        insert contTest;        
        LeaseWizardController controller = new LeaseWizardController();
        //The .getURL will return the page url the Save() method returns.
        String nextPage = controller.step1().getUrl();
        //Check that the save() method returns the proper URL.
        System.assertEquals('/apex/leasestep1', nextPage);     
    }     
 
    static testmethod void testStep2(){
        PageReference pageRef = Page.LeaseStep1;
        Test.setCurrentPage(pageRef);
        Account s = new Account(name='test');
        insert s;        
        date d = Date.today();        
        Contract contTest = new Contract();
        contTest.Status = 'Draft';
        contTest.StartDate = d + 7;
        contTest.AccountId = s.Id;
        contTest.NRSF__c = 5000;
        contTest.Raised_sf__c = 4500;
        contTest.kW_per_Lease__c = 1125;        
        insert contTest;        
        LeaseWizardController controller = new LeaseWizardController();
        //The .getURL will return the page url the Save() method returns.
        String nextPage = controller.step2().getUrl();
        //Check that the save() method returns the proper URL.
        System.assertEquals('/apex/leasestep2', nextPage);            
    }
 
    static testmethod void testStep3(){
        PageReference pageRef = Page.LeaseStep2;
        Test.setCurrentPage(pageRef);
        Account s = new Account(name='test');
        insert s;
        date d = Date.today();        
        Contract contTest = new Contract();
        contTest.Status = 'Draft';
        contTest.StartDate = d + 7;
        contTest.AccountId = s.Id;
        contTest.NRSF__c = 5000;
        contTest.Raised_sf__c = 4500;
        contTest.kW_per_Lease__c = 1125;        
        insert contTest;        
        LeaseWizardController controller = new LeaseWizardController();
        //The .getURL will return the page url the Save() method returns.
        String nextPage = controller.step3().getUrl();
        //Check that the save() method returns the proper URL.
        System.assertEquals('/apex/leasestep3', nextPage);     
    }
 
    static testmethod void testStep4(){
        PageReference pageRef = Page.LeaseStep3;
        Test.setCurrentPage(pageRef);
        Account s = new Account(name='test');
        insert s;         
        date d = Date.today();        
        Contract contTest = new Contract();
        contTest.Status = 'Draft';
        contTest.StartDate = d + 7;
        contTest.AccountId = s.Id;
        contTest.NRSF__c = 5000;
        contTest.Raised_sf__c = 4500;
        contTest.kW_per_Lease__c = 1125;        
        insert contTest;        
        LeaseWizardController controller = new LeaseWizardController();
        //The .getURL will return the page url this method returns.
        String nextPage = controller.step4().getUrl();
        //Check that the save() method returns the proper URL.
        System.assertEquals('/apex/leasestep4', nextPage);     
    }
 
    static testmethod void testSave(){
        PageReference pageRef = Page.LeaseStep4;
        Test.setCurrentPage(pageRef);
        Account s = new Account(name='test');
        insert s;         
        date d = Date.today();        
        Contract contTest = new Contract();
        contTest.Status = 'Draft';
        contTest.StartDate = d + 7;
        contTest.AccountId = s.Id;
        contTest.NRSF__c = 5000;
        contTest.Raised_sf__c = 4500;
        contTest.kW_per_Lease__c = 1125;        
        insert contTest;        
        if (contTest != null){
            LeaseWizardController controller = new LeaseWizardController(contTest);
            //The .getURL will return the page url this method returns.
            String nextPage = controller.save().getUrl();
            // Set what URL we expect to be returned by the save() method
            String expected = '/' + contTest.Id;
            //Check that the save() method returns the proper URL.
            System.assertEquals(expected, nextPage);
        }     
    }    
 
    static testmethod void testCancel(){
        PageReference pageRef = Page.LeaseStep1;
        Test.setCurrentPage(pageRef);
        LeaseWizardController controller = new LeaseWizardController();        
        //The .getURL will return the page url the cancel() method returns.
        String nextPage = controller.cancel().getUrl();
        //Check that the save() method returns the proper URL.
        System.assertEquals('/800/o', nextPage);     
    }
 
    static testmethod void testConstructor(){
        PageReference pageRef = Page.LeaseStep3;
        Test.setCurrentPage(pageRef);
        // Create dummy data
        Account acct = new Account(name='foobar');
            acct.Vertical__c = 'Internet Enterprise';
            insert acct;
        Property__c prop = new Property__c();
            prop.name = 'foo';
            insert prop;
        Suite__c suite = new Suite__c();
            suite.name = 'bar';
            suite.Property__c = prop.id;
            suite.RecordTypeId = '012800000006Kgh';
            insert suite;        
        Opportunity opp = new Opportunity();
            opp.Name = 'TEST - TEST - TEST';
            opp.StageName = 'Initial Inquiry';
            opp.Property__c = prop.id;
            opp.Suite_Lookup__c = suite.id;
            opp.AccountId = acct.id;
            opp.RecordTypeId = '012300000004r5k';
            opp.Product_Type__c = 'Turn-Key Datacenter';
            opp.Lease_Type__c = 'NNN';
            opp.Lease_Category__c = 'Technical Space';
            opp.Transaction_Type__c = 'New';
            opp.LeadSource = 'Word of Mouth';
            date d = Date.today();
            opp.CloseDate = d + 100;
            opp.Commencement_Date__c = d + 200;
            opp.Term__c = 120;
            opp.Total_K_W__c = 1125;
            opp.Raised_Floor_sf__c = 5000;
            opp.Month_1_Rent__c = 123.45;
            opp.Annual_Increase__c = '3';
            opp.Avg_Monthly_Rent_per_Square_Foot__c = 123.45;
            opp.Starting_kW__c = 123.45;
            opp.Broker_Representation__c = 'Yes'; 
            insert opp;        
        // Set the 'opptyID' URL parameter equal to the id value of our test Opportunity
        ApexPages.currentPage().getParameters().put('opptyID',opp.Id);        
        Account s = new Account(name='test');
        insert s;         
        Contract contTest = new Contract();
        contTest.Status = 'Draft';
        contTest.StartDate = d + 7;
        contTest.AccountId = s.Id;
        contTest.NRSF__c = 5000;
        contTest.Raised_sf__c = 4500;
        contTest.kW_per_Lease__c = 1125;
        insert contTest;        
        LeaseWizardController controller = new LeaseWizardController(contTest);
        System.assertNotEquals(null, controller);   
    }  
 
    static testmethod void testGetContract(){
        PageReference pageRef = Page.LeaseStep3;
        Test.setCurrentPage(pageRef);
        Account s = new Account(name='test');
        insert s;         
        date d = Date.today();        
        Contract contTest = new Contract();
        contTest.Status = 'Draft';
        contTest.StartDate = d + 7;
        contTest.AccountId = s.Id;
        contTest.NRSF__c = 5000;
        contTest.Raised_sf__c = 4500;
        contTest.kW_per_Lease__c = 1125;        
        insert contTest;        
        LeaseWizardController controller = new LeaseWizardController(contTest);
        System.assertNotEquals(null, controller.getContract());     
    }
 
    static testmethod void testGetSuiteRecords(){
        // Create dummy data
        Property__c prop = new Property__c();
            prop.name = 'foo';
            insert prop;
        // Create 3 Suite records we would expect returned from our query
        Suite__c suite1 = new Suite__c();
            suite1.name = 'bar';
            suite1.Property__c = prop.id;
            suite1.RecordTypeId = '012800000006Kgh';
            insert suite1;
        Suite__c suite2 = new Suite__c();
            suite2.name = 'bar';
            suite2.Property__c = prop.id;
            suite2.RecordTypeId = '012800000006Kgh';
            insert suite2;
        Suite__c suite3 = new Suite__c();
            suite3.name = 'bar';
            suite3.Property__c = prop.id;
            suite3.RecordTypeId = '012800000006Kgh';
            insert suite3;            
        PageReference pageRef = Page.LeaseStep1;
        Test.setCurrentPage(pageRef);         
        test.startTest();
        // Instantiate the controller for the Lease Wizard
        LeaseWizardController controller = new LeaseWizardController();
        controller.propID = prop.id;
        controller.getSuiteRecords();
        System.assertEquals(controller.allSuites.size(), 3);
        System.assertEquals(controller.options.size(), 3);
        test.stopTest();
    }         
}

Here is step 1 of the visualforce wizard:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<apex:page standardController="Contract" extensions="LeaseWizardController" tabStyle="Contract" sidebar="false" wizard="true">
<style>
.equalWidth{ width:200px; }
</style>
<apex:includeScript value="{!$Resource.LeaseWizardScript}"/>
  <apex:sectionHeader title="New Lease Wizard" subtitle="Step 1 of 5"/>
 
    <apex:form >
        <apex:pageBlock title="Enter the lease details" mode="edit">
                <div style="margin:5px; padding:5px;">
                <h1>Instructions</h1><br/><br/>
        In this wizard, you will create a new Lease record. Please note:
        <ol>
            <li>If you are on this page after having clicked the "Create New Lease" button on an Opportunity record, you will see various fields throughout this wizard pre-populated for you. You can change those values or leave them as is.</li>
            <li>Fields marked with a red highlight are required to continue.</li>
            <li>There is a small "?" icon next to each field. You can mouse over them for additional context to the fields intention or meaning.</li>
        </ol>
        </div>      
 
        <apex:pageBlockSection title="Customer Information" columns="1">
            <apex:inputField id="account" value="{!contract.AccountId}"/>
            <apex:inputField id="coNameOnLease" value="{!contract.Co_Name_on_Lease__c}"/>
            <apex:inputField id="industryCategory" value="{!contract.Industry_Category__c}"/>
        </apex:pageBlockSection>
 
        <apex:pageBlockSection title="Prior Lease (if renewal or re-lease)" columns="1">
            <apex:inputField id="renewalLease" value="{!contract.Prior_Lease__c}"/>            
        </apex:pageBlockSection>
 
        <apex:pageBlockSection title="Dates" columns="1">
            <apex:inputField id="signDate" value="{!contract.Sign_Date__c}"/>
            <apex:inputField id="startDate" value="{!contract.StartDate}"/>
            <apex:inputField id="contStartDate" value="{!contract.Contractual_Start_Date__c}"/>
            <apex:inputField id="rentStart" value="{!contract.Rent_Commencement__c}"/>            
            <apex:inputField id="contRentComm" value="{!contract.Contractual_Rent_Commencement__c}"/>
            <apex:inputField id="leaseEndDate" value="{!contract.Expiration_Date__c}"/>
            <apex:inputField id="original" value="{!contract.Original_Term_Expiration_Date__c}"/>            
        </apex:pageBlockSection> 
 
        <apex:pageBlockSection title="Categories" columns="1">
            <apex:inputField id="leaseCategory" value="{!contract.Lease_Category__c}" styleClass="equalWidth" />
            <apex:inputField id="transactionType" value="{!contract.Transaction_Type__c}" styleClass="equalWidth" />
            <apex:inputField id="unitType" value="{!contract.Unit_Type__c}" styleClass="equalWidth" />
        </apex:pageBlockSection>                 
 
        <apex:pageBlockSection title="Description" columns="1">
            <apex:inputField id="description" value="{!contract.description}" style="width:400px;"/>
            <apex:inputField id="comments" value="{!contract.Comments__c}" style="width:400px;"/>
        </apex:pageBlockSection>
 
        <apex:pageBlockButtons >
            <apex:commandButton action="{!step2}" value="Next"/>
            <apex:commandLink value="Cancel" action="{!cancel}" onclick="return confirmCancel()" immediate="true"/>            
        </apex:pageBlockButtons>        
 
      </apex:PageBlock>
    </apex:form>
</apex:page>

Here is step 2 of the visualforce wizard:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<apex:page standardController="Contract" extensions="LeaseWizardController" sidebar="false" wizard="true">
<apex:includeScript value="{!$Resource.LeaseWizardScript}"/>
  <apex:sectionHeader title="New Lease Wizard" subtitle="Step 2 of 5"/>
      <apex:form >
      <apex:pageBlock title="Enter the lease details" mode="edit">  
        <div style="margin:5px; padding:5px;">
        <h1>Instructions</h1><br/><br/>
        In this step, you will select the Property and Suite(s) associated with this Lease. You can either:
        <ol>
            <li>Select NO Suite(s)</li>
            <li>Select only ONE Suite</li>
            <li>Select MULTIPLE Suites</li>
        </ol>
        </div>
      <apex:pageBlockSection title="Property" columns="1">
        <apex:inputField value="{!contract.Property__c}">
            <apex:actionSupport event="onchange" action="{!clearOptions}" rerender="suiteTable" status="status" />
            <apex:actionStatus id="status" startText="Refreshing..." startStyle="font-weight:bold; font-size:14pt; color:red;" stopText="Make your selection below:" stopStyle="font-weight:bold; font-size:14pt; color:green;"></apex:actionStatus>                       
        </apex:inputField>
      </apex:pageBlockSection>      
 
      <apex:pageBlockSection id="suiterecords" title="Suite(s)" columns="1">
        This information entered below is input by the Region Analysts. Please alert the correct Region Analyst if the below information should be corrected or if a new Suite record is needed. If a new Suite record is needed, you can proceed with this wizard and add the Suite to this Lease later.
        <apex:selectCheckboxes value="{!selectedSuiteIds}" id="suiteTable" layout="pageDirection">
            <apex:selectOptions value="{!suiterecords}"/><br/>
        </apex:selectCheckboxes>        
      </apex:pageBlockSection>
 
        <apex:pageBlockButtons >
            <apex:commandButton action="{!step1}" value="Previous"/>
            <apex:commandButton action="{!step3}" value="Next"/>
            <apex:commandLink value="Cancel" action="{!cancel}" onclick="return confirmCancel()" immediate="true"/>
        </apex:pageBlockButtons>        
 
      </apex:PageBlock>
    </apex:form>
</apex:page>

Here is step 3 of the visualforce wizard:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<apex:page standardController="Contract" extensions="LeaseWizardController" sidebar="false" wizard="true">
<apex:includeScript value="{!$Resource.LeaseWizardScript}"/>
<apex:sectionHeader title="New Lease Wizard" subtitle="Step 3 of 5"/>
    <apex:form >
 
    <apex:pageBlock id="custCalcs">
 
        <apex:pageBlockButtons >
            <apex:commandButton action="{!step2}" value="Previous"/>
            <apex:commandButton action="{!step4}" value="Next" />
            <apex:commandLink value="Cancel" action="{!cancel}" onclick="return confirmCancel()" immediate="true"/>                           
        </apex:pageBlockButtons>       
        <div style="margin:5px; padding:5px;">
        <h1>Instructions</h1><br/><br/>
        In this step, you can enter all information regarding Square Feet, Power, Term, GAAP, Incremental GAAP, etc.
        </div>        
        <apex:pageBlockSection title="Square Feet and Power Commitments" columns="1">
            <apex:inputField id="nrsf" value="{!Contract.NRSF__c}"/>
            <apex:inputField id="raised" value="{!Contract.Raised_sf__c}"/>
            <apex:inputField id="kW" value="{!Contract.kW_per_Lease__c}"/>         
            <apex:inputField id="mtm" value="{!Contract.Month_to_Month__c}"/>
            <apex:inputField id="avgRentEsc" value="{!contract.Avg_Rent_Escalations__c}"/>
        </apex:pageBlockSection>        
 
        <apex:pageBlockSection title="Enter Custom Expressions Here" columns="1">
 
        <div style="margin:5px; padding:5px;">
        To use the custom expression fields below, follow these three steps: 
        <ol>
            <li>Enter the formula in the first field. Ex: (250000 * 12) / 12</li>
            <li>Click the "=" button</li>
            <li>The formula will evaluate and the value will be stored in the second field.</li>
        </ol>
        </div>
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Example:" />
                <apex:outputPanel >
                    <input value="(250000 * 120)/4" style="width:400px;" />
                    <input type="button" value=" = " />
                    <input value="7500000" />
                </apex:outputPanel>
            </apex:pageBlockSectionItem>
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Contractual Term" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Contractual_Term__c}" style="width:400px;" id="equation" onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
                    <apex:inputField value="{!Contract.Contractual_Term__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Term" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Term__c}" style="width:400px;" id="equation" onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
                    <apex:inputField value="{!Contract.Term__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>  
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Contractual Total Rent" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Contractual_Total_Rent__c}" style="width:400px;" id="equation" onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
                    <apex:inputField value="{!Contract.Contractual_Total_Rent__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>                                          
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Total Rent" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Total_Rent__c}" style="width:400px;" id="equation" onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
                    <apex:inputField value="{!Contract.Total_Rent__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem> 
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Contractual Incremental GAAP Ann Rent" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Contractual_Incremental_GAAP_Ann__c}" style="width:400px;" id="equation" onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
                    <apex:inputField value="{!Contract.Contractual_Incremental_GAAP_Ann_Revenue__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>              
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Incremental GAAP Ann Rent" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Incremental_GAAP_Ann_Rent__c}" style="width:400px;" id="equation" onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
                    <apex:inputField value="{!Contract.Incremental_GAAP_Annual_Revenue__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>  
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="TI/LW" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Total_TI_LW_IF__c}" style="width:400px;" id="equation" onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
                    <apex:inputField value="{!Contract.Total_TI_LW_IF__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>                  
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Renewing First Year’s Cash Rent" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_First_Years_Cash_Rent__c}" style="width:400px;" id="equation" onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
                    <apex:inputField value="{!Contract.Renewing_First_Year_s_Cash_Rent__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Renewal Expiring Last Year Cash Rent" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Renewal_Expiring_Last_Year__c}" style="width:400px;" id="equation" onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
                    <apex:inputField value="{!Contract.Expiring_Last_Year_s_Cash_Rent__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Prior Lease GAAP Annual Rent" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Prior_Lease_GAAP_Ann_Rent__c}" style="width:400px;" id="equation" onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
                    <apex:inputField value="{!Contract.Prior_Lease_GAAP_Ann_Rent__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>  
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Prior Lease Last Year's Cash Rent" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Prior_Lease_Last_Years_Cash_Rent__c}" style="width:400px;" id="equation" onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
                    <apex:inputField value="{!Contract.Prior_Lease_Last_Years_Cash_Rent__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>                                      
 
        </apex:pageBlockSection>            
 
    </apex:pageBlock>  
 
    </apex:form>
 
</apex:page>

Here is step 4 of the visualforce wizard:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<apex:page standardController="Contract" extensions="LeaseWizardController" sidebar="false" wizard="true">
<apex:includeScript value="{!$Resource.LeaseWizardScript}"/>
  <apex:sectionHeader title="New Lease Wizard" subtitle="Step 4 of 5"/>
    <apex:form >
      <apex:pageBlock title="Enter the lease details" mode="edit">
 
        <apex:pageBlockSection title="Commissions" columns="1">    
 
        <div>
        How do I use this?
        <ol>
            <li>Enter the formula in the first field. Ex: (250000 * 12) / 12</li>
            <li>Click the "=" button</li>
            <li>The formula will evaluate and the value will be stored in the second field.</li>
        </ol>
        </div>
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Example:" />
                <apex:outputPanel >
                    <input value="(250000 * 120)/4" style="width:400px;" />
                    <input type="button" value=" = " />
                    <input value="7500000" />
                </apex:outputPanel>
            </apex:pageBlockSectionItem>                 
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Sales Director Commission" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Sales_Director_Commission__c}" style="width:400px;" id="equation" 
                        onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
 
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
 
                    <apex:inputField value="{!Contract.Sales_Director_Commission__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Split Sales Director Commission" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Split_Sales_Director_Commission__c}" style="width:400px;" id="equation" 
                        onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
 
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
 
                    <apex:inputField value="{!Contract.Split_Sales_Director_Commission__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>            
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="VP Sales Commission" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_VP_Sales_Commission__c}" style="width:400px;" id="equation" 
                        onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
 
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
 
                    <apex:inputField value="{!Contract.VP_Sales_Commission__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Split VP Sales Commission" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Split_VP_Sales_Commission__c}" style="width:400px;" id="equation" 
                        onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
 
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
 
                    <apex:inputField value="{!Contract.Split_VP_Sales_Commission__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>            
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="SVP Sales Commission" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_SVP_Sales_Commission__c}" style="width:400px;" id="equation" 
                        onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
 
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
 
                    <apex:inputField value="{!Contract.SVP_Sales_Commission__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Channel Sales VP Commission" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Channel_Sales_VP_Commission__c}" style="width:400px;" id="equation" 
                        onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
 
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
 
                    <apex:inputField value="{!Contract.Channel_Sales_VP_Commission__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>                            
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Landlord Broker Commission" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Landlord_Broker_Commission__c}" style="width:400px;" id="equation" 
                        onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
 
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
 
                    <apex:inputField value="{!Contract.Landlord_Broker_Commission__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>            
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Tenant Broker Commission" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Tenant_Broker_Commission__c}" style="width:400px;" id="equation" 
                        onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
 
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
 
                    <apex:inputField value="{!Contract.Tenant_Broker_Commission__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem> 
 
            <apex:pageBlockSectionItem >
                <apex:outputLabel value="Referring Agent Commission" />
                <apex:outputPanel >
                    <apex:inputField value="{!Contract.Audit_Referring_Agent_Commission__c}" style="width:400px;" id="equation" 
                        onkeypress="if ((window.event ? event.keyCode : event.which) == 13) { this.form.elements['{!$Component.answer}'].value = calculate(this.value); }"/>
 
                    <input type="button" value=" = " onclick="this.form.elements['{!$component.answer}'].value = calculate(this.form.elements['{!$component.equation}'].value);" />
 
                    <apex:inputField value="{!Contract.Referring_Agent_Commission__c}" id="answer"/>
                </apex:outputPanel>
            </apex:pageBlockSectionItem>                                   
        </apex:pageBlockSection>  
 
        <apex:pageBlockSection title="DLR Sales Team" columns="2">        
            <apex:inputField value="{!Contract.Sales_Director__c}" id="salesDirector"/>
            <apex:inputField value="{!Contract.Split_Sales_Director__c}" id="splitSalesDirector"/>
            <apex:inputField value="{!Contract.VP_Sales__c}" id="vpSales"/>
            <apex:inputField value="{!Contract.Split_VP__c}" id="splitVP"/>
            <apex:inputField value="{!Contract.SVP_Sales__c}" id="svpSales"/>       
        </apex:pageBlockSection>         
 
        <apex:pageBlockSection title="External Brokers & Agents" columns="2">        
            <apex:inputField value="{!Contract.Landlord_Broker_Account__c}" id="landlordBrokerAccount"/>
            <apex:inputField value="{!Contract.Landlord_Broker__c}" id="landlordBroker"/>
            <apex:inputField value="{!Contract.Tenant_Broker_Account__c}" id="tenantBrokerAccount"/>
            <apex:inputField value="{!Contract.Tenant_Broker__c}" id="tenantBroker"/>
            <apex:inputField value="{!Contract.Referring_Agent_Account__c}" id="referringAgentAccount"/>
            <apex:inputField value="{!Contract.Referring_Agent__c}" id="referringAgent"/>        
        </apex:pageBlockSection> 
 
        <apex:pageBlockButtons >
          <apex:commandButton action="{!step3}" value="Previous"/>          
          <apex:commandButton action="{!save}" value="Save & Review"/>
          <apex:commandLink value="Cancel" action="{!cancel}" onclick="return confirmCancel()" immediate="true"/>          
        </apex:pageBlockButtons>        
 
      </apex:PageBlock>
    </apex:form>
</apex:page>

NOTE: Step 5 of the visualforce wizard is simply a ‘confirmation’ page that returns the user to the standard Contract details page of the newly-created record.