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
9 changes: 6 additions & 3 deletions src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2246,6 +2246,7 @@ function getIOUReportActionMessage(iouReportID, type, total, comment, currency,
* @param {Boolean} [isSendMoneyFlow] - Whether this is send money flow
* @param {Object} [receipt]
* @param {Boolean} [isOwnPolicyExpenseChat] - Whether this is an expense report create from the current user's policy expense chat
* @param {String} [created] - Action created time
* @returns {Object}
*/
function buildOptimisticIOUReportAction(
Expand All @@ -2261,6 +2262,7 @@ function buildOptimisticIOUReportAction(
isSendMoneyFlow = false,
receipt = {},
isOwnPolicyExpenseChat = false,
created = DateUtils.getDBTime(),
) {
const IOUReportID = iouReportID || generateReportID();

Expand Down Expand Up @@ -2318,7 +2320,7 @@ function buildOptimisticIOUReportAction(
],
reportActionID: NumberUtils.rand64(),
shouldShow: true,
created: DateUtils.getDBTime(),
created,
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
receipt,
whisperedToAccountIDs: _.contains([CONST.IOU.RECEIPT_STATE.SCANREADY, CONST.IOU.RECEIPT_STATE.SCANNING], receipt.state) ? [currentUserAccountID] : [],
Expand Down Expand Up @@ -2626,9 +2628,10 @@ function buildOptimisticChatReport(
/**
* Returns the necessary reportAction onyx data to indicate that the chat has been created optimistically
* @param {String} emailCreatingAction
* @param {String} [created] - Action created time
* @returns {Object}
*/
function buildOptimisticCreatedReportAction(emailCreatingAction) {
function buildOptimisticCreatedReportAction(emailCreatingAction, created = DateUtils.getDBTime()) {
return {
reportActionID: NumberUtils.rand64(),
actionName: CONST.REPORT.ACTIONS.TYPE.CREATED,
Expand All @@ -2655,7 +2658,7 @@ function buildOptimisticCreatedReportAction(emailCreatingAction) {
],
automatic: false,
avatar: lodashGet(allPersonalDetails, [currentUserAccountID, 'avatar'], UserUtils.getDefaultAvatar(currentUserAccountID)),
created: DateUtils.getDBTime(),
created,
shouldShow: true,
};
}
Expand Down
13 changes: 11 additions & 2 deletions src/libs/actions/IOU.js
Original file line number Diff line number Diff line change
Expand Up @@ -524,8 +524,9 @@ function getMoneyRequestInformation(
// 3. IOU action for the iouReport
// 4. REPORTPREVIEW action for the chatReport
// Note: The CREATED action for the IOU report must be optimistically generated before the IOU action so there's no chance that it appears after the IOU action in the chat
const currentTime = DateUtils.getDBTime();
const optimisticCreatedActionForChat = ReportUtils.buildOptimisticCreatedReportAction(payeeEmail);
const optimisticCreatedActionForIOU = ReportUtils.buildOptimisticCreatedReportAction(payeeEmail);
const optimisticCreatedActionForIOU = ReportUtils.buildOptimisticCreatedReportAction(payeeEmail, DateUtils.subtractMillisecondsFromDateTime(currentTime, 1));
const iouAction = ReportUtils.buildOptimisticIOUReportAction(
CONST.IOU.REPORT_ACTION_TYPE.CREATE,
amount,
Expand All @@ -538,6 +539,8 @@ function getMoneyRequestInformation(
false,
false,
receiptObject,
false,
currentTime,
);

let reportPreviewAction = isNewIOUReport ? null : ReportActionsUtils.getReportPreviewAction(chatReport.reportID, iouReport.reportID);
Expand Down Expand Up @@ -1119,8 +1122,9 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
// 3. IOU action for the iouReport
// 4. REPORTPREVIEW action for the chatReport
// Note: The CREATED action for the IOU report must be optimistically generated before the IOU action so there's no chance that it appears after the IOU action in the chat
const currentTime = DateUtils.getDBTime();
const oneOnOneCreatedActionForChat = ReportUtils.buildOptimisticCreatedReportAction(currentUserEmailForIOUSplit);
const oneOnOneCreatedActionForIOU = ReportUtils.buildOptimisticCreatedReportAction(currentUserEmailForIOUSplit);
const oneOnOneCreatedActionForIOU = ReportUtils.buildOptimisticCreatedReportAction(currentUserEmailForIOUSplit, DateUtils.subtractMillisecondsFromDateTime(currentTime, 1));
const oneOnOneIOUAction = ReportUtils.buildOptimisticIOUReportAction(
CONST.IOU.REPORT_ACTION_TYPE.CREATE,
splitAmount,
Expand All @@ -1130,6 +1134,11 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
oneOnOneTransaction.transactionID,
'',
oneOnOneIOUReport.reportID,
undefined,
undefined,
undefined,
undefined,
currentTime,
);

// Add optimistic personal details for new participants
Expand Down
18 changes: 12 additions & 6 deletions tests/actions/IOUTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ describe('actions/IOU', () => {
iouAction = iouActions[0];

// The CREATED action should not be created after the IOU action
expect(Date.parse(createdAction.created)).toBeLessThanOrEqual(Date.parse(iouAction.created));
expect(Date.parse(createdAction.created)).toBeLessThan(Date.parse(iouAction.created));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fortunately we already have the unit test, but it uses toBeLessThanOrEqual, so I changed it to toBeLessThan.

// The IOUReportID should be correct
expect(iouAction.originalMessage.IOUReportID).toBe(iouReportID);
Expand Down Expand Up @@ -213,6 +213,7 @@ describe('actions/IOU', () => {
};
let iouReportID;
let iouAction;
let iouCreatedAction;
let transactionID;
fetch.pause();
return Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, chatReport)
Expand Down Expand Up @@ -261,10 +262,11 @@ describe('actions/IOU', () => {

// The chat report should have a CREATED and an IOU action
expect(_.size(allIOUReportActions)).toBe(2);
iouCreatedAction = _.find(allIOUReportActions, (reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED);
iouAction = _.find(allIOUReportActions, (reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU);

// The CREATED action should not be created after the IOU action
expect(Date.parse(createdAction.created)).toBeLessThanOrEqual(Date.parse(iouAction.created));
expect(Date.parse(iouCreatedAction.created)).toBeLessThan(Date.parse(iouAction.created));

@bernhardoj bernhardoj Sep 13, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I changed it from createdAction to iouCreatedAction because createdAction is the CREATED action of the chat report, not the iou report, otherwise it will fail.

// The IOUReportID should be correct
expect(iouAction.originalMessage.IOUReportID).toBe(iouReportID);
Expand Down Expand Up @@ -598,7 +600,7 @@ describe('actions/IOU', () => {
iouAction = iouActions[0];

// The CREATED action should not be created after the IOU action
expect(Date.parse(createdAction.created)).toBeLessThanOrEqual(Date.parse(iouAction.created));
expect(Date.parse(createdAction.created)).toBeLessThan(Date.parse(iouAction.created));

// The IOUReportID should be correct
expect(iouAction.originalMessage.IOUReportID).toBe(iouReportID);
Expand Down Expand Up @@ -865,9 +867,11 @@ describe('actions/IOU', () => {

let carlosIOUReport;
let carlosIOUAction;
let carlosIOUCreatedAction;
let carlosTransaction;

let julesIOUAction;
let julesIOUCreatedAction;
let julesTransaction;

let vitChatReport;
Expand Down Expand Up @@ -1010,17 +1014,19 @@ describe('actions/IOU', () => {

// Carlos DM should have two reportActions – the existing CREATED action and a pending IOU action
expect(_.size(carlosReportActions)).toBe(2);
carlosIOUCreatedAction = _.find(carlosReportActions, (reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED);
carlosIOUAction = _.find(carlosReportActions, (reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU);
expect(carlosIOUAction.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD);
expect(carlosIOUAction.originalMessage.IOUReportID).toBe(carlosIOUReport.reportID);
expect(carlosIOUAction.originalMessage.amount).toBe(amount / 4);
expect(carlosIOUAction.originalMessage.comment).toBe(comment);
expect(carlosIOUAction.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE);
expect(Date.parse(carlosCreatedAction.created)).toBeLessThanOrEqual(Date.parse(carlosIOUAction.created));
expect(Date.parse(carlosIOUCreatedAction.created)).toBeLessThan(Date.parse(carlosIOUAction.created));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same reason as above

// Jules DM should have three reportActions, the existing CREATED action, the existing IOU action, and a new pending IOU action
expect(_.size(julesReportActions)).toBe(3);
expect(julesReportActions[julesCreatedAction.reportActionID]).toStrictEqual(julesCreatedAction);
julesIOUCreatedAction = _.find(julesReportActions, (reportAction) => reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED);
julesIOUAction = _.find(
julesReportActions,
(reportAction) =>
Expand All @@ -1031,7 +1037,7 @@ describe('actions/IOU', () => {
expect(julesIOUAction.originalMessage.amount).toBe(amount / 4);
expect(julesIOUAction.originalMessage.comment).toBe(comment);
expect(julesIOUAction.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE);
expect(Date.parse(julesCreatedAction.created)).toBeLessThanOrEqual(Date.parse(julesIOUAction.created));
expect(Date.parse(julesIOUCreatedAction.created)).toBeLessThan(Date.parse(julesIOUAction.created));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same reason as above

// Vit DM should have two reportActions – a pending CREATED action and a pending IOU action
expect(_.size(vitReportActions)).toBe(2);
Expand All @@ -1043,7 +1049,7 @@ describe('actions/IOU', () => {
expect(vitIOUAction.originalMessage.amount).toBe(amount / 4);
expect(vitIOUAction.originalMessage.comment).toBe(comment);
expect(vitIOUAction.originalMessage.type).toBe(CONST.IOU.REPORT_ACTION_TYPE.CREATE);
expect(Date.parse(vitCreatedAction.created)).toBeLessThanOrEqual(Date.parse(vitIOUAction.created));
expect(Date.parse(vitCreatedAction.created)).toBeLessThan(Date.parse(vitIOUAction.created));

// Group chat should have two reportActions – a pending CREATED action and a pending IOU action w/ type SPLIT
expect(_.size(groupReportActions)).toBe(2);
Expand Down