I am working on a requirement to create an opportunity and opportunity products , when there is an update on the asset object.

The asset object has a filed called Refresh_Asset_To__c, this is a lookup to the product object.

Basically each time I change the product on the Refresh_Asset_To__c, a new opportunity should be generated with the Refresh_Asset_To__c being the opportunity product.

I have tested , and its generating the opportunity , but each time i try to insert the opportunity product I get the error :

Update failed. First exception on row 0 with id 02i3B000003TAk7QAG; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AssetRefreshOpp: execution of AfterUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, field integrity exception: PricebookEntryId (pricebook entry currency code does not match opportunity currency code): [PricebookEntryId] Trigger.AssetRefreshOpp: line 56, column 1: []

This is my code:

trigger AssetRefreshOpp on Asset (after update) {
     Pricebook2 ikmBook    = [SELECT Id,CurrencyIsoCode FROM Pricebook2 WHERE Id = '01s46000003K1zXAAS'];

List<OpportunityLineItem> oppLiList = new List<OpportunityLineItem>();
Opportunity opp;
OpportunityLineItem oli;
string refeshed;

   List<asset> refreshedAss = [select Id,Contract__r.EndDate,OwnerId,quantity,Name,Refresh_Asset_To__c,Refresh_Asset_To__r.Id,AccountId,account.name from asset 
                                    where Id IN : Trigger.new 
                                    And Refresh_Asset__c = True];

       for(asset myAss:refreshedAss){

          // Create New Opportunity

            Opportunity newopp =new Opportunity();

newopp.Name=myAss.account.name + ' ' + 'refreshed';
newOpp.AccountId = myAss.AccountId;
newOpp.CloseDate = myAss.Contract__r.EndDate;
newOpp.StageName = 'Create';
newOpp.RecordTypeID = '01246000000TfMZAA0';
newOpp.OwnerId = myAss.OwnerId;
newOpp.Amount = 0;
newOpp.Type= 'Existing Business';
newOpp.OM_Order_Type__c = 'Regular';
newOpp.CurrencyIsoCode = ikmBook.CurrencyIsoCode;
newOpp.Pricebook2Id = ikmBook.Id;

insert newOpp;

       List<PriceBookEntry> priceBookList = [SELECT Id, Product2Id,CurrencyIsoCode, Product2.Id, Product2.Name FROM PriceBookEntry WHERE  PriceBook2.isStandard=true LIMIT 1];

            for(asset myAssets:refreshedAss){

             OpportunityLineItem oli = new OpportunityLineItem();

              oli.OpportunityId = newOpp.Id;

              oli.Product2Id = myAssets.Refresh_Asset_To__r.Id;

              oli.PriceBookEntryId = priceBookList[0].Id;

              oli.UnitPrice = 0;
              oli.Quantity = myAssets.Quantity;


         insert oppLiList;         

  • do not use hardcoded Ids Commented Jan 9, 2018 at 20:08
  • The only hard coded Id is for the opportunity record type. Commented Jan 9, 2018 at 20:09
  • You will also want to remove the DML and SOQL queries from the FOR Loop.
    – Bob Lopez
    Commented Jan 9, 2018 at 20:12
  • See here for Apex Best Practices (see #2 & #5)
    – Bob Lopez
    Commented Jan 9, 2018 at 20:17
  • ikmbook is also hardcoded. Commented Jan 9, 2018 at 20:24

1 Answer 1


Unless the hard-coded PriceBook in your second line is the same as the Standard Price Book, this is going to fail. All the products in an Opportunity must be from the same Price Book, and you're querying a price book entry record from a price book that might not be the same as the hard-coded one.

Also, I don't think you need to specify the OLI Product2 field if you're specifying the PBE field. Salesforce will do that for you. As long as the priceBookList[0] record is the same product as the asset refers to (and I don't think you can guarantee that in your code) then you're fine. But as I see it, this is risky code. Simplify, and many of your problems will fall away.

  • Thanks david, really appreciate your response. You hit it spot on with the line ; "As long as the priceBookList[0] record is the same product as the asset refers to (and I don't think you can guarantee that in your code)" How do I query in order to get the pricebook entry for the asset ? Thanks Commented Jan 9, 2018 at 20:38
  • You're very welcome! Feel free to mark my answer accordingly. Commented Jan 9, 2018 at 20:39
  • How do I query in order to get the pricebook entry for the asset ? Commented Jan 9, 2018 at 20:53
  • 1
    Assets don't have PriceBookEntry records. However, if you know the product, the currency, and the pricebook, you can get the pricebookentry record in a query. The combination of product and currency are unique for a given pricebook. Commented Jan 9, 2018 at 20:55
  • @TonyCurtis If the answer was sufficient, please mark it as accepted. Commented Jan 22, 2018 at 20:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .