1

I am trying bulkify the trigger below. The ERAPayer field is a text field for entering an acccountnumber. What the trigger is doing is on insert of a new payerconfig record, when ERAPayer field is not null, validate that the ERAPayer value entered has a recordtype of 'ERA' for that account. If not then throw the error. Problem I am having (with the bulkified version) is eventhough I have recordtype of ERA for the account, which I am using for the new record, the validation fails when it should pass.

Here is the original code:

trigger PTCValidateERAPayerID on PayerConfiguration__c (before insert, before update) 
{

// NOT Batch-safe

Integer cnt = 0;
Account eraPayer;

for (PayerConfiguration__c ptc : Trigger.new)
{ 
if (ptc.ERAPayerID__c <> null)
{ 
try
{
eraPayer = [select Id from Account where Name = :ptc.ERAPayerID__c limit 1];
}
catch (Exception e)
{
//ptc.ERAPayerID__c.addError('Payer does not exist');
continue;
}

cnt = 
[
select count() from PayerConfiguration__c 
where Account__c = :eraPayer.Id 
and TransTypeCode__c = 'ERA'
];
if (cnt == 0)
{
ptc.ERAPayerID__c.addError('Payer does not have ERA Transaction Type ' + ptc.ERAPayerID__c);
}
}
}
}

Here is what I have done to try to bulkify:

trigger PTCValidateERART on PayerConfiguration__c (before insert, before update) 
{

    Set<string>existacct = new Set<String>();
    Map<Id, Integer> ERAmap = new Map<Id, Integer>();

    Id acctId;
    Integer cnt;

    List<RecordType> RT =[Select Id, Name from RecordType Where Name = 'Payer' and sObjectType= 'Account'];

    List<Account> accs =[Select id, AccountNumber from Account where recordtypeid in : RT];

    List<PayerConfiguration__c> pclist = [Select Id, Account__c, ERAPayerId__c From PayerConfiguration__c where Account__c in :accs];

    for(Account act : accs)

       if(act.AccountNumber == null)

       {}

       else {

       existacct.add(act.AccountNumber);

       AggregateResult[] groupedResults = [SELECT Account__c, count(Name)
                                        FROM   PayerConfiguration__c
                                        WHERE  TransTypeCode__c = 'ERA'
                                        AND    Account__r.AccountNumber in: existacct
                                        GROUP BY Account__c];

    for (AggregateResult ar : groupedResults)
    {
        acctId = (ID) ar.get('Account__c');
        cnt = (Integer) ar.get('expr0');
        ERAmap.put(acctId,cnt);
    }        


           for (PayerConfiguration__c pc : Trigger.new) {

              for(PayerConfiguration__c pc0: pclist)
    { 
        if (pc.ERAPayerID__c != null  && !(ERAmap.containskey(pc.account__c)) ) 
            //&& pc.TransTypeCode__c != 'ERA'
        {
            pc.ERAPayerID__c.addError(pc.ERAPayerID__c + 'must have ERA Payer Configuration Record');
        }
    }
       }    
       }

}  
1
  • why is //&& pc.TransTypeCode__c != 'ERA' commented out? Seems like this code is just going to add errors to everything
    – NSjonas
    May 29, 2015 at 18:44

1 Answer 1

0

First let me say that SF treats text strings and Ids as being interchangeable, so you could presumably have the AccountID as a lookup that gets converted to a text string rather than have it entered manually if that's what you're doing. It appears from your code though that AccountNumber is the text string you're referring to? If so, that's what I've assumed.

I would approach this trigger quite differently than you have in order to simplify it and reduce the number of queries. First, since this trigger fires on PayerConfiguration__c, it appears from this query:

List<PayerConfiguration__c> pclist = [Select Id, Account__c, ERAPayerId__c From PayerConfiguration__c where Account__c in :accs];

that trigger.new will already contain the accountId and ERAPayerId__c. From other code, it looks like trigger.new also contains TransTypeCode__c.

So if you have all of that, it appears to me there's no need to run the following query when you can map it from your other results:

AggregateResult[] groupedResults = [SELECT Account__c, count(Name)
                                    FROM   PayerConfiguration__c
                                    WHERE  TransTypeCode__c = 'ERA'
                                    AND    Account__r.AccountNumber in: existacct
                                    GROUP BY Account__c];

It seems that your trigger should look more like the following:

trigger PTCValidateERART on PayerConfiguration__c (before insert, before update) 
{

Set<string>existacct = new Set<String>();
Map<Id, string> ERAmap = new Map<Id, string>();
Map<Id, string> TRNSmap = new Map<Id, string>();
list<PayerConfiguration__c>pcLst = new list<PayerConfiguration__c>(); 

for(pc:trigger.New){
   if(pc.ERAPayerId__c != null){
      PayerConfiguration__c pcc = new PayerConfiguration__c ();

      if(pc.Account__c.isEmpty == false){ 
         pcc.Account__c = pc.Account__c;
         existacct.add(pc.Account__c)
      }   
      pcc.ERAPayerId__c = pc.ERAPayerId__c;
      pcc.TransTypeCode__c = pc.TransTypeCode__c;

      TRANSmap.put(pcc.ERAPayerId__c, TransTypeCode__c);
      ERAmap.put(pcc.ERAPayerId__c, pcc.Account__c,);


   } else{
      pc.ERAPayerID__c.addError(pc.ERAPayerID__c + 'must have ERA Payer Configuration Record');  
      // remove this if the above field isn't in PayerConfiguration__c as it appears to be from your code
      // and add it as a subquery to the code below if it isn't.
   }
}

map<Id,PayerConfiguration__c> pcMap = new map([Select Id, Account__c, ERAPayerId__c, TransTypeCode__c, (Select Id, AccountNumber, RecordTypeID, RecordType.Name FROM Accounts) From PayerConfiguration__c where Account__c in :existacct]);
// The above returns everything in one query. 

// Now do the rest of your validation

for (Id pcId : pcMap.keyset()) {
   PayerConfiguration__c pcon = pcMap.get(pcId);

   // the pcon reference will have child lists for your account subqueries
   // they will not be null, but they could be empty lists

   List<Account> AcctLst = pcMap.Accounts;

      for (Account a : AcctLst) {
         account ac = new account(Id=a.Id, a.AccountNumber, a.RecordTypeID, a.RecordType.Name, );
         ac.ERAPayerId__c= pcon.ERAPayerID__c;

         // test here to see if values are same as in maps above
         if((pcon.ERAPayerId__c == ac.Id && TRANSmap.get(pcon.ERAPayerId__c) == 'ERA') && ((ERAmap.contains(ac.Id)) && ERAmap.get(ac.Id).account__C != ac.account__C)){
            // first part checks to make certain AcctID is same & correct Record TypeID.
            // 2nd part first checks to see if in map, then compares values

             trigger.newmap.put(pcon.Id,ERAPayerID__c).addError(pc.ERAPayerID__c + 'must have ERA Payer Configuration Record');

         }

      }

}   

} 

// code is untested and for guidance. Add debug statements as appropriate.

You must log in to answer this question.

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