Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ function usePreviewMessageAnimation({
if (isPolicyExpenseChat || isTripRoom) {
payerOrApproverName = getPolicyName({report: chatReport, policy, unavailableTranslation: translate('workspace.common.unavailable')});
} else if (isInvoiceRoom) {
payerOrApproverName = getInvoicePayerName(chatReport, invoiceReceiverPolicy, invoiceReceiverPersonalDetail);
payerOrApproverName = getInvoicePayerName(chatReport, translate, invoiceReceiverPolicy, invoiceReceiverPersonalDetail);
} else {
payerOrApproverName = getDisplayNameForParticipant({
accountID: managerID,
Expand Down
60 changes: 40 additions & 20 deletions src/libs/ReportNameUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {translateLocal} from './Localize';
// eslint-disable-next-line import/no-cycle
import {getForReportAction, getMovedReportID} from './ModifiedExpenseMessage';
import Parser from './Parser';
import {getDisplayNameOrDefault} from './PersonalDetailsUtils';
import {temporaryGetDisplayNameOrDefault} from './PersonalDetailsUtils';
import {getCleanedTagName, isPolicyAdmin, isPolicyFieldListEmpty} from './PolicyUtils';
import {
getActionableCard3DSTransactionApprovalMessage,
Expand Down Expand Up @@ -186,6 +186,7 @@ type ComputeReportName = {
reportActions?: OnyxCollection<ReportActions>;
currentUserAccountID?: number;
currentUserLogin: string;
translate: LocalizedTranslate;
// TODO: Make this required when https://github.com/Expensify/App/issues/66411 is done
conciergeReportID?: string;
reportAttributes?: ReportAttributesDerivedValue['reports'];
Expand Down Expand Up @@ -327,12 +328,14 @@ function getInvoicesChatName({
personalDetails,
policy,
currentUserAccountID,
translate,
}: {
report: OnyxEntry<Report>;
receiverPolicy: OnyxEntry<Policy>;
personalDetails?: Partial<PersonalDetailsList>;
policy: OnyxEntry<Policy>;
currentUserAccountID?: number;
translate: LocalizedTranslate;
}): string {
const invoiceReceiver = report?.invoiceReceiver;
const isIndividual = invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL;
Expand All @@ -344,14 +347,14 @@ function getInvoicesChatName({
}

if (isIndividual) {
return formatPhoneNumberPhoneUtils(getDisplayNameOrDefault((personalDetails ?? allPersonalDetails)?.[invoiceReceiverAccountID]));
return formatPhoneNumberPhoneUtils(temporaryGetDisplayNameOrDefault({passedPersonalDetails: (personalDetails ?? allPersonalDetails)?.[invoiceReceiverAccountID], translate}));
}

return getPolicyName({report, policy: receiverPolicy});
}

function getInvoiceReportName(report: OnyxEntry<Report>, policy?: OnyxEntry<Policy>, invoiceReceiverPolicy?: OnyxEntry<Policy>): string {
const moneyRequestReportName = getMoneyRequestReportName({report, policy, invoiceReceiverPolicy});
function getInvoiceReportName(report: OnyxEntry<Report>, translate: LocalizedTranslate, policy?: OnyxEntry<Policy>, invoiceReceiverPolicy?: OnyxEntry<Policy>): string {
const moneyRequestReportName = getMoneyRequestReportName({report, policy, invoiceReceiverPolicy, translate});
const oldDotInvoiceName = report?.reportName ?? moneyRequestReportName;
return isNewDotInvoice(report?.chatReportID) ? moneyRequestReportName : oldDotInvoiceName;
}
Expand All @@ -361,13 +364,18 @@ function getInvoiceReportName(report: OnyxEntry<Report>, policy?: OnyxEntry<Poli
* - Individual - a receiver display name.
* - Policy - a receiver policy name.
*/
function getInvoicePayerName(report: OnyxEntry<Report>, invoiceReceiverPolicy?: OnyxEntry<Policy>, invoiceReceiverPersonalDetail?: PersonalDetails | null): string {
function getInvoicePayerName(
report: OnyxEntry<Report>,
translate: LocalizedTranslate,
invoiceReceiverPolicy?: OnyxEntry<Policy>,
invoiceReceiverPersonalDetail?: PersonalDetails | null,
): string {
const invoiceReceiver = report?.invoiceReceiver;
const isIndividual = invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL;

if (isIndividual) {
const personalDetail = invoiceReceiverPersonalDetail ?? allPersonalDetails?.[invoiceReceiver.accountID];
return formatPhoneNumberPhoneUtils(getDisplayNameOrDefault(personalDetail ?? undefined));
return formatPhoneNumberPhoneUtils(temporaryGetDisplayNameOrDefault({passedPersonalDetails: personalDetail ?? undefined, translate}));
}

return getPolicyName({report, policy: invoiceReceiverPolicy});
Expand All @@ -376,7 +384,17 @@ function getInvoicePayerName(report: OnyxEntry<Report>, invoiceReceiverPolicy?:
/**
* Get the title for an IOU or expense chat which will be showing the payer and the amount
*/
function getMoneyRequestReportName({report, policy, invoiceReceiverPolicy}: {report: OnyxEntry<Report>; policy?: OnyxEntry<Policy>; invoiceReceiverPolicy?: OnyxEntry<Policy>}): string {
function getMoneyRequestReportName({
report,
policy,
invoiceReceiverPolicy,
translate,
}: {
report: OnyxEntry<Report>;
policy?: OnyxEntry<Policy>;
invoiceReceiverPolicy?: OnyxEntry<Policy>;
translate: LocalizedTranslate;
}): string {
// For expense reports with empty fieldList and empty reportName, return "New Report" (matches OldDot behavior)
if (isExpenseReport(report)) {
if (report?.reportName === '' && isPolicyFieldListEmpty(policy)) {
Expand All @@ -397,27 +415,27 @@ function getMoneyRequestReportName({report, policy, invoiceReceiverPolicy}: {rep
payerOrApproverName = getPolicyName({report: parentReport ?? report, policy});
} else if (isInvoiceReport(report)) {
const chatReport = getReportOrDraftReport(report?.chatReportID);
payerOrApproverName = getInvoicePayerName(chatReport, invoiceReceiverPolicy);
payerOrApproverName = getInvoicePayerName(chatReport, translate, invoiceReceiverPolicy);
} else {
payerOrApproverName = getDisplayNameForParticipant({accountID: report?.managerID, formatPhoneNumber: formatPhoneNumberPhoneUtils}) ?? '';
}
const payerPaidAmountMessage = translateLocal('iou.payerPaidAmount', formattedAmount, payerOrApproverName);
const payerPaidAmountMessage = translate('iou.payerPaidAmount', formattedAmount, payerOrApproverName);

if (isReportApproved({report})) {
return translateLocal('iou.managerApprovedAmount', payerOrApproverName, formattedAmount);
return translate('iou.managerApprovedAmount', payerOrApproverName, formattedAmount);
}

if (report?.isWaitingOnBankAccount) {
return `${payerPaidAmountMessage} ${CONST.DOT_SEPARATOR} ${translateLocal('iou.pending')}`;
return `${payerPaidAmountMessage} ${CONST.DOT_SEPARATOR} ${translate('iou.pending')}`;
}

if (!isSettled(report?.reportID) && hasNonReimbursableTransactions(report?.reportID)) {
payerOrApproverName = getDisplayNameForParticipant({accountID: report?.ownerAccountID, formatPhoneNumber: formatPhoneNumberPhoneUtils}) ?? '';
return translateLocal('iou.payerSpentAmount', formattedAmount, payerOrApproverName);
return translate('iou.payerSpentAmount', formattedAmount, payerOrApproverName);
}

if (isProcessingReport(report) || isOpenExpenseReport(report) || isOpenInvoiceReport(report) || moneyRequestTotal === 0) {
return translateLocal('iou.payerOwesAmount', formattedAmount, payerOrApproverName);
return translate('iou.payerOwesAmount', formattedAmount, payerOrApproverName);
}

return payerPaidAmountMessage;
Expand Down Expand Up @@ -930,6 +948,7 @@ function computeReportName({
reportActions,
currentUserAccountID,
currentUserLogin,
translate,
allPolicyTags,
conciergeReportID,
reportAttributes,
Expand All @@ -944,7 +963,7 @@ function computeReportName({
const parentReportAction = isThread(report) ? reportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.parentReportID}`]?.[report.parentReportActionID] : undefined;

const parentReportActionBasedName = computeReportNameBasedOnReportAction(
translateLocal,
translate,
formatPhoneNumberPhoneUtils,
parentReportAction,
report,
Expand Down Expand Up @@ -976,11 +995,12 @@ function computeReportName({
reportActions,
currentUserAccountID,
currentUserLogin,
translate,
conciergeReportID,
reportAttributes,
isTrackIntentUser,
});
return getCreatedReportForUnapprovedTransactionsMessage(originalID, reportName, isOriginalReportDeleted(parentReportAction, originalReport), translateLocal);
return getCreatedReportForUnapprovedTransactionsMessage(originalID, reportName, isOriginalReportDeleted(parentReportAction, originalReport), translate);
}

if (isTaskReport(report)) {
Expand All @@ -993,7 +1013,7 @@ function computeReportName({

const policyTags = allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report.policyID}`];
const chatThreadReportName = computeChatThreadReportName(
translateLocal,
translate,
privateIsArchivedValue,
report,
reports ?? {},
Expand All @@ -1009,7 +1029,7 @@ function computeReportName({

const transactionsArray = transactions ? (Object.values(transactions).filter(Boolean) as Array<OnyxEntry<Transaction>>) : undefined;
if (isClosedExpenseReportWithNoExpenses(report, transactionsArray)) {
return translateLocal('parentReportAction.deletedReport');
return translate('parentReportAction.deletedReport');
}

if (isGroupChat(report)) {
Expand All @@ -1028,7 +1048,7 @@ function computeReportName({

const policy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`];
if (isMoneyRequestReport(report)) {
formattedName = getMoneyRequestReportName({report, policy});
formattedName = getMoneyRequestReportName({report, policy, translate});
}

if (isInvoiceReport(report)) {
Expand All @@ -1039,7 +1059,7 @@ function computeReportName({
chatReceiverPolicyID = (chatReceiver as {policyID: string}).policyID;
}
const invoiceReceiverPolicy = chatReceiverPolicyID ? policies?.[`${ONYXKEYS.COLLECTION.POLICY}${chatReceiverPolicyID}`] : undefined;
formattedName = getInvoiceReportName(report, policy, invoiceReceiverPolicy);
formattedName = getInvoiceReportName(report, translate, policy, invoiceReceiverPolicy);
}

if (isInvoiceRoom(report)) {
Expand All @@ -1049,7 +1069,7 @@ function computeReportName({
receiverPolicyID = (receiver as {policyID: string}).policyID;
}
const invoiceReceiverPolicy = receiverPolicyID ? policies?.[`${ONYXKEYS.COLLECTION.POLICY}${receiverPolicyID}`] : undefined;
formattedName = getInvoicesChatName({report, receiverPolicy: invoiceReceiverPolicy, personalDetails: personalDetailsList, currentUserAccountID, policy});
formattedName = getInvoicesChatName({report, receiverPolicy: invoiceReceiverPolicy, personalDetails: personalDetailsList, currentUserAccountID, policy, translate});
}

if (isSelfDM(report)) {
Expand Down
6 changes: 3 additions & 3 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6084,7 +6084,7 @@ function getParentNavigationSubtitle(
const invoiceReceiverPolicyID = getInvoiceReceiverPolicyID(parentReport);
const invoiceReceiverPolicy = invoiceReceiverPolicyID ? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`] : undefined;
const isCurrentUserReceiver = isCurrentUserInvoiceReceiver(parentReport);
const invoicePayerName = getInvoicePayerName(parentReport, invoiceReceiverPolicy);
const invoicePayerName = getInvoicePayerName(parentReport, translate, invoiceReceiverPolicy);

let reportName = senderWorkspaceName;
if (!isCurrentUserReceiver && invoicePayerName) {
Expand Down Expand Up @@ -12721,12 +12721,12 @@ function isWaitingForSubmissionFromCurrentUser(chatReport: OnyxEntry<Report>, po
return chatReport?.isOwnPolicyExpenseChat && !policy?.harvesting?.enabled;
}

function getChatListItemReportName(action: ReportAction & {reportName?: string}, report: Report | undefined, conciergeReportID: string | undefined): string {
function getChatListItemReportName(action: ReportAction & {reportName?: string}, report: Report | undefined, conciergeReportID: string | undefined, translate: LocalizedTranslate): string {
if (report && isInvoiceReport(report)) {
const properInvoiceReport = report;
properInvoiceReport.chatReportID = report.parentReportID;

return getInvoiceReportName(properInvoiceReport);
return getInvoiceReportName(properInvoiceReport, translate);
}

if (action?.reportName) {
Expand Down
5 changes: 5 additions & 0 deletions src/libs/actions/OnyxDerived/configs/reportAttributes.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import type {LocalizedTranslate} from '@components/LocaleContextProvider';

import {translate as translateForLocale} from '@libs/Localize';
import {getIsOffline} from '@libs/NetworkState';
import {getLinkedTransactionID} from '@libs/ReportActionsUtils';
import {computeReportName} from '@libs/ReportNameUtils';
Expand Down Expand Up @@ -118,6 +121,7 @@ export default createOnyxDerivedValueConfig({
) => {
// Read the in-memory offline state directly (NETWORK is a dependency so recompute still fires when it changes).
const isOffline = getIsOffline();
const translate: LocalizedTranslate = (path, ...parameters) => translateForLocale(preferredLocale, path, ...parameters);
// Check if display names changed when personal details are updated
let displayNamesChanged = false;
if (hasKeyTriggeredCompute(ONYXKEYS.PERSONAL_DETAILS_LIST, sourceValues)) {
Expand Down Expand Up @@ -373,6 +377,7 @@ export default createOnyxDerivedValueConfig({
reportActions,
currentUserAccountID: session?.accountID ?? CONST.DEFAULT_NUMBER_ID,
currentUserLogin: session?.email ?? '',
translate,
allPolicyTags: policyTags,
conciergeReportID: conciergeReportID ?? undefined,
reportAttributes: currentValue?.reports,
Expand Down
2 changes: 1 addition & 1 deletion src/pages/inbox/report/SearchActionHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function SearchActionHeaderContent({action, report, isWhisper, onPress, children
const {translate} = useLocalize();
const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);

const reportName = getChatListItemReportName(action, report, conciergeReportID);
const reportName = getChatListItemReportName(action, report, conciergeReportID, translate);

return (
<View style={[styles.p4]}>
Expand Down
45 changes: 41 additions & 4 deletions tests/unit/ReportNameUtilsTest.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type {LocalizedTranslate} from '@components/LocaleContextProvider';

import {translate} from '@libs/Localize';
import {
buildReportNameFromParticipantNames,
Expand All @@ -24,7 +26,7 @@ import createRandomPolicy from '../utils/collections/policies';
import {createAdminRoom, createExpenseReport, createPolicyExpenseChat, createRegularChat, createRegularTaskReport, createSelfDM, createWorkspaceThread} from '../utils/collections/reports';
import createRandomTransaction from '../utils/collections/transaction';
import {fakePersonalDetails} from '../utils/LHNTestUtils';
import {formatPhoneNumber} from '../utils/TestHelper';
import {formatPhoneNumber, translateLocal} from '../utils/TestHelper';
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';

const currentUserLogin = 'lagertha2@vikings.net';
Expand All @@ -50,6 +52,7 @@ describe('ReportNameUtils', () => {
reportActions,
currentUserAccountID: currentUserID,
currentUserLogin,
translate: translateLocal,
isTrackIntentUser: false,
});
const participantsPersonalDetails: PersonalDetailsList = [
Expand Down Expand Up @@ -560,6 +563,7 @@ describe('ReportNameUtils', () => {
reportActions: reportActionsCollection,
currentUserAccountID,
currentUserLogin: '',
translate: translateLocal,
allPolicyTags: policyTagsCollection,
isTrackIntentUser: false,
});
Expand Down Expand Up @@ -1052,6 +1056,7 @@ describe('ReportNameUtils', () => {
personalDetails: participantsPersonalDetails,
policy: undefined,
currentUserAccountID,
translate: translateLocal,
});

expect(name).toBe('Personal Workspace');
Expand All @@ -1071,6 +1076,7 @@ describe('ReportNameUtils', () => {
personalDetails: participantsPersonalDetails,
policy: undefined,
currentUserAccountID,
translate: translateLocal,
});

const normalizedName = name?.replaceAll('\u00A0', ' ');
Expand All @@ -1082,11 +1088,42 @@ describe('ReportNameUtils', () => {
reportID: 'invoice-chat-3',
invoiceReceiver: {type: CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL, accountID: 1},
};
const name = getInvoicePayerName(report, undefined, null);
const name = getInvoicePayerName(report, translateLocal, undefined, null);

const normalizedName = name?.replaceAll('\u00A0', ' ');
expect(normalizedName).toBe('Ragnar Lothbrok');
});

test('Invoice room resolves the hidden fallback through the provided translate function', () => {
const translateWithHiddenMarker: LocalizedTranslate = (path, ...parameters) => (path === 'common.hidden' ? 'HiddenMarker' : translateLocal(path, ...parameters));
const report: Report = {
reportID: 'invoice-chat-4',
invoiceReceiver: {type: CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL, accountID: 424242},
};

const name = getInvoicesChatName({
report,
receiverPolicy: undefined,
personalDetails: {},
policy: undefined,
currentUserAccountID,
translate: translateWithHiddenMarker,
});

expect(name).toBe('HiddenMarker');
});

test('Invoice payer name resolves the hidden fallback through the provided translate function', () => {
const translateWithHiddenMarker: LocalizedTranslate = (path, ...parameters) => (path === 'common.hidden' ? 'HiddenMarker' : translateLocal(path, ...parameters));
const report: Report = {
reportID: 'invoice-chat-5',
invoiceReceiver: {type: CONST.REPORT.INVOICE_RECEIVER_TYPE.INDIVIDUAL, accountID: 424242},
};

const name = getInvoicePayerName(report, translateWithHiddenMarker, undefined, null);

expect(name).toBe('HiddenMarker');
});
});

describe('getPolicyExpenseChatName', () => {
Expand Down Expand Up @@ -1248,7 +1285,7 @@ describe('ReportNameUtils', () => {
};

// When we get the money request report name
const reportName = getMoneyRequestReportName({report: expenseReport, policy: policyWithEmptyFieldList});
const reportName = getMoneyRequestReportName({report: expenseReport, policy: policyWithEmptyFieldList, translate: translateLocal});

// Then it should return "New Report"
expect(reportName).toBe(CONST.REPORT.DEFAULT_EXPENSE_REPORT_NAME);
Expand Down Expand Up @@ -1290,7 +1327,7 @@ describe('ReportNameUtils', () => {
};

// When we get the money request report name
const reportName = getMoneyRequestReportName({report: expenseReport, policy: policyWithFieldList});
const reportName = getMoneyRequestReportName({report: expenseReport, policy: policyWithFieldList, translate: translateLocal});

// Then it should NOT return empty string — it should fall through to dynamic name computation
expect(reportName).not.toBe('');
Expand Down
Loading
Loading