+ Start a Discussion
Jessi WaldonJessi Waldon 

How to stop my code from causing a Self Reference From Trigger

I am trying to have a trigger and trigger handler that create Credit Note Lines only once a Credit Note status is Posted. 

I believe my code needs to be beforeUpdate to avoid a validation issue if I try afterUpdate(that validation is unable to be turned off as it's managed package code)

Below is my code. Do you know how to avoid the recurssion issue?
protected override void beforeUpdate() { 

        System.debug('CreditNoteTriggerHandler afterUpdate()'); 

        insertCreditNoteLine();} 

        

    @TestVisible 

    private void insertCreditNoteLine(){ 

        List<blng__creditNote__c> creditNotes = (List<blng__CreditNote__c>)Trigger.new; 

        List<blng__CreditNoteLine__c> creditNoteLinesToInsert = new List<blng__CreditNoteLine__c>(); 

        for(blng__CreditNote__c c : creditNotes){ 

        if(c.blng__CreditNoteSourceAction__c == 'Manual' && c.blng__Status__c == 'Posted'){ 

                Valpak__c vpc = Valpak__c.getOrgDefaults(); 

                //String discountstring = vpc.ZVP_Discounts_Returns_Allowances__c; 

                //Id discountid = id.valueOf(discountstring); 

                blng__CreditNoteLine__c line = new blng__CreditNoteLine__c(); 

                line.blng__CreditNote__c = c.Id;  

                line.blng__StartDate__c = c.blng__CreditNoteDate__c;  

                line.blng__EndDate__c = c.blng__CreditNoteDate__c;  

                   line.blng__LegalEntity__c = c.blng__Account__r.ZVP_Franchise__r.ZVP_Legal_Entity__r.Id; 

                   line.blng__Subtotal__c = c.ZVP_Amount__c; 

             

               if(c.ZVP_Credit_Adjustment_Type__c == 'NSF Add Payment'){ 

                   line.blng__Product__c = id.valueOf(vpc.ZVP_Billing_AR_Clearing__c);  

                                

               }Else if(c.ZVP_Credit_Adjustment_Type__c == 'Bad Debt Write-Off'){ 

                    line.blng__Product__c = id.valueOf(vpc.ZVP_Allow_for_Doubtful_Accounts_PC_Req__c);  

                                 

               }Else if (c.ZVP_Credit_Adjustment_Type__c == 'Exchange Rate - Reduce Amount Received'|| 

                     c.ZVP_Credit_Adjustment_Type__c == 'Intercompany Credit'){ 

                     line.blng__Product__c = id.valueOf(vpc.ZVP_Accrued_Intermarket_Fees_Payable__c);  

         

               }Else if (c.ZVP_Credit_Adjustment_Type__c == 'Misc Credit'|| 

                        c.ZVP_Credit_Adjustment_Type__c == 'Add Correct Payment'|| 

                        c.ZVP_Credit_Adjustment_Type__c == 'Go-Live Balance Reduction'||    

                        c.ZVP_Credit_Adjustment_Type__c == 'Finance Charge (CR)'||  

                        c.ZVP_Credit_Adjustment_Type__c == 'VBC Credit'){ 

                            line.blng__Product__c = id.valueOf(vpc.ZVP_Clearing_Account_Other__c);  

         

               }Else if(c.ZVP_Credit_Adjustment_Type__c == 'Barter/Direct Trade'){ 

                            line.blng__Product__c = id.valueOf(vpc.ZVP_Trade_Barter_Expense__c);  

         

               }Else if(c.ZVP_Credit_Adjustment_Type__c == 'Coupon/Discount'|| 

                        c.ZVP_Credit_Adjustment_Type__c == 'Sales Price Decrease'|| 

                        c.ZVP_Credit_Adjustment_Type__c == 'Refunds - Invoice'){ 

                                line.blng__Product__c = id.valueOf(vpc.ZVP_Discounts_Returns_Allowances__c);  

         

               }Else if(c.ZVP_Credit_Adjustment_Type__c == 'Collection Agency Fee Removed'){ 

                                line.blng__Product__c = id.valueOf(vpc.ZVP_Collection_Fees__c); //line.blng__Subtotal__c = c.ZVP_Amount__c; 

         

               }Else if (c.ZVP_Credit_Adjustment_Type__c == 'Sales Tax Adjustment'){ 

                                line.blng__Product__c = id.valueOf(vpc.ZVP_Sales_Tax__c); //line.blng__Subtotal__c = c.ZVP_Amount__c; 

               } 

            creditNoteLinesToInsert.add(line); 

                    

                                }//if manual 

         }//end for loop 

        if(creditNoteLinesToInsert.size() > 0) { 

            System.debug('creditNoteLinesToInsert: ' + creditNoteLinesToInsert); 

            insert creditNoteLinesToInsert; 

        } 

}

And here is my Trigger
 
trigger tgr_CreditNote on blng__CreditNote__c (before insert, before update, after insert, after update, before delete, after undelete) {
    
    new CreditNoteTriggerHandler().run();
}

Any help is greatly appreciated. I am trying to write test coverage and get this to my QA team soon.

Thanks!​​​​​​​
Greg HGreg H
Your logic looks fine. If your code is being fired more than once it is probably from something outside of this trigger logic such as a Flow. I recommend running this logic in the after update context instead of before. Primarily because you are not manipulating anything on the blng__CreditNote__c record and creating a list of blng__CreditNoteLine__c records to insert. Another option would be to use a queueable interface of future annotated method to process this logic asynchronously after the blng__CreditNote__c records are saved to the database.
-greg
Boss CoffeeBoss Coffee
Do you have a trigger on blng__CreditNoteLine__c that may be updating the parent blng__CreditNote__c?