Restrict multiple approval for a single user to a single record in Salesforce

I had a requirement to restrict multiple approval for a single user to a single record. There were multiple steps of approval process and the approver may be in different queue or as a manager for a user.

So, I implemented it using a trigger. In this article I’ll demonstrate how to implement it.
Here Application__c is the object, on which 3 steps approval process has implemented.
A custom check box field Check_Approver__c has set value to true, in all 3 steps field update action.

In below trigger I filtered the ProcessInstanceStep object records with current user Id in ActorId and the object Id (here object Id means record Id) in ProcessInstance.TargetObjectId.

  • If an User will approve or reject a record, then the SOQL query will return a single record.
  • If the SOQL query return a record, then trigger will throw an error message.

Trigger source code:

trigger ApplicationTrigger on Application__c (before Update)
{
    if(trigger.isUpdate){

        Id currentUserId = UserInfo.getUserId();
        for(Application__c sf: trigger.new){   
                  
            if(sf.Check_Approver__c == true){
              
                List<processinstancestep> existingApprovals = [SELECT ActorId
                                    FROM ProcessInstanceStep WHERE ProcessInstance.TargetObjectId = :sf.Id
                                    AND (StepStatus = 'Approved' OR StepStatus = 'Rejected')
                                    AND ActorId = :currentUserId];
                                      
                if(existingApprovals != null){
                  
                    if(existingApprovals.size() > 0){

                        sf.addError('You have already approved or rejeted the record.');
                    }
                }                  
             }
         }                         
    }
}

Hard Delete record using Apex in Salesforce

We can hard delete record or list of records using emptyRecycleBin() function in apex. Pass the record or record list to emptyRecycleBin() to delete it from Recycle Bin.

Contact con = new Contact(Id = '09k110000O5abc');
Database.emptyRecycleBin(con);

Note: The DML operation datatbase.emptyRecycleBin() is limited to 200 items.

Date Literals in Salesforce SOQL

Date Literal Range Example
YESTERDAY Starts 12:00:00 the day before and continues for 24 hours. SELECT Id FROM Account WHERE CreatedDate =
YESTERDAY
TODAY Starts 12:00:00 of the current day and continues for 24 hours. SELECT Id FROM Account WHERE CreatedDate >
TODAY
TOMORROW Starts 12:00:00 after the current day and continues for 24 hours. SELECT Id FROM Opportunity WHERE CloseDate =
TOMORROW
LAST_WEEK Starts 12:00:00 on the first day of the week before the most recent first day
of the week and continues for seven full days. First day of the week is determined
by your locale.
SELECT Id FROM Account WHERE CreatedDate >
LAST_WEEK
THIS_WEEK Starts 12:00:00 on the most recent first day of the week before the current day
and continues for seven full days. First day of the week is determined by your
locale.
SELECT Id FROM Account WHERE CreatedDate <
THIS_WEEK
NEXT_WEEK Starts 12:00:00 on the most recent first day of the week after the current day
and continues for seven full days. First day of the week is determined by your
locale.
SELECT Id FROM Opportunity WHERE CloseDate =
NEXT_WEEK
LAST_MONTH Starts 12:00:00 on the first day of the month before the current day and
continues for all the days of that month.
SELECT Id FROM Opportunity WHERE CloseDate >
LAST_MONTH
THIS_MONTH Starts 12:00:00 on the first day of the month that the current day is in and
continues for all the days of that month.
SELECT Id FROM Account WHERE CreatedDate <
THIS_MONTH
NEXT_MONTH Starts 12:00:00 on the first day of the month after the month that the current
day is in and continues for all the days of that month.
SELECT Id FROM Opportunity WHERE CloseDate =
NEXT_MONTH
LAST_90_DAYS Starts 12:00:00 of the current day and continues for the last 90 days. SELECT Id FROM Account WHERE CreatedDate =
LAST_90_DAYS
NEXT_90_DAYS Starts 12:00:00 of the current day and continues for the next 90 days. SELECT Id FROM Opportunity WHERE CloseDate >
NEXT_90_DAYS
LAST_N_DAYS:n For the number n provided, starts 12:00:00 of the current day and continues for the last n days. SELECT Id FROM Account WHERE CreatedDate =
LAST_N_DAYS:365
NEXT_N_DAYS:n For the number n provided, starts 12:00:00 of the current day and continues for the next n days. SELECT Id FROM Opportunity WHERE CloseDate >
NEXT_N_DAYS:15
NEXT_N_WEEKS: n For the number n provided, starts 12:00:00 of the first day of the next week and continues for the next n weeks. SELECT Id FROM Opportunity WHERE CloseDate >
NEXT_N_WEEKS:4
LAST_N_WEEKS:n For the number n provided, starts 12:00:00 of the last day of the previous week and continues for the last n weeks. SELECT Id FROM Account WHERE CreatedDate = LAST_N_WEEKS:52
NEXT_N_MONTHS:n For the number n provided, starts 12:00:00 of the first day of the next month and continues for the next n months. SELECT Id FROM Opportunity WHERE CloseDate >
NEXT_N_MONTHS:2
LAST_N_MONTHS:n For the number n provided, starts 12:00:00 of the last day of the previous month and continues for the last n months. SELECT Id FROM Account WHERE CreatedDate =
LAST_N_MONTHS:12
THIS_QUARTER Starts 12:00:00 of the current quarter and continues to the end of the current
quarter.
SELECT Id FROM Account WHERE CreatedDate =
THIS_QUARTER
LAST_QUARTER Starts 12:00:00 of the previous quarter and continues to the end of that
quarter.
SELECT Id FROM Account WHERE CreatedDate >
LAST_QUARTER
NEXT_QUARTER Starts 12:00:00 of the next quarter and continues to the end of that
quarter.
SELECT Id FROM Account WHERE CreatedDate <
NEXT_QUARTER
NEXT_N_QUARTERS:n Starts 12:00:00 of the next quarter and continues to the end of the nth quarter. SELECT Id FROM Account WHERE CreatedDate <
NEXT_N_QUARTERS:2
LAST_N_QUARTERS:n Starts 12:00:00 of the previous quarter and continues to the end of the previous nth quarter. SELECT Id FROM Account WHERE CreatedDate >
LAST_N_QUARTERS:2
THIS_YEAR Starts 12:00:00 on January 1 of the current year and continues through the end
of December 31 of the current year.
SELECT Id FROM Opportunity WHERE CloseDate =
THIS_YEAR
LAST_YEAR Starts 12:00:00 on January 1 of the previous year and continues through the end
of December 31 of that year.
SELECT Id FROM Opportunity WHERE CloseDate >
LAST_YEAR
NEXT_YEAR Starts 12:00:00 on January 1 of the following year and continues through the
end of December 31 of that year.
SELECT Id FROM Opportunity WHERE CloseDate <
NEXT_YEAR
NEXT_N_YEARS:n Starts 12:00:00 on January 1 of the following year and continues through the end of December 31 of the nth year. SELECT Id FROM Opportunity WHERE CloseDate <
NEXT_N_YEARS:5
LAST_N_YEARS:n Starts 12:00:00 on January 1 of the previous year and continues through the end of December 31 of the previous nth year. SELECT Id FROM Opportunity WHERE CloseDate >
LAST_N_YEARS:5
THIS_FISCAL_QUARTER Starts 12:00:00 on the first day of the current fiscal quarter and continues
through the end of the last day of the fiscal quarter. The fiscal year is defined in
the company profile under Setup at Company Profile | Fiscal Year.
SELECT Id FROM Account WHERE CreatedDate =
THIS_FISCAL_QUARTER
LAST_FISCAL_QUARTER Starts 12:00:00 on the first day of the last fiscal quarter and continues
through the end of the last day of that fiscal quarter. The fiscal year is defined
in the company profile under Setup at Company Profile | Fiscal Year.
SELECT Id FROM Account WHERE CreatedDate >
LAST_FISCAL_QUARTER
NEXT_FISCAL_QUARTER Starts 12:00:00 on the first day of the next fiscal quarter and continues
through the end of the last day of that fiscal quarter. The fiscal year is defined
in the company profile under Setup at Company Profile | Fiscal Year.
SELECT Id FROM Account WHERE CreatedDate <
NEXT_FISCAL_QUARTER
NEXT_N_FISCAL_​QUARTERS:n Starts 12:00:00 on the first day of the next fiscal quarter and continues through the end of the last day of the nth fiscal quarter. The fiscal year is defined in the company profile under Setup atCompany Profile | Fiscal Year. SELECT Id FROM Account WHERE CreatedDate <
NEXT_N_FISCAL_QUARTERS:6
LAST_N_FISCAL_​QUARTERS:n Starts 12:00:00 on the first day of the last fiscal quarter and continues
through the end of the last day of the previous
nth fiscal
quarter. The fiscal year is defined in the company profile under Setup at Company Profile | Fiscal Year.
SELECT Id FROM Account WHERE CreatedDate >
LAST_N_FISCAL_QUARTERS:6
THIS_FISCAL_YEAR Starts 12:00:00 on the first day of the current fiscal year and continues
through the end of the last day of the fiscal year. The fiscal year is defined in
the company profile under Setup at Company Profile | Fiscal Year.
SELECT Id FROM Opportunity WHERE CloseDate =
THIS_FISCAL_YEAR
LAST_FISCAL_YEAR Starts 12:00:00 on the first day of the last fiscal year and continues through
the end of the last day of that fiscal year. The fiscal year is defined in the
company profile under Setup at Company Profile | Fiscal Year.
SELECT Id FROM Opportunity WHERE CloseDate >
LAST_FISCAL_YEAR
NEXT_FISCAL_YEAR Starts 12:00:00 on the first day of the next fiscal year and continues through
the end of the last day of that fiscal year. The fiscal year is defined in the
company profile under Setup at Company Profile | Fiscal Year.
SELECT Id FROM Opportunity WHERE CloseDate <
NEXT_FISCAL_YEAR
NEXT_N_FISCAL_​YEARS:n Starts 12:00:00 on the first day of the next fiscal year and continues through
the end of the last day of the
nth fiscal year. The fiscal year
is defined in the company profile under Setup at Company Profile | Fiscal Year.
SELECT Id FROM Opportunity WHERE CloseDate <
NEXT_N_FISCAL_YEARS:3
LAST_N_FISCAL_​YEARS:n Starts 12:00:00 on the first day of the last fiscal year and continues through
the end of the last day of the previous
nth fiscal year. The
fiscal year is defined in the company profile under Setup at Company Profile | Fiscal Year.
SELECT Id FROM Opportunity WHERE CloseDate >
LAST_N_FISCAL_YEARS:3

Difference between Data Loader and Import Wizard in Salesforce

Import Wizard:

  • For simple imports of up to 50000 records.
  • It supports all custom objects and only few standard objects like Account, Contact, Leads, Solution.
  • It supports schedule export.
  • Delete operation is not available.
  • We cannot export data.
  • It doesn’t require installation.
  • While importing, duplicates can be ignored.

Data Loader:

  • For complex imports of any size more than 50000 records.
  • It supports all standard and custom objects.
  • It doesn’t support schedule export.
  • Delete operation is available.
  • We can export data of all custom & standard objects, and can import all custom & standard objects except User standard object.
  • It requires installation.
  • While importing, duplicates cannot be ignored.