ERP Order to Salesforce Account Lookup and Update
Salesforce action: GetRecordByExternalID. When a new order arrives in Dataverse (from ERP), uses the external customer ID to look up the Salesforce Account, retrieves current details, and updates the order record with the latest account info.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
When a new Account (representing an ERP-sourced order customer) lands in Dataverse, this flow automatically enriches the record with the latest customer data from Salesforce. It looks up the Salesforce Account by an external customer ID field, pulls the current Name / Industry / Phone / Billing City / Rating, and stamps a time-stamped snapshot into the Dataverse Account's description field.
The flow ships with the Dataverse-side binding set to the out-of-box account table (always present in every Dataverse environment) so the template imports cleanly with zero design-time errors. The Salesforce-side mappings and the name of the Dataverse external-ID column remain environment-variable driven, so customers can retarget the Salesforce side without editing the flow.
Use Case
Ideal for organizations that ingest customer records from an ERP into Dataverse and want each Account automatically enriched with the latest Salesforce context (Industry, Rating, Phone, Billing City) plus a time-stamped audit snapshot. Because the Salesforce object and external-ID column names vary per customer, those values are exposed as environment variables so the managed solution imports cleanly across Dev / Test / Prod without code edits.
The flow is ideal for teams that:
- ERP publishes new customers (as Dataverse Accounts) with a reference number from the source system (e.g. SAP customer ID, NetSuite internal ID)
- Sales / CSMs need each Account to carry current Salesforce context (Industry, Rating, Phone, Billing City) without logging into Salesforce
- Finance wants a time-stamped snapshot of what the Salesforce Account looked like at ingestion time for downstream reporting and audit
- The Salesforce object and external-ID column names vary per customer and must remain configurable across Dev / Test / Prod
Flow Architecture
When A New Order Arrives In Dataverse
Dataverse: SubscribeWebhookTriggerFires on Create (message = 1) at Organisation scope (scope = 4) for the OOB account entity. Runs whenever any new Account row is inserted.
Init varExternalCustomerIdField
Initialize variableSets varExternalCustomerIdField from the flowlibs_DataverseExternalCustomerIdField env var — which column on the Account row carries the external ERP customer ID.
Init varSalesforceAccountObject
Initialize variableSets varSalesforceAccountObject from the flowlibs_SalesforceAccountObject env var — the Salesforce object to look up (usually Account).
Init varSalesforceExternalIdField
Initialize variableSets varSalesforceExternalIdField from the flowlibs_SalesforceAccountExternalIdField env var — the Salesforce external-ID field name.
Init varOrderRecordId
Initialize variableParses the trigger's @odata.id to extract the newly-created Account's GUID without needing to hard-code the PK column name: first(split(last(split(triggerOutputs()?['body/@odata.id'], '(')), ')')).
Init varExternalCustomerId
Initialize variableDynamic property read of whichever Dataverse column holds the external customer ID (configured via the env var): coalesce(triggerBody()?[variables('varExternalCustomerIdField')], '').
Check If External Customer Id Provided
If conditionGuards the Salesforce call. If the new Account was created without the external customer ID, the flow takes the Else branch and writes a warning instead.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_DataverseExternalCustomerIdField | String | <configure> | The column on the Dataverse Account that holds the external ERP customer ID (e.g. accountnumber or flowlibs_erpcustomerid). Read dynamically from the trigger body. No default — set during solution import. |
| flowlibs_SalesforceAccountObject | String | <configure> | Salesforce object name to match against (usually Account; can be a custom object). No default — set during solution import. |
| flowlibs_SalesforceAccountExternalIdField | String | <configure> | The external-ID field on the Salesforce object (e.g. ERP_Customer_ID__c). No default — set during solution import. |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| Microsoft Dataverse | shared_commondataserviceforapps | SubscribeWebhookTrigger (trigger — fires on Create at Organisation scope for the account entity) UpdateRecord (writes the composed snapshot into the Account's description column) |
| Salesforce | shared_salesforce | GetItemByExternalId (looks up the Salesforce Account by external ID) |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Import the solution and set the three environment variables
- Set values during import (or post-import via Solutions -> [solution] -> Environment variables): the Dataverse external-ID column logical name on the Account table, the Salesforce object name (usually Account), and the Salesforce external-ID field API name.
- (Optional) Retarget the Dataverse table
- If you do not want to use the OOB account entity: on the trigger 'When A New Order Arrives In Dataverse', set Table name to your target entity (writes subscriptionRequest/entityname = entity logical name, singular). On 'Update Dataverse Order With Account Info', set Table name to the same entity (writes entityName = entity set name, plural). The field mapping (item/description) must also be updated to reference a field that exists on that table.
- Update the two connection references
- Point Dataverse at the mailbox / service principal that owns the target environment, and Salesforce at the OAuth connection for the org that holds the Account records.
- Turn the flow on
- The flow ships Stopped by design so no accidental fires happen in the target environment before configuration is complete.
- (Optional) Extend the Salesforce snapshot
- Edit 'Compose Account Info Description' to pull additional Salesforce fields such as AnnualRevenue, Website, or OwnerId. Any field returned by GetItemByExternalId is available via body('Get_Salesforce_Account_By_External_Id')?['FieldName'].
- (Optional) Write a structured snapshot column
- Replace the description stamp with a JSON structured value written to a dedicated AccountSnapshot column on the Dataverse Account for downstream reporting.
- (Optional) Add Try / Catch around the Salesforce branch
- Wrap the True branch in a Scope + Try / Catch pattern to write a clean error row on Salesforce connection failure.
- (Optional) Filter the Dataverse trigger
- Add a Dataverse-side filter expression on the trigger so the flow only fires for Accounts from specific business units or with specific source codes.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Record GUID from @odata.id
Use this pattern any time a Dataverse Create/Update trigger needs the row's primary key without knowing the PK column name.
EXPR.02Dynamic field lookup on the trigger body
Reads a column from the trigger body when the source column name is only known at runtime (env var or parameter).
EXPR.03Safe Salesforce field read
Coalesce the body to a placeholder so compose strings don't break on null Salesforce properties.
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.