1

I'm trying to populate a field in every opportunity that is created that has a value based on the account that it's a part of. Both the account field and the opportunity field are picklists, as there are circumstances where a manager may need to modify one of these fields in the future. My trigger only references the insert, not update, because there are also circumstances where the account field could change but we want the opportunity field to stay the same. So with all of this in mind, I'm getting the error specified in the subject line.

trigger BusinessDivisionOpportunity on Opportunity (before insert) 
{    
    Map<String, String> myPickListMap = Constants.businessDivisionMap;

    for (Opportunity o : Trigger.new)
    {
            o.Business_Division__c = myPickListMap.get(o.AccountId).Business_Division__c;
    } 

}

The map in this instance is calling a map that we have defined in a separate class. The error is being thrown on the final line of code. I'm not really sure how else to write this trigger without this error being thrown, however.

Thanks in advance for any help you all can give!

1
  • If your Constants.businessDivisionMap does contain a map of account ids to picklist values then you should just remove the ".Business_Division__c" part of your last statement as the map is already returning the picklist value.
    – Keith C
    Apr 23, 2014 at 18:40

4 Answers 4

3

The error message indicates that you attempted to use a 'dot' to retrieve a value that doesn't exist.

trigger BusinessDivisionOpportunity on Opportunity (before insert) 
{    
    Map<String, String> myPickListMap = Constants.businessDivisionMap;

    for (Opportunity o : Trigger.new)
    {
            // the .get() from the map will retrieve the value associated with the key
            // which is your accountId. The value returned (based on the way your map 
            // is defined (<string, string>) will be a string value.
            // So, your code is attempting to retrieve a field named Business_Division__c
            // from a string, which can't be done.
            // o.Business_Division__c = myPickListMap.get(o.AccountId).Business_Division__c;

            // try this - it presumes that the value in the map is the "business division"
            o.Business_Division__c = myPickListMap.get(o.AccountId);
    } 

}

Update

It seems that what you're trying to accomplish is to just copy some data from the parent Account onto the Opportunity. This can most easily and simply be accomplished using a workflow rule that executes on new Opportunity records and performs a field update on the record using the relationship to the parent Account.

Unless there's some complicated logic in the Constants class for determination of those business division values, a workflow field update might be a far simpler solution. Edit: It's not simpler in this case. A second answer added with caveats.

Alternatively, if this is the scenario (copy the field data from the parent account) that you are trying to accomplish must be done via trigger - my implementation would begin like this:

trigger BusinessDivisionOpportunity on Opportunity (before insert) {

    // collect the account ID values from these opportunities
    Set<Id> relatedAccountIdSet = new Set<Id>();

    for (Opportunity o : Trigger.new) {
        if (o.AccountId != null) {
            relatedAccountIdSet.add(o.AccountId);
        }
    }

    // query the Account details
    Map<Id, Account> relatedAccountsMap = new Map<Id, Account>([SELECT Id
                                                                    , Business_Division__c
                                                                FROM Account
                                                                WHERE Id IN :relatedAccountIdSet]);

    // set the business division on the opportunity based on what's in the field on the account
    for (Opportunity o : Trigger.new) {

        if (o.AccountId == null) {
            continue; // skip to the next opportunity in the list
        }

        Account parentAccount = relatedAccountsMap.get(o.AccountId);
        o.Business_Division__c = parentAccount.Business_Division__c;
    } 

}
3
  • Thanks, this removes the error and allows me to run my test class - however the field is not being updated still. The map is just a string of values that are in the picklist. So I'm trying to lookup what the value of the field is for the account, and populate that value into the opportunity's field. So I don't know if AccountId is the correct field to call on in this code, I'm just trying to find the correct account that the opportunity is tied to.
    – grimsvotn
    Apr 23, 2014 at 18:47
  • Thanks Mark. This trigger does what I needed it to do. Thank you for the comments in the code as well - I'm still pretty new to Apex so understanding why each of these lines of code are important definitely helps a lot. On a somewhat related note, when you suggested using workflow rules, is it possible to create a workflow rule that updates the field for every possible value in that field? Business_Division__c has around 25 values, and I need to create something similar to this for a few other objects, so creating 100 workflow rules when four triggers would suffice seems the better option.
    – grimsvotn
    Apr 23, 2014 at 19:58
  • Good comments are always helpful, even if you're just describing the intended logic to yourself! A workflow rule & field update probably won't work for you in this scenario but I posted another answer with that option anyway. The trigger is probably your best bet.
    – Mark Pond
    Apr 23, 2014 at 20:29
2

Your problem is here:

myPickListMap.get(o.AccountId)

this returns a String and it looks like here you want it to be an Account in order to fetch the value of the account's business_division__c

Your map needs to be of type <ID,Account> and you'll need to populate this map with the values of the Oppo's Accounts as in:

Set<ID> aIdSet = new Set<ID> ();
for (Opportunity o : Trigger.new)
  if (o.accountId != null) aIdSet.add(o.accountId);
Map<ID,Account> aIdToAccountMap = 
       new Map<ID,Account> ([select id, business_division__c from Account 
                                where id IN :aIdSet]);

for (Opportunity o : Trigger.new)
   o.Business_Division__c = o.AccountId != null 
         ? aIdToAccountMap.get(o.AccountId).Business_Division__c 
         : null;
3
  • That's what I'm trying to do, I'm not quite there yet. When you wrote aIdSet=o.accountId; did you mean aIdSet.add(o.accountId); ? Trying the latter, I am getting a new error when I try to run my test class: System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, BusinessDivisionOpportunity: execution of BeforeInsert caused by: System.NullPointerException: Attempt to de-reference a null object Trigger.BusinessDivisionOpportunity: line 14, column 1: []
    – grimsvotn
    Apr 23, 2014 at 19:03
  • @grimsvotn Use a null check to avoid null pointer if(aIdToAccountMap.get(o.AccountId)!=null) { o.Business_Division__c = aIdToAccountMap.get(o.AccountId).Business_Division__c; } Apr 23, 2014 at 19:12
  • thanks -- fixed (too-hastily-written) code to include null checks and the missing add() method
    – cropredy
    Apr 23, 2014 at 19:36
2

Creating a separate answer for the idea of using a workflow field update.

Huge caveat: a field update action targeting a picklist field does not allow for the copying of a value from another object into that field. In this example, the Business_Division__c field on the Opportunity is a Text(255) type and the field on the Account object is a single-select picklist. A multi-select picklist would show comma delimited values on the Opportunity.

While implementing this I also added a formula field to the Opportunity to reference the value in the parent Account Business_Division__c field as another possible option : TEXT(Account.Business_Division__c)

My picklist values on the account are [North, South, East, West] - the parent account is an East division.

Workflow Rule:

enter image description here

Field Update:

enter image description here

Before Save:

enter image description here

After Save:

enter image description here

0

Change

o.Business_Division__c = myPickListMap.get(o.AccountId).Business_Division__c;

to

o.Business_Division__c = myPickListMap.get(o.AccountId);

Your map is a Map of Strings, and you are treating it as a Map of Objects.

You must log in to answer this question.

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