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 objectProduct__c
. In the latter object you've got a lookup field toQBP__c
so that,Product__c
records appear in theQBP__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 manyProduct__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 aQBP__c
record needs to reference a LaptopProduct__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 yourQBP__c
records, can create a Junction Object record instead that references both object.In other words, one
QBP__c
record can be associated with manyProduct__c
, and oneProduct__c
can be associated with manyQBP__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 aProduct_Item__c
record that references both the Product and the QBP record. You can make as manyProduct_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: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: