Skip to content

Commit

Permalink
Merge pull request #46 from sahanHe/revamp
Browse files Browse the repository at this point in the history
Revamp salesforce integration samples
  • Loading branch information
anupama-pathirage authored Jan 10, 2024
2 parents 63049bb + 9db15fa commit b944537
Show file tree
Hide file tree
Showing 26 changed files with 252 additions and 370 deletions.
147 changes: 83 additions & 64 deletions ftp-edi-message-to-salesforce-opportunity/main.bal
Original file line number Diff line number Diff line change
@@ -1,77 +1,48 @@
import ballerina/file;
import ballerina/ftp;
import ballerina/io;
import ballerina/log;

import ballerinax/edifact.d03a.retail.mREQOTE;
import ballerinax/salesforce as sf;

configurable ftp:ClientConfiguration ftpConfig = ?;
configurable string ftpNewQuotesPath = ?;
configurable string ftpProcessedQuotesPath = ?;
configurable sf:ConnectionConfig salesforceConfig = ?;
configurable string salesforcePriceBookId = ?;

final ftp:Client fileServer = check new (ftpConfig);
final sf:Client salesforce = check new (salesforceConfig);

sf:Client salesforce = check new (salesforceConfig);
ftp:Client fileServer = check new ftp:Client(ftpConfig);
public function main() returns error? {
ftp:FileInfo[] quoteList = check fileServer->list(ftpNewQuotesPath);
foreach ftp:FileInfo quoteFile in quoteList {
string|error quoteText = getFileText(quoteFile);
if quoteText is error {
log:printError(quoteText.message());
continue;
}
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);
string|error accountId = getSalesforceAccountId(quoteRequest.accountName);
if accountId is error {
log:printError(accountId.message());
continue;
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);
}
string oppId = check getSalesforceOpportunityId(accountId, quoteRequest.oppName);
check createLineItems(quoteRequest.itemData, oppId);
check moveProcessedFile(quoteFile, quoteText);
}
}

function getSalesforceAccountId(string accountName) returns string|error {
stream<Id, error?> accQuery = check salesforce->query(
string `SELECT Id FROM Account WHERE Name = '${accountName}'`);
record {|Id value;|}? account = check accQuery.next();
check accQuery.close();
if account is () {
return error("Account not found. Account name: " + accountName);
}
return account.value.Id;
}

function getSalesforceOpportunityId(string accountId, string oppName) returns string|error {
stream<Id, error?> oppQuery = check salesforce->query(
string `SELECT Id FROM Opportunity WHERE Name = '${oppName}'`);
record {|Id value;|}? existingOpp = check oppQuery.next();
check oppQuery.close();
if existingOpp !is () {
return existingOpp.value.Id;
Opportunity opp = {
Name: quoteRequest.oppName,
AccountId: account.value.Id,
Pricebook2Id: salesforcePriceBookId
};
string oppId = check getOpportunityId(salesforce, quoteRequest, opp);
check createOpportunityLineItems(quoteRequest, oppId);
}
Opportunity opp = {
Name: oppName,
AccountId: accountId,
Pricebook2Id: salesforcePriceBookId
};
sf:CreationResponse oppResult = check salesforce->create("Opportunity", opp);
return oppResult.id;
}

function createLineItems(ItemData[] items, string oppId) returns error? {
foreach ItemData item in items {
function createOpportunityLineItems(QuoteRequest quoteRequest, string oppId) returns error? {
foreach ItemData item in quoteRequest.itemData {
stream<PriceBookEntry, error?> query = check salesforce->query(
string `SELECT UnitPrice FROM PricebookEntry WHERE Pricebook2Id = '01s6C000000UN4PQAW' AND Product2Id = '${item.itemId}'`);
string `SELECT UnitPrice FROM PricebookEntry WHERE Pricebook2Id =
'01s6C000000UN4PQAW' AND Product2Id = '${item.itemId}'`
);
record {|PriceBookEntry value;|}? unionResult = check query.next();
check query.close();
if unionResult is () {
return error(string `Pricebook entry not found. Opportunity: ${oppId}, Item ID: ${item.itemId}`);
return error(string `Pricebook entry not found. Opportunity name: ${quoteRequest.oppName}, Item ID: ${item.itemId}`);
}
OpportunityProduct oppProduct = {
OpportunityId: oppId,
Expand All @@ -82,20 +53,68 @@ function createLineItems(ItemData[] items, string oppId) returns error? {
_ = check salesforce->create("OpportunityLineItem", oppProduct);
}
}

function moveProcessedFile(ftp:FileInfo quoteFile, string quoteText) returns error? {
check fileServer->put(check file:joinPath(ftpProcessedQuotesPath, quoteFile.name), quoteText.toBytes());
check fileServer->delete(quoteFile.path);
function getOpportunityId(sf:Client salesforce, QuoteRequest quoteRequest, Opportunity opp) returns string|error {
string oppId = "";
stream<Id, error?> oppQuery = check salesforce->query(
string `SELECT Id FROM Opportunity WHERE Name = '${quoteRequest.oppName}'`);
record {|Id value;|}? existingOpp = check oppQuery.next();
check oppQuery.close();
if existingOpp is () {
sf:CreationResponse oppResult = check salesforce->create("Opportunity", opp);
oppId = oppResult.id;
} else {
oppId = existingOpp.value.Id;
}
return oppId;
}

function getFileText(ftp:FileInfo quoteFile) returns string|error {
if !quoteFile.name.endsWith(".edi") {
return error("Invalid file type. File name: " + quoteFile.name);
function transformQuoteRequest(mREQOTE:EDI_REQOTE_Request_for_quote_message quote) returns QuoteRequest|error {
QuoteRequest quoteRequest = {accountName: "", oppName: ""};
mREQOTE:Segment_group_1_GType[] segmentGroup1 = quote.Segment_group_1;
foreach mREQOTE:Segment_group_1_GType ref in segmentGroup1 {
if ref.REFERENCE.REFERENCE.Reference_code_qualifier == "AES" {
string? oppId = ref.REFERENCE.REFERENCE.Reference_identifier;
if oppId is () {
return error("Opportunity ID is not given");
}
quoteRequest.oppName = oppId;
}
}
mREQOTE:Segment_group_11_GType[] segmentGroup11 = quote.Segment_group_11;
foreach mREQOTE:Segment_group_11_GType party in segmentGroup11 {
if party.NAME_AND_ADDRESS.Party_function_code_qualifier == "BY" {
string? prospectId = party.NAME_AND_ADDRESS?.PARTY_IDENTIFICATION_DETAILS?.Party_identifier;
if prospectId is () {
return error("Prospect identifier not available in quote.");
}
quoteRequest.accountName = prospectId;
}
}
stream<byte[] & readonly, io:Error?> fileStream = check fileServer->get(quoteFile.path);
mREQOTE:Segment_group_27_GType[] items = quote.Segment_group_27;
foreach mREQOTE:Segment_group_27_GType item in items {
string? itemId = item.LINE_ITEM.Line_item_identifier;
if itemId is () {
return error("Item ID is not given");
}
ItemData itemData = {itemId};
mREQOTE:QUANTITY_Type[] quantities = item.QUANTITY;
foreach mREQOTE:QUANTITY_Type quantity in quantities {
if quantity.QUANTITY_DETAILS.Quantity_type_code_qualifier == "21" {
int|error amount = int:fromString(quantity.QUANTITY_DETAILS.Quantity);
if amount is error {
return error("Quantity must be a valid number.");
}
itemData.quantity = amount;
break;
}
}
quoteRequest.itemData.push(itemData);
}
return quoteRequest;
}
function streamToString(stream<byte[] & readonly, io:Error?> inStream) returns string|error {
byte[] content = [];
check fileStream.forEach(function(byte[] & readonly chunk) {
check inStream.forEach(function(byte[] & readonly chunk) {
content.push(...chunk);
});
return string:fromBytes(content);
}
}
17 changes: 6 additions & 11 deletions gdrive-files-to-microsoft-onedrive-files/main.bal
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import ballerina/log;
import ballerinax/googleapis.drive;
import ballerinax/microsoft.onedrive;

Expand All @@ -10,44 +9,40 @@ configurable string oneDrivePath = ?;

configurable boolean filesOverridable = ?;

public function main() returns error? {
drive:Client gDrive = check new ({auth: {token: gDriveAccessToken}});
onedrive:Client onedrive = check new ({auth: {token: oneDriveAccessToken}});
drive:Client gDrive = check new ({auth: {token: gDriveAccessToken}});
onedrive:Client onedrive = check new ({auth: {token: oneDriveAccessToken}});

string gDriveQuery = string `'${gDriveFolderId}' in parents and trashed = false`;
stream<drive:File> filesInGDrive = check gDrive->getAllFiles(gDriveQuery);
public function main() returns error? {
stream<drive:File> filesInGDrive = check gDrive->getAllFiles(
string `'${gDriveFolderId}' in parents and trashed = false`
);

foreach drive:File file in filesInGDrive {
string? fileName = file?.name;
string? fileId = file?.id;
boolean writable = false;

if fileName is () || fileId is () {
log:printError("File name or ID not found");
continue;
}
if !filesOverridable {
boolean|error isExistingFile = checkIfFileExistsInOneDrive(fileName, onedrive);
if isExistingFile is error {
log:printError("Searching files in Microsoft OneDrive failed!", isExistingFile);
continue;
}
writable = !isExistingFile;
}
if filesOverridable || writable {
drive:FileContent|error fileContent = gDrive->getFileContent(fileId);
if fileContent is error {
log:printError("Retrieving file from Google Drive failed!", fileContent);
continue;
}
onedrive:DriveItemData|error driveItemData = onedrive->
uploadFileToFolderByPath(oneDrivePath, fileName, fileContent?.content,
fileContent?.mimeType);
if driveItemData is error {
log:printError("Uploading file to Microsoft OneDrive failed!", driveItemData);
continue;
}
log:printInfo(string `File ${fileName} uploaded successfully!`);
}
}
}
Expand Down
Loading

0 comments on commit b944537

Please sign in to comment.