From 739ecd6fad1bd2e24e88ba4ff7857cc36c15ebf4 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 26 May 2025 13:36:53 +0200 Subject: [PATCH 1/7] fix optimistic message for reopen --- src/libs/NextStepUtils.ts | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts index 0a850c42c91d..d20cd231fe96 100644 --- a/src/libs/NextStepUtils.ts +++ b/src/libs/NextStepUtils.ts @@ -116,9 +116,16 @@ function buildOptimisticNextStepForPreventSelfApprovalsEnabled() { * @param predictedNextStatus - a next expected status of the report * @param shouldFixViolations - whether to show `fix the issue` next step * @param isUnapprove - whether a report is being unapproved + * @param isReopen - whether a report is being reopened * @returns nextStep */ -function buildNextStep(report: OnyxEntry, predictedNextStatus: ValueOf, shouldFixViolations?: boolean, isUnapprove?: boolean): ReportNextStep | null { +function buildNextStep( + report: OnyxEntry, + predictedNextStatus: ValueOf, + shouldFixViolations?: boolean, + isUnapprove?: boolean, + isReopen?: boolean, +): ReportNextStep | null { if (!isExpenseReport(report)) { return null; } @@ -209,6 +216,33 @@ function buildNextStep(report: OnyxEntry, predictedNextStatus: ValueOf Date: Mon, 26 May 2025 13:37:23 +0200 Subject: [PATCH 2/7] fix err message --- src/languages/en.ts | 1 + src/languages/es.ts | 1 + src/libs/actions/IOU.ts | 5 ++--- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 1abeb7d3bfbd..c26f52cf68c9 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1130,6 +1130,7 @@ const translations = { quantityGreaterThanZero: 'Quantity must be greater than zero', invalidSubrateLength: 'There must be at least one subrate', invalidRate: 'Rate not valid for this workspace. Please select an available rate from the workspace.', + reopenError: 'This report has already been reopened', }, dismissReceiptError: 'Dismiss error', dismissReceiptErrorConfirmation: 'Heads up! Dismissing this error will remove your uploaded receipt entirely. Are you sure?', diff --git a/src/languages/es.ts b/src/languages/es.ts index 7bfea7c15bd0..b3133e92c541 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1128,6 +1128,7 @@ const translations = { quantityGreaterThanZero: 'La cantidad debe ser mayor que cero', invalidSubrateLength: 'Debe haber al menos una subtasa', invalidRate: 'Tasa no válida para este espacio de trabajo. Por favor, selecciona una tasa disponible en el espacio de trabajo.', + reopenError: 'Este informe ya ha sido reabierto', }, dismissReceiptError: 'Descartar error', dismissReceiptErrorConfirmation: '¡Atención! Descartar este error eliminará completamente tu recibo cargado. ¿Estás seguro?', diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index fef8f7f1398d..7cc0a29cd367 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -9356,7 +9356,7 @@ function reopenReport(expenseReport: OnyxEntry) { const predictedNextState = CONST.REPORT.STATE_NUM.OPEN; const predictedNextStatus = CONST.REPORT.STATUS_NUM.OPEN; - const optimisticNextStep = buildNextStep(expenseReport, predictedNextStatus); + const optimisticNextStep = buildNextStep(expenseReport, predictedNextStatus, undefined, undefined, true); const optimisticReportActionsData: OnyxUpdate = { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, @@ -9417,8 +9417,7 @@ function reopenReport(expenseReport: OnyxEntry) { key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, value: { [optimisticReopenedReportAction.reportActionID]: { - pendingAction: null, - errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.other'), + errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.reopenError'), }, }, }, From fd568040cc477d7d3198d54b86987ef95ba48cc2 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 26 May 2025 15:21:36 +0200 Subject: [PATCH 3/7] fix reopened report bugs --- src/libs/ReportActionsUtils.ts | 5 +++++ src/libs/ReportPrimaryActionUtils.ts | 14 ++++++++++---- src/libs/ReportSecondaryActionUtils.ts | 16 +++++++++++----- src/libs/ReportUtils.ts | 11 +++++++++++ 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index f3675e651c97..adff8104e6a1 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -380,6 +380,10 @@ function isRenamedAction(reportAction: OnyxEntry): reportAction is return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.RENAMED); } +function isReopenedAction(reportAction: OnyxEntry): reportAction is ReportAction { + return isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.REOPENED); +} + function isRoomChangeLogAction(reportAction: OnyxEntry): reportAction is ReportAction> { return isActionOfType(reportAction, ...Object.values(CONST.REPORT.ACTIONS.TYPE.ROOM_CHANGE_LOG)); } @@ -2555,6 +2559,7 @@ export { getReopenedMessage, getLeaveRoomMessage, getReportActionFromExpensifyCard, + isReopenedAction, }; export type {LastVisibleMessage}; diff --git a/src/libs/ReportPrimaryActionUtils.ts b/src/libs/ReportPrimaryActionUtils.ts index 5c1b2650e23b..1ba8f8fd0b60 100644 --- a/src/libs/ReportPrimaryActionUtils.ts +++ b/src/libs/ReportPrimaryActionUtils.ts @@ -19,6 +19,7 @@ import { getParentReport, hasExportError as hasExportErrorUtil, hasOnlyHeldExpenses, + hasReportBeenReopened as hasReportBeenReopenedUtils, isArchivedReport, isClosedReport as isClosedReportUtils, isCurrentUserSubmitter, @@ -52,7 +53,7 @@ function isAddExpenseAction(report: Report, reportTransactions: Transaction[]) { return isExpenseReport && canAddTransaction && isReportSubmitter && reportTransactions.length === 0; } -function isSubmitAction(report: Report, reportTransactions: Transaction[], policy?: Policy, reportNameValuePairs?: ReportNameValuePairs) { +function isSubmitAction(report: Report, reportTransactions: Transaction[], policy?: Policy, reportNameValuePairs?: ReportNameValuePairs, reportActions?: ReportAction[]) { if (isArchivedReport(reportNameValuePairs)) { return false; } @@ -62,7 +63,7 @@ function isSubmitAction(report: Report, reportTransactions: Transaction[], polic const isOpenReport = isOpenReportUtils(report); const isManualSubmitEnabled = getCorrectedAutoReportingFrequency(policy) === CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL; const transactionAreComplete = reportTransactions.every((transaction) => transaction.amount !== 0 || transaction.modifiedAmount !== 0); - + const hasReportBeenReopened = hasReportBeenReopenedUtils(reportActions); const isAnyReceiptBeingScanned = reportTransactions?.some((transaction) => isReceiptBeingScanned(transaction)); if (isAnyReceiptBeingScanned) { @@ -75,7 +76,12 @@ function isSubmitAction(report: Report, reportTransactions: Transaction[], polic return false; } - return isExpenseReport && isReportSubmitter && isOpenReport && isManualSubmitEnabled && reportTransactions.length !== 0 && transactionAreComplete; + const baseIsSubmit = isExpenseReport && isReportSubmitter && isOpenReport && reportTransactions.length !== 0 && transactionAreComplete; + if (hasReportBeenReopened && baseIsSubmit) { + return true; + } + + return isManualSubmitEnabled && baseIsSubmit; } function isApproveAction(report: Report, reportTransactions: Transaction[], policy?: Policy) { @@ -290,7 +296,7 @@ function getReportPrimaryAction( return CONST.REPORT.PRIMARY_ACTIONS.REMOVE_HOLD; } - if (isSubmitAction(report, reportTransactions, policy, reportNameValuePairs)) { + if (isSubmitAction(report, reportTransactions, policy, reportNameValuePairs, reportActions)) { return CONST.REPORT.PRIMARY_ACTIONS.SUBMIT; } diff --git a/src/libs/ReportSecondaryActionUtils.ts b/src/libs/ReportSecondaryActionUtils.ts index 0086a74844aa..7a1839a4b4ed 100644 --- a/src/libs/ReportSecondaryActionUtils.ts +++ b/src/libs/ReportSecondaryActionUtils.ts @@ -33,6 +33,7 @@ import { isReportManager as isReportManagerUtils, isSettled, isWorkspaceEligibleForReportChange, + hasReportBeenReopened as hasReportBeenReopenedUtils, } from './ReportUtils'; import {getSession} from './SessionUtils'; import {allHavePendingRTERViolation, isDuplicate, isOnHold as isOnHoldTransactionUtils, shouldShowBrokenConnectionViolationForMultipleTransactions} from './TransactionUtils'; @@ -47,7 +48,7 @@ function isAddExpenseAction(report: Report, reportTransactions: Transaction[]) { return canAddTransaction(report); } -function isSubmitAction(report: Report, reportTransactions: Transaction[], policy?: Policy, reportNameValuePairs?: ReportNameValuePairs): boolean { +function isSubmitAction(report: Report, reportTransactions: Transaction[], policy?: Policy, reportNameValuePairs?: ReportNameValuePairs, reportActions?: ReportAction[]): boolean { if (isArchivedReport(reportNameValuePairs)) { return false; } @@ -59,17 +60,17 @@ function isSubmitAction(report: Report, reportTransactions: Transaction[], polic } const isExpenseReport = isExpenseReportUtils(report); - + if (!isExpenseReport || report?.total === 0) { return false; } - + const isReportSubmitter = isCurrentUserSubmitter(report.reportID); const isReportApprover = isApproverUtils(policy, getCurrentUserAccountID()); if (!isReportSubmitter && !isReportApprover) { return false; } - + const isOpenReport = isOpenReportUtils(report); if (!isOpenReport) { return false; @@ -80,6 +81,11 @@ function isSubmitAction(report: Report, reportTransactions: Transaction[], polic return false; } + const hasReportBeenReopened = hasReportBeenReopenedUtils(reportActions); + if (hasReportBeenReopened && isReportSubmitter) { + return false; + } + const isAdmin = policy?.role === CONST.POLICY.ROLE.ADMIN; const isManager = report.managerID === getCurrentUserAccountID(); if (isAdmin || isManager) { @@ -404,7 +410,7 @@ function getSecondaryReportActions( options.push(CONST.REPORT.SECONDARY_ACTIONS.ADD_EXPENSE); } - if (isSubmitAction(report, reportTransactions, policy, reportNameValuePairs)) { + if (isSubmitAction(report, reportTransactions, policy, reportNameValuePairs, reportActions)) { options.push(CONST.REPORT.SECONDARY_ACTIONS.SUBMIT); } diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index dc0aae394251..eaf8210ae5e4 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -174,6 +174,7 @@ import { isApprovedOrSubmittedReportAction, isCardIssuedAction, isClosedAction, + isReopenedAction, isCreatedTaskReportAction, isCurrentActionUnread, isDeletedAction, @@ -10782,6 +10783,15 @@ function getReportAttributes(reportID: string | undefined, reportAttributes?: Re return attributes[reportID]; } +function hasReportBeenReopened(reportActions: OnyxEntry | ReportAction[]): boolean { + if (!reportActions) { + return false; + } + + const reportActionList = Array.isArray(reportActions) ? reportActions : Object.values(reportActions); + return reportActionList.some((action) => isReopenedAction(action)); +} + export { addDomainToShortMention, completeShortMention, @@ -11162,6 +11172,7 @@ export { isWorkspaceEligibleForReportChange, getReportAttributes, navigateOnDeleteExpense, + hasReportBeenReopened, }; export type { From 41d71033da2a8d64e7bd82a3a4aa09193afceb2e Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 26 May 2025 16:17:38 +0200 Subject: [PATCH 4/7] revert err message --- src/languages/en.ts | 1 - src/languages/es.ts | 1 - src/libs/actions/IOU.ts | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index c26f52cf68c9..1abeb7d3bfbd 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1130,7 +1130,6 @@ const translations = { quantityGreaterThanZero: 'Quantity must be greater than zero', invalidSubrateLength: 'There must be at least one subrate', invalidRate: 'Rate not valid for this workspace. Please select an available rate from the workspace.', - reopenError: 'This report has already been reopened', }, dismissReceiptError: 'Dismiss error', dismissReceiptErrorConfirmation: 'Heads up! Dismissing this error will remove your uploaded receipt entirely. Are you sure?', diff --git a/src/languages/es.ts b/src/languages/es.ts index b3133e92c541..7bfea7c15bd0 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1128,7 +1128,6 @@ const translations = { quantityGreaterThanZero: 'La cantidad debe ser mayor que cero', invalidSubrateLength: 'Debe haber al menos una subtasa', invalidRate: 'Tasa no válida para este espacio de trabajo. Por favor, selecciona una tasa disponible en el espacio de trabajo.', - reopenError: 'Este informe ya ha sido reabierto', }, dismissReceiptError: 'Descartar error', dismissReceiptErrorConfirmation: '¡Atención! Descartar este error eliminará completamente tu recibo cargado. ¿Estás seguro?', diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 7cc0a29cd367..8ddfed076ff5 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -9417,7 +9417,7 @@ function reopenReport(expenseReport: OnyxEntry) { key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, value: { [optimisticReopenedReportAction.reportActionID]: { - errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.reopenError'), + errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.other'), }, }, }, From 1bf1c081cc6460cc6aee69ad75efdf886224fcef Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 26 May 2025 16:39:08 +0200 Subject: [PATCH 5/7] run pretty --- src/libs/ReportSecondaryActionUtils.ts | 8 ++++---- src/libs/ReportUtils.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libs/ReportSecondaryActionUtils.ts b/src/libs/ReportSecondaryActionUtils.ts index 7a1839a4b4ed..a1b990e965e0 100644 --- a/src/libs/ReportSecondaryActionUtils.ts +++ b/src/libs/ReportSecondaryActionUtils.ts @@ -19,6 +19,7 @@ import { canAddTransaction, canEditFieldOfMoneyRequest, canEditReportPolicy, + hasReportBeenReopened as hasReportBeenReopenedUtils, isArchivedReport, isClosedReport as isClosedReportUtils, isCurrentUserSubmitter, @@ -33,7 +34,6 @@ import { isReportManager as isReportManagerUtils, isSettled, isWorkspaceEligibleForReportChange, - hasReportBeenReopened as hasReportBeenReopenedUtils, } from './ReportUtils'; import {getSession} from './SessionUtils'; import {allHavePendingRTERViolation, isDuplicate, isOnHold as isOnHoldTransactionUtils, shouldShowBrokenConnectionViolationForMultipleTransactions} from './TransactionUtils'; @@ -60,17 +60,17 @@ function isSubmitAction(report: Report, reportTransactions: Transaction[], polic } const isExpenseReport = isExpenseReportUtils(report); - + if (!isExpenseReport || report?.total === 0) { return false; } - + const isReportSubmitter = isCurrentUserSubmitter(report.reportID); const isReportApprover = isApproverUtils(policy, getCurrentUserAccountID()); if (!isReportSubmitter && !isReportApprover) { return false; } - + const isOpenReport = isOpenReportUtils(report); if (!isOpenReport) { return false; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index eaf8210ae5e4..d611dc049d1b 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -174,7 +174,6 @@ import { isApprovedOrSubmittedReportAction, isCardIssuedAction, isClosedAction, - isReopenedAction, isCreatedTaskReportAction, isCurrentActionUnread, isDeletedAction, @@ -190,6 +189,7 @@ import { isPolicyChangeLogAction, isReimbursementQueuedAction, isRenamedAction, + isReopenedAction, isReportActionAttachment, isReportPreviewAction, isReversedTransaction, From 9b7fcc55ec893c899693f2ea6334deff3af14b7a Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Thu, 29 May 2025 17:11:55 +0200 Subject: [PATCH 6/7] run pretty --- src/libs/ReportSecondaryActionUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportSecondaryActionUtils.ts b/src/libs/ReportSecondaryActionUtils.ts index c0a7d43941cf..1c0262e94a5e 100644 --- a/src/libs/ReportSecondaryActionUtils.ts +++ b/src/libs/ReportSecondaryActionUtils.ts @@ -22,10 +22,10 @@ import { canAddTransaction, canEditFieldOfMoneyRequest, canEditReportPolicy, - hasReportBeenReopened as hasReportBeenReopenedUtils, canHoldUnholdReportAction, getTransactionDetails, hasOnlyHeldExpenses, + hasReportBeenReopened as hasReportBeenReopenedUtils, isArchivedReport, isClosedReport as isClosedReportUtils, isCurrentUserSubmitter, From a72b3164b63eb93a0542e6d35c2a0696418e3f22 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Thu, 29 May 2025 22:21:35 +0200 Subject: [PATCH 7/7] fix bad merge --- src/libs/ReportSecondaryActionUtils.ts | 37 -------------------------- 1 file changed, 37 deletions(-) diff --git a/src/libs/ReportSecondaryActionUtils.ts b/src/libs/ReportSecondaryActionUtils.ts index 8f7d9e7f6b90..5da6288a2b7c 100644 --- a/src/libs/ReportSecondaryActionUtils.ts +++ b/src/libs/ReportSecondaryActionUtils.ts @@ -61,43 +61,6 @@ function isAddExpenseAction(report: Report, reportTransactions: Transaction[]) { return canAddTransaction(report); } -function isSplitAction(report: Report, reportTransactions: Transaction[], policy?: Policy): boolean { - if (Number(reportTransactions?.length) !== 1) { - return false; - } - - const reportTransaction = reportTransactions.at(0); - - const isScanning = hasReceiptTransactionUtils(reportTransaction) && isReceiptBeingScanned(reportTransaction); - if (isPending(reportTransaction) || isScanning || !!reportTransaction?.errors) { - return false; - } - - const {amount} = getTransactionDetails(reportTransaction) ?? {}; - if (!amount) { - return false; - } - - const {isExpenseSplit, isBillSplit} = getOriginalTransactionWithSplitInfo(reportTransaction); - if (isExpenseSplit || isBillSplit) { - return false; - } - - if (!isExpenseReportUtils(report)) { - return false; - } - - if (report.stateNum && report.stateNum >= CONST.REPORT.STATE_NUM.APPROVED) { - return false; - } - - const isSubmitter = isCurrentUserSubmitter(report.reportID); - const isAdmin = policy?.role === CONST.POLICY.ROLE.ADMIN; - const isManager = (report.managerID ?? CONST.DEFAULT_NUMBER_ID) === getCurrentUserAccountID(); - - return isSubmitter || isAdmin || isManager; -} - function isSubmitAction(report: Report, reportTransactions: Transaction[], policy?: Policy, reportNameValuePairs?: ReportNameValuePairs, reportActions?: ReportAction[]): boolean { if (isArchivedReport(reportNameValuePairs)) { return false;