2

I am a certified admin and I am just beginning to learn code. I am currently trying to update several Order records to add a new Order Item and update the status on each record. My code worked in our sandbox but not in our production instance.

This is the error message I am receiving:

System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, Price Book Not Set on Order: []

This is my code so far:

 List<Order> allOrders = [
    SELECT Id,Legacy_DataSource__c
    FROM Order
    WHERE Id Not IN(                                                     
        SELECT OrderId                                                                  
        FROM OrderItem
    )
        AND StatusCode = 'D' 
    ];

    PriceBook2 pb2Standard = [
        select Id 
        from Pricebook2 
        where isStandard=true
    ];

    Id standardPriceBookId = pb2Standard.Id;

    PricebookEntry pbe = [ 
        SELECT Id,Product2Id,Pricebook2Id,UnitPrice 
        FROM PricebookEntry 
        WHERE Pricebook2Id = :standardPriceBookId 
            AND isActive = true
            AND ProductCode = 'Kit'
            LIMIT 1
    ];

    for(Order currentOrder : allOrders){
        if(currentOrder.Legacy_DataSource__c != null){
            Boolean result = currentOrder.Legacy_DataSource__c.contains('Warehouse');

        if(result == TRUE){                                                                 
            system.debug(currentOrder.Id); 

            UseStandardPrice = false;
            OrderItem myItem = new OrderItem();
            myItem.OrderId = currentOrder.Id;
            myItem.PricebookEntryId = pbe.Id;                   
            myItem.Quantity = 1;
            myItem.UnitPrice = pbe.UnitPrice;
            insert myItem;

            currentOrder.Status = 'Shipped';
            update currentOrder;

        } else {
         system.debug('Not from database'); 
        }
    }
}
  • Does your PricebookEntry pbe variable has a record? Can you confirm and check in developer console that your query SELECT Id,Product2Id,Pricebook2Id,UnitPrice FROM PricebookEntry WHERE Pricebook2Id = :standardPriceBookId AND isActive = true AND ProductCode = 'Kit' LIMIT 1 gives a record? – A-d Sep 15 '14 at 22:21
  • 1
    where do you set pricebook2Id on Order? This is a required field – cropredy Sep 16 '14 at 0:10
4

As @crop1645 is getting at, you must first make sure that the Order on which you are operating has a Pricebook associated with it before you can add any Products to it as OrderItems. It is possible to have an Order that does not have a Pricebook associated to it since the Pricebook is selected the first time the user adds a Product to the Order. I suspect that the Order that is failing for you does not have a Pricebook associated with it yet.

The Pricebook that is on the Order must be the same one that the OrderItems' PricebookEntry fields use as well. If you know that the user will have always set a Pricebook on the Order before using your page then you can use the Pricebook2Id field on the Order directly, e.g.:

// Add Pricebook2Id to query
List<Order> allOrders = [
    SELECT Id, Legacy_DataSource__c, Pricebook2Id
    FROM Order
    WHERE Id Not IN(                                                     
        SELECT OrderId                                                                  
        FROM OrderItem
    )
    AND StatusCode = 'D' 
];

You need to keep a Map of Pricebook2Id to PricebookEntry so that during the loop you can retrieve the desired PricebookEntry.

Set<Id> pbIds = new Set<Id>();
for (Order o : allOrders) {
     if (o.Pricebook2Id != null) {
          pbIds.add(o.Pricebook2Id);
     }
}

List<PricebookEntry> pbes = [ 
    SELECT Id,Product2Id,Pricebook2Id,UnitPrice 
    FROM PricebookEntry 
    WHERE Pricebook2Id In :pbIds
];

Map<Id, PricebookEntry> pbeMap = new Map<Id, PricebookEntry>();
for (PricebookEntry : pb : pbes) {
     pbeMap.put(pb.Pricebook2Id, pb);
}

 // then in your loop...
PricebookEntry pricebookEntry = pbeMap.get(currentOrder.Pricebook2Id);
myItem.PricebookEntryId = pricebookEntry.Id;

However, if you know that you always want the Pricebook to be set on the Order by your code or only if it hasn't been set and you always want it to be the standard one then you must code that.

// Include the Pricebook2Id
List<Order> allOrders = [
    SELECT Id, Legacy_DataSource__c, Pricebook2Id
    FROM Order
    WHERE Id Not IN(                                                     
        SELECT OrderId                                                                  
        FROM OrderItem
    )
    AND StatusCode = 'D' 
];

//.... other code to get standard pricebookId ....

// Before processing the Orders, ensure they all have the standard pricebook.
List<Order> ordersToUpdate = new List<Order>();
for (Order o : allOrders) {
    if (o.Pricebook2Id == null) {
        o.Pricebook2Id = standardPriceBookId;
        ordersToUpdate.add(o);
    } else if (o.Pricebook2Id != standardPriceBookId) {
        // handle this error condition somehow 
        // possibly remove the Order from the list "allOrders"
    }
}
update ordersToUpdate;

Since you are always adding a PricebookEntry from the standard pricebook the above pre-processing code must check to make sure that the Pricebook2Id of the Order is the standard one.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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