Skip to content

[$250] Report shows empty state when opening track expense submitted from self DM #60107

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

Closed
6 of 8 tasks
jponikarchuk opened this issue Apr 11, 2025 · 26 comments
Closed
6 of 8 tasks
Assignees
Labels
Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 External Added to denote the issue can be worked on by a contributor Help Wanted Apply this label when an issue is open to proposals by contributors

Comments

@jponikarchuk
Copy link

jponikarchuk commented Apr 11, 2025

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.1.27-0
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught on HybridApp, is this reproducible on New Expensify Standalone?: No, reproducible on hybrid only
If this was caught during regression testing, add the test name, ID and link from TestRail: Exp
Email or phone of affected tester (no customers): [email protected]
Issue reported by: Applause Internal Team
Device used: Mac 15.3 / Chrome
App Component: Money Requests

Action Performed:

Precondition:

  • Log in with Expensifail account.
  • Account has self DM.
  • Account has no workspace
  1. Go to staging.new.expensify.com
  2. Go to self DM.
  3. Track a manual expense in self DM.
  4. Click Categorize it.
  5. Click Upgrade > Click Got it, thanks.
  6. Select a category, enter merchant and submit the expense.
  7. Go to Reports.
  8. Go to Expense Reports.
  9. Click on the submitted expense from Step 6.

Expected Result:

The report will show the track expense submitted from self DM.

Actual Result:

The report does not show the track expense submitted from self DM.
It shows the empty state view.

Workaround:

Unknown

Platforms:

  • Android: Standalone
  • Android: HybridApp
  • Android: mWeb Chrome
  • iOS: Standalone
  • iOS: HybridApp
  • iOS: mWeb Safari
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

1.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021910692009075279879
  • Upwork Job ID: 1910692009075279879
  • Last Price Increase: 2025-04-18
Issue OwnerCurrent Issue Owner: @QichenZhu
@jponikarchuk jponikarchuk added Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 labels Apr 11, 2025
Copy link

melvin-bot bot commented Apr 11, 2025

Triggered auto assignment to @slafortune (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.

@samranahm
Copy link
Contributor

samranahm commented Apr 11, 2025

🚨 Edited by proposal-police: This proposal was edited at 2025-04-11 13:21:55 UTC.

Proposal

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

Expense Reports - Report shows empty state when opening track expense submitted from self DM

What is the root cause of that problem?

This happen due to selectTransactionsForReportID selector function

selector: (allTransactions): OnyxTypes.Transaction[] => selectTransactionsForReportID(allTransactions, reportID, reportActions),

Here we check transaction.reportID === reportID, but because the transaction.reportID was from selfDm and now that transection in policyExpenseChat so it does not match with reportID

return transaction.reportID === reportID && !isDeletedParentAction(action);

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

We should get the reportID from parentReportAction.originalMessage?.IOUReportID

const [parentReportAction] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {
canEvict: false,
selector: (parentReportActions) => getParentReportAction(parentReportActions, report?.parentReportActionID),
});

move parentReportAction declaration bellow

const {activeWorkspaceID} = useActiveWorkspace();

and update reportID logic like this

    const originalMessage = getOriginalMessage(parentReportAction) as OnyxTypes.OriginalMessageIOU;
    const reportID = originalMessage?.IOUReportID ?? report?.reportID;

so that selectTransactionsForReportID get the correct reportID

selector: (allTransactions): OnyxTypes.Transaction[] => selectTransactionsForReportID(allTransactions, reportID, reportActions),

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

N/A

What alternative solutions did you explore? (Optional)

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

@slafortune slafortune added the External Added to denote the issue can be worked on by a contributor label Apr 11, 2025
@melvin-bot melvin-bot bot changed the title Expense Reports - Report shows empty state when opening track expense submitted from self DM [$250] Expense Reports - Report shows empty state when opening track expense submitted from self DM Apr 11, 2025
Copy link

melvin-bot bot commented Apr 11, 2025

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

@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Apr 11, 2025
Copy link

melvin-bot bot commented Apr 11, 2025

Triggered auto assignment to Contributor-plus team member for initial proposal review - @QichenZhu (External)

@samranahm
Copy link
Contributor

Proposal updated

@Tony-MK
Copy link
Contributor

Tony-MK commented Apr 12, 2025

Proposal

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

Expense Reports - The Report shows the empty state when opening the track expense submitted from self DM

What is the root cause of that problem?

Since the tracked expense is moved to a policy expense chat, the transaction.reportID will not be equal to report?.reportID.

return transaction.reportID === reportID && !isDeletedParentAction(action);

Hence, the transactions array passed the MoneyRequestReportTransactionList component will be empty, and the SearchMoneyRequestReportEmptyState will be displayed.

<MoneyRequestReportActionsList
report={report}
transactions={transactions}

Image

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

We should add a check if transaction.reportID == report?.parentReportID is true for this case.

So, we need to replace the reportID argument in the selectTransactionsForReportID function with report: OnyxEntry<OnyxTypes.Report> to get the value of parentReportID.

Then, add the transaction.reportID == report?.parentReportID condition to the selectTransactionsForReportID function.

function selectTransactionsForReportID(transactions: OnyxCollection<OnyxTypes.Transaction>, report: OnyxEntry<OnyxTypes.Report>, reportActions: OnyxTypes.ReportAction[]) {
    ... rest of the function's code
    return Object.values(transactions ?? {}).filter((transaction): transaction is OnyxTypes.Transaction => {
        ... rest of the function's code
        return (transaction.reportID === report?.reportID || transaction.reportID == report?.parentReportID) && !isDeletedParentAction(action);
    });
}

Image

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

We should create a test for the selectTransactionsForReportID since there isn't one available.

Then, test it with different types of reports.

What alternative solutions did you explore? (Optional)

N/A

@thelullabyy
Copy link
Contributor

Proposal

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

  • The report view does not display the tracked expense submitted from a self-DM. Instead, it incorrectly shows an empty state.

What is the root cause of that problem?

  • Here, we navigate using the incorrect reportID—specifically, the transaction thread report ID rather than the expense report ID.

  • As a result, the transactions list is empty, because we’re attempting to retrieve transactions using the transaction thread report ID in this location, which doesn't return the correct data.

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

  • Update the navigation logic here to ensure we pass the correct report ID when handling transactions as reports. The corrected logic should be:
if (canUseTableReportView && shouldHandleTransactionAsReport) {
    if (isOpenedAsReport && isTransactionItem) {
        Navigation.navigate(ROUTES.SEARCH_MONEY_REQUEST_REPORT.getRoute({reportID: item.reportID, backTo}));
        return;
    }
    Navigation.navigate(ROUTES.SEARCH_MONEY_REQUEST_REPORT.getRoute({reportID, backTo}));
    return;
}

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

  • N/A

What alternative solutions did you explore? (Optional)

@huult
Copy link
Contributor

huult commented Apr 14, 2025

Proposal

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

Report shows empty state when opening track expense submitted from self DM

What is the root cause of that problem?

This issue is caused by a simple change to the onPress logic introduced in PR #59537.

Previously, when navigating to Expense Reports, if a user pressed a single "transaction" row, they would be redirected to the legacy RHP report using the transactionThreadReportID.

After the update, all report rows now redirect to the new MoneyRequestReportView, which only supports money request reportIDs. As a result, attempts to open transaction thread reports—especially from self DMs—now fail and show an empty state.

let reportID =

Since it uses the reportID to derive the transactionThreadReportID, we can no longer directly use transactionThreadReportID as a prop to open SEARCH_MONEY_REQUEST_REPORT

const transactionThreadReportID = getOneTransactionThreadReportID(reportID, reportActions ?? [], isOffline);

In summary, this issue occurred because we changed to using MoneyRequestReportView to open reports, but did not update the logic to get the correct reportID instead of transactionThreadReportID.

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

To resolve this issue, we should update the logic to get the correct reportID. If we need to handle the transaction as a report, then we should use reportID instead of transactionThreadReportID. Something like this:

let reportID =

update to:

const shouldHandleTransactionAsReport = isReportListItemType(item) || (isTransactionItem && isOpenedAsReport);
let reportID =
                isTransactionItem &&
                (!item.isFromOneTransactionReport || isFromSelfDM) &&
                item.transactionThreadReportID !== CONST.REPORT.UNREPORTED_REPORTID &&
                !(canUseTableReportView && shouldHandleTransactionAsReport)
                    ? item.transactionThreadReportID
                    : item.reportID;
Screen.Recording.2025-04-14.at.15.19.08.mov

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

None

What alternative solutions did you explore? (Optional)

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

@melvin-bot melvin-bot bot added the Overdue label Apr 14, 2025
@QichenZhu
Copy link
Contributor

We've got four proposals so far. I'll need one or two days to go through them.

@melvin-bot melvin-bot bot removed the Overdue label Apr 14, 2025
@QichenZhu
Copy link
Contributor

@samranahm Thanks for the proposal. This looks like a result of the issue, not the root cause.

Here we check transaction.reportID === reportID, but because the transaction.reportID was from selfDm and now that transection in policyExpenseChat so it does not match with reportID

@QichenZhu
Copy link
Contributor

@Tony-MK Thanks for the proposal. Like above, this doesn’t explain why it happens.

Since the tracked expense is moved to a policy expense chat, the transaction.reportID will not be equal to report?.reportID.

@QichenZhu
Copy link
Contributor

@thelullabyy Thanks for the proposal. Like above, we still need to understand the cause of it.

Here, we navigate using the incorrect reportID—specifically, the transaction thread report ID rather than the expense report ID.

@QichenZhu
Copy link
Contributor

QichenZhu commented Apr 16, 2025

@huult Thanks for the proposal. This doesn’t explain why transactionThreadReportID is used instead of reportID.

In summary, this issue occurred because we changed to using MoneyRequestReportView to open reports, but did not update the logic to get the correct reportID instead of transactionThreadReportID.

@thelullabyy
Copy link
Contributor

@QichenZhu The reportID we navigate to is sourced from the following line:

isTransactionItem && (!item.isFromOneTransactionReport || isFromSelfDM) && item.transactionThreadReportID !== CONST.REPORT.UNREPORTED_REPORTID
? item.transactionThreadReportID
: item.reportID;

Specifically, it's item.transactionThreadReportID, which is incorrect in this context.

Here's more detail on why the condition
isTransactionItem && (!item.isFromOneTransactionReport || isFromSelfDM) && item.transactionThreadReportID !== CONST.REPORT.UNREPORTED_REPORTID
evaluates to true: the backend is returning isFromOneTransactionReport as false, when it should actually be true.

@QichenZhu
Copy link
Contributor

I found these comments on another issue.

Ah I think I see the bug, we're not handling "type": "track" when setting isFromOneTransactionReport

@jnowakow I created an issue and have a PR in review

@QichenZhu
Copy link
Contributor

@thelullabyy thanks for the explanation! If so, I believe we should wait for the BE changes and revisit this issue later.

cc @slafortune

Copy link

melvin-bot bot commented Apr 18, 2025

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

@melvin-bot melvin-bot bot added the Overdue label Apr 18, 2025
@QichenZhu
Copy link
Contributor

Waiting on the BE changes: #59908 (comment)

@melvin-bot melvin-bot bot removed the Overdue label Apr 19, 2025
Copy link

melvin-bot bot commented Apr 22, 2025

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

@melvin-bot melvin-bot bot added the Overdue label Apr 22, 2025
@thelullabyy
Copy link
Contributor

@QichenZhu The linked issue is closed but I can still reproduce this issue.

@QichenZhu
Copy link
Contributor

The linked issue was closed in favor of #59960.

@melvin-bot melvin-bot bot removed the Overdue label Apr 22, 2025
@QichenZhu
Copy link
Contributor

@luacmartins, this issue (the backend returns isFromOneTransactionReport as false) might be related to the changes you are working on, but I'm not totally sure, as I don't have access to the issue or the PR. Could you help confirm if they are connected?

@luacmartins
Copy link
Contributor

@QichenZhu the changes in my PR were deployed yesterday. Could you please test again?

@QichenZhu
Copy link
Contributor

QichenZhu commented Apr 24, 2025

Thanks @luacmartins. I just tested again, and the backend still returns isOneTransactionReport false in this issue, so it might not be related?

Image
API Response
{
    "accountID": 19708875,
    "authToken": "949EAE6906E99BAA8FD021476B7563EB1DADBF26E524B8C6C81A1BA6060E44411E755ABE8C1B55BB701D0E8DC9A8B7B93AB0169440EC8AC34D7D36531266EC5F62F5F1FCB5095AA874217139E775C68FE09F27B4211905CA0365F04DDA7252A3555FCC9FFE9AA7FC663702C400AA19485741C7B277AD13E15069D5A8FAE118778F3AC1F107AA69FA4F94B3B67E65A00516C30DA66758D0222F69193E15379C14D99C557586072155491F9FAE9C61BA9D3EE4949062878EC1F8854A136963832266522F49DB8FF840AE9724987FA97C62E27712EAFFDFD6869CE84D69FF24EBE87BEDFC4F9B9675A562E499AE422F36B276613139B751A172AA4EBA39C33120BA6ADCFCA5C48519732A7BAFC5604269CB666A79F5F6604FCEA9F50A4861865760CE91011B944A3A4243F42D30D15D4F7F875D50F14506A5A9930DE75ABFE3962EEA4BDFFF31018382A69A55EFFECDC6CDAF2361E365D48B0AA786412F2FA3FB23",
    "email": "[email protected]",
    "onyxData": [
        {
            "key": "snapshot_243428839",
            "onyxMethod": "set",
            "value": {
                "data": {
                    "personalDetailsList": {
                        "19708875": {
                            "accountID": 19708875,
                            "avatar": "https:\/\/d2k5nsl2zxldvw.cloudfront.net\/images\/avatars\/default-avatar_4.png",
                            "displayName": "Q Z",
                            "firstName": "Q",
                            "lastName": "Z",
                            "login": "[email protected]"
                        }
                    },
                    "policy_B979838E148FEF26": {
                        "achAccount": null,
                        "approvalMode": "OPTIONAL",
                        "approver": "[email protected]",
                        "autoReimbursement": {
                            "limit": 0
                        },
                        "autoReimbursementLimit": 0,
                        "autoReporting": true,
                        "autoReportingFrequency": "instant",
                        "employeeList": {
                            "19708875": "admin"
                        },
                        "id": "B979838E148FEF26",
                        "name": "Q Z's Workspace",
                        "owner": "[email protected]",
                        "preventSelfApproval": false,
                        "reimbursementChoice": "reimburseManual",
                        "role": "admin",
                        "rules": [],
                        "type": "team"
                    },
                    "reportNameValuePairs_2258889478877025": [],
                    "reportNameValuePairs_2785775520463554": [],
                    "reportNameValuePairs_6760326891826770": [],
                    "report_2258889478877025": {
                        "accountID": 19708875,
                        "chatReportID": "6760326891826770",
                        "chatType": "",
                        "created": "2025-04-24 01:18:12",
                        "currency": "NZD",
                        "isOneTransactionReport": false,
                        "isOwnPolicyExpenseChat": false,
                        "isPolicyExpenseChat": false,
                        "isWaitingOnBankAccount": false,
                        "managerID": 19708875,
                        "nonReimbursableTotal": -100,
                        "oldPolicyName": "",
                        "ownerAccountID": 19708875,
                        "parentReportActionID": "1204455664721946806",
                        "parentReportID": "6760326891826770",
                        "policyID": "B979838E148FEF26",
                        "private_isArchived": "",
                        "reportID": "2258889478877025",
                        "reportName": "Expense Report #2258889478877025",
                        "stateNum": 1,
                        "statusNum": 1,
                        "total": -100,
                        "type": "expense",
                        "unheldTotal": -100
                    },
                    "report_2785775520463554": {
                        "accountID": 19708875,
                        "chatReportID": "6760326891826770",
                        "chatType": "",
                        "created": "2025-04-24 01:24:44",
                        "currency": "NZD",
                        "isOneTransactionReport": true,
                        "isOwnPolicyExpenseChat": false,
                        "isPolicyExpenseChat": false,
                        "isWaitingOnBankAccount": false,
                        "managerID": 19708875,
                        "nonReimbursableTotal": 0,
                        "oldPolicyName": "",
                        "ownerAccountID": 19708875,
                        "parentReportActionID": "4642791176506091068",
                        "parentReportID": "6760326891826770",
                        "policyID": "B979838E148FEF26",
                        "private_isArchived": "",
                        "reportID": "2785775520463554",
                        "reportName": "Expense Report #2785775520463554",
                        "stateNum": 1,
                        "statusNum": 1,
                        "total": -200,
                        "type": "expense",
                        "unheldTotal": -200
                    },
                    "transactions_4252390942336278814": {
                        "accountID": 19708875,
                        "amount": -100,
                        "bank": "",
                        "canDelete": true,
                        "canHold": true,
                        "canUnhold": false,
                        "category": "Advertising",
                        "comment": {
                            "comment": ""
                        },
                        "created": "2025-04-24",
                        "currency": "NZD",
                        "hasEReceipt": false,
                        "isFromOneTransactionReport": false,
                        "managerID": 19708875,
                        "merchant": "(none)",
                        "modifiedAmount": -100,
                        "modifiedCreated": "2025-04-24",
                        "modifiedCurrency": "NZD",
                        "modifiedMerchant": "a",
                        "parentTransactionID": "",
                        "policyID": "B979838E148FEF26",
                        "reportID": "2258889478877025",
                        "reportType": "expense",
                        "status": "Posted",
                        "tag": "",
                        "transactionID": "4252390942336278814",
                        "transactionThreadReportID": "1648054961142786",
                        "transactionType": "cash"
                    },
                    "transactions_476764147714659104": {
                        "accountID": 19708875,
                        "amount": -200,
                        "bank": "",
                        "canDelete": true,
                        "canHold": true,
                        "canUnhold": false,
                        "category": "Advertising",
                        "comment": {
                            "attendees": [
                                {
                                    "avatarUrl": "https:\/\/d2k5nsl2zxldvw.cloudfront.net\/images\/avatars\/default-avatar_4.png",
                                    "displayName": "Q Z",
                                    "email": "[email protected]"
                                }
                            ],
                            "comment": ""
                        },
                        "created": "2025-04-24",
                        "currency": "NZD",
                        "hasEReceipt": false,
                        "isFromOneTransactionReport": true,
                        "managerID": 19708875,
                        "merchant": "b",
                        "modifiedAmount": 0,
                        "modifiedCreated": "",
                        "modifiedCurrency": "",
                        "modifiedMerchant": "",
                        "parentTransactionID": "",
                        "policyID": "B979838E148FEF26",
                        "reportID": "2785775520463554",
                        "reportType": "expense",
                        "status": "Posted",
                        "tag": "",
                        "transactionID": "476764147714659104",
                        "transactionThreadReportID": "7939089587358296",
                        "transactionType": "cash"
                    }
                },
                "search": {
                    "columnsToShow": {
                        "shouldShowCategoryColumn": true,
                        "shouldShowTagColumn": false,
                        "shouldShowTaxColumn": false
                    },
                    "hasMoreResults": false,
                    "hasResults": true,
                    "offset": 0,
                    "status": "all",
                    "statusToShow": {
                        "expense": {
                            "all": true,
                            "approved": false,
                            "drafts": false,
                            "outstanding": true,
                            "paid": true
                        }
                    },
                    "type": "expense"
                }
            }
        }
    ],
    "httpCode": 200,
    "jsonCode": 200,
    "authResponseMessage": "200 OK",
    "requestID": "9352051fa98c1c4c-LAX"
}

@QichenZhu
Copy link
Contributor

@slafortune the empty page issue is no longer reproducible after merging this PR.

It now shows the details page for expenses originally created in self DM, while expenses submitted to the workspace display as a table.

Is the inconsistency expected? Should we retest and close this issue?

Image

Image

@mountiny mountiny changed the title [$250] Expense Reports - Report shows empty state when opening track expense submitted from self DM [$250] Report shows empty state when opening track expense submitted from self DM Apr 24, 2025
@mountiny
Copy link
Contributor

Yeah, that is expected for now, and we've got another issue to handle. I believe we can close this now. Thank you 🙇

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. Daily KSv2 External Added to denote the issue can be worked on by a contributor Help Wanted Apply this label when an issue is open to proposals by contributors
Projects
Status: DONE
Development

No branches or pull requests

9 participants