2

I have a custom object lookup Wholesaler__c in Account Object. my requirement is to create a trigger, which would create a custom object record Billing__c when an Opportunity is created. Billing__c should take inputs from Opportunity

error thrown is:

"Apex trigger CreateBilling caused an unexpected exception, contact your administrator: CreateBilling: execution of AfterInsert caused by: System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: Account.Wholesaler__r: Trigger.CreateBilling: line 12, column 1"

please help

Trigger written is:

trigger CreateBilling on Opportunity (after insert, after update) {
    billing__c bill = new billing__c();

    if(Trigger.isInsert == true){
        for(Opportunity opp: Trigger.new){
            if(Opp.StageName == 'Closed Won'){
                bill.Name='bill ' +opp.Name;
                bill.Opportunity__c=opp.id;
                bill.Dealer__c= opp.AccountId;
              //  Id accid =opp.AccountId;
                wholesaler__c wholesalerName = new wholesaler__c();
                wholesalerName= [SELECT Account.Wholesaler__c FROM account where id =:opp.AccountId].wholesaler__r;
                bill.Wholesaler__c= wholesalerName.name;
                system.debug('No errors observed with billing addition');
                insert bill;
            }
        }
    }

}
6
  • 1
    update your query [SELECT Name, wholesaler__c, Account.Wholesaler__c FROM account where id =:opp.AccountId].wholesaler__c
    – Ratan Paul
    Commented Jan 27, 2016 at 5:28
  • @arun Did you understand why you were facing this error? Commented Jan 27, 2016 at 5:34
  • @Salesforcesmarty: i thought i understood. so modified my query. but eventhen i couldnt resolve the issue. so i guess, my understanding is wrong
    – arun
    Commented Jan 27, 2016 at 5:40
  • Have you tried my solution? Commented Jan 27, 2016 at 5:40
  • @CasparHarmer: this query worked. however, please help me understand, why are we fetching wholesaler__c and assigning it to account[] ? why cant it be wholesaler ?
    – arun
    Commented Jan 27, 2016 at 5:43

2 Answers 2

0

First, you have SOQL in a for loop - which is something you will need to fix.

Aside from that, I think you are trying to get the wholesaler id and put it on the bill. For that, you don't need wholesaler name, just the wholesaler__c field on Account. Try this:

Account[] accts = [SELECT Account.Wholesaler__c FROM account where id =:opp.AccountId]
bill.Wholesaler__c= accts[0].Wholesaler__c;

The above can replace these three lines:

wholesaler__c wholesalerName = new wholesaler__c();
wholesalerName= [SELECT Account.Wholesaler__c FROM account where id =:opp.AccountId].wholesaler__r;
bill.Wholesaler__c= wholesalerName.name;

Going back to the SOQL in the for loop, to remove this (a process called bulkifying the trigger), you would:

  • Loop through all the Opportunities and collect all the account ids in a set.
  • Query all Accounts in this set into a list.
  • Put each Account into a map, indexed by Opportunity id.
  • Loop through the Opportunities again, creating bill records.
  • Get the indexed Account for each Opportunity and put the wholesaler name on the Bill__c.
  • Add each newly created Bill__c to a List<Bill__c> of bills.

Finally insert these new bills.

2

There were so many issues with your code

  • SOQL Query inside for loop
  • DML Statement inside for loop
  • You code was not bulkified for queries
  • You were initialising your bill variable at the second line, it will use the same bill reference if multiple opportunities are updated together, resulting in an error.
  • I don't know why you were initialising a wholesale object, when you can directly query the name

Compare your code with this below optimised code:

trigger CreateBilling on Opportunity (after insert, after update) {

    Billing__c bill;
    List<Billing__c> billingList = new List<Billing__c>();
    Set<id> accntSet = new Set<id>();
    Map<ID,String> wholesalerMap = new Map<ID,String>();

    if(Trigger.isInsert){
        for(Opportunity opp: Trigger.new){
            if(Opp.StageName == 'Closed Won'){
                accntSet.add(opp.AccountId);
            }
        }
        for(Account acc : [SELECT Wholesaler__r.Name FROM account where id =:accntSet Limit :accntSet.size()])
            wholesalerMap.put(acc.id, acc.Wholesaler__r.Name);

        for(Opportunity opp: Trigger.new){
            if(Opp.StageName == 'Closed Won'){
                bill = new billing__c();
                bill.Name='bill ' +opp.Name;
                bill.Opportunity__c=opp.id;
                bill.Dealer__c= opp.AccountId;

                bill.Wholesaler__c= wholesalerMap.get(opp.AccountId);
                billingList.add(bill);
            }
        }

        if(!billingList.isEmpty())
            insert billingList;
    }
}

Hope it helps to answer your question.

You must log in to answer this question.

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