// ========================== SERVICE LAYER METHODS ======================= //
// Logs in ServiceLayer and returns session cookies
function getSlCookies(companyDb, userName, password)
{
// Create client
var client = new $.net.http.Client();
// Where and what to send
var dest = $.net.http.readDestination("LoadCurrencyRates", "ServiceLayer");
var request = new $.net.http.Request($.net.http.POST, "Login");
request.setBody(JSON.stringify(
{
"CompanyDB": companyDb,
"UserName": userName,
"Password": password
}));
// Send the request and synchronously get the response
client.request(request, dest);
var response = client.getResponse();
// Get all the cookies from the response
var cookies = [];
for(var c in response.cookies)
{
cookies.push(response.cookies[c]);
}
// Close the connection
client.close();
// Throw an error message if B1SESSION cookie isn't got
if (cookies === undefined
|| cookies.length === 0
|| cookies.findIndex((e) => { return e.name === 'B1SESSION'; }) === -1)
{
throw new Error(response.body.asString());
}
// Return cookies if everything is ok
return cookies;
}
// Sets currency rates for the specified currencies using specified SL session
function postRates(slCookies, currencyRates, date)
{
try
{
// Create client and destination
var client = new $.net.http.Client();
var dest = $.net.http.readDestination("LoadCurrencyRates", "ServiceLayer");
// Create request
var request = new $.net.http.Request($.net.http.POST, "SBOBobService_SetCurrencyRate");
for (var cookiesCounter = 0; cookiesCounter < slCookies.length; cookiesCounter++)
{
var cookie = slCookies[cookiesCounter];
request.cookies.set(cookie.name, cookie.value);
}
// Send a request for each currency.
for (var counter = 0; counter < currencyRates.length; counter++)
{
var currencyDetails = currencyRates[counter];
if (!currencyDetails.rate) continue; // Continue if rate isn't specified
// Set body to the request
request.setBody(JSON.stringify(
{
"Currency": currencyDetails.currencyCode,
"Rate": currencyDetails.rate,
"RateDate": date
}));
// Send
client.request(request, dest);
client.getResponse();
}
// Close the connection
client.close();
}
catch (exc) {
var test = exc;
}
}
// Logs out ServiceLayer
function closeSlSession(slCookies)
{
try
{
// Create client
var client = new $.net.http.Client();
// Where and what to send
var dest = $.net.http.readDestination("LoadCurrencyRates", "ServiceLayer");
var request = new $.net.http.Request($.net.http.POST, "Logout");
for (var counter = 0; counter < slCookies.length; counter++)
{
var cookie = slCookies[counter];
request.cookies.set(cookie.name, cookie.value);
}
// Send the request. This request returns nothing.
client.request(request, dest);
client.getResponse();
// Close the connection
client.close();
}
catch (exc) {
var test = exc;
}
}
// ========================== GET CURRENCIES INFO METHODS ========================= //
// Gets info about company currencies settings
function getCompanyCurrenciesInfo(schemaName)
{
// Result object with all necessary data
var result = {
localCurrency: '',
isDirectRate: false,
isLocalEuro: false,
currencies: []
};
// Query to get currencies info
var qryText = `
SELECT "OCRN"."CurrCode" AS "CurrencyCode"
, "OADM"."MainCurncy" AS "LocalCurrency"
, "OADM"."DirectRate" AS "DirectRate"
FROM "<SchemaName>"."OCRN"
CROSS JOIN "<SchemaName>"."OADM"
WHERE "<SchemaName>"."OCRN"."CurrCode" <> "<SchemaName>"."OADM"."MainCurncy"
`;
// Open connection to HANA
var con = $.hdb.getConnection();
try
{
// Execute for the schema provided
qryText = qryText.replace(/<SchemaName>/g, schemaName);
var rs = con.executeQuery(qryText);
// Fill result object with the data from the first row
result.localCurrency = rs[0].LocalCurrency.trim();
result.isLocalEuro = result.localCurrency === 'EUR';
result.isDirectRate = rs[0].DirectRate === 'Y';
// Fill currencies array
var iterator = rs.getIterator();
while (iterator.next())
{
result.currencies.push({
currencyCode: iterator.value().CurrencyCode,
rate: 0
});
}
}
finally
{
// Close connection
con.close();
return result;
}
}
function getCurrencyRateFromXml(currencyCode, xmlString)
{
// Response is in XML so we need to parse it as string
// since there are no XML built-in functions in HANA 1.0
try
{
var pattern = "[Ss]*(?:s|<CurrencyCode>' rate=')([0-9.]*)['][Ss]*";
pattern = pattern.replace('<CurrencyCode>', currencyCode.trim());
var regex = new RegExp(pattern);
var match = regex.exec(xmlString);
if (match !== null)
{
// Value is presented
return parseFloat(match[1]);
}
else
{
// Value is not presented
return undefined;
}
}
catch (exc)
{
return undefined;
}
}
function calculateCurrencyRate(rateAgainstEuro, localAgainstEuro, isDirectRate)
{
var rate = isDirectRate ? localAgainstEuro / rateAgainstEuro : rateAgainstEuro / localAgainstEuro;
return Math.round(rate * 10000) / 10000;
}
// Fills rates from ECB web-service
function fillRates(currencyInfo)
{
// Create client
var client = new $.net.http.Client();
// Where and what to send
var dest = $.net.http.readDestination("LoadCurrencyRates", "EcbService");
var request = new $.net.http.Request($.net.http.GET, "");
// Send the request and synchronously get the response
client.request(request, dest);
var response = client.getResponse();
// Get the body
var bodyXml = response.body.asString();
// Close the connection
client.close();
// All rates are presented against euro so we need to get the cross-rate
// in case if local currency is not Euro
var localAgainstEuro = 1.0;
if (!currencyInfo.isLocalEuro)
{
localAgainstEuro = getCurrencyRateFromXml(currencyInfo.localCurrency, bodyXml);
if (localAgainstEuro === undefined) throw new Error('Cannot find the local currency with code ' + currencyInfo.localCurrency + ' in the ECB web-service'); // Stop processing if local currency isn't presented
}
var currencyAgainstEuroRate = 0.0;
for (var counter = 0; counter < currencyInfo.currencies.length; counter ++)
{
var currency = currencyInfo.currencies[counter];
if (!currencyInfo.isLocalEuro && currency.currencyCode === 'EUR')
{
// Calculate Euro rate according to company rate direction
currency.rate = calculateCurrencyRate(1, localAgainstEuro, currencyInfo.isDirectRate);
}
else // Calculate other currencies using Euro cross-rate
{
// Get currency exchange rate against euro
currencyAgainstEuroRate = getCurrencyRateFromXml(currency.currencyCode, bodyXml);
// Handle next if this currency isn't presented in the XML
if (currencyAgainstEuroRate === undefined) continue;
// Calculate rate with cross-rate and company rate direction
currency.rate = calculateCurrencyRate(currencyAgainstEuroRate, localAgainstEuro, currencyInfo.isDirectRate);
}
}
}
function GetCurrentDateAsString()
{
// Prepare todays date in necessary format
var todayDate = new Date();
var stringYear = String(todayDate.getFullYear());
var stringMonth = todayDate.getMonth() + 1 < 10 // Zero based
? '0' + String(todayDate.getMonth() + 1)
: String(todayDate.getMonth() + 1);
var stringDate = todayDate.getDate() < 10
? '0' + String(todayDate.getDate())
: String(todayDate.getDate());
return stringYear + stringMonth + stringDate;
}
// =============================== ENTRY POINT ============================ //
// Main function that performs the business logic
function loadRates(schemaName, userName, password)
{
var cookies; // SL session cookies
try // Handle exceptions in test mode only
{
// Try to login to Service Layer
cookies = getSlCookies(schemaName, userName, password);
// Get company currencies to work with
var curInfo = getCompanyCurrenciesInfo(schemaName);
// Check if currencies are got successfully and there are currencies except local currency
if (curInfo === undefined
|| curInfo.localCurrency === undefined
|| curInfo.localCurrency === ''
|| curInfo.currencies.length === 0
) throw new Error('Cannot get currency details!');
// Get currency rates for all necessary currencies
fillRates(curInfo);
// Set currency rates for the company
postRates(cookies, curInfo.currencies, GetCurrentDateAsString());
}
finally
{
// Logout if connected
if (cookies !== undefined) closeSlSession(cookies);
}
}
// Gets query string parameters
// Parameters are the following: schemaName, userName, password
function getParams()
{
var params = {};
// Extract parameters from the query string
for (var counter = 0; counter < $.request.parameters.length; counter++)
{
var param = $.request.parameters[counter];
if (param.name.toUpperCase() === 'SCHEMANAME') params.schemaName = param.value;
else if (param.name.toUpperCase() === 'USERNAME') params.userName = param.value;
else if (param.name.toUpperCase() === 'PASSWORD') params.password = param.value;
}
// Validate parameters
var mandatoryParams = [];
if (!params.hasOwnProperty('schemaName')) mandatoryParams.push('SchemaName');
if (!params.hasOwnProperty('userName')) mandatoryParams.push('UserName');
if (!params.hasOwnProperty('password')) mandatoryParams.push('Password');
// Throw an error in case not all parameters are got
if (mandatoryParams.length > 0) throw new Error('The following mandatory parameters are not provided: ' + mandatoryParams.join(', '));
return params;
}
function execute()
{
var result = {
isSuccess: true,
errMessage: ''
};
try
{
// Get parameters from the query string
var requestParams = getParams();
// Execute function
var rateLoader = $.import('LoadCurrencyRates', 'Performer');
rateLoader.loadRates(requestParams.schemaName, requestParams.userName, requestParams.password);
}
catch (exc)
{
result.isSuccess = false;
result.errMessage = !exc.message ? exc : exc.message;
}
//Build the response for test purposes
$.response.contentType = "application/json";
$.response.status = $.net.http.OK;
$.response.setBody(JSON.stringify(result));
}
execute();
// The main entry point for an XS Job
function execute(inputParameter)
{
try
{
var rateLoader = $.import('LoadCurrencyRates', 'Performer');
rateLoader.loadRates(inputParameter.schemaName, inputParameter.userName, inputParameter.password);
}
catch (exc) {
throw !exc.message ? exc : exc.message;
}
}
host = "www.ecb.europa.eu";
port = 443;
description = "Daily currency exchange rates posted by ECB";
useSSL = true;
pathPrefix = "/stats/eurofxref/eurofxref-daily.xml";
authType = none;
useProxy = false;
proxyHost = "";
proxyPort = 0;
timeout = 0;
host = "<HanaAddress>";
port = 50001;
description = "ServiceLayer UNTRUSTED!!!!";
useSSL = false;
pathPrefix = "/b1s/v1/";
authType = none;
useProxy = false;
proxyHost = "";
proxyPort = 0;
timeout = 0;
host = "<HanaAddress>";
port = 50000;
description = "ServiceLayer trusted";
useSSL = true;
pathPrefix = "/b1s/v1/";
authType = none;
useProxy = false;
proxyHost = "";
proxyPort = 0;
timeout = 0;
{
"description": "Loads currency exchange rates from ECB web-service using ServiceLayer",
"action": "LoadCurrencyRates:RunJob.xsjs::execute",
"schedules": [
{
"description": "The default schedule",
"xscron": "* * * * 23 00 0",
"parameter": {"schemaName": "SBODEMOGB",
"userName": "manager",
"password": "manager"
}
}
]
}
CREATE USER XS_ADMIN PASSWORD "Password1!";
CALL _SYS_REPO.GRANT_ACTIVATED_ROLE ('sap.hana.xs.admin.roles::TrustStoreAdministrator','XS_ADMIN');
CALL _SYS_REPO.GRANT_ACTIVATED_ROLE ('sap.hana.xs.admin.roles::JobAdministrator','XS_ADMIN');
CALL _SYS_REPO.GRANT_ACTIVATED_ROLE ('sap.hana.xs.admin.roles::JobSchedulerAdministrator','XS_ADMIN');
CALL _SYS_REPO.GRANT_ACTIVATED_ROLE ('sap.hana.xs.admin.roles::HTTPDestAdministrator','XS_ADMIN');
{"isSuccess":true,"errMessage":""}
{"isSuccess":false,"errMessage":"{\n \"error\" : {\n \"code\" : -304,\n \"message\" : {\n \"lang\" : \"en-us\",\n \"value\" : \"Fail to get DB Credentials from SLD\"\n }\n }\n}\n"}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
8 | |
3 | |
2 | |
2 | |
2 | |
2 | |
1 | |
1 | |
1 | |
1 |