Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: optimistic iou report date not matching #39665

Closed
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
19 changes: 14 additions & 5 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3552,9 +3552,18 @@ function buildOptimisticTaskCommentReportAction(
* @param chatReportID - Report ID of the chat where the IOU is.
* @param currency - IOU currency.
* @param isSendingMoney - If we pay someone the IOU should be created as settled
* @param created - The creation time for IOU action
*/

function buildOptimisticIOUReport(payeeAccountID: number, payerAccountID: number, total: number, chatReportID: string, currency: string, isSendingMoney = false): OptimisticIOUReport {
function buildOptimisticIOUReport(
payeeAccountID: number,
payerAccountID: number,
total: number,
chatReportID: string,
currency: string,
isSendingMoney = false,
created: string = DateUtils.getDBTime(),
): OptimisticIOUReport {
const formattedTotal = CurrencyUtils.convertToDisplayString(total, currency);
const personalDetails = getPersonalDetailsForAccountID(payerAccountID);
const payerEmail = 'login' in personalDetails ? personalDetails.login : '';
Expand All @@ -3580,7 +3589,7 @@ function buildOptimisticIOUReport(payeeAccountID: number, payerAccountID: number
reportName: `${payerEmail} owes ${formattedTotal}`,
notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
parentReportID: chatReportID,
lastVisibleActionCreated: DateUtils.getDBTime(),
lastVisibleActionCreated: created,
};
}

Expand Down Expand Up @@ -4049,7 +4058,7 @@ function buildOptimisticReportPreview(chatReport: OnyxEntry<Report>, iouReport:
const hasReceipt = TransactionUtils.hasReceipt(transaction);
const isReceiptBeingScanned = hasReceipt && TransactionUtils.isReceiptBeingScanned(transaction);
const message = getReportPreviewMessage(iouReport);
const created = DateUtils.getDBTime();
const created = iouReport.lastVisibleActionCreated ?? DateUtils.getDBTime();
return {
reportActionID: NumberUtils.rand64(),
reportID: chatReport?.reportID,
Expand Down Expand Up @@ -4797,10 +4806,10 @@ function buildOptimisticMoneyRequestEntities(
existingTransactionThreadReportID?: string,
linkedTrackedExpenseReportAction?: ReportAction,
): [OptimisticCreatedReportAction, OptimisticCreatedReportAction, OptimisticIOUReportAction, OptimisticChatReport, OptimisticCreatedReportAction | EmptyObject] {
const createdActionForChat = buildOptimisticCreatedReportAction(payeeEmail);
const createdActionForChat = buildOptimisticCreatedReportAction(payeeEmail, iouReport.lastVisibleActionCreated);

// 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 iouActionCreationTime = !iouReport.lastVisibleActionCreated || isEmpty(iouReport.lastVisibleActionCreated) ? DateUtils.getDBTime() : iouReport.lastVisibleActionCreated;
const createdActionForIOUReport = buildOptimisticCreatedReportAction(payeeEmail, DateUtils.subtractMillisecondsFromDateTime(iouActionCreationTime, 1));

const iouAction = buildOptimisticIOUReportAction(
Expand Down
6 changes: 4 additions & 2 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,14 +463,15 @@ function buildOnyxDataForMoneyRequest(
newQuickAction = CONST.QUICK_ACTIONS.REQUEST_DISTANCE;
}
const existingTransactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${existingTransactionThreadReportID}`] ?? null;

if (chatReport) {
optimisticData.push({
// Use SET for new reports because it doesn't exist yet, is faster and we need the data to be available when we navigate to the chat page
onyxMethod: isNewChatReport ? Onyx.METHOD.SET : Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
value: {
...chatReport,
// if it is a new money request then that becomes the most recent visible action
lastVisibleActionCreated: shouldCreateNewMoneyRequestReport ? iouReport.lastVisibleActionCreated : undefined,
lastReadTime: DateUtils.getDBTime(),
lastMessageTranslationKey: '',
iouReportID: iouReport.reportID,
Expand Down Expand Up @@ -1794,7 +1795,7 @@ function getMoneyRequestInformation(
if (!iouReport || shouldCreateNewMoneyRequestReport) {
iouReport = isPolicyExpenseChat
? ReportUtils.buildOptimisticExpenseReport(chatReport.reportID, chatReport.policyID ?? '', payeeAccountID, amount, currency)
: ReportUtils.buildOptimisticIOUReport(payeeAccountID, payerAccountID, amount, chatReport.reportID, currency);
: ReportUtils.buildOptimisticIOUReport(payeeAccountID, payerAccountID, amount, chatReport.reportID, currency, false, created);
} else if (isPolicyExpenseChat) {
iouReport = {...iouReport};
if (iouReport?.currency === currency && typeof iouReport.total === 'number') {
Expand All @@ -1804,6 +1805,7 @@ function getMoneyRequestInformation(
} else {
iouReport = IOUUtils.updateIOUOwnerAndTotal(iouReport, payeeAccountID, amount, currency);
}

// STEP 3: Build optimistic receipt and transaction
const receiptObject: Receipt = {};
let filename;
Expand Down
3 changes: 2 additions & 1 deletion src/pages/home/report/ReportActionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,8 @@ function ReportActionsList({
);
const lastActionIndex = sortedVisibleReportActions[0]?.reportActionID;
const reportActionSize = useRef(sortedVisibleReportActions.length);
const hasNewestReportAction = sortedReportActions?.[0].created === report.lastVisibleActionCreated;
const hasNewestReportAction =
sortedReportActions?.[0].created === report.lastVisibleActionCreated || sortedReportActions?.[0].created === transactionThreadReport?.lastVisibleActionCreated || sortedReportActions.some((reportAction) => reportAction.created === report.lastVisibleActionCreated);
const hasNewestReportActionRef = useRef(hasNewestReportAction);
hasNewestReportActionRef.current = hasNewestReportAction;
const previousLastIndex = useRef(lastActionIndex);
Expand Down
9 changes: 7 additions & 2 deletions tests/actions/IOUTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ describe('actions/IOU', () => {
it('updates existing chat report if there is one', () => {
const amount = 10000;
const comment = 'Giv money plz';
const created = DateUtils.getDBTime();
let chatReport: OnyxTypes.Report = {
reportID: '1234',
type: CONST.REPORT.TYPE.CHAT,
Expand All @@ -254,7 +255,7 @@ describe('actions/IOU', () => {
const createdAction: OnyxTypes.ReportAction = {
reportActionID: NumberUtils.rand64(),
actionName: CONST.REPORT.ACTIONS.TYPE.CREATED,
created: DateUtils.getDBTime(),
created,
};
let iouReportID: string | undefined;
let iouAction: OnyxEntry<OnyxTypes.ReportAction>;
Expand All @@ -270,7 +271,7 @@ describe('actions/IOU', () => {
}),
)
.then(() => {
IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, '', '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment, {});
IOU.requestMoney(chatReport, amount, CONST.CURRENCY.USD, created, '', RORY_EMAIL, RORY_ACCOUNT_ID, {login: CARLOS_EMAIL, accountID: CARLOS_ACCOUNT_ID}, comment, {});
return waitForBatchedUpdates();
})
.then(
Expand Down Expand Up @@ -318,6 +319,10 @@ describe('actions/IOU', () => {
// The CREATED action should not be created after the IOU action
expect(Date.parse(iouCreatedAction?.created ?? '')).toBeLessThan(Date.parse(iouAction?.created ?? ''));

// The iouAction created time should be same as lastVisibleActionCreated
// To prevent the "New message" from showing up in the report list
expect(iouAction?.created).toBe(chatReport.lastVisibleActionCreated);

// The IOUReportID should be correct
expect(iouAction?.originalMessage?.IOUReportID).toBe(iouReportID);

Expand Down
Loading