You need to sign in to do that
Don't have an account?
Nick Keehan
Apex Trigger - Convert String of products to OpportunityLineItems
Hi guys.
Looking to create an Apex trigger to fire on the Opportunity to convert a Long Text Area String to opportunityLineItems. I have a pricebook set on the opportunity already, so i think i am looking for a type of map that looks at the pricebook entry from the name and supplies a PricebookEntryID, then creating a loop of Opportunity Line Items with the entrys.
E.g. On Opportunity - Product_Names__c - Product 1, Product 2, Product 3
I can have the string seperated/formated in a number of ways, semi colon, no space etc.
Does anyone have any idea how this would look? sorry, still new with Maps.
Nick
Looking to create an Apex trigger to fire on the Opportunity to convert a Long Text Area String to opportunityLineItems. I have a pricebook set on the opportunity already, so i think i am looking for a type of map that looks at the pricebook entry from the name and supplies a PricebookEntryID, then creating a loop of Opportunity Line Items with the entrys.
E.g. On Opportunity - Product_Names__c - Product 1, Product 2, Product 3
I can have the string seperated/formated in a number of ways, semi colon, no space etc.
Does anyone have any idea how this would look? sorry, still new with Maps.
Nick
You can use following code,
trigger oppLineItem on Opportunity (after insert,after update) {
Map<id,Set<id>> oppIdProNameMap = new Map<id,Set<Id>>();
Set<Id> priceBookIdSet = new Set<id>();
if(checkRecursive.runOnce()){
for(Opportunity opp : trigger.new){
priceBookIdSet = new Set<Id>();
system.debug('---opp.Product_Names__c--'+opp.Product_Names__c);
if(opp.Product_Names__c != ''){
priceBookIdSet=getPriceBookId(opp.Product_Names__c,opp.Pricebook2Id);
system.debug('---priceBookIdSet---'+priceBookIdSet);
oppIdProNameMap.put(opp.Id, priceBookIdSet);
}
}
List<OpportunityLineItem> newLineItemsList = new List<OpportunityLineItem>();
for(id oppId : oppIdProNameMap.keySet()){
for(id pBId : oppIdProNameMap.get(oppId)){
OpportunityLineItem lineItem = new OpportunityLineItem (OpportunityID= oppId,PriceBookEntryID=pBId, quantity=1,TotalPrice = 100);
newLineItemsList.add(lineItem);
}
}
insert newLineItemsList;
}
public Set<id> getPriceBookId(string pName,id bookId){
List<String> proName = new List<String>();
proName = pName.split(',');
Map<id,product2> proIdMap = new Map<id,product2>([Select id from product2 where name IN: proName]);
system.debug('----proIdMap.keySet()--'+proIdMap.keySet());
Map<id,PricebookEntry> priceBookMap = new Map<id,PricebookEntry>([SELECT Id,IsActive,Product2Id,UnitPrice FROM PricebookEntry WHERE Product2Id IN: proIdMap.keySet() and Pricebook2Id =: bookId]);
return priceBookMap.keySet();
}
}
Hope it will solve your problem.
Thanks,
Shweta
All Answers
You can use following code,
trigger oppLineItem on Opportunity (after insert,after update) {
Map<id,Set<id>> oppIdProNameMap = new Map<id,Set<Id>>();
Set<Id> priceBookIdSet = new Set<id>();
if(checkRecursive.runOnce()){
for(Opportunity opp : trigger.new){
priceBookIdSet = new Set<Id>();
system.debug('---opp.Product_Names__c--'+opp.Product_Names__c);
if(opp.Product_Names__c != ''){
priceBookIdSet=getPriceBookId(opp.Product_Names__c,opp.Pricebook2Id);
system.debug('---priceBookIdSet---'+priceBookIdSet);
oppIdProNameMap.put(opp.Id, priceBookIdSet);
}
}
List<OpportunityLineItem> newLineItemsList = new List<OpportunityLineItem>();
for(id oppId : oppIdProNameMap.keySet()){
for(id pBId : oppIdProNameMap.get(oppId)){
OpportunityLineItem lineItem = new OpportunityLineItem (OpportunityID= oppId,PriceBookEntryID=pBId, quantity=1,TotalPrice = 100);
newLineItemsList.add(lineItem);
}
}
insert newLineItemsList;
}
public Set<id> getPriceBookId(string pName,id bookId){
List<String> proName = new List<String>();
proName = pName.split(',');
Map<id,product2> proIdMap = new Map<id,product2>([Select id from product2 where name IN: proName]);
system.debug('----proIdMap.keySet()--'+proIdMap.keySet());
Map<id,PricebookEntry> priceBookMap = new Map<id,PricebookEntry>([SELECT Id,IsActive,Product2Id,UnitPrice FROM PricebookEntry WHERE Product2Id IN: proIdMap.keySet() and Pricebook2Id =: bookId]);
return priceBookMap.keySet();
}
}
Hope it will solve your problem.
Thanks,
Shweta
Getting an issue with the variable (Compile Error: Variable does not exist: checkRecursive at line 4 column 8).
Any idea on how to overcome?
Nick
checkRecursive is a class to handale recursion. When we insert opportunity line item it will update the opportunity, which will cause recursion.
Find the code for checkRecusive
public Class checkRecursive{
private static boolean run = true;
public static boolean runOnce(){
if(run){
run=false;
return true;
}else{
return run;
}
}
}
Thanks,
Shweta
This works brilliantly, except for two minor exceptions.
1: We cant add two of the same product into the string field. Quite often there will be a situation where an agent could sell two of the same product. The trigger only adds the first item rather than the list of items. it must pick it up as remove it as the line item has been added.
2: It will not allow us to create normal opportunities as its trying to add line items each time. if(opp.Product_Names__c != '') doesnt seem to be firing. normally there is nothing in the string field however it is still giveing me a trying to reference a null object.
Any suggestions here?
Thanks for your help by the way!
Just looking to see if i can allow this process to allow multiple of the same opportunity Product.
E.g. String -" Line and Broadband,CallerID,CallerID
Currently it removes these from the list of products being added.
Nick
I have done few changes in above trigger. Hope it will solve your both problem.
trigger oppLineItem on Opportunity (after insert,after update) {
Map<id,Map<string,id>> oppIdProPriceMap = new Map<id,Map<string,id>>();
Map<string,id> mapOfPriceProName = new Map<string,id>();
Map<id,List<string>> oppIdProNameMap = new Map<id,List<string>>();
List<String> proName = new List<String>();
if(checkRecursive.runOnce()){
for(Opportunity opp : trigger.new){
mapOfPriceProName = new Map<string,id>();
system.debug('---opp.Product_Names__c--'+opp.Product_Names__c);
if(opp.Product_Names__c != null){
mapOfPriceProName=getPriceBookId(opp.Product_Names__c,opp.Pricebook2Id);
system.debug('---mapOfPriceProName---'+mapOfPriceProName);
oppIdProPriceMap.put(opp.Id, mapOfPriceProName);
oppIdProNameMap.put(opp.Id, proName);
}
}
List<OpportunityLineItem> newLineItemsList = new List<OpportunityLineItem>();
for(id oppId : oppIdProNameMap.keySet()){
for(String pName : oppIdProNameMap.get(oppId)){
system.debug('----oppIdProPriceMap.get(oppId).get(pName)---'+oppIdProPriceMap.get(oppId).get(pName));
if(oppIdProPriceMap.get(oppId).get(pName) != null){
OpportunityLineItem lineItem = new OpportunityLineItem (OpportunityID= oppId,PriceBookEntryID=oppIdProPriceMap.get(oppId).get(pName), quantity=1,TotalPrice = 100);
newLineItemsList.add(lineItem);
}
}
}
insert newLineItemsList;
}
public Map<string,id> getPriceBookId(string pName,id bookId){
proName = new List<String>();
proName = pName.split(',');
Map<id,product2> proIdMap = new Map<id,product2>([Select id from product2 where name IN: proName]);
system.debug('----proIdMap.keySet()--'+proIdMap.keySet());
system.debug('-----bookId----'+bookId);
List<PricebookEntry> priceBookList = [SELECT Id,IsActive,Product2Id,Product2.Name,UnitPrice FROM PricebookEntry WHERE Product2Id IN: proIdMap.keySet() and Pricebook2Id =: bookId];
Map<string,id> proNameEntryIdMap = new Map<string,id>();
for(PricebookEntry price : priceBookList){
proNameEntryIdMap.put(price.Product2.Name, price.id);
}
return proNameEntryIdMap;
}
}
Thanks
i have a small doubt , can you correct me as i am new working on the price books . i did not understand where my trihgger is firing .
i created a new longtext area field named "Product_Names__c " in opportunity and i placed your code in my org .
so while creating a new opportunity , i gave the values in field named "Product_Names__c " as "test1 , test2 ,test3 ".and i created a price boxfor this clicked on so i hope these all values should be falling as a related list .
but this is not happening am i doing some thing wrong . i did not understand where my trihgger is firing .
Can you check once if the price book for the product name which you entered in Product_name__c and price book for opportunity is same. This code will add only those product in realted list which are from same price book.
Thanks
thanks for explaining me , i tried this now but couldnt achieve this , can you please correct me am doing wrong as i want to learn this so i am posing you questions .
Step 1:
Price book name : test , which contains the below products
Step2 :
I created a new opportunity , with the product names same as below and I saved my opportunity .
I hope your trigger should display those product names in related list of the products . but this is not happening , can you please tell me the step by step how to achieve this functionality works
It will redirect you to pricebook selection page. when you select the pricebook "Test" and click on save then the trigger will fire and will add the products .