0

I have a visualforce page that is supposed to display some pricebook entries from a pricebook2.

At first, I was just using the PriceBook2 standard controller. However, I need to add some custom functionality that I can't really do with the standard controller, so I decided to try writing a custom controller for it.

I followed the directions for making the custom controller from the official Salesforce documentation page here: https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_controller_custom.htm

However, now that I've switched to the custom controller, I'm getting an error when I try to load the VF page saying "List has more than 1 row for assignment to SObject"

Here is my Apex controller:

public class PriceSheetController {
    private final PriceBook2 pricebook2;
    private final PriceBookEntry pricebookentries;

    public PriceSheetController() {
        pricebook2 = [
            SELECT Id, Name FROM PriceBook2
            WHERE Id = :ApexPages.currentPage().getParameters().get('id')
        ];
        pricebookentries = [
            SELECT Id, Name, Pricebook2Id FROM PricebookEntry
            WHERE Pricebook2Id = :ApexPages.currentPage().getParameters().get('id')
        ];
    }

    public PriceBook2 getPriceBook2() {
        return pricebook2;
    }

    public PriceBookEntry getPriceBookEntries() {
        return pricebookentries;
    }
}

Here is my VF page:

<apex:page controller="PriceSheetController" renderAs="pdf">
    <apex:stylesheet value="{!$Resource.pricesheetpdfstyles}" />
    <div class="pricesheet">
        <div class="sheet-body">
            <div class="sheet-row">
                <div class="sheet-header-column-1">
                    Name
                </div>
                <div class="sheet-header-column-2">
                    Description
                </div>
                <div class="sheet-header-column-3">
                    Price
                </div>
            </div>
            <apex:repeat value="{!PriceBook2.PriceBookEntries}" var="p">
                <apex:outputPanel styleClass="sheet-row" layout="block">
                    <div class="sheet-column-1">
                        <p class="product-name">
                            {!p.Product2.Short_Product_Description__c}
                        </p>
                        <p class="product-code">
                            ({!p.ProductCode})
                        </p>
                    </div>
                    <div class="sheet-column-2">
                        {!p.Product2.Description}
                    </div>
                    <div class="sheet-column-3">
                        <apex:outputText value="{0, number, currency}">
                            <apex:param value="{!p.UnitPrice}" />
                        </apex:outputText>  
                    </div>
                </apex:outputPanel>
            </apex:repeat>  
        </div>      
    </div>
</apex:page>

I tried changing private final PriceBookEntry pricebookentries; to private List<PriceBookEntry> pricebookentries; but I get "Illegal conversion from List to PricebookEntry"

Any ideas on what I need to do to get this to work? Note: This worked just fine with the standard PriceBook2 controller. Apparently with a custom controller I have to hand-roll the code to fetch the pricebook entries (and its not possible to just select "PriceBookEntries" from the PriceBook2 object in the SOQL query as it will not recognize it there)

3

It's not at all surprising that you would have more than one PricebookEntry record associated with your Pricebook. You should change the type of your pricebookentries to List<PricebookEntry>. The fact the name is plural should tip you off it's a collection, not a single instance.

final List<PricebookEntry> pricebookEntries;
public List<PricebookEntry> getPricebookEntries()
{
    return pricebookEntries;
}

Also note, it's somewhat more compact to just use the following syntax instead:

public List<PricebookEntry> pricebookEntries { get; private set; }

And one more note, you can write this class as an extension, rather than a custom controller, and it will be a bit simpler and more robust:

public with sharing class MyExtension
{
    public Pricebook2 pricebook { get; private set; } 
    public List<PricebookEntries> entries { get; private set; }
    public MyExtension(ApexPages.StandardController controller)
    {
        pricebook = (Pricebook2)controller.getRecord();
        entries = [
            SELECT ... FROM PricebookEntry WHERE PricebookId = :controller.getId()
        ];
    }
}
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.