Pages

Friday, March 1, 2013

Adding Custom Campaign Member Status

Hello Friends,
Today am gonna show you how to add custom status values for a campaign member while adding campaign members to the campaign in salesforce.com.

Requirement:-  Business needs to have additional values to choose while adding campaign members to a particular campaign recordtype. Salesforce provides only two values to choose from while adding campaign members to a campaign. Now a specific set of business users need to have additional values to choose while adding up campaignmembers.


Solution:
We cannot add or remove the values to this dropdown through customization's. In order to achieve this business need, I have written a trigger on the campaign object to remove the old values and Add new values to the dropdown. 



trigger Campaign_AI on Campaign (after insert,after update) {


List<CampaignMemberStatus> cms2Delete = new List<CampaignMemberStatus>();
    List<CampaignMemberStatus> cms2Insert = new List<CampaignMemberStatus>(); 


RecordType rt = [Select Id, Name from RecordType where Name = 'Meeting' limit 1];
    //change default member statuses (Sent and Responded) for                        //select campaigns
    Set <Id> cmpns = new Set <Id>();    
    for (Campaign c: trigger.new){ 
        if (c.RecordTypeId == rt.Id)
            cmpns.add(c.Id);
    }

    for (CampaignMemberStatus cm: [Select Id, Label, CampaignID  FROM CampaignMemberStatus WHERE CampaignID IN :cmpns]){
      if(cm.Label == 'Responded' ){
            cms2Delete.add(cm);
      }  else if(cm.Label == 'Sent'){           
    //          cms2Delete.add(cm);
            cm.SortOrder = 5; 
            cms2Insert.add(cm);
            CampaignMemberStatus cms1 = new CampaignMemberStatus(CampaignId=cm.CampaignID, Label='Active', HasResponded=false, IsDefault = True, SortOrder=3);          
            System.debug(cms1);         
            cms2Insert.add(cms1);
            CampaignMemberStatus cms6 = new CampaignMemberStatus(CampaignId=cm.CampaignID, Label='Send Email', HasResponded=false, SortOrder=4);
            System.debug(cms6);
            cms2Insert.add(cms6);
            CampaignMemberStatus cms3 = new CampaignMemberStatus(CampaignId=cm.CampaignID, Label='Accepted', HasResponded=true, SortOrder=6);
            System.debug(cms3);
            cms2Insert.add(cms3);   
            CampaignMemberStatus cms4 = new CampaignMemberStatus(CampaignId=cm.CampaignID, Label='Declined', HasResponded=true, SortOrder=7);
            System.debug(cms4);
            cms2Insert.add(cms4);   
            CampaignMemberStatus cms8 = new CampaignMemberStatus(CampaignId=cm.CampaignID, Label='Tentative', HasResponded=true, SortOrder=8);
            System.debug(cms8);
            cms2Insert.add(cms8);   
            CampaignMemberStatus cms5 = new CampaignMemberStatus(CampaignId=cm.CampaignID, Label='Attended', HasResponded=true, SortOrder=9);
            System.debug(cms5);
            cms2Insert.add(cms5);
            CampaignMemberStatus cms7 = new CampaignMemberStatus(CampaignId=cm.CampaignID, Label='Cancelled', HasResponded=true, SortOrder=10);
            System.debug(cms7);
            cms2Insert.add(cms7);
            CampaignMemberStatus cms9 = new CampaignMemberStatus(CampaignId=cm.CampaignID, Label='Invited', HasResponded=true, SortOrder=11);
            System.debug(cms9);
            cms2Insert.add(cms9);                                             
      }

    } 
    //perform insert before delete because system requires at //least one CMS for a Campaign
    upsert cms2Insert;
    delete cms2Delete; 
}



use sort order to arrange the dropwown values.

once this trigger is saved we can go back and crosscheck the to see the Add with Status values that are available while adding campaign members to a campaign.

** make sure you go the campaign that is of the record type that we mentioned in the trigger.(In this case "Meeting")



This is how i met the business needs.
hopefully this will help you.


happy coding.

Wednesday, February 27, 2013

Mass Updating records with Visualforce pages

Mass updating records:
Well the first thing that strikes everyone is to use "Data-Loader". Now if there is a need that we have to give this functionality to the end user and they are not comfortable to use Data-Loader. They wanted more out of the platform,like the ability to search for the desired records and update them at once.
Business use case can be any thing like below :


  • Updating the cases with a particular status or
  • Updating the selected Accounts fields or 
  • Updating the lead source created today by any particular user or
  • updating the records that might have same Name or any thing like this which involve manual searching and updating the selected records.
We can make this possible using Visualforce pages and its controllers with wrapper methods.
In order to show this more detail, I have created a custom Tab for the visualforce page and called it as Account MassUpdate as shown below:



On clicking the tab,It will be redirected to our visualforce page. Now you can see that there is a search button. Put any character or word to search for all 
the accounts starting with that value.


In this case i have just used a single character "g "  to search the Account object and it resulted in 2 records that start with  letter "g". if we can think that there can be hundreds or thousands of records resulting in search, we can add up another input field to refine our search. More over we can add pagination to it also.


We can observe one other thing after the search i have given the functionality of multiple selection or checkboxes and check All check box, this will help user a lot in real time.


Now once we have selected the records that needs to be updated and click on Update selected Accounts,
it will show up another section where you can actually update your records. In this case i have used only few fields to while updating. we can change it to meet any business need. 
Once the new values are entered click on Update Accounts button, This will do the stuff for You. I will update the Accounts the new values mentioned. we can cross check this by going back to the Account records. 
 Hope fully this will help people who are searching for the solution of Mass Updating  records.

***With the size limitation of the post am not able to provide code on this post. But if you need a sample code or any approach feel free to drop me an email.

Happy Coding.

Tuesday, February 26, 2013

Error on Fetching, Saving ,Refreshing and Creating force.com Project in Eclipse.


Hi Guys,
Recently I was trying to update some of my code on Eclipse.  It was throwing so wearied Error that i havent seen before.
  
Save error: Unable to perform save on all files: com.salesforce.ide.api.metadata.types.Metadata$JaxbAccessorF_fullName cannot be cast to com.sun.xml.internal.bind.v2.runtime.reflect.Accessor Antibiogram_Survey.page/Cubist Dev/src/pages line 1Force.com save problem

Then i thought may be i have older version of code on my eclipse and i was trying to refresh from the instance and the same error message showed up again. 

Then I thought may be my project got screwed up and was trying to create a new Force.com project, and the error was back.This was driving me crazy and went on doing google and found few solutions online.
  • Downgrading JRE to 1.6 instead of 1.7.
  • Working as an Admin.
  • using -clean
  • Switching between the workspaces.
Then with the above options i was trying to see which option will fix my problem. Firstly I was trying to downgrade my JRE but found it to be  little difficult and lengthy process.
Then i wanted some thing quick to solve my problem. I choose to use switching workspace. magically it started working. 
Follow the following steps to switch between workspaces.
  • Open your eclipse
  • File > Switch workspace >other
  • Now select the same workspace and click on  "ok"
  • This will restart your Eclipse and read to use.
Note : Make sure to copy all your code modifications before choosing this option. Since eclipse will restart after switching between workspaces and all the unsaved data will be lost.


I haven't got a chance to test and comment on the use of "-clean" way of fixing this issue. Eclipse say -clean will remove the loading and cache problems.

hope this helps.


Happy coding. 

Multiple Trigger's on an Object in Salesforce.com

Aim :-Combining Multiple triggers on an object to a Single trigger:

This post is about he error's that arise when you have More than 1  trigger on any Object.
Salesforce.com or force.com platform gives you a feasibility to write more than 1 trigger on any standard or custom object. which is a bad practice.
These Multiple triggers on an object which tend to Fire at specific DML operations or an events, may sometimes fire other triggers on the object and result in unnecessary data changes(Data corruption )  or recursive triggering or Show some wearied errors and break the business process.

 Salesforce.Com  says it's always a good practice to maintain  a single trigger on any object. To meet different business logic on the the same object we might want to have different triggers on the object.
This can be solved by using simple techniques as shown below.
  • Make your trigger to fire on a criteria.
  • Try and create methods or apex classes where you can put all logic.Your trigger should initiate and process logic in methods.
  • Make sure write code to meet governor limits.
Here is the sample how to write you trigger :

trigger TriggerName on ObjectName (after insert, before update,after update, before delete) 
{
    if(Trigger.isBefore)
    {  
        if (Trigger.isUpdate) 
        {
            CheckAndDeleteOldRecords();
        }    
        if(Trigger.isDelete) 
        {
            DeleteRelatedCases();
        }
    }      
    if(trigger.isAfter)
    {
        if(Trigger.isInsert) 
        {
            MigrateContacts();  
        }        
        if (Trigger.isInsert || Trigger.isUpdate) 
        {
            CheckAndCreateCasesAndTasks();
            if(Trigger.isUpdate)
            {
                UpdateYearSummaryWithStatus();
                UpdateStatus();
                ApprovalSubmitterForCase();
            }
        }     
    }  /// End of trigger 

/// These methods can be in the same trigger but should start after the trigger.

private void UpdateStatus()
    {
      for(Contact c :trigger.new)
      {
       // Do your code here.
       }  
    }
private void CheckAndDeleteOldRecords()
    {
      for(Contact c :trigger.new)
      {
       // Do your code here.
       }  
    }
private void ApprovalSubmitterForCase()
    {
      for(Contact c :trigger.new)
      {
       // Do your code here.
       }  
    }
private void UpdateYearSummaryWithStatus()
    {
      for(Contact c :trigger.new)
      {
       // Do your code here.
       }  
    }

So On...
This will reduce the risk and unwanted errors.Hoping this will help you.
Happy Coding.


Friday, February 1, 2013

Upgrading from Eclipse Indigo to Eclipse Juno


Hi friends,
Firstly its a good news that we have an upgraded IDE from Eclipse it is called as Eclipse Juno.
This version is little fancy than the previous version and few other upgrades.

Explore whats new in Juno.

Upgrading to JUNO is not smooth  The original download file is missing some plugins for UI. so what shall we do to have all this. 
Its simple we have to add those missing plugins to the newly downloaded folders.
go to the following link to download the missing plugins,
Extract the files and drop them into the newly downloaded eclipse plugins folder.

(/eclipse/plugins)

Now launch your exlipse Juno and go to  /Help/Install New Software's.
Click on the Add button and add the Force.com site to it.
select the check box and proceed you will see the force.com plugins getting installed without any errors. 
Now restart the IDE(eclipse) you will see a new and enhanced and fancy IDE to work with.

Happy Coding.
Thank you Eclipse.


Explore whats new in Juno.

List has no rows for assignment to Sobject



Today i was trying to write some test methods and was queering an object to get some values.
but i was thrown this error 
"list has no rows for assignment to Sobject"
I crosschecked everything and found nothing was wrong.
I was so like Debugging debugging and the result was coming to Null.
I tried to recollect everything i know and i did in the past.

Then i have figured it out that unless u tell your test method to see all data it will just see things that you have created @ that instance.
To make it work all you have to do is  make your test method to see all data.
this can be achieved by  making your first line of code to look like this
" @isTest (SeeAllData = true) " 
with this your Test method will get the ability to read or Query the records of the objects.

Hari Padmanaban showed this to me few month back but with a human tendency of forgetting things, i never thought of it  and started debugging. when i realized it my self, i thought of sharing this by by posting it and starting my Bolg.

hopefully this will be a good starting point for CloudSolutions...........

Happy Coding.

Accessing History of a custom or standard object


Tracking History of Salesforce Objects.....

Hi Friends,
Tracking down history of fields in salesforce custom objects is very simple and wellknown fact to most of us. 
If you dontknow it here is the procedure:
Go to: Setup-->App Setup-->Create-->object--> choose your custom object--> Edit
now Scrole down to see Optional features now enable or check Track Field History check box and save it. Now Once the track history is enabled you can see a new button showing up in  Custom Fields & Relationships  section of the Custom object page.
now all you have to do is hit the button and set history tracking to the fields.
All this is a known thing to all salesforce developers and admins.

My reason for this post is explain what's happening on checking  Track Field History checkbox on the object level. Can we control this object and modifications made on the object's record level.
Here is the explanation: 
whats happening is As soon as we check the check box and hit save on the object level.
Salesforce is creating an object(child object to the current object) which is not visible on 
Setup-->App Setup-->Create-->object page. This is just a read only object making users to read the records of the object. when ever there is a change to the track history field a record is created to thisobject with filed name old value new value parentId and user who chenged it. That is waht we are seeing in the related list of the object as chenges made on the record.
every thing is fine now the question is to why do we have to worry if about this object now. Consider a secinario where you have to take an action onthe record o lockthe record after certain number of changes have been done to the record irrespective to the number of changes on pirticular field or fields.  At this point i wanted to Querie the Hidden object to find the number of records created for each object on every change. 
in order to Query the number of records createdd to the new object we have to see it and Querie it and we salesforce gives permissions to see it thats it now we have to find the name of the object to querie it. 
Salesforce have a naming convention to this every time a new History object is created salesforce names it as custom_object__History. insted of __C for custom things it appends the object as __History.  try this use this in quering in your triggers and apex classes and make coding more comfortable.

Main points:  
  • All history Objects created by salesforce readonly and hidden
  • you can access this object by using Custom_Object__History append by__H insted of__C 

Hope this Post helps you.
You are free to Comment or ask questions on this post.


Happy Coding.