function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Joe StolzJoe Stolz 

Trigger that can bypass validation rule

I have been searching for answers and testing solutions all day for this. Any help would be greatly appreciated.

We use a large number of workflow tasks that are assigned to different members of our opportunity teams depending on what stage the opportunity enters. We do not want our users to change when these tasks are due, but we also do not want tasks to be due during non business days. Both of these solutions I have solved for, but I cannot solve for both at the same time. I have a trigger in place that changes the date of tasks that fall due on Saturdays or Sundays.
trigger WeekendTasks on Task (after insert, after update)
{
for (Task tas : Trigger.new)
{
if (tas.RecordTypeID == '012i00000011lsq' && tas.ActivityDate != null)
{
Date origin = Date.newInstance(1900,1,6);
Date due = tas.ActivityDate;
Integer x = origin.daysBetween(due);
Integer day = Math.mod(x,7);
if (day < 2 )
{
Task tt = new Task
(
Id = tas.Id,
ActivityDate = (tas.ActivityDate + 1)
  );
update tt;
}
}
}
}
This works perfectly for our needs, but when I combine this with my Task Validation Rule:
AND( ISCHANGED( ActivityDate ), RecordType.Name ="RPA Auto Task" ,$Profile.Name <>"System Administrator", $Profile.Name <>"RPA Director")
My users receive this error:
 
There were custom validation error(s) encountered while saving the affected record(s). The first validation error encountered was "Apex trigger WeekendTasksUpdate caused an unexpected exception, contact your administrator: WeekendTasksUpdate: execution of AfterInsert caused by: System.DmlException: Update failed. First exception on row 0 with id 00Te000000DlLGREA3; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Only Administrators and Directors are able to change task due dates.: [ActivityDate]: Trigger.WeekendTasksUpdate: line 18, column 1".
This only happens when a workflow tasks falls on the weekends and the trigger trys to change the task due date which is prevented by my validation rule. I tried to follow Bob Buzzard's guide (http://bobbuzzard.blogspot.com/2011/11/bypass-validation-rules-from-apex.html) on setting a custom checkbox on the task but could not get this to work. I believe the issue comes because my trigger fires after update/insert, but I do not know enough about apex to fix this.

Any ideas on how to make the validation rule and trigger play nice with each other? I would love the ability to run the trigger as an admin each time, but that does not seem possible either.
Best Answer chosen by Joe Stolz
Douglas AyersDouglas Ayers
Try changing the IF statement to handle two conditions (Saturday and Sunday):

if ( day == 0 ) // Saturday
{
    tas.ActivityDate = (tas.ActivityDate + 2);
}
else if ( day == 1 ) // Sunday
{
    tas.ActivityDate = (tas.ActivityDate + 1);
}

All Answers

Douglas AyersDouglas Ayers
Hi Joe,

Can you try changing your trigger to be before insert/update rather than after? This should allow your apex code to adjust the ActivityDate without firing another "update" event on the task that would cause the validation rule to run. Why I think this would work (untested) is that if workflows are spawning these tasks then the tasks are being created new and given some due date (e.g. today + 7 days) and your before insert trigger would adjust the date prior its initial insertion thus never truly causing an "update" (line 18) thus the validation rule would not run.

trigger WeekendTasks on Task ( before insert, before update )
{
    for ( Task tas : Trigger.new )
    {
        if ( tas.RecordTypeID == '012i00000011lsq' && tas.ActivityDate != null )
        {
            Date origin = Date.newInstance(1900,1,6);
            Date due = tas.ActivityDate;
            Integer x = origin.daysBetween(due);
            Integer day = Math.mod(x,7);
            if ( day < 2 )
            {
                tas.ActivityDate = (tas.ActivityDate + 1);
            }
        }
    }
}

David "w00t!" LiuDavid "w00t!" Liu
If all else fails you can also create a "Bypass Validation Rules" field and have that field uneditable by any profiles (Apex runs in god mode)

Then, have a clause in your validation rule that allows changes if that field is checked. Then build a workflow that unchecks that box whenever it's checked.

Not the cleanest solution but it'll work!
Douglas AyersDouglas Ayers
@David, yes, I've used those too! I'm hoping Joe can get away with some minor tweaks to the trigger. But like you said, if all else fails the workflow/validation bypass trick will work!
Joe StolzJoe Stolz
Thank you for the responses.

When I try before update/insert, I receive the error:

There were custom validation error(s) encountered while saving the affected record(s). The first validation error encountered was "Apex trigger WeekendTasksUpdate caused an unexpected exception, contact your administrator: WeekendTasksUpdate: execution of BeforeInsert caused by: System.DmlException: Update failed. First exception on row 0; first error: MISSING_ARGUMENT, Id not specified in an update call: []: Trigger.WeekendTasksUpdate: line 18, column 1".

This was also my problem when I tried the bypass trick. I received an error that the field was not editable with an after update/insert. I'm probably missing something very simple. Any ideas?
 
Douglas AyersDouglas Ayers
Correct, you will need to use the modified trigger syntax from my previous post. You will no longer need to re-create a Task object nor issue an update command. In a before insert/update trigger, you are essentially modifying the values "before" they get to the database. It's like real-time transformation of the values.
Joe StolzJoe Stolz
I apologize...I read your post too quickly and just saw the first line and did not realize you modified anything else.

I did try the trigger and it did not throw an error or trigger the validation code so thank you for that. But of course, when you fix one thing, something else pops up. No, if the task due date lands on a Saturday, the task due date will now change to a Sunday. The trigger I was using before seemed to refire if the due date landed on a Saturday changing the due date until it lands on a week day.

Is there a way for the trigger to re-evaluate and fire again to move the due date to Monday?
Douglas AyersDouglas Ayers
Try changing the IF statement to handle two conditions (Saturday and Sunday):

if ( day == 0 ) // Saturday
{
    tas.ActivityDate = (tas.ActivityDate + 2);
}
else if ( day == 1 ) // Sunday
{
    tas.ActivityDate = (tas.ActivityDate + 1);
}

This was selected as the best answer
Joe StolzJoe Stolz
That was it!

Thank you so much for your help.