function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
JamesMJamesM 

APEX code to insert opportunity line item

Hello All

Im having a few issues with an Apex class im calling using the process builder.
The following code is creating the OLI ok, but only when a specific pricebook is assigned to the Opp.
Essentially im unable to find a way to set the pricebook to the one that is already assigned to the Opp, as currently its just using the first active pricebook it finds that the product is present in. Resulting in the following error; "pricebook entry is in a different pricebook than the one assigned to the opportunity".
 
Public class AutoCreateProduct
{
    @InvocableMethod
    public static void ProductAssign(List<Id> OppIds)
    {
     List<OpportunityLineItem> oliList = new List<OpportunityLineItem>();

    List<PriceBookEntry> priceBookList = [SELECT Id, Product2Id, Product2.Id, Product2.Name FROM PriceBookEntry WHERE Product2Id='01ta0000003vqHeAAI' AND PriceBook2.isActive=true LIMIT 1]; 

OpportunityLineItem oli = new OpportunityLineItem
(OpportunityId=OppIds[0], PricebookEntryId=priceBookList[0].Id, Quantity = 1);

    oliList.add(oli);
    insert oliList;
   }
}

Just some extra info, as im sure im not doing this in the best manner.
Im currently tasked with setting up fully automatic Lead conversion, and iv completed everystep up to this.
So leads are automatically converted in accounts, contacts and opps and have a pricebook assigned to them.

I have custom fields on the opportunity that will effect the prodcuts that will be added aswell as products that are in multiple pricebooks.
This last step is casing me no end of trouble, and iv not even added in any logic yet for the custom fields.

Thank you in advance for any help that can be offered.
Regards
James
 
Best Answer chosen by JamesM
Mahesh DMahesh D
Hi James,

You can compare the CurrencyISOCode and assign the record appropriately.
 
Public class AutoCreateProduct {
    @InvocableMethod
    public static void ProductAssign(List<Id> OppIds) {
    
		Set<Id> pbIdSet = new Set<Id>();
		List<Opportunity> oppList = [Select Id, PriceBook2Id, CurrencyIsoCode from Opportunity where Id IN: OppIds];
		for(Opportunity opp: oppList) {
			if(opp.PriceBook2Id != null)
				pbIdSet.add(opp.PriceBook2Id);
		}
		
		if(!pbIdSet.isEmpty()) {
			List<OpportunityLineItem> oliList = new List<OpportunityLineItem>();
			List<PriceBookEntry> pbeList = [SELECT Id, PriceBook2Id, Product2Id, CurrencyIsoCode, Product2.Id, Product2.Name FROM PriceBookEntry WHERE Product2Id='01ta0000003vqHeAAI' AND PriceBook2Id IN: pbIdSet AND PriceBook2.isActive=true LIMIT 1];
			for(Opportunity opp: oppList) {
				for(PriceBookEntry pbe: pbeList) {
					if(opp.PriceBook2Id == pbe.PriceBook2Id && opp.CurrencyIsoCode == pbe.CurrencyIsoCode) {
						OpportunityLineItem oli = new OpportunityLineItem(OpportunityId= opp.Id, PricebookEntryId = pbe.Id, Quantity = 1);
						oliList.add(oli);
						break;
					}
				}
			}
			
			if(!oliList.isEmpty())
				insert oliList;
		}
   }
}

Regards,
Mahesh

All Answers

Mahesh DMahesh D
Hi James,

You can try below code:
 
Public class AutoCreateProduct {
    @InvocableMethod
    public static void ProductAssign(List<Id> OppIds) {
    
		Set<Id> pbIdSet = new Set<Id>();
		List<Opportunity> oppList = [Select Id, PriceBook2Id from Opportunity where Id IN: OppIds];
		for(Opportunity opp: oppList) {
			if(opp.PriceBook2Id != null)
				pbIdSet.add(opp.PriceBook2Id);
		}
		
		if(!pbIdSet.isEmpty()) {
			List<OpportunityLineItem> oliList = new List<OpportunityLineItem>();
			List<PriceBookEntry> pbeList = [SELECT Id, PriceBook2Id, Product2Id, Product2.Id, Product2.Name FROM PriceBookEntry WHERE Product2Id='01ta0000003vqHeAAI' AND PriceBook2Id IN: pbIdSet AND PriceBook2.isActive=true LIMIT 1];
			for(Opportunity opp: oppList) {
				for(PriceBookEntry pbe: pbeList) {
					if(opp.PriceBook2Id == pbe.PriceBook2Id) {
						OpportunityLineItem oli = new OpportunityLineItem(OpportunityId= opp.Id, PricebookEntryId = pbe.Id, Quantity = 1);
						oliList.add(oli);
						break;
					}
				}
			}
			
			if(!oliList.isEmpty())
				insert oliList;
		}
    }
}

Regards,
Mahesh
JamesMJamesM
Hello Mahesh

Thanks alot for that.
It looks like the correct pricebook is now being selected, but is resulting in an error as it isnt selecting the price with the same currency value as the opp.

The Products usually have three prices, EUR, USD and GBP

thanks again

Regards
James
Mahesh DMahesh D
Hi James,

You can compare the CurrencyISOCode and assign the record appropriately.
 
Public class AutoCreateProduct {
    @InvocableMethod
    public static void ProductAssign(List<Id> OppIds) {
    
		Set<Id> pbIdSet = new Set<Id>();
		List<Opportunity> oppList = [Select Id, PriceBook2Id, CurrencyIsoCode from Opportunity where Id IN: OppIds];
		for(Opportunity opp: oppList) {
			if(opp.PriceBook2Id != null)
				pbIdSet.add(opp.PriceBook2Id);
		}
		
		if(!pbIdSet.isEmpty()) {
			List<OpportunityLineItem> oliList = new List<OpportunityLineItem>();
			List<PriceBookEntry> pbeList = [SELECT Id, PriceBook2Id, Product2Id, CurrencyIsoCode, Product2.Id, Product2.Name FROM PriceBookEntry WHERE Product2Id='01ta0000003vqHeAAI' AND PriceBook2Id IN: pbIdSet AND PriceBook2.isActive=true LIMIT 1];
			for(Opportunity opp: oppList) {
				for(PriceBookEntry pbe: pbeList) {
					if(opp.PriceBook2Id == pbe.PriceBook2Id && opp.CurrencyIsoCode == pbe.CurrencyIsoCode) {
						OpportunityLineItem oli = new OpportunityLineItem(OpportunityId= opp.Id, PricebookEntryId = pbe.Id, Quantity = 1);
						oliList.add(oli);
						break;
					}
				}
			}
			
			if(!oliList.isEmpty())
				insert oliList;
		}
   }
}

Regards,
Mahesh
This was selected as the best answer
JamesMJamesM
Hello Mahesh

Perfect thanks alot, this has made my morning.

I just needed to remove the  "LIMIT 1" as it wasnt storing the three currencys only the first one

Regards
James