diff --git a/src/components/LHNOptionsList/OptionRowLHNData.tsx b/src/components/LHNOptionsList/OptionRowLHNData.tsx index 8f3d78546dd3..bb5fdb580aa7 100644 --- a/src/components/LHNOptionsList/OptionRowLHNData.tsx +++ b/src/components/LHNOptionsList/OptionRowLHNData.tsx @@ -47,6 +47,7 @@ function OptionRowLHNData({ policy, parentReportAction, hasViolations: !!shouldDisplayViolations, + transactionViolations, }); if (deepEqual(item, optionItemRef.current)) { return optionItemRef.current; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index b4e3d206e566..3076e029fdad 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -609,6 +609,13 @@ function isDraftReport(reportID: string | undefined): boolean { return !!draftReport; } +/** + * Returns the report + */ +function getReport(reportID: string): OnyxEntry { + return ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; +} + /** * Returns the parentReport if the given report is a thread */ @@ -7380,6 +7387,7 @@ export { findPolicyExpenseChatByPolicyID, hasOnlyNonReimbursableTransactions, getMostRecentlyVisitedReport, + getReport, }; export type { diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts index f2082fbf5d2b..3151f522d800 100644 --- a/src/libs/SidebarUtils.ts +++ b/src/libs/SidebarUtils.ts @@ -18,11 +18,18 @@ import localeCompare from './LocaleCompare'; import * as LocalePhoneNumber from './LocalePhoneNumber'; import * as Localize from './Localize'; import * as OptionsListUtils from './OptionsListUtils'; +import Permissions from './Permissions'; import * as PolicyUtils from './PolicyUtils'; import * as ReportActionsUtils from './ReportActionsUtils'; import * as ReportUtils from './ReportUtils'; import * as TaskUtils from './TaskUtils'; +let allBetas: OnyxEntry; +Onyx.connect({ + key: ONYXKEYS.BETAS, + callback: (value) => (allBetas = value), +}); + const visibleReportActionItems: ReportActions = {}; Onyx.connect({ key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, @@ -94,8 +101,17 @@ function getOrderedReportIDs( const isHidden = report.notificationPreference === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN; const isFocused = report.reportID === currentReportId; const allReportErrors = OptionsListUtils.getAllReportErrors(report, reportActions) ?? {}; + const transactionReportActions = ReportActionsUtils.getAllReportActions(report.reportID); + const oneTransactionThreadReportID = ReportActionsUtils.getOneTransactionThreadReportID(report.reportID, transactionReportActions, undefined); + let doesTransactionThreadReportHasViolations = false; + if (oneTransactionThreadReportID) { + const transactionReport = ReportUtils.getReport(oneTransactionThreadReportID); + doesTransactionThreadReportHasViolations = !!transactionReport && OptionsListUtils.shouldShowViolations(transactionReport, betas ?? [], transactionViolations); + } const hasErrorsOtherThanFailedReceipt = - doesReportHaveViolations || Object.values(allReportErrors).some((error) => error?.[0] !== Localize.translateLocal('iou.error.genericSmartscanFailureMessage')); + doesTransactionThreadReportHasViolations || + doesReportHaveViolations || + Object.values(allReportErrors).some((error) => error?.[0] !== Localize.translateLocal('iou.error.genericSmartscanFailureMessage')); if (ReportUtils.isOneTransactionThread(report.reportID, report.parentReportID ?? '0', parentReportAction)) { return; } @@ -214,6 +230,7 @@ function getOptionData({ policy, parentReportAction, hasViolations, + transactionViolations, }: { report: OnyxEntry; reportActions: OnyxEntry; @@ -222,6 +239,7 @@ function getOptionData({ policy: OnyxEntry | undefined; parentReportAction: OnyxEntry | undefined; hasViolations: boolean; + transactionViolations?: OnyxCollection; }): ReportUtils.OptionData | undefined { // When a user signs out, Onyx is cleared. Due to the lazy rendering with a virtual list, it's possible for // this method to be called after the Onyx data has been cleared out. In that case, it's fine to do @@ -282,6 +300,21 @@ function getOptionData({ result.shouldShowSubscript = ReportUtils.shouldReportShowSubscript(report); result.pendingAction = report.pendingFields?.addWorkspaceRoom ?? report.pendingFields?.createChat; result.brickRoadIndicator = hasErrors || hasViolations ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''; + const oneTransactionThreadReportID = ReportActionsUtils.getOneTransactionThreadReportID(report.reportID, ReportActionsUtils.getAllReportActions(report.reportID)); + if (oneTransactionThreadReportID) { + const oneTransactionThreadReport = ReportUtils.getReport(oneTransactionThreadReportID); + + if ( + Permissions.canUseViolations(allBetas) && + ReportUtils.shouldDisplayTransactionThreadViolations( + oneTransactionThreadReport, + transactionViolations, + ReportActionsUtils.getAllReportActions(report.reportID)[oneTransactionThreadReport?.parentReportActionID ?? '-1'], + ) + ) { + result.brickRoadIndicator = CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; + } + } result.ownerAccountID = report.ownerAccountID; result.managerID = report.managerID; result.reportID = report.reportID; diff --git a/src/libs/actions/Task.ts b/src/libs/actions/Task.ts index 0a7244bde1e5..964f5be0129b 100644 --- a/src/libs/actions/Task.ts +++ b/src/libs/actions/Task.ts @@ -126,7 +126,7 @@ function createTaskAndNavigate( const currentTime = DateUtils.getDBTimeWithSkew(); const lastCommentText = ReportUtils.formatReportLastMessageText(ReportActionsUtils.getReportActionText(optimisticAddCommentReport.reportAction)); - const parentReport = getReport(parentReportID); + const parentReport = ReportUtils.getReport(parentReportID); const optimisticParentReport = { lastVisibleActionCreated: optimisticAddCommentReport.reportAction.created, lastMessageText: lastCommentText, @@ -906,13 +906,6 @@ function getParentReport(report: OnyxEntry): OnyxEntry { - return ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; -} - /** * Cancels a task by setting the report state to SUBMITTED and status to CLOSED */