From 997027d7996d21bbdeeb5b67c3d45c1fcdbd10df Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Sun, 14 Dec 2025 23:39:48 +0800
Subject: [PATCH 01/13] show concierge system message after submit/approval
 action

---
 src/CONST/index.ts                            |   1 +
 src/hooks/useOriginalReportID.ts              |   4 +-
 src/languages/de.ts                           |   1 +
 src/languages/en.ts                           |   2 +
 src/languages/es.ts                           |   1 +
 src/languages/fr.ts                           |   1 +
 src/languages/it.ts                           |   1 +
 src/languages/ja.ts                           |   1 +
 src/languages/nl.ts                           |   1 +
 src/languages/params.ts                       |   5 +
 src/languages/pl.ts                           |   1 +
 src/languages/pt-BR.ts                        |   1 +
 src/languages/zh-hans.ts                      |   1 +
 src/libs/OptionsListUtils/index.ts            |  19 +-
 src/libs/ReportActionsUtils.ts                |  65 +++-
 src/libs/ReportUtils.ts                       |   4 +-
 .../BaseReportActionContextMenu.tsx           |   3 +-
 .../report/ContextMenu/ContextMenuActions.tsx |  21 +-
 src/types/onyx/OriginalMessage.ts             |  15 +
 tests/unit/OptionsListUtilsTest.tsx           |  24 +-
 tests/unit/ReportActionsUtilsTest.ts          | 318 +++++++++++++++++-
 tests/unit/ReportUtilsTest.ts                 |   7 +
 22 files changed, 477 insertions(+), 20 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 975cbd0052a7..ef816265fe2f 100755
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -1213,6 +1213,7 @@ const CONST = {
                 DELETED_TRANSACTION: 'DELETEDTRANSACTION',
                 DISMISSED_VIOLATION: 'DISMISSEDVIOLATION',
                 DONATION: 'DONATION', // Deprecated OldDot Action
+                DYNAMIC_EXTERNAL_WORKFLOW_ROUTED: 'DYNAMICEXTERNALWORKFLOWROUTED',
                 EXPENSIFY_CARD_SYSTEM_MESSAGE: 'EXPENSIFYCARDSYSTEMMESSAGE',
                 EXPORTED_TO_CSV: 'EXPORTCSV', // OldDot Action
                 EXPORTED_TO_INTEGRATION: 'EXPORTINTEGRATION', // OldDot Action
diff --git a/src/hooks/useOriginalReportID.ts b/src/hooks/useOriginalReportID.ts
index 361a57aef3df..c49ca0c6e2e8 100644
--- a/src/hooks/useOriginalReportID.ts
+++ b/src/hooks/useOriginalReportID.ts
@@ -1,6 +1,6 @@
 import {useMemo} from 'react';
 import {getAllNonDeletedTransactions} from '@libs/MoneyRequestReportUtils';
-import {getOneTransactionThreadReportID} from '@libs/ReportActionsUtils';
+import {getOneTransactionThreadReportID, withDEWRoutedActionsObject} from '@libs/ReportActionsUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {OnyxInputOrEntry, ReportAction} from '@src/types/onyx';
@@ -21,7 +21,7 @@ import useTransactionsAndViolationsForReport from './useTransactionsAndViolation
  *
  */
 function useOriginalReportID(reportID: string | undefined, reportAction: OnyxInputOrEntry<Pick<ReportAction, 'reportActionID' | 'childReportID'>>): string | undefined {
-    const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {canBeMissing: true});
+    const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {canBeMissing: true, selector: withDEWRoutedActionsObject});
     const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {canBeMissing: true});
     const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`, {canBeMissing: true});
     const {isOffline} = useNetwork();
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 438a7f79fc6f..d34d232c9d87 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -1570,6 +1570,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Arbeitsbereich auswählen',
+        routedDueToDEW: ({to}) => `bericht aufgrund eines benutzerdefinierten Genehmigungsworkflows an ${to} weitergeleitet`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 9eafd177a704..4bf5f859a89c 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -194,6 +194,7 @@ import type {
     RoleNamesParams,
     RoomNameReservedErrorParams,
     RoomRenamedToParams,
+    RoutedDueToDEWParams,
     RulesEnableWorkflowsParams,
     SecondaryLoginParams,
     SetTheDistanceMerchantParams,
@@ -1541,6 +1542,7 @@ const translations = {
             },
         },
         chooseWorkspace: 'Choose a workspace',
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `report routed to ${to} due to custom approval workflow`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index c6810a535868..63278622b9ae 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1172,6 +1172,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Elige un espacio de trabajo',
+        routedDueToDEW: ({to}) => `informe enviado a ${to} debido a un flujo de aprobación personalizado`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index f9b578835ca5..84ca446a1479 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -1571,6 +1571,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Choisir un espace de travail',
+        routedDueToDEW: ({to}) => `rapport acheminé vers ${to} en raison d'un workflow d'approbation personnalisé`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index a169b1e94713..651053ed9876 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1566,6 +1566,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Scegli uno spazio di lavoro',
+        routedDueToDEW: ({to}) => `rapporto inoltrato a ${to} a causa del flusso di lavoro di approvazione personalizzato`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 52d58496a89b..8ba3b56452b2 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -1567,6 +1567,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'ワークスペースを選択',
+        routedDueToDEW: ({to}) => `カスタム承認ワークフローにより、${to} 宛にルーティングされたレポート`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index e205c3130aff..8ffd2be2a075 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1564,6 +1564,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Kies een workspace',
+        routedDueToDEW: ({to}) => `rapport doorgestuurd naar ${to} vanwege aangepaste goedkeuringsworkflow`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/params.ts b/src/languages/params.ts
index 5efb1a2c5c82..ebcc27101c0f 100644
--- a/src/languages/params.ts
+++ b/src/languages/params.ts
@@ -973,6 +973,10 @@ type FocusModeUpdateParams = {
     priorityModePageUrl: string;
 };
 
+type RoutedDueToDEWParams = {
+    to: string;
+};
+
 export type {
     SettlementAccountReconciliationParams,
     ToggleImportTitleParams,
@@ -1291,4 +1295,5 @@ export type {
     ReportFieldParams,
     FocusModeUpdateParams,
     TagSelectionParams,
+    RoutedDueToDEWParams,
 };
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index da8ef238832d..926a6dd73d12 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1563,6 +1563,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Wybierz przestrzeń roboczą',
+        routedDueToDEW: ({to}) => `raport przekazany do ${to} z powodu niestandardowego procesu zatwierdzania`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index e827ad66059f..579779fbbedc 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -1562,6 +1562,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Escolha um workspace',
+        routedDueToDEW: ({to}) => `relatório encaminhado para ${to} devido ao fluxo de trabalho de aprovação personalizado`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 0ac0fd5f87e7..81581e755c7c 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -1541,6 +1541,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: '选择一个工作区',
+        routedDueToDEW: ({to}) => `报告因自定义审批工作流而转发至 ${to}`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index 8fb4177cd352..b0bd4cdb937f 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -36,6 +36,7 @@ import {
     getActionableMentionWhisperMessage,
     getChangedApproverActionMessage,
     getCombinedReportActions,
+    getDynamicExternalWorkflowRoutedMessage,
     getExportIntegrationLastMessageText,
     getIOUReportIDFromReportActionPreview,
     getJoinRequestMessage,
@@ -54,6 +55,7 @@ import {
     getRoomAvatarUpdatedMessage,
     getRoomChangeLogMessage,
     getSortedReportActions,
+    getSortedReportActionsForDisplay,
     getTravelUpdateMessage,
     getUpdateRoomDescriptionMessage,
     isActionableAddPaymentCard,
@@ -266,10 +268,13 @@ Onyx.connect({
                 continue;
             }
 
+            const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
+            const reportNameValuePairs = allReportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`];
+            const isReportArchived = !!reportNameValuePairs?.private_isArchived;
+            const isWriteActionAllowed = canUserPerformWriteAction(report, isReportArchived);
             const reportActionsArray = Object.values(reportActions[1] ?? {});
-            let sortedReportActions = getSortedReportActions(reportActionsArray, true);
+            let sortedReportActions = getSortedReportActionsForDisplay(reportActionsArray, isWriteActionAllowed);
             allSortedReportActions[reportID] = sortedReportActions;
-            const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
             const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`];
 
             // If the report is a one-transaction report and has , we need to return the combined reportActions so that the LHN can display modifications
@@ -287,16 +292,11 @@ Onyx.connect({
                 lastReportActions[reportID] = firstReportAction;
             }
 
-            const reportNameValuePairs = allReportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`];
-            const isReportArchived = !!reportNameValuePairs?.private_isArchived;
-            const isWriteActionAllowed = canUserPerformWriteAction(report, isReportArchived);
-
             // The report is only visible if it is the last action not deleted that
             // does not match a closed or created state.
             const reportActionsForDisplay = sortedReportActions.filter(
-                (reportAction, actionKey) =>
+                (reportAction) =>
                     (!(isWhisperAction(reportAction) && !isReportPreviewAction(reportAction) && !isMoneyRequestAction(reportAction)) || isActionableMentionWhisper(reportAction)) &&
-                    shouldReportActionBeVisible(reportAction, actionKey, isWriteActionAllowed) &&
                     reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.CREATED &&
                     reportAction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
             );
@@ -617,6 +617,7 @@ function getLastMessageTextForReport({
     const reportID = report?.reportID;
     const lastReportAction = reportID ? lastVisibleReportActions[reportID] : undefined;
     const lastVisibleMessage = getLastVisibleMessage(report?.reportID);
+    console.log('last action', lastReportAction);
 
     // some types of actions are filtered out for lastReportAction, in some cases we need to check the actual last action
     const lastOriginalReportAction = reportID ? lastReportActions[reportID] : undefined;
@@ -789,6 +790,8 @@ function getLastMessageTextForReport({
         lastMessageTextFromReport = Parser.htmlToText(getUnreportedTransactionMessage(lastReportAction));
     } else if (isActionableMentionWhisper(lastReportAction)) {
         lastMessageTextFromReport = Parser.htmlToText(getActionableMentionWhisperMessage(lastReportAction));
+    } else if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED)) {
+        lastMessageTextFromReport = getDynamicExternalWorkflowRoutedMessage(lastReportAction, translateLocal);
     }
 
     // we do not want to show report closed in LHN for non archived report so use getReportLastMessage as fallback instead of lastMessageText from report
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index bfc9c958ed86..bd6c36987468 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -23,6 +23,7 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject';
 import {isCardPendingActivate} from './CardUtils';
 import {getDecodedCategoryName} from './CategoryUtils';
 import {convertAmountToDisplayString, convertToDisplayString, convertToShortDisplayString} from './CurrencyUtils';
+import DateUtils from './DateUtils';
 import {getEnvironmentURL, getOldDotEnvironmentURL} from './Environment/Environment';
 import getBase62ReportID from './getBase62ReportID';
 import {isReportMessageAttachment} from './isReportMessageAttachment';
@@ -219,6 +220,10 @@ function isSubmittedAndClosedAction(reportAction: OnyxInputOrEntry<ReportAction>
     return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.SUBMITTED_AND_CLOSED);
 }
 
+function isDynamicExternalWorkflowSubmitAction(reportAction: OnyxInputOrEntry<ReportAction>): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.SUBMITTED> {
+    return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.SUBMITTED) && getOriginalMessage(reportAction)?.workflow === CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL;
+}
+
 function isMarkAsClosedAction(reportAction: OnyxInputOrEntry<ReportAction>): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.CLOSED> {
     return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.CLOSED) && !!getOriginalMessage(reportAction)?.amount;
 }
@@ -235,6 +240,10 @@ function isForwardedAction(reportAction: OnyxInputOrEntry<ReportAction>): report
     return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.FORWARDED);
 }
 
+function isDynamicExternalWorkflowForwardedAction(reportAction: OnyxInputOrEntry<ReportAction>): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.FORWARDED> {
+    return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.FORWARDED) && getOriginalMessage(reportAction)?.workflow === CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL;
+}
+
 function isModifiedExpenseAction(reportAction: OnyxInputOrEntry<ReportAction>): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE> {
     return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE);
 }
@@ -1099,6 +1108,43 @@ function getFilteredReportActionsForReportView(actions: ReportAction[]) {
     return actions.filter(isVisiblePreviewOrMoneyRequest);
 }
 
+function getDynamicExternalWorkflowRoutedAction(
+    reportAction: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.SUBMITTED> | ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.FORWARDED>,
+): ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED> {
+    return {
+        reportActionID: `${reportAction.reportActionID}DEW`,
+        created: DateUtils.addMillisecondsFromDateTime(reportAction.created, 1),
+        actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED,
+        actorAccountID: CONST.ACCOUNT_ID.CONCIERGE,
+        message: [{html: 'DYNAMIC_EXTERNAL_WORKFLOW', type: 'COMMENT', text: ''}],
+        originalMessage: {
+            to: getOriginalMessage(reportAction)?.to ?? '',
+        },
+    };
+}
+
+function withDEWRoutedActionsArray(reportActions: ReportAction[]): ReportAction[] {
+    return reportActions.flatMap((reportAction) => {
+        if (isDynamicExternalWorkflowSubmitAction(reportAction) || isDynamicExternalWorkflowForwardedAction(reportAction)) {
+            return [reportAction, getDynamicExternalWorkflowRoutedAction(reportAction)];
+        }
+        return reportAction;
+    });
+}
+
+function withDEWRoutedActionsObject(reportActions: OnyxEntry<ReportActions>): OnyxEntry<ReportActions> {
+    return Object.entries(reportActions ?? {}).reduce((acc, value) => {
+        const [reportActionID, reportAction] = value;
+        acc[reportActionID] = reportAction;
+
+        if (isDynamicExternalWorkflowSubmitAction(reportAction) || isDynamicExternalWorkflowForwardedAction(reportAction)) {
+            const dynamicExternalWorkflowRoutedAction = getDynamicExternalWorkflowRoutedAction(reportAction);
+            acc[dynamicExternalWorkflowRoutedAction.reportActionID] = dynamicExternalWorkflowRoutedAction;
+        }
+        return acc;
+    }, {} as ReportActions);
+}
+
 /**
  * This method returns the report actions that are ready for display in the ReportActionsView.
  * The report actions need to be sorted by created timestamp first, and reportActionID second
@@ -1124,7 +1170,7 @@ function getSortedReportActionsForDisplay(
     }
 
     const baseURLAdjustedReportActions = filteredReportActions.map((reportAction) => replaceBaseURLInPolicyChangeLogAction(reportAction));
-    return getSortedReportActions(baseURLAdjustedReportActions, true);
+    return getSortedReportActions(withDEWRoutedActionsArray(baseURLAdjustedReportActions), true);
 }
 
 /**
@@ -1955,6 +2001,11 @@ function getReportActionMessageFragments(action: ReportAction): Message[] {
         return [{text: message, html: message, type: 'COMMENT'}];
     }
 
+    if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED)) {
+        const message = getDynamicExternalWorkflowRoutedMessage(action, translateLocal);
+        return [{text: message, html: `<muted-text>${message}</muted-text>`, type: 'COMMENT'}];
+    }
+
     const actionMessage = action.previousMessage ?? action.message;
     if (Array.isArray(actionMessage)) {
         return actionMessage.filter((item): item is Message => !!item);
@@ -3299,6 +3350,13 @@ function getChangedApproverActionMessage<T extends typeof CONST.REPORT.ACTIONS.T
     return translateLocal('iou.changeApprover.changedApproverMessage', {managerID: actorAccountID});
 }
 
+function getDynamicExternalWorkflowRoutedMessage(
+    action: OnyxEntry<ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED>>,
+    translate: LocaleContextProps['translate'],
+) {
+    return translate('iou.routedDueToDEW', {to: getOriginalMessage(action)!.to});
+}
+
 function isCardIssuedAction(
     reportAction: OnyxEntry<ReportAction>,
 ): reportAction is ReportAction<
@@ -3539,6 +3597,7 @@ export {
     getUpdatedApprovalRuleMessage,
     getRemovedFromApprovalChainMessage,
     getDemotedFromWorkspaceMessage,
+    getDynamicExternalWorkflowRoutedMessage,
     getReportAction,
     getReportActionHtml,
     getReportActionMessage,
@@ -3611,8 +3670,10 @@ export {
     isWhisperAction,
     isSubmittedAction,
     isSubmittedAndClosedAction,
+    isDynamicExternalWorkflowSubmitAction,
     isMarkAsClosedAction,
     isApprovedAction,
+    isDynamicExternalWorkflowForwardedAction,
     isUnapprovedAction,
     isForwardedAction,
     isWhisperActionTargetedToOthers,
@@ -3696,6 +3757,8 @@ export {
     filterOutDeprecatedReportActions,
     getActionableCardFraudAlertMessage,
     isSystemUserMentioned,
+    withDEWRoutedActionsArray,
+    withDEWRoutedActionsObject,
 };
 
 export type {LastVisibleMessage};
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 0fcd11e1aacc..48e8551c9902 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -10766,6 +10766,7 @@ function shouldDisableThread(reportAction: OnyxInputOrEntry<ReportAction>, repor
     const isReportPreviewActionLocal = isReportPreviewAction(reportAction);
     const isIOUAction = isMoneyRequestAction(reportAction);
     const isWhisperActionLocal = isWhisperAction(reportAction) || isActionableTrackExpense(reportAction);
+    const isDynamicWorkflowRoutedAction = isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED);
     const isActionDisabled = CONST.REPORT.ACTIONS.THREAD_DISABLED.some((action: string) => action === reportAction?.actionName);
 
     return (
@@ -10774,7 +10775,8 @@ function shouldDisableThread(reportAction: OnyxInputOrEntry<ReportAction>, repor
         (isDeletedActionLocal && !reportAction?.childVisibleActionCount) ||
         (isReportArchived && !reportAction?.childVisibleActionCount) ||
         (isWhisperActionLocal && !isReportPreviewActionLocal && !isIOUAction) ||
-        isThreadReportParentAction
+        isThreadReportParentAction ||
+        isDynamicWorkflowRoutedAction
     );
 }
 
diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx
index aba61908fd89..879c416a9d52 100755
--- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx
+++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx
@@ -25,7 +25,7 @@ import useStyleUtils from '@hooks/useStyleUtils';
 import useTransactionsAndViolationsForReport from '@hooks/useTransactionsAndViolationsForReport';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {getMovedReportID} from '@libs/ModifiedExpenseMessage';
-import {getLinkedTransactionID, getOneTransactionThreadReportID, getOriginalMessage, getReportAction, isDeletedAction} from '@libs/ReportActionsUtils';
+import {getLinkedTransactionID, getOneTransactionThreadReportID, getOriginalMessage, getReportAction, isDeletedAction, withDEWRoutedActionsObject} from '@libs/ReportActionsUtils';
 import {
     chatIncludesChronosWithID,
     getSourceIDFromReportAction,
@@ -162,6 +162,7 @@ function BaseReportActionContextMenu({
     const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${originalReportID}`, {
         canBeMissing: true,
         canEvict: false,
+        selector: withDEWRoutedActionsObject,
     });
 
     const reportAction: OnyxEntry<ReportAction> = useMemo(() => {
diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx
index 2aee575bc8f0..b5ca5558a550 100644
--- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx
+++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx
@@ -31,6 +31,7 @@ import {
     getChangedApproverActionMessage,
     getDefaultApproverUpdateMessage,
     getDeletedApprovalRuleMessage,
+    getDynamicExternalWorkflowRoutedMessage,
     getExportIntegrationMessageHTML,
     getForwardsToUpdateMessage,
     getIntegrationSyncFailedMessage,
@@ -280,7 +281,10 @@ type ContextMenuAction = (ContextMenuActionWithContent | ContextMenuActionWithIc
 const ContextMenuActions: ContextMenuAction[] = [
     {
         isAnonymousAction: false,
-        shouldShow: ({type, reportAction}) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && !!reportAction && 'message' in reportAction && !isMessageDeleted(reportAction),
+        shouldShow: ({type, reportAction}) => {
+            const isDynamicWorkflowRoutedAction = isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED);
+            return type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && !!reportAction && 'message' in reportAction && !isMessageDeleted(reportAction) && !isDynamicWorkflowRoutedAction;
+        },
         renderContent: (closePopover, {reportID, reportAction, close: closeManually, openContextMenu, setIsEmojiPickerActive}) => {
             const isMini = !closePopover;
 
@@ -361,7 +365,10 @@ const ContextMenuActions: ContextMenuAction[] = [
         textTranslateKey: 'reportActionContextMenu.markAsUnread',
         icon: 'ChatBubbleUnread',
         successIcon: 'Checkmark',
-        shouldShow: ({type, isUnreadChat}) => type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION || (type === CONST.CONTEXT_MENU_TYPES.REPORT && !isUnreadChat),
+        shouldShow: ({type, reportAction, isUnreadChat}) => {
+            const isDynamicWorkflowRoutedAction = isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED);
+            return (type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && !isDynamicWorkflowRoutedAction) || (type === CONST.CONTEXT_MENU_TYPES.REPORT && !isUnreadChat);
+        },
         onPress: (closePopover, {reportAction, reportID}) => {
             markCommentAsUnread(reportID, reportAction);
             if (closePopover) {
@@ -479,13 +486,16 @@ const ContextMenuActions: ContextMenuAction[] = [
             const isWhisperAction = isWhisperActionReportActionsUtils(reportAction) || isActionableTrackExpense(reportAction);
             const isExpenseReportAction = isMoneyRequestAction(reportAction) || isReportPreviewActionReportActionsUtils(reportAction);
             const isTaskAction = isCreatedTaskReportAction(reportAction);
+            const isDynamicWorkflowRoutedAction = isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED);
+
             return (
                 !subscribed &&
                 !isWhisperAction &&
                 !isTaskAction &&
                 !isExpenseReportAction &&
                 !isThreadReportParentAction &&
-                (shouldDisplayThreadReplies || (!isDeletedAction && !isArchivedRoom))
+                (shouldDisplayThreadReplies || (!isDeletedAction && !isArchivedRoom)) &&
+                !isDynamicWorkflowRoutedAction
             );
         },
         onPress: (closePopover, {reportAction, reportID}) => {
@@ -839,6 +849,8 @@ const ContextMenuActions: ContextMenuAction[] = [
                 } else if (isActionableJoinRequest(reportAction)) {
                     const displayMessage = getJoinRequestMessage(reportAction);
                     Clipboard.setString(displayMessage);
+                } else if (isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED)) {
+                    setClipboardMessage(getDynamicExternalWorkflowRoutedMessage(reportAction, translate));
                 } else if (content) {
                     setClipboardMessage(
                         content.replaceAll(/(<mention-user>)(.*?)(<\/mention-user>)/gi, (match, openTag: string, innerContent: string, closeTag: string): string => {
@@ -868,7 +880,8 @@ const ContextMenuActions: ContextMenuAction[] = [
 
             // Only hide the copy link menu item when context menu is opened over img element.
             const isAttachmentTarget = menuTarget?.current && 'tagName' in menuTarget.current && menuTarget?.current.tagName === 'IMG' && isAttachment;
-            return type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && !isAttachmentTarget && !isMessageDeleted(reportAction);
+            const isDynamicWorkflowRoutedAction = isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED);
+            return type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && !isAttachmentTarget && !isMessageDeleted(reportAction) && !isDynamicWorkflowRoutedAction;
         },
         onPress: (closePopover, {reportAction, reportID}) => {
             const originalReportID = getOriginalReportID(reportID, reportAction);
diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts
index 63d2a6d5e112..a2342b9f7fd0 100644
--- a/src/types/onyx/OriginalMessage.ts
+++ b/src/types/onyx/OriginalMessage.ts
@@ -235,6 +235,9 @@ type OriginalMessageSubmitted = {
 
     /** Carbon copy list */
     cc?: string;
+
+    /** The workflow the report is submitted on */
+    workflow: ValueOf<typeof CONST.POLICY.APPROVAL_MODE>;
 };
 
 /** Model of `created` report action */
@@ -828,6 +831,11 @@ type OriginalMessageDismissedViolation = {
     violationName: string;
 };
 
+type OriginalMessageDynamicExternalWorkflowRouted = {
+    /** The approver of the report is submitted to */
+    to: string;
+};
+
 /** Model of `marked reimbursed` report action */
 type OriginalMessageMarkedReimbursed = {
     /** Whether this action was created from NewDot */
@@ -883,6 +891,12 @@ type OriginalMessageForwarded = {
 
     /** Report ID of the expense */
     expenseReportID: string;
+
+    /** The login the approver who is acting on behalf of the vacationer */
+    to?: string;
+
+    /** The workflow the report is approved on */
+    workflow: ValueOf<typeof CONST.POLICY.APPROVAL_MODE>;
 };
 
 /**
@@ -1064,6 +1078,7 @@ type OriginalMessageMap = {
     [CONST.REPORT.ACTIONS.TYPE.CLOSED]: OriginalMessageClosed;
     [CONST.REPORT.ACTIONS.TYPE.CREATED]: OriginalMessageCreated;
     [CONST.REPORT.ACTIONS.TYPE.DISMISSED_VIOLATION]: OriginalMessageDismissedViolation;
+    [CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED]: OriginalMessageDynamicExternalWorkflowRouted;
     [CONST.REPORT.ACTIONS.TYPE.EXPENSIFY_CARD_SYSTEM_MESSAGE]: never;
     [CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_CSV]: never;
     [CONST.REPORT.ACTIONS.TYPE.EXPORTED_TO_INTEGRATION]: OriginalMessageExportIntegration;
diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx
index 36405fddcf14..c83d4f3af344 100644
--- a/tests/unit/OptionsListUtilsTest.tsx
+++ b/tests/unit/OptionsListUtilsTest.tsx
@@ -36,7 +36,7 @@ import {
     sortAlphabetically,
 } from '@libs/OptionsListUtils';
 import Parser from '@libs/Parser';
-import {getChangedApproverActionMessage} from '@libs/ReportActionsUtils';
+import {getChangedApproverActionMessage, getDynamicExternalWorkflowRoutedMessage} from '@libs/ReportActionsUtils';
 import {
     canCreateTaskInReport,
     canUserPerformWriteAction,
@@ -57,7 +57,7 @@ import createRandomReportAction from '../utils/collections/reportActions';
 import {createRandomReport, createRegularChat} from '../utils/collections/reports';
 import createRandomTransaction from '../utils/collections/transaction';
 import {getFakeAdvancedReportAction} from '../utils/LHNTestUtils';
-import {getNvpDismissedProductTraining, localeCompare} from '../utils/TestHelper';
+import {getNvpDismissedProductTraining, localeCompare, translateLocal} from '../utils/TestHelper';
 import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
 
 jest.mock('@rnmapbox/maps', () => {
@@ -2803,6 +2803,26 @@ describe('OptionsListUtils', () => {
             const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false});
             expect(lastMessage).toBe(Parser.htmlToText(getMovedActionMessage(movedAction, report)));
         });
+        it('DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action', async () => {
+            // Given a DYNAMIC_EXTERNAL_WORKFLOW_ROUTED as the last action
+            const report: Report = createRandomReport(0, undefined);
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED> = {
+                reportActionID: '1',
+                created: '',
+                actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED,
+                message: [{type: 'COMMENT', text: ''}],
+                originalMessage: {to: 'example@gmail.com'},
+            };
+            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, {
+                [action.reportActionID]: action,
+            });
+
+            // When getting the last message text for the report
+            const lastMessage = getLastMessageTextForReport({report, lastActorDetails: null, isReportArchived: false});
+
+            // Then it should return the DYNAMIC_EXTERNAL_WORKFLOW_ROUTED message
+            expect(lastMessage).toBe(Parser.htmlToText(getDynamicExternalWorkflowRoutedMessage(action, translateLocal)));
+        });
         it('should return last visible message text when last action is hidden (e.g. whisper)', async () => {
             const report: Report = {
                 ...createRandomReport(0, undefined),
diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts
index 14e476617b78..ffbfb8f349ab 100644
--- a/tests/unit/ReportActionsUtilsTest.ts
+++ b/tests/unit/ReportActionsUtilsTest.ts
@@ -9,7 +9,7 @@ import CONST from '../../src/CONST';
 import * as ReportActionsUtils from '../../src/libs/ReportActionsUtils';
 import {getCardIssuedMessage, getOneTransactionThreadReportID, getOriginalMessage, getSendMoneyFlowAction, isIOUActionMatchingTransactionList} from '../../src/libs/ReportActionsUtils';
 import ONYXKEYS from '../../src/ONYXKEYS';
-import type {Card, OriginalMessageIOU, Report, ReportAction} from '../../src/types/onyx';
+import type {Card, OriginalMessageIOU, Report, ReportAction, ReportActions} from '../../src/types/onyx';
 import createRandomReportAction from '../utils/collections/reportActions';
 import {createRandomReport} from '../utils/collections/reports';
 import * as LHNTestUtils from '../utils/LHNTestUtils';
@@ -1041,6 +1041,26 @@ describe('ReportActionsUtils', () => {
             const expectedFragments = ReportActionsUtils.getReportActionMessageFragments(action);
             expect(expectedFragments).toEqual([{text: expectedMessage, html: `<muted-text>${expectedMessage}</muted-text>`, type: 'COMMENT'}]);
         });
+
+        it('should return the correct fragment for the DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action', () => {
+            // Given a DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED> = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED,
+                reportActionID: '1',
+                created: '1',
+                message: [],
+                originalMessage: {
+                    to: 'example@gmail.com',
+                },
+            };
+
+            // When getting the message fragments of the action
+            const expectedMessage = ReportActionsUtils.getDynamicExternalWorkflowRoutedMessage(action, translateLocal);
+            const expectedFragments = ReportActionsUtils.getReportActionMessageFragments(action);
+
+            // Then it should return the correct message fragments
+            expect(expectedFragments).toEqual([{text: expectedMessage, html: `<muted-text>${expectedMessage}</muted-text>`, type: 'COMMENT'}]);
+        });
     });
 
     describe('getSendMoneyFlowAction', () => {
@@ -1522,4 +1542,300 @@ describe('ReportActionsUtils', () => {
             expect(ReportActionsUtils.isDeletedAction(action)).toBe(false);
         });
     });
+
+    describe('isDynamicExternalWorkflowSubmitAction', () => {
+        it('should return true for SUBMITTED action if workflow is DYNAMICEXTERNAL', () => {
+            // Given a report action with SUBMITTED action type and workflow is DYNAMICEXTERNAL
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.SUBMITTED> = {
+                ...createRandomReportAction(0),
+                actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
+                created: '2025-11-21',
+                previousMessage: [],
+                message: [],
+                originalMessage: {
+                    workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL,
+                    amount: 1,
+                    currency: CONST.CURRENCY.USD,
+                },
+            };
+
+            // When checking if the action is a DEW submit action
+            const result = ReportActionsUtils.isDynamicExternalWorkflowSubmitAction(action);
+
+            // Then it should return true
+            expect(result).toBe(true);
+        });
+
+        it('should return false for SUBMITTED action if workflow is not DYNAMICEXTERNAL', () => {
+            // Given a report action with SUBMITTED action type and workflow is not DYNAMICEXTERNAL
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.SUBMITTED> = {
+                ...createRandomReportAction(0),
+                actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
+                created: '2025-11-21',
+                previousMessage: [],
+                message: [],
+                originalMessage: {
+                    workflow: CONST.POLICY.APPROVAL_MODE.BASIC,
+                    amount: 1,
+                    currency: CONST.CURRENCY.USD,
+                },
+            };
+
+            // When checking if the action is a DEW submit action
+            const result = ReportActionsUtils.isDynamicExternalWorkflowSubmitAction(action);
+
+            // Then it should return false
+            expect(result).toBe(false);
+        });
+
+        it('should return false for non SUBMITTED action', () => {
+            // Given a report action with non SUBMITTED action type
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.APPROVED> = {
+                ...createRandomReportAction(0),
+                actionName: CONST.REPORT.ACTIONS.TYPE.APPROVED,
+                created: '2025-11-21',
+                previousMessage: [],
+                message: [],
+                originalMessage: {
+                    expenseReportID: '1',
+                    amount: 1,
+                    currency: CONST.CURRENCY.USD,
+                },
+            };
+
+            // When checking if the action is a DEW submit action
+            const result = ReportActionsUtils.isDynamicExternalWorkflowSubmitAction(action);
+
+            // Then it should return false
+            expect(result).toBe(false);
+        });
+    });
+
+    describe('isDynamicExternalWorkflowForwardedAction', () => {
+        it('should return true for FORWARDED action if workflow is DYNAMICEXTERNAL', () => {
+            // Given a report action with FORWARDED action type and workflow is DYNAMICEXTERNAL
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.FORWARDED> = {
+                ...createRandomReportAction(0),
+                actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED,
+                created: '2025-11-21',
+                previousMessage: [],
+                message: [],
+                originalMessage: {
+                    workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL,
+                    expenseReportID: '1',
+                    amount: 1,
+                    currency: CONST.CURRENCY.USD,
+                },
+            };
+
+            // When checking if the action is a DEW forwarded action
+            const result = ReportActionsUtils.isDynamicExternalWorkflowForwardedAction(action);
+
+            // Then it should return true
+            expect(result).toBe(true);
+        });
+
+        it('should return false for FORWARDED action if workflow is not DYNAMICEXTERNAL', () => {
+            // Given a report action with FORWARDED action type and workflow is not DYNAMICEXTERNAL
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.FORWARDED> = {
+                ...createRandomReportAction(0),
+                actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED,
+                created: '2025-11-21',
+                previousMessage: [],
+                message: [],
+                originalMessage: {
+                    workflow: CONST.POLICY.APPROVAL_MODE.BASIC,
+                    expenseReportID: '1',
+                    amount: 1,
+                    currency: CONST.CURRENCY.USD,
+                },
+            };
+
+            // When checking if the action is a DEW forwarded action
+            const result = ReportActionsUtils.isDynamicExternalWorkflowForwardedAction(action);
+
+            // Then it should return false
+            expect(result).toBe(false);
+        });
+
+        it('should return false for non FORWARDED action', () => {
+            // Given a report action with non FORWARDED action type
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.APPROVED> = {
+                ...createRandomReportAction(0),
+                actionName: CONST.REPORT.ACTIONS.TYPE.APPROVED,
+                created: '2025-11-21',
+                previousMessage: [],
+                message: [],
+                originalMessage: {
+                    expenseReportID: '1',
+                    amount: 1,
+                    currency: CONST.CURRENCY.USD,
+                },
+            };
+
+            // When checking if the action is a DEW forwarded action
+            const result = ReportActionsUtils.isDynamicExternalWorkflowForwardedAction(action);
+
+            // Then it should return false
+            expect(result).toBe(false);
+        });
+    });
+
+    describe('withDEWRoutedActionsArray', () => {
+        it('should add a DEW routed action for each DEW SUBMITTED and FORWARDED action', () => {
+            // Given a report actions array with DEW SUBMITTED and FORWARDED actions
+            const reportActions: ReportAction[] = [
+                {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
+                {
+                    actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
+                    created: '',
+                    reportActionID: '2',
+                    originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example@gmail.com'},
+                },
+                {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'},
+                {
+                    actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED,
+                    created: '',
+                    reportActionID: '4',
+                    originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example2@gmail.com'},
+                },
+            ];
+
+            // When extending the array with DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action
+            const expected: Partial<ReportAction>[] = [
+                {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
+                {
+                    actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
+                    created: '',
+                    reportActionID: '2',
+                    originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example@gmail.com'},
+                },
+                {actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, reportActionID: '2DEW', originalMessage: {to: 'example@gmail.com'}},
+                {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'},
+                {
+                    actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED,
+                    created: '',
+                    reportActionID: '4',
+                    originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example2@gmail.com'},
+                },
+                {actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, reportActionID: '4DEW', originalMessage: {to: 'example2@gmail.com'}},
+            ];
+            const actual = ReportActionsUtils.withDEWRoutedActionsArray(reportActions);
+
+            // Then DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action should be added for each SUBMITTED and FORWARDED actions to the array
+            expected.forEach((e, i) => {
+                expect(actual[i]).toEqual(expect.objectContaining(e));
+            });
+        });
+
+        it(`should not add a DEW routed action if we don't have DEW SUBMITTED or FORWARDED action`, () => {
+            // Given a report actions array with no DEW SUBMITTED or FORWARDED actions
+            const reportActions: ReportAction[] = [
+                {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
+                {actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED, created: '', reportActionID: '2'},
+                {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'},
+                {actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED, created: '', reportActionID: '4'},
+            ];
+
+            // When extending the array with DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action
+            const expected: ReportAction[] = [
+                {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
+                {actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED, created: '', reportActionID: '2'},
+                {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'},
+                {actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED, created: '', reportActionID: '4'},
+            ];
+            const actual = ReportActionsUtils.withDEWRoutedActionsArray(reportActions);
+
+            // Then no DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action should be added to the array
+            expect(actual).toEqual(expected);
+        });
+    });
+
+    describe('withDEWRoutedActionsObject', () => {
+        it('should add a DEW routed action for each DEW SUBMITTED and FORWARDED action', () => {
+            // Given a report actions collection with DEW SUBMITTED and FORWARDED actions
+            const reportActions: ReportActions = {
+                1: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
+                2: {
+                    actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
+                    created: '',
+                    reportActionID: '2',
+                    originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example@gmail.com'},
+                },
+                3: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'},
+                4: {
+                    actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED,
+                    created: '',
+                    reportActionID: '4',
+                    originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example2@gmail.com'},
+                },
+            };
+
+            // When extending the collection with DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action
+            const expected: ReportActions = {
+                1: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
+                2: {
+                    actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
+                    created: '',
+                    reportActionID: '2',
+                    originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example@gmail.com'},
+                },
+                '2DEW': {actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, reportActionID: '2DEW', originalMessage: {to: 'example@gmail.com'}} as ReportAction,
+                3: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'},
+                4: {
+                    actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED,
+                    created: '',
+                    reportActionID: '4',
+                    originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example2@gmail.com'},
+                },
+                '4DEW': {actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, reportActionID: '4DEW', originalMessage: {to: 'example2@gmail.com'}} as ReportAction,
+            };
+            const actual = ReportActionsUtils.withDEWRoutedActionsObject(reportActions);
+
+            // Then DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action should be added for each SUBMITTED and FORWARDED actions to the collection
+            expect(actual).toMatchObject(expected);
+        });
+
+        it(`should not add a DEW routed action if we don't have DEW SUBMITTED or FORWARDED action`, () => {
+            // Given a report actions collection with no DEW SUBMITTED or FORWARDED actions
+            const reportActions: ReportActions = {
+                1: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
+                2: {actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED, created: '', reportActionID: '2'},
+                3: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'},
+                4: {actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED, created: '', reportActionID: '4'},
+            };
+
+            // When extending the collection with DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action
+            const expected: ReportActions = {
+                1: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
+                2: {actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED, created: '', reportActionID: '2'},
+                3: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'},
+                4: {actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED, created: '', reportActionID: '4'},
+            };
+            const actual = ReportActionsUtils.withDEWRoutedActionsObject(reportActions);
+
+            // Then no DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action should be added to the collection
+            expect(actual).toEqual(expected);
+        });
+    });
+
+    describe('getDynamicExternalWorkflowRoutedMessage', () => {
+        it('should return the routed message', () => {
+            // Given a DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action
+            const to = 'example@gmail.com';
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED> = {
+                reportActionID: '1',
+                actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED,
+                created: '',
+                originalMessage: {to},
+            };
+
+            // When getting the DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action message
+            const actual = ReportActionsUtils.getDynamicExternalWorkflowRoutedMessage(action, translateLocal);
+
+            // Then it should return the routed due to DEW message with the correct "to" value
+            const expected = translateLocal('iou.routedDueToDEW', {to});
+            expect(actual).toBe(expected);
+        });
+    });
 });
diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts
index b1b8b70312d1..99ad554df7d0 100644
--- a/tests/unit/ReportUtilsTest.ts
+++ b/tests/unit/ReportUtilsTest.ts
@@ -3355,6 +3355,13 @@ describe('ReportUtils', () => {
             expect(shouldDisableThread(reportAction, reportID, true)).toBeTruthy();
         });
 
+        it('should disable on a DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action', () => {
+            const reportAction = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED,
+            } as ReportAction;
+            expect(shouldDisableThread(reportAction, reportID, true)).toBeTruthy();
+        });
+
         describe('deleted threads', () => {
             it('should be enabled if the report action is not-deleted and child visible action count is 1', () => {
                 // Given a normal report action with one child visible action count

From a0a912a7f6465d2fbb82c0101e27832e9b4f78c3 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Sun, 14 Dec 2025 23:54:39 +0800
Subject: [PATCH 02/13] remove log

---
 src/libs/OptionsListUtils/index.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index b0bd4cdb937f..36a62bb909ef 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -617,7 +617,6 @@ function getLastMessageTextForReport({
     const reportID = report?.reportID;
     const lastReportAction = reportID ? lastVisibleReportActions[reportID] : undefined;
     const lastVisibleMessage = getLastVisibleMessage(report?.reportID);
-    console.log('last action', lastReportAction);
 
     // some types of actions are filtered out for lastReportAction, in some cases we need to check the actual last action
     const lastOriginalReportAction = reportID ? lastReportActions[reportID] : undefined;

From 7ef0b5cbc8b23df103de697529ac42c34ab24dc8 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Sun, 14 Dec 2025 23:57:20 +0800
Subject: [PATCH 03/13] add missing param

---
 src/languages/de.ts      | 3 ++-
 src/languages/es.ts      | 4 ++--
 src/languages/fr.ts      | 3 ++-
 src/languages/it.ts      | 3 ++-
 src/languages/ja.ts      | 3 ++-
 src/languages/nl.ts      | 3 ++-
 src/languages/pl.ts      | 3 ++-
 src/languages/pt-BR.ts   | 3 ++-
 src/languages/zh-hans.ts | 3 ++-
 9 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index d34d232c9d87..58e65a8add62 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -206,6 +206,7 @@ import type {
     RoleNamesParams,
     RoomNameReservedErrorParams,
     RoomRenamedToParams,
+    RoutedDueToDEWParams,
     RulesEnableWorkflowsParams,
     SecondaryLoginParams,
     SetTheDistanceMerchantParams,
@@ -1570,7 +1571,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Arbeitsbereich auswählen',
-        routedDueToDEW: ({to}) => `bericht aufgrund eines benutzerdefinierten Genehmigungsworkflows an ${to} weitergeleitet`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `bericht aufgrund eines benutzerdefinierten Genehmigungsworkflows an ${to} weitergeleitet`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 63278622b9ae..f30c985a2997 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2,7 +2,7 @@ import {CONST as COMMON_CONST} from 'expensify-common';
 import dedent from '@libs/StringUtils/dedent';
 import CONST from '@src/CONST';
 import type en from './en';
-import type {BeginningOfChatHistoryParams, TagSelectionParams, ViolationsRterParams} from './params';
+import type {BeginningOfChatHistoryParams, RoutedDueToDEWParams, TagSelectionParams, ViolationsRterParams} from './params';
 import type {TranslationDeepObject} from './types';
 
 /* eslint-disable max-len */
@@ -1172,7 +1172,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Elige un espacio de trabajo',
-        routedDueToDEW: ({to}) => `informe enviado a ${to} debido a un flujo de aprobación personalizado`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `informe enviado a ${to} debido a un flujo de aprobación personalizado`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 84ca446a1479..37a6d1961612 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -206,6 +206,7 @@ import type {
     RoleNamesParams,
     RoomNameReservedErrorParams,
     RoomRenamedToParams,
+    RoutedDueToDEWParams,
     RulesEnableWorkflowsParams,
     SecondaryLoginParams,
     SetTheDistanceMerchantParams,
@@ -1571,7 +1572,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Choisir un espace de travail',
-        routedDueToDEW: ({to}) => `rapport acheminé vers ${to} en raison d'un workflow d'approbation personnalisé`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `rapport acheminé vers ${to} en raison d'un workflow d'approbation personnalisé`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 651053ed9876..1a9eb378db14 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -206,6 +206,7 @@ import type {
     RoleNamesParams,
     RoomNameReservedErrorParams,
     RoomRenamedToParams,
+    RoutedDueToDEWParams,
     RulesEnableWorkflowsParams,
     SecondaryLoginParams,
     SetTheDistanceMerchantParams,
@@ -1566,7 +1567,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Scegli uno spazio di lavoro',
-        routedDueToDEW: ({to}) => `rapporto inoltrato a ${to} a causa del flusso di lavoro di approvazione personalizzato`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `rapporto inoltrato a ${to} a causa del flusso di lavoro di approvazione personalizzato`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 8ba3b56452b2..7b783896a0c3 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -206,6 +206,7 @@ import type {
     RoleNamesParams,
     RoomNameReservedErrorParams,
     RoomRenamedToParams,
+    RoutedDueToDEWParams,
     RulesEnableWorkflowsParams,
     SecondaryLoginParams,
     SetTheDistanceMerchantParams,
@@ -1567,7 +1568,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'ワークスペースを選択',
-        routedDueToDEW: ({to}) => `カスタム承認ワークフローにより、${to} 宛にルーティングされたレポート`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `カスタム承認ワークフローにより、${to} 宛にルーティングされたレポート`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 8ffd2be2a075..d1cd8dbdeeff 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -206,6 +206,7 @@ import type {
     RoleNamesParams,
     RoomNameReservedErrorParams,
     RoomRenamedToParams,
+    RoutedDueToDEWParams,
     RulesEnableWorkflowsParams,
     SecondaryLoginParams,
     SetTheDistanceMerchantParams,
@@ -1564,7 +1565,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Kies een workspace',
-        routedDueToDEW: ({to}) => `rapport doorgestuurd naar ${to} vanwege aangepaste goedkeuringsworkflow`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `rapport doorgestuurd naar ${to} vanwege aangepaste goedkeuringsworkflow`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 926a6dd73d12..e78b7e5686ca 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -206,6 +206,7 @@ import type {
     RoleNamesParams,
     RoomNameReservedErrorParams,
     RoomRenamedToParams,
+    RoutedDueToDEWParams,
     RulesEnableWorkflowsParams,
     SecondaryLoginParams,
     SetTheDistanceMerchantParams,
@@ -1563,7 +1564,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Wybierz przestrzeń roboczą',
-        routedDueToDEW: ({to}) => `raport przekazany do ${to} z powodu niestandardowego procesu zatwierdzania`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `raport przekazany do ${to} z powodu niestandardowego procesu zatwierdzania`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 579779fbbedc..5fe1645742f0 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -206,6 +206,7 @@ import type {
     RoleNamesParams,
     RoomNameReservedErrorParams,
     RoomRenamedToParams,
+    RoutedDueToDEWParams,
     RulesEnableWorkflowsParams,
     SecondaryLoginParams,
     SetTheDistanceMerchantParams,
@@ -1562,7 +1563,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: 'Escolha um workspace',
-        routedDueToDEW: ({to}) => `relatório encaminhado para ${to} devido ao fluxo de trabalho de aprovação personalizado`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `relatório encaminhado para ${to} devido ao fluxo de trabalho de aprovação personalizado`,
     },
     transactionMerge: {
         listPage: {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 81581e755c7c..4b356f4ee8d6 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -206,6 +206,7 @@ import type {
     RoleNamesParams,
     RoomNameReservedErrorParams,
     RoomRenamedToParams,
+    RoutedDueToDEWParams,
     RulesEnableWorkflowsParams,
     SecondaryLoginParams,
     SetTheDistanceMerchantParams,
@@ -1541,7 +1542,7 @@ const translations: TranslationDeepObject<typeof en> = {
             },
         },
         chooseWorkspace: '选择一个工作区',
-        routedDueToDEW: ({to}) => `报告因自定义审批工作流而转发至 ${to}`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `报告因自定义审批工作流而转发至 ${to}`,
     },
     transactionMerge: {
         listPage: {

From fb158b874fc33f883e38c84bca73e81ca086237e Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Mon, 15 Dec 2025 14:23:23 +0800
Subject: [PATCH 04/13] lint

---
 src/libs/OptionsListUtils/index.ts   |  2 +-
 src/libs/ReportActionsUtils.ts       |  3 +-
 src/libs/ReportUtils.ts              |  9 ++-
 src/libs/actions/IOU.ts              |  8 ++-
 src/types/onyx/OriginalMessage.ts    |  1 +
 tests/unit/ReportActionsUtilsTest.ts | 92 +++++++++++++++-------------
 tests/unit/SidebarUtilsTest.ts       |  1 +
 7 files changed, 70 insertions(+), 46 deletions(-)

diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index 36a62bb909ef..57347dc8ebc4 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -54,7 +54,6 @@ import {
     getRetractedMessage,
     getRoomAvatarUpdatedMessage,
     getRoomChangeLogMessage,
-    getSortedReportActions,
     getSortedReportActionsForDisplay,
     getTravelUpdateMessage,
     getUpdateRoomDescriptionMessage,
@@ -790,6 +789,7 @@ function getLastMessageTextForReport({
     } else if (isActionableMentionWhisper(lastReportAction)) {
         lastMessageTextFromReport = Parser.htmlToText(getActionableMentionWhisperMessage(lastReportAction));
     } else if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED)) {
+        // eslint-disable-next-line @typescript-eslint/no-deprecated
         lastMessageTextFromReport = getDynamicExternalWorkflowRoutedMessage(lastReportAction, translateLocal);
     }
 
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index 7c8c815c79cf..745129a240ef 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -2006,6 +2006,7 @@ function getReportActionMessageFragments(action: ReportAction): Message[] {
     }
 
     if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED)) {
+        // eslint-disable-next-line @typescript-eslint/no-deprecated
         const message = getDynamicExternalWorkflowRoutedMessage(action, translateLocal);
         return [{text: message, html: `<muted-text>${message}</muted-text>`, type: 'COMMENT'}];
     }
@@ -3358,7 +3359,7 @@ function getDynamicExternalWorkflowRoutedMessage(
     action: OnyxEntry<ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED>>,
     translate: LocaleContextProps['translate'],
 ) {
-    return translate('iou.routedDueToDEW', {to: getOriginalMessage(action)!.to});
+    return translate('iou.routedDueToDEW', {to: getOriginalMessage(action)?.to ?? ''});
 }
 
 function isCardIssuedAction(
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index d06ee2e5f957..b77e7d26268e 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -7543,11 +7543,18 @@ function buildOptimisticUnreportedTransactionAction(transactionThreadReportID: s
  * Builds an optimistic SUBMITTED report action with a randomly generated reportActionID.
  *
  */
-function buildOptimisticSubmittedReportAction(amount: number, currency: string, expenseReportID: string, adminAccountID: number | undefined): OptimisticSubmittedReportAction {
+function buildOptimisticSubmittedReportAction(
+    amount: number,
+    currency: string,
+    expenseReportID: string,
+    adminAccountID: number | undefined,
+    workflow: ValueOf<typeof CONST.POLICY.APPROVAL_MODE>,
+): OptimisticSubmittedReportAction {
     const originalMessage = {
         amount,
         currency,
         expenseReportID,
+        workflow,
     };
 
     const delegateAccountDetails = getPersonalDetailByEmail(delegateEmail);
diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts
index 3456d99b66ed..3f92cbce644d 100644
--- a/src/libs/actions/IOU.ts
+++ b/src/libs/actions/IOU.ts
@@ -11493,7 +11493,13 @@ function submitReport(
     const isCurrentUserManager = currentUserAccountIDParam === expenseReport.managerID;
     const isSubmitAndClosePolicy = isSubmitAndClose(policy);
     const adminAccountID = policy?.role === CONST.POLICY.ROLE.ADMIN ? currentUserAccountIDParam : undefined;
-    const optimisticSubmittedReportAction = buildOptimisticSubmittedReportAction(expenseReport?.total ?? 0, expenseReport.currency ?? '', expenseReport.reportID, adminAccountID);
+    const optimisticSubmittedReportAction = buildOptimisticSubmittedReportAction(
+        expenseReport?.total ?? 0,
+        expenseReport.currency ?? '',
+        expenseReport.reportID,
+        adminAccountID,
+        policy?.approvalMode,
+    );
 
     // buildOptimisticNextStep is used in parallel
     // eslint-disable-next-line @typescript-eslint/no-deprecated
diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts
index a2342b9f7fd0..bb6feefb5039 100644
--- a/src/types/onyx/OriginalMessage.ts
+++ b/src/types/onyx/OriginalMessage.ts
@@ -831,6 +831,7 @@ type OriginalMessageDismissedViolation = {
     violationName: string;
 };
 
+/** Model of DYNAMIC_EXTERNAL_WORKFLOW_ROUTED report action */
 type OriginalMessageDynamicExternalWorkflowRouted = {
     /** The approver of the report is submitted to */
     to: string;
diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts
index 175870d189df..42e966761a25 100644
--- a/tests/unit/ReportActionsUtilsTest.ts
+++ b/tests/unit/ReportActionsUtilsTest.ts
@@ -1711,7 +1711,7 @@ describe('ReportActionsUtils', () => {
             ];
 
             // When extending the array with DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action
-            const expected: Partial<ReportAction>[] = [
+            const expected: Array<Partial<ReportAction>> = [
                 {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
                 {
                     actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
@@ -1732,9 +1732,9 @@ describe('ReportActionsUtils', () => {
             const actual = ReportActionsUtils.withDEWRoutedActionsArray(reportActions);
 
             // Then DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action should be added for each SUBMITTED and FORWARDED actions to the array
-            expected.forEach((e, i) => {
-                expect(actual[i]).toEqual(expect.objectContaining(e));
-            });
+            for (let i = 0; i < expected.length; i++) {
+                expect(actual.at(i)).toEqual(expect.objectContaining(expected.at(i)));
+            }
         });
 
         it(`should not add a DEW routed action if we don't have DEW SUBMITTED or FORWARDED action`, () => {
@@ -1763,41 +1763,45 @@ describe('ReportActionsUtils', () => {
     describe('withDEWRoutedActionsObject', () => {
         it('should add a DEW routed action for each DEW SUBMITTED and FORWARDED action', () => {
             // Given a report actions collection with DEW SUBMITTED and FORWARDED actions
+            const firstAction = {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'};
+            const secondAction = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
+                created: '',
+                reportActionID: '2',
+                originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example@gmail.com'},
+            };
+            const thirdAction = {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'};
+            const fourthAction = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED,
+                created: '',
+                reportActionID: '4',
+                originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example2@gmail.com'},
+            };
             const reportActions: ReportActions = {
-                1: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
-                2: {
-                    actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
-                    created: '',
-                    reportActionID: '2',
-                    originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example@gmail.com'},
-                },
-                3: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'},
-                4: {
-                    actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED,
-                    created: '',
-                    reportActionID: '4',
-                    originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example2@gmail.com'},
-                },
+                [firstAction.reportActionID]: firstAction,
+                [secondAction.reportActionID]: secondAction,
+                [thirdAction.reportActionID]: thirdAction,
+                [fourthAction.reportActionID]: fourthAction,
             };
 
             // When extending the collection with DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action
+            const secondDEWAction = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED,
+                reportActionID: '2DEW',
+                originalMessage: {to: 'example@gmail.com'},
+            } as ReportAction;
+            const fourthDEWAction = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED,
+                reportActionID: '4DEW',
+                originalMessage: {to: 'example2@gmail.com'},
+            } as ReportAction;
             const expected: ReportActions = {
-                1: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
-                2: {
-                    actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
-                    created: '',
-                    reportActionID: '2',
-                    originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example@gmail.com'},
-                },
-                '2DEW': {actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, reportActionID: '2DEW', originalMessage: {to: 'example@gmail.com'}} as ReportAction,
-                3: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'},
-                4: {
-                    actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED,
-                    created: '',
-                    reportActionID: '4',
-                    originalMessage: {workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL, to: 'example2@gmail.com'},
-                },
-                '4DEW': {actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, reportActionID: '4DEW', originalMessage: {to: 'example2@gmail.com'}} as ReportAction,
+                [firstAction.reportActionID]: firstAction,
+                [secondAction.reportActionID]: secondAction,
+                [secondDEWAction.reportActionID]: secondDEWAction,
+                [thirdAction.reportActionID]: thirdAction,
+                [fourthAction.reportActionID]: fourthAction,
+                [fourthDEWAction.reportActionID]: fourthDEWAction,
             };
             const actual = ReportActionsUtils.withDEWRoutedActionsObject(reportActions);
 
@@ -1807,19 +1811,23 @@ describe('ReportActionsUtils', () => {
 
         it(`should not add a DEW routed action if we don't have DEW SUBMITTED or FORWARDED action`, () => {
             // Given a report actions collection with no DEW SUBMITTED or FORWARDED actions
+            const firstAction = {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'};
+            const secondAction = {actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED, created: '', reportActionID: '2'};
+            const thirdAction = {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'};
+            const fourthAction = {actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED, created: '', reportActionID: '4'};
             const reportActions: ReportActions = {
-                1: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
-                2: {actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED, created: '', reportActionID: '2'},
-                3: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'},
-                4: {actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED, created: '', reportActionID: '4'},
+                [firstAction.reportActionID]: firstAction,
+                [secondAction.reportActionID]: secondAction,
+                [thirdAction.reportActionID]: thirdAction,
+                [fourthAction.reportActionID]: fourthAction,
             };
 
             // When extending the collection with DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action
             const expected: ReportActions = {
-                1: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '1'},
-                2: {actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED, created: '', reportActionID: '2'},
-                3: {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'},
-                4: {actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED, created: '', reportActionID: '4'},
+                [firstAction.reportActionID]: firstAction,
+                [secondAction.reportActionID]: secondAction,
+                [thirdAction.reportActionID]: thirdAction,
+                [fourthAction.reportActionID]: fourthAction,
             };
             const actual = ReportActionsUtils.withDEWRoutedActionsObject(reportActions);
 
diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts
index e01ce850444c..81bfe9d42a2a 100644
--- a/tests/unit/SidebarUtilsTest.ts
+++ b/tests/unit/SidebarUtilsTest.ts
@@ -1943,6 +1943,7 @@ describe('SidebarUtils', () => {
                         currency: 'USD',
                         message: '',
                         to: 'email1@test.com',
+                        workflow: CONST.POLICY.APPROVAL_MODE.BASIC,
                     },
                     previousMessage: undefined,
                     automatic: false,

From 11ef3ee5784eff0d81313a42b4763c5786a0ee86 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Tue, 16 Dec 2025 12:00:43 +0800
Subject: [PATCH 05/13] lint

---
 src/libs/actions/IOU.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts
index 2b54da5769ba..3fe50a21fe1a 100644
--- a/src/libs/actions/IOU.ts
+++ b/src/libs/actions/IOU.ts
@@ -11501,7 +11501,7 @@ function submitReport(
         expenseReport.currency ?? '',
         expenseReport.reportID,
         adminAccountID,
-        policy?.approvalMode,
+        policy?.approvalMode ?? CONST.POLICY.APPROVAL_MODE.BASIC,
     );
 
     // buildOptimisticNextStep is used in parallel

From a5304d668096c88335daddb34ea24dc9a7913e20 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Wed, 17 Dec 2025 23:07:34 +0800
Subject: [PATCH 06/13] fix type

---
 tests/unit/ReportUtilsTest.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts
index b417319557ad..046d9d368935 100644
--- a/tests/unit/ReportUtilsTest.ts
+++ b/tests/unit/ReportUtilsTest.ts
@@ -3401,7 +3401,7 @@ describe('ReportUtils', () => {
             const reportAction = {
                 actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED,
             } as ReportAction;
-            expect(shouldDisableThread(reportAction, reportID, true)).toBeTruthy();
+            expect(shouldDisableThread(reportAction, false, false)).toBeTruthy();
         });
 
         describe('deleted threads', () => {

From d826503f0704684a9ac67221aec28408e7535c22 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Thu, 18 Dec 2025 10:30:42 +0800
Subject: [PATCH 07/13] fix dew routed action detail is missing

---
 src/pages/Debug/ReportAction/DebugReportActionPage.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/pages/Debug/ReportAction/DebugReportActionPage.tsx b/src/pages/Debug/ReportAction/DebugReportActionPage.tsx
index 634a43d0bca6..988edb5591d2 100644
--- a/src/pages/Debug/ReportAction/DebugReportActionPage.tsx
+++ b/src/pages/Debug/ReportAction/DebugReportActionPage.tsx
@@ -14,7 +14,7 @@ import DebugTabNavigator from '@libs/Navigation/DebugTabNavigator';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {DebugParamList} from '@libs/Navigation/types';
-import {getLinkedTransactionID} from '@libs/ReportActionsUtils';
+import {getLinkedTransactionID, withDEWRoutedActionsObject} from '@libs/ReportActionsUtils';
 import DebugDetails from '@pages/Debug/DebugDetails';
 import DebugJSON from '@pages/Debug/DebugJSON';
 import Debug from '@userActions/Debug';
@@ -37,7 +37,7 @@ function DebugReportActionPage({
 
     const getReportActionSelector = useCallback(
         (reportActions: OnyxEntry<ReportActions>): OnyxEntry<ReportAction> => {
-            return reportActions?.[reportActionID];
+            return withDEWRoutedActionsObject(reportActions)?.[reportActionID];
         },
         [reportActionID],
     );

From c5d3751a7bb978b65b206aacd07b3addf5dbd40a Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Thu, 18 Dec 2025 10:34:12 +0800
Subject: [PATCH 08/13] don't show dew routed action until the report is
 submitted

---
 src/libs/ReportActionsUtils.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index 6b9a70d81088..cb87de14c534 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -1126,7 +1126,7 @@ function getDynamicExternalWorkflowRoutedAction(
 
 function withDEWRoutedActionsArray(reportActions: ReportAction[]): ReportAction[] {
     return reportActions.flatMap((reportAction) => {
-        if (isDynamicExternalWorkflowSubmitAction(reportAction) || isDynamicExternalWorkflowForwardedAction(reportAction)) {
+        if ((isDynamicExternalWorkflowSubmitAction(reportAction) || isDynamicExternalWorkflowForwardedAction(reportAction)) && getOriginalMessage(reportAction)?.to) {
             return [reportAction, getDynamicExternalWorkflowRoutedAction(reportAction)];
         }
         return reportAction;
@@ -1138,7 +1138,7 @@ function withDEWRoutedActionsObject(reportActions: OnyxEntry<ReportActions>): On
         const [reportActionID, reportAction] = value;
         acc[reportActionID] = reportAction;
 
-        if (isDynamicExternalWorkflowSubmitAction(reportAction) || isDynamicExternalWorkflowForwardedAction(reportAction)) {
+        if ((isDynamicExternalWorkflowSubmitAction(reportAction) || isDynamicExternalWorkflowForwardedAction(reportAction)) && getOriginalMessage(reportAction)?.to) {
             const dynamicExternalWorkflowRoutedAction = getDynamicExternalWorkflowRoutedAction(reportAction);
             acc[dynamicExternalWorkflowRoutedAction.reportActionID] = dynamicExternalWorkflowRoutedAction;
         }

From 3c87f0e5bd0557c62b083b218caf9c702f0ef059 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Thu, 18 Dec 2025 11:02:30 +0800
Subject: [PATCH 09/13] add test

---
 tests/unit/hooks/useOriginalReportID.test.tsx | 53 +++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 tests/unit/hooks/useOriginalReportID.test.tsx

diff --git a/tests/unit/hooks/useOriginalReportID.test.tsx b/tests/unit/hooks/useOriginalReportID.test.tsx
new file mode 100644
index 000000000000..6225bc3f06c5
--- /dev/null
+++ b/tests/unit/hooks/useOriginalReportID.test.tsx
@@ -0,0 +1,53 @@
+import {renderHook} from '@testing-library/react-native';
+import {ReactNode} from 'react';
+import Onyx from 'react-native-onyx';
+import OnyxListItemProvider from '@components/OnyxListItemProvider';
+import useOriginalReportID from '@hooks/useOriginalReportID';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import {ReportAction} from '@src/types/onyx';
+
+describe('useOriginalReportID', () => {
+    beforeAll(() => {
+        Onyx.init({
+            keys: ONYXKEYS,
+        });
+    });
+
+    beforeEach(() => {
+        jest.clearAllMocks();
+        Onyx.clear();
+    });
+
+    it('should return the reportID given a DEW routed action', async () => {
+        // Given a report actions that contain DEW SUBMITTED action
+        const reportID = '1';
+        const dewSubmittedAction: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.SUBMITTED> = {
+            actionName: CONST.REPORT.ACTIONS.TYPE.SUBMITTED,
+            created: '',
+            reportActionID: '1',
+            originalMessage: {
+                workflow: CONST.POLICY.APPROVAL_MODE.DYNAMICEXTERNAL,
+                to: 'example@gmail.com',
+                amount: 1,
+                currency: CONST.CURRENCY.USD,
+            },
+        };
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {
+            [dewSubmittedAction.reportActionID]: dewSubmittedAction,
+        });
+
+        const wrapper = ({children}: {children: ReactNode}) => <OnyxListItemProvider>{children}</OnyxListItemProvider>;
+
+        // When getting the original reportID of a DEW routed action that is derived from the DEW SUBMITTED action
+        const dewRoutedAction: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED> = {
+            actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED,
+            created: '',
+            reportActionID: '1DEW',
+        };
+        const {result} = renderHook(() => useOriginalReportID(reportID, dewRoutedAction), {wrapper});
+
+        // Then it should successfully return the reportID of the action
+        expect(result.current).toBe(reportID);
+    });
+});

From ff91890dcc1d7b9e4c14662d0b95ee7d3eb0dcf5 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Thu, 18 Dec 2025 11:04:52 +0800
Subject: [PATCH 10/13] lint

---
 tests/unit/hooks/useOriginalReportID.test.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/unit/hooks/useOriginalReportID.test.tsx b/tests/unit/hooks/useOriginalReportID.test.tsx
index 6225bc3f06c5..b8c55405796a 100644
--- a/tests/unit/hooks/useOriginalReportID.test.tsx
+++ b/tests/unit/hooks/useOriginalReportID.test.tsx
@@ -1,11 +1,11 @@
 import {renderHook} from '@testing-library/react-native';
-import {ReactNode} from 'react';
+import type {ReactNode} from 'react';
 import Onyx from 'react-native-onyx';
 import OnyxListItemProvider from '@components/OnyxListItemProvider';
 import useOriginalReportID from '@hooks/useOriginalReportID';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import {ReportAction} from '@src/types/onyx';
+import type {ReportAction} from '@src/types/onyx';
 
 describe('useOriginalReportID', () => {
     beforeAll(() => {

From 80d821839290b9160cee3b7125e44463303e20ed Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Thu, 18 Dec 2025 22:25:09 +0800
Subject: [PATCH 11/13] fix test

---
 src/libs/OptionsListUtils/index.ts | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index 0a6ee5be3799..4ba1b434371a 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -272,7 +272,7 @@ Onyx.connect({
             const isReportArchived = !!reportNameValuePairs?.private_isArchived;
             const isWriteActionAllowed = canUserPerformWriteAction(report, isReportArchived);
             const reportActionsArray = Object.values(reportActions[1] ?? {});
-            let sortedReportActions = getSortedReportActionsForDisplay(reportActionsArray, isWriteActionAllowed);
+            let sortedReportActions = getSortedReportActionsForDisplay(reportActionsArray, isWriteActionAllowed, true);
             allSortedReportActions[reportID] = sortedReportActions;
             const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`];
 
@@ -294,8 +294,9 @@ Onyx.connect({
             // The report is only visible if it is the last action not deleted that
             // does not match a closed or created state.
             const reportActionsForDisplay = sortedReportActions.filter(
-                (reportAction) =>
+                (reportAction, actionKey) =>
                     (!(isWhisperAction(reportAction) && !isReportPreviewAction(reportAction) && !isMoneyRequestAction(reportAction)) || isActionableMentionWhisper(reportAction)) &&
+                    shouldReportActionBeVisible(reportAction, actionKey, isWriteActionAllowed) &&
                     reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.CREATED &&
                     reportAction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
             );

From 0aa8352ce60f805adf8c3b5ee8859bc979d00e5f Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Thu, 18 Dec 2025 23:30:20 +0800
Subject: [PATCH 12/13] use getSortedReportActions back and apply
 withDEWRoutedActionsArray to it

---
 src/libs/OptionsListUtils/index.ts | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index 4ba1b434371a..1f6805b3313d 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -54,7 +54,7 @@ import {
     getRetractedMessage,
     getRoomAvatarUpdatedMessage,
     getRoomChangeLogMessage,
-    getSortedReportActionsForDisplay,
+    getSortedReportActions,
     getTravelUpdateMessage,
     getUpdateRoomDescriptionMessage,
     isActionableAddPaymentCard,
@@ -82,6 +82,7 @@ import {
     isUnapprovedAction,
     isWhisperAction,
     shouldReportActionBeVisible,
+    withDEWRoutedActionsArray,
 } from '@libs/ReportActionsUtils';
 import {computeReportName} from '@libs/ReportNameUtils';
 import type {OptionData} from '@libs/ReportUtils';
@@ -267,13 +268,10 @@ Onyx.connect({
                 continue;
             }
 
-            const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
-            const reportNameValuePairs = allReportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`];
-            const isReportArchived = !!reportNameValuePairs?.private_isArchived;
-            const isWriteActionAllowed = canUserPerformWriteAction(report, isReportArchived);
             const reportActionsArray = Object.values(reportActions[1] ?? {});
-            let sortedReportActions = getSortedReportActionsForDisplay(reportActionsArray, isWriteActionAllowed, true);
+            let sortedReportActions = getSortedReportActions(withDEWRoutedActionsArray(reportActionsArray), true);
             allSortedReportActions[reportID] = sortedReportActions;
+            const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
             const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.chatReportID}`];
 
             // If the report is a one-transaction report and has , we need to return the combined reportActions so that the LHN can display modifications
@@ -291,6 +289,10 @@ Onyx.connect({
                 lastReportActions[reportID] = firstReportAction;
             }
 
+            const reportNameValuePairs = allReportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`];
+            const isReportArchived = !!reportNameValuePairs?.private_isArchived;
+            const isWriteActionAllowed = canUserPerformWriteAction(report, isReportArchived);
+
             // The report is only visible if it is the last action not deleted that
             // does not match a closed or created state.
             const reportActionsForDisplay = sortedReportActions.filter(

From 795998752f9adcce9f4e69efee3b3633a188f82e Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Fri, 19 Dec 2025 22:25:58 +0800
Subject: [PATCH 13/13] make workflow type optional

---
 src/libs/ReportUtils.ts           | 2 +-
 src/libs/actions/IOU.ts           | 2 +-
 src/types/onyx/OriginalMessage.ts | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 90af43a3160c..51e69b4d3734 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -7601,7 +7601,7 @@ function buildOptimisticSubmittedReportAction(
     currency: string,
     expenseReportID: string,
     adminAccountID: number | undefined,
-    workflow: ValueOf<typeof CONST.POLICY.APPROVAL_MODE>,
+    workflow: ValueOf<typeof CONST.POLICY.APPROVAL_MODE> | undefined,
 ): OptimisticSubmittedReportAction {
     const originalMessage = {
         amount,
diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts
index e929acf28c5f..fa9aa59857f7 100644
--- a/src/libs/actions/IOU.ts
+++ b/src/libs/actions/IOU.ts
@@ -11644,7 +11644,7 @@ function submitReport(
         expenseReport.currency ?? '',
         expenseReport.reportID,
         adminAccountID,
-        policy?.approvalMode ?? CONST.POLICY.APPROVAL_MODE.BASIC,
+        policy?.approvalMode,
     );
 
     // buildOptimisticNextStep is used in parallel
diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts
index bb6feefb5039..3aabb1ebefa6 100644
--- a/src/types/onyx/OriginalMessage.ts
+++ b/src/types/onyx/OriginalMessage.ts
@@ -237,7 +237,7 @@ type OriginalMessageSubmitted = {
     cc?: string;
 
     /** The workflow the report is submitted on */
-    workflow: ValueOf<typeof CONST.POLICY.APPROVAL_MODE>;
+    workflow?: ValueOf<typeof CONST.POLICY.APPROVAL_MODE>;
 };
 
 /** Model of `created` report action */
@@ -897,7 +897,7 @@ type OriginalMessageForwarded = {
     to?: string;
 
     /** The workflow the report is approved on */
-    workflow: ValueOf<typeof CONST.POLICY.APPROVAL_MODE>;
+    workflow?: ValueOf<typeof CONST.POLICY.APPROVAL_MODE>;
 };
 
 /**
