Skip to content
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

[$250] Expense - On changing 1st approver, 2nd approver is not greyed out&error for not added approvers #54524

Open
2 of 8 tasks
IuliiaHerets opened this issue Dec 24, 2024 · 5 comments
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

@IuliiaHerets
Copy link

IuliiaHerets commented Dec 24, 2024

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.0.78-1
Reproducible in staging?: Yes
Reproducible in production?: Yes
Issue reported by: Applause Internal Team
Device used: Redmi note 10s Android 13
App Component: Money Requests

Action Performed:

Pre-condition: 1. Have a workspace with few members
2. Enable workflows and add approval flow

  1. Go to https://staging.new.expensify.com/home
  2. Go to workspace settings- workflows
  3. Go offline
  4. Tap add approvals
  5. Tap additional approver
  6. Select a user & save it [user1]
  7. Save edit approval flow
  8. Tap add approvals
  9. Note second approver is greyed out [user1]
  10. Tap first approver and select different member and save it [user2]
  11. Tap add approvals and note first approver is greyed out and second approver not greyed out now
  12. Tap additional approver and select a new user and save it [user3]
  13. Tap add approvals and note first+third approver greyed out & second approver is not greyed out
  14. Remove the third approver & second approver ( note now we have only additional approver row)
  15. Change the first approver ( to second approver who was removed [user1] ) and save
  16. Now note after first approver is changed, edit approval flow automatically shows second approver with user selected
  17. Now tap additional approver ( set as first approver who was selected in step 10- [ user2] )& save it
  18. Note fourth and fifth approver automatically added and error is displayed.

Expected Result:

After changing 1st approver, 2nd approver must be same as it was before changing 1st approver & not added approvers must not be shown with error message.

Actual Result:

After changing 1st approver, 2nd approver is not greyed out & not added approvers are shown with error message.

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

Bug6701635_1735015172299.Screenrecorder-2024-12-24-09-29-51-391_compress_1.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021871540038795816648
  • Upwork Job ID: 1871540038795816648
  • Last Price Increase: 2024-12-24
Issue OwnerCurrent Issue Owner: @getusha
@IuliiaHerets IuliiaHerets added Daily KSv2 Bug Something is broken. Auto assigns a BugZero manager. labels Dec 24, 2024
Copy link

melvin-bot bot commented Dec 24, 2024

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

@bfitzexpensify bfitzexpensify added the External Added to denote the issue can be worked on by a contributor label Dec 24, 2024
@melvin-bot melvin-bot bot changed the title Expense - On changing 1st approver, 2nd approver is not greyed out&error for not added approvers [$250] Expense - On changing 1st approver, 2nd approver is not greyed out&error for not added approvers Dec 24, 2024
Copy link

melvin-bot bot commented Dec 24, 2024

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

@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Dec 24, 2024
Copy link

melvin-bot bot commented Dec 24, 2024

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

@cretadn22
Copy link
Contributor

Proposal

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

On changing 1st approver, 2nd approver is not greyed out&error for not added approvers

What is the root cause of that problem?

We have identified two separate bugs:

Bug 1 (Steps 1 to 13): The app incorrectly greys out the approver

The second approver is greyed out because the first approver has pendingFields.forwardsTo. However, when the first approver is updated, the pendingFields.forwardsTo of the first approver is not updated to reflect the new approver. This results in the second approver not being greyed out.

Bug 2 (Steps 14 to 18): The app incorrectly adds approvers automatically

When removing the second and third approvers in step 14, the changes are not saved. Consequently, in policy.employeeList, the first approver still forwards to the second approver, and the second approver forwards to the third approver.
This explains why, when changing the first approver to the second approver, the third approver is added automatically. This happens because the app retrieves information from employeeList, causing it to add more approvers automatically during the change.

if (policy.employeeList[approver.email]?.forwardsTo) {

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

Solution for bug 1:

Onyx.merge(ONYXKEYS.APPROVAL_WORKFLOW, {approvers: updatedApprovers, errors});

We need to update the APPROVAL_WORKFLOW in onyx to migrate pendingFields.forwardsTo from the old approver to the new approver.

    const oldApprover = currentApprovalWorkflow.approvers.find((approver, index) => index === approverIndex);
    const oldApproverInMember = currentApprovalWorkflow.members.find((member) => member.email === oldApprover?.email);

    const updatedMembers = currentApprovalWorkflow.members.map((member, index) => {
        if (member.email === approver?.email) {
            return {
                ...member,
                pendingFields: {
                    forwardsTo: oldApproverInMember?.pendingFields?.forwardsTo
                }
            }
        }
        if (member.email === oldApprover?.email) {
            return {
                ...member,
                pendingFields: {
                    forwardsTo: null,
                }
            }
        }
        return {...member}
    })

    Onyx.merge(ONYXKEYS.APPROVAL_WORKFLOW, {approvers: updatedApprovers, members: updatedMembers, errors});

Additionally, we need to migrate the pendingFields.forwardTo from the approvalWorkflow to the employee list

forwardsTo: pendingAction,

    approvalWorkflow.members.forEach(({email, pendingFields}) => {
            ......
            pendingFields: {
                submitsTo: pendingAction,
                forwardsTo: pendingFields?.forwardsTo
            },
Solution for bug 2:

When removing an approver from the Approver Page, we need to introduce an additional field, perhaps named pendingRemove, in the clearApprovalWorkflowApprover function. This field will mark the approver as already removed from the current workflow. Then, we need to ensure that an approver is added automatically only if pendingRemove is false.

if (policy.employeeList[approver.email]?.forwardsTo) {

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

Bug 1:

We might need to add a new test for this scenario in https://github.com/Expensify/App/blob/main/tests/unit/WorkflowUtilsTest.ts

This test will validate that pendingFields is correctly handled in the edit approval workflow. The input will consist of an employee list, and it will verify which indices should be greyed

Bug 2:

Testing this case is quite challenging, as it would be complicated to mock the test. However, if we still want to cover it with a unit test, we need to validate that the approver who was just deleted cannot be automatically added back to the approval chain

What alternative solutions did you explore? (Optional)

@nkdengineer
Copy link
Contributor

Proposal

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

After changing 1st approver, 2nd approver is not greyed out & not added approvers are shown with error message.

What is the root cause of that problem?

  1. When we change the first approver, pendingFields.forwardsTo of the new approver is undefined then the second row is not greyed out.

function setApprovalWorkflowApprover(approver: Approver, approverIndex: number, policyID: string) {

After we click on the save button, we've had the logic to add forwardsTo pending field here

pendingFields: {
forwardsTo: pendingAction,
},

But it's overridden here when the submitsTo is changed here. That is why this bug only happens when we change the first approver

pendingFields: {
submitsTo: pendingAction,
},

  1. When we change the approver without saving, we add the forwardsTo of the approver automatically based on the policy employee list here then that causes the error because the first approver still forwards to user 1 and user 1 still forwards to user 2.

if (policy.employeeList[approver.email]?.forwardsTo) {
const additionalApprovers = calculateApprovers({employees: policy.employeeList, firstEmail: approver.email, personalDetailsByEmail});
approvers.splice(approverIndex, approvers.length, ...additionalApprovers);

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

  1. When we update the approver here, we can update forwardsTo pending fields of the new approver based on the old approver
const prevApprover = currentApprovalWorkflow.approvers.find((approver, index) => index === approverIndex);
const prevApproverInMember = currentApprovalWorkflow.members.find((member) => member.email === prevApprover?.email);

const updatedMembers = currentApprovalWorkflow.members.map((member, index) => {
    if (member.email === approver?.email) {
        return {
            ...member,
            pendingFields: {
                forwardsTo: prevApproverInMember?.pendingFields?.forwardsTo
            }
        }
    }
    if (member.email === prevApprover?.email) {
        return {
            ...member,
            pendingFields: {
                forwardsTo: null,
            }
        }
    }
    return {...member}
})

Onyx.merge(ONYXKEYS.APPROVAL_WORKFLOW, {approvers: updatedApprovers, members: updatedMembers, errors});

function setApprovalWorkflowApprover(approver: Approver, approverIndex: number, policyID: string) {

When we save the workflow, we should keep the rest pending field here

const pendingFields = updatedEmployeeList?.[email]?.pendingFields ?? {};
updatedEmployeeList[email] = {
    ...(updatedEmployeeList[email] ? updatedEmployeeList[email] : {email}),
    submitsTo,
    pendingAction,
    pendingFields: {
        ...pendingFields,
        submitsTo: pendingAction,
    },
};

pendingFields: {
submitsTo: pendingAction,
},

  1. I think we can remove this logic since it's not necessary

if (policy.employeeList[approver.email]?.forwardsTo) {
const additionalApprovers = calculateApprovers({employees: policy.employeeList, firstEmail: approver.email, personalDetailsByEmail});
approvers.splice(approverIndex, approvers.length, ...additionalApprovers);

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

What alternative solutions did you explore? (Optional)

NA

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.

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
None yet
Development

No branches or pull requests

5 participants