Total Pageviews

Thursday, October 9, 2014

Shortie on Analytic Report Chart API

Its a busy world and everyone wants all the important information at the click of a button, and that too in a single screen. Salesforce used dashboards  to showcase multiple information in one screen, but different people have different needs. Many people wanted charts to be combined with their normals screens hence salesforce provided "Apex Analytics API and Report Chart Component" to enable developers to build snazzy interfaces coupled with:-
1. Widgets
2. Charts (Based on reports)
3. Usual VF components

The Analytics API has been made available in Apex in the Spring ’14 release (API version 30).

We can use Analytics API along with the Visualforce component <analytics:reportChart>  to build informative and pictoral UIs.
<analytics:reportChart> had been made Generally Available (GA) in the Spring ’14 release .
 Use <analytics:reportChart> component to add Salesforce report charts to a Visualforce page. One can filter chart data to show specific results. The component is available in API version 29.0 or later.

Syntax to use report charts in VF page

<analytics:reportChart reportid="{The unique ID of the report you want to display}"  size="{tiny/small/medium/large/huge}"  showRefreshButton="{A Boolean indicating whether to add a refresh button to the chart.}" hideOnError="{Use the attribute to control whether users see a chart that has an error.}" filter="{Most Important Attribute so lets discuss this in detail}"/>

Filter Attribute of analytics:reportChart component

The attribute is used to filter a report chart by fields in addition to field filters already in the report to get specific data. 
Note that a report can have up to 20 field filters. 
A filter has these attributes in the form of a JSON string: 
  1. column: The API name of the field that you want to filter on. 
  2. operator:The API name of the condition you want to filter a field by. For example, to filter by "not equal to," use the API name "notEqual." 
  3. value: The filter criteria.


<analtics:reportchart reportid="" size="tiny" filter="[{column:'STAGE_NAME',operator:'equals',value:'Prospecting'}]"/>

Many times while defining the filter you may mention the API names of the fields and on running the page you will encounter "Filter exceptions".
Please note API name on the field and the API name of Column to be used in filter attribute may be different.

Column does not exist or is not filterable

To get the API name of the field and the operator, make a describe request via the Salesforce1 Reporting REST API or Salesforce1 Reporting Apex Library as shown in following examples (I used the 2nd option in developer console and got it printed):

  • Salesforce1 Reporting API {OrgURL}/services/data/v29.0/analytics/reports/00OD0000001ZbNHMA0/describe
  • Salesforce1 Reporting Apex Library                                    First,get report metadata from a describe request:      Reports.ReportManager.describeReport(00OD0000001ZbBBFFF)
I got output as follows and searched for the column name which I wanted in my case it was a field Account__c and in the output below it was displayed as "IB_Asset__c.Account__c.Id":-

DEBUG|Reports.ReportDescribeResult[reportExtendedMetadata=Reports.ReportExtendedMetadata[aggregateColumnInfo={RowCount=Reports.AggregateColumn[acrossGroupingContext=null, dataType=INT_DATA, downGroupingContext=null, label=Record Count, name=RowCount]}, detailColumnInfo={IB_Asset__c.Account__c.Name=Reports.DetailColumn[dataType=STRING_DATA, label=Account: Account Name, name=IB_Asset__c.Account__c.Name], IB_Asset__c.Japan_Modality__c=Reports.DetailColumn[dataType=STRING_DATA, label=Modality, name=IB_Asset__c.Japan_Modality__c], IB_Asset__c.Name=Reports.DetailColumn[dataType=STRING_DATA, label=IB Asset Name, name=IB_Asset__c.Name], IB_Asset__c.Product_Code__c=Reports.DetailColumn[dataType=STRING_DATA, label=Product Code, name=IB_Asset__c.Product_Code__c]}, groupingColumnInfo={IB_Asset__c.IB_Asset_Age__c=Reports.GroupingColumn[dataType=STRING_DATA, groupingLevel=0, label=IB Asset Age, name=IB_Asset__c.IB_Asset_Age__c]}], reportMetadata=Reports.ReportMetadata[aggregates=(RowCount), currencyCode=USD, detailColumns=(IB_Asset__c.Name, IB_Asset__c.Account__c.Name, IB_Asset__c.Japan_Modality__c, IB_Asset__c.Product_Code__c), developerName=IB_Asset_By_Age, groupingsAcross=null, groupingsDown=(Reports.GroupingInfo[dateGranularity=NONE, name=IB_Asset__c.IB_Asset_Age__c, sortAggregate=null, sortOrder=ASCENDING]), historicalSnapshotDates=null, id=00Of0000000PQbgEAG, name=IB Asset - By Age, reportBooleanFilter=null, reportFilters=(Reports.ReportFilter[column=IB_Asset__c.Account__c.Id, operator=equals, value=]), reportFormat=SUMMARY, reportType=Reports.ReportType[label=@IB Assets, type=IB_Assets__c]], reportTypeMetadata=Reports.ReportTypeMetadata[categories=(Reports.ReportTypeColumnCategory[columns={IB_Asset__c.Account_City__c=Reports.ReportTypeColumn[dataType=STRING_DATA, filterValues=null, filterable=true, label=Account City, name=IB_Asset__c.Account_City__c], IB_Asset__c.Account_Country__c=Reports.ReportTypeColumn[dataType=STRING_DATA, filterValues=null, filterable=true, label=Account Country, name=IB_Asset__c.Account_Country__c], IB_Asset__c.Account_Public_Private__c=Reports.ReportTypeColumn[dataType=PICKLIST_DATA, filterValues=(Reports.FilterValue[label=Yes, name=Yes], Reports.FilterValue[label=No, name=No]), filterable=true, label=Public Account, name=IB_Asset__c.Account_Public_Private__c], IB_Asset__c.Account_Region__c=Reports.ReportTypeColumn[dataType=STRING_DATA, filterValues=null, filterable=true, label=Account Region, name=IB_Asset__c.Account_Region__c], IB_Asset__c.Account_Site__c=Reports.ReportTypeColumn[dataType=STRING_DATA, filterValues=null, filterable=true, label=Account Site, name=IB_Asset__c.Account_Site__c], IB_Asset__c.Account_State__c=Reports.ReportTypeColumn[dataType=STRING_DATA, filterValues=null, filterable=true, label=Account State, name=IB_Asset__c.Account_State__c], IB_Asset__c.Account_Zone__c=Reports.ReportTypeColumn[dataType=STRING_DATA, filterValues=null, filterable=true, label=Account Zone, name=IB_Asset__c.Account_Zone__c], IB_Asset__c.Account__c.Id=Reports.ReportTypeColumn[dataType=ID_DATA, filterValues=null, filterable=true, label=Account: Account ID, name=IB_Asset__c.Account__c.Id], IB_Asset__c.Account__c.Name=Reports.ReportTypeColumn[dataType=STRING_DATA, filterValues=null, filterable=true, label=Account: Account Name, name=IB_Asset__c.Account__c.Name], IB_Asset__c.Account__c.UltimateParentId__c=Reports.ReportTypeColumn[dataType=STRING_DATA, filterValues=null, filterable=true, label=Account: UltimateParentId, name=IB_Asset__c.Account__c.UltimateParentId__c], ...}, label=IB Assets])]]

This is how I used the ReportChart tag

<analytics:reportChart reportid="00OD0000001ZbBBFFF"  size="tiny"  showRefreshButton="truehideOnError="false" filter="[{column:'IB_Asset__c.Account__c.Id',operator:'equals',value:'{!AccountId}'}]"/>

Thursday, September 4, 2014

Salesforce Summer 14 Developer Release Exam Important Info

Summer ‘14 Certification Maintenance for Developer

To prepare for the exam, Certified Developer Summer ‘14 Certification Maintenance,

Access the Release Training here:

Download the Release Notes here:

You will have 3 attempts to pass the exam. There are 5 exam questions and the passing score is 80%.

Last Date:
October 31, 2014, prior to the next release (Winter ‘15).

Please visit the schedule page for exact details:

Folks and Friends dont forget the important dates ...

Sunday, August 17, 2014

Curious Case of Parent Account and Child Accounts!!

Parent-Child Accounts in Salesforce

Account Hierarchy

Each one of us might have been plagued by the question of "Extracting an Account and all its children, grand-children ,etc.. accounts in a single query" . Did u find any easy answers?
Well first of all you would wonder what should be format of such a query? 
Okay! lets says what about something like:-

Select id,name, (Select id, name, from Parent ) from Account

I am penning this blog after wadding a lot in the search results thrown by google. So you will find many pointers but it will take a while to figure out the answer.
The above query will not work as the name of the Relation between Account and a Parent Account is "ChildAccounts"

     So by corollary the following query should work:-

Select id,name, (Select id, name, from ChildAccounts ) from Account

Well the above query gets us the immediate children but fails to get the grandchildren and so on...
So what should be the query like? Consider the following
select id,name,  from account where'Parent' or'Parent' 
The above query will give you 2 levels of child records of a Parent Account.
You can define the levels of Hierarchy Allowed in a custom setting and use it to define the clause dynamically and get the desired results in a single query.

Saturday, April 12, 2014

Campaigns - means to track Return of Investment on money spent on Promotion / Advertisement

Campaigns are means through which you generate buzz around your services and products offered by your organization. Organizing campaigns involves money as you may use one of the following to drive campaigns:-

i. Email blasts
ii. Print Advertisement
iii. Organize seminars

For a successful campaign one need to :-
a. Plan the campaign -type, objectives,mode of delivery, etc.
b. Have a targeted audience
c. Track response and new business generated from the campaign

As it involves an investment- hence as a business one would be interested in knowing :-
1. the time period for the campaign (Start date - End Date)
2. Cost of running the campaign (expected & actual)
3. New business expected to be generated from it (in monetary terms)

In salesforce too Campaigns are recorded , stored and tracked.
People are the final target of any campaign which will form their future perspective clients. People added to a campaign are called "Campaign Members" and the following can be added as campaign members:-
1. Contact
2. Lead
3. Person Account
Campaigns can be a webinar or an email campaign, one can have different layout and record type assigned for each one.
People who are target for your campaigns are called as "Campaign Members"
Target may be an existing customer or a new one.
Also the same applies for "Campaign Member" different fields can be displayed in respective page layout.
One thing very important w.r.t. Campaigns is "Advanced Setup". In simple terms one can define different member statuses . Also one can define what each status signify (responded / default) refer to screenshot below for clarity:-

Next you may ask ok I created a Campaign from The Campaign Tab by clicking on the "new" button. Also I set the "Advanced Setup" of campaign, now how do I add the targeted audiencs?

1. You can run a report to add Campaign Member ( good for adding 50000 members)
2. Add by search from Campaign Add/ Search member page ( Good for adding 1000 members)
3. Using a file to add members to a campaign.

I have a thumb rule if a blog crosses more than 1 page length- split it into 2.
More on Campaigns in my next post.
To be continued...

Friday, April 4, 2014

Group Tasks in Salesforce - Facts and Fault lines

Group Tasks

Tasks which can be assigned to more than one user is called a group task. One can create a task so that up to 100 users are each assigned an independent copy of the task. 

To create a group task:
  1. On the New Task page, click the lookup icon (Lookup icon) next to the Assigned To field.
  2. In the lookup window, select the Multiple Users tab.
  3. Users can be organized into various categories such as personal groups, public groups, roles, or territories. In the Searchdrop-down list, select the appropriate option.
  4. Optionally, enter one or more characters in the text box and click Find to search.
  5. In the Available Members list, click one or more items to select them. Press CTRL+click to select multiple items individually, or SHIFT+click to select multiple adjacent items at the same time.
  6. Click the Add and Remove buttons to move your selections between the lists.
  7. When the appropriate choices are in the Selected Members list, click Done. If your selections total more than 100 users, you must reduce your selections before you can proceed.
  8. On the New Task page, see your selections display next to the Assigned To field. The total number of tasks you are creating also displays.
  9. Continue entering task details such as due date, status, and comments.
  10. When you save the task, your selected users will be assigned copies of the task. Note that these copies are independent and not linked; they can be edited, transferred, or deleted individually.
Problem Statement
Elena is the practice-head of her  Salesforce competency and has to assign a task to all her team members to take their maintenance exams.
Elena notices that a task can be assigned to a role in a workflow.
Elena plans to create a Role of all her colleagues who have to take this exam periodically , she names it "SFDC Competency" and assigned this role to all the users who take these exam periodically.
Elena planned to create a Learning Activity Custom object on which she create a workflow which will create a task for taking exam assigned to all the users who are assigned to the "SFDC Competency" role when she creates an instance of Learning activity Object.
When she tried to test the rule she noticed that only a single  task was getting created and was getting assigned to the creator of the "Learning Activity" object.
To test the issue further she removes all users from the "SFDC Competency"  and leaves a single user.
Then she tests it again - now she finds that a task gets created and is assigned to the user of the single user in the "SFDC Competency" role.

In gist, there's no neat feature available in Salesforce for assigning Group tasks via workflows. But there are some workarounds that can be built to accommodate the business needs. As of now Salesforce does not recognize multiple people assigned to a role in a workflow. When there are more than a user assigned to a workflow task assignment rule, it will instead send the task to the rule initiator and not the intended recipients. You can create multiple roles and assigned single person to each one. alternatively, one can have each workflow rule to have multiple task assingment rules one for each role.
But this may not be a good solution from house-keeping / maintenance point of view , what when user leave or new users get added.

Will keep looking for a better and more automated solution. 

Sunday, March 30, 2014

Unraveling the mystery about Products , Price Books and Assets

Any technology if its a hot cake is lapped up by job-seekers, people try to subvert the system to get into it.
Why subvert the system when all resources related to current hot-cake salesforce is online and the platform also freely available for developer to use and develop and acquire skills.
I believe in equal opportunity in its true sense , hence I keep blogging at regular intervals so that I may contribute in my very minuscule way in  making information available freely to all concerned.
Leaving behind the small talk lets concentrate on something which forms the very backbone of all business entities- Products.
In context of salesforce - Product is a pivotal piece in its implementation -popularly called the "Sales Cloud"
So what do products signify in slaesforce?

Product is some service or items that as an organization one may sell to people who may need them.
You may think that's fine , but are is there more to products - are they all same?
Do they have any categorization?
Are they grouped or categorized in any way?
Talking of classification or categorization - a term which rings a bell is "Product Family"
Now what is Product Family?
Say there is a home appliance manufacturer, they might make different types of appliances like:-
i. Kitchen appliances
ii. Bathroom appliances
You realize that products can be grouped into different categories based on some common characteristics- such a grouping is called "Product Family" in salesforce.
Generally whenever you shop online you try to find the Product list with the associated prices- such an compilation of products along with the associated prices is called a Price-book
Each Product -with its associated  Price is a Price-Book Entry or in short a price-book is a collection of PriceBook Entries
Every organization has at least one "Standard Price Book" which is the master list of all products with their associated standard price.

Now the question can we have price books which contain the selling price or also called the list price? Yes we can have more than one custom price books  each catering to a different market. For ex. most books have a cheaper Indian editions with economical prices and a International edition with prices at par with international market. So in this case one can create a Domestic Pricebook and an Overseas Pricebook .
P.S. Every product is always present in the standard pricebook and in one or more than one custom pricebook. Also an opportunity can contain only one pricebook.

Many times you might have created too many pricebooks and dont want to use them anymore , then what does one do ? You cant delete pricebooks with associated records. You can Archive them, but once archived but once archived they cannot be restored.

Organization wide / default Access on Pricebooks
1. Use Access - With this access all users of org can view pricebook and can add Price Books and products in price book to an opportunity
2. View Only- With this access all Users can view and report on Price book but not add them to opportunity. So in order people to add price book to opportunity you need to give people /users edit access to opportunity and give "use" access to the pricebooks you want them to use.
3. No Access- Users cannot see or add pricebooks to opportunity. We use this access when we want only specific users to use and view the pricebooks and the people whom you want to use pricebooks grant them "use" access if you want them to add pricebooks to opportunity or give "View only" access if you want them to view and report on pricebooks.
Another important aspect of Products is Scheduling. Its of 2 types :-
1. Revenue
2. Quantity

Enabling schedule from the Setup / Customize / Products/ Schedule Setup (refer to screenshot for clarity)

Enabling schedule adds a scheduling section to the Product page layout. More on Scheduling in later posts.
Enabling schedules also enables users to create reports on for tracking shipments, deliveries and payments using the report type Opportunity with products and schedules.

A product which is purchased by the customer is tracked in Asset. It may be a product purchased from you or your competitor - it may hold information about:-
1. Serial number
2. Expiration date
3. If it is competitor asset or not
Also asset can be tracked from Account, Contact and Product by adding it as a related list to these objects' layouts.
Also one can add a lookup to asset in cases and a case can be created linked to the asset purchased by the customer which will help the support and service folks.

Some questions about Products:-
1. Many times one faces queries like how do I add a check on restricting selection of a particular Pricebook for a particular profile or record type of opportunity?
Answer- You have to add validation rules at the Opportunity Product level and in case if its too complex one may have to write the validation rule logic in a trigger on Opportunity Product.
2. Can i add more that one pricebook to am opportunity?
Answer - No
3.How do I load data related to Products , Pricebooks , etc.?
Now that requires a dedicated post - may be next post will dwell on that.

Sunday, March 23, 2014

Lead Status field and the common queries which may bother you!!

Lead Status
Lead Status field the common pitfalls / concerns

Lead represents a Prospect or potential Opportunity.The field named "LeadStatus" (API name) indicates the state of the lead in the pre-sales process of turning a lead into an opportunity. Some default values for the Lead Status field include Open, Contacted, and Qualified.
Some of the things which need to be taken care of w.r.t. leads and Lead Status field in particular:-
I. Do we need to assign at least one picklist value in status field as Converted ? Yes , at least one of the picklist values in this field has to be marked as "Converted". 
One may ask you -How are converted lead status values setup?

How to set converted leads status values?
To set the values available for the "converted status" field on the convert page layout do the following:
1. Click on:
Setup | App Setup | Customize | Leads | Fields | Lead Status2. Click "Edit" next to a value3. Select the "converted" checkbox if you would like it to be an available value during lead conversion (NOTE: you can have more than one converted status value)

II. Can we have more than one picklist value as "converted"? 
Yes more than one field can be related to / or assigned as "Converted" picklist value.
III. Many times a user may find the presence of the picklist value confusing? 
They may ask the picklist value to be re-christened or renamed. Yes you can remove , rename picklist values assigned as "Converted" , only catch is atleast one picklist value has to be there which assigned as "Converted"
IV. How to remove converted status off lead status value?
In order to make a value no longer have a converted status you should click edit beside the value and uncheck the converted checkbox

V.  Many times while converting a Lead we come across errors , what causes them?
More often these error are caused due to presence of Mandatory fields on objects whose records are created as a result of conversion like Account, Contact, Opportunity, Task, etc. In case say you have created a custom mandatory field on Account, then lead conversion will give error if you do not map a mandatory field from lead onto the newly created mandatory field on account. 
VI. If we have multiple values corresponding to "Converted Status" how  is converted status values derived when a lead is converted?
If record types are not being used in Leads, all of the existing converted status values will be displayed on the lead convert page.  But , if record types are being utilized, the values displayed on the lead convert page are taken from the values available on the default record type of the profile assigned to the user who is triggering the lead conversion, and not from the converted status values that are setup on a lead record type / lead process that is assigned to the lead being converted.
Lead  is accorded special attributes and status like Opportunity and Task because of many native or in-built salesforce features / functionality running off them, hence lot of caution and thinking should be invested while customizing or changing the basic characteristics of this functionality.

Saturday, February 1, 2014

Batch Apex – What you should be careful about?

I have been writing or reviewing codes in Salesforce for over six years now. Whenever one comes across a tricky situation which involves processing huge volumes of data “Batch Apex” is the way to go, but every now and then you may be alarmed by someone telling you – that hey I hit the 10k limit while executing a Batch Job!

You would wonder- how is that possible? Soon you would realize that its the result of one the common slips that one does while designing a “Batch Job”. Most commonly we fetch records in access of 10,000 within the Execute() method. Treat all code written within execute() method as if you are writing for normal Apex.
Batch Apex surely has more flexible Governor Limits for example:-
·         200  SOQL per cycle (Please check the latest limit a s per latest release)
·         Records retrieved by SOQL query 50,000,000 as against 50k in the normal apex.
·         Heap Size is much larger than that compared to normal apex.
Why Batch Job is capable of handling huge data sets?
 One has to understand what makes Batch Apex successful in processing huge data sets:-
·         The large data set is processed in batches – which implies that the parameter “query” in  Start Method () that has to be the query which will return the bulk of data. Please refer to following code snippet for clarity:-
global Database.QueryLocator start(Database.BatchableContext BC){
 return Database.getQueryLocator(query);
Common Pitfalls
è You might say well what’s new in that we all know that. Well true but just reiterating -that the dataset which is the largest - it has to be fetched with the SOQL in “Query” and then processed in batches
è Always remember within the Execute() method never execute an Insert or update which will process more that 10k records in a cycle.
·         Also the enhanced governor limits enables the Batch Apex to process huge datasets, but one needs to cautious that though relaxed the governor still exist w.r.t. Batch Apex too. The following may be important for considering while finalizing your design and organization wide setup:-
o   Batch Apex Governor Limits
o   These are the governor Limits you need to keep in mind when dealing with Batch Apex
o   Up to five queued or active batch jobs are allowed for Apex.
o   A user can have up to 50 query cursors open at a time. For example, if 50 cursors are open and a client application still logged in as the same user attempts to open a new one, the oldest of the 50 cursors is released. Note that this limit is different for the batch Apex start method, which can have up to five query cursors open at a time per user. The other batch Apex methods have the higher limit of 50 cursors. Cursor limits for different features are tracked separately. For example, you can have 50 Apex query cursors, 50 batch cursors, and 50 Visualforce cursors open at the same time.
o   A maximum of 50 million records can be returned in the Database.QueryLocator object. If more than 50 million records are returned, the batch job is immediately terminated and marked as Failed. So if you have a requirement to process in excess of that value factor in the necessary checks and balances in your design.
o   If the start method returns a QueryLocator, the optional scope parameter of Database.executeBatch can have a maximum value of 2,000. If you set to a higher value it will anyways break it into smaller chunks, which is a blessing in a sense.
o   If no size is specified with the optional scope parameter of Database.executeBatch, Salesforce chunks the records returned by the start method into batches of 200, and then passes each batch to the execute method. Apex governor limits are reset for each execution of execute.
o   The start, execute, and finish methods can implement up to 10 callouts each.
o   Batch executions are limited to 10 callouts per method execution.
o   The maximum number of batch executions is 250,000 per 24 hours.
o   Only one batch Apex job's start method can run at a time in an organization. Batch jobs that haven’t started yet remain in the queue until they're started. Note that this limit doesn't cause any batch job to fail and execute methods of batch Apex jobs still run in parallel if more than one job is running.