Tuesday, 22 December 2015

How to create a case record from a VF page and attach a particular file to the record?

Below is code snippet for the same.


VF Page:-
<apex:page controller="creatingcaseAttachment">
  <apex:form >
      <apex:pageBlock title="Customer Issue">
      
          <apex:pageBlockSection title="Case Creation ">
              <apex:inputField value="{!customerCase.accountid}"/>  
              <apex:inputField value="{!customerCase.contactId}"/>  
              <apex:inputField value="{!customerCase.Origin}"/>  
              <apex:inputField value="{!customerCase.Status}"/>  
              <apex:inputField value="{!customerCase.Reason}"/>
              <apex:inputField value="{!customerCase.Subject}"/>  
              
              <apex:outputPanel style="float:right;">
                <apex:inputfile value="{!objAttachment.body}" filename="{!objAttachment.name}" ></apex:inputfile>
                <apex:commandButton value="Create Case" action="{!CaseCreation}"/>
               </apex:outputPanel>
               
          </apex:pageBlockSection>
      </apex:pageBlock>
  </apex:form>
</apex:page> 

Controller:-
public with sharing class creatingcaseAttachment {
    
    public Case customerCase{get;set;}
     Public attachment objAttachment{get; set;}
    
    public creatingcaseAttachment (){
        customerCase = new Case();
        objAttachment = new Attachment();
    } 
     Public PageReference CaseCreation(){
        Insert customerCase;
        
        objAttachment.ParentId = customerCase.id;
        insert objAttachment;
        
        PageReference p  = new PageReference('/'+customerCase.id);
        p.setRedirect(true);
        return p;
    }
}

Monday, 21 December 2015

How to remove particular key from a map?

This is pretty simple one, One of my friend asked me how to remove a particular key-value pair from a map.

Below is code snippet for the same. Hope It will help all.

Map<String, String> colorCodes =   new Map<String, String>();

colorCodes.put('Red', 'FF0000');
colorCodes.put('Blue', '0000A0');
colorCodes.put('Blue2', '0000A0');

// If you know the key then just use like below
     colorCodes.remove('Blue2');
System.debug('printing=== '+colorCodes);
//if you are not sure what about the key or need some manipulation then follow below approach
for(String key:colorCodes.keySet().clone()) {
    // myMap.get(key), process that value
    colorCodes.remove('Blue2');
}
System.debug('printing==ater= '+colorCodes);



Thursday, 10 December 2015

How to get sandbox name in apex?

As we all know sandbox username looks like "behera@mycompany.com.dev "

dev- is the sandbox name, How can we get it this dynamically ?

Use below code :-

if(UserInfo.getUserName().substringAfterLast('.com')!= null)
                    contact.Email = contactInfo.Email+'.'+UserInfo.getUserName().substringAfterLast('.');
                else
                    contact.Email = contactInfo.Email;
}

UserInfo.getUserName().substringAfterLast('.') - will give you sandbox name.

UserInfo.getUserName().substringAfterLast('.com') will tell you whether anything is there after " .com ". if not there that means we are in production otherwise in sandbox. 
We can also used same method to identify type of org like prod or non prod. There is another approach for this. 

Organization org = [select id,IsSandbox from Organization];
org.IsSandbox = true if it a sandbox. It willwork classs of higher version.

Feel free to suggest more.

Thursday, 3 December 2015

Workaround for COMPILE ERROR: Field is not writeable: Account.IsPartner

As part of my requirement, I had to create an account making isPartner as true, Unfortunately I got this  COMPILE ERROR: Field is not writable: Account.IsPartner 



Then I first inserted that account then updated isPartner as true.


Account acc = new Account(name = 'Asish');
insert acc;
System.debug('Inserted account Ispartner ---'+acc.Ispartner);
acc.Ispartner = true;
update acc;
System.debug('Inserted account---'+acc);

For more info on Ispartner field--  https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_account.htm

Friday, 27 November 2015

How to make java script function will execute after the controller method executed?

As we all know java script function will execute first then controller method executes, In some case we need java script method should execute first. Below is the work around for this case.

Instead of normal java script we will use on load java script which means when page loads/refresh that java script function will execute. Again it will be problem because each and every time that method will execute. How to avoid this ?

We will use a Boolean variable to control execution.

public Boolean isJavascriptInvoked {
        get {
            if (null == this.isJavascriptInvoked ) {
                this.isJavascriptInvoked = false;
           
            }
            return this.isJavascriptInvoked ;
        }
        set;
    }

public PageReference test(){

    // your method logic
    isJavascriptInvoked = true;
   return null;

}

<script>
   If({!isJavaScriptInvoked} == 'true'){
       // javascript logic.
  }
 
</Script>

When page loads isJavascriptInvoked will be null or false since it is boolean type,So javascript method wont execute since there is a condtion defined. When controller method invoked by some action then isJavascriptInvoked value will be set as true then js method will execute.

How to get document URL dynamically ?

A we all know sales-force host name (na5,or cs20) used to change from sandbox to production and also when SFDC refresh their server. That is why it is always suggested not to use any hard coded link. Below is code snippet to get document URL dynamically.

 //method to send document link  
    public Static String getDocumentRelativeLink(String documentName){
        String documentURL= '';
        try{
            list<Document> doc = [Select id,Name,SystemModStamp From Document Where Name  = :documentName];
            ID docIds = doc[0].id;
            documentURL = URL.getSalesforceBaseUrl().getProtocol()+'://'+System.URL.getSalesforceBaseUrl().getHost().remove('-api' )+'/servlet/servlet.ImageServer?id='+docIds+'&oid='+userinfo.getorganizationid();
        }Catch(Exception ex){}
        return documentURL ;
    }

OR

 public Static String getDocumentRelativeLink(String documentName){
      
 string baseURL = URL.getSalesforceBaseUrl().toExternalForm();        
        string instanceName;
        String sfdcUrlStrForImage = '';
        integer i;
        string tempInstance;
               try{
            list<Document> doc = [Select id,Name,SystemModStamp From Document Where Name  = :documentName];
         String id = doc[0].id;
         String recordId = id.substring(0,15);
            if(baseURL.contains('cs')){
            i = baseURL.indexof('cs');
            tempInstance = baseURL.substring(i,baseURL.length());
            instanceName = tempInstance.substring(0,tempInstance.indexof('.'));
        }
        else if(baseURL.contains('na')){
            i = baseURL.indexof('cs');
            tempInstance = baseURL.substring(i,baseURL.length());
            instanceName = tempInstance.substring(0,tempInstance.indexof('.'));
        }
        sfdcUrlStrForImage = baseURL.substring(0,i-1)+'c.'+instanceName+'.content.force.com/servlet/servlet.ImageServer?id='+recordId+'&oid='+UserInfo.getOrganizationId()+'&lastMod='+doc[0].SystemModStamp.getTime();
            
        }Catch(Exception ex){}
        return sfdcUrlStrForImage;
    }

Below is the link where I have explained few mistake we do while developing.

http://salesforceworld4u.blogspot.in/2014/04/common-mistake-we-do-while-developing.html

Thursday, 19 November 2015

How to launch service cloud console from a link clicks?

 Here is the link format

 https://(instance).salesforce.com/ui/support/servicedesk/ServiceDeskPage#/recordid

Monday, 26 October 2015

How to find duplicates element from a list?

This is an interview question one of my colleague asked, so thought of sharing.

Below is code snippet

List<String> stringList = new List<String>{'One','two','Three','Four','One','two'};

set<String> setString = new set<String>();
set<String> duplicatesetString = new set<String>();
for(String s:stringList ){
   if(!setString.add(s)){
      duplicatesetString .add(s);
   }
}
System.debug('duplicatelistString----'+duplicatesetString );
System.debug('duplicatelistString----'+duplicatesetString.add('ten'));


Monday, 19 October 2015

How to make Case comments as Private?

Hi All,

Sometimes we don't want to display all the case comments to be visible in the portal page. A customer should see his comments and the agent's comments in the portal page. Internal user's like R&D department comments should not be visible.

For that I have created a workflow to achieve this.
Case comments is a child object of Case, "Is-published" is the field which specifies comments as private or public. Is-published is true means comments must be public otherwise it will be private.




Thursday, 1 October 2015

How to use Like Operator in SOSL

Hi All,

I have already explained about the LIKE operator in my earlier post.

http://salesforceworld4u.blogspot.in/2013/08/like-operator-in-salesforce_13.html

Some asked how to use Like operator in SOSL, Below is the some code snippet where Like operator being used in SOSL.
Lets find account,contact,lead and opportunities records whose name is containing test keyword

List<List<SObject>> searchList = [FIND 'Test*' IN ALL FIELDS RETURNING Account (Id, Name WHERE Name LIKE '%test%' limit 10),Contact(Id, Name WHERE Name LIKE '%test%' limit 10),Opportunity(Id, Name WHERE Name LIKE '%test%' limit 10),Lead(Id, Name WHERE Name LIKE '%test%' limit 10)];

Account [] accounts = ((List<Account>)searchList[0]);
System.debug('Printing size-- '+accounts.size());
System.debug('Printing size-- '+accounts );

Contact [] contacts = ((List<Contact>)searchList[1]);
System.debug('Printing size-- '+contacts.size());
System.debug('Printing size-- '+contacts);

Opportunity [] opportunities = ((List<Opportunity>)searchList[2]);
System.debug('Printing size-- '+opportunities.size());
System.debug('Printing size-- '+opportunities);

Lead [] leads = ((List<Lead>)searchList[3]);
System.debug('Printing size-- '+leads.size());
System.debug('Printing size-- '+leads);


Friday, 4 September 2015

How will external system get SFDC service endpoint URL dynamically

Hi All,

This post is all about to avoid an integration issue(Service not available or invalid session id) when instance url get changed in SFDC. From SFDC side no need to perform any action ,but we can suggest appropriate approach of fetching endpoint url to external system so that communication will be smoother.

For an inbound integration SFDC has to provide two WSDL to external system.

  1. Partner WSDL (Required to generate session id )
  2. Service WSDL
In the service wsdl the endpoint URL will be <soap:address location="https://cs15.salesforce.com/services/Soap/class/YourWebserviceClassName"/>

So the external system will add endpoint URL in a property file or in some in configuration stuff, that is how webservice works.As we all know instance (cs15) used to change from environment to environment (QA to UAT), and instance will  also change when SFDC plan for refreshment of server. At that time we have to update external team about the new url otherwise they wont be able to connect the SFDC service. In order to avoid such issues,external system should follow below approach to get endpoint URL dynamically.

Solution
  1. Create stub classes for both WSDL(Partner and service).
  2. Invoke stub class's (generated from partner wsdl) below method.
public partnerSoapSforceCom.LoginResult login(String username,String password) {
            partnerSoapSforceCom.login_element request_x = new partnerSoapSforceCom.login_element();
            request_x.username = username;
            request_x.password = password;
            partnerSoapSforceCom.loginResponse_element response_x;
            Map<String, partnerSoapSforceCom.loginResponse_element> response_map_x = new Map<String, partnerSoapSforceCom.loginResponse_element>();
}

3. Login method will return below result.
public class LoginResult {
        public String metadataServerUrl;
        public Boolean passwordExpired;
        public Boolean sandbox;
        public String serverUrl;
        public String sessionId;

        public String userId;
        public partnerSoapSforceCom.GetUserInfoResult userInfo;
        private String[] metadataServerUrl_type_info = new String[]{'metadataServerUrl','urn:partner.soap.sforce.com',null,'1','1','true'};
        private String[] passwordExpired_type_info = new String[]{'passwordExpired','urn:partner.soap.sforce.com',null,'1','1','false'};
        private String[] sandbox_type_info = new String[]{'sandbox','urn:partner.soap.sforce.com',null,'1','1','false'};
        private String[] serverUrl_type_info = new String[]{'serverUrl','urn:partner.soap.sforce.com',null,'1','1','true'};
        private String[] sessionId_type_info = new String[]{'sessionId','urn:partner.soap.sforce.com',null,'1','1','true'};
        private String[] userId_type_info = new String[]{'userId','urn:partner.soap.sforce.com',null,'1','1','true'};
        private String[] userInfo_type_info = new String[]{'userInfo','urn:partner.soap.sforce.com',null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{'urn:partner.soap.sforce.com','true','false'};
        private String[] field_order_type_info = new String[]{'metadataServerUrl','passwordExpired','sandbox','serverUrl','sessionId','userId','userInfo'};
    }

4. Take both sessionId and ServerUrl from login result class.
<serverUrl>https://cs15.salesforce.com/services/Soap/u/34.0/00De0000005VVRj</serverUrl>

<sessionId>00De0000005VVRj!AQ4AQCaFYonDr06YPr.lRtb7gHlmAMW8R9pFKRUvwJAyTUZrtET9puPvtRDe8By7_cI9j9QLVvaKukkn2E90fEAt.PlqULKA</sessionId>

5.From the response get value of service URL value and keep only yellow colored part (https://cs15.salesforce.com/services/Soap/) then append (class/YourWebserviceClassName) because class name is not going to be changed.

Now the desired endpoint URL will look like
https://cs15.salesforce.com/services/Soap/class/YourWebserviceClassName.

Note- With this approach external system will always get endpoint url dynamically , if instance url get changed they will get it in the response itself,  No need to update new endpoint url in the property file.

6. Now the final step they will setsessionId and new endpoint url before calling our service wsdl method.

For partner wsdl

Before providing partner wsdl to external system, SFDC team has to change address location as  below.
<soap:address location="https://test.salesforce.com"> for sandbox
<soap:address location="https://login.salesforce.com"> for production/developer org

How to make pageblock section to be collapsed by default

Hi All,

We can achieve it through java script.

<apex:page standardController="Account">
<apex:form>
<apex:pageBlock id="block1">
    <apex:pageBlockSection id="section1" columns="2" collapsible="true" title="Collapsebale Section">
        <apex:inputField value="{!Account.Name}"/>
         <apex:inputField value="{!Account.Phone}"/>
    </apex:pageBlockSection>
    
<script> twistSection(document.getElementById('{!$Component.block1.section1}').getElementsByTagName('img')[0]) </script>
</apex:pageBlock>
</apex:form>
</apex:page>

Normal Section


Collapsed Section  

Tuesday, 11 August 2015

How to Override Go button in SFDC(Overriding List view In SFDC )

Hi All,

I had come across a scenario like to override a button so called "Go" in standard page.As we all know,when Go button clicked,it will always navigate to sfdc standard list view. What if you want to navigate to your custom page? How can we achieve it?


It is very easy, please go through below image.











Thursday, 23 July 2015

Hyperlink formula is not working(Instance URL is getting appended along with the external link)

HI Guys,

This post is regarding an issue i had come across at my development work. I had to display a hyper link to navigate to some other site from a standard layout. That link varies from record to record.
So I created a text field(Brass_Link__c) to store the link and created a hyperlink formula field(Brass_Hyper_formula__c) to display "view " as link if text field is having some value.

Below is the formula field logic
IF(BRASS_Link__c <> null, HYPERLINK( BRASS_Link__c , "View"), "")

BRASS_Link__c - Stores link 



How will we solve above issue?
Its quite simple change the link from www.google.com to https://www.google.com

Saturday, 18 July 2015

How to wrap page block title in a single line?

Hi All,

This is so simple .You have to just include some css code in the VF page.


</script>
    <style>
     
        .pbTitle {
        white-space: nowrap
       
    }
    </style>


Thank you very much.

Saturday, 4 July 2015

How to control two batch job execution ?

We are all familiar with batch class in SFDC. This  post is all about to discuss a known issue in batch class and what is workaround for that?

As we know batch class is is required when we are dealing with large number of records and total number of batch job will be decided based on scope parameter (defined while calling a batch class) and total number of records.
Say total number of records = 100
Scope parameter = 5.  Database.executeBatch(new batchclass(),5);
Then batch job will be 20 which means each job will process 5 records.

We can see how many jobs are pending and how many jobs completed in set up-->apex jobs.

While one batch is in progress we invoke same batch class another time having batch size 5 and total number of records 50. Ideally number jobs should be 10 but actually it will be 10 + number of progressing job of previous batch. Which causes data redundancy that means same records will be processed two times in both the batch.This is the known issue in batch class.

The prime motto is two batch should not pic same records.

Let me share the issue what i had come across. External system were passing all the data to SFDC (SFDC had exposed a service to receive data from) then i was storing in staging table(temporary obj) then i was calling batch class after data is inserted in staging table to push into original object.I was calling batch class from a trigger.let say batch size is 5 and 20 records inserted in staging obj then obviously batch will be invoked and 4 jobs will be progress. While third batch job is running another 30 set of records inserted in staging obj then again batch will be invoked and total number jobs will be 30/5=6+ two jobs of previous batch  = 8 jobs will be in progress.That means 2jobs= 10 records will be processed two times.In our original object 50 records should be created but actually total number if records will be 55. 5 duplicate records which is an issue.

Solution :-

  •  Create a flag(check box field) in staging obj. When original records will be created set that flag is true so that after one week these records will be deleted from staging obj.
  • Create a class where check whether batch is in progress or not if not call batch class
  • Scheduler same class every one minute interval until all the progress batch job is completed and check if there is few records to be processed in staging obj.
  • Call same class from trigger if same class is not scheduled.
Technical Details:-
String batchClassId = '01pS0000000Fm2W';
String  schedulerclassId = '01pS0000000FvKF';

global class Scheduling_Svc_WS_CreateBatch implements Schedulable{    // Execute method     global void execute(SchedulableContext SC) {     // Code to be executed when the schedule class wakes up           // code           list<BRASS_Case__c > listOfBrassCases;           list<AsyncApexJob> jobList;           try{                jobList = [select id,ApexClassID,JobType,Status from AsyncApexJob where ApexClassID =:batchClassId AND Status ='Processing'];                listOfBrassCases  = [select id from BRASS_Case__c where Is_Org_Case_Created__c !=true];                          if(jobList.size()==0){             //String cronID = System.scheduleBatch(new Svc_WS_CreateCaseBatch(), 'original case creation', 5);             Database.executebatch(new Svc_WS_CreateCaseBatch(),5);                        }           }catch(QueryException ex){             system.debug('pringint exception---'+ex);           }            // This section of code will schedule the next execution 1 minutes from now     if(listOfBrassCases.size()>0 && (!(jobList.size()>0) || jobList.size()>0)){       datetime nextScheduleTime = system.now().addMinutes(1);         string minute = string.valueof(nextScheduleTime.minute());         string second = string.valueof(nextScheduleTime.second ());         string cronvalue = second+' '+minute+' 0-23 * * ?' ;         string jobName = 'selfReschedulingClass ' +nextScheduleTime.format('hh:mm');           Scheduling_Svc_WS_CreateBatch p = new Scheduling_Svc_WS_CreateBatch();       system.schedule(jobName, cronvalue , p);       system.abortJob(sc.getTriggerId());               }     else{       // this section of code will abort the current schedule job       system.abortJob(sc.getTriggerId());       }              }  }

From Trigger you call above class like this
try{
                list<AsyncApexJob> jobList = [select id,ApexClassID,JobType,Status from AsyncApexJob where ApexClassID =cAND Status ='Queued'];
                if(!(jobList !=null && jobList.size()>0)){
                    datetime nextScheduleTime = system.now().addMinutes(1);
                    string minute = string.valueof(nextScheduleTime.minute());
                    string second = string.valueof(nextScheduleTime.second ());
                    string cronvalue = second+' '+minute+' 0-23 * * ?' ;
                    string jobName = 'selfReschedulingClass ' +nextScheduleTime.format('hh:mm');
                 
                    Scheduling_Svc_WS_CreateBatch p = new Scheduling_Svc_WS_CreateBatch();
                    system.schedule(jobName, cronvalue , p);
                }
                
     
           }catch(Exception ex){
           }


Friday, 26 June 2015

UNABLE_TO_LOCK_ROW Error during deployment.

Hi All,

I came across an issue (UNABLE_TO_LOCK_ROW) while deploying and validating change set. As you know all the test classes run when a change set is validated or deployed,one of the test class was throwing UNABLE_TO_LOCK_ROW exception.


How will you handle above exception?

Ans- Setup--Develop-- Apex Test Execution--Click Options--Checked Disable Parallel Apex Testing.


Sunday, 21 June 2015

Passing JavaScript in Page reference method.

The below post is all about closing child window and refreshing parent window after updating record.

http://salesforceworld4u.blogspot.in/2015/06/closing-child-window-and-refreshing.html

But let's think there is a requirement like we have to validate before updating and closing child window then above approach wont work.

For the above requirement we have to pass javascript code in pagereference method instead of calling javascript on button click.

public PageRefeRence savingAccount(){
        PageRefeRence pageRef ;
        if(account.name == ''){
            ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.Error,'You must enter some value...');
            ApexPages.addMessage(myMsg);
        }
        else{
            upsert account;  
        }
     
        pageRef = new PageReference('javascript:window.opener.location.href='+'\'/'+account.ID+'\';window.close();');
     
        return pageRef ;

Thursday, 11 June 2015

Closing the child window and Refreshing parent window.

As we all know there are many window properties are available so it is quite easy even i had thought same thing but while implementing i faced many issue so i thought of sharing.

Below are few window property which are useful.

·         window.opener refers to the window that called window.open( ... ) to open the window from which it's called
·         window.parent refers to the parent of a window in a <frame> or <iframe>
·         window.top refers to the top-most window from a window nested in one or more layers of <iframe> sub-windows.

Lets say there is button on account "Change Account Name" ,On clicked one popup is opening and which would allow you to change Account name and one button "Save" is there in popup window. On clicked child window will be closed and account name will updated with the new name.

Approach:-
Step-1 Create vf page

<apex:page standardController="Account" extensions="PopuptestForAccount" showHeader="false" sidebar="false">
   
<script type="text/javascript">
       
     function Callmefunc(){
        window.top.location.href = "/"+'{!account.ID}';
       window.close();// optional.not required but better to keep it. 
     }
   </script>
    <apex:form > 
    <apex:pagemessages />
        <apex:pageBlock id="testblock">
            <apex:pageBlockSection >
                <apex:inputField value="{!account.name}"/>
                <apex:commandButton value="save"  action="{!savingAccount}" oncomplete="Callmefunc();" />
            </apex:pageBlockSection> 
        </apex:pageBlock>
    </apex:form>
</apex:page>
Step-2:-Create an extension class
public class PopuptestForAccount{
    public Account account{get;set;}
    public PopuptestForAccount(ApexPages.StandardController controller){
        this.account = (Account)controller.getRecord(); 
    }
    public PageRefeRence savingAccount(){
       
        if(account.name == ''){
            ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.Error,'You must enter some value...');
            ApexPages.addMessage(myMsg);
        }
        else{
            upsert account;
            
        }
         return null;
    }
}
Step-3 :-Create custom button on account and choose above page as content source.

Refer this link for to create custom button.


Wednesday, 10 June 2015

How to schedule one class to run in every 1 mins?

Sometimes we need to run a class in every minute to do some operation.


    // This section of code will schedule the next execution 1 minutes from now
   global class Scheduling_Svc_WS_CreateBatch implements Schedulable{

 // Execute method
    global void execute(SchedulableContext SC) {

         datetime nextScheduleTime = system.now().addMinutes(1);
         string minute = string.valueof(nextScheduleTime.minute());
         string second = string.valueof(nextScheduleTime.second ());
         string cronvalue = second+' '+minute+' 0-23 * * ?' ;
         string jobName = 'selfReschedulingClass ' +nextScheduleTime.format('hh:mm');
         Scheduling_Svc_WS_CreateBatch p = new Scheduling_Svc_WS_CreateBatch();
          system.schedule(jobName, cronvalue , p);
         // this section of code will abort the current schedule job
         system.abortJob(sc.getTriggerId());
    }
}
  

Friday, 15 May 2015

How to check accessibility of an user on a particular record ?

It is a very challenging requirement, Generally we will update records through trigger for complex requirement.
 Lets think a scenario where we have to update a particular field value(say field name-IsUpdate) on an Opportunity and few profile is having editable access to that field,there is a already a trigger written for other purpose(updating some other thing) on Opportunity,So we have to modify same trigger and add our logic in that trigger.
Our first and foremost approach  would be checking profile name in the condition as below.

Approach-1(Using profile)

Assume that profile "Test_profile_name" is having editable access to that field(IsUpdate)
Profile ProfileName = [select Name from profile where id = :userinfo.getProfileId()];
for(Opportunity opp:trigger.new){

     if(profileName.Name.containsIgnoreCase('Test_profile_name')){
   
          // opp.IsUpdate = true;
     }
}

It will work fine no doubt, But let assume we have more than 100 profiles having editable access then we have add each profile name in same condition separated by OR.

if(profileName.Name.containsIgnoreCase('Test_profile_name') OR profileName.Name.containsIgnoreCase('Test_profile_name')...................)

What if profile name is renamed or deleted then also it wont work. So finally above approach is not good at all.

Approach-2(Enforcing Object and Field Permissions)

We can avoid above issue by using sobject describe result method.

if (Schema.sObjectType.Opportunity.fields.IsUpdate.isUpdateable()) {
   // Update Opportunity IsUpdate
}

This approach is 90% right still some problem is there, By this approach we can check object level access but what about record level access ? As we are dealing with record(updating record) we have to check record level accessibility.

It is quite often that one user may have object level edit access still he/she cant edit particular record.

Approach-3(Using UserRecordAccess object).

You can write query to fetch user access to a record 

UserRecordAccess  = [SELECT RecordId, HasReadAccess, HasTransferAccess, MaxAccessLevel
                     FROM UserRecordAccess
                     WHERE UserId = [single ID]
                     AND RecordId = [single ID]
 
or 
 
SELECT Id, Name, UserRecordAccess.HasReadAccess, UserRecordAccess.HasTransferAccess, UserRecordAccess.MaxAccessLevel 
      FROM Opportunity
for more details 
https://www.salesforce.com/developer/docs/api/Content/sforce_api_objects_userrecordaccess.htm
 

Thursday, 14 May 2015

How to call apex class from process builder?

As we all know it is not possible to invoke apex class from work flow,for that purpose sfdc lunched new functionality called process builder.

Please go through this link. In my previous post i have explained about creation of process builder and updating a field through process builder.

Now this is post is all about calling an apex class from process builder.

public class DeleteBrassCaseUtil{

  @InvocableMethod(label='Get Brass Cases Names' description='Returns the list of Brass Cases corresponding to the specified Brass Cases IDs.')
  public static void deleteBrassCase(List<Id> BrassCaseIds)
    {
        List<BRASS_Case__c> brassCases =[SELECT Id,Is_Org_Case_Created__c FROM BRASS_Case__c WHERE Is_Org_Case_Created__c =true AND id IN :BrassCaseIds];
 
        delete brassCases;
    }
}

The annotation "@InvocableMethod" defines this method can be invoked from process builder. This class will delete some custom object records based on meeting criteria.

Below is the process builder.