I have two Visualforce pages and a custom controller that comprise a wizard to add products to an opportunity (yes I know that's already in there but I had to resort to this because I couldn't remove "Sales Price" from the standard one, and we don't use sales price as we rent and make money from commission).
The first page works fine, it displays a list of all products and a checkbox on the left. The second page will eventually display a number of fields for every item that was selected on the previous page, and then the user can save. However, since adding the apex repeat tag in the second page I've been getting the error: Validation Errors While Saving Record(s) every time I navigate to it.
The error detail reads: There were custom validation error(s) encountered while saving the affected record(s). The first validation error encountered was "Product ID: value not of required type: core.apexpages.el.adapters.metadata.SObjectMetadataELAdapter@4d4bebc6".
The interesting thing is I'm not trying to save any records; not yet at least. The insert statement is in the Save action and the button for that isn't even visible until the last page.
Code below, can anyone help?
Controller
public class NewOpportunityProductsController {
// PROPERTIES
public List<SelectableListProduct> prodList {get;set;}
public List<OpportunityLineItem> itemsToAdd {get;set;}
public List<PricebookEntry> selProducts {get;set;}
public Boolean hasSelProd {get;set;}
public Opportunity owner {get;set;}
// CONSTRUCTOR
public NewOpportunityProductsController(){
prodList = new List<SelectableListProduct>();
selProducts = new List<PricebookEntry>();
itemsToAdd = new List<OpportunityLineItem>();
owner = [SELECT Id FROM Opportunity WHERE Id = :ApexPages.currentPage().getParameters().get('oid')];
for(PricebookEntry p : [SELECT Product2.Name, Id, Product2.ProductCode, Product2.Standard_Install_Cost__c, Product2.Standard_Monthly_Cost__c, Product2.Supplier__c
FROM PricebookEntry WHERE Product2.Name != NULL]){
prodList.add(new SelectableListProduct(p));
}
prodList.sort();
}
// METHODS
private void gatherSelectedProducts(){
selProducts.clear();
itemsToAdd.clear();
hasSelProd = false;
for(SelectableListProduct cProdWrapper : prodList){
if(cProdWrapper.isSelected){
hasSelProd = true;
selProducts.add(cProdWrapper.cProduct);
}
}
//Create line items
for (PricebookEntry p : selProducts)
{
OpportunityLineItem newLineItem = new OpportunityLineItem();
newLineItem.OpportunityId = ApexPages.currentPage().getParameters().get('oid');
newLineItem.PricebookEntryId = p.Id;
newLineItem.UnitPrice = 0;
newLineItem.Install_Cost__c = p.Product2.Standard_Install_Cost__c;
newLineItem.Monthly_Cost__c = p.Product2.Standard_Monthly_Cost__c;
itemsToAdd.add(newLineItem);
}
itemsToAdd.sort();
}
public PageReference step1() {
return Page.SelectNewItems;
}
public PageReference step2() {
gatherSelectedProducts();
return Page.EditNewItems;
}
public PageReference cancel() {
PageReference opportunityPage = new ApexPages.StandardController(owner).view();
opportunityPage.setRedirect(true);
return opportunityPage;
}
public PageReference save() {
try {
insert itemsToAdd;
} catch (System.DMLException e) {
ApexPages.addMessages(e);
return null;
}
PageReference opportunityPage = new ApexPages.StandardController(owner).view();
opportunityPage.setRedirect(true);
return opportunityPage;
}
}
Wrapper Class
public class SelectableListProduct implements Comparable
{
public Boolean isSelected {get;set;}
public PricebookEntry cProduct {get;set;}
public SelectableListProduct(PricebookEntry cProduct){
this.cProduct = cProduct;
}
public Integer compareTo(Object comparisonObject)
{
SelectableListProduct comparisonProduct = (SelectableListProduct)comparisonObject;
return cProduct.Product2.Name.compareTo(comparisonProduct.cProduct.Product2.Name);
}
}
Page One
<apex:page controller="NewOpportunityProductsController" tabstyle="Opportunity">
<apex:sectionHeader title="Add New Opportunity Products" subtitle="Select Products"/>
<apex:form >
<apex:pageBlock title="Product List">
<apex:pageBlockButtons >
<apex:commandButton action="{!step2}" value="Next"/>
<apex:commandButton action="{!cancel}" value="Cancel"/>
</apex:pageBlockButtons>
<!-- PRODUCT LIST -->
<apex:pageBlockTable value="{!prodList}"
var="SelectableListProduct">
<apex:column >
<apex:inputCheckbox value="{!SelectableListProduct.isSelected}"/>
</apex:column>
<apex:column value="{!SelectableListProduct.cProduct.Product2.Name}"/>
<apex:column value="{!SelectableListProduct.cProduct.Product2.ProductCode}"/>
<apex:column value="{!SelectableListProduct.cProduct.Product2.Standard_Install_Cost__c}"/>
<apex:column value="{!SelectableListProduct.cProduct.Product2.Standard_Monthly_Cost__c}"/>
<apex:column value="{!SelectableListProduct.cProduct.Product2.Supplier__c}"/>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
</apex:page>
Page Two
<apex:page controller="NewOpportunityProductsController" tabStyle="Opportunity">
<apex:sectionHeader title="Add New Opportunity Products" subtitle="Edit Products"/>
<apex:form >
<apex:pageBlock title="Edit Item Information">
<apex:pageBlockButtons >
<apex:commandButton action="{!save}" value="Done"/>
<apex:commandButton action="{!step1}" value="Back"/>
<apex:commandButton action="{!cancel}" value="Cancel"/>
</apex:pageBlockButtons>
<apex:repeat value="{!itemsToAdd}" var="currentItem">
<apex:outputField value="{!currentItem.PricebookEntry.Product2}" />
<apex:inputField value="{!currentItem.Install_Cost__c}" />
<apex:inputField value="{!currentItem.Monthly_Cost__c}" />
</apex:repeat>
</apex:pageBlock>
</apex:form>
</apex:page>