Skip to content

Commit

Permalink
Merge pull request #561 from Expensify/andrewli-parsecurrency
Browse files Browse the repository at this point in the history
Handle currency symbols with a period in fromUSDToNumber
  • Loading branch information
dangrous authored Aug 2, 2023
2 parents b60e464 + df708b5 commit 1076899
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 9 deletions.
32 changes: 32 additions & 0 deletions __tests__/Str-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,38 @@ describe('Str.sanitizeURL', () => {
});
});

describe('Str.fromCurrencyToNumber', () => {
it('Handles negative amounts with minus sign', () => {
expect(Str.fromCurrencyToNumber('-$5.23')).toBe(-523);
expect(Str.fromCurrencyToNumber('$-5.23')).toBe(-523);
});

it('Handles negative amounts with ()', () => {
expect(Str.fromCurrencyToNumber('($5.23)')).toBe(-523);
});

it('Handles fractional cents when allowed', () => {
expect(Str.fromCurrencyToNumber('$5.223', true)).toBe(522.3);
});

it('Handles amounts without leading zeros', () => {
expect(Str.fromCurrencyToNumber('$.23')).toBe(23);
});

it('Handles amounts without cents', () => {
expect(Str.fromCurrencyToNumber('$5')).toBe(500);
});

it('Handles currency symbols with a period', () => {
expect(Str.fromCurrencyToNumber('Bs.S2.48')).toBe(248);
expect(Str.fromCurrencyToNumber('Bs.S-2.48')).toBe(-248);
expect(Str.fromCurrencyToNumber('-Bs.S2.48')).toBe(-248);
expect(Str.fromCurrencyToNumber('(Bs.S2.48)')).toBe(-248);
expect(Str.fromCurrencyToNumber('Bs.S.48')).toBe(48);
expect(Str.fromCurrencyToNumber('Bs.S2')).toBe(200);
});
});

describe('Str.isValidEmail', () => {
it('Correctly detects a valid email', () => {
expect(Str.isValidEmail('[email protected]')).toBeTruthy();
Expand Down
37 changes: 28 additions & 9 deletions lib/str.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,25 @@ const Str = {
},

/**
* Converts a USD string into th number of cents it represents.
* Converts a currency string into the number of cents it represents.
*
* @param {String} amountStr A string representing a USD value.
* @param {Boolean} allowFraction Flag indicating if fractions of cents should be
* allowed in the output.
* @param {String} amountStr String representing a currency symbol and value, like $4.02 or Bs.S97.9
* @param {Boolean} allowFraction Flag indicating if fractions of cents should be allowed in the output.
*
* @return {Number} The cent value of the @p amountStr.
*/
fromUSDToNumber(amountStr, allowFraction) {
let amount = String(amountStr).replace(/[^\d.\-()]+/g, '');
if (amount.match(/\(.*\)/)) {
const modifiedAmount = amount.replace(/[()]/g, '');
amount = `-${modifiedAmount}`;
fromCurrencyToNumber(amountStr, allowFraction) {
// eslint-disable-next-line no-param-reassign
amountStr = String(amountStr);

// Ideally, we would pass the currency symbol directly here the same string
// could be interpreted differently based on currency symbol but for now
// we match the amount from the end of the string.
let amount = amountStr.match(/(-?(?:\.\d+|\d+\.?\d*))\)?$/)[1];

// We want to support both -$5.00 and $-5.00, so we check if the string starts with -
if (amountStr.match(/\(.*\)/) || amountStr[0] === '-') {
amount = `-${amount}`;
}
amount = Number(amount) * 100;

Expand All @@ -50,6 +56,19 @@ const Str = {
return allowFraction ? amount : Math.round(amount);
},

/**
* Wrapper around fromCurrencyToNumber
*
* @deprecated
* @param {String} amountStr String representing a currency symbol and value, like $4.02 or Bs.S97.9
* @param {Boolean} allowFraction Flag indicating if fractions of cents should be allowed in the output.
*
* @return {Number} The cent value of the @p amountStr.
*/
fromUSDToNumber(...args) {
return Str.fromCurrencyToNumber(...args);
},

/**
* Truncates the middle section of a string based on the max allowed length
* @param {string} fullStr
Expand Down

0 comments on commit 1076899

Please sign in to comment.