Expensify / App

Welcome to New Expensify: a complete re-imagination of financial collaboration, centered around chat. Help us build the next generation of Expensify by sharing feedback and contributing to the code.
https://new.expensify.com
MIT License
3.53k stars 2.88k forks source link

[HOLD for payment 2023-10-10] [$500] Don't allow decimals in request amounts if the currency doesn't support decimals #26551

Closed kbecciv closed 1 year ago

kbecciv commented 1 year ago

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Action Performed:

  1. Open anything that involves money. (Request money, split bill etc).
  2. Write any amount in decimal in a currency that disallows decimals (i.e. ISK or MGA)
  3. Click next

Expected Result:

We should return an error stating that decimals are not supported in the selected currency.

Actual Result:

No error is returned and the amount is rounded.

Workaround:

Unknown

Platforms:

Which of our officially supported platforms is this issue occurring on?

Version Number: 1.3.62.0 Reproducible in staging?: y Reproducible in production?: y If this was caught during regression testing, add the test name, ID and link from TestRail: Email or phone of affected tester (no customers): Logs: https://stackoverflow.com/c/expensify/questions/4856 Notes/Photos/Videos: Any additional supporting documentation

https://github.com/Expensify/App/assets/93399543/faf670c6-a706-4534-92ea-136ac30b1b6e

https://github.com/Expensify/App/assets/93399543/c0c8f7af-8350-4be0-84ea-62aa2101610e

Expensify/Expensify Issue URL: Issue reported by: @priyankrawat Slack conversation: https://expensify.slack.com/archives/C049HHMV9SM/p1690213457772999

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~018f0f0811f6fe308d
  • Upwork Job ID: 1699169106621186048
  • Last Price Increase: 2023-09-25
  • Automatic offers:
    • esh-g | Contributor | 26858302
esh-g commented 1 year ago

Proposal

Please re-state the problem we are trying to solve

Some currencies are automatically rounded off and decimals are removed while requesting money.

What is the root cause of this problem?

Some currencies don't allow decimals places to be present in their denominations. We are already getting the decimals allowed by a currency in the ONYXKEYS.CURRENCY_LIST. Example:

VND: { 
  ISO4217: "704",
  decimals: 0,
  name: "Vietnam Dong",
  symbol: "₫"
}

So, if we select this currency the decimals are removed as decimals : 0.

What changes should be made to fix this?

We should not allow the user to enter decimals places for currencies that don't allow it. This can be done by modifying the MoneyRequestUtils.validateAmount() method.

  1. https://github.com/Expensify/App/blob/9701fbe5ec24bf5031da390075b2a9fb125b3ce3/src/pages/iou/steps/MoneyRequestAmountForm.js#L64-L72 In the MoneyRequestAccountForm we should get the decimals allowed for the currency in the body of the component like this:

    const decimals = CurrencyUtils.getCurrencyDecimals(currency);
  2. https://github.com/Expensify/App/blob/9701fbe5ec24bf5031da390075b2a9fb125b3ce3/src/libs/MoneyRequestUtils.js#L59-L62 Modify the MoneyRequestUtils.validateAmount() to take two arguments instead of one: amount and decimals. Then, use a dynamic regex to validate the amount according to the decimals like this:

    function validateAmount(amount, decimals) {
    const regexString = decimals === 0
    ? `^(\\d+(,\\d+)?)?$`                            // don't allow decimal point if decimals === 0
    : `^(\\d+(,\\d+)*(\\.\\d{0,${decimals}})?)?$`;   // Allow the decimal point and the desired number of digits after the point
    const decimalNumberRegex = new RegExp(regexString, 'i');
    return amount === '' || (decimalNumberRegex.test(amount) && calculateAmountLength(amount) <= CONST.IOU.AMOUNT_MAX_LENGTH);
    }
  3. https://github.com/Expensify/App/blob/9701fbe5ec24bf5031da390075b2a9fb125b3ce3/src/pages/iou/steps/MoneyRequestAmountForm.js#L126 Modify the use of the validateAmount() function and pass the decimals we got in step 1 to the function like this:

    if (!MoneyRequestUtils.validateAmount(newAmountWithoutSpaces, decimals)) {
  4. We can also add a function to strip the decimals places if the currentAmount if it doesn't match the decimals when the currency is changed. Like we have these functions here: https://github.com/Expensify/App/blob/1eafc7dff1cb609e72a97d6f1d1993a2bf22aaa6/src/libs/MoneyRequestUtils.js#L10-L24

    function stripDecimalsFromAmount(amount) {
    return amount.replace(/\.\d*/, '');
    }

    Then add a useEffect to MoneyRequestAccountForm to use the function on currency change:

    useEffect(() => {
        if (!MoneyRequestUtils.validateAmount(currentAmount, decimals)) {
            setCurrentAmount(MoneyRequestUtils.stripDecimalsFromAmount(currentAmount));
        }
    }, [currency]);
melvin-bot[bot] commented 1 year ago

Triggered auto assignment to @sakluger (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details.

melvin-bot[bot] commented 1 year ago

Bug0 Triage Checklist (Main S/O)

sakluger commented 1 year ago

This is by design. Some currencies do not support decimals.

melvin-bot[bot] commented 1 year ago

Current assignee @sakluger is eligible for the NewFeature assigner, not assigning anyone new.

sakluger commented 1 year ago

Reopening as a NewFeature. I updated the title and OP to reflect that we should not even allow amounts to be entered with decimals if the selected currency doesn't support decimals.

sakluger commented 1 year ago

I think this has to be internal - in order to determine if a currency supports decimals, we need to access a private repo.

melvin-bot[bot] commented 1 year ago

Job added to Upwork: https://www.upwork.com/jobs/~018f0f0811f6fe308d

melvin-bot[bot] commented 1 year ago

Triggered auto assignment to Contributor Plus for review of internal employee PR - @parasharrajat (Internal)

melvin-bot[bot] commented 1 year ago

Triggered auto assignment to @grgia (Engineering), see https://stackoverflow.com/c/expensify/questions/4319 for more details.

sakluger commented 1 year ago

cc @aldo-expensify since we discussed in Slack: https://expensify.slack.com/archives/C049HHMV9SM/p1693939667624119?thread_ts=1690213457.772999&cid=C049HHMV9SM

parasharrajat commented 1 year ago

@esh-g proposal looks good but instead of point 4, we should strip decimals when currency is changed.

What will be your plan for that?

esh-g commented 1 year ago

@parasharrajat I have updated the proposal step 4 to reflect the changes you asked for. Please let me know if it looks good. I went with stripping the decimals without checking the decimal places allowed because I don't think we support currencies with denominations other than 1 or 0.01. But still if we want to strip only the places with respect to the decimals provided we can use this function:

function stripDecimalsFromAmount(amount, decimals) {
    if (!decimals) {
        // If 'decimals' is not provided or equals 0, strip all decimals
        return amount.replace(/\.\d*/, '');
    } else {
        // If 'decimals' is provided, strip digits after the specified number of decimal places
        const decimalPattern = `\\.\\d{0,${decimals}}`;
        const regex = new RegExp(decimalPattern);
        return amount.replace(regex, '');
    }
}

Let me know if I should add this function instead of the one used in the proposal which is:

function stripDecimalsFromAmount(amount) {
    return amount.replace(/\.\d*/, '');
}
parasharrajat commented 1 year ago

This component is a little tricky when it comes down to localization. Some languages use , for decimal. So let's make sure we are manipulating the base amount not the represenational value.

I will check your updated proposal in sometime.

esh-g commented 1 year ago

@parasharrajat I have tested for localzation as well. Here is a video of what I think is expected with the current proposal:

https://github.com/Expensify/App/assets/77237602/c1a7be55-0585-484f-9810-1973e6ce79cb

esh-g commented 1 year ago

Bump @parasharrajat

parasharrajat commented 1 year ago

Sorry for the delay. We were on merge freeze so it wasn't in favor of any of us to create a PR that will be held.

parasharrajat commented 1 year ago

I think @esh-g 's proposal looks promising. This component can be tricky to work with as we have to maintain performance as well as functionality.

Please make sure to test your PR against performance(fast keystrokes) and edge cases.

I don't think we support currencies with denominations other than 1 or 0.01

This is something I will have to check. From the regex, it seems we don't. Do you mind confirming this on Slack?

:ribbon: :eyes: :ribbon: C+ reviewed

melvin-bot[bot] commented 1 year ago

Current assignee @grgia is eligible for the choreEngineerContributorManagement assigner, not assigning anyone new.

esh-g commented 1 year ago

Thanks @parasharrajat I have added a comment on slack here as you asked! 😇

melvin-bot[bot] commented 1 year ago

Current assignee @sakluger is eligible for the External assigner, not assigning anyone new.

melvin-bot[bot] commented 1 year ago

Current assignee @parasharrajat is eligible for the External assigner, not assigning anyone new.

grgia commented 1 year ago

@aldo-expensify can you take over as the engineer for this Bug issue? I don't have the full context

melvin-bot[bot] commented 1 year ago

📣 @parasharrajat Please request via NewDot manual requests for the Reviewer role ($500)

melvin-bot[bot] commented 1 year ago

📣 @esh-g 🎉 An offer has been automatically sent to your Upwork account for the Contributor role 🎉 Thanks for contributing to the Expensify app!

Offer link Upwork job Please accept the offer and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review 🧑‍💻 Keep in mind: Code of Conduct | Contributing 📖

melvin-bot[bot] commented 1 year ago

📣 @priyankrawat We're missing your Upwork ID to automatically send you an offer for the Reporter role. Once you apply to the Upwork job, your Upwork ID will be stored and you will be automatically hired for future jobs!

esh-g commented 1 year ago

Here is the PR: https://github.com/Expensify/App/pull/28137 @parasharrajat @aldo-expensify

priyankrawat commented 1 year ago

Though I've already added my upwork details, I've also sent a proposal to the above link as mentioned by the bot.

priyankrawat commented 1 year ago

📣 @priyankrawat We're missing your Upwork ID to automatically send you an offer for the Reporter role. Once you apply to the Upwork job, your Upwork ID will be stored and you will be automatically hired for future jobs!

Hi guys, any updates? Thanks!

melvin-bot[bot] commented 1 year ago

Based on my calculations, the pull request did not get merged within 3 working days of assignment. Please, check out my computations here:

On to the next one 🚀

melvin-bot[bot] commented 1 year ago

Reviewing label has been removed, please complete the "BugZero Checklist".

melvin-bot[bot] commented 1 year ago

The solution for this issue has been :rocket: deployed to production :rocket: in version 1.3.76-6 and is now subject to a 7-day regression period :calendar:. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2023-10-10. :confetti_ball:

After the hold period is over and BZ checklist items are completed, please complete any of the applicable payments for this issue, and check them off once done.

For reference, here are some details about the assignees on this issue:

As a reminder, here are the bonuses/penalties that should be applied for any External issue:

sakluger commented 1 year ago

Hi @priyankrawat, sorry but we don't pay out a reporting bonus for New Features. You can see in the original Slack post where we discussed that this is a new feature rather than a bug. The Github automation incorrectly said you were eligible for the reporting bonus because the GH issue was originally labeled as bug. Sorry for the confusion 🙇.

For the other payments, I'm going to apply the speed bonus because the delay was due to BE, otherwise it would have been merged on time.

Summarizing payouts for this issue:

Contributor: @esh-g $750 (paid via Upwork) Contributor+: @parasharrajat $750 (payable via Manual Request after BZ checklist is completed)

Above payments include efficiency bonus 🎉 Upwork job: https://www.upwork.com/jobs/~018f0f0811f6fe308d

sakluger commented 1 year ago

@parasharrajat could you please complete the BZ checklist and let me know when you've sent the request for payment? I'd love to close this one out. 🙇

parasharrajat commented 1 year ago

New features does not need BZ checklist. Feel free to close it, I can request it later.

sakluger commented 1 year ago

Good call out, my bad! Closing this one out!

parasharrajat commented 11 months ago

Payment requested as per https://github.com/Expensify/App/issues/26551#issuecomment-1759005522

JmillsExpensify commented 11 months ago

$750 payment approved for @parasharrajat based on this comment.