App icon indicating copy to clipboard operation
App copied to clipboard

[$250] Invoice-Wrong recipient when selecting an email address after selecting an Invoice room

Open mitarachim opened this issue 3 months ago β€’ 37 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: v9.2.21-3 Reproducible in staging?: Yes Reproducible in production?: Yes If this was caught during regression testing, add the test name, ID and link from TestRail: Found when working on https://github.com/Expensify/App/pull/71648 Email or phone of affected tester (no customers): [email protected] Issue reported by: Applause Internal Team Device used: Windows 11/ Chrome, Samsung S23FE/ Android 15, iPhone 13 Mini/ iOS 18.5 App Component: Other

Action Performed:

Preconditions: Have a workspace with the Invoices feature enabled. Have at least one Invoice room.

  1. Go to staging.new.expensify.com
  2. Open FAB > Send invoice
  3. Enter amount > Next
  4. Select an Invoice room from Recents
  5. In the "To" field, click on the right caret icon
  6. Enter an email address that is not included in any Invoice room with the current user 7 Send the invoice

Expected Result:

The app creates the invoice thread in a new Invoice room with the email address entered in step 6.

Actual Result:

The app creates the invoice thread in the Invoice room selected in step 4.

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

https://github.com/user-attachments/assets/a778754b-769f-44d2-80d3-04a42a96b49d

View all open jobs on GitHub

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

mitarachim avatar Oct 02 '25 02:10 mitarachim

Triggered auto assignment to @dylanexpensify (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 Oct 02 '25 02:10 melvin-bot[bot]

Proposal

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

Invoice-Wrong recipient when selecting an email address after selecting an Invoice room

What is the root cause of that problem?

Invoice room selection logic prioritizes a pre-selected report over checking if the current transaction participants have changed

https://github.com/Expensify/App/blob/f3984ef514f3293ab0c843ead97223a6f1a3678c/src/pages/iou/request/step/IOURequestStepConfirmation.tsx#L869-L884

  • report is the invoice room selected from recents
  • existingInvoiceReport is determined by the useParticipantsInvoiceReport hook based on current transaction participants

The issue occurs because when a user selects an invoice room and then changes the email address, the transaction participants are updated but it still uses the originally selected report instead of checking if it matches the new recipient

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

We can check if the selected report matches the current transaction participants before using it

                const doesReportMatchCurrentReceiver = report?.invoiceReceiver && 'accountID' in report.invoiceReceiver && report.invoiceReceiver.accountID === receiverAccountID;

                // Or check for policyID as well

                const doesReportMatchCurrentReceiver =
                    report?.invoiceReceiver &&
                    (('accountID' in report.invoiceReceiver && report.invoiceReceiver.accountID === receiverAccountID) ||
                        ('policyID' in report.invoiceReceiver &&
                            receiverParticipant &&
                            'policyID' in receiverParticipant &&
                            report.invoiceReceiver.policyID === receiverParticipant.policyID)) &&
                    report.invoiceReceiver.type === receiverType;

Then use it here

                const invoiceChatReport = doesReportMatchCurrentReceiver && report?.reportID ? report : existingInvoiceReport;

https://github.com/Expensify/App/blob/f3984ef514f3293ab0c843ead97223a6f1a3678c/src/pages/iou/request/step/IOURequestStepConfirmation.tsx#L870

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)

None

nyomanjyotisa avatar Oct 02 '25 03:10 nyomanjyotisa

Proposal

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

Wrong recipient when selecting an email address after selecting an Invoice room

What is the root cause of that problem?

The existingInvoiceReport is calculated by useParticipantsInvoiceReport based on current transaction participants (recipient B)

https://github.com/Expensify/App/blob/7a216023f2371a3c26c8a31112966a0ca8a55c0e/src/pages/iou/request/step/IOURequestStepConfirmation.tsx#L177

But the original report from route parameter (for recipient A)

When no existing invoice report exists for the new recipient B, the logic fell back to the original report for recipient A

So instead of creating a new report, the code fell back to the stale original report --> This caused the invoice to be created in the wrong room

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

For useParticipantsInvoiceReport, we need the correct receiverID based on receiver type to calculate existingInvoiceReport in useParticipantsInvoiceReport

    let receiverID: string | number | undefined = receiverAccountID;
    if (receiverType === CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS && receiverParticipant && 'policyID' in receiverParticipant) {
        receiverID = receiverParticipant.policyID;
    }

    const existingInvoiceReport = useParticipantsInvoiceReport(receiverID, receiverType, senderWorkspaceID);

https://github.com/Expensify/App/blob/7a216023f2371a3c26c8a31112966a0ca8a55c0e/src/pages/iou/request/step/IOURequestStepConfirmation.tsx#L177

Update here to fallback to existingInvoiceReport if exists

    const invoiceChatReport = existingInvoiceReport;

https://github.com/Expensify/App/blob/7a216023f2371a3c26c8a31112966a0ca8a55c0e/src/pages/iou/request/step/IOURequestStepConfirmation.tsx#L865

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 Oct 02 '25 03:10 lorretheboy

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

melvin-bot[bot] avatar Oct 02 '25 08:10 melvin-bot[bot]

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

melvin-bot[bot] avatar Oct 02 '25 08:10 melvin-bot[bot]

🚫 Duplicated proposal withdrawn by πŸ€– ProposalPolice.

huult avatar Oct 03 '25 05:10 huult

⚠️ @huult 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 Oct 03 '25 05:10 github-actions[bot]

Proposal

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

Invoice drafts created from the FAB could not be addressed to a new recipient if the user previously picked an existing invoice room. Entering a new email in the confirmation step still re-used the earlier room, so the invoice was sent to the wrong conversation.

What is the root cause of that problem?

The confirmation step and the invoicing action both prioritized an existing invoice room whenever a report was available on the route. In getSendInvoiceInformation, the receiver was picked only when a participant had a persisted accountID, otherwise the logic fell back to the existing room

https://github.com/Expensify/App/blob/b76a7405c94919fc6269506d9489decaffa572e5/src/libs/actions/IOU.ts#L3204-L3218

Similarly, the confirmation page derived the receiver directly from report?.invoiceReceiver when no accountID was present, ignoring a newly entered login

https://github.com/Expensify/App/blob/b76a7405c94919fc6269506d9489decaffa572e5/src/pages/iou/request/step/IOURequestStepConfirmation.tsx#L174-L179

As a result the old room stayed selected even after typing a different email.

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

Update both the confirmation screen and the invoicing action to prefer the participant supplied by the current transaction (including those identified only by login) and only reuse the existing invoice room when that participant truly represents the same room.

// src/pages/iou/request/step/IOURequestStepConfirmation.tsx
const receiverParticipantFromTransaction = transaction?.participants?.find(
    (participant) => !participant?.isSender && (!!participant?.accountID || !!participant?.login),
);
const receiverParticipant: Participant | InvoiceReceiver | undefined = receiverParticipantFromTransaction ?? report?.invoiceReceiver;
// src/libs/actions/IOU.ts
const receiverParticipantFromTransaction = participants?.find(
    (participant) => !participant?.isSender && (!!participant?.accountID || !!participant?.login),
);
const shouldUseExistingInvoiceChat = !receiverParticipantFromTransaction || !!receiverParticipantFromTransaction.reportID;
const invoiceChatReportToUse = shouldUseExistingInvoiceChat ? invoiceChatReport : undefined;
const receiverParticipantFromReport = invoiceChatReportToUse?.invoiceReceiver;
const receiverParticipant: Participant | InvoiceReceiver | undefined = receiverParticipantFromTransaction ?? receiverParticipantFromReport;
...
const parameters: SendInvoiceParams = {
    ...,
    ...(receiverInvoiceRoomID ? {receiverInvoiceRoomID} : {receiverEmail: receiver.login ?? ''}),
};

These updates ensure a new invoice room is generated when the user types an email that does not yet belong to an existing room, while still preserving the previous behavior when the selected participant already references a room.

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

  • Unit test for the confirmation step selector ensuring it returns the new participant when present and only falls back to report?.invoiceReceiver when transaction data lacks a receiver.

ShridharGoel avatar Oct 05 '25 14:10 ShridharGoel

Hi everyone, I think we should fix this issue from the RCA that reportID from the route isn't updated, when the user selects another option --> In IOURequestStepConfirmation, reportReal will be wrong --> report will be wrong --> invoiceChatReport will be wrong

You guys can see how we handle this problem in another place to suggest ideas

DylanDylann avatar Oct 07 '25 06:10 DylanDylann

πŸ“£ 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 Oct 09 '25 16:10 melvin-bot[bot]

Looking for proposals

DylanDylann avatar Oct 15 '25 02:10 DylanDylann

@dylanexpensify @DylanDylann 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 Oct 16 '25 09:10 melvin-bot[bot]

πŸ“£ 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 Oct 16 '25 16:10 melvin-bot[bot]

@DylanDylann Eep! 4 days overdue now. Issues have feelings too...

melvin-bot[bot] avatar Oct 20 '25 11:10 melvin-bot[bot]

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

melvin-bot[bot] avatar Oct 22 '25 17:10 melvin-bot[bot]

@dylanexpensify Should we consider doubling the price?

DylanDylann avatar Oct 23 '25 04:10 DylanDylann

πŸ“£ 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 Oct 23 '25 16:10 melvin-bot[bot]

@DylanDylann Eep! 4 days overdue now. Issues have feelings too...

melvin-bot[bot] avatar Oct 28 '25 23:10 melvin-bot[bot]

πŸ“£ 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 Oct 30 '25 16:10 melvin-bot[bot]

@dylanexpensify @DylanDylann this issue is now 4 weeks old, please consider:

  • Finding a contributor to fix the bug
  • Closing the issue if BZ has been unable to add the issue to a VIP or Wave project
  • If you have any questions, don't hesitate to start a discussion in #expensify-open-source

Thanks!

melvin-bot[bot] avatar Oct 30 '25 22:10 melvin-bot[bot]

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

melvin-bot[bot] avatar Oct 30 '25 23:10 melvin-bot[bot]

@DylanDylann 10 days overdue. Is anyone even seeing these? Hello?

melvin-bot[bot] avatar Nov 03 '25 23:11 melvin-bot[bot]

@DylanDylann 12 days overdue. Walking. Toward. The. Light...

melvin-bot[bot] avatar Nov 05 '25 23:11 melvin-bot[bot]

πŸ“£ 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 Nov 06 '25 16:11 melvin-bot[bot]

Looking for proposals

DylanDylann avatar Nov 12 '25 10:11 DylanDylann

πŸ“£ 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 Nov 13 '25 16:11 melvin-bot[bot]

πŸ“£ 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 Nov 20 '25 16:11 melvin-bot[bot]

πŸ“£ 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 Nov 27 '25 16:11 melvin-bot[bot]

This issue has not been updated in over 14 days. @dylanexpensify, @DylanDylann eroding to Weekly issue.

melvin-bot[bot] avatar Nov 28 '25 23:11 melvin-bot[bot]

Issue not reproducible during KI retests. (First week)

mvtglobally avatar Nov 30 '25 07:11 mvtglobally