Thursday, January 10, 2013

Trigger Context Variables Considerations



Be aware of the following considerations for trigger context variables:

1)       trigger.new and trigger.old cannot be used in Apex DML operations.
2)       You can use an object to change its own field values using trigger.new, but only in before triggers. In all after triggers, trigger.new is not saved, so a runtime exception is thrown.
3)       trigger.old is always read-only.
4)       You cannot delete trigger.new.
The following table lists considerations about certain actions in different trigger events:

Trigger Event
Can change fields using trigger.new
Can update original object using an update DML operation
Can delete original object using a delete DML operation
Before insert
Allowed.
Not applicable. The original object has not been created; nothing can reference it, so nothing can update it.
Not applicable. The original object has not been created; nothing can reference it, so nothing can update it.
After insert
Not allowed. A runtime error is thrown, as trigger.new is already saved.
Allowed.
Allowed, but unnecessary. The object is deleted immediately after being inserted.
Before update
Allowed.
Not allowed. A runtime error is thrown.
Not allowed. A runtime error is thrown.
After update
Not allowed. A runtime error is thrown, as trigger.new is already saved.
Allowed. Even though bad code could cause an infinite recursion doing this incorrectly, the error would be found by the governor limits.
Allowed. The updates are saved before the object is deleted, so if the object is undeleted, the updates become visible.
Before delete
Not allowed. A runtime error is thrown. trigger.new is not available in before delete triggers.
Allowed. The updates are saved before the object is deleted, so if the object is undeleted, the updates become visible.
Not allowed. A runtime error is thrown. The deletion is already in progress.
After delete
Not allowed. A runtime error is thrown. trigger.new is not available in after delete triggers.
Not applicable. The object has already been deleted.
Not applicable. The object has already been deleted.
After undelete
Not allowed. A runtime error is thrown. trigger.old is not available in after undelete triggers.
Allowed.
Allowed, but unnecessary. The object is deleted immediately after being inserted.

All triggers define implicit variables that allow developers to access runtime context. These variables are contained in the System.Trigger class:

Variable
Usage
isExecuting
Returns true if the current context for the Apex code is a trigger, not a Visualforce page, a Web service, or an executeanonymous() API call.
isInsert
Returns true if this trigger was fired due to an insert operation, from the Salesforce user interface, Apex, or the API.
isUpdate
Returns true if this trigger was fired due to an update operation, from the Salesforce user interface, Apex, or the API.
isDelete
Returns true if this trigger was fired due to a delete operation, from the Salesforce user interface, Apex, or the API.
isBefore
Returns true if this trigger was fired before any record was saved.
isAfter
Returns true if this trigger was fired after all records were saved.
isUndelete
Returns true if this trigger was fired after a record is recovered from the Recycle Bin (that is, after an undelete operation from the Salesforce user interface, Apex, or theAPI.)
new
Returns a list of the new versions of the sObject records.
Note that this sObject list is only available in insert and update triggers, and the records can only be modified in before triggers.
newMap
A map of IDs to the new versions of the sObject records.
Note that this map is only available in before update, after insert, and after update triggers.
old
Returns a list of the old versions of the sObject records.
Note that this sObject list is only available in update and delete triggers.
oldMap
A map of IDs to the old versions of the sObject records.
Note that this map is only available in update and delete triggers.
size
The total number of records in a trigger invocation, both old and new.

Monday, January 7, 2013

Next Birthday formula field that respects Leap Day

The following formula is calculated from a custom Birthday field and will display this year's Birthday if it has not passed, next year's Birthday if it has passed, and takes Birthdays on Leap day into consideration.


IF ( MONTH (Birthday__c)=2 && DAY (Birthday__c)=29,
    IF ((DATE (YEAR(TODAY()),1,1) + 59)  > TODAY(),
         (DATE (YEAR(TODAY()),1,1)) + 59,
         (DATE (YEAR(TODAY())+1,1,1)) + 59),
    IF (DATE (YEAR(TODAY()),MONTH(Birthday__c),DAY(Birthday__c)) > TODAY(),
         DATE (YEAR(TODAY()),MONTH(Birthday__c),DAY(Birthday__c)),
         DATE (YEAR(TODAY())+1,MONTH(Birthday__c),DAY(Birthday__c))
       )
)
 
This says that:
 
1.        if the B-Day is a leap day
a.       then if TODAY() is less than the 60th day of the year (which is 2/29 in a leap year and 3/1 in a non leap year)
i.      then display Jan 1st + 59 (the 60th day) of this year
b.      else
i.      display Jan 1st + 59 of next year
2.       else
a.       then if TODAY is less than the custom date field’s month and day of this year
i.      then display the custom month and day of this year
b.      else
 i.      display the custom month and day of next year