1

We have multi-currency enabled and custom pricebooks. I have a before insert class that automatically sets the pricebook when an Opportunity is created that works well. When a user changes the currency on the Opportunity the pricebook is removed by Salesforce API per the standard functionality.

So I wrote a before update class to check if the currency changes and then set the pricebook back. The problem is Salesforce still removes the pricebook after the the record is saved and reloads in the UI. Checking debug logs, before the process, during the process, after the process, the pricebook2id is set all through my filters and setting the pricebook.

If you save/edit the record after changing the currency the pricebook gets sets so I'm pretty sure my logic is right.

My question is do you know when Salesforce actually removes the Pricebook2Id when the currency is changed on an Opportunity? If the before update doesn't work I suppose I have to move it to after update but then I'd have to do another update on the record to update it after instead of setting it before. That feels like a wrong way to do it.

Example:

public static void filterupdate(Map<Id, Opportunity> oldMap, Map<Id, Opportunity> newMap)
{
    List<Opportunity> oppsToUpdate = new List<Opportunity>();   

    // Check if the fields changed
    for(Opportunity oppy : newMap.values())
    {
        if( 
            oppy.Pricebook2Id       != oldMap.get(oppy.Id).Pricebook2Id ||
            oppy.CurrencyISOCode    != oldMap.get(oppy.Id).CurrencyISOCode ||
            oppy.Pricebook2id       == null
        )
            {
                oppsToUpdate.add(oppy);
            }
    }
    setPricebook(oppsToUpdate);
}

public static void setPricebook(List<Opportunity> newList)
{
    Id pb = [
        SELECT      Id 
        FROM        Pricebook2 
        WHERE       Name = 'NPD Price Book'
        ORDER BY    Id DESC
        LIMIT       1].Id;
    if(pb != null)
    {
        for(Opportunity oppy : newList)
        {
            oppy.Pricebook2id = pb;
        }
    }
} 
4
  • N.B. a normal pattern would be one Pricebook w/ multiple currencies. SKUs being identical but offered in different prices
    – cropredy
    Dec 7, 2017 at 5:52
  • Does that solve that the pricebook would get removed? I'm trying to automate putting the pricebook back onto the Opportunity record. Dec 7, 2017 at 16:55
  • do you already have OpportunityLineItems when you try and change the currency? If yes, they have to be deleted, then Opportunity currency changed, then re-added
    – cropredy
    Dec 7, 2017 at 23:49
  • I did not. I figured out that I needed to do an after update method. I'll post new code. Dec 8, 2017 at 20:45

1 Answer 1

2

Salesforce removes the Pricebook2Id if the currency changes sometime after the before update actions take place. So to populate the Pricebook2Id automatically when a record is changed you have to do it in an after update method.

This could be a problem if you do not take into account recursion as you could be stuck in a loop but if your trigger takes that into account you can update the same record again safely.

Example finished code:

public static void filterupdate(Map<Id, Opportunity> oldMap, Map<Id, Opportunity> newMap)
{
    List<Opportunity> oppsToUpdate = new List<Opportunity>();

    // Check if the fields changed
    for(Opportunity oppy : newMap.values())
    {
        if( 
            oppy.CurrencyISOCode != oldMap.get(oppy.Id).CurrencyISOCode ||
            oppy.Pricebook2Id == null
        )
            {
                oppsToUpdate.add(oppy);
            }
    }
    setPricebookUpdate(oppsToUpdate);
}

public static void setPricebookUpdate(List<Opportunity> oppsToUpdate)
{
    List<Opportunity> oppyUpdate = new List<Opportunity>();
    Id pb = getPricebook();

    if(pb != null)
    {
        for(Opportunity oppy : oppsToUpdate)
        {
            Opportunity oppyU = new Opportunity(Id = oppy.Id);
            oppyU.Pricebook2Id = pb;
            oppyUpdate.add(oppyU);
        }
    }

    update oppyUpdate;
} 
1
  • nice addition to the corpus of knowledge on the community
    – cropredy
    Dec 9, 2017 at 6:17

You must log in to answer this question.

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