Wednesday, December 2, 2015

Salesforce Activities in a Nutshell


What is Activity?
Activities in Salesforce are the actions you take, for example calls, emails, to-dos.
Activities consist of tasks and events.
Tasks are your to-dos. It has a due date, but not a due time.
Events are events on your calendar. It has both due date and due time. All-day event is an exception, because it doesn’t have a due time.
Although tasks and events are two different standard objects, they are mostly the same behind the scene. You can take them as different record types of activities.
"Who" and "What"
"Who" is the "Name" field of an activity. It refers to a person,  ex. contact or lead. What of an activity is the “related to” field. It refers to an object type things,  ex. account, opportunity, product ...
If Mary has a task "Grab coffee with David from Coca Cola." Then activity "Owner" is Mary. "Who" is contact David. "What” is the account David coming from "Coca Cola".

Activity’s Parent
Activities have "Who", "What" and "Owner" fields. Which one is activity's parent?
The short answer is both "Who" and "What".
Please note that the "parent" relation here is not "master-detail" or "lookup" relationship. Definition of "parent" here is the following:
1. Deleting the "parent" objects will cascade delete the activity.
2. Parent field is not mandatory. An activity can have null "Who" and "What".
3. Sharings of child activities are determined by parents.

Most other Salesforce standard objects have 1 and only 1 parent. However, activity can have multiple parents.

Activities Sharing
Sharing for activities is different from sharing of all other entities. (Thanks Peter Wu for insights about activities sharing.)
When "Org Wide Sharing Settings" is set to the following:
"Controlled by Parent" 
1. 1 "What", 0 "Who": User must have access to the What to see the activity
2. 0 "What", 1 "Who": User must have access to at least 1 Who to see the activity
3. 1 "What", n "Who": User must have access to both the What and at least 1 Who to see the activity.
"Private"
Private sharing for Activities, is actually better named as "Has read-only access if have access to Parents." It's not true private sharing.

“Shared Activities” Perm
Out of the box, one activity can only be associated with 1 "Who". However, turning on "shared activities" allows an activity being associated with multiple "Who"s. For example, if "Mary grab coffee with David and Peter". Then this task is associated with two contacts "David" and "Peter".
When shared activity is enabled, an activity can be “parented” to 1 “What” and up to 50 “Who”s at the same time.
Keep in mind that disable "Shared Activities" is a destructive process. It only keeps the "primary Who" association and removes all extra "who" relationships. Please be very careful about whether you wanna turn on "Shared activities". Never turn off "shared activities" by yourself. Inquire Salesforce support about the risk.

Recurring Events
Creating a recurring event will create a event series and multiple occurrence records. To modify the series events, you must modify the series rather than an occurrence of the event.
When "Advanced Calendaring" perm is on, orgs will see two new columns added to the standard event object. "IsException" and "OriginalInstanceDateTime". Once an occurrence’s "IsException" field is set to true, modify the series will not modify this occurrence. Keep in mind that an occurrence is marked as exception if you modify the subject of this occurrence.

API Tables
In workbench, there are Task and Event tables.
If you turned on “Shared Activities” preference,  two new tables "TaskRelation" "EventRelation" will be added to keep track of the "What", "Who" and "Invitee" relationships.

Activities Archiving
Closed activities due one year ago are automatically archived by Salesforce. Once activities are archived, users should not see them from UI or API. ( System Admin is an exception.) However, Customer can still access these activities via Data export files.  A side note for API, query() call doesn’t return archived activities, queryAll() call does.



Saturday, October 31, 2015

Wanna Sync Google Calendar Event to Salesforce? DIY!

Have you ever wanted to push your Google Calendar event to Salesforce?  Do you want to save at least $10 per user per month on purchasing apps? Here’s the recipe to build a simple solution yourself.  

Prerequisite:
  1. A login to Salesforce org with Admin access privilege. Your profile needs to be API enabled.
  2. Create a security token to be used in the app. (You can use an existing token if you have one.)  Your name > My Settings > Personal  >  Reset My Security Token.


The tutorial includes 4 steps:
  1. Create a Google Standalone App Script following. https://developers.google.com/apps-script/guides/standalone

  1. Connect your script to your Salesforce account.

  • You need to configure Connected apps in setup menu to create a new remote access application. ( See details in tutorial below.)

  • OAuth (Username and Password Flow) will be implemented for API authorization. Keep in mind that embed your username and password in application is not a good practice. OAuth(Refresh Token Flow) is more secure.  We are not able to demonstrate this in the tutorial because, refresh token flow will prompt a page for user to approve Google accessing Salesforce Data.  Google Standalone App Script doesn’t allow prompting a dialog/page.

  1. Pull calendar event from Google Calendar via Calendar API.
  2. Create event record in Salesforce via REST API.

Tutorial:
1. Create a standalone app script with a simple hello world function. Publish to web app. Copy the “Current Web App URL”. We will paste this to Salesforce later.

2.  Now we want to whitelist the app you just created and let Salesforce know where to make callback to. Create a new Connected App from Salesforce > Setup > Connected Apps.  Paste the “Current  Web App URL” in OAuth “Callback URL” section. Configure Selected OAuth Scopes according to your own need.


Wait for 2-10 mins, go back to the app you just created. You will find “Consumer Key” (client_id) and “Consumer Secret” (client_secret). They will later be embeded in your request to Salesforce.

Manage OAuth policies of this app. Set “Relaxation” to “Relax IP Restrictions”.
Then copy and paste the source code to your own project. Put your User Settings in.


SalesforceConnectUtil.gs handles authorization with Salesforce.

//Salesforce Authorizatin Endpoint
var AUTHORIZE_URL = 'https://login.salesforce.com/services/oauth2/token';

//PUT YOUR USER SETTINGS HERE
var CLIENT_ID = 'REPLACE_WITH_YOUR_CLIENT_ID';//Consumer Key
var CLIENT_SECRET='REPLACE_WITH_YOUR_CLIENT_SECRET';//Consumer Secret
var USERNAME = 'REPLACE_WITH_YOUR_USERNAME';
var PASSWORD = 'REPLACE_WITH_YOUR_PASSWORD_SECURITY_TOKEN';//password+securitytoken

function loginToSalesforce(){
 var token = PropertiesService.getScriptProperties().getProperty('token');
 //If user doesn't have a token
 if(!token){
   //Request access token using username and password
   var response = requestService().getContentText();
   //Parse and store access token, instance_url
   parseResponse(response);
 }
}

function requestService(){
 var payload = {
   "grant_type" : "password",
   "client_id" : CLIENT_ID,
   "client_secret" : CLIENT_SECRET,
   "username" : USERNAME,
   "password": PASSWORD
 };
 var options = {
   "method": "post",
   "payload": payload
 };
 return postToURL(AUTHORIZE_URL, options);
}

function parseResponse(r){
 //Parse Response
 var tokenResponse = JSON.parse(r);
 //store token and instsanceURL
 PropertiesService.getUserProperties().setProperty( 'instance_url', tokenResponse.instance_url);
 PropertiesService.getUserProperties().setProperty( 'token', tokenResponse.access_token);
}

3. Retrieve calendar event from Google Calendar using Calendar API. Note that to keep it simple, the sample code only fetches 1 calendar event.(The 1st event in the future) It’s a simple modification to retrieve multiple events at a time. Be aware if you want to send multiple records to Salesforce, REST API will not be the best choice. Consider using SOAP API or Bulk API in step 4.

//Google Calendar API: https://developers.google.com/google-apps/calendar/v3/reference/events/list
function retrieveCalendarEventFromGoogle() {
 var calendarId = 'primary';
 var optionalArgs = {
   timeMin: (new Date()).toISOString(),//Lower bound (inclusive) for an event's end time to filter by.
   showDeleted: false,
   singleEvents: true,
   maxResults: 1,//Maximum number of events returned on one result page.
   orderBy: 'startTime'
 };  
 var eventList = Calendar.Events.list(calendarId, optionalArgs).items;
 if(eventList.length > 0 ){
   return  eventList[0];
 }
}

4. Now, it’s time to create Event in Salesforce with REST API.
function sendEventToSalesforce(event){
 var url = getRestAPIEndpoint()+'/sobjects/Event/';
 
 var payload = {
   "Subject" : event.summary,
   "Location" : event.location,
   "Description" : event.description,
   "StartDateTime" : Utilities.formatDate(new Date(), "GMT", "yyyy-mm-dd'T'hh:mm:ss'Z'"),
   "EndDateTime" : Utilities.formatDate(new Date(), "GMT", "yyyy-mm-dd'T'hh:mm:ss'Z'")
 };
 

var options = {
   "method": "post",
   "contentType" : "application/json",
   "headers" : {
     "Authorization" : "Bearer " + PropertiesService.getUserProperties().getProperty('token')
   },
   "payload" : JSON.stringify(payload)
 };
 
 var res = postToURL(url, options);
 Logger.log(res.getContentText());

}


Finally, it’s time to celebrate your success. Create a future event on your Google Calendar, run the script and go back to Salesforce. Hurrah!  A brand new event just get created!


Reference:
https://www.youtube.com/watch?v=9SEAmNDtlcA&list=PL68F511F6E3C122EB