1

I am trying to set a boolean to true upon insert based on first this logic:

if((pr.recordtypeid == '012g0000000D63fAAC' || pr.recordtypeid == '012g0000000D63iAAC' || pr.recordtypeid == '012g0000000D63gAAC' || pr.recordtypeid == '012g0000000D63kAAC' ||
   pr.recordtypeid == '012g0000000D63jAAC' || pr.recordtypeid == '012g0000000D63TAAS' || pr.recordtypeid == '012g0000000D63RAAS' || pr.recordtypeid == '012g0000000D63UAAS') 
   &&  pr.route_code__c == 'H - HCFA Print Image (HCFA to NSF)' && pr.Transaction_Format__c== 'S - NSF 3.01' )

and that a record of the same account that is of Emdeon One - Client, '012g0000000D63W' that has print image__c = true.

I am not sure how compose this logic but here is what I have and am getting

AfterInsert caused by: System.FinalException: Record is read-only: Trigger.eOneProdConfigUpdatePrintImage: line 58, column 1

code

trigger eOneProdConfigUpdatePrintImage on Product_Configuration__c (after insert) {

/*RecTypes
"012g0000000D63eAAC","275"
"012g0000000D63fAAC","837"
"012g0000000D63gAAC","837D"
"012g0000000D63hAAC","837DW"
"012g0000000D63iAAC","837I"
"012g0000000D63jAAC","837IW"
"012g0000000D63kAAC","837W"
"012g0000000D63RAAS","CSI"
"012g0000000D63SAAS","EDGE"
"012g0000000D63TAAS","ELG"
"012g0000000D63VAAS","Emdeon One - Channel Partner"
"012g0000000D63WAAS","Emdeon One - Client"
"012g0000000D63XAAS","Emdeon One - Data"
"012g0000000D63YAAS","Emdeon One - Fiscal Intermediary"
"012g0000000D63ZAAS","Emdeon One - Payer"
"012g0000000D63UAAS","ERA"
"012g0000000D63aAAC","Payment"
"012g0000000D63bAAC","Portal Services"
"012g0000000D63cAAC","RFI"
"012g0000000D63dAAC","RFR"*/

set<id> prid = new set<id>();
set<id> acctids = new set<id>();
Map<String, Integer> configmap = new Map<String, Integer>();
List<product_configuration__c>pr2upt = new list<product_configuration__c>();

Integer cnt;
Id acctid;

List<Product_Configuration__c> prodlist = [Select Id, Route_Code__c, ES_Format__c, Account__c from product_configuration__c where recordtypeid = '012g0000000D63W'];

For(product_configuration__c pr: trigger.new)  {

if((pr.recordtypeid == '012g0000000D63fAAC' || pr.recordtypeid == '012g0000000D63iAAC' || pr.recordtypeid == '012g0000000D63gAAC' || pr.recordtypeid == '012g0000000D63kAAC' ||
   pr.recordtypeid == '012g0000000D63jAAC' || pr.recordtypeid == '012g0000000D63TAAS' || pr.recordtypeid == '012g0000000D63RAAS' || pr.recordtypeid == '012g0000000D63UAAS') 
   &&  pr.route_code__c == 'H - HCFA Print Image (HCFA to NSF)' && pr.Transaction_Format__c== 'S - NSF 3.01' ) {

prid.add(pr.Id); 
acctids.add(pr.Account__c);
pr2upt.add(pr);

AggregateResult[] groupedResults = [Select Account__c, count(Name) From Product_Configuration__c where Account__c in : acctids Group by Account__c];  

For(AggregateResult ar : groupedresults) {

cnt = (Integer) ar.get('expr0');
acctid = (Id) ar.get('Account__c');
configmap.put(acctid, cnt);  

For(Product_Configuration__c emd1 : prodlist) {


if(emd1.Print_Image__c = true && (configmap.containskey(acctid)) )   {

pr.Print_Image__c = true;



                         }
                       }


                   } 
                 }

              }
              update pr2upt;

            } 
Vamsi Krishna Gosu
  • 10,464
  • 5
  • 32
  • 49
Zane
  • 21
  • 2

1 Answers1

0

I was too tired to post last night, but in an after trigger, trigger.new is read only. The line pr.Print_Image__c = true; was trying to change a value in trigger.new, thus the cause of your error message.

If you'd have ended this loop:

For(product_configuration__c pr: trigger.new)  {` 

after the line with pr2upt.add(pr);

Then started a new For loop based on the list pr2upt after the line:

configmap.put(acctid, cnt);

you could have kept things as an AfterUpdate trigger.

Regardless of whether this is executed as a BeforeInsert or an AfterInsert Trigger, there are things that to me, appear to need to be revised. One very important change that needs to be made is to prevent your trigger from automatically running queries that may not be necessary every time the trigger runs.

The following loop

For(AggregateResult ar : groupedresults) { 

needs to be closed after configmap.put(acctid, cnt);.

Once you do that, if done as an After Trigger, the following line could then become:

For(Product_Configuration__c emd1 : pr2upt) {

There's no need to loop through your entire product list when you've already filtered out the Id's of the products that need updated! This would easily be facilitated had initialized your query at the start of your trigger as a map like this:

map<Id,Product_Configuration__c>plmap = new map([Select Id, Route_Code__c, ES_Format__c, Account__c from product_configuration__c where recordtypeid = '012g0000000D63W']);

You could then do something like this:

   if(plmap.get(emd1.Id).Print_Image__c = true && (configmap.containskey(emd1.Account__c)) )   {

      emd1.Print_Image__c = true;          

   }

As an AfterInsert, your trigger would like what's below. A BeforeInsert should look similar in terms of breaking it into separate loops with the AggregateResult in the middle (look at a debug log and you'll see what I mean) but you'd repeat the last loop using variables that still operate on trigger.new.

Here's the body of the code:

trigger eOneProdConfigUpdatePrintImage on Product_Configuration__c (after insert) {

set<id> prid = new set<id>();
set<id> acctids = new set<id>();
Map<String, Integer> configmap = new Map<String, Integer>();
List<product_configuration__c>pr2upt = new list<product_configuration__c>();
Id acctid;
AggregateResult[] groupedResults = new AggregateResult[];

map<Id,Product_Configuration__c>plmap = new map<Id,Product_Configuration__c>();

For(product_configuration__c pr: trigger.new)  {

   if((pr.recordtypeid == '012g0000000D63fAAC' || pr.recordtypeid == '012g0000000D63iAAC' || pr.recordtypeid == '012g0000000D63gAAC' || pr.recordtypeid == '012g0000000D63kAAC' ||
   pr.recordtypeid == '012g0000000D63jAAC' || pr.recordtypeid == '012g0000000D63TAAS' || pr.recordtypeid == '012g0000000D63RAAS' || pr.recordtypeid == '012g0000000D63UAAS') 
   &&  pr.route_code__c == 'H - HCFA Print Image (HCFA to NSF)' && pr.Transaction_Format__c== 'S - NSF 3.01' ) {

      prid.add(pr.Id); 
      acctids.add(pr.Account__c);
      pr2upt.add(pr);
   } // end if(pr.recordtypeid ==
} // end For(product_configuration__c pr: trigger.new)

if(acctids.isEmpty() == false){ 
   // no need for the trigger to go any further if the acctids isEmpty

   plmap = ([Select Id, Route_Code__c, ES_Format__c, Account__c from product_configuration__c where recordtypeid = '012g0000000D63W']);
   // no need to run this query until you know it's necessary

   groupedResults = ([Select Account__c, count(Name) From Product_Configuration__c where Account__c in : acctids Group by Account__c]);

}

For(AggregateResult ar : groupedresults) {

      cnt = (Integer) ar.get('expr0');
      acctid = (Id) ar.get('Account__c');
      configmap.put(acctid, cnt);  
} // end For(AggregateResult ar : groupedresults)

For(Product_Configuration__c emd1 : pr2upt) {

   if(plmap.get(emd1.Id).Print_Image__c = true && (configmap.containskey(emd1.Account__c)) )   {
   // I strongly suspect the 2nd test is no longer necessary, but as I'm not familiar with your products, I wouldn't know for certain

      emd1.Print_Image__c = true;
   }

} // end For(Product_Configuration__c emd1 : pr2upt)

update pr2upt;

} // end trigger

Note: above code has not been tested.

crmprogdev
  • 40,955
  • 9
  • 58
  • 115
  • Thanks for posting on SF.SE. Please help the rest of the community by marking this answer as solving your question if it resolved your issue. – crmprogdev May 28 '15 at 13:41
  • I am not able to get the code to compile. My understanding is this function must be used with a query. I am talking specifically for where you have AggregateResult[] groupedResults = new AggregateResult[]; – Zane Jun 01 '15 at 19:46
  • That may have been a typo from copy/pasting, try using list<AggregateResult>groupedResults = new list<AggregateResult>();. It has to be declared outside of the if statement that follows, or it won't compile since the the list won't be recognized as having been declared when used later. – crmprogdev Jun 01 '15 at 20:05
  • I am now having an issue with the plmap is being generated as a list. Also, would this cause SOQL limit issues since it's in the for loop? I have tried doing it this way: create a list and reference in the map thus, Map<Id, Product_Configuration__c> plmap = new Map<Id, Product_Configuration__c>(pclist); But I get error: attempt to de-reference a null object where the validation is the final loop. – Zane Jun 04 '15 at 16:11
  • Notice that I defined it first at the start of the trigger so that inside the If statement and outside the first For loop, it would already be defined and the query would be created as a map if surrounded by parens as I've done above. Did you do the same? If you did, try changing query line to plmap = new map([SELECT Id, etc....]); – crmprogdev Jun 04 '15 at 18:32
  • Yes. I have the logic as that but it is not updating the field to true upon insert. There is no error and nothing in the debug. – Zane Jun 10 '15 at 21:15
  • I cannot add the code due to the character limit. Could I email it to you? – Zane Jun 10 '15 at 21:17
  • What character limit? The above code doesn't have very many characters in it. Where are you hitting a character limit? What editor are you using? And no, I don't provide email support. This is a volunteer based forum. – crmprogdev Jun 10 '15 at 21:28
  • I deployed in our test environment and did get an attempt to dereference a null pointer Sobject error. It's referring to line: if(plmap.get(emd1.Id).Print_Image__c) – Zane Jun 10 '15 at 21:48
  • I was just copying your code on that line. emd1.Print_Image__c = true should actually be emd1.Print_Image__c == true. Note the '=='. I recommend you add debug statements and see How do I start to debug my own Apex code?. Also, create a test class so you know what you're dealing with and can control the test environment. – crmprogdev Jun 11 '15 at 04:46
  • Is is not a string value I am setting to but a boolean. Anyway, I had some time to re-think this and was able to get it to work. Yes, I know how to use debug statements. Thanks for your comments. – Zane Jun 11 '15 at 16:37
  • Yes, a string would have had single quotes around it. It appeared that you were testing it for equality, not setting the value, so I'm not following your comments. In any case, I'm glad you got it sorted. If this post led you to solving your issue, please help the rest of the community who might search for answers to their problems later, by marking this answer as having answered your question. – crmprogdev Jun 11 '15 at 22:00