1

I would like to know if the following is possible to achieve:   When adding a product to the opportunity, the user is taken to a product selection page and then after selecting the product, the user is taken to a page that is called MultiLineItem.jsp.

Is it possible to override the multilineitem.jsp page with a custom visualforce page? What options are available? I know I can override the "add product" button. Ideally, I'd like to keep the product selection page intact and intercept the redirect to the multilineitem.jsp page and redirect to a custom visualforce page. Is that possible?

When clicking Edit All button from the products related list on the opportunity, I have overridden the button to point to a custom visualforce page. However, I cannot seem to be able to do it when clicking add product, making the product selection and then overriding to my custom visualforce page. Any way to do this?

  • 1
    Not without overriding the product selection page. I'll see if I can find my example of doing it as it is only a small amount of vf markup. I am about to start a project doing this so I need it anyways. Be an hour or so – Eric Mar 3 '17 at 23:20
  • Thanks @Eric, I appreciate the help. That is a good starting point. – Dman100 Mar 4 '17 at 4:31
1

Ok, so I was wrong it is more than a few lines, but manageable as long as you are ok with missing a few features or implementing them yourself. When you override you are only limited by your ability

What you have to do:

  1. override the "Add Product" button with you product picker page - (for the life of me I forget where the "Add Products" (note the s) button is used)
  2. Have the product picker page check for a price book set on the Opp
  3. If no price book set then redirect to the price book picker (you could make your own)
  4. Show products available on product picker (customize as needed)
  5. on select send to custom multiline page where details can be added
  6. save

Controller for pages

public class addProductController {

    @testVisible private Opportunity the_opp;

    public String opp_currency { get; set; }


    public addProductController(ApexPages.StandardController con) {
        the_opp = [
                Select ID, PriceBook2.Name, (Select PriceBookEntry.Product2ID, ProductCode From OpportunityLineItems)
                From Opportunity
                Where ID = :con.getId()
        ];


    }

    public PageReference priceBookCheck() {
        if (pbName == null) {
            PageReference pr = New Pagereference('/oppitm/choosepricebook.jsp');
            pr.getParameters().put('id', the_opp.id);
            pr.getParameters().put('retURL', '/' + the_opp.id);
            pr.getParameters().put('saveURL', '/apex/p/opp/pickProducts?id=' + the_opp.id + '&retURL=' + EncodingUtil.urlEncode('/apex/p/opp/pickProducts?id=' + the_opp.id + '&retURL=/' + the_opp.id, 'UTF-8'));

            pr.setRedirect(true);
            return pr;
        } else {
            return null;
        }
    }

    public PageReference gotoCustomMultiLine() {
        System.debug(the_opp.Pricebook2.Name);
        PageReference pr = Page.customMultiLine;
        pr.getParameters().put('id', the_opp.id);
        pr.setRedirect(false);
        return pr;

    }

    public String pbName {
        get {
            return the_opp.PriceBook2 == null ? null : the_opp.PriceBook2.Name;
        }
        private set;
    }

    public productSelection[] prods {
        get {
            if(prods == null) {
                prods = New productSelection[]{};

                for(PriceBookEntry pbe : [
                        Select UnitPrice, Product2.Name, ProductCode, Product2.Description, Product2.RecordType.Name
                        From PriceBookEntry
                        Where PriceBook2ID = :the_opp.PriceBook2ID
                        AND isActive = true
                ]){
                    prods.add(
                            New productSelection(pbe)
                    );
                }
            }

            if (prods.isEmpty()) {
                apexPages.addMessage(New ApexPages.Message(ApexPages.Severity.FATAL, 'Unable to find active products'));
            }

            return prods;
        }
        set;
    }

    public OpportunityLineItem[] OLIs {
        get {
            if (OLIs == null) {
                OLIs = New OpportunityLineItem[]{};

                for (productSelection ps : prods) {
                    if(ps.isSelected) {
                        OLIs.add(
                                New OpportunityLineItem(
                                        OpportunityID = the_opp.id,
                                        UnitPrice = ps.pbe.UnitPrice,
                                        PriceBookEntryID = ps.pbe.id
                                )
                        );
                        //Add names to Id map to display on page
                        prodNames.put(ps.pbe.id, ps.pbe.Product2.Name);
                    }
                }

            }


            return OLIs;

        }
        set;
    }

    public pageReference saveOLIs() {
        try {
            update the_opp;
        } catch (DMLException e) {
            apexPages.addMessage(New ApexPages.Message(ApexPages.Severity.FATAL, 'Error Updating Opportunity: ' + e.getDMLMessage(0)));
            return null;

        }

        for (OpportunityLineItem oli : OLIs) {
            if (oli.ServiceDate == null)
                oli.ServiceDate = date.today();
        }

        try {
            insert OLIs;
        } catch (DMLException e) {
            return null;
        }

        return gotoOpp();
    }

    public pageReference gotoOpp() {
        PageReference pr = New PageReference('/' + the_opp.id);
        return pr;
    }

    public Map<ID, String> prodNames {
        get {

            if (prodNames == null) {
                prodNames = New Map<ID, String>();
            }

            return prodNames;

        }
        private set;
    }


    public class productSelection{
        public boolean isSelected {get;set;}
        public PriceBookEntry pbe {get;set;}

        public productSelection(PricebookEntry pbe){
            this.pbe = pbe;
            isSelected = false;
        }
    }

}

product picker page

    <apex:page id="pickProducts" standardController="Opportunity" extensions="addProductController"
               action="{!priceBookCheck}">
        <apex:sectionHeader title="Add Products for" subtitle="{!Opportunity.Name}"
                            description="Enter your keyword and filter criteria, then click Search to begin your search. Click More filters to use more than one filter. Search results include all records that match both your keyword and filter entries."/>

        <apex:pageMessages id="msgs"/>

        <apex:form>
            <apex:pageBlock title="Select Products">
                <apex:pageBlockButtons>
                    <apex:commandButton  value="Select and Continue" action="{!gotoCustomMultiLine}"/>
                </apex:pageBlockButtons>
                <apex:pageBlockTable value="{!prods}" var="p">
                    <apex:column >
                        <apex:inputCheckbox value="{!p.isSelected}"/>
                    </apex:column>
                    <apex:column headerValue="Product Name" value="{!p.pbe.Product2.Name}"/>
                    <apex:column headerValue="Price" value="{!p.pbe.UnitPrice}"/>
                    <apex:column headerValue="Product Code" value="{!p.pbe.ProductCode}"/>
                    <apex:column headerValue="Product Description" value="{!p.pbe.Product2.Description}"/>
                    <apex:column headerValue="Product Record Type" value="{!p.pbe.Product2.RecordType.Name}"/>
                </apex:pageBlockTable>
            </apex:pageBlock>
        </apex:form>

    </apex:page>

custom multi line page

<apex:page id="customMultiLine" standardController="Opportunity" extensions="addProductController" showHeader="true" sidebar="true">

    <style>
        .dateFormat{
            display: none;
        }

        .pbTitle{
            display: none;
        }
    </style>

    <apex:sectionHeader title="Add Products for" subtitle="{!Opportunity.Name}" description="Add products to this opportunity from <b>{!pbName}</b> price book"/>

    <apex:pageMessages id="msgs"/>

    <apex:form >
        <apex:pageBlock >

            <apex:pageBlockButtons style="text-align: center;">
                <apex:actionStatus id="save_status">
                    <apex:facet name="stop">
                        <apex:outPutPanel >
                            <apex:commandButton value="Save" action="{!saveOLIs}" status="save_status" rerender="msgs"/>
                            <apex:commandButton value="Cancel" action="{!gotoOpp}" immediate="true" rerender="msgs"/>
                        </apex:outPutPanel>
                    </apex:facet>
                    <apex:facet name="start">
                        <apex:outPutText value="processing...."/>
                    </apex:facet>
                </apex:actionStatus>
            </apex:pageBlockButtons>


            <apex:pageBlockTable value="{!OLIs}" var="oli">

                <apex:column headerValue="Product" value="{!prodNames[oli.PriceBookEntryID]}"/>

                <apex:column headerValue="Quantity">
                    <apex:inputField value="{!oli.Quantity}"/>
                </apex:column>

                <apex:column headerValue="Currency" value="{!opp_currency}"/>

                <apex:column headerValue="Sales Price">
                    <apex:inputField value="{!oli.UnitPrice}"/>
                </apex:column>

                <apex:column headerValue="Date [{!TODAY()}]">
                    <apex:inputField value="{!oli.ServiceDate}"/>
                </apex:column>


            </apex:pageBlockTable>

        </apex:pageBlock>
    </apex:form>

</apex:page>

Note With lightning this can be much more robust. Additionally this is the basic functionality so customize as needed. Also needs some additional error checks etc but should get you started

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.