diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 82285545b303..84096773e373 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -18,6 +18,7 @@ import * as UserUtils from './UserUtils'; import * as ReportActionUtils from './ReportActionsUtils'; import * as PersonalDetailsUtils from './PersonalDetailsUtils'; import * as ErrorUtils from './ErrorUtils'; +import * as TransactionUtils from './TransactionUtils'; /** * OptionsListUtils is used to build a list options passed to the OptionsList component. Several different UI views can @@ -67,14 +68,16 @@ Onyx.connect({ const lastReportActions = {}; const allSortedReportActions = {}; +const allReportActions = {}; Onyx.connect({ key: ONYXKEYS.COLLECTION.REPORT_ACTIONS, callback: (actions, key) => { if (!key || !actions) { return; } - const sortedReportActions = ReportActionUtils.getSortedReportActions(_.toArray(actions), true); const reportID = CollectionUtils.extractCollectionItemID(key); + allReportActions[reportID] = actions; + const sortedReportActions = ReportActionUtils.getSortedReportActions(_.toArray(actions), true); allSortedReportActions[reportID] = sortedReportActions; lastReportActions[reportID] = _.first(sortedReportActions); }, @@ -91,6 +94,18 @@ Onyx.connect({ }, }); +let allTransactions = {}; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.TRANSACTION, + waitForCollectionCallback: true, + callback: (val) => { + if (!val) { + return; + } + allTransactions = _.pick(val, (transaction) => transaction); + }, +}); + /** * Get the option for a policy expense report. * @param {Object} report @@ -347,20 +362,25 @@ function getSearchText(report, reportName, personalDetailList, isChatRoomOrPolic function getAllReportErrors(report, reportActions) { const reportErrors = report.errors || {}; const reportErrorFields = report.errorFields || {}; - const reportActionErrors = {}; - _.each(reportActions, (action) => { - if (action && !_.isEmpty(action.errors)) { - _.extend(reportActionErrors, action.errors); - } else if (ReportActionUtils.isReportPreviewAction(action)) { - const iouReportID = ReportActionUtils.getIOUReportIDFromReportActionPreview(action); - - // Instead of adding all Smartscan errors, let's just add a generic error if there are any. This - // will be more performant and provide the same result in the UI - if (ReportUtils.hasMissingSmartscanFields(iouReportID)) { - _.extend(reportActionErrors, {smartscan: ErrorUtils.getMicroSecondOnyxError('report.genericSmartscanFailureMessage')}); - } + const reportActionErrors = _.reduce( + reportActions, + (prevReportActionErrors, action) => (!action || _.isEmpty(action.errors) ? prevReportActionErrors : _.extend(prevReportActionErrors, action.errors)), + {}, + ); + + const parentReportAction = !report.parentReportID || !report.parentReportActionID ? {} : lodashGet(allReportActions, [report.parentReportID, report.parentReportActionID], {}); + + if (parentReportAction.actorAccountID === currentUserAccountID && ReportActionUtils.isTransactionThread(parentReportAction)) { + const transactionID = lodashGet(parentReportAction, ['originalMessage', 'IOUTransactionID'], ''); + const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] || {}; + if (TransactionUtils.hasMissingSmartscanFields(transaction)) { + _.extend(reportActionErrors, {smartscan: ErrorUtils.getMicroSecondOnyxError('report.genericSmartscanFailureMessage')}); } - }); + } else if ((ReportUtils.isIOUReport(report) || ReportUtils.isExpenseReport(report)) && report.ownerAccountID === currentUserAccountID) { + if (ReportUtils.hasMissingSmartscanFields(report.reportID)) { + _.extend(reportActionErrors, {smartscan: ErrorUtils.getMicroSecondOnyxError('report.genericSmartscanFailureMessage')}); + } + } // All error objects related to the report. Each object in the sources contains error messages keyed by microtime const errorSources = {