App icon indicating copy to clipboard operation
App copied to clipboard

[$250] Expense - Report can be selected on confirm page when expense cannot be added

Open jponikarchuk opened this issue 3 weeks ago • 13 comments

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.2.78-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: Exp https://github.com/Expensify/App/pull/75792 Email or phone of affected tester (no customers): [email protected] Issue reported by: Applause Internal Team Bug source: Exploratory - Critical User Impact Device used: Mac 26.1 / Chrome App Component: Money Requests

Action Performed:

  1. Go to staging.new.expensify.com
  2. Create a workspace.
  3. Go to workspace chat.
  4. Create an expense in workspace chat.
  5. Click Submit on the expense preview.
  6. Open the report and rename it (to easily identify later).
  7. Go back to workspace chat and create an empty report.
  8. Go to workspace settings > Workflows.
  9. Disable Add approvals and Make or track payments.
  10. Change Submission frequency to Instantly.
  11. Go back to workspace chat.
  12. Click + > Create expense > Manual.
  13. Enter amount > Next.
  14. On confirm page, click Report and select the first report from Step 6.
  15. Click Create expense.

Expected Result:

In Step 14, user should not be able to select the outstanding report from Step 6 because app does not allow user to add expense to it after changing submission frequency from Manually to Instantly.

Actual Result:

In Step 14, user can select the outstanding report from Step 6. In Step 15, after creating the expense, app opens the selected report in Step 14, but the expense is created in a new report.

Workaround:

Unknown

Platforms:

  • [ ] Android: App
  • [ ] Android: mWeb Chrome
  • [ ] iOS: App
  • [ ] iOS: mWeb Safari
  • [ ] iOS: mWeb Chrome
  • [x] Windows: Chrome
  • [x] MacOS: Chrome / Safari

Screenshots/Videos

https://github.com/user-attachments/assets/5509a451-3085-4417-bd15-002fece63298

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~022001509799870274929
  • Upwork Job ID: 2001509799870274929
  • Last Price Increase: 2025-12-25
Issue OwnerCurrent Issue Owner: @dominictb

jponikarchuk avatar Dec 15 '25 13:12 jponikarchuk

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

melvin-bot[bot] avatar Dec 15 '25 13:12 melvin-bot[bot]

Proposal

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

Report can be selected on confirm page when expense cannot be added

What is the root cause of that problem?

Inside getOutstandingReportsForUser, we are not checking if the policy is has isInstantSubmitEnabled, isSubmitAndClose and payments are disabled configuration before we return all outstanding reports https://github.com/Expensify/App/blob/4456dcd7f9c67db4b7c466f7fb99926b39080116/src/libs/ReportUtils.ts#L11417-L11427

Then availableOutstandingReports.length > 1 will be true and we make report field editable https://github.com/Expensify/App/blob/584bccac259cab76ee16ce54531bfce5baf9b074/src/components/MoneyRequestConfirmationListFooter.tsx#L364

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

We should return empty array if isInstantSubmitEnabled, isSubmitAndClose and payments are disabled

const policy = allPolicies[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`];
    const isInstantSubmitEnabledLocal = isInstantSubmitEnabled(policy);
    const isSubmitAndCloseLocal = isSubmitAndClose(policy);
    const arePaymentsDisabled = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO;
    if (isInstantSubmitEnabledLocal && isSubmitAndCloseLocal && arePaymentsDisabled) {
        return [];
    }
    return Object.values(reports).filter(
        (report) =>

What alternative solutions did you explore? (Optional)

Inside MoneyRequestConfirmationListFooter, we can filter availableOutstandingReports to return availableOutstandingReports when the workflow configuration mentioned above is not true and use the filteredOutStandingReports instead of availableOutstandingReports here

const filteredOutStandingReports = useMemo(()=> {
        const isInstantSubmitEnabledLocal = isInstantSubmitEnabled(policy);
            const isSubmitAndCloseLocal = isSubmitAndClose(policy);
            const arePaymentsDisabled = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO;
            if (isInstantSubmitEnabledLocal && isSubmitAndCloseLocal && arePaymentsDisabled) {
                return [];
            }
            return availableOutstandingReports;


    },[availableOutstandingReports, policy])
 const shouldReportBeEditable = (isFromGlobalCreate ? shouldReportBeEditableFromFAB : filteredOutStandingReports.length > 1) && !isMoneyRequestReport(reportID, allReports); 

Note: we can do similar changes in IOURequestEditReportCommon if needed

etCoderDysto avatar Dec 15 '25 13:12 etCoderDysto

Proposal

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

In Step 14, user can select the outstanding report from Step 6. In Step 15, after creating the expense, app opens the selected report in Step 14, but the expense is created in a new report.

What is the root cause of that problem?

It looks like shouldAllowSubmittedReport condition is incorrect; it's always true for instant submit.

https://github.com/Expensify/App/blob/584bccac259cab76ee16ce54531bfce5baf9b074/src/libs/ReportUtils.ts#L11410

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

In Step 14, user should not be able to select the outstanding report from Step 6 because app does not allow user to add expense to it after changing submission frequency from Manually to Instantly.

Based on the expected, we should only allow the submitted report if the submission frequency is not instant. We can also check if the payment is disabled and the policy is submit and close. It can disccus in the PR to match with the backend logic.

const shouldAllowSubmittedReport = allowSubmitted || !isInstantSubmitEnabled(policy) || isProcessingReport(activeReport);

https://github.com/Expensify/App/blob/584bccac259cab76ee16ce54531bfce5baf9b074/src/libs/ReportUtils.ts#L11410

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.

nkdengineer avatar Dec 15 '25 13:12 nkdengineer

Proposal

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

On the expense confirmation page, a user can still select a submitted expense report after switching the workspace to Instant submit + Submit & Close with payments disabled. The app then opens that submitted report, but the expense is placed in a new report instead of the one the user picked.

What is the root cause of that problem?

  • The outstanding-report selector passes allowSubmitted=false, but isReportOutstanding still treats submitted reports as valid whenever the policy has Instant submit enabled, so those reports stay selectable even though they cannot accept more expenses. See the logic in shouldAllowSubmittedReport, which ignores the caller’s allowSubmitted flag when auto-submit is instant. https://github.com/Expensify/App/blob/8cd91dce98b21ad3d8d537ed453e051437fa7dc8/src/libs/ReportUtils.ts#L11393-L11407

  • MoneyRequestConfirmationListFooter relies on getOutstandingReportsForUser(..., allowSubmitted=false) to hide submitted reports, but because the helper above still includes them, the UI exposes destinations the backend will reject. https://github.com/Expensify/App/blob/8cd91dce98b21ad3d8d537ed453e051437fa7dc8/src/components/MoneyRequestConfirmationListFooter.tsx#L323-L347

  • We also do not filter the list by whether a report can currently accept new transactions (canAddTransaction), so once a submitted report slips through, nothing else blocks it from being selected.

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

  • Make allowSubmitted authoritative: drop the Instant-submit override so submitted reports are excluded whenever callers pass allowSubmitted=false, while still letting in-processing reports stay selectable.
  • Only surface reports that can actually accept new expenses when allowSubmitted is false, reusing canAddTransaction to mirror backend rules (instant + submit & close + payments disabled, non-reimbursable-only, etc.).

Code changes:

// src/libs/ReportUtils.ts
function isReportOutstanding(
    iouReport: OnyxInputOrEntry<Report>,
    policyID: string | undefined,
    reportNameValuePairs: OnyxCollection<ReportNameValuePairs> = allReportNameValuePair,
    allowSubmitted = true,
): boolean {
    ...
    const shouldAllowSubmittedReport = allowSubmitted || isProcessingReport(activeReport);
    const meetsSubmittedThreshold =
        shouldAllowSubmittedReport
            ? iouReport.stateNum <= CONST.REPORT.STATE_NUM.SUBMITTED && iouReport.statusNum <= CONST.REPORT.STATUS_NUM.SUBMITTED
            : iouReport.stateNum < CONST.REPORT.STATE_NUM.SUBMITTED && iouReport.statusNum < CONST.REPORT.STATUS_NUM.SUBMITTED;
    const canReceiveTransactions = allowSubmitted || canAddTransaction(iouReport);

    return (
        isExpenseReport(iouReport) &&
        iouReport?.policyID === policyID &&
        meetsSubmittedThreshold &&
        !hasForwardedAction(iouReport.reportID) &&
        !isArchivedReport(reportNameValuePair) &&
        canReceiveTransactions
    );
}

function getOutstandingReportsForUser(
    policyID: string | undefined,
    reportOwnerAccountID: number | undefined,
    reports: OnyxCollection<Report> = allReports,
    reportNameValuePairs: OnyxCollection<ReportNameValuePairs> = allReportNameValuePair,
    allowSubmitted = true,
): Array<OnyxEntry<Report>> {
    if (!reports) {
        return [];
    }

    return Object.values(reports).filter(
        (report) =>
            report?.pendingFields?.preview !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE &&
            isReportOutstanding(report, policyID, reportNameValuePairs, allowSubmitted) &&
            report?.ownerAccountID === reportOwnerAccountID &&
            (allowSubmitted || canAddTransaction(report)),
    );
}

ShridharGoel avatar Dec 15 '25 14:12 ShridharGoel

Proposal

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

Report can be selected on confirm page when expense cannot be added

What is the root cause of that problem?

When instant submit was enabled, shouldAllowSubmittedReport was always true regardless of the allowSubmitted parameter. Thefore: Old submitted reports appeared in the report picker (because isReportOutstanding returned true) But canAddTransaction prevented adding transactions to them (because they weren't awaiting first level approval) The expense creation logic then created a new report instead, causing confusion https://github.com/Expensify/App/blob/827087d0a0292389160d8a359b105c04ad395c0e/src/libs/ReportUtils.ts#L11357

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

    // Determine if we should allow submitted reports to be considered outstanding
    // When allowSubmitted is false, we need to check if transactions can actually be added to processing reports
    let shouldAllowSubmittedReport = allowSubmitted || isProcessingReport(activeReport);

    // For instant submit policies, when allowSubmitted is false, we need to verify that
    // processing reports can actually accept new transactions (i.e., they're awaiting first level approval)
    if (!allowSubmitted && isInstantSubmitEnabled(policy) && isProcessingReport(iouReport)) {
        shouldAllowSubmittedReport = isAwaitingFirstLevelApproval(iouReport);
    } else if (allowSubmitted && isInstantSubmitEnabled(policy)) {
        // When allowSubmitted is true, instant submit policies can show submitted reports
        shouldAllowSubmittedReport = true;
    }

https://github.com/Expensify/App/blob/827087d0a0292389160d8a359b105c04ad395c0e/src/libs/ReportUtils.ts#L11357

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.

lorretheboy avatar Dec 15 '25 14:12 lorretheboy

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

melvin-bot[bot] avatar Dec 18 '25 04:12 melvin-bot[bot]

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

melvin-bot[bot] avatar Dec 18 '25 04:12 melvin-bot[bot]

🚨 Edited by proposal-police: This proposal was edited at 2025-12-21 05:32:12 UTC.

Proposal

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

Outstanding/submitted report can be selected when creating new expense on policy with approval mode is basic / disabled

What is the root cause of that problem?

When generating target/candidate reports in:

https://github.com/Expensify/App/blob/df5234bd3120bd81727c7e764f5af88dc878348d/src/pages/iou/request/step/IOURequestEditReportCommon.tsx#L142 https://github.com/Expensify/App/blob/df5234bd3120bd81727c7e764f5af88dc878348d/src/pages/iou/request/step/IOURequestEditReportCommon.tsx#L153

getOutstandingReports possibly returning outstanding reports based on some conditions/states of policy and it depends on the isReportOutstanding.

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

Since we don't want any outstanding report returned, and only needs the draft/ un-submitted report, we could make new report utils to get the un-submitted reports, instead of using getOutstandingReports

We could add an additional utility function, such as getUnsubmittedReportsForUser:

function getUnsubmittedReportsForUser(
    policyID: string | undefined,
    reportOwnerAccountID: number | undefined,
    reports: OnyxCollection<Report> = allReports,
    reportNameValuePairs: OnyxCollection<ReportNameValuePairs> = allReportNameValuePair): Array<OnyxEntry<Report>> {
    if (!reports) {
        return [];
    }
    return Object.values(reports).filter(
        (report) =>
            report?.pendingFields?.preview !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE &&
            isOpenReport(report) &&
            report?.ownerAccountID === reportOwnerAccountID,
            also check whether report is archived,  etc...
    );
}

Then use the function in:

https://github.com/Expensify/App/blob/df5234bd3120bd81727c7e764f5af88dc878348d/src/pages/iou/request/step/IOURequestEditReportCommon.tsx#L142

https://github.com/Expensify/App/blob/df5234bd3120bd81727c7e764f5af88dc878348d/src/pages/iou/request/step/IOURequestEditReportCommon.tsx#L153

https://github.com/Expensify/App/blob/df5234bd3120bd81727c7e764f5af88dc878348d/src/components/MoneyRequestConfirmationListFooter.tsx#L330

Result:

https://github.com/user-attachments/assets/5292691c-8380-4ae6-b78f-e83c6deb1776

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.

tsa321 avatar Dec 21 '25 02:12 tsa321

cc @NJ-2020 mind checking and post your idea? Since you've worked extensively on Report field.

dominictb avatar Dec 22 '25 09:12 dominictb

Hi, sorry for the delay, I'll post the update tomorrow. Thanks!

NJ-2020 avatar Dec 24 '25 09:12 NJ-2020

Hi 👋, So report field will be editable if the available (un-submitted) report lists is more than > 1, but in this case it will return true, because this condition/check isInstantSubmitEnabled returns true https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/components/MoneyRequestConfirmationListFooter.tsx#L360 https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/components/MoneyRequestConfirmationListFooter.tsx#L330 https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/libs/ReportUtils.ts#L11515-L11520 We already passing allowSubmitted false (to only include un-submitted/draft reports), but it becomes true here due to this check isInstantSubmitEnabled(policy) https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/libs/ReportUtils.ts#L11485

It was being added in this PR(regression issue/original issue) specifically this commit

Thanks.

cc: @dominictb

NJ-2020 avatar Dec 25 '25 09:12 NJ-2020

@NJ-2020 Thank you. Do you have a solution in mind? Mind posting a proposal if you had one?

dominictb avatar Dec 25 '25 10:12 dominictb

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

melvin-bot[bot] avatar Dec 25 '25 16:12 melvin-bot[bot]

Hi 👋 I've been looking into this one for the past few days regarding the expected result, root cause and correct solution, Hopefully I will be able to post an update/proposal tomorrow. Thanks!

NJ-2020 avatar Dec 29 '25 09:12 NJ-2020

@dominictb Thoughts on the existing proposals?

ShridharGoel avatar Dec 29 '25 09:12 ShridharGoel

@strepanier03 @dominictb this issue was created 2 weeks ago. Are we close to approving a proposal? If not, what's blocking us from getting this issue assigned? Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!

melvin-bot[bot] avatar Dec 29 '25 21:12 melvin-bot[bot]

Proposal

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

Expense - Report can be selected on confirm page when expense cannot be added

What is the root cause of that problem?

Report field will be editable if the available (un-submitted) report lists is more than > 1, but in this case it will return true, because this condition/check isInstantSubmitEnabled returns true

https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/components/MoneyRequestConfirmationListFooter.tsx#L360

https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/components/MoneyRequestConfirmationListFooter.tsx#L330

https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/libs/ReportUtils.ts#L11515-L11520

We already passing allowSubmitted false (to only include un-submitted/draft reports), but it becomes true here due to this check isInstantSubmitEnabled(policy)

https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/libs/ReportUtils.ts#L11485

It was added because if we have instant submit policy enabled, every time we create new expense it will be automatically submitted

So we should allow the users to choose different reports and instead of creating new report for each expense which will become redundant, and it will only exclude the report if the iouReport.statusNum is greater than 1 or CONST.REPORT.STATUS_NUM.SUBMITTED i.e like approved, paid

https://github.com/Expensify/App/blob/a1fa8dc80731f431d5d0b8af9bb74faaea290b28/src/libs/ReportUtils.ts#L9863-L9871

https://github.com/Expensify/App/blob/a1fa8dc80731f431d5d0b8af9bb74faaea290b28/src/libs/ReportUtils.ts#L11497-L11498

  1. Disable Add approvals and Make or track payments.
  2. Change Submission frequency to Instantly.

In this issue, we disable approvals and paid options and update the submission frequency to Instantly, so whenever we submit/create expense, the status will become CLOSED or 2

Image

But in this case we didn't update the stateNum/statusNum expense from report (submitted) "A" to CLOSED 2 after updating the workspace workflows settings, so it will still remain SUBMITTED or 1

Image

So when checking whether if the report ("A") is outstanding or not, it will return true based on this condition

https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/libs/ReportUtils.ts#L11485

But when it came to creating the expense, we have a different [check condition](https://github.com/Expensify/App/pull/75792), where if the workspace has instant submit policy enabled isInstantSubmitEnabled(policy) and the approvals options is disabled (optional) isSubmitAndClose(policy) and payments are also disabled reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO and the has already been submitted (in this case it will return true), then we will return false which causes to automatically create new report shouldCreateNewMoneyRequestReport https://github.com/Expensify/App/blob/a1fa8dc80731f431d5d0b8af9bb74faaea290b28/src/libs/ReportUtils.ts#L2775-L2782

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

When updating the workflow settings specifically when disabling the payments option, we should adjust/update the expense stateNum/statusNum accordingly using getExpenseReportStateAndStatus or create new one if neccessary

https://github.com/Expensify/App/blob/a1fa8dc80731f431d5d0b8af9bb74faaea290b28/src/libs/ReportUtils.ts#L6947

  • CONST.REPORT.STATUS_NUM.SUBMITTED or 1: → CONST.REPORT.STATE_NUM.CLOSED or 2

OR when updating submission frequency to Instantly

  • CONST.REPORT.STATUS_NUM.OPEN or 0: → CONST.REPORT.STATE_NUM.SUBMITTED or 1

We should update BE as well, because we can see this bug in the app where after updating changing the workspace workflows settings, the expense stateNum / statusNum still remain as before

https://github.com/user-attachments/assets/527830d3-9ecb-41e2-ad76-436e4fdd8fbc

function getExpenseReportStateAndStatus(policy: OnyxEntry<Policy>, isEmptyOptimisticReport = false, iouReport: OnyxEntry<Report>) {
  const isInstantSubmitEnabledLocal = isInstantSubmitEnabled(policy);
  const isSubmitAndCloseLocal = isSubmitAndClose(policy);
  const arePaymentsDisabled = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO;
  
  if (isInstantSubmitEnabledLocal && arePaymentsDisabled && isSubmitAndCloseLocal) {
    return {
      stateNum: CONST.REPORT.STATE_NUM.APPROVED,
      statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
    };
  }
  
  if (isInstantSubmitEnabledLocal && isOpenReport(iouReport)) {
    return {
      stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
      statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
    };
  }
  
  return {
    stateNum: iouReport?.stateNum,
    statusNum: iouReport?.statusNum,
  }
}

Then when updating the workspace workflows settings specifically we need to update the affected (it should be the user owner of the expense / access permission) transactions (expense | reports) similarly to pushTransactionViolationsOnyxData

https://github.com/Expensify/App/blob/1c1ade94876825a4ecef626275bb46b708c25f5c/src/libs/actions/Policy/Category.ts#L403

What alternative solutions did you explore? (Optional)

Alternatively, we can create new util report function like this one

function isInstantClosedReport(policy: OnyxEntry<Policy>, iouReport: OnyxInputOrEntry<Report>) {
  return isInstantSubmitEnabled(policy) && isSubmitAndClose(policy) && !isOpenExpenseReport(iouReport) && policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO;
}

function isReportOutstanding(
  iouReport: OnyxInputOrEntry<Report>,
  policyID: string | undefined,
  reportNameValuePairs: OnyxCollection<ReportNameValuePairs> = allReportNameValuePair,
  allowSubmitted = true,
): boolean {
  if (!iouReport || isEmptyObject(iouReport)) {
    return false;
  }
  
  const currentRoute = navigationRef.getCurrentRoute();
  const params = currentRoute?.params as MoneyRequestNavigatorParamList[typeof SCREENS.MONEY_REQUEST.STEP_CONFIRMATION] | ReportsSplitNavigatorParamList[typeof SCREENS.REPORT];
  const activeReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${params?.reportID}`];
  const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`];
  const reportNameValuePair = reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${iouReport.reportID}`];
  const shouldAllowSubmittedReport = allowSubmitted || isInstantSubmitEnabled(policy) || isProcessingReport(activeReport);
  
  return (
    isExpenseReport(iouReport) &&
    iouReport?.stateNum !== undefined &&
    iouReport?.statusNum !== undefined &&
    iouReport?.policyID === policyID &&
    (shouldAllowSubmittedReport ? iouReport?.stateNum <= CONST.REPORT.STATE_NUM.SUBMITTED : iouReport?.stateNum < CONST.REPORT.STATE_NUM.SUBMITTED) &&
    (shouldAllowSubmittedReport ? iouReport?.statusNum <= CONST.REPORT.STATE_NUM.SUBMITTED : iouReport?.statusNum < CONST.REPORT.STATE_NUM.SUBMITTED) &&
    !isInstantClosedReport(policy,iouReport) &&
    !hasForwardedAction(iouReport.reportID) &&
    !isArchivedReport(reportNameValuePair)
  );
}

Or when checking the statusNum / stateNum value, we can retrieve the new one from getExpenseReportStateAndStatus function (updated code using the above 👆 solution)

https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/libs/ReportUtils.ts#L11485

Result

https://github.com/user-attachments/assets/cb4dcdf8-6d88-48e3-b0bf-67d89bcb1c5e

NJ-2020 avatar Dec 30 '25 09:12 NJ-2020

⚠️ @NJ-2020 Your proposal is a duplicate of an already existing proposal and has been automatically withdrawn to prevent spam. Please review the existing proposals before submitting a new one.

github-actions[bot] avatar Dec 30 '25 09:12 github-actions[bot]

Posted proposal

cc: @dominictb

NJ-2020 avatar Dec 30 '25 09:12 NJ-2020

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

melvin-bot[bot] avatar Jan 01 '26 16:01 melvin-bot[bot]

@dominictb Still overdue 6 days?! Let's take care of this!

melvin-bot[bot] avatar Jan 01 '26 23:01 melvin-bot[bot]

Issue not reproducible during KI retests. (First week)

mvtglobally avatar Jan 04 '26 20:01 mvtglobally

Reproducible. Still evaluating the proposals. What bother me the most is why we have isInstantSubmitEnabled(policy) check here

https://github.com/Expensify/App/blob/54c7eb47b7e774379769129367bc930dbdfb976f/src/libs/ReportUtils.ts#L11485

dominictb avatar Jan 05 '26 20:01 dominictb

What bother me the most is why we have isInstantSubmitEnabled(policy) check here

It was added here: https://github.com/Expensify/App/pull/62592
Maybe we should ask @daledah.


@dominictb isReportOutstanding is also used when listing reports for moving a transaction to another report. In that case, we allow outstanding reports as destination reports, based on this comment https://github.com/Expensify/App/pull/62592#issuecomment-3106781031

Video:

https://github.com/user-attachments/assets/5b99ed63-1584-45dc-bef8-2496de2e5176


However, when creating a new expense, we don’t allow submitted/outstanding reports. It might be clearer to introduce getUnsubmittedReport instead of using getOutstandingReport and used it in MoneyRequestConfirmationListFooter, since getOutstandingReport originally returns outstanding/submitted reports.

tsa321 avatar Jan 06 '26 02:01 tsa321