[SalesForce] Adding Multiple Products to Related list of custom object

I am building CPQ Module for my client and I am done with Product and Bundle management
Now, I am implementing Quote management and I am stuck for the following :

I am developing one visualforce page and apex class for the following requirement

I have a custom object named QBP__c and in this object I need to store multiple Products in related list (only existing products) with entering Quantity of each products

To achieve this requirement I have created one field Product__c(Lookup) because user will select product using this lookup field and after clicking on the save button it will
move to the related list of the QBP__c object

Now, the question is how can I add multiple Products to this related list from selecting the product using lookup field ? And How can I add quantity to each product while saving from visualforce page ?

Let me show you my visualforce code :

<apex:pageBlockButtons location="Bottom">
    <apex:commandButton value="Add Product" action="{!addSection1}"/>
    <apex:commandButton value="Save" action="{!Save}"/>
    <apex:commandButton value="Cancel" action="{!Cancel}"/>
</apex:pageBlockButtons>
    <apex:outputPanel >
    <div>
    <ul id="sortable">
     <apex:variable value="" var="foo" rendered="{!IF(lstSections1 = True, true, false)}">
            <apex:pageBlockSection title="Select Product">
                <apex:actionRegion >
                    <apex:pageBlockTable value="{!QBP}" var="QBP">
                    <apex:column >
                        <apex:outputLabel >Select Product :</apex:outputLabel>
                    </apex:column>
                    <apex:column >
                    <apex:inputField value="{!QBP.Product__c}" >
                        <apex:actionSupport event="onchange" rerender="relatedInfo" action="{!retrieveproductInfo}" immediate="false"/>
                    </apex:inputField>
                    </apex:column>
                    <apex:column >
                        <apex:pageBlockSection id="relatedInfo">
                            <apex:outputText value="{!partNumber}" label="Part Number :"/>
                            <apex:outputText value="{!Description}" label="Description :"/>
                        </apex:pageBlockSection>
                    </apex:column>
                    </apex:pageBlockTable>
                </apex:actionRegion>
            </apex:pageBlockSection>
    </apex:variable>
    </ul>
    </div>        
    </apex:outputPanel>

Apex Class :

    public class AddQBPForQuoteController{

    public Quote quote{get;set;}
    public boolean lstSections1{get;set;}
    public String partNumber{get;set;}
    public String Description{get;set;}
    public QBP__c QBP{get;set;}
    public List<QBP__c> QBPList{get;set;}

    public AddGroupForQuoteController(ApexPages.StandardController controller) {
        lstSections1 = false;
        grp = new Group__c();
        QBP = new QBP__c();
        QBPList = new List<QBP__c>();
        this.quote = (Quote)controller.getRecord();
    }

    public void retrieveproductInfo() {
        if(QBP.Product__c != Null){
            this.partNumber = [SELECT Id, ProductCode FROM Product2 WHERE Id =: QBP.Product__c].ProductCode;
            this.Description = [SELECT Id, Description FROM Product2 WHERE Id =: QBP.Product__c].Description;
        }
    }

    public PageReference addSection1() {
        lstSections1 = true;
        QBP = new QBP__c();
        QBPList.add(QBP);
        return null;
    }

    public Pagereference Save(){
        insert QBP;
        for(integer i=0; i<QBPList.size(); i++){
            this.partNumber = [SELECT Id, ProductCode FROM Product2 WHERE Id =: QBP.Product__c].ProductCode;
            this.Description = [SELECT Id, Description FROM Product2 WHERE Id =: QBP.Product__c].Description;
        }
        upsert QBP;
        return null;
    }

    public Pagereference Cancel(){
        PageReference pg = new PageReference('/apex/AddQBPForQuote?id='+quote.Id);
        pg.setRedirect(True);
        return pg;
    }

}

Best Answer

It sounds to me like you've got your schema slightly wrong.

If I understand what you're saying, you've got an object: QBP__c and an object Product__c. In the latter object you've got a lookup field to QBP__c so that, Product__c records appear in the QBP__c record's Product Related list?

If I'm right, what you've created is a one to many (1:n) relationship where one QBP__c record can have many Product__c records. The problem with that is that, if you have a product record (let's pretend it's a Laptop), you'd have to recreate the same Laptop record every time a QBP__c record needs to reference a Laptop Product__c.

What you really need to do is create a Junction Object and thus create a many-to-many (n:n) relationship. This will allow you to, in Product__c, create one Laptop record. Then, when you need to reference it in your QBP__c records, can create a Junction Object record instead that references both object.

In other words, one QBP__c record can be associated with many Product__c, and one Product__c can be associated with many QBP__c.

To fix this, you need to create a new Object (let's call it Product_Item__c) that has two fields (Lookup or Master Detail, depending on which is more appropriate, you'd probably typically use Master Detail). Whenever you want to add a new Product to a QBP record, you'd just create a Product_Item__c record that references both the Product and the QBP record. You can make as many Product_Item__c records as appropriate without duplicating Products or QBP records (depending on which way round you put the Lookup field, if I'm wrong about where you put it).

Edit

If you want to display related Lists and are using a Standard Controller, you could simply use <apex:relatedList> to do this and put it in your Visualforce Page:

<apex:relatedList list="Product_List__r" title="Related Products" />

Where I've written Product_List__r you basically need to use the name of the Child Relationship related to the Object, from the docs:

To specify this value, use the name of the child relationship to the related object. For example, to display the Contacts related list that would normally display on an account detail page, use list="Contacts".

Related Topic