diff --git a/src/languages/de.ts b/src/languages/de.ts index 8a6be1581b8f..2fd86c348bfa 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -1577,7 +1577,7 @@ const translations: TranslationDeepObject = { }, }, chooseWorkspace: 'Wähle einen Arbeitsbereich', - routedDueToDEW: (to: string) => `Report aufgrund des benutzerdefinierten Genehmigungsworkflows an ${to} weitergeleitet`, + routedDueToDEW: (to: string, reason?: string) => `Bericht weitergeleitet an ${to}${reason ? ` weil ${reason}` : ''}`, timeTracking: { hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'Stunde' : 'Stunden'} @ ${rate} / Stunde`, hrs: 'Std.', diff --git a/src/languages/en.ts b/src/languages/en.ts index 3f10e590d6ed..bed6aba34e27 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1602,7 +1602,7 @@ const translations = { }, }, chooseWorkspace: 'Choose a workspace', - routedDueToDEW: (to: string) => `report routed to ${to} due to custom approval workflow`, + routedDueToDEW: (to: string, reason?: string) => `report routed to ${to}${reason ? ` because ${reason}` : ''}`, timeTracking: { hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'hour' : 'hours'} @ ${rate} / hour`, hrs: 'hrs', diff --git a/src/languages/es.ts b/src/languages/es.ts index b415f6a0dd7f..f7e38ae4ea44 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1443,7 +1443,7 @@ const translations: TranslationDeepObject = { }, }, chooseWorkspace: 'Elige un espacio de trabajo', - routedDueToDEW: (to) => `informe enviado a ${to} debido a un flujo de aprobación personalizado`, + routedDueToDEW: (to: string, reason?: string) => `informe enviado a ${to}${reason ? ` porque ${reason}` : ''}`, timeTracking: { hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'hora' : 'horas'} a ${rate} / hora`, hrs: 'h', diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 0b82ad790797..be83f1af6149 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -1582,7 +1582,7 @@ const translations: TranslationDeepObject = { }, }, chooseWorkspace: 'Choisir un espace de travail', - routedDueToDEW: (to: string) => `note de frais transmise à ${to} en raison du flux d’approbation personnalisé`, + routedDueToDEW: (to: string, reason?: string) => `note de frais acheminée vers ${to}${reason ? ` parce que ${reason}` : ''}`, timeTracking: { hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'heure' : 'heures'} @ ${rate} / heure`, hrs: 'h', diff --git a/src/languages/it.ts b/src/languages/it.ts index d273792b023f..a63bd756547c 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -1574,7 +1574,7 @@ const translations: TranslationDeepObject = { }, }, chooseWorkspace: 'Scegli uno spazio di lavoro', - routedDueToDEW: (to: string) => `rendiconto instradato a ${to} a causa del flusso di approvazione personalizzato`, + routedDueToDEW: (to: string, reason?: string) => `report indirizzato a ${to}${reason ? ` perché ${reason}` : ''}`, timeTracking: { hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'ora' : 'ore'} @ ${rate} / ora`, hrs: 'ore', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index 0a811ba9bb8c..106d5b7f8363 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -1564,7 +1564,7 @@ const translations: TranslationDeepObject = { }, }, chooseWorkspace: 'ワークスペースを選択', - routedDueToDEW: (to: string) => `カスタム承認ワークフローにより、レポートは${to}に回付されました`, + routedDueToDEW: (to: string, reason?: string) => `レポートは ${to}${reason ? ` ${reason} のため` : ''} に回覧されました`, timeTracking: { hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? '時間' : '時間'} @ ${rate} / 時間`, hrs: '時間', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index 6ffe1f3c1a21..6522c2cd3095 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -1572,7 +1572,7 @@ const translations: TranslationDeepObject = { }, }, chooseWorkspace: 'Kies een werkruimte', - routedDueToDEW: (to: string) => `rapport doorgestuurd naar ${to} vanwege aangepast goedkeuringsworkflow`, + routedDueToDEW: (to: string, reason?: string) => `rapport doorgestuurd naar ${to}${reason ? ` omdat ${reason}` : ''}`, timeTracking: { hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'uur' : 'uren'} @ ${rate} / uur`, hrs: 'uur', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 5fac6256ad35..b31a25fedf97 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -1571,7 +1571,7 @@ const translations: TranslationDeepObject = { }, }, chooseWorkspace: 'Wybierz przestrzeń roboczą', - routedDueToDEW: (to: string) => `raport skierowano do ${to} z powodu niestandardowego przepływu zatwierdzania`, + routedDueToDEW: (to: string, reason?: string) => `raport przekazany do ${to}${reason ? ` bo ${reason}` : ''}`, timeTracking: { hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'godzina' : 'godziny'} @ ${rate} / godzinę`, hrs: 'godz.', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index a441fe5c534c..1cdf6b0aa3e2 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -1569,7 +1569,7 @@ const translations: TranslationDeepObject = { }, }, chooseWorkspace: 'Escolha um workspace', - routedDueToDEW: (to: string) => `relatório encaminhado para ${to} devido ao fluxo de aprovação personalizado`, + routedDueToDEW: (to: string, reason?: string) => `relatório encaminhado para ${to}${reason ? ` porque ${reason}` : ''}`, timeTracking: { hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'hora' : 'horas'} @ ${rate} / hora`, hrs: 'h', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 3f3090d975a4..5d1358b91fc4 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -1539,7 +1539,7 @@ const translations: TranslationDeepObject = { }, }, chooseWorkspace: '选择工作区', - routedDueToDEW: (to: string) => `报表因自定义审批流程被转交给 ${to}`, + routedDueToDEW: (to: string, reason?: string) => `报销单已转交给 ${to}${reason ? ` 因为 ${reason}` : ''}`, timeTracking: { hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? '小时' : '小时'},按 ${rate} / 小时`, hrs: '小时', diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index 491a9c213196..ddadc8505854 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -1433,6 +1433,7 @@ function getFilteredReportActionsForReportView(actions: ReportAction[]) { function getDynamicExternalWorkflowRoutedAction( reportAction: ReportAction | ReportAction, ): ReportAction { + const originalMessage = getOriginalMessage(reportAction); return { reportActionID: `${reportAction.reportActionID}DEW`, created: DateUtils.addMillisecondsFromDateTime(reportAction.created, 1), @@ -1440,7 +1441,8 @@ function getDynamicExternalWorkflowRoutedAction( actorAccountID: CONST.ACCOUNT_ID.CONCIERGE, message: [{html: 'DYNAMIC_EXTERNAL_WORKFLOW', type: 'COMMENT', text: ''}], originalMessage: { - to: getOriginalMessage(reportAction)?.to ?? '', + to: originalMessage?.to ?? '', + message: originalMessage?.message ?? '', }, }; } @@ -4132,7 +4134,8 @@ function getDynamicExternalWorkflowRoutedMessage( action: OnyxEntry>, translate: LocaleContextProps['translate'], ) { - return translate('iou.routedDueToDEW', getOriginalMessage(action)?.to ?? ''); + const originalMessage = getOriginalMessage(action); + return translate('iou.routedDueToDEW', originalMessage?.to ?? '', originalMessage?.message ?? ''); } function getSettlementAccountLockedMessage(translate: LocalizedTranslate, action: OnyxEntry): string { diff --git a/src/pages/inbox/report/PureReportActionItem.tsx b/src/pages/inbox/report/PureReportActionItem.tsx index 9b858c23d041..82bbf87f5b17 100644 --- a/src/pages/inbox/report/PureReportActionItem.tsx +++ b/src/pages/inbox/report/PureReportActionItem.tsx @@ -1355,6 +1355,9 @@ function PureReportActionItem({ ); } 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 = ; } diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index 099ed08bcbe5..cc91471cb300 100644 --- a/src/types/onyx/OriginalMessage.ts +++ b/src/types/onyx/OriginalMessage.ts @@ -1044,6 +1044,9 @@ type OriginalMessageDismissedViolation = { type OriginalMessageDynamicExternalWorkflowRouted = { /** The approver of the report is submitted to */ to: string; + + /** Explanation for why the report was routed that way */ + message?: string; }; /** Model of `marked reimbursed` report action */ @@ -1110,6 +1113,9 @@ type OriginalMessageForwarded = { /** The workflow the report is approved on */ workflow?: ValueOf; + + /** Optional message explaining why the report was forwarded that way */ + message?: string; }; /** diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index 2f6d40170062..4b04baaefaa0 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -4564,7 +4564,7 @@ describe('OptionsListUtils', () => { created: '', actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, message: [{type: 'COMMENT', text: ''}], - originalMessage: {to: 'example@gmail.com'}, + originalMessage: {to: 'example@gmail.com', message: ''}, }; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, { [action.reportActionID]: action, diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts index 701b37dde387..e82970f2a553 100644 --- a/tests/unit/ReportActionsUtilsTest.ts +++ b/tests/unit/ReportActionsUtilsTest.ts @@ -1175,6 +1175,7 @@ describe('ReportActionsUtils', () => { message: [], originalMessage: { to: 'example@gmail.com', + message: '', }, }; @@ -2641,7 +2642,7 @@ describe('ReportActionsUtils', () => { 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.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, reportActionID: '2DEW', originalMessage: {to: 'example@gmail.com', message: ''}}, {actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT, created: '', reportActionID: '3'}, { actionName: CONST.REPORT.ACTIONS.TYPE.FORWARDED, @@ -2649,7 +2650,7 @@ describe('ReportActionsUtils', () => { 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'}}, + {actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, reportActionID: '4DEW', originalMessage: {to: 'example2@gmail.com', message: ''}}, ]; const actual = ReportActionsUtils.withDEWRoutedActionsArray(reportActions); @@ -2710,12 +2711,12 @@ describe('ReportActionsUtils', () => { const secondDEWAction = { actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, reportActionID: '2DEW', - originalMessage: {to: 'example@gmail.com'}, + originalMessage: {to: 'example@gmail.com', message: ''}, } as ReportAction; const fourthDEWAction = { actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, reportActionID: '4DEW', - originalMessage: {to: 'example2@gmail.com'}, + originalMessage: {to: 'example2@gmail.com', message: ''}, } as ReportAction; const expected: ReportActions = { [firstAction.reportActionID]: firstAction, @@ -2766,14 +2767,33 @@ describe('ReportActionsUtils', () => { reportActionID: '1', actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, created: '', - originalMessage: {to}, + originalMessage: {to, message: ''}, }; // 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); + const expected = translateLocal('iou.routedDueToDEW', to, ''); + expect(actual).toBe(expected); + }); + + it('should return the routed message with reason', () => { + // Given a DYNAMIC_EXTERNAL_WORKFLOW_ROUTED action with a reason message + const to = 'example@gmail.com'; + const reason = 'the report total exceeds the auto-approval limit'; + const action: ReportAction = { + reportActionID: '1', + actionName: CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED, + created: '', + originalMessage: {to, message: reason}, + }; + + // 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 and reason + const expected = translateLocal('iou.routedDueToDEW', to, reason); expect(actual).toBe(expected); }); });