From d47cde7c85af654fa35d99b28a7e1762f4a0670f Mon Sep 17 00:00:00 2001 From: KJ21-ENG Date: Mon, 3 Aug 2026 21:28:17 +0530 Subject: [PATCH] Fix workflows off submission fallback --- src/libs/actions/Policy/Policy.ts | 10 +- .../WorkspaceMoreFeaturesPage/index.tsx | 10 +- tests/actions/PolicyTest.ts | 96 ++++++++++++++++--- 3 files changed, 101 insertions(+), 15 deletions(-) diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 09ecaef1f208..7953d4e95bd4 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -5230,6 +5230,7 @@ function enablePolicyWorkflows( enabled: boolean, currentApprovalMode: Policy['approvalMode'], currentAutoReporting: Policy['autoReporting'], + currentAutoReportingFrequency: Policy['autoReportingFrequency'], currentHarvesting: Policy['harvesting'], currentReimbursementChoice: Policy['reimbursementChoice'], ) { @@ -5243,9 +5244,10 @@ function enablePolicyWorkflows( ...(!enabled ? { approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL, - autoReporting: false, + autoReporting: true, + autoReportingFrequency: CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT, harvesting: { - enabled: false, + enabled: true, }, reimbursementChoice: CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO, } @@ -5256,6 +5258,7 @@ function enablePolicyWorkflows( ? { approvalMode: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, autoReporting: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + autoReportingFrequency: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, harvesting: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, reimbursementChoice: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, } @@ -5275,6 +5278,7 @@ function enablePolicyWorkflows( ? { approvalMode: null, autoReporting: null, + autoReportingFrequency: null, harvesting: null, reimbursementChoice: null, } @@ -5293,6 +5297,7 @@ function enablePolicyWorkflows( ? { approvalMode: currentApprovalMode, autoReporting: currentAutoReporting, + autoReportingFrequency: currentAutoReportingFrequency ?? null, harvesting: currentHarvesting, reimbursementChoice: currentReimbursementChoice, } @@ -5303,6 +5308,7 @@ function enablePolicyWorkflows( ? { approvalMode: null, autoReporting: null, + autoReportingFrequency: null, harvesting: null, reimbursementChoice: null, } diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx index 2536dbc9bbe9..b3488b465b0b 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage/index.tsx @@ -495,7 +495,15 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro if (!policyID) { return; } - enablePolicyWorkflows(policyID, isEnabled, policy?.approvalMode, policy?.autoReporting, policy?.harvesting, policy?.reimbursementChoice); + enablePolicyWorkflows( + policyID, + isEnabled, + policy?.approvalMode, + policy?.autoReporting, + policy?.autoReportingFrequency, + policy?.harvesting, + policy?.reimbursementChoice, + ); }} onPress={() => { if (!policyID) { diff --git a/tests/actions/PolicyTest.ts b/tests/actions/PolicyTest.ts index 2ec6867ed2a3..6f9d8954623e 100644 --- a/tests/actions/PolicyTest.ts +++ b/tests/actions/PolicyTest.ts @@ -5263,7 +5263,7 @@ describe('actions/Policy', () => { // When enablePolicyWorkflows is called to enable workflows mockFetch.pause(); - Policy.enablePolicyWorkflows(policyID, true, undefined, undefined, undefined, undefined); + Policy.enablePolicyWorkflows(policyID, true, undefined, undefined, undefined, undefined, undefined); await waitForBatchedUpdates(); // Then workflows should be enabled optimistically @@ -5279,7 +5279,7 @@ describe('actions/Policy', () => { expect(updatedPolicy?.pendingFields?.areWorkflowsEnabled).toBeUndefined(); }); - it('should revert policy workflows when fail', async () => { + it('should disable policy workflows with instant submission optimistically and succeed', async () => { // Given a policy with workflows enabled const policyID = '1'; const fakePolicy = { @@ -5287,26 +5287,98 @@ describe('actions/Policy', () => { areWorkflowsEnabled: true, approvalMode: CONST.POLICY.APPROVAL_MODE.ADVANCED, autoReporting: true, - harvesting: {enabled: true, jobID: 123}, + autoReportingFrequency: CONST.POLICY.AUTO_REPORTING_FREQUENCIES.WEEKLY, + harvesting: {enabled: false}, reimbursementChoice: CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES, }; Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, fakePolicy); await waitForBatchedUpdates(); - // When enablePolicyWorkflows is called to disable workflows and fails - mockFetch.fail(); - Policy.enablePolicyWorkflows(policyID, false, fakePolicy.approvalMode, fakePolicy.autoReporting, fakePolicy.harvesting, fakePolicy.reimbursementChoice); + // When enablePolicyWorkflows is called to disable workflows + mockFetch.pause(); + Policy.enablePolicyWorkflows( + policyID, + false, + fakePolicy.approvalMode, + fakePolicy.autoReporting, + fakePolicy.autoReportingFrequency, + fakePolicy.harvesting, + fakePolicy.reimbursementChoice, + ); await waitForBatchedUpdates(); - // Then workflows should be reverted to enabled and other fields restored - const updatedPolicy = await getOnyxValue(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); - expect(updatedPolicy?.areWorkflowsEnabled).toBe(true); - expect(updatedPolicy?.approvalMode).toBe(CONST.POLICY.APPROVAL_MODE.ADVANCED); + // Then workflows should be disabled with instant submission optimistically + let updatedPolicy = await getOnyxValue(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); + expect(updatedPolicy?.areWorkflowsEnabled).toBe(false); + expect(updatedPolicy?.approvalMode).toBe(CONST.POLICY.APPROVAL_MODE.OPTIONAL); expect(updatedPolicy?.autoReporting).toBe(true); + expect(updatedPolicy?.autoReportingFrequency).toBe(CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT); expect(updatedPolicy?.harvesting?.enabled).toBe(true); - expect(updatedPolicy?.reimbursementChoice).toBe(CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES); + expect(updatedPolicy?.reimbursementChoice).toBe(CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO); + expect(updatedPolicy?.pendingFields).toMatchObject({ + areWorkflowsEnabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + approvalMode: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + autoReporting: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + autoReportingFrequency: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + harvesting: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + reimbursementChoice: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + }); + + // When the fetch resumes and succeeds + await mockFetch.resume(); + + // Then all workflow pending fields should be cleared + updatedPolicy = await getOnyxValue(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); expect(updatedPolicy?.pendingFields?.areWorkflowsEnabled).toBeUndefined(); - }); + expect(updatedPolicy?.pendingFields?.approvalMode).toBeUndefined(); + expect(updatedPolicy?.pendingFields?.autoReporting).toBeUndefined(); + expect(updatedPolicy?.pendingFields?.autoReportingFrequency).toBeUndefined(); + expect(updatedPolicy?.pendingFields?.harvesting).toBeUndefined(); + expect(updatedPolicy?.pendingFields?.reimbursementChoice).toBeUndefined(); + }); + + it.each([CONST.POLICY.AUTO_REPORTING_FREQUENCIES.WEEKLY, undefined] as const)( + 'should revert policy workflows when fail with auto reporting frequency %s', + async (autoReportingFrequency) => { + // Given a policy with workflows enabled + const policyID = '1'; + const fakePolicy = { + id: policyID, + areWorkflowsEnabled: true, + approvalMode: CONST.POLICY.APPROVAL_MODE.ADVANCED, + autoReporting: true, + autoReportingFrequency, + harvesting: {enabled: true, jobID: 123}, + reimbursementChoice: CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES, + }; + Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, fakePolicy); + await waitForBatchedUpdates(); + + // When enablePolicyWorkflows is called to disable workflows and fails + mockFetch.fail(); + Policy.enablePolicyWorkflows( + policyID, + false, + fakePolicy.approvalMode, + fakePolicy.autoReporting, + fakePolicy.autoReportingFrequency, + fakePolicy.harvesting, + fakePolicy.reimbursementChoice, + ); + await waitForBatchedUpdates(); + + // Then workflows should be reverted to enabled and other fields restored + const updatedPolicy = await getOnyxValue(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); + expect(updatedPolicy?.areWorkflowsEnabled).toBe(true); + expect(updatedPolicy?.approvalMode).toBe(CONST.POLICY.APPROVAL_MODE.ADVANCED); + expect(updatedPolicy?.autoReporting).toBe(true); + expect(updatedPolicy?.autoReportingFrequency).toBe(autoReportingFrequency); + expect(updatedPolicy?.harvesting?.enabled).toBe(true); + expect(updatedPolicy?.reimbursementChoice).toBe(CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES); + expect(updatedPolicy?.pendingFields?.areWorkflowsEnabled).toBeUndefined(); + expect(updatedPolicy?.pendingFields?.autoReportingFrequency).toBeUndefined(); + }, + ); }); describe('enableDistanceRequestTax', () => { it('should enable distance request tax optimistically and succeed', async () => {