4

enter image description here

Since Summer 14 released this weekend every time I try and clone a product I get the below error message and I don’t understand what its saying? I think something changed with the price book in the new release. Any ideas?

It doesn’t happen when I create a new product and type all the data in manually…very much a pain but it works. The following is the trigger in question I believe

trigger PriceBookEntryUpdate on Product2 (before insert,after insert, before update) {
  List<User> userDetails=[Select u.Email, u.Id from User u];
  Map<String , Id> userMap= new Map <String,Id>();
    for (User user : userDetails){
        userMap.put(user.Email,user.Id);

    }

if(Trigger.isInsert || Trigger.isUpdate){
if(Trigger.isBefore){
 //Before trigger starts    
    for(Product2 prod : Trigger.new){
            if(prod.PME_Text__c!=NULL ){
                    prod.PME__c=userMap.get(prod.PME_Text__c.trim());
            }
            if(prod.AE_Text__c!=NULL ){
                         prod.AE__c=userMap.get(prod.AE_Text__c.trim());
            } 
            if((Trigger.isInsert) &&(prod.Product_Status_Code1__c!='6EOL' && prod.Product_Status_Code1__c!='8INAC')){  
                prod.IsActive=true; 
            }
    }
}
 //After trigger starts-creation of PriceBookEntry Record
 if(Trigger.isAfter){
Id StdPrcId=[Select id from PriceBook2 where isStandard=true limit 1].id;
List<PricebookEntry> pbList= new List<PricebookEntry>();
for(Product2 p : Trigger.new){
    PricebookEntry pb=new PricebookEntry(Product2Id=p.id,PriceBook2Id=StdPrcId,UnitPrice=(p.unit_Cost_default__C==null?0:p.unit_Cost_default__C),IsActive=true);
    pbList.add(pb);
}
 try{ 
insert pbList;    } catch(Exception e){system.debug('Error :' +e.getMessage());}
}
}
}
EricSSH
  • 4,334
  • 1
  • 29
  • 59

2 Answers2

0

To automatically create a pricebook entry when a single product is created or cloned (clone does this by default) We have a separate piece of code for multiples (bulk inserts) which will never be clones. Btw, we don't use price books. This is stubbed out to be able to use standard SF quoting features.

trigger insertPBE on Product2 (after insert) {
  Pricebook2 standardPriceBook = [SELECT Id from Pricebook2 where Name='Standard Price Book'];
  if(trigger.New.size() <= 1) { //clone would be single record
    try {               
      Product2 product = trigger.New[0];
      //grab existing pricebook entry
      PriceBookEntry pbe = [Select Id from PricebookEntry where Product2Id = :product.Id];
      if(pbe == null)
        pbe = new PricebookEntry(); //create a new one if necessary         
      pbe.Product2Id = product.Id;
      pbe.IsActive = true;
      pbe.Pricebook2Id = standardPriceBook.Id;
      pbe.UnitPrice = 1.00;
      upsert pbe;
    }
    catch (Exception e) { return; }
    return;
}
dphil
  • 6,185
  • 2
  • 36
  • 71
0

Your after trigger creates PriceBookEntry for inserted Products. When you try to clone a Product with PriceBookEntry, the functionality clones both of them (Product and PBE).

With the Summer '14 Release, your trigger fires after Product creation and before PBE creation. The clone functionality tries to clone the PBE after your trigger has already created it. The database can't allow 2 PBEs with the same currency in the same Price Book for the same Product - therefore, an common.exception.SfdcSqlException is thrown.

You can try to create the PBE from an asynchronous (@future) method. Execute this method in your after trigger and pass the product id (or set of product ids) as parameter. In the future method you can check whether PBE already exists for this product id, or not. If not you can create one.

TSB
  • 1
  • 1