Skip to content

Commit 3d59622

Browse files
luacmartinsOSBotify
authored andcommitted
Merge pull request #61667 from Expensify/cmartins-fixWorkpsaceChangeLogic
[CP Staging] Fix workspace change logic (cherry picked from commit 3db7396) (cherry-picked to staging by yuwenmemon)
1 parent 09a3b38 commit 3d59622

5 files changed

Lines changed: 60 additions & 18 deletions

File tree

src/libs/ReportSecondaryActionUtils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,10 @@ function isHoldActionForTransation(report: Report, reportTransaction: Transactio
313313
return isProcessingReport;
314314
}
315315

316-
function isChangeWorkspaceAction(report: Report): boolean {
316+
function isChangeWorkspaceAction(report: Report, policy?: Policy): boolean {
317317
const policies = getAllPolicies();
318318
const session = getSession();
319-
return policies.filter((newPolicy) => isWorkspaceEligibleForReportChange(newPolicy, report, session)).length > 0;
319+
return policies.filter((newPolicy) => isWorkspaceEligibleForReportChange(newPolicy, report, session, policy)).length > 0;
320320
}
321321

322322
function isDeleteAction(report: Report, reportTransactions: Transaction[]): boolean {
@@ -391,7 +391,7 @@ function getSecondaryReportActions(
391391

392392
options.push(CONST.REPORT.SECONDARY_ACTIONS.DOWNLOAD);
393393

394-
if (isChangeWorkspaceAction(report)) {
394+
if (isChangeWorkspaceAction(report, policy)) {
395395
options.push(CONST.REPORT.SECONDARY_ACTIONS.CHANGE_WORKSPACE);
396396
}
397397

src/libs/ReportUtils.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10392,7 +10392,7 @@ function verifyStatus(report: OnyxEntry<Report>, validStatuses: Array<ValueOf<ty
1039210392
/**
1039310393
* Determines whether the report can be moved to the workspace.
1039410394
*/
10395-
function isWorkspaceEligibleForReportChange(newPolicy: OnyxEntry<Policy>, report: OnyxEntry<Report>, session: OnyxEntry<Session>): boolean {
10395+
function isWorkspaceEligibleForReportChange(newPolicy: OnyxEntry<Policy>, report: OnyxEntry<Report>, session: OnyxEntry<Session>, currentPolicy?: OnyxEntry<Policy>): boolean {
1039610396
if (!session?.accountID) {
1039710397
return false;
1039810398
}
@@ -10403,6 +10403,7 @@ function isWorkspaceEligibleForReportChange(newPolicy: OnyxEntry<Policy>, report
1040310403
const managerLogin = report?.managerID && getLoginByAccountID(report?.managerID);
1040410404
const isManagerMember = !!managerLogin && !!newPolicy?.employeeList?.[managerLogin];
1040510405
const isCurrentUserAdmin = isPolicyAdminPolicyUtils(newPolicy, session?.email);
10406+
const isAdminOfCurrentPolicy = isPolicyAdminPolicyUtils(currentPolicy, session?.email);
1040610407
const isPaidGroupPolicyType = isPaidGroupPolicyPolicyUtils(newPolicy);
1040710408
const isReportOpenOrSubmitted = verifyState(report, [CONST.REPORT.STATE_NUM.OPEN, CONST.REPORT.STATE_NUM.SUBMITTED]);
1040810409

@@ -10415,13 +10416,15 @@ function isWorkspaceEligibleForReportChange(newPolicy: OnyxEntry<Policy>, report
1041510416

1041610417
// From this point on, reports must be of type Expense, the policy must be a paid type.
1041710418
// The submitter and manager must also be policy members OR the current user is an admin so they can invite the non-members to the policy.
10419+
// Additionally, if the report is not open or submitted, the current user must be an admin.
10420+
// We're temporarily disabling moving reports to a workspace if the submitter is not a member of the new policy because this flow requires additional API changes.
1041810421
const isExpenseReportType = isExpenseReport(report);
10419-
if (!isExpenseReportType || !isPaidGroupPolicyType || !((isSubmitterMember && isManagerMember) || isCurrentUserAdmin)) {
10422+
if (!isExpenseReportType || !isPaidGroupPolicyType || !isSubmitterMember || (!isReportOpenOrSubmitted && !isAdminOfCurrentPolicy)) {
1042010423
return false;
1042110424
}
1042210425

1042310426
const isCurrentUserReportSubmitter = session.accountID === report?.ownerAccountID;
10424-
if (isCurrentUserReportSubmitter && isReportOpenOrSubmitted) {
10427+
if (isCurrentUserReportSubmitter) {
1042510428
return true;
1042610429
}
1042710430

src/pages/ReportChangeWorkspacePage.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,14 @@ function ReportChangeWorkspacePage({report}: ReportChangeWorkspacePageProps) {
5656
[session?.email, report, reportID],
5757
);
5858

59+
const reportPolicy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`];
5960
const {sections, shouldShowNoResultsFoundMessage, shouldShowSearchInput} = useWorkspaceList({
6061
policies,
6162
currentUserLogin: session?.email,
6263
shouldShowPendingDeletePolicy: false,
6364
selectedPolicyID: report.policyID,
6465
searchTerm: debouncedSearchTerm,
65-
additionalFilter: (newPolicy) => isWorkspaceEligibleForReportChange(newPolicy, report, session),
66+
additionalFilter: (newPolicy) => isWorkspaceEligibleForReportChange(newPolicy, report, session, reportPolicy),
6667
});
6768

6869
if (!isMoneyRequestReport(report) || isMoneyRequestReportPendingDeletion(report) || (!report.total && !report.unheldTotal)) {

tests/unit/PolicyUtilsTest.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,31 @@ describe('PolicyUtils', () => {
751751
expect(result).toBe(true);
752752
});
753753

754+
it('returns false if current user is not a policy admin and the report is approved', () => {
755+
const currentUserLogin = approverEmail;
756+
const currentUserAccountID = approverAccountID;
757+
const session = {email: currentUserLogin, accountID: currentUserAccountID};
758+
759+
const newPolicy = {
760+
...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
761+
role: CONST.POLICY.ROLE.USER,
762+
approver: approverEmail,
763+
employeeList: {
764+
[employeeEmail]: {email: employeeEmail, role: CONST.POLICY.ROLE.USER},
765+
[currentUserLogin]: {email: currentUserLogin, role: CONST.POLICY.ROLE.USER},
766+
},
767+
};
768+
const report = {
769+
...createRandomReport(0),
770+
type: CONST.REPORT.TYPE.EXPENSE,
771+
stateNum: CONST.REPORT.STATE_NUM.APPROVED,
772+
ownerAccountID: currentUserAccountID,
773+
};
774+
775+
const result = isWorkspaceEligibleForReportChange(newPolicy, report, session);
776+
expect(result).toBe(false);
777+
});
778+
754779
it('returns true if current user is the approver and submitter is a member', () => {
755780
const currentUserLogin = approverEmail;
756781
const currentUserAccountID = approverAccountID;
@@ -831,6 +856,15 @@ describe('PolicyUtils', () => {
831856
role: CONST.POLICY.ROLE.ADMIN,
832857
employeeList: {
833858
[currentUserLogin]: {email: currentUserLogin, role: CONST.POLICY.ROLE.ADMIN},
859+
[employeeEmail]: {email: employeeEmail, role: CONST.POLICY.ROLE.USER},
860+
},
861+
};
862+
const currentPolicy = {
863+
...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
864+
role: CONST.POLICY.ROLE.ADMIN,
865+
employeeList: {
866+
[currentUserLogin]: {email: currentUserLogin, role: CONST.POLICY.ROLE.ADMIN},
867+
[employeeEmail]: {email: employeeEmail, role: CONST.POLICY.ROLE.USER},
834868
},
835869
};
836870
const report = {
@@ -839,9 +873,10 @@ describe('PolicyUtils', () => {
839873
stateNum: CONST.REPORT.STATE_NUM.APPROVED,
840874
type: CONST.REPORT.TYPE.EXPENSE,
841875
managerID: approverAccountID,
876+
policyID: currentPolicy.id,
842877
};
843878

844-
expect(isWorkspaceEligibleForReportChange(newPolicy, report, session)).toBe(true);
879+
expect(isWorkspaceEligibleForReportChange(newPolicy, report, session, currentPolicy)).toBe(true);
845880
});
846881
});
847882

tests/unit/ReportSecondaryActionUtilsTest.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ describe('getSecondaryAction', () => {
434434
expect(result.includes(CONST.REPORT.SECONDARY_ACTIONS.CHANGE_WORKSPACE)).toBe(true);
435435
});
436436

437-
it('includes CHANGE_WORKSPACE option for opened expense report submitter', async () => {
437+
it('includes CHANGE_WORKSPACE option for open expense report submitter', async () => {
438438
const report = {
439439
reportID: REPORT_ID,
440440
type: CONST.REPORT.TYPE.EXPENSE,
@@ -454,6 +454,7 @@ describe('getSecondaryAction', () => {
454454
role: CONST.POLICY.ROLE.ADMIN,
455455
employeeList: {
456456
[ADMIN_EMAIL]: {email: ADMIN_EMAIL, role: CONST.POLICY.ROLE.ADMIN},
457+
[EMPLOYEE_EMAIL]: {email: EMPLOYEE_EMAIL, role: CONST.POLICY.ROLE.USER},
457458
},
458459
} as unknown as Policy;
459460

@@ -575,29 +576,31 @@ describe('getSecondaryAction', () => {
575576
});
576577

577578
it('includes CHANGE_WORKSPACE option for admin', async () => {
579+
const policy = {
580+
id: POLICY_ID,
581+
type: CONST.POLICY.TYPE.TEAM,
582+
role: CONST.POLICY.ROLE.ADMIN,
583+
employeeList: {
584+
[ADMIN_EMAIL]: {email: ADMIN_EMAIL, role: CONST.POLICY.ROLE.ADMIN},
585+
[EMPLOYEE_EMAIL]: {login: EMPLOYEE_EMAIL, role: CONST.POLICY.ROLE.USER},
586+
},
587+
} as unknown as Policy;
588+
578589
const report = {
579590
reportID: REPORT_ID,
580591
type: CONST.REPORT.TYPE.EXPENSE,
581592
ownerAccountID: EMPLOYEE_ACCOUNT_ID,
582593
managerID: MANAGER_ACCOUNT_ID,
583594
statusNum: CONST.REPORT.STATUS_NUM.REIMBURSED,
584595
stateNum: CONST.REPORT.STATE_NUM.APPROVED,
596+
policyID: policy.id,
585597
} as unknown as Report;
586598

587599
const personalDetails = {
588600
[EMPLOYEE_ACCOUNT_ID]: {login: EMPLOYEE_EMAIL},
589601
[ADMIN_ACCOUNT_ID]: {login: ADMIN_EMAIL},
590602
};
591603

592-
const policy = {
593-
id: POLICY_ID,
594-
type: CONST.POLICY.TYPE.TEAM,
595-
role: CONST.POLICY.ROLE.ADMIN,
596-
employeeList: {
597-
[ADMIN_EMAIL]: {email: ADMIN_EMAIL, role: CONST.POLICY.ROLE.ADMIN},
598-
},
599-
} as unknown as Policy;
600-
601604
await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${POLICY_ID}`, policy);
602605
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`, report);
603606
await Onyx.merge(ONYXKEYS.SESSION, {email: ADMIN_EMAIL, accountID: ADMIN_ACCOUNT_ID});

0 commit comments

Comments
 (0)