diff --git a/src/pages/inbox/report/PureReportActionItem.tsx b/src/pages/inbox/report/PureReportActionItem.tsx
index ef2dee3fd01b..0bd9fcbb67b7 100644
--- a/src/pages/inbox/report/PureReportActionItem.tsx
+++ b/src/pages/inbox/report/PureReportActionItem.tsx
@@ -76,7 +76,7 @@ import type {ReportsSplitNavigatorParamList} from '@libs/Navigation/types';
import {getBankAccountLastFourDigits} from '@libs/PaymentUtils';
import Permissions from '@libs/Permissions';
import {getDisplayNameOrDefault} from '@libs/PersonalDetailsUtils';
-import {getCleanedTagName, hasDynamicExternalWorkflow, isPolicyAdmin, isPolicyMember, isPolicyOwner} from '@libs/PolicyUtils';
+import {getCleanedTagName, isPolicyAdmin, isPolicyMember, isPolicyOwner} from '@libs/PolicyUtils';
import {containsActionableFollowUps, parseFollowupsFromHtml} from '@libs/ReportActionFollowupUtils';
import {
extractLinksFromMessageHtml,
@@ -170,8 +170,6 @@ import {
getWorkspaceTagUpdateMessage,
getWorkspaceTaxUpdateMessage,
getWorkspaceUpdateFieldMessage,
- hasPendingDEWApprove,
- hasPendingDEWSubmit,
isActionableAddPaymentCard,
isActionableCardFraudAlert,
isActionableJoinRequest,
@@ -188,7 +186,6 @@ import {
isDeletedAction,
isDeletedParentAction as isDeletedParentActionUtils,
isIOURequestReportAction,
- isMarkAsClosedAction,
isMessageDeleted,
isMoneyRequestAction,
isPendingRemove,
@@ -250,6 +247,7 @@ import type * as OnyxTypes from '@src/types/onyx';
import type {Errors} from '@src/types/onyx/OnyxCommon';
import type {JoinWorkspaceResolution} from '@src/types/onyx/OriginalMessage';
import {isEmptyObject, isEmptyValueObject} from '@src/types/utils/EmptyObject';
+import ApprovalFlowContent, {isApprovalFlowAction} from './actionContents/ApprovalFlowContent';
import SimpleMessageContent, {isSimpleMessageAction} from './actionContents/SimpleMessageContent';
import {RestrictedReadOnlyContextMenuActions} from './ContextMenu/ContextMenuActions';
import MiniReportActionContextMenu from './ContextMenu/MiniReportActionContextMenu';
@@ -1364,47 +1362,16 @@ function PureReportActionItem({
originalReport={originalReport}
/>
);
- } else if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.SUBMITTED) || isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.SUBMITTED_AND_CLOSED) || isMarkAsClosedAction(action)) {
- const wasSubmittedViaHarvesting = !isMarkAsClosedAction(action) ? (getOriginalMessage(action)?.harvesting ?? false) : false;
- const isDEWPolicy = hasDynamicExternalWorkflow(policy);
-
- const isPendingAdd = action.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD;
- if (wasSubmittedViaHarvesting) {
- children = (
-
- );
- } else if (hasPendingDEWSubmit(reportMetadata, isDEWPolicy) && isPendingAdd) {
- children = ;
- } else if (isDEWPolicy) {
- // Don't show a memo for DEW actions, it's shown in the Concierge action below
- children = ;
- } else {
- children = ;
- }
- } else if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.APPROVED)) {
- const wasAutoApproved = getOriginalMessage(action)?.automaticAction ?? false;
- const isDEWPolicy = hasDynamicExternalWorkflow(policy);
- const isPendingAdd = action.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD;
-
- if (wasAutoApproved) {
- children = (
-
- );
- } else if (hasPendingDEWApprove(reportMetadata, isDEWPolicy) && isPendingAdd) {
- children = ;
- } else {
- children = ;
- }
+ } else if (isApprovalFlowAction(action)) {
+ children = (
+
+ );
} else if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.IOU) && getOriginalMessage(action)?.type === CONST.IOU.REPORT_ACTION_TYPE.PAY) {
const wasAutoPaid = getOriginalMessage(action)?.automaticAction ?? false;
const paymentType = getOriginalMessage(action)?.paymentType;
@@ -1453,17 +1420,6 @@ function PureReportActionItem({
children = ;
} else if (isSimpleMessageAction(action)) {
children = ;
- } else if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.FORWARDED)) {
- const wasAutoForwarded = getOriginalMessage(action)?.automaticAction ?? false;
- if (wasAutoForwarded) {
- children = (
-
- ${translate('iou.automaticallyForwarded')}`} />
-
- );
- } else {
- children = ;
- }
} else if (action.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.CORPORATE_UPGRADE) {
children = ;
} else if (action.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.CORPORATE_FORCE_UPGRADE) {
diff --git a/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx b/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx
new file mode 100644
index 000000000000..a711068df2b2
--- /dev/null
+++ b/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx
@@ -0,0 +1,102 @@
+import React from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
+import RenderHTML from '@components/RenderHTML';
+import useLocalize from '@hooks/useLocalize';
+import {hasDynamicExternalWorkflow} from '@libs/PolicyUtils';
+import {getOriginalMessage, hasPendingDEWApprove, hasPendingDEWSubmit, isActionOfType, isMarkAsClosedAction} from '@libs/ReportActionsUtils';
+import ReportActionItemBasicMessage from '@pages/inbox/report/ReportActionItemBasicMessage';
+import ReportActionItemMessageWithExplain from '@pages/inbox/report/ReportActionItemMessageWithExplain';
+import CONST from '@src/CONST';
+import type * as OnyxTypes from '@src/types/onyx';
+
+type ApprovalFlowContentProps = {
+ action: OnyxTypes.ReportAction;
+ policy: OnyxEntry;
+ reportMetadata: OnyxEntry;
+ childReport: OnyxEntry;
+ originalReport: OnyxEntry;
+};
+
+function isApprovalFlowAction(action: OnyxTypes.ReportAction): boolean {
+ return (
+ isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.SUBMITTED) ||
+ isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.SUBMITTED_AND_CLOSED) ||
+ isMarkAsClosedAction(action) ||
+ isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.APPROVED) ||
+ isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.FORWARDED)
+ );
+}
+
+function ApprovalFlowContent({action, policy, reportMetadata, childReport, originalReport}: ApprovalFlowContentProps) {
+ const {translate} = useLocalize();
+ const isDEWPolicy = hasDynamicExternalWorkflow(policy);
+ const isPendingAdd = action?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD;
+
+ if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.SUBMITTED) || isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.SUBMITTED_AND_CLOSED) || isMarkAsClosedAction(action)) {
+ const wasSubmittedViaHarvesting = !isMarkAsClosedAction(action) ? (getOriginalMessage(action)?.harvesting ?? false) : false;
+
+ if (wasSubmittedViaHarvesting) {
+ return (
+
+ );
+ }
+
+ if (hasPendingDEWSubmit(reportMetadata, isDEWPolicy) && isPendingAdd) {
+ return ;
+ }
+
+ if (isDEWPolicy) {
+ // Don't show a memo for DEW actions, it's shown in the Concierge action below
+ return ;
+ }
+
+ return ;
+ }
+
+ if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.APPROVED)) {
+ const wasAutoApproved = getOriginalMessage(action)?.automaticAction ?? false;
+
+ if (wasAutoApproved) {
+ return (
+
+ );
+ }
+
+ if (hasPendingDEWApprove(reportMetadata, isDEWPolicy) && isPendingAdd) {
+ return ;
+ }
+
+ return ;
+ }
+
+ if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.FORWARDED)) {
+ const wasAutoForwarded = getOriginalMessage(action)?.automaticAction ?? false;
+
+ if (wasAutoForwarded) {
+ return (
+
+ ${translate('iou.automaticallyForwarded')}`} />
+
+ );
+ }
+
+ return ;
+ }
+
+ return null;
+}
+
+ApprovalFlowContent.displayName = 'ApprovalFlowContent';
+
+export default ApprovalFlowContent;
+export {isApprovalFlowAction};
diff --git a/tests/ui/PureReportActionItemTest.tsx b/tests/ui/PureReportActionItemTest.tsx
index 0d488e056e51..e2be1714fd15 100644
--- a/tests/ui/PureReportActionItemTest.tsx
+++ b/tests/ui/PureReportActionItemTest.tsx
@@ -482,6 +482,130 @@ describe('PureReportActionItem', () => {
expect(screen.getByText(translateLocal('iou.submitted'))).toBeOnTheScreen();
expect(screen.queryByText(translateLocal('iou.queuedToSubmitViaDEW'))).not.toBeOnTheScreen();
});
+
+ it('should display DEW queued message for pending APPROVED action when policy has DEW enabled', async () => {
+ const action = createReportAction(CONST.REPORT.ACTIONS.TYPE.APPROVED, {automaticAction: false});
+ action.pendingAction = CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD;
+
+ const dewPolicy = {
+ id: 'testPolicy',
+ name: 'Test DEW Policy',
+ type: CONST.POLICY.TYPE.TEAM,
+ role: CONST.POLICY.ROLE.ADMIN,
+ owner: 'owner@test.com',
+ outputCurrency: CONST.CURRENCY.USD,
+ isPolicyExpenseChatEnabled: true,
+ approvalMode: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL,
+ } as const;
+
+ const reportMetadata = {
+ pendingExpenseAction: CONST.EXPENSE_PENDING_ACTION.APPROVE,
+ };
+
+ await act(async () => {
+ await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}testPolicy`, dewPolicy);
+ });
+ await waitForBatchedUpdatesWithAct();
+
+ render(
+
+
+
+
+
+
+
+
+ ,
+ );
+ await waitForBatchedUpdatesWithAct();
+
+ expect(screen.getByText(actorEmail)).toBeOnTheScreen();
+ expect(screen.getByText(translateLocal('iou.queuedToApproveViaDEW'))).toBeOnTheScreen();
+ });
+
+ it('should display submitted without memo for SUBMITTED action on DEW policy that is not pending', async () => {
+ const action = createReportAction(CONST.REPORT.ACTIONS.TYPE.SUBMITTED, {harvesting: false, message: 'my memo'});
+
+ const dewPolicy = {
+ id: 'testPolicy',
+ name: 'Test DEW Policy',
+ type: CONST.POLICY.TYPE.TEAM,
+ role: CONST.POLICY.ROLE.ADMIN,
+ owner: 'owner@test.com',
+ outputCurrency: CONST.CURRENCY.USD,
+ isPolicyExpenseChatEnabled: true,
+ approvalMode: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL,
+ } as const;
+
+ await act(async () => {
+ await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}testPolicy`, dewPolicy);
+ });
+ await waitForBatchedUpdatesWithAct();
+
+ render(
+
+
+
+
+
+
+
+
+ ,
+ );
+ await waitForBatchedUpdatesWithAct();
+
+ expect(screen.getByText(actorEmail)).toBeOnTheScreen();
+ // DEW policy should show submitted without the memo (memo is shown in the Concierge action)
+ expect(screen.getByText(translateLocal('iou.submitted'))).toBeOnTheScreen();
+ expect(screen.queryByText('my memo')).not.toBeOnTheScreen();
+ });
+
+ it('CLOSED action with amount (MARK_AS_CLOSED) renders submitted message', async () => {
+ const action = createReportAction(CONST.REPORT.ACTIONS.TYPE.CLOSED, {amount: 5000});
+ renderItemWithAction(action);
+ await waitForBatchedUpdatesWithAct();
+
+ expect(screen.getByText(translateLocal('iou.submitted'))).toBeOnTheScreen();
+ });
});
describe('Followup list buttons', () => {