SFDC Data Models for Pros -
Simplifying The Complexities
​ Baruch Oxman
​ R&D Manager, Implisit
​ @implisithq, @baruchoxman
Baruch Oxman
R&D Manager
Implisit – Intro & Motivation
Implisit – Intro & Motivation
Data Entry, Insights
& Analytics
Standalone UI
Real-time SFDC
Data interaction
Offline SFDC Data
Processing
Connected App UI
In this session
Object Relationship
Types
Polymorphic
Relations
Security &
Permissions
Deleted RecordsMetadata
History Records
Objects Relationships
•  Master-Detail
•  One-to-Many
•  Lookup
•  Many-to-Many
•  Polymorphic relations
Object Relations
•  Closely linked objects
•  Detail extends the master
•  Owner of master owns the child record
•  Example:
•  Custom “AccountDetails” object, extending Account
Master-Detail Relationship
Master
Detail
One-to-Many
Opportunity
Opportunity
Competitor
Opportunity
Competitor
Opportunity
Competitor
Lookup
Account
Contact Contact Contact
Many-to-Many
Contact Lead
Campaign Campaign
Task Task
Contact Contact
Many-to-Many
CampaignCampaign Contact Contact
Campaign
Member
Campaign
Member
Campaign
Member TaskRelation TaskRelation TaskRelation
Task TaskLeadContact
Tasks & Events
Polymorphic Relations
Polymorphic Relations
Task Attachment
Contact/Lead
Opportunity/Case/
Account
Opportunity/Case/Account/Contact/Lead/…
WhatId WhoId ParentId
Challenge
​ SELECT Subject, Account.Name, Who.Company FROM Task
Error: “No such column 'Company' on entity 'Name'…”
Naïve Approach
1. SELECT Subject, Account.Name, WhoId FROM Task
2. SELECT Company FROM Lead WHERE Id IN <WhoId list from previous query>
1st option: 2 SOQL queries
​ SELECT Subject, Account.Name,
TYPEOF Who
WHEN Lead THEN Company
END
FROM Task
•  Developer preview, to enable - contact Salesforce
2nd option: TYPEOF
​ SELECT Id, Company,
(SELECT Id
FROM Tasks
WHERE <tasks filtering condition>)
FROM Lead
Nested SOQL Query
​ { 'totalSize': 2,
​  'records': [
​  {'Company': ‘Salesforce.com', u'Tasks': None, u'Id': u'00Qd0000007Q36GEAS'},
​  {'Company': ‘Implisit',
​  'Tasks': {'totalSize': 1, u'records': [{'Id': u'00Ti000000zM7rLEAS'}]},
​  'Id': u'00Qd0000007Q36GEAS'}
​ ]}
Nested SOQL Query - result
​ SELECT Id, Who.Name FROM Task WHERE Who.Type = ‘Lead’
TYPE qualifier
History records
Motivation
History records
Accounts
Cases
Products
Leads Contacts
Opportunities Contracts
Assets and more…
•  Field Name
•  Old Value
•  New Value
•  Id (AccountId / OpportunityId / ContactId / …)
•  Who changed it and when ?
•  Read-only records
Structure
​ {
​  "Id" : "017200000GScFz0AQF",
​  "Field" : "StageName",
​  "OldValue" : "Intro",
​  "NewValue" : "Closed Lost",
​  "OpportunityId" : "0062000000W1QT6AAN",
​  "CreatedById" : "00520000003KQCNAA4",
​  "CreatedDate" : "2014-02-24T09:39:04.000+0000",
​ }
OpportunityFieldHistory record - example
•  Monitoring a subset of fields:
• Amount
• Probability
• Stage
• Close Date
• Few more…
•  Each record contains the values for all these fields
•  Useful for pipeline snapshots
OpportunityHistory
​ {
​  "Id" : "00820000014EWPlAAO",
​  "Amount" : 5280.0,
​  "CloseDate" : "2014-12-31",
​  "ExpectedRevenue" : 5280.0,
​  "ForecastCategory" : "Closed",
​  "Probability" : 100.0,
​  "StageName" : "Closed Won",
​  "OpportunityId" : "0062000000W0TMNAA3",
​  "SystemModstamp" : "2015-01-22T08:41:32.000+0000",
​  "CreatedById" : "00520000003KQCNAA4",
​  "CreatedDate" : "2015-01-22T08:41:32.000+0000",
​ }
OpportunityHistory record - example
Security & Permissions
Security & Permissions
Objects Fields
Records Relations
Objects Metadata
​ from suds.client import Client
​ …
​ soap_api = Client(wsdl_url)
​ describe_global_res = soap_api.service.describeGlobal()
​ supported_obj_names = [sobject.name for describe_global_res['sobjects']]
describeGlobal() - list supported objects
​  (DescribeGlobalSObjectResult){
​  activateable = False
​  createable = True
​  custom = False
​  customSetting = False
​  deletable = True
​  deprecatedAndHidden = False
​  feedEnabled = True
​  keyPrefix = "001"
​  label = "Account"
​  labelPlural = "Accounts"
​  layoutable = True
​  mergeable = True
​  name = "Account"
​  queryable = True
​  replicateable = True
​  retrieveable = True
​  searchable = True
​  triggerable = True
​  undeletable = True
​  updateable = True
​  },
describeGlobal() – output example
​ get_desc_url = "https://na15.salesforce.com/services/data/v32/sobjects/Lead/describe"
desc_json = json.loads(perform_request(get_desc_url))
​ lead_fields_metadata = desc_json['fields']
​ // get all available field names
​ lead_field_names = [field['name'] for field in lead_fields_metadata]
Describe
​ [(DescribeSObjectResult){
​ …
​  activateable = False
​  keyPrefix = "00Q"
​  label = "Lead"
​  labelPlural = "Leads"
​  layoutable = True
​  mergeable = True
​  name = "Lead"
​  queryable = True
​  replicateable = True
​  retrieveable = True
​  searchLayoutable = True
​  searchable = True
​  triggerable = True
​  undeletable = True
​  updateable = True
​ ….
​ }]
Describe - output
​ # get all picklist values for a field
​ def get_active_picklist_values(obj_fields_metadata, field_name):
for field_metadata in fields_metadata:
if field_metadata['name'] != field_name:
continue
picklist_values = field_metadata.get('picklistValues', [])
return [ picklist_val['value']
for picklist_val in picklist_values
if picklist_val['active'] ]
Describe
​ (Field){
​  autoNumber = False
​  byteLength = 120
​  calculated = False
​  caseSensitive = False
​  createable = True
​  custom = False
​  defaultedOnCreate = False
​  deprecatedAndHidden = False
​  digits = 0
​  filterable = True
​  groupable = True
​  idLookup = False
​  label = "Lead Source"
​  length = 40
​  name = "LeadSource"
​  nameField = False
​  namePointing = False
​  nillable = True
​  permissionable = True
​  picklistValues[] =
​  (PicklistEntry){
​  active = True
​  defaultValue = False
​  label = "Advertisement"
​  value = "Advertisement"
​  },
​  ...
​  precision = 0
​  restrictedPicklist = False
​  scale = 0
​  soapType = "xsd:string"
​  sortable = True
​  type = "picklist"
​  unique = False
​  updateable = True
​  },
Describe – single field output
Tracking deleted records
getDeleted()
• SOAP
• Single API call
queryAll(isDeleted = True)
• REST
• Multiple API calls
• Recycle Bin objects
Tracking deleted records
Summary
Object Relationship
Types
Polymorphic
Relations
Security &
Permissions
Deleted RecordsMetadata
History Records
•  Object relationships types
•  SFDC Sales Objects relationships diagram
•  describeGlobal, describeSObject
•  SFDC Task & Event objects
•  SOQL Polymorphism
•  Understanding Polymorphic Keys and
Relationships
•  Polymorphic Lookups
•  TYPEOF
Additional Resources
Thank you

Salesforce Data Models for Pros: Simplifying The Complexities