0

I have a batch process to update Accounts with address info from the Cust_Address__c object. I use a Junc_Account_Address__c object as a junction. How do I loop through the accounts to update the addresses. Currently I get the error Loop must iterate over collection:Account

global class AddressManager implements 
    Database.Batchable<sObject>, Database.Stateful {

    // instance member to retain state across transactions
    global Integer recordsProcessed = 0;
    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator(
            'SELECT Id, Start_Date__c, End_Date__c, Account__c, Cust_Address__c, Recordtype' +
            'FROM Junc_Account_Address__c' + 
            'WHERE Start_Date__c <= TODAY AND End_Date__c >= TODAY'  
        );
    }
    global void execute(Database.BatchableContext bc, List<Junc_Account_Address__c> scope){
        // process each batch of records
        List<Account> accountsToUpdate = new List<Account>();
        for (Junc_Account_Address__c ac : scope) {
            for (Account acc : ac.Account__r) {
                acc.BillingStreet = ac.Cust_Address__r.BillingStreet__c;
                acc.BillingPostalCode = ac.Cust_Address__r.BillingPostalCode__c;
                acc.BillingCity = ac.Cust_Address__r.BillingCity__c;
                acc.BillingState = ac.Cust_Address__r.BillingState__c;
                // add account to list to be updated
                accountsToUpdate.add(acc);
                // increment the instance member counter
                recordsProcessed = recordsProcessed + 1;
            }
        }
        update accountsToUpdate;
    }    
    global void finish(Database.BatchableContext bc){
        System.debug(recordsProcessed + ' records processed. Shazam!');
        AsyncApexJob job = [SELECT Id, Status, NumberOfErrors, 
            JobItemsProcessed,
            TotalJobItems, CreatedBy.Email
            FROM AsyncApexJob
            WHERE Id = :bc.getJobId()];
        // call some utility
    }    
}
  • Is there only one record for junction object Junc_Account_Address__c or it can be multiple? – rahul gawale Dec 12 '19 at 11:14
  • From which object you want to update information? – Rohit Mourya Dec 12 '19 at 11:14
  • 1
    As account is parent of Junc_Account_Address__c, ac.Account__r is not a list but a single record which you will never get in your query as you are not querying any field from an account object. And for loop work on collections only not a single record. see the line for (Account acc : ac.Account__r) { – rahul gawale Dec 12 '19 at 11:16
  • @rahulgawale it can be multiple since I will be using record types on Cust_Address – Thomas Dec 12 '19 at 11:39
  • 1
    @Thomas Don't you think copying data from Cust_Address__c to Account, you might end up with updating same Account multiple times. Since its a master detail relationship, one Account can be linked with many Addresses. – Rohit Mourya Dec 12 '19 at 13:24
1

Use __r child relationship query if in your Account object actually has a lookup field to Junc_Account_Address__c. The inner for loop below is not needed.

    for (Junc_Account_Address__c ac : scope) {
        for (Account acc : ac.Account__r) {
        }
    }

Also, since you are referencing some fields from the Cust_Address__c, you need to include them in your SOQL string. Otherwise you'll get the exception

"SObject row was retrieved via SOQL without querying the requested field"

    SELECT Id, Start_Date__c, End_Date__c, Account__c, 
        Cust_Address__r.BillingStreet__c, 
        Cust_Address__r.BillingPostalCode__c, 
        Cust_Address__r.BillingCity__c, 
        Cust_Address__r.BillingState__c, 
        Recordtype
    FROM Junc_Account_Address__c
    WHERE Start_Date__c <= TODAY AND End_Date__c >= TODAY
    global void execute(Database.BatchableContext bc, List<Junc_Account_Address__c> scope){
        // process each batch of records
        List<Account> accountsToUpdate = new List<Account>();
        for (Junc_Account_Address__c ac : scope) {
            Account acc = new Account (
                Id = ac.Account__c,
                BillingStreet = ac.Cust_Address__r.BillingStreet__c,
                BillingPostalCode = ac.Cust_Address__r.BillingPostalCode__c,
                BillingCity = ac.Cust_Address__r.BillingCity__c,
                BillingState = ac.Cust_Address__r.BillingState__c
            );
            // add account to list to be updated
            accountsToUpdate.add(acc);
            // increment the instance member counter
            recordsProcessed = recordsProcessed + 1;
        }
        update accountsToUpdate;
    }
| improve this answer | |

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.