Skip to content

Commit

Permalink
fix: ensure that currencies are loaded at startup
Browse files Browse the repository at this point in the history
This commit ensures that the CurrencyFilter will request all available
currencies at startup.  This allows the application to use currencies
with impunity, without considering if the currency is available or not,
since it will be by default.
  • Loading branch information
jniles committed Apr 13, 2016
1 parent 740ca1d commit 4f2d1c4
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 63 deletions.
71 changes: 39 additions & 32 deletions client/src/js/filters/currency.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,74 @@
'use strict';

/**
* @description
* BHIMA fork of angular's native currency filter.
* Allows currency to be defined for each filter individually.
/**
* BHIMA fork of angular's native currency filter.
* Allows currency to be defined for each filter individually.
* Currency IDs are used to fetch configuration files asynchronously from the server.
* Completely seperates locale from currency format to facilitate reliable accounting.
* Completely separates locale from currency format to facilitate reliable accounting.
* Clearly fails given an unsupported currency ID or configuration.
*
* @param {number} amount Value to be converted into currency
* @param {number} currencyId ID for
* @param {number} currencyId ID for
* @returns {string} Valid supported currency or error string
*/
*/

angular.module('bhima.filters')
.filter('currency', ['currencyFormat', 'SessionService', function (CurrencyFormat, Session) {
var requireCurrencyDefinition = false;

.filter('currency', CurrencyFilter);

CurrencyFilter.$inject = [
'currencyFormat', 'SessionService'
];


function CurrencyFilter(CurrencyFormat, Session) {
var requireCurrencyDefinition = false;

function currencyFilter(amount, currencyId) {
var formatConfiguration;
var amountUndefined = angular.isUndefined(amount) || angular === null;
var amountUndefined = angular.isUndefined(amount) || angular === null;

if (angular.isUndefined(currencyId)) {
if (angular.isUndefined(currencyId)) {

if (requireCurrencyDefinition) {
if (requireCurrencyDefinition) {
return formatError('INVALID_CURRENCY_DEFINITION', amount);
} else {
// Display enterprise currency unless otherwise specified
} else {

// Display enterprise currency unless otherwise specified
currencyId = Session.enterprise.currency_id;
}
}
// Terminate early to reduce calculations for ill formed requests
if (amountUndefined) {

// Terminate early to reduce calculations for ill formed requests
if (amountUndefined) {
return null;
}

// Currency cache has not yet retrieved available currency index
if (!CurrencyFormat.indexReady()) {
// Currency cache has not yet retrieved available currency index
if (!CurrencyFormat.indexReady()) {
return null;
}

formatConfiguration = CurrencyFormat.request(currencyId);

// No configuration found - definition is probably being fetched
if (angular.isUndefined(formatConfiguration)) {
if (angular.isUndefined(formatConfiguration)) {
return null;
}

// Currency ID did not match a currency ID or format configuration was not found
if (!formatConfiguration.supported) {
if (!formatConfiguration.supported) {
return formatError('CURRENCY_NOT_SUPPORTED', amount);
}

return formatNumber(amount, formatConfiguration.PATTERNS[1], formatConfiguration.GROUP_SEP, formatConfiguration.DECIMAL_SEP)
.replace(/\u00A4/g, formatConfiguration.CURRENCY_SYM);
}

// Utility methods
function formatError(message, amount) {
// utility methods
function formatError(message, amount) {
return message.concat('(', amount, ')');
}

// Formatting method directly from angular native filter - does not support BHIMA coding guidelines
var DECIMAL_SEP = '.';
function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
Expand Down Expand Up @@ -134,7 +140,7 @@ angular.module('bhima.filters')
fraction += '0';
}

if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize); // jshint ignore:line
if (fractionSize && fractionSize !== '0') { formatedText += decimalSep + fraction.substr(0, fractionSize); }
} else {
if (fractionSize > 0 && number < 1) {
formatedText = number.toFixed(fractionSize);
Expand All @@ -153,5 +159,6 @@ angular.module('bhima.filters')
}

currencyFilter.$stateful = true;

return currencyFilter;
}]);
}
71 changes: 40 additions & 31 deletions client/src/js/services/currencyFormat.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,95 +2,104 @@

/**
* @description
* Provides asynchronous GET requests for currency configuration files, fetched
* Provides asynchronous GET requests for currency configuration files, fetched
* configurations are cached and served directly to subsequent requests.
*
* @returns {object} Wrapper object exposing request configuration method
*/
angular.module('bhima.services')
.factory('currencyFormat', ['$http', 'util', 'store', function ($http, util, Store) {
.factory('currencyFormat', currencyFormat);

currencyFormat.$inject = [
'CurrencyService', '$http', 'store'
];

function currencyFormat(Currencies, $http, Store) {
var currencyConfigurationPath = '/i18n/currency/';
var loadedSupportedCurrencies = false;
var supportedCurrencies = new Store({identifier : 'id'});
var currentFormats = new Store({identifier : 'format_key'});
var fetchingKeys = [];
var invalidCurrency = { supported : false };

// Request all defined BHIMA currencies
$http.get('/currencies')
.then(util.unwrapHttpResponse)
.then(function (currencyList) {
supportedCurrencies.setData(currencyList);
Currencies.read()
.then(function (currencies) {
supportedCurrencies.setData(currencies);
loadedSupportedCurrencies = true;

// automatically load all currency formats at startup
currencies.forEach(function (currency) {
searchFormatConfiguration(currency.id);
});
});

// Requests individual currency configurations
function fetchFormatConfiguration(key) {
function fetchFormatConfiguration(key) {
var formatObject = null;
fetchingKeys[key] = true;

$http.get(currencyConfigurationPath.concat(key, '.json'))
.then(function (response) {
.then(function (response) {

// Add configuration to local cache
formatObject = response.data;
formatObject.supported = true;
formatObject.format_key = key;
addFormat(formatObject);
addFormat(formatObject);
})
.catch(function (err) {
.catch(function (err) {

// Deny future attempts to request this configuration
formatObject = invalidCurrency;
formatObject.format_key = key;
addFormat(formatObject);
});
}

function addFormat(formatObject) {

// FIXME Resolve issue with initial Store data to just allow post. Github Ref: #
if (angular.isUndefined(currentFormats.data.length)) {
function addFormat(formatObject) {
/** @FIXME Resolve issue with initial Store data to just allow post. */
if (angular.isUndefined(currentFormats.data.length)) {
currentFormats.setData([formatObject]);
} else {
} else {
currentFormats.post(formatObject);
}
}

/**
* @param {number} currencyId ID of currency to be checked against BHIMA's database
*
* @returns {object} Returns format configuration if it has been found and fetched,
* @returns {object} Returns format configuration if it has been found and fetched,
* objects reporting unsupported status if configuration or currency cannot be found
*/
function searchFormatConfiguration(currencyId) {
var supportedCurrency = supportedCurrencies.get(currencyId);

if (angular.isUndefined(supportedCurrency)) {
if (angular.isUndefined(supportedCurrency)) {
return invalidCurrency;
}
// currency has been identified - search for configuration

// currency has been identified - search for configuration
var formatKey = supportedCurrency.format_key;
var progress = fetchingKeys[formatKey];

// initial for request for currency with this key - initialise configuration request
if (!angular.isDefined(progress)) {
if (!angular.isDefined(progress)) {
fetchFormatConfiguration(formatKey);
}

return currentFormats.get(formatKey);
}

/**
* @returns {boolean} Exposes status of initial currency index cache request
*/
function reportStatus() {
function reportStatus() {
return loadedSupportedCurrencies;
}

return {
return {
request : searchFormatConfiguration,
indexReady : reportStatus
};
}]);
}

0 comments on commit 4f2d1c4

Please sign in to comment.