Skip to content

[Due for payment 2025-05-30] [$250] Invoice - Pay button appears in invoice preview for sender after receiver pays as business #61315

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

Open
8 tasks done
jponikarchuk opened this issue May 2, 2025 · 14 comments
Assignees
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. External Added to denote the issue can be worked on by a contributor Weekly KSv2

Comments

@jponikarchuk
Copy link

jponikarchuk commented May 2, 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.39-2
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from TestRail: https://expensify.testrail.io/index.php?/tests/view/6032955
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.
  • Invoice is enabled.
  1. Go to staging.new.expensify.com
  2. [User A] Open FAB > Send invoice.
  3. [User A] Send two invoices to User B.
  4. [User B] Open invoice room with User A.
  5. [User B] On the first invoice, click Pay button > Pay as a business > Pay elsewhere.
  6. [User B] Note that pay button on the second invoice disappears for User B after paying the first invoice as business.
  7. [User A] Go to invoice room with User B.
  8. [User A] Note that pay button on the second invoice appears for User A who is also the invoice sender.

Expected Result:

After paying invoice as business,

  • In Step 6, the pay button on the second invoice will not disappear for User B.
  • In Step 8, the pay button on the second invoice will not appear for User A who is the invoice sender.

Actual Result:

After paying invoice as business,

  • In Step 6, the pay button on the second invoice disappears for User B.
  • In Step 8, the pay button on the second invoice appears for User A who is the invoice sender.

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

1.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021919538908936604963
  • Upwork Job ID: 1919538908936604963
  • Last Price Increase: 2025-05-05
  • Automatic offers:
    • nkdengineer | Contributor | 107220768
Issue OwnerCurrent Issue Owner: @mallenexpensify
@jponikarchuk jponikarchuk added Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 labels May 2, 2025
Copy link

melvin-bot bot commented May 2, 2025

Triggered auto assignment to @mallenexpensify (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 melvin-bot bot added the Overdue label May 5, 2025
Copy link

melvin-bot bot commented May 5, 2025

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

@mallenexpensify mallenexpensify added the External Added to denote the issue can be worked on by a contributor label May 5, 2025
@melvin-bot melvin-bot bot changed the title Invoice - Pay button appears in invoice preview for sender after receiver pays as business [$250] Invoice - Pay button appears in invoice preview for sender after receiver pays as business May 5, 2025
Copy link

melvin-bot bot commented May 5, 2025

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

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

melvin-bot bot commented May 5, 2025

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

@melvin-bot melvin-bot bot removed the Overdue label May 5, 2025
@mallenexpensify
Copy link
Contributor

Seems like it could be worked on by a contributor.

@nkdengineer
Copy link
Contributor

Proposal

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

After paying invoice as business,

What is the root cause of that problem?

If the invoice receiver has type policy, we return true if the current user is the admin of the policy but this condition is wrong, we should check the role of the receiver policy instead.

From userA's side, policy is the userA's policy that is used to create the invoice.

const parentReport = getParentReport(report);
if (parentReport?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL) {
return parentReport?.invoiceReceiver?.accountID === getCurrentUserAccountID();
}
return policy?.role === CONST.POLICY.ROLE.ADMIN;

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

We should pass a new param invoiceReceiverPolicy to canPay function.

return getReportPreviewAction(violations, iouReport, policy, transactions, reportNameValuePairs);

Then here we should return true if the user is the admin of the receiver policy

return invoiceReceiverPolicy?.role === CONST.POLICY.ROLE.ADMIN; 

const parentReport = getParentReport(report);
if (parentReport?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL) {
return parentReport?.invoiceReceiver?.accountID === getCurrentUserAccountID();
}
return policy?.role === CONST.POLICY.ROLE.ADMIN;

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

Update ReportPreviewActionUtilsTest to correct this scenario

What alternative solutions did you explore? (Optional)

We can get the invoiceReceiverPolicy via getPolicy function

const invoiceReceiverPolicy = getPolicy(parentReport?.invoiceReceiver?.policyID);
return invoiceReceiverPolicy?.role === CONST.POLICY.ROLE.ADMIN;

const parentReport = getParentReport(report);
if (parentReport?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL) {
return parentReport?.invoiceReceiver?.accountID === getCurrentUserAccountID();
}
return policy?.role === CONST.POLICY.ROLE.ADMIN;

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.

@Nick4dawin
Copy link

Proposal

Please re-state the problem that we are trying to solve in this issue.
After paying invoice as business, there are two issues:

  1. The pay button on other invoices disappears for User B (invoice receiver) when it shouldn't.
  2. The pay button appears for User A (invoice sender) when it shouldn't.

What is the root cause of that problem?
When determining whether to show the pay button for an invoice, the code is checking if the current user is an admin of the policy. However, it's using the wrong policy for this check. It should check if the user is an admin of the invoice receiver's policy, not the policy that's currently being passed to the function.

When paying as business, the invoice receiver (User B) should see pay buttons for all invoices where they're an admin of the receiver policy. The invoice sender (User A) should never see pay buttons for invoices they've sent.

App/src/libs/ReportPreviewActionUtils.ts has a function canPay that checks:

const parentReport = getParentReport(report);
if (parentReport?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL) {
    return parentReport?.invoiceReceiver?.accountID === getCurrentUserAccountID();
}

return policy?.role === CONST.POLICY.ROLE.ADMIN;

The issue is that when we pass a policy to this function, the function doesn't check whether it's the invoice receiver's policy. The MoneyRequestReportPreviewContent component has access to the receiver policy but it's not properly using it.

What changes do you think we should make in order to solve the problem?
We need to modify two files:

  1. In MoneyRequestReportPreviewContent.tsx, we need to ensure the invoiceReceiverPolicy is passed to getReportPreviewAction instead of the report's policy when available:
return getReportPreviewAction(violations, iouReport, invoiceReceiverPolicy ?? policy, transactions, reportNameValuePairs);
  1. In ReportPreviewActionUtils.ts, we should update the comments to clarify that the policy parameter should be the invoice receiver's policy for invoice reports, as this will determine whether the pay button should be shown:
// For business receivers, we need to check if the current user is the admin of the receiver policy
// If policy parameter is the invoiceReceiverPolicy (passed from MoneyRequestReportPreviewContent),
// then we check if the current user is an admin of that policy
return policy?.role === CONST.POLICY.ROLE.ADMIN;

These changes ensure that:

  • The pay button appears correctly for the invoice receiver (User B) for all invoices.
  • The pay button doesn't appear for the invoice sender (User A) after the receiver has paid as business.

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?
We should add a test that verifies the pay button visibility based on the invoice receiver policy:

  1. Create a test that simulates an invoice with a sender policy and receiver policy
  2. Check that when the receiver policy is passed and the user is an admin, the pay button is shown
  3. Check that when the sender policy is passed and the user is not an admin of the receiver policy, the pay button is not shown

What alternative solutions did you explore? (Optional)
I considered modifying the canPay function to fetch the receiver policy directly:

const invoiceReceiverPolicy = getPolicy(parentReport?.invoiceReceiver?.policyID);
return invoiceReceiverPolicy?.role === CONST.POLICY.ROLE.ADMIN;

However, this would introduce an additional dependency and potentially duplicate policy fetching logic. The cleaner approach is to ensure the correct policy is passed from the component that already has access to both policies.

@fedirjh
Copy link
Contributor

fedirjh commented May 7, 2025

@nkdengineer 's proposal looks good to me .

🎀 👀 🎀 C+ reviewed

Copy link

melvin-bot bot commented May 7, 2025

Triggered auto assignment to @Julesssss, see https://stackoverflow.com/c/expensify/questions/7972 for more details.

@Julesssss
Copy link
Contributor

I agree with nkdengineer's solution which solves the root cause 👍

@melvin-bot melvin-bot bot removed the Help Wanted Apply this label when an issue is open to proposals by contributors label May 7, 2025
Copy link

melvin-bot bot commented May 7, 2025

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

@melvin-bot melvin-bot bot added Weekly KSv2 Awaiting Payment Auto-added when associated PR is deployed to production labels May 23, 2025
@melvin-bot melvin-bot bot changed the title [$250] Invoice - Pay button appears in invoice preview for sender after receiver pays as business [Due for payment 2025-05-30] [$250] Invoice - Pay button appears in invoice preview for sender after receiver pays as business May 23, 2025
@melvin-bot melvin-bot bot removed the Reviewing Has a PR in review label May 23, 2025
Copy link

melvin-bot bot commented May 23, 2025

Reviewing label has been removed, please complete the "BugZero Checklist".

Copy link

melvin-bot bot commented May 23, 2025

The solution for this issue has been 🚀 deployed to production 🚀 in version 9.1.50-0 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2025-05-30. 🎊

For reference, here are some details about the assignees on this issue:

Copy link

melvin-bot bot commented May 23, 2025

@fedirjh @mallenexpensify @fedirjh The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. External Added to denote the issue can be worked on by a contributor Weekly KSv2
Projects
Status: No status
Development

No branches or pull requests

6 participants