Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
56de607
fix: add more report fields for optimistic report names
lorretheboy Sep 16, 2025
58162eb
feat: add tests
lorretheboy Sep 16, 2025
93861b6
chore: add default value
lorretheboy Sep 16, 2025
a7316c4
Merge branch 'main' of https://github.com/Expensify/App into fix/68695
lorretheboy Sep 16, 2025
59dff1c
Merge branch 'main' of https://github.com/Expensify/App into fix/68695
lorretheboy Sep 23, 2025
52a8417
Merge branch 'main' of https://github.com/Expensify/App into fix/68695
lorretheboy Sep 24, 2025
24fa802
Merge branch 'main' of https://github.com/Expensify/App into fix/68695
lorretheboy Oct 15, 2025
a8987f4
chore: merge main
lorretheboy Oct 24, 2025
a356466
chore: optimize expense cnt flow
lorretheboy Oct 24, 2025
f7a2e69
Merge branch 'main' of https://github.com/Expensify/App into fix/68695
lorretheboy Oct 30, 2025
0e347a0
chore: merge main
lorretheboy Nov 2, 2025
62ae5d5
fix: handle deleted txn
lorretheboy Nov 2, 2025
0d6f49a
chore: merge main
lorretheboy Nov 3, 2025
6b540c3
fix: exp cnt when adding new exp
lorretheboy Nov 3, 2025
a94ae0d
chore: resolve conflicts
lorretheboy Nov 5, 2025
f560205
fix: revert changes
lorretheboy Nov 5, 2025
66c0868
feat: include txn data in update batch
lorretheboy Nov 5, 2025
9014f1a
Merge branch 'main' of https://github.com/Expensify/App into fix/68695
lorretheboy Nov 6, 2025
8ce89fe
chore: revert code
lorretheboy Nov 6, 2025
9c39791
fix: bring back code comment
lorretheboy Nov 6, 2025
d82d1d3
fix: remove use of getReportTransactions
lorretheboy Nov 9, 2025
5f201eb
Merge branch 'main' of https://github.com/Expensify/App into fix/68695
lorretheboy Nov 10, 2025
6016201
fix: add exp cnt
lorretheboy Nov 10, 2025
f9504b9
fix: type
lorretheboy Nov 10, 2025
6d039df
fix: test
lorretheboy Nov 10, 2025
4e7782f
fix: type
lorretheboy Nov 10, 2025
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
2 changes: 2 additions & 0 deletions src/libs/DebugUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ function validateReportDraftProperty(key: keyof Report | keyof ReportNameValuePa
case 'unheldTotal':
case 'nonReimbursableTotal':
case 'unheldNonReimbursableTotal':
case 'transactionCount':
return validateNumber(value);
case 'chatType':
return validateConstantEnum(value, CONST.REPORT.CHAT_TYPE);
Expand Down Expand Up @@ -629,6 +630,7 @@ function validateReportDraftProperty(key: keyof Report | keyof ReportNameValuePa
// eslint-disable-next-line @typescript-eslint/naming-convention
expensify_text_title: CONST.RED_BRICK_ROAD_PENDING_ACTION,
created: CONST.RED_BRICK_ROAD_PENDING_ACTION,
transactionCount: CONST.RED_BRICK_ROAD_PENDING_ACTION,
});
case 'expensify_text_title':
return validateObject<ObjectElement<ReportNameValuePairs, 'expensify_text_title'>>(value, {
Expand Down
43 changes: 40 additions & 3 deletions src/libs/Formula.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import type {Policy, Report, Transaction} from '@src/types/onyx';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import {getCurrencySymbol} from './CurrencyUtils';
import {formatDate} from './FormulaDatetime';
import getBase62ReportID from './getBase62ReportID';
import {getAllReportActions} from './ReportActionsUtils';
import {getMoneyRequestSpendBreakdown, getReportTransactions} from './ReportUtils';
import {getCreated, isPartialTransaction} from './TransactionUtils';
import {getHumanReadableStatus, getMoneyRequestSpendBreakdown, getReportTransactions} from './ReportUtils';
import {getCreated, isPartialTransaction, isTransactionPendingDelete} from './TransactionUtils';

type FormulaPart = {
/** The original definition from the formula */
Expand All @@ -28,6 +29,7 @@ type FormulaContext = {
report: Report;
policy: OnyxEntry<Policy>;
transaction?: Transaction;
allTransactions?: Record<string, Transaction>;
};

type FieldList = Record<string, {name: string; defaultValue: string}>;
Expand Down Expand Up @@ -327,7 +329,7 @@ function computeAutoReportingInfo(part: FormulaPart, context: FormulaContext, su
* Compute the value of a report formula part
*/
function computeReportPart(part: FormulaPart, context: FormulaContext): string {
const {report, policy} = context;
const {report, policy, allTransactions} = context;
const [field, ...additionalPath] = part.fieldPath;
// Reconstruct format string by joining additional path elements with ':'
// This handles format strings with colons like 'HH:mm:ss'
Expand All @@ -338,6 +340,12 @@ function computeReportPart(part: FormulaPart, context: FormulaContext): string {
}

switch (field.toLowerCase()) {
case 'id':
return getBase62ReportID(Number(report.reportID));
case 'status':
return formatStatus(report.statusNum);
case 'expensescount':
return String(getExpensesCount(report, allTransactions));
case 'type':
return formatType(report.type);
case 'startdate':
Expand Down Expand Up @@ -368,6 +376,35 @@ function computeReportPart(part: FormulaPart, context: FormulaContext): string {
}
}

/**
* Get the number of expenses in a report
* @param report - The report to get expenses for
* @param allTransactions - Optional map of all transactions. If provided, uses this instead of fetching from Onyx
*/
function getExpensesCount(report: Report, allTransactions?: Record<string, Transaction>): number {
if (!report.reportID) {
return 0;
}

if (allTransactions) {
const transactions = Object.values(allTransactions).filter((transaction): transaction is Transaction => !!transaction && transaction.reportID === report.reportID);
return transactions?.filter((transaction) => !isTransactionPendingDelete(transaction))?.length ?? 0;
}

return report.transactionCount ?? 0;
}

/**
* Format a report status number to human-readable string
*/
function formatStatus(statusNum: number | undefined): string {
if (statusNum === undefined) {
return '';
}

return getHumanReadableStatus(statusNum);
}

/**
* Compute the value of a field formula part
*/
Expand Down
1 change: 1 addition & 0 deletions src/libs/OptimisticReportNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ function computeReportNameIfNeeded(report: Report | undefined, incomingUpdate: O
report: updatedReport,
policy: updatedPolicy,
transaction: updatedTransaction,
allTransactions: context.allTransactions,
};

const newName = compute(formula, formulaContext);
Expand Down
1 change: 1 addition & 0 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@
const parsedReportActionMessageCache: Record<string, string> = {};

let conciergeReportID: OnyxEntry<string>;
Onyx.connect({

Check warning on line 952 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.CONCIERGE_REPORT_ID,
callback: (value) => {
conciergeReportID = value;
Expand All @@ -957,7 +957,7 @@
});

const defaultAvatarBuildingIconTestID = 'SvgDefaultAvatarBuilding Icon';
Onyx.connect({

Check warning on line 960 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
// When signed out, val is undefined
Expand All @@ -975,7 +975,7 @@
let allPersonalDetails: OnyxEntry<PersonalDetailsList>;
let allPersonalDetailLogins: string[];
let currentUserPersonalDetails: OnyxEntry<PersonalDetails>;
Onyx.connect({

Check warning on line 978 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
if (currentUserAccountID) {
Expand All @@ -987,14 +987,14 @@
});

let allReportsDraft: OnyxCollection<Report>;
Onyx.connect({

Check warning on line 990 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_DRAFT,
waitForCollectionCallback: true,
callback: (value) => (allReportsDraft = value),
});

let allPolicies: OnyxCollection<Policy>;
Onyx.connect({

Check warning on line 997 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY,
waitForCollectionCallback: true,
callback: (value) => (allPolicies = value),
Expand All @@ -1009,7 +1009,7 @@

let allReports: OnyxCollection<Report>;
let reportsByPolicyID: ReportByPolicyMap;
Onyx.connect({

Check warning on line 1012 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand Down Expand Up @@ -1047,14 +1047,14 @@
});

let allBetas: OnyxEntry<Beta[]>;
Onyx.connect({

Check warning on line 1050 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.BETAS,
callback: (value) => (allBetas = value),
});

let allTransactions: OnyxCollection<Transaction> = {};
let reportsTransactions: Record<string, Transaction[]> = {};
Onyx.connect({

Check warning on line 1057 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -1080,7 +1080,7 @@
});

let allReportActions: OnyxCollection<ReportActions>;
Onyx.connect({

Check warning on line 1083 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (actions) => {
Expand All @@ -1093,7 +1093,7 @@

let allReportMetadata: OnyxCollection<ReportMetadata>;
const allReportMetadataKeyValue: Record<string, ReportMetadata> = {};
Onyx.connect({

Check warning on line 1096 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_METADATA,
waitForCollectionCallback: true,
callback: (value) => {
Expand Down Expand Up @@ -12827,6 +12827,7 @@
getOutstandingReportsForUser,
isReportOutstanding,
generateReportAttributes,
getHumanReadableStatus,
getReportPersonalDetailsParticipants,
isAllowedToSubmitDraftExpenseReport,
isWorkspaceEligibleForReportChange,
Expand Down
3 changes: 3 additions & 0 deletions src/types/onyx/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ type Report = OnyxCommon.OnyxValueWithOfflineFeedback<
/** Invoice room receiver data */
invoiceReceiver?: InvoiceReceiver;

/** Number of transactions in the report */
transactionCount?: number;

/** ID of the parent report of the current report, if it exists */
parentReportID?: string;

Expand Down
1 change: 1 addition & 0 deletions src/types/utils/whitelistedReportKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ type WhitelistedReport = OnyxCommon.OnyxValueWithOfflineFeedback<
private_isArchived: unknown;
welcomeMessage: unknown;
agentZeroProcessingRequestIndicator: unknown;
transactionCount: unknown;
},
PolicyReportField['fieldID']
>;
Expand Down
Loading
Loading