1

I have some code that is intended to work like the following: When the zipcode field on Accounts is inserted or updated, the triggers looks up whether the zip code is in a field called name on a custom object called DMA_Value__c. If the value is there the DMA_Value__c field on the DMA_Value__c object is returned to a field called DMA__c on the Opportunity object. My code is throwing a Invalide foreign key relationship for the line where I have Account.Opportunity. I'm guessing this means I need a map but I'm not sure where it should go. If your answer provides code could you please add an explanation so that I understand this better in the future? Please see the code below.

trigger UpdateDMAAccount on Account (before insert, before update) {
   Set<String> BillingPostalCodes = new Set<String>();
for(Account a : trigger.new){
    if(a.BillingPostalCode != null){
        BillingPostalCodes.add(a.BillingPostalCode);
    }
}
if(BillingPostalCodes.size() > 0){
    //create Map of custom object records with Name (BillingPostalCode) as key
    Map<String,DMA_Value__c> validBillingPostalCode = new Map<String,DMA_Value__c>();
    for(DMA_Value__c obj : [SELECT Id, Name, DMA_Value__c FROM DMA_Value__c WHERE Name IN :BillingPostalCodes]){
        validBillingPostalCode.put(obj.Name,obj);
    }
    for(Account a : trigger.new){
        if((Trigger.isInsert || trigger.oldMap.get(a.Id).BillingPostalCode != a.BillingPostalCode) && validBillingPostalCode.containsKey(a.BillingPostalCode)){

            a.opportunity.DMA__c = validBillingPostalCode.get(a.BillingPostalCode).DMA_Value__c;
        }
        else if(trigger.oldMap.get(a.Id).BillingPostalCode != a.BillingPostalCode && !validBillingPostalCode.containsKey(a.BillingPostalCode)){
            //blank value if new BillingPostalCode does not match a record in the Map
            a.Opportunity.DMA__c = null;
        }
    }
}
}
6
  • 1
    Is Account.Opportunity a custom lookup field on the account object? If so, first of all, it needs to be referenced with the proper name, which can be found by going to the setup page for that field. It is probably Opportunity__c, so the relationship is Opportunity__r.DMA__c. Commented Mar 9, 2015 at 16:30
  • 2
    The other issue is that you can't update a related object just by referencing the lookup. You'll need to actually query the opportunity object itself, pull a list, and update the record there. I can help you with the apex for that, but please first confirm that you are updating an opportunity record related to the account, and not a field on the account itself. Commented Mar 9, 2015 at 16:30
  • @MattBritton Thank you for your response. The field I'm trying to update is DMA__c on the Opportunity object. I had Account.Opportunity.DMA__c because I was trying to create a relationship between the Account and Opportunity kind of like in Visualforce. I am new to coding and everytime I think I understand, I run into a snag. Commented Mar 9, 2015 at 16:38
  • One of the issues I see that you're likely to have with this trigger is that your zip code strings will not be unique. Having them in a map with the account ID and zip code will assure their uniqueness. You can then get values in the map to collect all the zips or get the keyset to get all the account Id's. In any case, I would not use the zip code as the map key for DMA__c.
    – crmprogdev
    Commented Mar 9, 2015 at 16:45
  • 1
    @MattBritton You don't need to query for records if you already have their Id. Just construct a new one with that Id and you can update it.
    – Adrian Larson
    Commented Mar 9, 2015 at 16:58

1 Answer 1

1

Typically Opportunity lives under Account, but you have it the other way around. If Account.Opportunity__c is a field, your solution is fairly simple:

List<Opportunity> opportunities = new List<Opportunity>();
for (Account newAccount : accountsToActOn)
{
    opportunities.add(new Opportunity(Id=newAccount.Opportunity__c, DMA__c=dmaValue);
}

This seems unlikely. What is more likely the case is that you have to group child Opportunity records by their parent Account.

Map<Id, List<Opportunity>> accountIdToOpportunities = new Map<Id, List<Opportunity>>();
for (Opportunity childOpportunity : [
    SELECT Id, AccountId FROM Opportunity
    WHERE AccountId IN :trigger.new])
{
    if (!accountIdToOpportunities.containsKey(childOpportunity.AccountId)
        accountIdToOpportunities.put(childOpportunity.AccountId, new List<Opportunity>();
    accountIdToOpportunities.get(childOpportunity.AccountId).add(childOopportunity);
}

Now you can loop through the children for each account meeting your criteria. You didn't specify the type of field for DMA__c so I will assume String will work.

List<Opportunity> opportunitiesToUpdate = new List<Opportunity>();
for (Id accountId : accountIdToOpportunities)
{
    Account a = trigger.newMap.get(accountId);
    if (validBillingPostalCode.containsKey(a.BillingPostalCode))
    { // fill out your condition as needed
        String dmaValue = validBillingPostalCode.get(a.BillingPostalCode).DMA_Value__c;
        for (Opportunity child : accountIdToOpportunities.get(accountId))
        {
            child.DMA__c = dmaValue;
            opportunitiesToUpdate.add(child);
        }
    }
}
update opportunitiesToUpdate;

You must log in to answer this question.

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