+ Start a Discussion
Ravi K 47Ravi K 47 

trigger to update new and old records on product

Hello All,

I have a requirement to udpate Product2(IsActive) field.

The requirement is udpate IsActive=true for all newly updating records and remaing all old records(oldrecords- newly updating records) should update with IsActive=false value.

Below are the old records 
 
id name isactive
1   ravi     true
2    kumar true
3   kusuma true

Below are the newly updating records
id name isactive
1  ravi    true

and final output looks like 
id name isactive
1   ravi     true
2    kumar false
3   kusuma false

Could you please help me to provide the trigger for this requirement .

 
Varun SinghVarun Singh
Hi @Ravi 
try  this  code
I  have  created  and  tested in my  org  its  working well!

try  this code
 
trigger isActivefalse on Product2 (before insert,before update) {
 Set<Id> Ids = new Set<Id>();
for(product2 p:trigger.new){
Ids.add(p.id);
}
List<product2 > lstpro=[select id,name,isactive from product2 where id not in:ids];
List<product2 > updatepro=new List<product2 >();
for(Product2 p:lstpro){
p.isactive=false;
updatepro.add(p);
}
if(updatepro.size()>0){
update updatepro;
}
}

If  information in informative  please make my answer as best answer.
Thanks,
varun​
Glyn Anderson 3Glyn Anderson 3
Varun's answer should work fine, and he should get credit for the answer.  Except that it won't work on before insert, as Trigger.new has no IDs before insert.  We can do it in after triggers.  We don't worry about recursion, as we're updating Products that aren't in the trigger.  And no need to update Products that are already inactive.  Here's the same with fewer lines of code:

<pre>
trigger isActiveFalse on Product2 (after insert, after update)
{
    List<Product2 > lstpro =
    [   SELECT  Id, IsActive
        FROM     Product2
        WHERE    IsActive = true AND Id NOT IN :Trigger.new
    ];
    for ( Product2 p : lstpro )
    {
        p.IsActive = false;
    }
    // DML on an empty collection does not count against DML limits
    update lstpro;
}
</pre>
Ravi K 47Ravi K 47
@All, Thank You for your reply .

But if im trying to update the Isactive=false record and these record should be active  as well. 

I have already tried with the above one and its working fine.

Could you please help me on this ?
Glyn Anderson 3Glyn Anderson 3

Ravi,  I want to help, but I don't understand your new question.  If "it's working fine", then what do you need help with?  Could you provide more information, please?

Ravi K 47Ravi K 47
Thanks for your consern.
While updating the Inactive records ,we need to update to Active and all other old records should be InActive mode.

For Example:
We have an Inactive record in the above given scenorio (2 kumar False)
Now i am updating 2nd record then this should be updated to Active as below.
id name isactive
1   ravi     false
2    kumar true
3   kusuma false


 
Glyn Anderson 3Glyn Anderson 3
Thank you, now I understand.  Below is an updated trigger that should do what you require.  We modify the record in the trigger during the "before" phase, so that we don't have to do any DML.

<pre>
trigger ProductActivation on Product2 (before insert, after insert, before update, after update)
{
    if ( Trigger.isBefore )
    {
        for ( Product2 product : Trigger.new )
        {
            product.IsActive = true;
        }
    }

    if ( Trigger.isAfter )
    {
        List<Product2 > productsToDeactivate =
        [   SELECT  Id, IsActive
            FROM     Product2
            WHERE    IsActive = true AND Id NOT IN :Trigger.new
        ];
        for ( Product2 product : productsToDeactivate )
        {
            product.IsActive = false;
        }
        // DML on an empty collection does not count against DML limits
        update productsToDeactivate;
    }
}
</pre>
 
Ravi K 47Ravi K 47
For the latest code im getting the following error

Error: Invalid Data. 
Review all error messages below to correct your data.
Apex trigger isActiveFalse caused an unexpected exception, contact your administrator: isActiveFalse: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 01t7F0000016JQAQA2; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, isActiveFalse: execution of BeforeUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 01t7F0000016JQ6QAM; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, isActiveFalse: execution of BeforeUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 01t7F0000016JQAQA2; first error: SELF_REFERENCE_FROM_TRIGGER, Object (id = 01t7F0000016JQA) is currently in trigger isActiveFalse, therefore it cannot recursively update itself: [] Trigger.isActiveFalse: line 21, column 1: [] Trigger.isActiveFalse: line 21, column 1: []: Trigger.isActiveFalse: line 21, column 
Glyn Anderson 3Glyn Anderson 3
Make sure you're not updating any records in the "before" events in the trigger.  It is not allowed to update the records that are in the trigger.  During the "before" phase, they have not yet been written to the database.  You can modify them without use "update", and they will get written to the database with your modifications.  If you are using my latest code, you will not have this problem.  Can you post the code you are using?
Ravi K 47Ravi K 47
trigger isActiveFalse on Product2 (after insert, after update,before insert,before update )
{
    
    if ( Trigger.isBefore && trigger.isupdate )
    {
        for ( Product2 product : Trigger.new )
        {
            product.IsActive = true;
        }
    }
    List<Product2 > lstpro =
    [   SELECT  Id, IsActive
        FROM     Product2
        WHERE    IsActive = true AND Id NOT IN :Trigger.new
    ];
    for ( Product2 p : lstpro )
    {
        p.IsActive = false;
    }
    // DML on an empty collection does not count against DML limits
    update lstpro;
}

Hello ,

Please find the above code snippet. 

Many thanks for your help in advance!
Ravi K 47Ravi K 47
Hello ,

Below is the udpated code ,please ignore the above 
trigger isActiveFalse on Product2 (after insert, after update,before insert,before update )
{
    if ( Trigger.isBefore )
    {
        for ( Product2 product : Trigger.new )
        {
            product.IsActive = true;
        }
    }

    if ( Trigger.isAfter )
    {
        List<Product2 > productsToDeactivate =
        [   SELECT  Id, IsActive
            FROM     Product2
            WHERE    IsActive = true AND Id NOT IN :Trigger.new
        ];
        for ( Product2 product : productsToDeactivate )
        {
            product.IsActive = false;
        }
        // DML on an empty collection does not count against DML limits
        update productsToDeactivate;
    }
}

Below is the latest error message 
 
Apex trigger isActiveFalse caused an unexpected exception, contact your administrator: isActiveFalse: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 01t7F0000016JQAQA2; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, isActiveFalse: maximum trigger depth exceeded Product2 trigger event AfterUpdate for [01t7F0000016JQ6] Product2 trigger event AfterUpdate for [01t7F0000016JQA] Product2 trigger event AfterUpdate for [01t7F0000016JQ6] Product2 trigger event AfterUpdate for [01t7F0000016JQA] Product2 trigger event AfterUpdate for [01t7F0000016JQ6] Product2 trigger event AfterUpdate for [01t7F0000016JQA] Product2 trigger event AfterUpdate for [01t7F0000016JQ6] Product2 trigger event AfterUpdate for [01t7F0000016JQA] Product2 trigger event AfterUpdate for [01t7F0000016JQ6] Product2 trigger event AfterUpdate for [01t7F0000016JQA] Product2 trigger event AfterUpdate for [01t7F0000016JQ6] Product2 trigger event AfterUpdate for [01t7F0000016JQA] Product2 trigger event AfterUpdate for [01t7F0000016JQ6] Product2 trigger event AfterUpdate for [01t7F0000016JQA] Product2 trigger event AfterUpdate for [01t7F0000016JQ6] Product2 trigger event AfterUpdate for [01t7F0000016JQA]: []: Trigger.isActiveFalse: line 23, column 1

 
Varun SinghVarun Singh
Hi Ravi 
Many developers face this issue because of a recursive trigger. For example, in an 'after update' trigger, a developer could be performing an update operation and this would lead to recursive call, and the error:
"maximum trigger depth exceeded"

Solution:In order to avoid the situation of recursive call, make sure your trigger is getting executed only one time. To do so, you can create a class with a static boolean variable with default value true.

In the trigger, before executing your code keep a check that the variable is true or not.

Once you check, make the variable false.
 
trigger isActiveFalse on Product2 (after insert, after update,before insert,before update )
{


    
    if ( Trigger.isBefore )
    {
        for ( Product2 product : Trigger.new )
        {
            product.IsActive = true;
        }
    }

     if(checkRecursive.runOnce())
    {
    if ( Trigger.isAfter )
    {
        List<Product2 > productsToDeactivate =
        [   SELECT  Id, IsActive
            FROM     Product2
            WHERE    IsActive = true AND Id NOT IN :Trigger.new
        ];
        for ( Product2 product : productsToDeactivate )
        {
            product.IsActive = false;
        }
        // DML on an empty collection does not count against DML limits
        update productsToDeactivate;
    }
    }
}

apex class
 
public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
    if(run){
     run=false;
     return true;
    }else{
        return run;
    }
    }
}

I hope  this  is  helpful  for you make my answer as best answer
 
Glyn Anderson 3Glyn Anderson 3
Ravi K 47,  Did any of these answers solve your problem?  If so, please mark the question as "Solved".  If not, let us know.  If you solved it yourself another way, please post your solution.  Thanks!