Skip to content

[$250] Reports-Expense still shown in Submit section after being submitted offline and going online #76519

Closed

Description

@nlemma

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


Version Number: 9.2.67-0
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from BrowserStack: https://test-management.browserstack.com/projects/2219752/folder/13176923/test-cases/41237528
Email or phone of affected tester (no customers): N/A
Issue reported by: Applause Internal Team
Device used: MacBook Air 15.6.1 Chrome, iPhone 15 iOS 26.1
App Component: Search

Action Performed:

  1. Sign in to ND
  2. Create two expenses in the workspace chat
  3. Navigate to the Reports tab, select Submit in To-do section
  4. Go offline
  5. Open the report, click Submit button
  6. Click back button - expense is still displayed in the Submit section
  7. Click Approve section - it has an empty state
  8. Open Submit section again and go online

Expected Result:

Expense is not shown in Submit section after being submitted offline and going online

Actual Result:

Expense still shown in Submit section after being submitted offline and going online

Workaround:

Unknown

Platforms:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Bug7018170_1764644695901.Expense_stays_in_Submit.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021998059595376860907
  • Upwork Job ID: 1998059595376860907
  • Last Price Increase: 2025-12-15
Issue OwnerCurrent Issue Owner: @nkdengineer

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Dec 2, 2025
  2. melvin-bot commented on Dec 2, 2025

    @melvin-bot

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

  3. ashu75575 commented on Dec 2, 2025

    @ashu75575
    Contributor

    Proposal

    Problem Statement

    When a user submits an expense report while offline and then goes back online, the report remains stuck in the "Submit" section even though it has already been submitted. The report appears in a ghost state where it shows as submitted but still displays in the Submit to-do list.

    Root Cause

    When submitting a report offline, the app applies optimistic updates to immediately show the report as submitted in the UI. These updates change several report fields:

    • statusNum and stateNum to SUBMITTED
    • managerID to the new approver
    • lastMessageText and lastMessageHtml to show the submit action
    • pendingAction flag on the report action

    When the device goes back online, if the API request fails, the app should revert all these changes using failureData. However, the current failureData is incomplete - it only reverts the status fields but not the other changed fields like managerID, lastMessageText, and lastMessageHtml.

    This partial revert creates an inconsistent state where the report shows conflicting information, causing it to remain visible in the Submit section.

    Proposed Solution

    Update the failureData in the submitReport function (src/libs/actions/IOU.ts) to revert all optimistically changed fields when submission fails:

    const failureData: OnyxUpdate[] = [
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`,
            value: {
                statusNum: CONST.REPORT.STATUS_NUM.OPEN,
                stateNum: CONST.REPORT.STATE_NUM.OPEN,
                managerID: expenseReport.managerID,              // ✅ Add this
                lastMessageText: expenseReport.lastMessageText,  // ✅ Add this
                lastMessageHtml: expenseReport.lastMessageHtml,  // ✅ Add this
                nextStep: expenseReport.nextStep ?? null,
                pendingFields: {
                    nextStep: null,
                },
            },
        },
        // ... existing code ...
    ];
    
    failureData.push({
        onyxMethod: Onyx.METHOD.MERGE,
        key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`,
        value: {
            [optimisticSubmittedReportAction.reportActionID]: {
                errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.other'),
                pendingAction: null,  // ✅ Add this
            },
        },
    });

    This ensures when a submission fails after going online, the report returns to its exact pre-submission state.

    Alternative Solutions

    N/A

  4. melvin-bot commented on Dec 2, 2025

    @melvin-bot

    📣 @ashu75575! 📣
    Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork.
    Please follow these steps:

    1. Make sure you've read and understood the contributing guidelines.
    2. Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
    3. Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
    4. Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details.
      Screen Shot 2022-11-16 at 4 42 54 PM
      Format:
    Contributor details
    Your Expensify account email: <REPLACE EMAIL HERE>
    Upwork Profile Link: <REPLACE LINK HERE>
    
  5. ashu75575 commented on Dec 2, 2025

    @ashu75575
    Contributor

    Contributor details
    Your Expensify account email: tejveersingh.75575@gmail.com
    Upwork Profile Link: https://www.upwork.com/freelancers/~01309a71996aa312f4

  6. melvin-bot commented on Dec 2, 2025

    @melvin-bot

    ✅ Contributor details stored successfully. Thank you for contributing to Expensify!

  7. nkdengineer commented on Dec 3, 2025

    @nkdengineer
    Contributor

    Proposal

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

    Expense still shown in Submit section after being submitted offline and going online

    What is the root cause of that problem?

    We only have the logic to filter out the report based on the status. No logic to filter out the report based on the action.

    let shouldShow = true;

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

    Update the shouldShow here to filter out the report based on the action. We have two options to do that:

    1. Based on the action from the query, we can check the report status
    const actionFilterMapping = {
        [CONST.SEARCH.ACTION_FILTERS.SUBMIT]: expenseStatusActionMapping[CONST.SEARCH.STATUS.EXPENSE.DRAFTS],
        [CONST.SEARCH.ACTION_FILTERS.APPROVE]: expenseStatusActionMapping[CONST.SEARCH.STATUS.EXPENSE.OUTSTANDING],
        [CONST.SEARCH.ACTION_FILTERS.PAY]: expenseStatusActionMapping[CONST.SEARCH.STATUS.EXPENSE.APPROVED],
        [CONST.SEARCH.ACTION_FILTERS.EXPORT]: () => true,
    }
    function isValidActionFilter(action: unknown): action is ValueOf<typeof CONST.SEARCH.ACTION_FILTERS> {
        return typeof action === 'string' && action in actionFilterMapping;
    }
    const actionFromQuery = queryJSON?.flatFilters?.find((filter) => filter.key === CONST.SEARCH.SYNTAX_FILTER_KEYS.ACTION)?.filters?.at(0)?.value;
    
    if (actionFromQuery && isValidActionFilter(actionFromQuery)) {
                    shouldShow = shouldShow && actionFilterMapping[actionFromQuery](reportItem);
                }
    

    let shouldShow = true;

    1. Based on the action from the query, we can check if allActions include this action
    if (actionFromQuery === CONST.SEARCH.ACTION_FILTERS.EXPORT || (actionFromQuery && isValidActionFilter(actionFromQuery) && allActions.includes(actionFromQuery))) {
                        reportIDToTransactions[reportKey] = {
                            ...reportItem,
                            action: allActions.at(0) ?? CONST.SEARCH.ACTION_TYPES.VIEW,
                            allActions,
                            keyForList: String(reportItem.reportID),
                            groupedBy: CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT,
                            from: fromDetails,
                            to: toDetails,
                            formattedFrom,
                            formattedTo,
                            formattedStatus,
                            transactions,
                            ...(reportPendingAction ? {pendingAction: reportPendingAction} : {}),
                            shouldShowYear: doesDataContainAPastYearReport,
                            hasVisibleViolations: hasVisibleViolationsForReport,
                        };
                        if (isIOUReport) {
                            reportIDToTransactions[reportKey].reportName = getIOUReportName(data, reportIDToTransactions[reportKey]);
                        }
                    }
    

    We can align with the backend filter logic to improve the filter check above.

    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.

  8. melvin-bot commented on Dec 6, 2025

    @melvin-bot

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

  9. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Dec 8, 2025
  10. changed the title [-]Reports-Expense still shown in Submit section after being submitted offline and going online[/-] [+][$250] Reports-Expense still shown in Submit section after being submitted offline and going online[/+] on Dec 8, 2025
  11. melvin-bot commented on Dec 8, 2025

    @melvin-bot
  12. added
    Help WantedApply this label when an issue is open to proposals by contributors
    on Dec 8, 2025
  13. 48 remaining items

  14. changed the title [-][Due for payment 2026-01-07] [$250] Reports-Expense still shown in Submit section after being submitted offline and going online[/-] [+][$250] Reports-Expense still shown in Submit section after being submitted offline and going online[/+] on Jan 20, 2026
  15. added and removed
    ReviewingHas a PR in review
    Awaiting PaymentAuto-added when associated PR is deployed to production
    on Jan 20, 2026
  16. luacmartins commented on Jan 20, 2026

    @luacmartins
    Contributor

    Correct

  17. garrettmknight commented on Jan 21, 2026

    @garrettmknight
    Contributor

    @nkdengineer you wanna take another swing?

  18. nkdengineer commented on Jan 21, 2026

    @nkdengineer
    Contributor

    It's on my list, will raise the PR soon.

  19. bernhardoj commented on Jan 21, 2026

    @bernhardoj
    Contributor

    Expected Result:
    Expense is not shown in Submit section after being submitted offline and going online

    Hmm, if we don't want to hide the expense from the list when submitting while offline, then what's the new expected behavior?

  20. nkdengineer commented on Jan 25, 2026

    @nkdengineer
    Contributor

    @luacmartins @garrettmknight Can you please check the @bernhardoj 's comment?

  21. garrettmknight commented on Jan 27, 2026

    @garrettmknight
    Contributor

    Hmm, if we don't want to hide the expense from the list when submitting while offline, then what's the new expected behavior?

    I'm not sure I follow, where did someone say we don't want the report not to show in Submit after submitting offline?

  22. bernhardoj commented on Jan 27, 2026

    @bernhardoj
    Contributor

    I understand that we don't want to do the client-side filtering from these comments
    #79714 (comment)
    #79132 (comment)

  23. nkdengineer commented on Jan 27, 2026

    @nkdengineer
    Contributor

    Look like it's fixed now with live data on todo section #79506

  24. garrettmknight commented on Jan 29, 2026

    @garrettmknight
    Contributor

    I think we can close since it's fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributor

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions