0

I have created a Record Detail button to clone a Product's detail, a related list called Bill of Materials, and both the Standard PB Entry, and any Custom PB Entries.

If I remove the Custom PB Entry clone code, everything works as intended, however, if I save with the Custom PB Entries, it fails with the following log entry (which refers to the line insert CustomPB;).

Class.ProductDeepClone.DeepCloneProduct: line 127, column 1
System.DmlException: Insert failed. First exception on row 0; first error: DUPLICATE_VALUE, This price definition already exists in this price book: []

Although I (sort of) understand the error, in as much as it's essentially the same Object (PBE), I am not sure why the insert is considered a duplicate, or more importantly how better write the code.

Thanks

APEX:

global class ProductDeepClone {

    webservice static string DeepCloneProduct(Id ProId){

        Product2 pro = [SELECT id,Name,Country__c,Width_mm__c
            FROM Product2 WHERE Id = :ProId];

        Product2 proCopy = pro.clone(false,true);

        proCopy.Name = 'RENAME ME - ' + pro.Name;

        proCopy.Country__c = pro.Country__c;
        proCopy.Width_mm__c = pro.Width_mm__c;

        insert proCopy;

        List<Bill_Of_Materials__c> boms = new List<Bill_Of_Materials__c>();
        for(Bill_Of_Materials__c b :[
            SELECT b.id,b.Product_Material__c,b.Quantity__c,b.Unit_Cost__c
            FROM Bill_Of_Materials__c b
            WHERE Product__c = :pro.Id]){

                Bill_Of_Materials__c bCopy = b.clone(false,true);
                bCopy.Product__c = proCopy.Id;
                boms.add(bCopy);
            }
        insert boms;

        List<PricebookEntry> standardPB = new List<PricebookEntry>();
        for(PricebookEntry spb :[

            SELECT 
                spb.id,
                spb.UseStandardPrice,
                spb.UnitPrice,
                spb.ProductCode,
                spb.Product2Id,
                spb.Pricebook2Id,
                spb.Pricebook2.IsStandard,
                spb.Name,
                spb.IsActive

            FROM PricebookEntry spb
            WHERE Pricebook2.IsStandard = TRUE
            AND Product2id = :pro.Id
            LIMIT 1]){

                PricebookEntry spbCopy = spb.clone(false,true);
                spbCopy.Product2id = proCopy.Id;
                standardPB.add(spbCopy);
            }
        insert standardPB;

        List<PricebookEntry> CustomPB = new List<PricebookEntry>();
        for(PricebookEntry p :[

            SELECT 
                p.id,
                p.UseStandardPrice,
                p.UnitPrice,
                p.ProductCode,
                p.Product2Id,
                p.Pricebook2Id,
                p.Name,
                p.IsActive

            FROM PricebookEntry p
            WHERE Product2id = :pro.Id]){

                PricebookEntry pCopy = p.clone(false,true);
                pCopy.Product2id = proCopy.Id;
                CustomPB.add(pCopy);
            }
        insert CustomPB;


        string resultId = Id.valueOf(proCopy.Id);
        return resultId;
    }
}
4
  • can you try pro.clone(false,true, false, false); ? May 21, 2018 at 7:14
  • Hi Sagar, I dont follow, isn't that just preseriving the following - preserveReadonlyTimestamps, preserveAutonumber ?? May 21, 2018 at 7:37
  • can you check the ID of the cloned object using method getCloneSourceId() ?? whether it is coming same or different? May 21, 2018 at 7:42
  • Hi Sagar, the clone process is working, however the line thats failing is 'Insert CustomPB;' So the ID is passing, however the insertion of the customPB is being treated as a duplicate. May 22, 2018 at 1:48

1 Answer 1

0

So I managed to overcome this error, by adding a WHERE clause in the 2nd Pricebook entry list.

When adding the standard price to a cloned product I used WHERE Pricebook2.IsStandard = TRUE.

To avoid the duplication error, I specified that the custom pricebook had the reverse clause - WHERE Pricebook2.IsStandard <> TRUE

This seemed to work!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.