Skip to content

Commit

Permalink
Update ftp to salesforce integration sample
Browse files Browse the repository at this point in the history
  • Loading branch information
sahanHe committed Jan 10, 2024
1 parent 65d7236 commit e9a6b73
Showing 1 changed file with 82 additions and 63 deletions.
145 changes: 82 additions & 63 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,19 +53,67 @@ 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);
Expand Down

0 comments on commit e9a6b73

Please sign in to comment.