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
90 changes: 0 additions & 90 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@
buildOptimisticEmptyReport,
buildOptimisticExportIntegrationAction,
buildOptimisticGroupChatReport,
buildOptimisticIOUReportAction,
buildOptimisticMovedReportAction,
buildOptimisticRenamedRoomReportAction,
buildOptimisticReportPreview,
Expand Down Expand Up @@ -280,7 +279,7 @@
/** @deprecated This value is deprecated and will be removed soon after migration. Use the email from useCurrentUserPersonalDetails hook instead. */
let deprecatedCurrentUserLogin: string | undefined;

Onyx.connect({

Check warning on line 282 in src/libs/actions/Report.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 @@ -294,7 +293,7 @@
},
});

Onyx.connect({

Check warning on line 296 in src/libs/actions/Report.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 @@ -302,7 +301,7 @@
// map of reportID to all reportActions for that report
const allReportActions: OnyxCollection<ReportActions> = {};

Onyx.connect({

Check warning on line 304 in src/libs/actions/Report.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,
callback: (actions, key) => {
if (!key || !actions) {
Expand All @@ -314,7 +313,7 @@
});

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

Check warning on line 316 in src/libs/actions/Report.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 @@ -323,7 +322,7 @@
});

let allPersonalDetails: OnyxEntry<PersonalDetailsList> = {};
Onyx.connect({

Check warning on line 325 in src/libs/actions/Report.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) => {
allPersonalDetails = value ?? {};
Expand All @@ -338,7 +337,7 @@
});

let onboarding: OnyxEntry<Onboarding>;
Onyx.connect({

Check warning on line 340 in src/libs/actions/Report.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.NVP_ONBOARDING,
callback: (val) => {
if (Array.isArray(val)) {
Expand All @@ -349,13 +348,13 @@
});

let introSelected: OnyxEntry<IntroSelected> = {};
Onyx.connect({

Check warning on line 351 in src/libs/actions/Report.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.NVP_INTRO_SELECTED,
callback: (val) => (introSelected = val),
});

let allReportDraftComments: Record<string, string | undefined> = {};
Onyx.connect({

Check warning on line 357 in src/libs/actions/Report.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_COMMENT,
waitForCollectionCallback: true,
callback: (value) => (allReportDraftComments = value),
Expand Down Expand Up @@ -1076,95 +1075,6 @@
});
}

// This is a legacy transactions that doesn't have either a transaction thread or a money request preview
if (transaction && !parentReportActionID) {
const transactionParentReportID = parentReportID ?? transaction?.reportID;
const iouReportActionID = rand64();

// Get the parent report to determine the actual submitter/owner of the expense
// Use optimisticSelfDMReport if provided (when selfDM exists but wasn't in allReports)
const parentReport =
transactionParentReportID === optimisticSelfDMReport?.reportID ? optimisticSelfDMReport : allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionParentReportID}`];
const submitterAccountID = parentReport?.ownerAccountID ?? deprecatedCurrentUserAccountID;
// eslint-disable-next-line @typescript-eslint/no-deprecated
const submitterEmail = PersonalDetailsUtils.getLoginsByAccountIDs([submitterAccountID]).at(0) ?? deprecatedCurrentUserLogin ?? '';
const submitterPersonalDetails = PersonalDetailsUtils.getPersonalDetailByEmail(submitterEmail);

const optimisticIOUAction = buildOptimisticIOUReportAction({
type: isSelfDM(parentReport) ? CONST.IOU.REPORT_ACTION_TYPE.TRACK : CONST.IOU.REPORT_ACTION_TYPE.CREATE,
amount: Math.abs(transaction.amount),
currency: transaction.currency,
comment: transaction.comment?.comment ?? '',
participants: [],
transactionID: transaction.transactionID,
isOwnPolicyExpenseChat: false,
reportActionID: iouReportActionID,
iouReportID: transactionParentReportID,
});

// Override actor fields to show the submitter instead of current user.
// This is needed for legacy transactions where the approver opens the transaction but it should show the submitter
optimisticIOUAction.actorAccountID = submitterAccountID;
optimisticIOUAction.person = [
{
style: 'strong',
text: submitterPersonalDetails?.displayName ?? submitterEmail,
type: 'TEXT',
},
];
optimisticIOUAction.avatar = submitterPersonalDetails?.avatar;

// We have a case where the transaction data is only available from the snapshot
// So we need to add the transaction data to Onyx so it's available when opening the report
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`,
value: transaction,
});

// Add violations if they exist. This is needed when opening from search results where
// violations are in the snapshot but not yet synced to the main collections, so we need
// to add them to Onyx to ensure they show up in the transaction thread
if (transactionViolations) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction.transactionID}`,
value: transactionViolations,
});
}

// Attach the optimistic IOU report action created for the transaction to the transaction thread
// Set chatReportID to link back to the parent policy expense chat for proper avatar rendering
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
parentReportActionID: iouReportActionID,
chatReportID: transactionParentReportID,
},
});

optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionParentReportID}`,
value: {
[iouReportActionID]: {
...optimisticIOUAction,
childReportID: reportID,
},
},
});

parameters.moneyRequestPreviewReportActionID = iouReportActionID;

// Log how often the legacy transaction fallback path is taken
Log.info('[Report] Legacy transaction fallback: creating money request preview', false, {
transactionParentReportID,
transactionID: transaction.transactionID,
reportID,
});
}

const isInviteOnboardingComplete = introSelected?.isInviteOnboardingComplete ?? false;
const isOnboardingCompleted = onboarding?.hasCompletedGuidedSetupFlow ?? false;

Expand Down
73 changes: 0 additions & 73 deletions tests/actions/ReportTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -901,79 +901,6 @@ describe('actions/Report', () => {
TestHelper.expectAPICommandToHaveBeenCalled(WRITE_COMMANDS.OPEN_REPORT, 1);
});

it('openReport legacy preview fallback stores action under correct Onyx key and preserves existing actions', async () => {
global.fetch = TestHelper.getGlobalFetchMock();

const TEST_USER_ACCOUNT_ID = 1;
const TEST_USER_LOGIN = 'test@user.com';
const SELF_DM_ID = '555';
const CHILD_REPORT_ID = '9999';
const TXN_ID = 'txn_123';

// Sign in and set personal details
await TestHelper.signInWithTestUser(TEST_USER_ACCOUNT_ID, TEST_USER_LOGIN);
await TestHelper.setPersonalDetails(TEST_USER_LOGIN, TEST_USER_ACCOUNT_ID);

// Seed a self-DM report
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${SELF_DM_ID}`, {
reportID: SELF_DM_ID,
chatType: CONST.REPORT.CHAT_TYPE.SELF_DM,
} as OnyxTypes.Report);

// Seed an existing action in self DM to ensure MERGE does not overwrite
await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${SELF_DM_ID}`, {
123: {
actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT,
message: [{type: 'COMMENT', html: 'Existing', text: 'Existing'}],
reportActionID: '123',
created: DateUtils.getDBTime(),
},
} as unknown as OnyxTypes.ReportActions);

// Seed a legacy transaction (no parentReportActionID)
await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${TXN_ID}`, {
transactionID: TXN_ID,
amount: -101,
currency: CONST.CURRENCY.USD,
comment: {comment: 'Legacy expense'},
} as unknown as OnyxTypes.Transaction);

// Get the transaction object from Onyx
const transaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION}${TXN_ID}` as const);
expect(transaction).toBeTruthy();

// Call openReport with transaction object to trigger the legacy preview flow
Report.openReport(CHILD_REPORT_ID, undefined, [], undefined, undefined, false, [], undefined, false, transaction ?? undefined, undefined, SELF_DM_ID);
await waitForBatchedUpdates();

// Validate the correct Onyx key received the new action and existing one is preserved
const selfDMActions = (await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${SELF_DM_ID}` as const)) as OnyxTypes.ReportActions | undefined;
expect(selfDMActions).toBeTruthy();
// Existing action still present
expect(selfDMActions?.['123']).toBeTruthy();

// Derive the created parentReportActionID from the self DM actions by finding the one that links to the child report
const entries = Object.entries(selfDMActions ?? {}) as Array<[string, OnyxTypes.ReportAction]>;
const createdEntry = entries.find((tuple): tuple is [string, OnyxTypes.ReportAction] => tuple?.[1]?.childReportID === CHILD_REPORT_ID);
expect(createdEntry).toBeDefined();
// Type guard for TS; the expect above will fail the test if undefined
if (!createdEntry) {
return;
}
const [parentReportActionID, createdAction] = createdEntry;
expect(createdAction.childReportID).toBe(CHILD_REPORT_ID);

// Ensure we did not create a stray concatenated key like reportActions_<selfDMReportID><generatedActionID>
const wrongKeyValue = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${SELF_DM_ID}${parentReportActionID}` as const);
expect(wrongKeyValue).toBeUndefined();

// The API call should include moneyRequestPreviewReportActionID matching the created action
TestHelper.expectAPICommandToHaveBeenCalledWith(WRITE_COMMANDS.OPEN_REPORT, 0, {
reportID: CHILD_REPORT_ID,
moneyRequestPreviewReportActionID: parentReportActionID,
});
});

it('should replace duplicate OpenReport commands with the same reportID', async () => {
global.fetch = TestHelper.getGlobalFetchMock();

Expand Down
Loading