Ballerina for Salesforce
Many organizations use Salesforce to centralize customer information, aiming to enhance customer service and sales processes. In this context, it is critical to integrate Salesforce with all customer touchpoints in order to unlock its full potential.
Ballerina, a language specifically designed for integrations, can facilitate the integration of Salesforce with all relevant systems and support any complex Salesforce integration use case.
Connect Salesforce with e-commerce platforms
E-commerce platforms like Shopify and WooCommerce are the main points of customer interactions. Ballerina can utilize packages in its library to listen for events like customer registrations, contact updates, or order placements from such platforms and propagate those changes to Salesforce.
Example: Update customer records in Salesforce, when customer data is updated in Shopify.
service /salesforce_bridge on new http:Listener(9090) {
resource function post customers(ShopifyCustomer shopifyCustomer) returns error? {
string firstName = shopifyCustomer.first_name ?: regex:split(shopifyCustomer.email, "@")[0];
string lastName = shopifyCustomer.last_name ?: "";
Address? shopifyAddress = shopifyCustomer.default_address;
string address = (shopifyAddress !is ()) ? string `${shopifyAddress.address1},
${shopifyAddress.address2}, ${shopifyAddress.city}, ${shopifyAddress.country}` : "";
SalesforceCustomer salesforceCustomer = {
Name: string `${firstName} ${lastName}`,
Email__c: shopifyCustomer.email,
Address__c: address
};
stream<Id, error?> customerStream = check salesforce->query(
string `SELECT Id FROM HmartCustomer__c WHERE Email__c = '${salesforceCustomer.Email__c}'`);
record {|Id value;|}? existingCustomer = check customerStream.next();
check customerStream.close();
if existingCustomer is () {
_ = check salesforce->create("HmartCustomer__c", salesforceCustomer);
} else {
check salesforce->update("HmartCustomer__c",
existingCustomer.value.Id, salesforceCustomer);
}
}
}
Make sales staff aware of customer issues
Customer issues are tracked in support systems such as JIRA or ServiceNow. However, sales staff also need to be informed about the problems faced by their customers. This synchronization can be done with Ballerina using a few simple steps.
Example: Import support cases from ServiceNow to Salesforce for a given time period.
public function main() returns error? {
DateRange fetchPeriod = check calculateFetchingPeriod();
CaseData[] cases = check fetchCasesFromServiceNow(fetchPeriod.'start, fetchPeriod.end);
foreach CaseData caseData in cases {
stream<Id, error?> customerStream = check salesforce->query(
string `SELECT Id FROM Account WHERE Name = '${caseData.account.name}'`);
record {|Id value;|}? existingCustomer = check customerStream.next();
check customerStream.close();
if existingCustomer is () {
continue;
}
SalesforceCase salesforceCase = {
Name: caseData.number,
Created_on__c: caseData.sys_created_on,
Priority__c: caseData.priority,
Account__c: existingCustomer.value.Id,
Summary__c: caseData.case
};
_ = check salesforce->create("Support_Case__c", salesforceCase);
}
check io:fileWriteString(syncData, check time:civilToString(fetchPeriod.now));
}
Bridge Salesforce with disparate data sources
Data about products, customers, and sales transactions are often scattered across various systems, databases, and business units. With its rich set of connectors and data handling capabilities, Ballerina can link Salesforce with all relevant data sources.
Example: Load product data from a MySQL database to Salesforce.
public function main() returns error? {
stream<ProductRecieved, error?> streamOutput = mysql->query(
`SELECT name, unitType, currencyISO, productId FROM products WHERE processed = false`);
record {|ProductRecieved value;|}|error? productRecieved = streamOutput.next();
while productRecieved !is error|() {
Product product = {
Name: productRecieved.value.name,
Product_Unit__c: productRecieved.value.unitType,
CurrencyIsoCode: productRecieved.value.currencyISO
};
_ = check salesforce->create("Product2", product);
_ = check mysql->execute(
`UPDATE products SET processed = true WHERE productId = ${productRecieved.value.productId}`);
productRecieved = streamOutput.next();
}
}
Act on Salesforce based notifications
Sales-related events need to be acted upon as soon as possible. For example, when a new contact is received, sales staff need to evaluate it and get in contact immediately. Ballerina can listen for any event in Salesforce and notify relevant employees over their preferred channels, ensuring that all customer events are attended on time.
Example: Send an SMS to a given number (via Twilio) when a new contact is created in Salesforce.
service salesforce:RecordService on sfdcEventListener {
isolated remote function onCreate(salesforce:EventData payload) returns error? {
string firstName = "";
string lastName = "";
string[] nameParts = re `,`.split(payload.changedData["Name"].toString());
if nameParts.length() >= 2 {
firstName = re `=`.split(nameParts[0])[1];
lastName = re `=`.split(re `\}`.replace(nameParts[1], ""))[1];
} else {
lastName = re `=`.split(re `\}`.replace(nameParts[0], ""))[1];
}
twilio:SmsResponse response = check twilio->sendSms(fromNumber, toNumber,
string `New contact is created! | Name: ${firstName} ${lastName} | Created Date:
${(check payload.changedData.CreatedDate).toString()}`);
}
}
Connect Salesforce with productivity tools
Sales and customer data are often captured via office productivity tools such as Google Docs, Sheets, and Slack. Ballerina can pump data from such tools into Salesforce by performing validation and cleansing where necessary to standardize manually entered data.
Example: Create contacts in Salesforce by reading contact details given in a Google Sheet.
public function main() returns error? {
sheets:Range range = check sheets->getRange(spreadsheetId, worksheetName, "A1:G");
(int|string|decimal)[] headers = range.values[0];
foreach (int|string|decimal)[] item in range.values.slice(1) {
int? indexOfEmail = headers.indexOf("Email");
if indexOfEmail is int {
stream<Contact, error?> retrievedStream = check salesforce->query(
string `SELECT Id, Email FROM Contact WHERE Email='${item[indexOfEmail]}'`);
if retrievedStream.next() is () {
record {} newContact = map from int index in 0 ..< headers.length()
let int|string|decimal header = headers[index]
select [header.toString(), item[index]];
_ = check salesforce->create("Contact", newContact);
}
}
}
}
Synchronize Salesforce with real-time data
Information, such as inventory levels, order statuses, or product prices, change constantly. With its large number of connectors and streaming capabilities, Ballerina can keep Salesforce in sync with such real-time data sources.
Example: Update Salesforce price books by listening to price details published to a Kafka topic.
service on priceListener {
isolated remote function onConsumerRecord(ProductPrice[] prices) returns error? {
foreach ProductPrice {name, unitPrice} in prices {
stream<record {}, error?> retrievedStream = check salesforce->query(
string `SELECT Id FROM PricebookEntry
WHERE Pricebook2Id = '${salesforcePriceBookId}' AND
Name = '${name}'`);
record {}[] retrieved = check from record {} entry in retrievedStream
select entry;
anydata pricebookEntryId = retrieved[0]["Id"];
if pricebookEntryId is string {
ProductPriceUpdate updatedPrice = {UnitPrice: unitPrice};
check salesforce->update("PricebookEntry", pricebookEntryId, updatedPrice);
}
}
}
}
Utilize AI to extract sales information
A Great amount of valuable sales-related information is captured in ad-hoc forms, such as emails, Word documents, and slides. Ballerina AI capabilities can be used to update Salesforce with information extracted from such unstructured data.
Example: Extract lead details such as name, phone number and company from emails using OpenAI, and create corresponding leads in Salesforce.
public function main() returns error? {
gmail:LabelList labelList = check gmail->listLabels("me");
Email[] emails = check getMatchingEmails(labelList);
foreach Email email in emails {
chat:CreateChatCompletionRequest request = {
model: "gpt-3.5-turbo",
messages: [
{
role: "user",
content: string `Extract the following details in JSON from the email.
{
firstName__c: string, // Mandatory
lastName__c: string, // Mandatory
email__c: string // Mandatory
phoneNumber__c: string, // With country code. Use N/A if unable to find
company__c: string, // Mandatory
designation__c: string // Not mandatory. Use N/A if unable to find
}
Here is the email:
{
from: ${email.'from},
subject: ${email.subject},
body: ${email.body}
}`
}
]
};
chat:CreateChatCompletionResponse response = check openAiChat->/chat/completions.post(request);
if response.choices.length() < 1 {
return error("Unable to find any choices in the response.");
}
string content = check response.choices[0].message?.content.ensureType(string);
_ = check salesforce->create("EmailLead__c", check content.fromJsonStringWithType(Lead));
}
}
Integrate Salesforce with B2B Channels
Interactions between businesses, such as sending purchase orders and invoices, usually occur over EDI-based B2B channels. Ballerina's built-in EDI capabilities can directly integrate B2B channels with Salesforce and update sales data based on B2B transactions.
Example: Update products associated with Salesforce opportunities based on products listed in EDIFACT Request for Quotation (REQOTE) messages.
public function main() returns error? {
ftp:FileInfo[] quoteList = check fileServer->list(ftpNewQuotesPath);
foreach ftp:FileInfo quoteFile in quoteList {
stream<byte[] & readonly, io:Error?> fileStream = check fileServer->get(quoteFile.path);
string quoteText = check streamToString(fileStream);
mREQOTE:EDI_REQOTE_Request_for_quote_message quote = check mREQOTE:fromEdiString(quoteText);
QuoteRequest quoteRequest = check transformQuoteRequest(quote);
stream<Id, error?> accQuery = check salesforce->query(
string `SELECT Id FROM Account WHERE Name = '${quoteRequest.accountName}'`
);
record {|Id value;|}? account = check accQuery.next();
check accQuery.close();
if account is () {
return error("Account not found. Account name: " + quoteRequest.accountName);
}
Opportunity opp = {
Name: quoteRequest.oppName,
AccountId: account.value.Id,
Pricebook2Id: salesforcePriceBookId
};
string oppId = check getOpportunityId(salesforce, quoteRequest, opp);
check createOpportunityLineItems(quoteRequest, oppId);
}
}
Start Salesforce integrations instantly with Ballerina + Choreo
Choreo provides a comprehensive app development environment with production-ready deployment, CI/CD pipelines, multi-environment support, and robust monitoring for Ballerina apps. Start Salesforce integrations instantly on the cloud with Choreo and continue incrementally to unleash the full power of Salesforce.