Skip to content
Open
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
8 changes: 7 additions & 1 deletion src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@
existingTransactionThreadReportID?: string;
linkedTrackedExpenseReportAction?: ReportAction;
optimisticCreatedReportActionID?: string;
optimisticIOUCreatedReportActionID?: string;
reportActionID?: string;
};

Expand Down Expand Up @@ -936,7 +937,7 @@
const parsedReportActionMessageCache: Record<string, string> = {};

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

Check warning on line 940 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 @@ -944,7 +945,7 @@
});

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

Check warning on line 948 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 @@ -962,7 +963,7 @@
let allPersonalDetails: OnyxEntry<PersonalDetailsList>;
let allPersonalDetailLogins: string[];
let currentUserPersonalDetails: OnyxEntry<PersonalDetails>;
Onyx.connect({

Check warning on line 966 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 @@ -974,14 +975,14 @@
});

let allReportsDraft: OnyxCollection<Report>;
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.COLLECTION.REPORT_DRAFT,
waitForCollectionCallback: true,
callback: (value) => (allReportsDraft = value),
});

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

Check warning on line 985 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 @@ -989,7 +990,7 @@

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

Check warning on line 993 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 All @@ -1004,7 +1005,7 @@
return acc;
}

InteractionManager.runAfterInteractions(() => {

Check failure on line 1008 in src/libs/ReportUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

`runAfterInteractions` is deprecated
handlePreexistingReport(report);
});

Expand All @@ -1029,14 +1030,14 @@
});

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

Check warning on line 1033 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 1040 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 @@ -1062,7 +1063,7 @@
});

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

Check warning on line 1066 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 @@ -1075,7 +1076,7 @@

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

Check warning on line 1079 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 @@ -8392,6 +8393,7 @@
existingTransactionThreadReportID,
linkedTrackedExpenseReportAction,
optimisticCreatedReportActionID,
optimisticIOUCreatedReportActionID,
shouldGenerateTransactionThreadReport = true,
reportActionID,
}: OptimisticMoneyRequestEntities): [
Expand All @@ -8405,7 +8407,11 @@

// The `CREATED` action must be optimistically generated before the IOU action so that it won't appear after the IOU action in the chat.
const iouActionCreationTime = DateUtils.getDBTime();
const createdActionForIOUReport = buildOptimisticCreatedReportAction(payeeEmail, DateUtils.subtractMillisecondsFromDateTime(iouActionCreationTime, 1));
const createdActionForIOUReport = buildOptimisticCreatedReportAction(
payeeEmail,
DateUtils.subtractMillisecondsFromDateTime(iouActionCreationTime, 1),
optimisticIOUCreatedReportActionID,
);

const iouAction = buildOptimisticIOUReportAction({
type,
Expand Down
6 changes: 6 additions & 0 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ type RequestMoneyInformation = {
optimisticChatReportID?: string;
optimisticCreatedReportActionID?: string;
optimisticIOUReportID?: string;
optimisticIOUCreatedReportActionID?: string;
optimisticReportPreviewActionID?: string;
shouldGenerateTransactionThreadReport: boolean;
};
Expand All @@ -511,6 +512,7 @@ type MoneyRequestInformationParams = {
optimisticChatReportID?: string;
optimisticCreatedReportActionID?: string;
optimisticIOUReportID?: string;
optimisticIOUCreatedReportActionID?: string;
optimisticReportPreviewActionID?: string;
shouldGenerateTransactionThreadReport?: boolean;
isSplitExpense?: boolean;
Expand Down Expand Up @@ -3405,6 +3407,7 @@ function getMoneyRequestInformation(moneyRequestInformation: MoneyRequestInforma
optimisticChatReportID,
optimisticCreatedReportActionID,
optimisticIOUReportID,
optimisticIOUCreatedReportActionID,
optimisticReportPreviewActionID,
shouldGenerateTransactionThreadReport = true,
isSplitExpense,
Expand Down Expand Up @@ -3582,6 +3585,7 @@ function getMoneyRequestInformation(moneyRequestInformation: MoneyRequestInforma
transactionID: optimisticTransaction.transactionID,
paymentType: isSelectedManagerMcTest(participant.login) || transactionParams.receipt?.isTestDriveReceipt ? CONST.IOU.PAYMENT_TYPE.ELSEWHERE : undefined,
existingTransactionThreadReportID: linkedTrackedExpenseReportAction?.childReportID,
optimisticIOUCreatedReportActionID,
optimisticCreatedReportActionID,
linkedTrackedExpenseReportAction,
shouldGenerateTransactionThreadReport,
Expand Down Expand Up @@ -5871,6 +5875,7 @@ function requestMoney(requestMoneyInformation: RequestMoneyInformation) {
optimisticChatReportID,
optimisticCreatedReportActionID,
optimisticIOUReportID,
optimisticIOUCreatedReportActionID,
optimisticReportPreviewActionID,
shouldGenerateTransactionThreadReport,
} = requestMoneyInformation;
Expand Down Expand Up @@ -5956,6 +5961,7 @@ function requestMoney(requestMoneyInformation: RequestMoneyInformation) {
optimisticChatReportID,
optimisticCreatedReportActionID,
optimisticIOUReportID,
optimisticIOUCreatedReportActionID,
optimisticReportPreviewActionID,
shouldGenerateTransactionThreadReport,
action,
Expand Down
2 changes: 2 additions & 0 deletions src/pages/iou/request/step/IOURequestStepConfirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ function IOURequestStepConfirmation({
const optimisticChatReportID = generateReportID();
const optimisticCreatedReportActionID = rand64();
const optimisticIOUReportID = generateReportID();
const optimisticIOUCreatedReportActionID = rand64();
Copy link
Contributor

@ZhenjaHorbach ZhenjaHorbach Oct 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused
We are going to pass a random actionID
But we already use it for buildOptimisticCreatedReportAction by default

reportActionID: optimisticReportActionID ?? rand64(),

Copy link
Contributor Author

@bernhardoj bernhardoj Oct 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but it will be different for each expense created, and we want it to be the same.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh
Right
It makes sense

const optimisticReportPreviewActionID = rand64();

transactions.forEach((item, index) => {
Expand All @@ -504,6 +505,7 @@ function IOURequestStepConfirmation({
optimisticChatReportID,
optimisticCreatedReportActionID,
optimisticIOUReportID,
optimisticIOUCreatedReportActionID,
optimisticReportPreviewActionID,
participantParams: {
payeeEmail: currentUserPersonalDetails.login,
Expand Down
59 changes: 59 additions & 0 deletions tests/actions/IOUTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import {
getSortedReportActions,
isActionableTrackExpense,
isActionOfType,
isCreatedAction,
isMoneyRequestAction,
} from '@libs/ReportActionsUtils';
import type {OptimisticChatReport} from '@libs/ReportUtils';
Expand Down Expand Up @@ -2062,6 +2063,64 @@ describe('actions/IOU', () => {

expect(newNonReimbursableTotal).toBe(-100);
});

it('should create CREATED action with the passed optimistic ID', async () => {
const optimisticIOUCreatedReportActionID = rand64();
const optimisticIOUReportID = rand64();
const chatReportID = '123';
requestMoney({
report: {reportID: chatReportID},
participantParams: {
payeeEmail: RORY_EMAIL,
payeeAccountID: RORY_ACCOUNT_ID,
participant: {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID},
},
transactionParams: {
amount: 1,
attendees: [],
currency: CONST.CURRENCY.USD,
created: '',
merchant: '',
},
shouldGenerateTransactionThreadReport: true,
optimisticIOUCreatedReportActionID,
optimisticIOUReportID,
});
requestMoney({
report: {reportID: chatReportID},
participantParams: {
payeeEmail: RORY_EMAIL,
payeeAccountID: RORY_ACCOUNT_ID,
participant: {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID},
},
transactionParams: {
amount: 1,
attendees: [],
currency: CONST.CURRENCY.USD,
created: '',
merchant: '',
},
shouldGenerateTransactionThreadReport: true,
optimisticIOUCreatedReportActionID,
optimisticIOUReportID,
});

await waitForBatchedUpdates();

const iouReportActions = await new Promise<OnyxEntry<ReportActions>>((resolve) => {
const connection = Onyx.connectWithoutView({
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticIOUReportID}`,
callback: (reportActions) => {
resolve(reportActions);
Onyx.disconnect(connection);
},
});
});
const createdActions = Object.values(iouReportActions ?? {}).find(
(reportAction) => isCreatedAction(reportAction) && reportAction.reportActionID === optimisticIOUCreatedReportActionID,
);
expect(createdActions).not.toBeUndefined();
});
});

describe('createDistanceRequest', () => {
Expand Down
Loading