Pages

Tuesday 25 June 2019

Delegate Approvers in Salesforce

This is very often that the Sales manager or director is out of the office and due to their absence, there are many approvals fall in the pending queue. As a result, this impacts the Sales cycle and business. Thanks to Salesforce! After reading this post, this problem will be fixed by using the power of delegation. In the absence of the Sales Manager, the delegated user can approve or reject the approvals assigned to the Sales Manager.

Fasten your seat belt and ready to learn the power of delegation in Salesforce.

Step 1: The existing approval process should have the option enabled for the delegation, refer the below screenshot.


Step 2: Set the Delegated approver (the user who can Approve/Reject the records in the absence of Actual Approver) by selecting the Approver in the Delegated Approver field on the user detail page.


Set your preference for receiving approval request emails. The options are:
  • If I am an approver or delegated approver
  • Only if I am an approver
  • Only if I am a delegated approver
  • Never—If you select this option, you won't receive any approval request emails, even if your organization has email approval response enabled. However, if the assignee of an approval step is a queue, selecting Never may not block all approval request emails, depending on the queue settings.

When an approval request email is sent to the assigned approver, the delegated approver also receives an email notification that there is an approval request to review. Delegated approvers can't reassign approval requests; they can only approve or reject approval requests.

Delegate Approvers can also approve/reject via an email.


Monday 10 June 2019

'List has no rows for assignment to SObject' error

The following query is not returning any number of records:
"[SELECT Id FROM Account WHERE Id = :Trigger.new[0].Account__c]"
The error "List has no rows for assignment to SObject" occurs when the query doesn't return any rows.

Player__c player = [SELECT Id from Player__c where Name = :username];
if (player != null)
 p = player.Id;
The above code will fail if there is no Player__c record with the matching username. It doesn't actually return a null.

It would be safer to do the following:

Player__c[] players = [SELECT Id from Player__c where Name = :username];
if (players.size() > 0)
p = players[0].Id;
It’s one of those situations for which you would not normally think of creating a test, so it’s safer to just avoid the possibility.

Enforce Field-Level Security in Apex (Pilot)

Apex has a new security feature for field-level data protection, which is accessed through the Security and SObjectAccessDecision classes. To ensure secure processing in Apex in the context of the current user’s read, create, or update operation, use the stripInaccessible method. Based on the field-level security of the current user, this method can be used to strip the fields from query results that the user can’t access. The method can also be used to remove inaccessible fields from sObjects before a DML operation to avoid exceptions and to sanitize sObjects that have been deserialized from an untrusted source.
How: The stripInaccesible method checks the source records for fields that don’t meet the field-level security check for the current user and creates a return list of sObjects. The return list is identical to the source records, except that the fields that are inaccessible to the current user are removed.

Example
If the user doesn’t have the permission to create the Probability field of an Opportunity object, this example removes the Probability field before creating the records. The DML operation is completed without throwing an exception.


List<Opportunity> opportunities = new List<Opportunity>{
    new Opportunity(Name='Opportunity1'),
    new Opportunity(Name='Opportunity2', Probability=95)
};

// Strip fields that are not creatable
SObjectAccessDecision decision = Security.stripInaccessible(
    AccessType.CREATABLE,
    opportunities);

// Print stripped records
for (SObject strippedOpportunity : decision.getRecords()) {
    System.debug(strippedOpportunity);
}

// print modified indexes
System.debug(decision.getModifiedIndexes());

// Print removed fields
System.debug(decision.getRemovedFields());

//System.debug Output
// DEBUG|Opportunity:{Name=Opportunity1}
// DEBUG|Opportunity:{Name=Opportunity2}
// DEBUG|{1}
// DEBUG|{Opportunity={Probability}}