Salesforce Lead-to-Order


Introduction

With the Salesforce Lead-to-Order app template you can load raw input data from Salesforce for the Salesforce Lead-To-Order process, extracted to either Snowflake or SQl Server using CData Sync. The raw input data is transformed through a series of transformations that take place via dbt (data build tool) and produce the required input data used in Process Mining process apps.

Lead-to-Order process

The Lead-to-Order process is an end-to-end process which starts with a potential customer's intent to buy a product, up to the fulfillment of this sale.

Lead Qualification

Once a lead is generated, the lead will go through a qualification process. The objective of this process is to determine whether the lead is likely to make an actual purchase. Once the lead is qualified, this will turn into an actual opportunity for a sale. In Salesforce, this is tracked via the Lead object.

Opportunity Management

As a lead qualifies into an opportunity, the sales team will work on the opportunity together with the potential customer, to identify the need and suggest an appropriate product or service which will meet this need. Part of the process may involve generating a quote to the customer, but this is not always the case. In case the opportunity is won, this will generate one or more orders to fulfill the won opportunity. In Salesforce, this is tracked via the Opportunity object, and optionally, the Quote object.

Order Management

Within Order Management, the order lifecycle is maintained, including order capture, and fulfillment. In Salesforce, the Order object is used to maintain this process. One opportunity may have multiple orders.

Optionally, this may then extend and generate an invoice and receivables, in what is called the Lead to Cash process.

Entity relationship diagram

The following shows all entities that were used for the process.

Tags

Tag Description
Opportunity amount reduced Opportunity Amount was changed to a value less than the original value. Represents an opportunity which is losing value.
Opportunity won without a Quote An opportunity was won without sending a formal quote. Potentially arriving to a tentative price or list of products could have improved chances.
Multiple Owner Changes Applies for all entities, reflects a back and forth between team members which may be justified (vacations, escalations) or may require attention.
Approval process started multiple times Multiple approvals may exist for one entity, however if the same approval process is triggered multiple times, there might be inefficiencies to review.
Opportunity close date postponed An opportunity is getting delayed according to it's original close date, which means the opportunity might require attention.

Due Dates

Due date Description
Original Opportunity Close Date Identifies original expected close date for the opportunity and verifies against the actual close date.

Salesforce Sales Cloud configuration

Source system

Salesforce Sales Cloud.

Depending on which fields have field history tracked, different change events will be recorded. Field history tracking can be configured from each object within Salesforce setup. Recommended minimal setup is having the following object and fields tracked:

By default, Field History is disabled per object. In order to setup Field History Tracking for an object, the following Salesforce manual contains a step by step instruction: Salesforce - Track Field History for Standard Objects. Note: if a field is activated for tracking, the values will be tracked from that moment onwards. Any changes before that point in time will not be saved. As of February 2022, Salesforce retains field history data for up to 18 months through the org and up to 24 months via the API, and Field history tracking data doesn't count towards Salesforce org's data storage limits.

In case the history needs to be stored for a longer period of time, Field Audit Trail must be activated. This allows copying of history data into a separate big data object and allows storage for up to 10 years.

Environmental settings

In order to connect via CData Sync, the user establishing the connection must be API Enabled, and must have appropriate read permissions on each of the objects which are being extracted.

Additionally, the user must be marked as "Marketing User" in the user settings in order to extract Campaign information.

In order to calculate amounts using historical exchange rates, Effective dated currency should be enabled in the Salesforce org, and historical exchange rates should be loaded into the system.

System specific settings

The Salesforce Lead to Order connector works on the process starting on the marketing campaign generation, up to the generation of customer orders. This includes processing of the following Salesforce transactional objects:

The following additional objects which are used to add additional attribute information into the model:

In case they are used, the following tables add Currency conversion to the model:

*Quote, Order, OrderHistory, CurrencyType, DatedExchangeRate objects are by default disabled in Salesforce orgs. By default, these will not be considered in the transformations. If these are used, the transformation and related logic can be enabled by using DBT variables.


Configuring CData Sync for Salesforce Sales Cloud

Below is a description on how to use CData Sync to set up a source connection and load data into a Process Mining Salesforce Lead-to-Order process app.

In general, you should follow the steps as described in Loading data using CData Sync (Snowflake) or Loading data using CData Sync (SQL Server) to set up data loading using CData Sync. Since specific settings are required when using Salesforce, pay attention to the steps described below.

Setting up the source connection

Creating the extraction job

Define the following settings in the Replicate Options section in the Advanced tab in the Job Settings panel.

Setting up environment variables in the extraction job

Important: Make sure you edit the Pre-job Event.

CData Sync allows the use of environment variables in order to drive specific extraction logic in each query.

Variable Description Comment
start_extraction_date Defines first date for which data will be extracted. Mandatory
end_extraction_date Last date for which data will be extracted.

Be mindful of choosing a start_extraction_date that encompasses the data that you want to capture, as orders are the starting point of the order to cash process.

In order to setup the environment variables:

Step Action
1 Access the job created in the previous step.
2 Click on the Events tab.
3 Add the following lines to the Pre-Job Event script.
<!-- Modify environment variables here. --> <!-- Variable start_extraction_date must be populated.--> <api:set attr="out.env:start_extraction_date" value="2022-01-01" /> <!-- In case a specific end date is needed, replace the value string with the required date in yyyy-MM-dd format. --> <!-- i.e api:set attr="out.env:end_extraction_date" value="2022-02-01" --> <api:set attr="out.env:end_extraction_date" value="[null | now() | todate('yyyy-MM-dd')]" /> <api:push item="out" />

Important: Do not modify the api:info details that are shown by default.

In order to modify the environment variables, modify the values within the Events tab. By default, end_extraction_date will default to today's date. start_extraction_date must always be populated.

Table Replication

Once the job is correctly setup, click on Add Custom Query under the Tables tab and paste the following queries (each query needs to maintain the semicolon at the end). Make sure you save all changes.

Default Extraction

The following script is prepared for scenarios where Currency Conversions and Person Accounts are not used and are disabled. In case any of these are used, please add the scripts in the Alternative Scenarios section.

REPLICATE [Account_raw] SELECT [Id], [AccountSource], [BillingCountry], [BillingState], [CreatedById], [CreatedDate], [Industry], [Name], [OwnerId], [Ownership], [ParentId], [Rating], [Type] FROM [Account]; REPLICATE [Campaign_raw] SELECT [Id], [CreatedById], [CreatedDate], [Name], [OwnerId], [ParentId], [Status], [Type] FROM [Campaign] WHERE ([CreatedDate] >= '{env:start_extraction_date}') AND ([CreatedDate] <= '{env:end_extraction_date}'); REPLICATE [CampaignMember_raw] SELECT [Id], [CampaignId], [CreatedById], [CreatedDate], [LeadId], [Status] FROM [CampaignMember] WHERE ([CreatedDate] >= '{env:start_extraction_date}') AND ([CreatedDate] <= '{env:end_extraction_date}'); REPLICATE [Lead_raw] SELECT [Id], [ConvertedOpportunityId], [CreatedById], [CreatedDate], [Name], [OwnerId] FROM [Lead] WHERE ([CreatedDate] >= '{env:start_extraction_date}') AND ([CreatedDate] <= '{env:end_extraction_date}'); REPLICATE [LeadHistory_raw] WITH ReplicateStartDate = '{env:start_extraction_date}', replicateenddate = '{env:end_extraction_date}' SELECT * FROM [LeadHistory] WHERE ((([Field] = 'Status') OR ([Field] = 'Rating')) OR ([Field] = 'Owner')) AND ([DataType] != 'EntityId'); REPLICATE [Opportunity_raw] SELECT [Id], [AccountId], [Amount], [CloseDate], [CreatedById], [CreatedDate], [ForecastCategory], [IsClosed], [IsWon], [LastStageChangeDate],[LeadSource], [Name], [OwnerId], [Probability], [StageName], [Type] FROM [Opportunity] WHERE ([CreatedDate] >= '{env:start_extraction_date}') AND ([CreatedDate] <= '{env:end_extraction_date}'); REPLICATE [OpportunityFieldHistory_raw] WITH ReplicateStartDate = '{env:start_extraction_date}', replicateenddate = '{env:end_extraction_date}' SELECT * FROM [OpportunityFieldHistory] WHERE (((([Field] = 'Amount') OR ([Field] = 'StageName')) OR ([Field] = 'Owner')) OR ([Field] = 'CloseDate')) AND ([DataType] != 'EntityId'); REPLICATE [RecordType_raw] SELECT [Id], [Name] FROM [RecordType]; REPLICATE [User_raw] SELECT [Id], [Department], [Name], [UserType] FROM [User]; REPLICATE [ProcessDefinition_raw] SELECT [Id], [Name], [TableEnumOrId], [Type] FROM [ProcessDefinition] WHERE [Type] = 'Approval'; REPLICATE [ProcessInstance_raw] SELECT [Id], [TargetObjectId], [CreatedById], [CreatedDate] ,[ProcessDefinitionId] ,[Status] FROM [ProcessInstance] WHERE ([CreatedDate] >= '{env:start_extraction_date}') AND ([CreatedDate] <= '{env:end_extraction_date}'); REPLICATE [ProcessInstanceStep_raw] SELECT [Id], [Comments], [CreatedById], [CreatedDate], [ProcessInstanceId], [StepStatus] FROM [ProcessInstanceStep] WHERE ([CreatedDate] >= '{env:start_extraction_date}') AND ([CreatedDate] <= '{env:end_extraction_date}');

Note regarding CData Salesforce Provider Version 21.0.8097.0 When a table has an _Incremental Check Column_ field predefined in CData Sync, the SQL query cannot use the same date field in both statements (WITH and WHERE) at the same time. If version 21.0.8097.0 (or an older version) of CData is used, the date filtering should be done in the WHERE clause and should be removed from the WITH statement.

Alternative Scenarios

The following scenarios can be used in combination of each other:

Order Object is enabled in Salesforce Org

In case the order object is enabled, add the following scripts to the default extraction:

REPLICATE [Order_raw] SELECT [Id], [CreatedById], [CreatedDate], [OpportunityId],[Name] FROM [Order] WHERE ([CreatedDate] >= '{env:start_extraction_date}') AND ([CreatedDate] <= '{env:end_extraction_date}'); REPLICATE [OrderHistory_raw] WITH ReplicateStartDate = '{env:start_extraction_date}', replicateenddate = '{env:end_extraction_date}' SELECT * FROM [OrderHistory] WHERE ((([Field] = 'Status') OR ([Field] = 'Owner')) OR ([Field] = 'TotalAmount')) AND ([DataType] != 'EntityId');

Quote Object is enabled in Salesforce Org

In case the quote object is enabled, add the following scripts to the default extraction:

REPLICATE [Quote_raw] SELECT [Id], [CreatedById], [CreatedDate], [Name], [OpportunityId] FROM [Quote] WHERE ([CreatedDate] >= '{env:start_extraction_date}') AND ([CreatedDate] <= '{env:end_extraction_date}');

Multi Currency and Dated Conversion Rates are enabled in Salesforce Org

In case multi currency is used in the Salesforce org, add the following queries:

REPLICATE [CurrencyType_raw] SELECT [Id], [IsCorporate], [IsoCode] FROM [CurrencyType] WHERE [IsCorporate] = 1; REPLICATE [DatedConversionRate_raw] SELECT [Id], [IsoCode], [NextStartDate], [StartDate], [ConversionRate] FROM [DatedConversionRate];

Additionally, the Opportunity query must be amended to add the CurrencyISOCode field in the query.

Person Accounts enabled in Salesforce Org

In Case Person Accounts (field IsPersonAccount) are used - replace the Accounts query with the following query. This query will add the field IsPersonAccount in the Accounts extraction.

REPLICATE [Account_raw] SELECT [Id], [AccountSource], [BillingCountry], [BillingState], [CreatedById], [CreatedDate], [Industry], [IsPersonAccount], [Name], [OwnerId], [Ownership], [ParentId], [Rating], [Type] FROM [Account];

Record Types are enabled in Salesforce Org

In case Record Types are used the Opportunity query must be amended to add the RecordTypeId field in the query.


Input fields

The following tables include the list of fields per input table, their description, data type to be used when formatting the input and the filter flag to identify those that are being used to filter data.

Input types

Below is an overview of the different field types and their default format settings.

Field type Description
boolean true, false, 1, 0
date yyyy-mm-dd
datetime yyyy-mm-dd hh:mm:ss[.ms], where [.ms] is optional.
double Decimal separator: . (dot); thousand separator: none
integer Thousand separator: none
text N/A

Account

Represents an individual account, which is an organization or person involved with your business (such as customers, competitors, and partners).

Field Type Stores Filtering
Id text Account Identifier (Primary Key)
AccountSource text The source of the account record. For example, Advertisement, Data.com, or Trade Show. The source is selected from a picklist of available values, which are set by an administrator.
BillingCountry text Details for the billing address of this account.
BillingState text Details for the billing address of this account.
CreatedById text User ID who created the account.
CreatedDate datetime Date in which the account was created.
Industry text An industry associated with this account.
IsPersonAccount* boolean Indicates whether this account has a record type of Person Account (true) or not (false). This field is not available by default in Salesforce, but is setup by Salesforce when requested for B2C environments. This attribute can be enabled / disabled using the use_is_person_account DBT variable .
Name text Name of the account. If the account has a record type of Person Account: This value is the concatenation of the FirstName, MiddleName, LastName, and Suffix of the associated person contact.
OwnerId text The ID of the user who currently owns this account.
Ownership text Ownership type for the account, for example Private, Public, or Subsidiary.
ParentId text ID of the parent object, if any.
Rating text The account's prospect rating, for example Hot, Warm, or Cold.
Type text Type of account, for example, Customer, Competitor, or Partner.

Campaign

Represents and tracks a marketing campaign, such as a direct mail promotion, webinar, or trade show.

Field Type Stores Filtering
Id text Campaign Identifier (Primary Key)
CreatedById text User ID who created the campaign.
CreatedDate datetime Date in which the campaign was created. Main field used for time-based filtering
Name text Name of the campaign.
OwnerId text ID of the user who owns this campaign.
ParentId text ID of the parent Campaign record, if any.
Status text Status of the campaign, for example, Planned, In Progress.
Type text Type of campaign, for example, Direct Mail or Referral Program.

CampaignMember

Represents the association between a campaign and either a lead or a contact.

Field Type Stores Filtering
Id text Campaign Member Identifier (Primary Key)
CampaignId text Required. ID of the Campaign to which this Lead or Contact is associated.
CreatedById text User ID who created the campaign member record
CreatedDate datetime Date in which the campaign member record was created. Main field used for time-based filtering
LeadId text Required. ID of the Lead who is associated with a Campaign.
Status text Controls the HasResponded flag on this object. In the Salesforce user interface, Marketing users can define valid status values for the Status picklist.

CurrencyType

Represents the currencies used by an organization for which the multicurrency feature is enabled.

Field Type Stores Filtering
Id text Currency Type record identifier (Primary Key).
IsoCode text ISO code of the currency. Must be one of the valid alphabetic, three-letter currency ISO codes defined by the ISO 4217 standard, such as USD, GBP, or JPY.
IsCorporate boolean Indicates whether this currency type is the corporate currency (true) or not (false). Label is Corporate Currency. All other currency conversion rates are applied against this corporate currency. = 1

DatedConversionRate

Represents the dated exchange rates used by an organization for which the multicurrency and the effective dated currency features are enabled.

Field Type Stores
Id text Dated Conversion Rate record identifier (Primary Key).
IsoCode text ISO code of the currency. Must be one of the valid alphabetic, three-letter currency ISO codes defined by the ISO 4217 standard, such as USD, GBP, or JPY.
StartDate date The date on which the effective dated exchange rate starts.
NextStarteDate date The date on which the next effective dated exchange rate will start. Effectively the day after the end date for this exchange rate.
ConversionRate double Conversion rate of this currency type against the corporate currency.

Lead

Represents a prospect or lead.

Field Type Stores Filtering
Id text Lead Identifier (Primary Key).
ConvertedOpportunityId text Object reference ID that points to the opportunity into which the lead has been converted.
CreatedById text User ID who created the campaign member record.
CreatedDate datetime Date in which the campaign member record was created. Main field used for time-based filtering
Name text Concatenation of FirstName, MiddleName, LastName, and Suffix up to 203 characters, including whitespaces
OwnerId text ID of the lead's owner.

LeadHistory

History for tracked fields of Lead.

Field Type Stores Filtering
Id text Lead History Identifier (Primary Key)
IsDeleted text Flags whether the lead history record was deleted
LeadId text Related Lead Record Id
CreatedById text User ID who created the history record
CreatedDate datetime Date in which the history record was created. Main field used for time-based filtering
DataType text Data Type for the field which was modified <> 'EntityId'
Field text Field which was modified on the lead record in ('Owner','Status','Rating')
OldValue text Value before change
NewValue text Value after change

Opportunity (Main Object)

Represents an opportunity, which is a sale or pending deal. This will be the main Case Identifier for the Process Mining model.

Field Type Stores Filtering
Id text Opportunity Identifier (Primary Key).
AccountId text ID of the account associated with this opportunity.
Amount double Estimated total sale amount. For opportunities with products, the amount is the sum of the related products.
CloseDate date Date when the opportunity is expected to close.
CreatedById text User ID who created the opportunity record.
CreatedDate datetime Date in which the opportunity record was created. Main field used for time-based filtering
CurrencyIsoCode text Available only for organizations with the multicurrency feature enabled. Contains the ISO code for any currency allowed by the organization.
ForecastCategory text Used to group opportunities for forecasting. It is implied, but not directly controlled, by the StageName field.
IsClosed boolean Boolean value which states whether the opportunity is closed.
IsWon boolean Boolean value which states whether the opportunity is won.
LastStageChangeDate datetime Shows timestamp in which the stage was changed last. Present starting from Salesforce REST API version 52.0.
LeadSource text Source of this opportunity, such as Advertisement or Trade Show.
Name text A name for this opportunity.
OwnerId text ID of the User who has been assigned to work this opportunity.
Probability double Percentage of estimated confidence in closing the opportunity. It is implied, but not directly controlled, by the StageName field.
RecordTypeId* text ID of the record type assigned to this object. In order for this field to appear on the opportunity object, there needs to be at least one record type for opportunities.
StageName text Current stage of this record. The StageName field controls several other fields on an opportunity.
Type text Type of opportunity. For example, Existing Business or New Business.

OpportunityFieldHistory

Represents the history of changes to the values in the fields of an opportunity.

Field Type Stores Filtering
Id text Opportunity History Identifier (Primary Key)
IsDeleted text Flags whether the opportunity history record was deleted.
OpportunityId text Related Opportunity Record Id.
CreatedById text User ID who created the history record.
CreatedDate datetime Date in which the history record was created. Main field used for time-based filtering
DataType text Data Type for the field which was modified. <> 'EntityId'
Field text Field which was modified on the opportunity record. in ('StageName','Amount','Owner','CloseDate')
OldValue text Value before change.
NewValue text Value after change.

Order

Represents an order associated with a contract or an account.

Field Type Stores Filtering
Id text Order Identifier (Primary Key).
CreatedById text User ID who created the order.
CreatedDate datetime Date in which the quote was order. Main field used for time-based filtering
Name text Name for the order.
OpportunityId text ID for the opportunity associated with the order.

OrderHistory

Represents historical information about changes that have been made to the standard fields of the associated order, or to any custom fields with history tracking enabled.

Field Type Stores Filtering
Id text Order History Identifier (Primary Key).
IsDeleted text Flags whether the Order history record was deleted.
OrderId text Related order Record Id.
CreatedById text User ID who created the history record.
CreatedDate datetime Date in which the history record was created. Main field used for time-based filtering
DataType text Data Type for the field which was modified. <> 'EntityId'
Field text Field which was modified on the order record. in ('Status','Owner','TotalAmount')
OldValue text Value before change.
NewValue text Value after change.

Quote

The Quote object represents a quote, which is a record showing proposed prices for products and services. Quotes can be created from and synced with opportunities, and emailed as PDFs to customers.

Field Type Stores Filtering
Id text Quote Identifier (Primary Key).
CreatedById text User ID who created the quote.
CreatedDate datetime Date in which the quote was created. Main field used for time-based filtering
Name text Name for the quote.
OpportunityId text ID for the opportunity associated with the quote.

ProcessDefinition

Represents the definition of a single approval process.

Field Type Stores Filtering
Id text Record Type Identifier (Primary Key).
Name text The unique process name, used internally.
TableEnumOrId text Specifies the object associated with the approval process, such as Account or Contact.
Type text The type of this process. Approval Process: used to control the action taken for a record. State-based Process: Used internally to track various control processes, such as for developing Salesforce Knowledge articles. = 'Approval'

ProcessInstance

Represents an instance of a single, end-to-end approval process.

Field Type Stores Filtering
Id text Record Type Identifier (Primary Key).
CreatedById text User ID who created the process instance. Â
CreatedDate datetime Date in which the process instance was created. Main field used for time-based filtering
Status text The status of this approval process instance, for example Started, Pending, or Approved.
ProcessDefinitionId text The ID of this approval process instance. This is a relationship field
TargetObjectId text ID of the object affected by this approval process instance. This is a polymorphic relationship field.

ProcessInstanceStep

Represents one work item in an approval process (ProcessInstance).

Field Type Stores Filtering
Id text Record Type Identifier (Primary Key).
Comments text Limit: 4,000 bytes.
CreatedById text User ID who created the process instance step. Â
CreatedDate datetime Date in which the process instance step was created. Main field used for time-based filtering
StepStatus text The current status of this approval step. Examples are Approved, Fault, Held, NoResponse, Pending, Reassigned, Rejected, Removed, Started.
ProcessInstanceId Text ID of the ProcessInstance that this approval step belongs to. This is a relationship field.

RecordType

Represents a record type, which might define a different sales process for opportunities.

Field Type Stores Filtering
Id text Record Type Identifier (Primary Key).
Name text Label of the record type in the user interface.

User

Represents each user in the Salesforce organization.

Field Type Stores Filtering
Id text Record Type Identifier (Primary Key).
Department text The company department associated with the user.
Name text Concatenation of FirstName and LastName.
UserType text The category of user license.

Design specifications

Entities

Salesforce already treats each object as an individual entity, however the objects are joined to additional master data in order to provide additional information.

Entity Input Data
Lead Lead, User
Opportunity Opportunity, Accounts, User, RecordType
Quote Quote, User
Order Order, User

The opportunities are used as input for the Cases_base table containing the following fields:

Cases_base

Field Data Type Description
Case_ID Text The unique identifier of the case. Mandatory field.
Case Text A user-friendly name to identify the case.
Account* Text Account related to the opportunity.
Account_billing_state* Text Billing State for Account.
Account_billing_country* Text Billing Country for Account.
Account_industry* Text Industry for Account.
Account_owner* Text Account Owner.
Account_ownership* Text Account Ownership (Public, Private, Subsidiary).
Account_rating* Text Rating for Account (Hot, Warm, Cold).
Account_source* Text Source for Account, such as email campaign or advertising.
Account_type* Text Account Type (mid-size, small).
Case_owner Text Opportunity Owner.
Case_status Text The status of the case in the process. For example, ‘open’, ‘closed’, ‘pending’, ‘approved’, etc.
Case_type Text The categorization of the cases.
Case_value Double A monetary value related to the case. Shown in corporate currency.
Corporate_currency* Text Currency code used to report values across the organization.
Forecast_category* Text Category for Opportunity Forecast.
Lead_source* Text Source for Lead related to Opportunity.
Opportunity_closed* Boolean Whether the Opportunity has been closed.
Opportunity_name* Text Opportunity Name.
Opportunity_probability* Text Probability of Winning the opportunity.
Opportunity_won* Boolean Whether the Opportunity has been won.
Opportunity_creator* Text User who created the opportunity.
Original_amount* Double Value for opportunity in original currency.
Record_type* Text Record Type for the opportunity.
Person_account* Boolean Whether the Account is a person account.
Transaction_currency* Text Original transaction currency.

*Case attributes which need to be configured on top of standard TemplateOne case attributes.

Activities

Entity Activity Description
Lead Creation Lead is generated in the system. Identified based on the CreateDate field on the Lead object.
Lead Add to Campaign Lead is added to a marketing campaign for tracking. Identified based on the CreateDate field on the CampaignMember object for each LeadId.
Lead Status Change* Lead moves from different status. Standard status in Salesforce are: Open, Contacted, Qualified, Unqualified. Identified based on the Old and New values for field = Status on the LeadHistory object.
Lead Approvals* Any approval process which was submitted. This may be generated by any custom configuration the customer has.
Lead Additional Field Changes* Depending on fields tracked on the object, the event will be record as a change activity. In the standard connector, Owner and Rating are tracked, but may be expanded depending on customer configuration. Identified based on records on the LeadHistory object.
Opportunity Creation Opportunity is generated in the system. Identified based on the CreateDate field on the Opportunity object.
Opportunity Stage Change* Opportunity moves from different status. Standard status in Salesforce are: Prospecting, Qualification, Needs Analysis, Value Proposition, ID Decision Makers, Perception Analysis, Proposal / Price Quote, Negotiation / Review, Closed Won, Closed Lost. Identified based on the Old and New values for field = StageName on the OpportunityFieldHistory object.
Opportunity Additional Changes* Depending on fields tracked on the object, the event will be record as a change activity. In the standard connector, Owner, Close Date and Amount are tracked, but may be expanded depending on customer configuration. Identified based on values on the OpportunityFieldHistory object.
Opportunity Approvals* Any approval process which was submitted. This may be generated by any custom configuration the customer has.
Quote Creation Quote is generated in the system. Identified based on the CreateDate field on the Quote
Quote Approvals* Any approval process which was submitted. This may be generated by any custom configuration the customer has.
Order Creation Order is generated in the system. Identified based on the CreateDate field on the Order
Order Status Change* Order moves from different status. Standard status in Salesforce are: Draft, Activated. Identified based on the Old and New values for field = Status on the OrderHistory object.
Order Additional Changes* Depending on fields tracked on the object, the event will be record as a change activity. In the standard connector, Owner, and TotalAmount are tracked, but may be expanded depending on customer configuration. Identified based on the values on the OrderHistory object.
Order Approvals* Any approval process which was submitted. This may be generated by any custom configuration the customer has.

*The actual activity names will depend on the values defined on the customer Salesforce organization.


Customizing the transformations

Seeds

Dbt Variables

Below is an overview of the variables that must be configured based on the Salesforce configuration for the end customer. These variables are defined in the dbt_project.yml file.

Variable Type Description
starting_date string Specifies the starting date for currency conversions, when there are no prior historic exchange rates. This replaces the null value that is used in Salesforce.
use_is_person_account Boolean Defines whether the IsPersonAccount attribute will be used. This should be disabled in Salesforce Orgs where there are no Person Accounts. Setting this to true will enable the attribute to being queried in the transformations, and will enable associated tests. Default is false.
use_currency_conversion Boolean Defines whether the multi currency conversion will be used. This should be disabled in Salesforce Orgs where multi currency is not used. Setting this to true will enable currency conversion. Default is false.
use_record_types Boolean Defines whether the record type conversions will be used. This should be disabled in Salesforce Orgs where record types are not used. Setting this to true will enable record types to be queried and added to the transformations. Default is false.
order_object_enabled Boolean Defines whether the order entity will be used. This should be disabled in Salesforce Orgs where orders are not used. Setting this to true will enable any transformations related to orders. Default is false.
quote_object_enabled Boolean Defines whether the quote entity will be used. This should be disabled in Salesforce Orgs where quotes are not used. Setting this to true will enable any transformations related to quotes. Default is false.

Limitations

As of January 2022, this is a current limitation on the quote object in Salesforce, as it currently does not allow for field history tracking.

No Event Start

Salesforce does not store the start time for each change activity.

No flag to identify automated users

Salesforce does not have a field or special license for automated users. It does however have a default user named Automated Process which is used for automated processing for Salesforce changes, however any additional users such as interfaces or RPA will use normal licenses and are not differentiated by user type.

Salesforce Retention Policy

As of February 2022, Salesforce retains field history data for up to 18 months through the org and up to 24 months via the API.

In case the history needs to be stored for a longer period of time, Field Audit Trail must be activated. This allows copying of history data into a separate big data object and allows storage for up to 10 years.

Troubleshooting

General

Field not available in object during data extraction

Check Field Level Security in order to confirm the field is available and visible for the user profile extracting data. For CurrencyISOCode, IsPersonAccount, LastStageChangeDate, RecordTypeId check the specific issues in the following section.

Object not available during data extraction

The user profile might not have read access to the object. This can be corrected on the user profile or a different user should extract the data. For Order, Quote, CurrencyType, DatedConversionRate check the specific issues in the following section.

Object Specific

Campaign and CampaignMember objects not available

Check the user record for the user extracting data, and verify the Marketing User checkbox is Active.

CurrencyISOCode is not available when extracting data from the Opportunity object

Multicurrency is not enabled within the Salesforce org. In case this happens, the conversions should be removed from the data model. This can be achieved by adjusting the variable use_currency_conversion in the dbt_project.yml to false.

CurrencyType object is not available when extracting data

Multicurrency is not enabled within the Salesforce org. In case this happens, the conversions should be removed from the data model. This can be achieved by adjusting the variable use_currency_conversion in the dbt_project.yml to false.

DatedConversionRate object is not available when extracting data

Effective currency rate management is not enabled within the Salesforce org. In case this happens, the conversions should be removed from the data model. This can be achieved by adjusting the variable use_currency_conversion in the dbt_project.yml to false.

IsPersonAccount field not available in Account object when extracting from Salesforce

When extracting data from Salesforce, IsPersonAccount may not be available as the organization may not have B2C customers. In case this happens, the field should be removed from the data model. This can be achieved by adjusting the variable use_is_person_account in the dbt_project.yml to false.

LastStageChangeDate field not available in Opportunity object when extracting from Salesforce

The field LastStageChangeDate was only made available starting with Salesforce REST API 52.0. Make sure the CData extraction or the extraction method used is using API 52.0 onwards.

Order object not available

The Order object may not be enabled in the Salesforce org. In case this happens the table must be loaded empty to allow for all the rest of the transformations to occur. This can be achieved by adjusting the variable order_object_enabled in the dbt_project.yml to false.

Quote object not available

The Order object may not be enabled in the Salesforce org. In case this happens the table must be loaded empty to allow for all the rest of the transformations to occur. This can be achieved by adjusting the variable quote_object_enabled in the dbt_project.yml to false.

RecordTypeId is not available when extracting data from the Opportunity object

Record Types are not used within the Salesforce org. In case this happens, the conversions should be removed from the data model. This can be achieved by adjusting the variable use_record_types in the dbt_project.yml to false.