Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[$250] Search - Total amount does not auto update after changing the expense currency #49493

Open
2 of 6 tasks
IuliiaHerets opened this issue Sep 19, 2024 · 59 comments
Open
2 of 6 tasks
Assignees
Labels
Bug Something is broken. Auto assigns a BugZero manager. External Added to denote the issue can be worked on by a contributor Needs Reproduction Reproducible steps needed retest-weekly Apply this label if you want this issue tested on a Weekly basis by Applause Reviewing Has a PR in review Weekly KSv2

Comments

@IuliiaHerets
Copy link

IuliiaHerets commented Sep 19, 2024

If you haven’t already, check out our contributing guidelines for onboarding and email [email protected] to request to join our Slack channel!


Version Number: 9.0.38-0
Reproducible in staging?: Y
Reproducible in production?: Y
Email or phone of affected tester (no customers): [email protected]
Issue reported by: Applause Internal Team

Action Performed:

  1. Go to staging.new.expensify.com
  2. Go to DM.
  3. Submit two expenses.
  4. Go to Search.
  5. Go to Outstanding.
  6. Click View next to the submitted expense.
  7. Click Amount.
  8. Change the currency and save it.
  9. Dismiss the RHP.

Expected Result:

The total amount should auto update after changing the expense currency.

Actual Result:

The total amount does not auto update after changing the expense currency.

Workaround:

Unknown

Platforms:

  • Android: Native
  • Android: mWeb Chrome
  • iOS: Native
  • iOS: mWeb Safari
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Bug6608678_1726739142065.bandicam_2024-09-19_17-41-06-770.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021845906959284211554
  • Upwork Job ID: 1845906959284211554
  • Last Price Increase: 2024-10-29
  • Automatic offers:
    • situchan | Reviewer | 104685821
    • huult | Contributor | 104685823
Issue OwnerCurrent Issue Owner: @
@IuliiaHerets IuliiaHerets added Daily KSv2 Bug Something is broken. Auto assigns a BugZero manager. labels Sep 19, 2024
Copy link

melvin-bot bot commented Sep 19, 2024

Triggered auto assignment to @CortneyOfstad (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

@IuliiaHerets
Copy link
Author

We think that this bug might be related to #wave-control

@IuliiaHerets
Copy link
Author

@CortneyOfstad FYI I haven't added the External label as I wasn't 100% sure about this issue. Please take a look and add the label if you agree it's a bug and can be handled by external contributors

@CyberAndrii
Copy link
Contributor

Proposal

Please re-state the problem that we are trying to solve in this issue.

Total amount does not auto update after changing the expense currency

What is the root cause of that problem?

We compute the total here

const formattedTotal = TransactionUtils.getAmount(transactionItem, isExpenseReport);

However, this function (getTransactionItemCommonFormattedProperties) is only called if the route/query changes. When we change the currency the route/query doesn't change, and we read the outdated total value.

const {type, status, sortBy, sortOrder, hash} = queryJSON;
const [currentSearchResults] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`);

What changes do you think we should make in order to solve the problem?

Instead of reading from the formattedTotal property, we can calculate the total based on the updated transaction list.

Replace this line

let amount = CurrencyUtils.convertToDisplayString(transactionItem.formattedTotal, currency);

with the following code

const isExpenseReport = transactionItem.reportType === CONST.REPORT.TYPE.EXPENSE;
const total = TransactionUtils.getAmount(transactionItem, isExpenseReport);
let amount = CurrencyUtils.convertToDisplayString(total, currency);

A similar approach is already implemented for reports.

Finally, we can remove the formattedTotal property from here

const formattedTotal = TransactionUtils.getAmount(transactionItem, isExpenseReport);

@melvin-bot melvin-bot bot added the Overdue label Sep 23, 2024
Copy link

melvin-bot bot commented Sep 23, 2024

@CortneyOfstad Whoops! This issue is 2 days overdue. Let's get this updated quick!

@CortneyOfstad CortneyOfstad added Needs Reproduction Reproducible steps needed retest-weekly Apply this label if you want this issue tested on a Weekly basis by Applause labels Sep 23, 2024
@CortneyOfstad
Copy link
Contributor

So one aspect here is missing — the default currency in the workspace. If the default currency is set to MHR, then the total amount did update.

I am not able to recreate this as the expense converts to the home currency of the workspace.

Going to have this retested.

@melvin-bot melvin-bot bot removed the Overdue label Sep 23, 2024
@MelvinBot
Copy link

This has been labelled "Needs Reproduction". Follow the steps here: https://stackoverflowteams.com/c/expensify/questions/16989

@melvin-bot melvin-bot bot added the Overdue label Sep 26, 2024
Copy link

melvin-bot bot commented Sep 27, 2024

@CortneyOfstad Whoops! This issue is 2 days overdue. Let's get this updated quick!

Copy link

melvin-bot bot commented Oct 1, 2024

@CortneyOfstad 6 days overdue. This is scarier than being forced to listen to Vogon poetry!

@CortneyOfstad
Copy link
Contributor

Still waiting for this to be retested!

@melvin-bot melvin-bot bot removed the Overdue label Oct 1, 2024
Copy link

melvin-bot bot commented Oct 3, 2024

@CortneyOfstad this issue was created 2 weeks ago. Are we close to a solution? Let's make sure we're treating this as a top priority. Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!

@melvin-bot melvin-bot bot added the Overdue label Oct 3, 2024
@CortneyOfstad
Copy link
Contributor

Not overdue as waiting for this to be retested!

@melvin-bot melvin-bot bot added Overdue and removed Overdue labels Oct 4, 2024
@CortneyOfstad
Copy link
Contributor

Again, still waiting for this to be retested!

@melvin-bot melvin-bot bot removed the Overdue label Oct 8, 2024
@CyberAndrii
Copy link
Contributor

This issue is still reproducible. To clarify as the title is a bit misleading - the total amount does update, but not to the correct value. It should be around 1500 but it's showing as 1212. Refreshing the page displays the correct amount.

@melvin-bot melvin-bot bot added the Overdue label Oct 10, 2024
Copy link

melvin-bot bot commented Oct 11, 2024

@CortneyOfstad Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

@CortneyOfstad
Copy link
Contributor

Thanks @CyberAndrii!

@luacmartins luacmartins added the External Added to denote the issue can be worked on by a contributor label Oct 28, 2024
Copy link

melvin-bot bot commented Oct 28, 2024

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

@marcochavezf
Copy link
Contributor

Not overdue, waiting for review or more proposals

@melvin-bot melvin-bot bot removed the Overdue label Oct 28, 2024
@situchan
Copy link
Contributor

@huult I don't think your new solution is correct. I don't get how that change in Onyx fixes the root cause and it will easily cause regressions.

@huult
Copy link
Contributor

huult commented Oct 29, 2024

@situchan After calling UpdateMoneyRequestAmountAndCurrency, we have two report_ data entries: item 4, which contains the value from the request response, and item 10, which contains the value we updated with pendingActions: null for the report_ data.

  • Screenshot 2024-10-29 at 09 27 24

After that, we will loop through the data in react-native-onyx to update report_ in the snapshot_. According to the logic, we loop through each item in the data, and if it meets all the conditions, we update the value in updatedData.

https://github.com/Expensify/react-native-onyx/blob/36ff87b26a2751d0818462cceba8edacf9d3f923/lib/Onyx.ts#L558-L574

In this ticket, the data contains two items (report_), and updatedData will be assigned twice. The first time, report_ will be updated with the new data from the request response and assigned to updatedData. The second time, report_ is assigned an empty object because the value is pendingActions: null, and there is no value to pick under that condition.

  • Screenshot 2024-10-29 at 10 15 14
  • Screenshot 2024-10-29 at 10 16 43

So, the final updatedData will have report_ as an empty object {}, and the report_ in the snapshot will not be updated. As a result, the total amount will not be changed.
https://github.com/Expensify/react-native-onyx/blob/36ff87b26a2751d0818462cceba8edacf9d3f923/lib/Onyx.ts#L581

To resolve this issue, I think we have two possible approaches:

  1. We need to remove the update of pendingActions: null from the list data queue that includes the response of the request. This way, the new value in the response can be updated to the snapshot_ after updating pendingActions: null. I think this approach is possible, but it requires significant changes.

  2. We need to update to check if lodashPick(value, Object.keys(snapshotData[key])) returns an empty object and assign it to a key that has existing data. I think we should skip this and not assign an empty object to a key that has existing data because I believe we won't have a case where new data is updated after being set to an empty object. If the key is assigned an empty object, then the data in the snapshot will not be updated.

We need to update the condition to prevent assigning an empty object to a key that has existing new data. If updatedData[key] contains data and newValue is empty, we should skip assigning this value to updatedData

//.lib/Onyx.ts#L273
-      updatedData = {...updatedData, [key]: lodashPick(value, Object.keys(snapshotData[key]))};
+      const newValue = lodashPick(value, Object.keys(snapshotData[key]))
+      if (updatedData[key] && !utils.isEmptyObject(updatedData[key]) && utils.isEmptyObject(newValue)) {
+          return
+      }

+      updatedData = {...updatedData, [key]: newValue};

Code example change in node_modules to test:

//.App/node_modules/react-native-onyx/dist/Onyx.js#L483
    data.forEach(({ key, value }) => {
            // snapshots are normal keys so we want to skip update if they are written to Onyx
            if (OnyxUtils_1.default.isCollectionMemberKey(snapshotCollectionKey, key, snapshotCollectionKeyLength)) {
                return;
            }
            if (typeof snapshotValue !== 'object' || !('data' in snapshotValue)) {
                return;
            }
            const snapshotData = snapshotValue.data;
            if (!snapshotData || !snapshotData[key]) {
                return;
            }

+           if (updatedData[key] && Object.keys(updatedData[key]).length && !Object.keys((0, pick_1.default)(value, Object.keys(snapshotData[key]))).length) {
+                return;
+            }
            updatedData = Object.assign(Object.assign({}, updatedData), { [key]: (0, pick_1.default)(value, Object.keys(snapshotData[key])) });
        });

@huult
Copy link
Contributor

huult commented Oct 29, 2024

Proposal updated

  • Update the main solution: Change the condition to check if updatedData[key] has an existing value and the new value is an empty object, then skip assigning it.

Copy link

melvin-bot bot commented Oct 29, 2024

📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸

@situchan
Copy link
Contributor

This bug only happens when change currency.
Still interesting why this doesn't happen when change amount in USD. Still happens when change amount in another currency.
So report in snapshot is updated correctly in USD but not in another currency.
@huult I think we should find this root cause.

@huult
Copy link
Contributor

huult commented Oct 31, 2024

@situchan

This bug only happens when change currency.

I saw this bug happen when we call UpdateMoneyRequestAmountAndCurrency with both currency and amount.

Still interesting why this doesn't happen when change amount in USD.

This issue still happens in USD. You can see that the total change reflects the previous iouReport?.total, not the updated iouReport?.total from the request response.

Still happens when change amount in another currency.

This issue happens with all currencies. The total does not change when updating the amount in a currency other than USD. This is because when you change the amount, the response update is delayed compared to USD. If you wait for the response before changing, the behavior will be the same as with USD.

App/src/libs/actions/IOU.ts

Lines 2627 to 2630 in 224b633

updatedMoneyRequestReport = {
...iouReport,
total: iouReport.total - diff,
};

So report in snapshot is updated correctly in USD

This is still updated incorrectly because it is being updated by the previous iouReport?.total. I mention this because, before sending the request, we have a prepareRequest step where we update only optimisticData to Onyx and then to the snapshot, so you can see the total change with the previous iouReport?.total.

if (optimisticData) {
Log.info('[API] Applying optimistic data', false, {command, type});
Onyx.update(optimisticData);
}

@huult I think we should find this root cause.

Therefore, you can see the total amount change, which comes from the prepareRequest step, with this updated to optimisticData in Onyx. However, the report in the snapshot is still not updated with the data from the request, as I mentioned in the proposal. To update the report in the snapshot correctly, we need to apply the update I suggested.

The video I mentioned describes that
Screen.Recording.2024-10-31.at.22.39.19.mp4

@situchan
Copy link
Contributor

@huult thanks. Can we also think of an alternative solution? So instead of fully overwriting, only update picked field values?

const oldValue = updatedData[key] || {}
const newValue = lodashPick(value, Object.keys(snapshotData[key]))

updatedData = {...updatedData, [key]: Object.assign(oldValue, newValue)};

@situchan
Copy link
Contributor

We can assign @huult for providing the correct root cause and proper solution. The root cause is in Onyx.
Proposal: #49493 (comment)
I also suggested alternative.
🎀👀🎀 C+ reviewed

Copy link

melvin-bot bot commented Oct 31, 2024

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

@marcochavezf
Copy link
Contributor

Thanks for the review @situchan, assigning @huult 🚀

@melvin-bot melvin-bot bot removed the Help Wanted Apply this label when an issue is open to proposals by contributors label Oct 31, 2024
Copy link

melvin-bot bot commented Oct 31, 2024

📣 @situchan 🎉 An offer has been automatically sent to your Upwork account for the Reviewer role 🎉 Thanks for contributing to the Expensify app!

Offer link
Upwork job

Copy link

melvin-bot bot commented Oct 31, 2024

📣 @huult 🎉 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 📖

@huult
Copy link
Contributor

huult commented Nov 1, 2024

Thank you all. I will create the PR within 24 hours

@huult
Copy link
Contributor

huult commented Nov 1, 2024

@situchan @marcochavezf

I created a pull request. Can you check it? I saw my pull request was auto-assigned to @rlinoz. Thanks!

@melvin-bot melvin-bot bot added the Overdue label Nov 4, 2024
@marcochavezf
Copy link
Contributor

PR merged, not overdue

@melvin-bot melvin-bot bot removed the Overdue label Nov 4, 2024
@situchan
Copy link
Contributor

situchan commented Nov 4, 2024

Should we hold this for #51942 or bump version to v2.0.79 in that PR?

@huult huult mentioned this issue Nov 5, 2024
49 tasks
@melvin-bot melvin-bot bot added Reviewing Has a PR in review Weekly KSv2 and removed Daily KSv2 labels Nov 5, 2024
@huult
Copy link
Contributor

huult commented Nov 5, 2024

I've created a pull request to bump the Onyx version to 2.0.79.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something is broken. Auto assigns a BugZero manager. External Added to denote the issue can be worked on by a contributor Needs Reproduction Reproducible steps needed retest-weekly Apply this label if you want this issue tested on a Weekly basis by Applause Reviewing Has a PR in review Weekly KSv2
Projects
Status: Polish
Development

No branches or pull requests

8 participants