utils/currency.js

  1. /*
  2. * Your installation or use of this SugarCRM file is subject to the applicable
  3. * terms available at
  4. * http://support.sugarcrm.com/Resources/Master_Subscription_Agreements/.
  5. * If you do not agree to all of the applicable terms or do not have the
  6. * authority to bind the entity as an authorized representative, then do not
  7. * install or use this SugarCRM file.
  8. *
  9. * Copyright (C) SugarCRM Inc. All rights reserved.
  10. */
  11. const math = require('./math');
  12. const User = require('../core/user');
  13. const Utils = require('./utils');
  14. /**
  15. * Currency module provides utility methods for working with currencies.
  16. *
  17. * @module Utils/Currency
  18. */
  19. module.exports = {
  20. /**
  21. * Gets the base currency id.
  22. *
  23. * @return {string} The base currency id.
  24. */
  25. getBaseCurrencyId: function() {
  26. return SUGAR.App.metadata.getBaseCurrencyId();
  27. },
  28. /**
  29. * Gets the system's base currency.
  30. *
  31. * @return {Object} The base currency data.
  32. */
  33. getBaseCurrency: function() {
  34. var currId = SUGAR.App.metadata.getBaseCurrencyId(),
  35. currencyObj = SUGAR.App.metadata.getCurrency(currId);
  36. // add currency_id to returned data
  37. currencyObj.currency_id = currId;
  38. return currencyObj;
  39. },
  40. /**
  41. * Returns a map of currency IDs to the result of applying the
  42. * given Handlebars template to them.
  43. *
  44. * Example for the `template` param:
  45. * ```
  46. * getCurrenciesSelector(Handlebars.compile('{{symbol}} ({{iso}})'));
  47. * ```
  48. *
  49. * @param {Function} template How to format the values returned.
  50. * @return {Object} Map from currency IDs to formatted currency data.
  51. */
  52. getCurrenciesSelector: function(template) {
  53. var currencies = {};
  54. _.each(SUGAR.App.metadata.getCurrencies(), function(currency, id) {
  55. currencies[id] = template(currency);
  56. });
  57. return currencies;
  58. },
  59. /**
  60. * Gets the symbol for the given currency ID.
  61. *
  62. * @param {string} currencyId Currency identifier.
  63. * @return {string} The currency display symbol (e.g. "$").
  64. */
  65. getCurrencySymbol: function (currencyId) {
  66. var currency = SUGAR.App.metadata.getCurrency(currencyId);
  67. return currency ? currency.symbol : '';
  68. },
  69. /**
  70. * Formats a currency amount.
  71. *
  72. * @param {number} amount The amount to be formatted.
  73. * @param {string} [currencyId] The currency id to be used. If not
  74. * specified, the system default will be used.
  75. * @param {number} [decimalPrecision=2] The number of digits for
  76. * decimal precision.
  77. * @param {string} [numberGroupingSeparator=','] The thousands separator.
  78. * @param {string} [decimalSeparator='.'] The decimal separator (string
  79. * between number and decimal digits).
  80. * @param {string} [symbolSeparator=''] The string between the symbol and
  81. * the amount.
  82. * @return {string} The formatted currency amount.
  83. */
  84. formatAmount: function(
  85. amount,
  86. currencyId,
  87. decimalPrecision,
  88. numberGroupingSeparator,
  89. decimalSeparator,
  90. symbolSeparator
  91. ) {
  92. // we don't want to format non-numbers
  93. if (!_.isFinite(amount)) {
  94. return amount;
  95. }
  96. var currencySymbol;
  97. var config = SUGAR.App.metadata.getConfig();
  98. // default to base currency
  99. currencyId = currencyId || this.getBaseCurrencyId();
  100. symbolSeparator = symbolSeparator || '';
  101. // use reasonable defaults if none exist
  102. if (!_.isFinite(decimalPrecision)) {
  103. if (_.isFinite(config.defaultCurrencySignificantDigits)) {
  104. decimalPrecision = config.defaultCurrencySignificantDigits;
  105. }
  106. else {
  107. decimalPrecision = 2;
  108. }
  109. }
  110. decimalSeparator = decimalSeparator || config.defaultDecimalSeparator || '.';
  111. // if the numberGroupingSeparator is truly undefined we need to get the defaults, if it's an empty string
  112. // we need to use the empty string as it's a valid value.
  113. numberGroupingSeparator = (!_.isUndefined(numberGroupingSeparator)) ?
  114. numberGroupingSeparator : config.defaultNumberGroupingSeparator || ',';
  115. currencySymbol = this.getCurrencySymbol(currencyId) || this.getCurrencySymbol(this.getBaseCurrencyId());
  116. amount = Utils.formatNumber(
  117. amount,
  118. decimalPrecision,
  119. decimalPrecision,
  120. numberGroupingSeparator,
  121. decimalSeparator
  122. );
  123. return currencySymbol + symbolSeparator + amount;
  124. },
  125. /**
  126. * Formats a currency amount according to the current user's locale.
  127. *
  128. * @param {number} amount The amount to format.
  129. * @param {string} [currencyId] The currency id to use. If not
  130. * specified, the system default will be used.
  131. * @param {string} [decimalPrecision] The number of decimal digits to use.
  132. * If not specified, the user preference will be used.
  133. * @return {string} formatted currency amount.
  134. */
  135. formatAmountLocale: function (amount, currencyId, decimalPrecision) {
  136. // get user preferred formatting
  137. var decimalSeparator = User.getPreference('decimal_separator');
  138. var numberGroupingSeparator = User.getPreference('number_grouping_separator');
  139. var userDecimalPrecision = User.getPreference('decimal_precision');
  140. decimalPrecision = (_.isFinite(decimalPrecision)) ? decimalPrecision : userDecimalPrecision;
  141. return this.formatAmount(
  142. amount,
  143. currencyId,
  144. decimalPrecision,
  145. numberGroupingSeparator,
  146. decimalSeparator
  147. );
  148. },
  149. /**
  150. * Unformats a currency amount.
  151. *
  152. * @param {string} amount The amount to unformat.
  153. * @param {string} numberGroupingSeparator Thousands separator.
  154. * @param {string} decimalSeparator The string between number and decimals.
  155. * @param {boolean} [toFloat=false] If `true`, convert string to float
  156. * value.
  157. * @return {string} The unformatted currency amount.
  158. */
  159. unformatAmount:function (amount, numberGroupingSeparator, decimalSeparator, toFloat) {
  160. toFloat = toFloat || false;
  161. // strip off currency symbol, or anything prefixed that is not a digit or separator
  162. amount = amount.toString().replace(/^[^\d\.\,-]+/, '');
  163. return Utils.unformatNumberString(
  164. amount,
  165. numberGroupingSeparator,
  166. decimalSeparator,
  167. toFloat
  168. );
  169. },
  170. /**
  171. * Unformats the currency amount according to the current user's locale.
  172. *
  173. * @param {string} amount Amount to unformat.
  174. * @param {boolean} toFloat If `true`, convert string to float value.
  175. * @return {string} The unformatted currency amount.
  176. */
  177. unformatAmountLocale:function (amount, toFloat) {
  178. var decimalSeparator,
  179. numberGroupingSeparator,
  180. config = SUGAR.App.metadata.getConfig();
  181. // use user locale or reasonable defaults
  182. decimalSeparator = User.getPreference('decimal_separator') || config.defaultDecimalSeparator || '.';
  183. var userNumGroupingSeparator = User.getPreference('number_grouping_separator');
  184. numberGroupingSeparator = userNumGroupingSeparator || config.defaultNumberGroupingSeparator || ',';
  185. return this.unformatAmount(
  186. amount,
  187. numberGroupingSeparator,
  188. decimalSeparator,
  189. toFloat
  190. );
  191. },
  192. /**
  193. * Converts from one currency to another.
  194. *
  195. * @param {number|string} amount Base currency amount.
  196. * @param {string} fromId Source currency id.
  197. * @param {string} toId Target currency id.
  198. * @return {string} The converted amount.
  199. */
  200. convertAmount: function(amount, fromId, toId) {
  201. var currency1;
  202. var currency2;
  203. if (fromId == toId) {
  204. return math.round(amount, undefined, true);
  205. }
  206. currency1 = SUGAR.App.metadata.getCurrency(fromId);
  207. currency2 = SUGAR.App.metadata.getCurrency(toId);
  208. return this.convertWithRate(amount, currency1.conversion_rate, currency2.conversion_rate);
  209. },
  210. /**
  211. * Converts a currency to the base currency.
  212. *
  213. * @param {number|string} amount The amount in the source currency.
  214. * @param {string} fromId Source currency id.
  215. * @return {string} The converted amount.
  216. */
  217. convertToBase: function (amount, fromId) {
  218. return this.convertAmount(amount, fromId, this.getBaseCurrencyId());
  219. },
  220. /**
  221. * Converts from the base currency to another currency.
  222. *
  223. * @param {number|string} amount The amount in the base currency.
  224. * @param {string} toId Target currency id.
  225. * @return {string} The converted amount.
  226. */
  227. convertFromBase:function (amount, toId) {
  228. return this.convertAmount(amount, this.getBaseCurrencyId(), toId);
  229. },
  230. /**
  231. * Converts a currency with given conversion rates.
  232. *
  233. * @param {number|string} amount The amount in the origin currency.
  234. * @param {number} fromRate The origin conversion rate relative to the base
  235. * currency.
  236. * @param {number} toRate The target conversion rate relative to the base
  237. * currency.
  238. * @return {string} The converted amount.
  239. */
  240. convertWithRate: function(amount, fromRate, toRate) {
  241. fromRate = fromRate || 1.0;
  242. toRate = toRate || 1.0;
  243. return math.mul(math.div(amount, fromRate, undefined, true), toRate, undefined, true);
  244. }
  245. };
  246. JAVASCRIPT
    Copied!