diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 0355ad00644f..278dc4e09ff2 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -135,7 +135,7 @@ import Parser from './Parser'; import {getParsedMessageWithShortMentions} from './ParsingUtils'; import {getBankAccountLastFourDigits} from './PaymentUtils'; import Permissions from './Permissions'; -import {getAccountIDsByLogins, getDisplayNameOrDefault, getLoginByAccountID, getLoginsByAccountIDs, getPersonalDetailByEmail, getShortMentionIfFound} from './PersonalDetailsUtils'; +import {getAccountIDsByLogins, getDisplayNameOrDefault, getLoginByAccountID, getPersonalDetailByEmail} from './PersonalDetailsUtils'; import { canSendInvoiceFromWorkspace, getActivePolicies, @@ -985,11 +985,6 @@ getEnvironment().then((env) => { environment = env; }); -// This cache is used to save parse result of report action html message into text -// to prevent unnecessary parsing when the report action is not changed/modified. -// Example case: when we need to get a report name of a thread which is dependent on a report action message. -const parsedReportActionMessageCache: Record = {}; - /** * Fallback title field used when a policy has an empty fieldList (matches OldDot behavior). */ @@ -4939,8 +4934,9 @@ function getNextApproverAccountID(report: OnyxEntry, isUnapproved = fals return bypassApproverAccountID === deprecatedCurrentUserAccountID && !isUnapproved ? undefined : bypassApproverAccountID; } - const approvalChain = getApprovalChain(policy, report); - const submitToAccountID = getSubmitToAccountID(policy, report, getLoginByAccountID(report?.ownerAccountID, allPersonalDetails)); + const ownerLogin = getLoginByAccountID(report?.ownerAccountID, allPersonalDetails); + const approvalChain = getApprovalChain(policy, report, ownerLogin); + const submitToAccountID = getSubmitToAccountID(policy, report, ownerLogin); if (isUnapproved) { if (approvalChain.includes(deprecatedCurrentUserEmail ?? '')) { @@ -5858,52 +5854,6 @@ function getModifiedExpenseOriginalMessage( return originalMessage; } -/** - * Parse html of reportAction into text - */ -function parseReportActionHtmlToText(reportAction: OnyxEntry, reportID: string | undefined, conciergeReportID: string | undefined, childReportID?: string): string { - if (!reportAction) { - return ''; - } - const key = `${reportID}_${reportAction.reportActionID}_${reportAction.lastModified}`; - const cachedText = parsedReportActionMessageCache[key]; - if (cachedText !== undefined) { - return cachedText; - } - - const {html, text} = getReportActionMessageReportUtils(reportAction) ?? {}; - - if (!html) { - return text ?? ''; - } - - const mentionReportRegex = /|><\/mention-report>)/gi; - const matches = html.matchAll(mentionReportRegex); - - const reportIDToName: Record = {}; - for (const match of matches) { - if (match[1] !== childReportID) { - reportIDToName[match[1]] = getReportName(getReportOrDraftReport(match[1]), reportAttributesDerivedValue) ?? ''; - } - } - - const mentionUserRegex = /(?:|><\/mention-user>))/gi; - const accountIDToName: Record = {}; - const accountIDs = Array.from(html.matchAll(mentionUserRegex), (mention) => Number(mention[1])); - const logins = getLoginsByAccountIDs(accountIDs); - for (const [index, id] of accountIDs.entries()) { - const login = logins.at(index); - const user = allPersonalDetails?.[id]; - const displayName = formatPhoneNumberPhoneUtils(login ?? '') || getDisplayNameOrDefault(user); - accountIDToName[id] = getShortMentionIfFound(displayName, id.toString(), currentUserPersonalDetails, login) ?? ''; - } - - const textMessage = Str.removeSMSDomain(Parser.htmlToText(html, {reportIDToName, accountIDToName})); - parsedReportActionMessageCache[key] = textMessage; - - return textMessage; -} - /** * Get the payee name given a report. */ @@ -12517,11 +12467,10 @@ function getBypassApproverAccountIDIfTakenControl(expenseReport: OnyxEntry, expenseReport: OnyxEntry): string[] { +function getApprovalChain(policy: OnyxEntry, expenseReport: OnyxEntry, ownerLogin: string | undefined): string[] { const approvalChain: string[] = []; const fullApprovalChain: string[] = []; const reportTotal = expenseReport?.total ?? 0; - const submitterEmail = getLoginsByAccountIDs([expenseReport?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID]).at(0) ?? ''; if (isSubmitAndClose(policy)) { return approvalChain; @@ -12533,13 +12482,13 @@ function getApprovalChain(policy: OnyxEntry, expenseReport: OnyxEntry, expenseReport: OnyxEntry { }); }); - describe('parseReportActionHtmlToText', () => { - it('should return empty string for undefined reportAction', () => { - const result = parseReportActionHtmlToText(undefined, '123', undefined); - expect(result).toBe(''); - }); - - it('should return text from reportAction message when no html', () => { - const reportAction = createMock({ - ...createRandomReportAction(1), - message: [{type: 'COMMENT', text: 'Hello world'}], - }); - const result = parseReportActionHtmlToText(reportAction, '123', undefined); - expect(result).toBe('Hello world'); - }); - - it('should parse html to text with conciergeReportID', () => { - const reportAction = createMock({ - ...createRandomReportAction(1), - message: [{type: 'COMMENT', html: '

Hello world

', text: 'Hello world'}], - }); - const result = parseReportActionHtmlToText(reportAction, '123', '999'); - expect(result).toBe('Hello world'); - }); - - it('should handle conciergeReportID being undefined', () => { - const reportAction = createMock({ - ...createRandomReportAction(1), - message: [{type: 'COMMENT', html: '

Test message

', text: 'Test message'}], - }); - const result = parseReportActionHtmlToText(reportAction, '456', undefined); - expect(result).toBe('Test message'); - }); - }); - describe('requiresAttentionFromCurrentUser', () => { afterEach(async () => { await Onyx.clear(); @@ -8019,7 +7984,7 @@ describe('ReportUtils', () => { type: CONST.REPORT.TYPE.EXPENSE, }; - expect(getApprovalChain(policyTest, expenseReport)).toStrictEqual([]); + expect(getApprovalChain(policyTest, expenseReport, undefined)).toStrictEqual([]); }); }); describe('basic/advance workflow', () => { @@ -8040,7 +8005,7 @@ describe('ReportUtils', () => { }; Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, personalDetails).then(() => { const result = ['owner@test.com']; - expect(getApprovalChain(policyTest, expenseReport)).toStrictEqual(result); + expect(getApprovalChain(policyTest, expenseReport, undefined)).toStrictEqual(result); }); }); it('should return list contain submitsTo of ownerAccountID and the forwardsTo of them if the policy use advance workflow', () => { @@ -8059,7 +8024,7 @@ describe('ReportUtils', () => { }; Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, personalDetails).then(() => { const result = ['admin@test.com']; - expect(getApprovalChain(policyTest, expenseReport)).toStrictEqual(result); + expect(getApprovalChain(policyTest, expenseReport, personalDetails[employeeAccountID]?.login)).toStrictEqual(result); }); }); }); @@ -8104,7 +8069,7 @@ describe('ReportUtils', () => { }, }).then(() => { const result = ['owner@test.com']; - expect(getApprovalChain(policyTest, expenseReport)).toStrictEqual(result); + expect(getApprovalChain(policyTest, expenseReport, personalDetails[employeeAccountID]?.login)).toStrictEqual(result); }); }); }); @@ -8164,7 +8129,7 @@ describe('ReportUtils', () => { transactions_4: transaction4, }).then(() => { const result = [categoryApprover2Email, categoryApprover1Email, tagApprover2Email, tagApprover1Email, 'admin@test.com']; - expect(getApprovalChain(policyTest, expenseReport)).toStrictEqual(result); + expect(getApprovalChain(policyTest, expenseReport, personalDetails[employeeAccountID]?.login)).toStrictEqual(result); }); }); });