From cd6dba82b0c0a2b3d8edcc7692bee3304821de70 Mon Sep 17 00:00:00 2001 From: Nathalie Kuoch Date: Wed, 21 Jun 2023 15:35:49 +0200 Subject: [PATCH 01/60] Handle isWaitingForBankAccount when paying request --- src/CONST.js | 3 +++ src/components/AddPlaidBankAccount.js | 2 +- src/components/LHNOptionsList/OptionRowLHN.js | 3 ++- src/components/MoneyRequestHeader.js | 11 ++++++-- src/components/ReportActionItem/IOUPreview.js | 10 +++++-- .../ReportActionItem/MoneyRequestAction.js | 2 +- .../ReportActionItem/ReportPreview.js | 7 +++-- src/languages/en.js | 2 ++ src/languages/es.js | 1 + src/libs/OptionsListUtils.js | 1 + src/libs/ReportActionsUtils.js | 1 + src/libs/ReportUtils.js | 16 ++++++++--- src/libs/SidebarUtils.js | 5 +++- src/libs/actions/Plaid.js | 4 ++- src/pages/ReimbursementAccount/CompanyStep.js | 4 --- src/pages/home/report/ReportActionItem.js | 10 +++++++ .../ReportActionItemReimbursementQueued.js | 27 +++++++++++++++++++ .../home/report/ReportActionItemSingle.js | 1 + src/pages/home/report/ReportActionsList.js | 1 + 19 files changed, 93 insertions(+), 18 deletions(-) create mode 100644 src/pages/home/report/ReportActionItemReimbursementQueued.js diff --git a/src/CONST.js b/src/CONST.js index 50bfb5675bd8..a9a2b7acbd84 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -490,6 +490,8 @@ const CONST = { TASKEDITED: 'TASKEDITED', TASKCANCELED: 'TASKCANCELED', IOU: 'IOU', + REIMBURSEMENTQUEUED: 'REIMBURSEMENTQUEUED', + REIMBURSED: 'REIMBURSED', RENAMED: 'RENAMED', CHRONOSOOOLIST: 'CHRONOSOOOLIST', TASKCOMPLETED: 'TASKCOMPLETED', @@ -1043,6 +1045,7 @@ const CONST = { DECLINE: 'decline', CANCEL: 'cancel', DELETE: 'delete', + REIMBURSEMENTQUEUED: 'REIMBURSEMENTQUEUED', }, AMOUNT_MAX_LENGTH: 10, }, diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index 4739e9ed1f12..ff97c9be24a6 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -180,7 +180,7 @@ class AddPlaidBankAccount extends React.Component { token={token} onSuccess={({publicToken, metadata}) => { Log.info('[PlaidLink] Success!'); - BankAccounts.openPlaidBankAccountSelector(publicToken, metadata.institution.name, this.props.allowDebit); + BankAccounts.openPlaidBankAccountSelector(publicToken, metadata.institution.name, this.props.allowDebit, this.props.bankAccountID); }} onError={(error) => { Log.hmmm('[PlaidLink] Error: ', error.message); diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index 20dfc639fcba..a0fe0dbf9903 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -87,7 +87,8 @@ function OptionRowLHN(props) { !hasBrickError && (optionItem.isUnreadWithMention || (optionItem.hasOutstandingIOU && !optionItem.isIOUReportOwner) || - (optionItem.isTaskReport && optionItem.isTaskAssignee && !optionItem.isTaskCompleted)); + (optionItem.isTaskReport && optionItem.isTaskAssignee && !optionItem.isTaskCompleted) || + (optionItem.isWaitingOnBankAccount && optionItem.isIOUReportOwner)); /** * Show the ReportActionContextMenu modal popover. diff --git a/src/components/MoneyRequestHeader.js b/src/components/MoneyRequestHeader.js index 0976818f9545..43bfebfc70c5 100644 --- a/src/components/MoneyRequestHeader.js +++ b/src/components/MoneyRequestHeader.js @@ -87,9 +87,16 @@ function MoneyRequestHeader(props) { const policy = props.policies[`${ONYXKEYS.COLLECTION.POLICY}${props.report.policyID}`]; const isPayer = Policy.isAdminOfFreePolicy([policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(props.session, 'accountID', null) === moneyRequestReport.managerID); - const shouldShowSettlementButton = !isSettled && !props.isSingleTransactionView && isPayer; + const shouldShowSettlementButton = !isSettled && !props.isSingleTransactionView && isPayer && !props.report.isWaitingOnBankAccount; const bankAccountRoute = ReportUtils.getBankAccountRoute(props.chatReport); const shouldShowPaypal = Boolean(lodashGet(props.personalDetails, [moneyRequestReport.managerID, 'payPalMeAddress'])); + let description = `${props.translate('iou.amount')} • ${props.translate('iou.cash')}`; + if (isSettled) { + description += ` • ${props.translate('iou.settledExpensify')}`; + } else if (props.report.isWaitingOnBankAccount) { + description += ` • Waiting for credit account`; + } + return ( {CurrencyUtils.convertToDisplayString(requestAmount, requestCurrency)} - {!props.iouReport.hasOutstandingIOU && !props.isBillSplit && ( + {!props.iouReport.hasOutstandingIOU && !props.isBillSplit && !props.iouReport.isWaitingOnBankAccount && ( {_.map(props.action.message, (message, index) => ( @@ -123,7 +126,7 @@ function ReportPreview(props) { ) : ( - {lodashGet(message, 'html', props.translate('iou.payerSettled', {amount: reportAmount}))} + {props.iouReport.isWaitingOnBankAccount ? props.translate('iou.waitingOnBankAccount', {submitterDisplayName}) : lodashGet(message, 'html', props.translate('iou.payerSettled', {amount: reportAmount}))} )} @@ -134,7 +137,7 @@ function ReportPreview(props) { /> ))} - {isCurrentUserManager && !ReportUtils.isSettled(props.iouReport.reportID) && ( + {isCurrentUserManager && !ReportUtils.isSettled(props.iouReport.reportID) && !props.chatReport.isWaitingOnBankAccount && ( `${payer} owes ${amount}`, payerPaidAmount: ({payer, amount}) => `${payer} paid ${amount}`, payerSettled: ({amount}) => `paid ${amount}`, + waitingOnBankAccount: ({submitterDisplayName}) => `started settling up, payment is held until ${submitterDisplayName} adds a `, noReimbursableExpenses: 'This report has an invalid amount', pendingConversionMessage: "Total will update when you're back online", threadRequestReportName: ({formattedAmount, comment}) => `${formattedAmount} request${comment ? ` for ${comment}` : ''}`, diff --git a/src/languages/es.js b/src/languages/es.js index d54fa5110117..af01311ccb58 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -359,6 +359,7 @@ export default { payerOwesAmount: ({payer, amount}) => `${payer} debe ${amount}`, payerPaidAmount: ({payer, amount}) => `${payer} pagó ${amount}`, payerSettled: ({amount}) => `pagó ${amount}`, + waitingOnBankAccount: ({submitterDisplayName}) => `comenzó a establecerse, el pago se retiene hasta que ${submitterDisplayName} agrega una `, noReimbursableExpenses: 'El monto de este informe es inválido', pendingConversionMessage: 'El total se actualizará cuando estés online', threadRequestReportName: ({formattedAmount, comment}) => `Solicitud de ${formattedAmount}${comment ? ` para ${comment}` : ''}`, diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 611f44f751db..5a8b9270b19d 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -471,6 +471,7 @@ function createOption(accountIDs, personalDetails, report, reportActions = {}, { result.keyForList = String(report.reportID); result.tooltipText = ReportUtils.getReportParticipantsTitle(report.participantAccountIDs || []); result.hasOutstandingIOU = report.hasOutstandingIOU; + result.isWaitingOnBankAccount = report.isWaitingOnBankAccount; hasMultipleParticipants = personalDetailList.length > 1 || result.isChatRoom || result.isPolicyExpenseChat; subtitle = ReportUtils.getChatRoomSubtitle(report); diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index f57084c9f0e0..6d244a3a5db6 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -88,6 +88,7 @@ function isSentMoneyReportAction(reportAction) { reportAction && reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && lodashGet(reportAction, 'originalMessage.type') === CONST.IOU.REPORT_ACTION_TYPE.PAY && + lodashGet(reportAction, 'originalMessage.type') === CONST.IOU.REPORT_ACTION_TYPE.REIMBURSEMENTQUEUED && _.has(reportAction.originalMessage, 'IOUDetails') ); } diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 6f317cc08d29..843f22be6774 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -233,7 +233,13 @@ function canFlagReportAction(reportAction) { * @returns {Boolean} */ function isSettled(reportID) { - return !lodashGet(allReports, [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, 'hasOutstandingIOU']); + const report = lodashGet(allReports, `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {}); + return !report.hasOutstandingIOU && !report.isWaitingOnBankAccount; +} + +function isCurrentUserSubmitter(reportID) { + const report = lodashGet(allReports, `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {}); + return report.owner === sessionEmail; } /** @@ -916,7 +922,7 @@ function getMoneyRequestAction(reportAction = {}) { * @returns {Number} */ function getMoneyRequestTotal(report, moneyRequestReports = {}) { - if (report.hasOutstandingIOU || isMoneyRequestReport(report)) { + if (report.hasOutstandingIOU || report.isWaitingOnBankAccount || isMoneyRequestReport(report)) { const moneyRequestReport = moneyRequestReports[`${ONYXKEYS.COLLECTION.REPORT}${report.iouReportID}`] || report; const total = lodashGet(moneyRequestReport, 'total', 0); @@ -1821,7 +1827,7 @@ function hasOutstandingIOU(report, iouReports) { } if (iouReport.ownerAccountID === currentUserAccountID) { - return false; + return report.isWaitingOnBankAccount; } return report.hasOutstandingIOU; @@ -1840,6 +1846,9 @@ function isIOUOwnedByCurrentUser(report, iouReports = {}) { return iouReport.ownerAccountID === currentUserAccountID; } } + if (report.isWaitingOnBankAccount) { + return report.ownerAccountID === currentUserAccountID; + } return false; } @@ -2300,6 +2309,7 @@ export { getIOUReportActionMessage, getDisplayNameForParticipant, isChatReport, + isCurrentUserSubmitter, isExpenseReport, isIOUReport, isTaskReport, diff --git a/src/libs/SidebarUtils.js b/src/libs/SidebarUtils.js index a41249ebfa3d..b311f831cb1d 100644 --- a/src/libs/SidebarUtils.js +++ b/src/libs/SidebarUtils.js @@ -168,7 +168,7 @@ function getOrderedReportIDs(reportIDFromRoute) { return; } - if (report.hasOutstandingIOU && !ReportUtils.isIOUOwnedByCurrentUser(report, allReports)) { + if ((report.hasOutstandingIOU || report.isWaitingOnBankAccount) && !ReportUtils.isIOUOwnedByCurrentUser(report, allReports)) { outstandingIOUReports.push(report); return; } @@ -258,6 +258,7 @@ function getOptionData(reportID) { shouldShowSubscript: false, isPolicyExpenseChat: false, isMoneyRequestReport: false, + isWaitingOnBankAccount: false, }; const participantPersonalDetailList = _.values(OptionsListUtils.getPersonalDetailsForAccountIDs(report.participantAccountIDs, personalDetails)); @@ -289,6 +290,8 @@ function getOptionData(reportID) { result.tooltipText = ReportUtils.getReportParticipantsTitle(report.participantAccountIDs || []); result.hasOutstandingIOU = report.hasOutstandingIOU; result.parentReportID = report.parentReportID || null; + result.isWaitingOnBankAccount = report.isWaitingOnBankAccount; + const hasMultipleParticipants = participantPersonalDetailList.length > 1 || result.isChatRoom || result.isPolicyExpenseChat; const subtitle = ReportUtils.getChatRoomSubtitle(report); diff --git a/src/libs/actions/Plaid.js b/src/libs/actions/Plaid.js index 3155058624af..53763980d285 100644 --- a/src/libs/actions/Plaid.js +++ b/src/libs/actions/Plaid.js @@ -40,14 +40,16 @@ function openPlaidBankLogin(allowDebit, bankAccountID) { * @param {String} publicToken * @param {String} bankName * @param {Boolean} allowDebit + * @param {Number} bankAccountID */ -function openPlaidBankAccountSelector(publicToken, bankName, allowDebit) { +function openPlaidBankAccountSelector(publicToken, bankName, allowDebit, bankAccountID) { API.read( 'OpenPlaidBankAccountSelector', { publicToken, allowDebit, bank: bankName, + bankAccountID, }, { optimisticData: [ diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js index e44d0562b58e..756aca8e244c 100644 --- a/src/pages/ReimbursementAccount/CompanyStep.js +++ b/src/pages/ReimbursementAccount/CompanyStep.js @@ -59,10 +59,6 @@ class CompanyStep extends React.Component { this.defaultWebsite = lodashGet(props, 'user.isFromPublicDomain', false) ? 'https://' : `https://www.${Str.extractEmailDomain(props.session.email, '')}`; } - componentWillUnmount() { - BankAccounts.resetReimbursementAccount(); - } - /** * @param {Array} fieldNames * diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 2303ee6c556f..eb3c35cff703 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -30,6 +30,7 @@ import * as ContextMenuActions from './ContextMenu/ContextMenuActions'; import * as EmojiPickerAction from '../../../libs/actions/EmojiPickerAction'; import {withBlockedFromConcierge, withNetwork, withPersonalDetails, withReportActionsDrafts} from '../../../components/OnyxProvider'; import RenameAction from '../../../components/ReportActionItem/RenameAction'; +import ReportActionItemReimbursementQueued from './ReportActionItemReimbursementQueued'; import InlineSystemMessage from '../../../components/InlineSystemMessage'; import styles from '../../../styles/styles'; import SelectionScraper from '../../../libs/SelectionScraper'; @@ -56,6 +57,7 @@ import TaskPreview from '../../../components/ReportActionItem/TaskPreview'; import TaskAction from '../../../components/ReportActionItem/TaskAction'; import * as Session from '../../../libs/actions/Session'; import {hideContextMenu} from './ContextMenu/ReportActionContextMenu'; +import * as PersonalDetailsUtils from "../../../libs/PersonalDetailsUtils"; const propTypes = { ...windowDimensionsPropTypes, @@ -275,6 +277,14 @@ function ReportActionItem(props) { isHovered={hovered} /> ); + } else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED) { + const submitterDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(props.personalDetailsList, [props.report.ownerAccountID, 'displayName'], props.report.ownerEmail); + children = ( + + ); } else { const message = _.last(lodashGet(props.action, 'message', [{}])); const hasBeenFlagged = !_.contains([CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING], moderationDecision); diff --git a/src/pages/home/report/ReportActionItemReimbursementQueued.js b/src/pages/home/report/ReportActionItemReimbursementQueued.js new file mode 100644 index 000000000000..0336cadc460d --- /dev/null +++ b/src/pages/home/report/ReportActionItemReimbursementQueued.js @@ -0,0 +1,27 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Text from '../../../components/Text'; +import styles from '../../../styles/styles'; +import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; + +const propTypes = { + submitterDisplayName: PropTypes.string.isRequired, + isCurrentUserSubmitter: PropTypes.bool.isRequired, + + ...withLocalizePropTypes, +}; + +function ReportActionItemReimbursementQueued(props) { + // TODO: add click on Bank Account to open Plaid + return ( + + {props.translate('iou.waitingOnBankAccount', {submitterDisplayName: props.submitterDisplayName})} + {props.isCurrentUserSubmitter ? props.translate('common.bankAccount') : props.translate('common.bankAccount')}. + + ); +} + +ReportActionItemReimbursementQueued.propTypes = propTypes; +ReportActionItemReimbursementQueued.displayName = 'ReportActionItemReimbursementQueued'; + +export default withLocalize(ReportActionItemReimbursementQueued); diff --git a/src/pages/home/report/ReportActionItemSingle.js b/src/pages/home/report/ReportActionItemSingle.js index 3e49dfe621c4..667a154189eb 100644 --- a/src/pages/home/report/ReportActionItemSingle.js +++ b/src/pages/home/report/ReportActionItemSingle.js @@ -84,6 +84,7 @@ function ReportActionItemSingle(props) { ] : props.action.person; + return ( Date: Thu, 22 Jun 2023 09:54:54 +0200 Subject: [PATCH 02/60] Handle reimbursed action --- .../ReportActionItem/ReportPreview.js | 2 +- src/languages/en.js | 2 ++ src/languages/es.js | 3 ++ src/libs/ReportActionsUtils.js | 1 - src/libs/ReportUtils.js | 28 ++++++++----------- src/libs/SidebarUtils.js | 22 ++++++++++----- .../actions/ReimbursementAccount/store.js | 10 ++++++- src/pages/home/report/ReportActionItem.js | 13 ++++++++- .../home/report/ReportActionItemReimbursed.js | 27 ++++++++++++++++++ .../ReportActionItemReimbursementQueued.js | 13 +++++++-- .../home/report/ReportActionItemSingle.js | 1 - 11 files changed, 90 insertions(+), 32 deletions(-) create mode 100644 src/pages/home/report/ReportActionItemReimbursed.js diff --git a/src/components/ReportActionItem/ReportPreview.js b/src/components/ReportActionItem/ReportPreview.js index 500d9b3eadb3..cdb050477ce3 100644 --- a/src/components/ReportActionItem/ReportPreview.js +++ b/src/components/ReportActionItem/ReportPreview.js @@ -126,7 +126,7 @@ function ReportPreview(props) { ) : ( - {props.iouReport.isWaitingOnBankAccount ? props.translate('iou.waitingOnBankAccount', {submitterDisplayName}) : lodashGet(message, 'html', props.translate('iou.payerSettled', {amount: reportAmount}))} + {props.iouReport.isWaitingOnBankAccount ? `${props.translate('iou.waitingOnBankAccount', {submitterDisplayName})} ${props.translate('common.bankAccount')}` : lodashGet(message, 'html', props.translate('iou.payerSettled', {amount: reportAmount}))} )} diff --git a/src/languages/en.js b/src/languages/en.js index c78f973232a4..eecf4f86e37e 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -361,7 +361,9 @@ export default { payerOwesAmount: ({payer, amount}) => `${payer} owes ${amount}`, payerPaidAmount: ({payer, amount}) => `${payer} paid ${amount}`, payerSettled: ({amount}) => `paid ${amount}`, + payerSettledUp: ({amount}) => `settled up ${amount}`, waitingOnBankAccount: ({submitterDisplayName}) => `started settling up, payment is held until ${submitterDisplayName} adds a `, + afterAddedBankAccount: ({submitterDisplayName}) => `after ${submitterDisplayName} added a bank account`, noReimbursableExpenses: 'This report has an invalid amount', pendingConversionMessage: "Total will update when you're back online", threadRequestReportName: ({formattedAmount, comment}) => `${formattedAmount} request${comment ? ` for ${comment}` : ''}`, diff --git a/src/languages/es.js b/src/languages/es.js index af01311ccb58..1da1cdf74965 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -346,6 +346,7 @@ export default { sendMoney: 'Enviar dinero', pay: 'Pagar', viewDetails: 'Ver detalles', + pending: 'Pendiente', settledExpensify: 'Pagado', settledElsewhere: 'Pagado de otra forma', settledPaypalMe: 'Pagado con PayPal.me', @@ -359,7 +360,9 @@ export default { payerOwesAmount: ({payer, amount}) => `${payer} debe ${amount}`, payerPaidAmount: ({payer, amount}) => `${payer} pagó ${amount}`, payerSettled: ({amount}) => `pagó ${amount}`, + payerSettledUp: ({amount}) => `pagó ${amount}`, waitingOnBankAccount: ({submitterDisplayName}) => `comenzó a establecerse, el pago se retiene hasta que ${submitterDisplayName} agrega una `, + afterAddedBankAccount: ({submitterDisplayName}) => `después ${submitterDisplayName} agregó una cuenta bancaria`, noReimbursableExpenses: 'El monto de este informe es inválido', pendingConversionMessage: 'El total se actualizará cuando estés online', threadRequestReportName: ({formattedAmount, comment}) => `Solicitud de ${formattedAmount}${comment ? ` para ${comment}` : ''}`, diff --git a/src/libs/ReportActionsUtils.js b/src/libs/ReportActionsUtils.js index 6d244a3a5db6..f57084c9f0e0 100644 --- a/src/libs/ReportActionsUtils.js +++ b/src/libs/ReportActionsUtils.js @@ -88,7 +88,6 @@ function isSentMoneyReportAction(reportAction) { reportAction && reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && lodashGet(reportAction, 'originalMessage.type') === CONST.IOU.REPORT_ACTION_TYPE.PAY && - lodashGet(reportAction, 'originalMessage.type') === CONST.IOU.REPORT_ACTION_TYPE.REIMBURSEMENTQUEUED && _.has(reportAction.originalMessage, 'IOUDetails') ); } diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 843f22be6774..8b7b2436fc1b 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -239,7 +239,7 @@ function isSettled(reportID) { function isCurrentUserSubmitter(reportID) { const report = lodashGet(allReports, `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {}); - return report.owner === sessionEmail; + return report.ownerEmail === sessionEmail; } /** @@ -1817,20 +1817,16 @@ function isUnreadWithMention(report) { * @returns {boolean} */ function hasOutstandingIOU(report, iouReports) { - if (!report || !report.iouReportID || _.isUndefined(report.hasOutstandingIOU)) { - return false; - } - - const iouReport = iouReports && iouReports[`${ONYXKEYS.COLLECTION.REPORT}${report.iouReportID}`]; - if (!iouReport || !iouReport.ownerAccountID) { - return false; - } + if (report.iouReportID) { + const iouReport = iouReports && iouReports[`${ONYXKEYS.COLLECTION.REPORT}${report.iouReportID}`]; + if (!iouReport || !iouReport.ownerAccountID) { + return false; + } - if (iouReport.ownerAccountID === currentUserAccountID) { - return report.isWaitingOnBankAccount; + return iouReport.ownerAccountID === currentUserAccountID ? iouReport.isWaitingOnBankAccount : iouReport.hasOutstandingIOU; } - return report.hasOutstandingIOU; + return report.ownerAccountID === currentUserAccountID ? report.isWaitingOnBankAccount : report.hasOutstandingIOU; } /** @@ -1840,16 +1836,14 @@ function hasOutstandingIOU(report, iouReports) { * @returns {Boolean} */ function isIOUOwnedByCurrentUser(report, iouReports = {}) { - if (report.hasOutstandingIOU) { + if (report.iouReportID) { const iouReport = iouReports[`${ONYXKEYS.COLLECTION.REPORT}${report.iouReportID}`]; if (iouReport) { return iouReport.ownerAccountID === currentUserAccountID; } } - if (report.isWaitingOnBankAccount) { - return report.ownerAccountID === currentUserAccountID; - } - return false; + + return report.ownerAccountID === currentUserAccountID; } /** diff --git a/src/libs/SidebarUtils.js b/src/libs/SidebarUtils.js index b311f831cb1d..fc0f6d114ea2 100644 --- a/src/libs/SidebarUtils.js +++ b/src/libs/SidebarUtils.js @@ -148,31 +148,38 @@ function getOrderedReportIDs(reportIDFromRoute) { // The LHN is split into five distinct groups, and each group is sorted a little differently. The groups will ALWAYS be in this order: // 1. Pinned - Always sorted by reportDisplayName - // 2. Outstanding IOUs - Always sorted by iouReportAmount with the largest amounts at the top of the group - // 3. Drafts - Always sorted by reportDisplayName - // 4. Non-archived reports + // 2. Waiting on bank account - Always sorted by reportDisplayName + // 3. Outstanding IOUs - Always sorted by iouReportAmount with the largest amounts at the top of the group + // 4. Drafts - Always sorted by reportDisplayName + // 5. Non-archived reports // - Sorted by lastVisibleActionCreated in default (most recent) view mode // - Sorted by reportDisplayName in GSD (focus) view mode - // 5. Archived reports + // 6. Archived reports // - Sorted by lastVisibleActionCreated in default (most recent) view mode // - Sorted by reportDisplayName in GSD (focus) view mode let pinnedReports = []; let outstandingIOUReports = []; + let waitingOnBankAccountReports = []; let draftReports = []; let nonArchivedReports = []; let archivedReports = []; - _.each(reportsToDisplay, (report) => { if (report.isPinned) { pinnedReports.push(report); return; } - if ((report.hasOutstandingIOU || report.isWaitingOnBankAccount) && !ReportUtils.isIOUOwnedByCurrentUser(report, allReports)) { + const isIOUOwnedByCurrentUser = ReportUtils.isIOUOwnedByCurrentUser(report, allReports); + if (report.hasOutstandingIOU && !isIOUOwnedByCurrentUser) { outstandingIOUReports.push(report); return; } + if (report.isWaitingOnBankAccount && isIOUOwnedByCurrentUser) { + waitingOnBankAccountReports.push(report); + return; + } + if (report.hasDraft) { draftReports.push(report); return; @@ -193,6 +200,7 @@ function getOrderedReportIDs(reportIDFromRoute) { // Sort each group of reports accordingly pinnedReports = _.sortBy(pinnedReports, (report) => report.displayName.toLowerCase()); + waitingOnBankAccountReports = _.sortBy(waitingOnBankAccountReports, (report) => report.displayName.toLowerCase()); outstandingIOUReports = lodashOrderBy(outstandingIOUReports, ['iouReportAmount', (report) => report.displayName.toLowerCase()], ['desc', 'asc']); draftReports = _.sortBy(draftReports, (report) => report.displayName.toLowerCase()); nonArchivedReports = isInDefaultMode @@ -207,7 +215,7 @@ function getOrderedReportIDs(reportIDFromRoute) { // Now that we have all the reports grouped and sorted, they must be flattened into an array and only return the reportID. // The order the arrays are concatenated in matters and will determine the order that the groups are displayed in the sidebar. - return _.pluck([].concat(pinnedReports).concat(outstandingIOUReports).concat(draftReports).concat(nonArchivedReports).concat(archivedReports), 'reportID'); + return _.pluck([].concat(pinnedReports).concat(waitingOnBankAccountReports).concat(outstandingIOUReports).concat(draftReports).concat(nonArchivedReports).concat(archivedReports), 'reportID'); } /** diff --git a/src/libs/actions/ReimbursementAccount/store.js b/src/libs/actions/ReimbursementAccount/store.js index d1e41ba7f8ec..5e69467932b9 100644 --- a/src/libs/actions/ReimbursementAccount/store.js +++ b/src/libs/actions/ReimbursementAccount/store.js @@ -1,6 +1,7 @@ import Onyx from 'react-native-onyx'; import lodashGet from 'lodash/get'; import ONYXKEYS from '../../../ONYXKEYS'; +import BankAccount from "../../models/BankAccount"; /** Reimbursement account actively being set up */ let reimbursementAccountInSetup = {}; @@ -43,6 +44,13 @@ function getBankAccountList() { return bankAccountList; } +function hasCreditBankAccount() { + return _.some(bankAccountList, (bankAccountJSON) => { + const bankAccount = new BankAccount(bankAccountJSON); + return bankAccount.isDefaultCredit(); + }); +} + function getCredentials() { return credentials; } @@ -51,4 +59,4 @@ function getReimbursementAccountWorkspaceID() { return reimbursementAccountWorkspaceID; } -export {getReimbursementAccountInSetup, getBankAccountList, getCredentials, getReimbursementAccountWorkspaceID}; +export {getReimbursementAccountInSetup, getBankAccountList, getCredentials, getReimbursementAccountWorkspaceID, hasCreditBankAccount}; diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index eb3c35cff703..4bb5009dc7de 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -57,7 +57,9 @@ import TaskPreview from '../../../components/ReportActionItem/TaskPreview'; import TaskAction from '../../../components/ReportActionItem/TaskAction'; import * as Session from '../../../libs/actions/Session'; import {hideContextMenu} from './ContextMenu/ReportActionContextMenu'; -import * as PersonalDetailsUtils from "../../../libs/PersonalDetailsUtils"; +import * as PersonalDetailsUtils from '../../../libs/PersonalDetailsUtils'; +import ReportActionItemReimbursed from './ReportActionItemReimbursed'; +import * as CurrencyUtils from '../../../libs/CurrencyUtils'; const propTypes = { ...windowDimensionsPropTypes, @@ -285,6 +287,15 @@ function ReportActionItem(props) { isCurrentUserSubmitter={ReportUtils.isCurrentUserSubmitter(props.report.reportID)} /> ); + } else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSED) { + const submitterDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(props.personalDetailsList, [props.report.ownerAccountID, 'displayName'], props.report.ownerEmail); + children = ( + + ); } else { const message = _.last(lodashGet(props.action, 'message', [{}])); const hasBeenFlagged = !_.contains([CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING], moderationDecision); diff --git a/src/pages/home/report/ReportActionItemReimbursed.js b/src/pages/home/report/ReportActionItemReimbursed.js new file mode 100644 index 000000000000..b2b3c3947dec --- /dev/null +++ b/src/pages/home/report/ReportActionItemReimbursed.js @@ -0,0 +1,27 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Text from '../../../components/Text'; +import styles from '../../../styles/styles'; +import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; + +const propTypes = { + amount: PropTypes.string.isRequired, + submitterDisplayName: PropTypes.string.isRequired, + isFromSubmitterAddingBankAccount: PropTypes.bool.isRequired, + + ...withLocalizePropTypes, +}; + +function ReportActionItemReimbursed(props) { + return ( + + {props.translate('iou.payerSettledUp', {amount: props.amount})}{' '} + {props.isFromSubmitterAddingBankAccount ? props.translate('iou.afterAddedBankAccount', {submitterDisplayName: props.submitterDisplayName}) : ''} + + ); +} + +ReportActionItemReimbursed.propTypes = propTypes; +ReportActionItemReimbursed.displayName = 'ReportActionItemAddedBankAccount'; + +export default withLocalize(ReportActionItemReimbursed); diff --git a/src/pages/home/report/ReportActionItemReimbursementQueued.js b/src/pages/home/report/ReportActionItemReimbursementQueued.js index 0336cadc460d..4b11afe3be11 100644 --- a/src/pages/home/report/ReportActionItemReimbursementQueued.js +++ b/src/pages/home/report/ReportActionItemReimbursementQueued.js @@ -3,20 +3,27 @@ import PropTypes from 'prop-types'; import Text from '../../../components/Text'; import styles from '../../../styles/styles'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; +import TextLink from "../../../components/TextLink"; +import * as BankAccounts from '../../../libs/actions/BankAccounts'; +import * as store from "../../../libs/actions/ReimbursementAccount/store"; const propTypes = { submitterDisplayName: PropTypes.string.isRequired, isCurrentUserSubmitter: PropTypes.bool.isRequired, - ...withLocalizePropTypes, }; function ReportActionItemReimbursementQueued(props) { - // TODO: add click on Bank Account to open Plaid + const shouldSubmitterAddBankAccount = props.isCurrentUserSubmitter && !store.hasCreditBankAccount(); + return ( {props.translate('iou.waitingOnBankAccount', {submitterDisplayName: props.submitterDisplayName})} - {props.isCurrentUserSubmitter ? props.translate('common.bankAccount') : props.translate('common.bankAccount')}. + {shouldSubmitterAddBankAccount ? ( + + {props.translate('common.bankAccount')} + + ) : props.translate('common.bankAccount')}. ); } diff --git a/src/pages/home/report/ReportActionItemSingle.js b/src/pages/home/report/ReportActionItemSingle.js index 667a154189eb..3e49dfe621c4 100644 --- a/src/pages/home/report/ReportActionItemSingle.js +++ b/src/pages/home/report/ReportActionItemSingle.js @@ -84,7 +84,6 @@ function ReportActionItemSingle(props) { ] : props.action.person; - return ( Date: Thu, 22 Jun 2023 15:51:58 +0200 Subject: [PATCH 03/60] Some cleaning --- src/CONST.js | 1 - src/components/ReportActionItem/ReportPreview.js | 4 +++- src/libs/SidebarUtils.js | 5 ++++- src/libs/actions/ReimbursementAccount/store.js | 3 ++- src/pages/home/report/ReportActionItemReimbursed.js | 2 +- .../report/ReportActionItemReimbursementQueued.js | 13 ++++++++----- src/pages/home/report/ReportActionsList.js | 1 - 7 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index a9a2b7acbd84..6a4b11c49f04 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -1045,7 +1045,6 @@ const CONST = { DECLINE: 'decline', CANCEL: 'cancel', DELETE: 'delete', - REIMBURSEMENTQUEUED: 'REIMBURSEMENTQUEUED', }, AMOUNT_MAX_LENGTH: 10, }, diff --git a/src/components/ReportActionItem/ReportPreview.js b/src/components/ReportActionItem/ReportPreview.js index cdb050477ce3..97c0696f1021 100644 --- a/src/components/ReportActionItem/ReportPreview.js +++ b/src/components/ReportActionItem/ReportPreview.js @@ -126,7 +126,9 @@ function ReportPreview(props) { ) : ( - {props.iouReport.isWaitingOnBankAccount ? `${props.translate('iou.waitingOnBankAccount', {submitterDisplayName})} ${props.translate('common.bankAccount')}` : lodashGet(message, 'html', props.translate('iou.payerSettled', {amount: reportAmount}))} + {props.iouReport.isWaitingOnBankAccount + ? `${props.translate('iou.waitingOnBankAccount', {submitterDisplayName})} ${props.translate('common.bankAccount')}` + : lodashGet(message, 'html', props.translate('iou.payerSettled', {amount: reportAmount}))} )} diff --git a/src/libs/SidebarUtils.js b/src/libs/SidebarUtils.js index fc0f6d114ea2..5fa3bd635a89 100644 --- a/src/libs/SidebarUtils.js +++ b/src/libs/SidebarUtils.js @@ -215,7 +215,10 @@ function getOrderedReportIDs(reportIDFromRoute) { // Now that we have all the reports grouped and sorted, they must be flattened into an array and only return the reportID. // The order the arrays are concatenated in matters and will determine the order that the groups are displayed in the sidebar. - return _.pluck([].concat(pinnedReports).concat(waitingOnBankAccountReports).concat(outstandingIOUReports).concat(draftReports).concat(nonArchivedReports).concat(archivedReports), 'reportID'); + return _.pluck( + [].concat(pinnedReports).concat(waitingOnBankAccountReports).concat(outstandingIOUReports).concat(draftReports).concat(nonArchivedReports).concat(archivedReports), + 'reportID', + ); } /** diff --git a/src/libs/actions/ReimbursementAccount/store.js b/src/libs/actions/ReimbursementAccount/store.js index 5e69467932b9..422c0ffc43dd 100644 --- a/src/libs/actions/ReimbursementAccount/store.js +++ b/src/libs/actions/ReimbursementAccount/store.js @@ -1,7 +1,8 @@ import Onyx from 'react-native-onyx'; import lodashGet from 'lodash/get'; +import _ from 'underscore'; import ONYXKEYS from '../../../ONYXKEYS'; -import BankAccount from "../../models/BankAccount"; +import BankAccount from '../../models/BankAccount'; /** Reimbursement account actively being set up */ let reimbursementAccountInSetup = {}; diff --git a/src/pages/home/report/ReportActionItemReimbursed.js b/src/pages/home/report/ReportActionItemReimbursed.js index b2b3c3947dec..1fca16dade58 100644 --- a/src/pages/home/report/ReportActionItemReimbursed.js +++ b/src/pages/home/report/ReportActionItemReimbursed.js @@ -14,7 +14,7 @@ const propTypes = { function ReportActionItemReimbursed(props) { return ( - + {props.translate('iou.payerSettledUp', {amount: props.amount})}{' '} {props.isFromSubmitterAddingBankAccount ? props.translate('iou.afterAddedBankAccount', {submitterDisplayName: props.submitterDisplayName}) : ''} diff --git a/src/pages/home/report/ReportActionItemReimbursementQueued.js b/src/pages/home/report/ReportActionItemReimbursementQueued.js index 4b11afe3be11..3691cc15d936 100644 --- a/src/pages/home/report/ReportActionItemReimbursementQueued.js +++ b/src/pages/home/report/ReportActionItemReimbursementQueued.js @@ -3,9 +3,9 @@ import PropTypes from 'prop-types'; import Text from '../../../components/Text'; import styles from '../../../styles/styles'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; -import TextLink from "../../../components/TextLink"; +import TextLink from '../../../components/TextLink'; import * as BankAccounts from '../../../libs/actions/BankAccounts'; -import * as store from "../../../libs/actions/ReimbursementAccount/store"; +import * as store from '../../../libs/actions/ReimbursementAccount/store'; const propTypes = { submitterDisplayName: PropTypes.string.isRequired, @@ -17,13 +17,16 @@ function ReportActionItemReimbursementQueued(props) { const shouldSubmitterAddBankAccount = props.isCurrentUserSubmitter && !store.hasCreditBankAccount(); return ( - + {props.translate('iou.waitingOnBankAccount', {submitterDisplayName: props.submitterDisplayName})} {shouldSubmitterAddBankAccount ? ( - {props.translate('common.bankAccount')} + {props.translate('common.bankAccount')} - ) : props.translate('common.bankAccount')}. + ) : ( + props.translate('common.bankAccount') + )} + . ); } diff --git a/src/pages/home/report/ReportActionsList.js b/src/pages/home/report/ReportActionsList.js index a322c4b51626..c3288c3eeb6a 100644 --- a/src/pages/home/report/ReportActionsList.js +++ b/src/pages/home/report/ReportActionsList.js @@ -148,7 +148,6 @@ function ReportActionsList(props) { // To notify there something changes we can use extraData prop to flatlist const extraData = [props.isSmallScreenWidth ? props.newMarkerReportActionID : undefined, ReportUtils.isArchivedRoom(props.report)]; const shouldShowReportRecipientLocalTime = ReportUtils.canShowReportRecipientLocalTime(props.personalDetailsList, props.report, props.currentUserPersonalDetails.accountID); - return ( Date: Tue, 27 Jun 2023 11:26:16 +0200 Subject: [PATCH 04/60] Add translations --- src/components/MoneyRequestHeader.js | 2 +- src/languages/en.js | 3 +-- src/languages/es.js | 5 ++--- src/pages/home/report/ReportActionItemReimbursed.js | 3 +-- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/components/MoneyRequestHeader.js b/src/components/MoneyRequestHeader.js index 43bfebfc70c5..14ca3493599b 100644 --- a/src/components/MoneyRequestHeader.js +++ b/src/components/MoneyRequestHeader.js @@ -94,7 +94,7 @@ function MoneyRequestHeader(props) { if (isSettled) { description += ` • ${props.translate('iou.settledExpensify')}`; } else if (props.report.isWaitingOnBankAccount) { - description += ` • Waiting for credit account`; + description += ` • ${props.translate('iou.pending')}`; } return ( diff --git a/src/languages/en.js b/src/languages/en.js index eecf4f86e37e..9973b362c100 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -361,9 +361,8 @@ export default { payerOwesAmount: ({payer, amount}) => `${payer} owes ${amount}`, payerPaidAmount: ({payer, amount}) => `${payer} paid ${amount}`, payerSettled: ({amount}) => `paid ${amount}`, - payerSettledUp: ({amount}) => `settled up ${amount}`, waitingOnBankAccount: ({submitterDisplayName}) => `started settling up, payment is held until ${submitterDisplayName} adds a `, - afterAddedBankAccount: ({submitterDisplayName}) => `after ${submitterDisplayName} added a bank account`, + settledAfterAddedBankAccount: ({submitterDisplayName}) => `Payment settled after ${submitterDisplayName} added a bank account`, noReimbursableExpenses: 'This report has an invalid amount', pendingConversionMessage: "Total will update when you're back online", threadRequestReportName: ({formattedAmount, comment}) => `${formattedAmount} request${comment ? ` for ${comment}` : ''}`, diff --git a/src/languages/es.js b/src/languages/es.js index 1da1cdf74965..f10af2f308e4 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -360,9 +360,8 @@ export default { payerOwesAmount: ({payer, amount}) => `${payer} debe ${amount}`, payerPaidAmount: ({payer, amount}) => `${payer} pagó ${amount}`, payerSettled: ({amount}) => `pagó ${amount}`, - payerSettledUp: ({amount}) => `pagó ${amount}`, - waitingOnBankAccount: ({submitterDisplayName}) => `comenzó a establecerse, el pago se retiene hasta que ${submitterDisplayName} agrega una `, - afterAddedBankAccount: ({submitterDisplayName}) => `después ${submitterDisplayName} agregó una cuenta bancaria`, + waitingOnBankAccount: ({submitterDisplayName}) => `inicio el pago, pero no se procesará hasta que ${submitterDisplayName} agregue una `, + settledAfterAddedBankAccount: ({submitterDisplayName}) => `Pago realizado cuando ${submitterDisplayName} agregó su cuenta bancaria`, noReimbursableExpenses: 'El monto de este informe es inválido', pendingConversionMessage: 'El total se actualizará cuando estés online', threadRequestReportName: ({formattedAmount, comment}) => `Solicitud de ${formattedAmount}${comment ? ` para ${comment}` : ''}`, diff --git a/src/pages/home/report/ReportActionItemReimbursed.js b/src/pages/home/report/ReportActionItemReimbursed.js index 1fca16dade58..127a0ccf38ee 100644 --- a/src/pages/home/report/ReportActionItemReimbursed.js +++ b/src/pages/home/report/ReportActionItemReimbursed.js @@ -15,8 +15,7 @@ const propTypes = { function ReportActionItemReimbursed(props) { return ( - {props.translate('iou.payerSettledUp', {amount: props.amount})}{' '} - {props.isFromSubmitterAddingBankAccount ? props.translate('iou.afterAddedBankAccount', {submitterDisplayName: props.submitterDisplayName}) : ''} + {props.isFromSubmitterAddingBankAccount ? props.translate('iou.settledAfterAddedBankAccount', {submitterDisplayName: props.submitterDisplayName}) : props.translate('iou.payerSettled', {amount: props.amount})} ); } From f9a0756aaa75248bc5bd7a4d4b10e8ef605a7524 Mon Sep 17 00:00:00 2001 From: Nathalie Kuoch Date: Thu, 29 Jun 2023 16:21:21 +0200 Subject: [PATCH 05/60] New copies --- src/languages/en.js | 2 +- src/languages/es.js | 2 +- src/pages/home/report/ReportActionItemReimbursed.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index 9973b362c100..51be8ee2d454 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -362,7 +362,7 @@ export default { payerPaidAmount: ({payer, amount}) => `${payer} paid ${amount}`, payerSettled: ({amount}) => `paid ${amount}`, waitingOnBankAccount: ({submitterDisplayName}) => `started settling up, payment is held until ${submitterDisplayName} adds a `, - settledAfterAddedBankAccount: ({submitterDisplayName}) => `Payment settled after ${submitterDisplayName} added a bank account`, + settledAfterAddedBankAccount: ({submitterDisplayName, amount}) => `${submitterDisplayName} added a bank account. The ${amount} payment has been made.`, noReimbursableExpenses: 'This report has an invalid amount', pendingConversionMessage: "Total will update when you're back online", threadRequestReportName: ({formattedAmount, comment}) => `${formattedAmount} request${comment ? ` for ${comment}` : ''}`, diff --git a/src/languages/es.js b/src/languages/es.js index f10af2f308e4..44139591a34c 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -361,7 +361,7 @@ export default { payerPaidAmount: ({payer, amount}) => `${payer} pagó ${amount}`, payerSettled: ({amount}) => `pagó ${amount}`, waitingOnBankAccount: ({submitterDisplayName}) => `inicio el pago, pero no se procesará hasta que ${submitterDisplayName} agregue una `, - settledAfterAddedBankAccount: ({submitterDisplayName}) => `Pago realizado cuando ${submitterDisplayName} agregó su cuenta bancaria`, + settledAfterAddedBankAccount: ({submitterDisplayName, amount}) => `${submitterDisplayName} agregó una cuenta bancaria. El pago de ${amount} se ha realizado.`, noReimbursableExpenses: 'El monto de este informe es inválido', pendingConversionMessage: 'El total se actualizará cuando estés online', threadRequestReportName: ({formattedAmount, comment}) => `Solicitud de ${formattedAmount}${comment ? ` para ${comment}` : ''}`, diff --git a/src/pages/home/report/ReportActionItemReimbursed.js b/src/pages/home/report/ReportActionItemReimbursed.js index 127a0ccf38ee..7a6d0085eeaf 100644 --- a/src/pages/home/report/ReportActionItemReimbursed.js +++ b/src/pages/home/report/ReportActionItemReimbursed.js @@ -15,7 +15,7 @@ const propTypes = { function ReportActionItemReimbursed(props) { return ( - {props.isFromSubmitterAddingBankAccount ? props.translate('iou.settledAfterAddedBankAccount', {submitterDisplayName: props.submitterDisplayName}) : props.translate('iou.payerSettled', {amount: props.amount})} + {props.isFromSubmitterAddingBankAccount ? props.translate('iou.settledAfterAddedBankAccount', {submitterDisplayName: props.submitterDisplayName, amount: props.amount}) : props.translate('iou.payerSettled', {amount: props.amount})} ); } From be5f7cc1c0ddc7b4a2ef43ab2d06445e6a67fb64 Mon Sep 17 00:00:00 2001 From: Nathalie Kuoch Date: Fri, 30 Jun 2023 15:35:16 +0200 Subject: [PATCH 06/60] js style --- src/pages/home/report/ReportActionItemReimbursed.js | 4 +++- .../home/report/ReportActionItemReimbursementQueued.js | 6 +----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/pages/home/report/ReportActionItemReimbursed.js b/src/pages/home/report/ReportActionItemReimbursed.js index 7a6d0085eeaf..2ef46852ca2f 100644 --- a/src/pages/home/report/ReportActionItemReimbursed.js +++ b/src/pages/home/report/ReportActionItemReimbursed.js @@ -15,7 +15,9 @@ const propTypes = { function ReportActionItemReimbursed(props) { return ( - {props.isFromSubmitterAddingBankAccount ? props.translate('iou.settledAfterAddedBankAccount', {submitterDisplayName: props.submitterDisplayName, amount: props.amount}) : props.translate('iou.payerSettled', {amount: props.amount})} + {props.isFromSubmitterAddingBankAccount + ? props.translate('iou.settledAfterAddedBankAccount', {submitterDisplayName: props.submitterDisplayName, amount: props.amount}) + : props.translate('iou.payerSettled', {amount: props.amount})} ); } diff --git a/src/pages/home/report/ReportActionItemReimbursementQueued.js b/src/pages/home/report/ReportActionItemReimbursementQueued.js index 7a0ea7c834f7..7cb23777e030 100644 --- a/src/pages/home/report/ReportActionItemReimbursementQueued.js +++ b/src/pages/home/report/ReportActionItemReimbursementQueued.js @@ -27,11 +27,7 @@ function ReportActionItemReimbursementQueued(props) { ); } - return ( - - {props.translate('iou.waitingOnBankAccount', {submitterDisplayName: props.submitterDisplayName})} - - ); + return {props.translate('iou.waitingOnBankAccount', {submitterDisplayName: props.submitterDisplayName})}; } ReportActionItemReimbursementQueued.propTypes = propTypes; From ff482abe15f53edddd13889545bee0aa98c76077 Mon Sep 17 00:00:00 2001 From: Nathalie Kuoch Date: Tue, 4 Jul 2023 13:24:44 +0200 Subject: [PATCH 07/60] Use getMoneyRequestTotal for displayed amount --- src/languages/en.js | 4 ++-- src/languages/es.js | 2 +- src/pages/home/report/ReportActionItem.js | 4 +++- src/pages/home/report/ReportActionItemReimbursementQueued.js | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index 2020320916cd..e30765f7497f 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -362,9 +362,9 @@ export default { amountEach: ({amount}) => `${amount} each`, payerOwesAmount: ({payer, amount}) => `${payer} owes ${amount}`, payerPaidAmount: ({payer, amount}) => `${payer} paid ${amount}`, - waitingOnBankAccount: ({submitterDisplayName}) => `started settling up, payment is held until ${submitterDisplayName} adds a bank account`, - paymentWaitingOnSubmitter: ({submitterDisplayName}) => `started settling up, payment is held until ${submitterDisplayName} adds a `, payerSettled: ({amount}) => `paid ${amount}`, + waitingOnBankAccount: ({submitterDisplayName}) => `started settling up, payment is held until ${submitterDisplayName} adds a bank account`, + waitingOnBankAccountPrefix: ({submitterDisplayName}) => `started settling up, payment is held until ${submitterDisplayName} adds a `, settledAfterAddedBankAccount: ({submitterDisplayName, amount}) => `${submitterDisplayName} added a bank account. The ${amount} payment has been made.`, settledElsewhereWithAmount: ({amount}) => `paid ${amount} elsewhere`, settledPaypalMeWithAmount: ({amount}) => `paid ${amount} using Paypal.me`, diff --git a/src/languages/es.js b/src/languages/es.js index bcb634afd76c..d513d86a74f9 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -363,7 +363,7 @@ export default { payerPaidAmount: ({payer, amount}) => `${payer} pagó ${amount}`, payerSettled: ({amount}) => `pagó ${amount}`, waitingOnBankAccount: ({submitterDisplayName}) => `inicio el pago, pero no se procesará hasta que ${submitterDisplayName} agregue una Cuenta bancaria`, - paymentWaitingOnSubmitter: ({submitterDisplayName}) => `inicio el pago, pero no se procesará hasta que ${submitterDisplayName} agregue una `, + waitingOnBankAccountPrefix: ({submitterDisplayName}) => `inicio el pago, pero no se procesará hasta que ${submitterDisplayName} agregue una `, settledAfterAddedBankAccount: ({submitterDisplayName, amount}) => `${submitterDisplayName} agregó una cuenta bancaria. El pago de ${amount} se ha realizado.`, settledElsewhereWithAmount: ({amount}) => `pagó ${amount} de otra forma`, settledPaypalMeWithAmount: ({amount}) => `pagó ${amount} con PayPal.me`, diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index abdf9ada532c..fcfb92a1bc61 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -60,6 +60,7 @@ import {hideContextMenu} from './ContextMenu/ReportActionContextMenu'; import * as PersonalDetailsUtils from '../../../libs/PersonalDetailsUtils'; import ReportActionItemReimbursed from './ReportActionItemReimbursed'; import * as CurrencyUtils from '../../../libs/CurrencyUtils'; +import {getMoneyRequestTotal} from "../../../libs/ReportUtils"; const propTypes = { ...windowDimensionsPropTypes, @@ -280,10 +281,11 @@ function ReportActionItem(props) { /> ); } else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSED) { + const totalAmount = getMoneyRequestTotal(props.report); const submitterDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(props.personalDetailsList, [props.report.ownerAccountID, 'displayName'], props.report.ownerEmail); children = ( diff --git a/src/pages/home/report/ReportActionItemReimbursementQueued.js b/src/pages/home/report/ReportActionItemReimbursementQueued.js index 7cb23777e030..1c515ea82297 100644 --- a/src/pages/home/report/ReportActionItemReimbursementQueued.js +++ b/src/pages/home/report/ReportActionItemReimbursementQueued.js @@ -19,7 +19,7 @@ function ReportActionItemReimbursementQueued(props) { if (shouldSubmitterAddBankAccount) { return ( - {props.translate('iou.paymentWaitingOnSubmitter', {submitterDisplayName: props.submitterDisplayName})} + {props.translate('iou.waitingOnBankAccountPrefix', {submitterDisplayName: props.submitterDisplayName})} {props.translate('common.bankAccount')} From ffdbf1ae4815dac5930b3fb4bc88b85f8d4001e0 Mon Sep 17 00:00:00 2001 From: Nathalie Kuoch Date: Tue, 4 Jul 2023 13:37:31 +0200 Subject: [PATCH 08/60] Fix console error by adding report billing state --- src/CONST.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CONST.js b/src/CONST.js index 11208087065e..b73231ae4944 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -592,6 +592,7 @@ const CONST = { OPEN: 0, PROCESSING: 1, SUBMITTED: 2, + BILLING: 3, }, STATUS: { OPEN: 0, From 2f1a1b291d76499cca05da4ebcc540191335eae6 Mon Sep 17 00:00:00 2001 From: Nathalie Kuoch Date: Tue, 4 Jul 2023 14:20:20 +0200 Subject: [PATCH 09/60] Fix eslint --- src/pages/home/report/ReportActionItem.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index fcfb92a1bc61..3bd636826cd3 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -60,7 +60,6 @@ import {hideContextMenu} from './ContextMenu/ReportActionContextMenu'; import * as PersonalDetailsUtils from '../../../libs/PersonalDetailsUtils'; import ReportActionItemReimbursed from './ReportActionItemReimbursed'; import * as CurrencyUtils from '../../../libs/CurrencyUtils'; -import {getMoneyRequestTotal} from "../../../libs/ReportUtils"; const propTypes = { ...windowDimensionsPropTypes, @@ -281,7 +280,7 @@ function ReportActionItem(props) { /> ); } else if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSED) { - const totalAmount = getMoneyRequestTotal(props.report); + const totalAmount = ReportUtils.getMoneyRequestTotal(props.report); const submitterDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(props.personalDetailsList, [props.report.ownerAccountID, 'displayName'], props.report.ownerEmail); children = ( Date: Tue, 4 Jul 2023 18:20:41 +0200 Subject: [PATCH 10/60] Some refactoring --- src/components/LHNOptionsList/OptionRowLHN.js | 5 +- .../ReportActionItem/MoneyRequestAction.js | 2 +- src/libs/OptionsListUtils.js | 27 ++------- src/libs/ReportUtils.js | 55 ++++++++++++------ src/libs/SidebarUtils.js | 3 +- src/pages/home/ReportScreen.js | 1 + src/pages/home/sidebar/SidebarLinks.js | 1 + src/pages/reportPropTypes.js | 3 + tests/unit/ReportUtilsTest.js | 57 ++++++++++++------- 9 files changed, 91 insertions(+), 63 deletions(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index 753f5e01c585..1f581d60a388 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -28,6 +28,7 @@ import * as OptionsListUtils from '../../libs/OptionsListUtils'; import compose from '../../libs/compose'; import ONYXKEYS from '../../ONYXKEYS'; import * as Report from '../../libs/actions/Report'; +import * as ReportUtils from '../../libs/ReportUtils'; const propTypes = { /** Style for hovered state */ @@ -101,12 +102,12 @@ function OptionRowLHN(props) { const focusedBackgroundColor = styles.sidebarLinkActive.backgroundColor; const hasBrickError = optionItem.brickRoadIndicator === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; + const shouldShowGreenDotIndicator = !hasBrickError && (optionItem.isUnreadWithMention || - (optionItem.hasOutstandingIOU && !optionItem.isIOUReportOwner) || (optionItem.isTaskReport && optionItem.isTaskAssignee && !optionItem.isTaskCompleted) || - (optionItem.isWaitingOnBankAccount && optionItem.isIOUReportOwner)); + (ReportUtils.isWaitingForIOUActionFromCurrentUser(optionItem))); /** * Show the ReportActionContextMenu modal popover. diff --git a/src/components/ReportActionItem/MoneyRequestAction.js b/src/components/ReportActionItem/MoneyRequestAction.js index 2a78013fdabd..8bef184bab08 100644 --- a/src/components/ReportActionItem/MoneyRequestAction.js +++ b/src/components/ReportActionItem/MoneyRequestAction.js @@ -135,7 +135,7 @@ function MoneyRequestAction(props) { if ( !_.isEmpty(props.iouReport) && !_.isEmpty(props.reportActions) && - (props.chatReport.hasOutstandingIOU || props.chatReport.isWaitingOnBankAccount) && + props.chatReport.hasOutstandingIOU && props.isMostRecentIOUReportAction && props.action.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD && props.network.isOffline diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index e9376b246f1a..c1701a9bcb01 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -57,26 +57,6 @@ Onyx.connect({ }, }); -const expenseReports = {}; -const iouReports = {}; -Onyx.connect({ - key: ONYXKEYS.COLLECTION.REPORT, - callback: (report, key) => { - if (!report || !key || !report.ownerEmail) { - return; - } - - if (ReportUtils.isExpenseReport(report)) { - expenseReports[key] = report; - return; - } - - if (ReportUtils.isIOUReport(report)) { - iouReports[key] = report; - } - }, -}); - const lastReportActions = {}; const allSortedReportActions = {}; Onyx.connect({ @@ -437,6 +417,7 @@ function createOption(accountIDs, personalDetails, report, reportActions = {}, { isDefaultRoom: false, isPinned: false, hasOutstandingIOU: false, + isWaitingOnBankAccount: false, iouReportID: null, isIOUReportOwner: null, iouReportAmount: 0, @@ -510,8 +491,8 @@ function createOption(accountIDs, personalDetails, report, reportActions = {}, { result.alternateText = LocalePhoneNumber.formatPhoneNumber(lodashGet(personalDetails, [accountIDs[0], 'login'], '')); } - result.isIOUReportOwner = ReportUtils.isIOUOwnedByCurrentUser(result, iouReports); - result.iouReportAmount = ReportUtils.getMoneyRequestTotal(result, iouReports); + result.isIOUReportOwner = ReportUtils.isIOUOwnedByCurrentUser(result); + result.iouReportAmount = ReportUtils.getMoneyRequestTotal(result); if (!hasMultipleParticipants) { result.login = personalDetail.login; @@ -625,7 +606,7 @@ function getOptions( const searchValue = parsedPhoneNumber.possible ? parsedPhoneNumber.number.e164 : searchInputValue; // Filter out all the reports that shouldn't be displayed - const filteredReports = _.filter(reports, (report) => ReportUtils.shouldReportBeInOptionList(report, Navigation.getReportIDFromRoute(), false, iouReports, betas, policies)); + const filteredReports = _.filter(reports, (report) => ReportUtils.shouldReportBeInOptionList(report, Navigation.getReportIDFromRoute(), false, betas, policies)); // Sorting the reports works like this: // - Order everything by the last message timestamp (descending) diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index d7dbb68727f8..6d6ec9329db3 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -998,8 +998,17 @@ function getPolicyExpenseChatName(report) { function getMoneyRequestReportName(report) { const formattedAmount = CurrencyUtils.convertToDisplayString(getMoneyRequestTotal(report), report.currency); const payerName = isExpenseReport(report) ? getPolicyName(report) : getDisplayNameForParticipant(report.managerID); + const payerPaidAmountMsg = Localize.translateLocal('iou.payerPaidAmount', {payer: payerName, amount: formattedAmount}); - return Localize.translateLocal(report.hasOutstandingIOU ? 'iou.payerOwesAmount' : 'iou.payerPaidAmount', {payer: payerName, amount: formattedAmount}); + if (report.isWaitingOnBankAccount) { + return `${payerPaidAmountMsg} • ${Localize.translateLocal('iou.pending')}`; + } + + if (report.hasOutstandingIOU) { + return Localize.translateLocal('iou.payerOwesAmount', {payer: payerName, amount: formattedAmount}); + } + + return payerPaidAmountMsg; } /** @@ -1888,41 +1897,54 @@ function isUnreadWithMention(report) { } /** - * Determines if a report has an outstanding IOU that doesn't belong to the currently logged in user + * Determines if a report has an outstanding IOU that is waiting for an action from the current user * * @param {Object} report * @param {String} report.iouReportID - * @param {Object} iouReports * @returns {boolean} */ -function hasOutstandingIOU(report, iouReports) { +function isWaitingForIOUActionFromCurrentUser(report) { + let reportToLook = report; + if (report.iouReportID) { - const iouReport = iouReports && iouReports[`${ONYXKEYS.COLLECTION.REPORT}${report.iouReportID}`]; - if (!iouReport || !iouReport.ownerAccountID) { + const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${report.iouReportID}`]; + if (!iouReport) { return false; } - return iouReport.ownerAccountID === currentUserAccountID ? iouReport.isWaitingOnBankAccount : iouReport.hasOutstandingIOU; + reportToLook = iouReport; + } + + if (!reportToLook.ownerAccountID) { + return false; + } + + if (reportToLook.ownerAccountID === currentUserAccountID && reportToLook.isWaitingOnBankAccount) { + return true; + } + + if (reportToLook.ownerAccountID !== currentUserAccountID && reportToLook.hasOutstandingIOU) { + return true; } - return report.ownerAccountID === currentUserAccountID ? report.isWaitingOnBankAccount : report.hasOutstandingIOU; + return false; } /** * @param {Object} report * @param {String} report.iouReportID - * @param {Object} iouReports * @returns {Boolean} */ -function isIOUOwnedByCurrentUser(report, iouReports = {}) { +function isIOUOwnedByCurrentUser(report) { + let reportToLook = report; if (report.iouReportID) { - const iouReport = iouReports[`${ONYXKEYS.COLLECTION.REPORT}${report.iouReportID}`]; + const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${report.iouReportID}`]; if (iouReport) { - return iouReport.ownerAccountID === currentUserAccountID; + reportToLook = iouReport; } } - return report.ownerAccountID === currentUserAccountID; + return reportToLook.ownerAccountID === currentUserAccountID; } /** @@ -1993,12 +2015,11 @@ function canAccessReport(report, policies, betas) { * @param {Object} report * @param {String} currentReportId * @param {Boolean} isInGSDMode - * @param {Object} iouReports * @param {String[]} betas * @param {Object} policies * @returns {boolean} */ -function shouldReportBeInOptionList(report, currentReportId, isInGSDMode, iouReports, betas, policies) { +function shouldReportBeInOptionList(report, currentReportId, isInGSDMode, betas, policies) { const isInDefaultMode = !isInGSDMode; // Exclude reports that have no data because there wouldn't be anything to show in the option item. @@ -2025,7 +2046,7 @@ function shouldReportBeInOptionList(report, currentReportId, isInGSDMode, iouRep // Include reports if they have a draft, are pinned, or have an outstanding IOU // These are always relevant to the user no matter what view mode the user prefers - if (report.hasDraft || report.isPinned || hasOutstandingIOU(report, iouReports)) { + if (report.hasDraft || report.isPinned || isWaitingForIOUActionFromCurrentUser(report)) { return true; } @@ -2429,7 +2450,7 @@ export { isCurrentUserTheOnlyParticipant, hasAutomatedExpensifyAccountIDs, hasExpensifyGuidesEmails, - hasOutstandingIOU, + isWaitingForIOUActionFromCurrentUser, isIOUOwnedByCurrentUser, getMoneyRequestTotal, canShowReportRecipientLocalTime, diff --git a/src/libs/SidebarUtils.js b/src/libs/SidebarUtils.js index b9961f5fd870..497bc1e5258d 100644 --- a/src/libs/SidebarUtils.js +++ b/src/libs/SidebarUtils.js @@ -125,7 +125,7 @@ function getOrderedReportIDs(currentReportId) { const isInDefaultMode = !isInGSDMode; // Filter out all the reports that shouldn't be displayed - const reportsToDisplay = _.filter(allReports, (report) => ReportUtils.shouldReportBeInOptionList(report, currentReportId, isInGSDMode, allReports, betas, policies)); + const reportsToDisplay = _.filter(allReports, (report) => ReportUtils.shouldReportBeInOptionList(report, currentReportId, isInGSDMode, betas, policies)); if (_.isEmpty(reportsToDisplay)) { // Display Concierge chat report when there is no report to be displayed const conciergeChatReport = _.find(allReports, ReportUtils.isConciergeChatReport); @@ -302,6 +302,7 @@ function getOptionData(reportID) { result.hasOutstandingIOU = report.hasOutstandingIOU; result.parentReportID = report.parentReportID || null; result.isWaitingOnBankAccount = report.isWaitingOnBankAccount; + result.shouldShowGreenDotIndicator = report.shouldShowGreenDotIndicator; const hasMultipleParticipants = participantPersonalDetailList.length > 1 || result.isChatRoom || result.isPolicyExpenseChat; const subtitle = ReportUtils.getChatRoomSubtitle(report); diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index efe86e94b2bf..765da723697e 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -97,6 +97,7 @@ const defaultProps = { report: { hasOutstandingIOU: false, isLoadingReportActions: false, + isWaitingOnBankAccount: false, }, isComposerFullSize: false, betas: [], diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js index 6f122733607b..7a64a42389f8 100644 --- a/src/pages/home/sidebar/SidebarLinks.js +++ b/src/pages/home/sidebar/SidebarLinks.js @@ -294,6 +294,7 @@ const chatReportSelector = (report) => lastVisibleActionCreated: report.lastVisibleActionCreated, iouReportID: report.iouReportID, hasOutstandingIOU: report.hasOutstandingIOU, + isWaitingOnBankAccount: report.isWaitingOnBankAccount, statusNum: report.statusNum, stateNum: report.stateNum, chatType: report.chatType, diff --git a/src/pages/reportPropTypes.js b/src/pages/reportPropTypes.js index 4b50909032a1..5cc9fdbe55ee 100644 --- a/src/pages/reportPropTypes.js +++ b/src/pages/reportPropTypes.js @@ -25,6 +25,9 @@ export default PropTypes.shape({ /** Indicates if the report is pinned to the LHN or not */ isPinned: PropTypes.bool, + /** Whether we're waiting on submitter to add a bank account */ + isWaitingOnBankAccount: PropTypes.bool, + /** The email of the last message's actor */ lastActorEmail: PropTypes.string, diff --git a/tests/unit/ReportUtilsTest.js b/tests/unit/ReportUtilsTest.js index f33fdc86ef77..6771332ff4c6 100644 --- a/tests/unit/ReportUtilsTest.js +++ b/tests/unit/ReportUtilsTest.js @@ -291,67 +291,70 @@ describe('ReportUtils', () => { }); }); - describe('hasOutstandingIOU', () => { + describe('isWaitingForIOUActionFromCurrentUser', () => { it('returns false when there is no report', () => { - expect(ReportUtils.hasOutstandingIOU()).toBe(false); + expect(ReportUtils.isWaitingForIOUActionFromCurrentUser()).toBe(false); }); it('returns false when the report has no iouReportID', () => { const report = LHNTestUtils.getFakeReport(); - expect(ReportUtils.hasOutstandingIOU(report)).toBe(false); + expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(false); }); it('returns false when there is no iouReports collection', () => { const report = { ...LHNTestUtils.getFakeReport(), iouReportID: '1', }; - expect(ReportUtils.hasOutstandingIOU(report)).toBe(false); + expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(false); }); it('returns false when there is no matching IOU report', () => { const report = { ...LHNTestUtils.getFakeReport(), iouReportID: '1', }; - const iouReports = {}; - expect(ReportUtils.hasOutstandingIOU(report, iouReports)).toBe(false); + Onyx.merge(ONYXKEYS.COLLECTION.REPORT, { + report_2: { + reportID: '2', + }, + }); + expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(false); }); it('returns false when the matched IOU report does not have an owner email', () => { const report = { ...LHNTestUtils.getFakeReport(), iouReportID: '1', }; - const iouReports = { + Onyx.merge(ONYXKEYS.COLLECTION.REPORT, { report_1: { reportID: '1', }, - }; - expect(ReportUtils.hasOutstandingIOU(report, iouReports)).toBe(false); + }); + expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(false); }); it('returns false when the matched IOU report does not have an owner email', () => { const report = { ...LHNTestUtils.getFakeReport(), iouReportID: '1', }; - const iouReports = { + Onyx.merge(ONYXKEYS.COLLECTION.REPORT, { report_1: { reportID: '1', ownerAccountID: 99, }, - }; - expect(ReportUtils.hasOutstandingIOU(report, iouReports)).toBe(false); + }); + expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(false); }); it('returns true when the report has an oustanding IOU', () => { const report = { ...LHNTestUtils.getFakeReport(), - iouReportID: '1', - hasOutstandingIOU: true, + iouReportID: '1',q }; - const iouReports = { + Onyx.merge(ONYXKEYS.COLLECTION.REPORT, { report_1: { reportID: '1', ownerAccountID: 99, }, - }; - expect(ReportUtils.hasOutstandingIOU(report, iouReports)).toBe(true); + }); + expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(true); }); it('returns false when the report has no oustanding IOU', () => { const report = { @@ -359,13 +362,29 @@ describe('ReportUtils', () => { iouReportID: '1', hasOutstandingIOU: false, }; - const iouReports = { + Onyx.merge(ONYXKEYS.COLLECTION.REPORT, { report_1: { reportID: '1', ownerAccountID: 99, }, + }); + expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(false); + }); + + it('returns true when the report has no oustanding IOU but is waiting for a bank account', () => { + const report = { + ...LHNTestUtils.getFakeReport(), + iouReportID: '1', + hasOutstandingIOU: false, }; - expect(ReportUtils.hasOutstandingIOU(report, iouReports)).toBe(false); + Onyx.merge(ONYXKEYS.COLLECTION.REPORT, { + report_1: { + reportID: '1', + ownerAccountID: currentUserEmail, + isWaitingOnBankAccount: true, + }, + }); + expect(ReportUtils.isWaitingForIOUActionFromCurrentUser(report)).toBe(false); }); }); From 53717db4f52558dad170c7ed8d55b519f4fa60ab Mon Sep 17 00:00:00 2001 From: Nathalie Kuoch Date: Tue, 4 Jul 2023 21:45:47 +0200 Subject: [PATCH 11/60] Use button instead of link to add a bank account --- src/languages/en.js | 1 - src/languages/es.js | 1 - .../ReportActionItemReimbursementQueued.js | 29 ++++++++++--------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index e30765f7497f..e8e9fdca7dcd 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -364,7 +364,6 @@ export default { payerPaidAmount: ({payer, amount}) => `${payer} paid ${amount}`, payerSettled: ({amount}) => `paid ${amount}`, waitingOnBankAccount: ({submitterDisplayName}) => `started settling up, payment is held until ${submitterDisplayName} adds a bank account`, - waitingOnBankAccountPrefix: ({submitterDisplayName}) => `started settling up, payment is held until ${submitterDisplayName} adds a `, settledAfterAddedBankAccount: ({submitterDisplayName, amount}) => `${submitterDisplayName} added a bank account. The ${amount} payment has been made.`, settledElsewhereWithAmount: ({amount}) => `paid ${amount} elsewhere`, settledPaypalMeWithAmount: ({amount}) => `paid ${amount} using Paypal.me`, diff --git a/src/languages/es.js b/src/languages/es.js index d513d86a74f9..59666ef7f6b8 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -363,7 +363,6 @@ export default { payerPaidAmount: ({payer, amount}) => `${payer} pagó ${amount}`, payerSettled: ({amount}) => `pagó ${amount}`, waitingOnBankAccount: ({submitterDisplayName}) => `inicio el pago, pero no se procesará hasta que ${submitterDisplayName} agregue una Cuenta bancaria`, - waitingOnBankAccountPrefix: ({submitterDisplayName}) => `inicio el pago, pero no se procesará hasta que ${submitterDisplayName} agregue una `, settledAfterAddedBankAccount: ({submitterDisplayName, amount}) => `${submitterDisplayName} agregó una cuenta bancaria. El pago de ${amount} se ha realizado.`, settledElsewhereWithAmount: ({amount}) => `pagó ${amount} de otra forma`, settledPaypalMeWithAmount: ({amount}) => `pagó ${amount} con PayPal.me`, diff --git a/src/pages/home/report/ReportActionItemReimbursementQueued.js b/src/pages/home/report/ReportActionItemReimbursementQueued.js index 1c515ea82297..dbca5d6de0bb 100644 --- a/src/pages/home/report/ReportActionItemReimbursementQueued.js +++ b/src/pages/home/report/ReportActionItemReimbursementQueued.js @@ -1,11 +1,12 @@ import React from 'react'; import PropTypes from 'prop-types'; +import {View} from "react-native"; import Text from '../../../components/Text'; import styles from '../../../styles/styles'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; -import TextLink from '../../../components/TextLink'; import * as BankAccounts from '../../../libs/actions/BankAccounts'; import * as store from '../../../libs/actions/ReimbursementAccount/store'; +import Button from "../../../components/Button"; const propTypes = { submitterDisplayName: PropTypes.string.isRequired, @@ -16,18 +17,20 @@ const propTypes = { function ReportActionItemReimbursementQueued(props) { const shouldSubmitterAddBankAccount = props.isCurrentUserSubmitter && !store.hasCreditBankAccount(); - if (shouldSubmitterAddBankAccount) { - return ( - - {props.translate('iou.waitingOnBankAccountPrefix', {submitterDisplayName: props.submitterDisplayName})} - - {props.translate('common.bankAccount')} - - - ); - } - - return {props.translate('iou.waitingOnBankAccount', {submitterDisplayName: props.submitterDisplayName})}; + return ( + + {props.translate('iou.waitingOnBankAccount', {submitterDisplayName: props.submitterDisplayName})} + {shouldSubmitterAddBankAccount && ( +