From 1057dd6c48edbc4083d467fa9c0bb44e592bd129 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 31 Jan 2024 22:56:21 +0700 Subject: [PATCH 1/9] fix: Approved expense preview does not show GBR when submitter needs to add a bank account --- .../ReportActionItem/ReportPreview.tsx | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index b2fece085f57e..beef49c0c015b 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -25,12 +25,13 @@ import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu'; import * as IOU from '@userActions/IOU'; +import * as store from '@userActions/ReimbursementAccount/store'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Policy, Report, ReportAction, Session, Transaction, TransactionViolations} from '@src/types/onyx'; -import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; +import type {IOUMessage, PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import ReportActionItemImages from './ReportActionItemImages'; type ReportPreviewOnyxProps = { @@ -228,6 +229,16 @@ function ReportPreview({ return isCurrentUserManager && !isDraftExpenseReport && !isApproved && !iouSettled; }, [isPaidGroupPolicy, isCurrentUserManager, isDraftExpenseReport, isApproved, iouSettled]); const shouldShowSettlementButton = shouldShowPayButton || shouldShowApproveButton; + const paymentType = (action.originalMessage as IOUMessage).paymentType; + const isSubmitterOfUnsettledReport = ReportUtils.isCurrentUserSubmitter(iouReportID) && !ReportUtils.isSettled(iouReportID); + + const shouldPromptUserToAddBankAccount = + action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED && + isSubmitterOfUnsettledReport && + !store.hasCreditBankAccount() && + paymentType !== CONST.IOU.PAYMENT_TYPE.EXPENSIFY; + const shouldShowRBR = !iouSettled && hasErrors; + return ( @@ -256,12 +267,18 @@ function ReportPreview({ {getPreviewMessage()} - {!iouSettled && hasErrors && ( + {shouldShowRBR && ( )} + {!shouldShowRBR && shouldPromptUserToAddBankAccount && ( + + )} From 9ffd082c9f8027534012db6d2ef28d635c1801bc Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 1 Feb 2024 16:02:50 +0700 Subject: [PATCH 2/9] create util function --- .../ReportActionItem/ReportPreview.tsx | 17 +++++------------ src/libs/ReportUtils.ts | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index beef49c0c015b..ae7edc3c6d711 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -1,8 +1,8 @@ import React, {useMemo} from 'react'; -import {View} from 'react-native'; import type {StyleProp, ViewStyle} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; +import {View} from 'react-native'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import Button from '@components/Button'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; @@ -25,13 +25,12 @@ import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu'; import * as IOU from '@userActions/IOU'; -import * as store from '@userActions/ReimbursementAccount/store'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Policy, Report, ReportAction, Session, Transaction, TransactionViolations} from '@src/types/onyx'; -import type {IOUMessage, PaymentMethodType} from '@src/types/onyx/OriginalMessage'; +import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import ReportActionItemImages from './ReportActionItemImages'; type ReportPreviewOnyxProps = { @@ -229,14 +228,8 @@ function ReportPreview({ return isCurrentUserManager && !isDraftExpenseReport && !isApproved && !iouSettled; }, [isPaidGroupPolicy, isCurrentUserManager, isDraftExpenseReport, isApproved, iouSettled]); const shouldShowSettlementButton = shouldShowPayButton || shouldShowApproveButton; - const paymentType = (action.originalMessage as IOUMessage).paymentType; - const isSubmitterOfUnsettledReport = ReportUtils.isCurrentUserSubmitter(iouReportID) && !ReportUtils.isSettled(iouReportID); - - const shouldPromptUserToAddBankAccount = - action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED && - isSubmitterOfUnsettledReport && - !store.hasCreditBankAccount() && - paymentType !== CONST.IOU.PAYMENT_TYPE.EXPENSIFY; + + const shouldPromptUserToAddBankAccount = ReportUtils.hasAddBankAccountAction(iouReportID); const shouldShowRBR = !iouSettled && hasErrors; return ( diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 228db29aea6c9..29219e7df0376 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -25,6 +25,7 @@ import type {Receipt, WaypointCollection} from '@src/types/onyx/Transaction'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; +import * as store from './actions/ReimbursementAccount/store'; import * as CollectionUtils from './CollectionUtils'; import * as CurrencyUtils from './CurrencyUtils'; import DateUtils from './DateUtils'; @@ -4613,6 +4614,22 @@ function canBeAutoReimbursed(report: OnyxEntry, policy: OnyxEntry + action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED && + isSubmitterOfUnsettledReport && + !hasCreditBankAccount && + (action.originalMessage as IOUMessage)?.paymentType !== CONST.IOU.PAYMENT_TYPE.EXPENSIFY, + ); +} + export { getReportParticipantsTitle, isReportMessageAttachment, @@ -4798,6 +4815,7 @@ export { isReportParticipant, isValidReport, isReportFieldOfTypeTitle, + hasAddBankAccountAction, }; export type { From 3b9eb00bbd396ea6e7b5dbd5e03adb96dfe8289f Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 5 Feb 2024 10:48:19 +0700 Subject: [PATCH 3/9] refactor code --- src/libs/ReportUtils.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 1760635a83523..1a5883909009c 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4769,11 +4769,14 @@ function hasAddBankAccountAction(iouReportID: string): boolean { const reportActions = ReportActionsUtils.getAllReportActions(iouReportID); const isSubmitterOfUnsettledReport = isCurrentUserSubmitter(iouReportID) && !isSettled(iouReportID); const hasCreditBankAccount = store.hasCreditBankAccount(); + + if(!isSubmitterOfUnsettledReport || hasCreditBankAccount){ + return false; + } + return !!Object.values(reportActions).find( (action) => action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED && - isSubmitterOfUnsettledReport && - !hasCreditBankAccount && (action.originalMessage as IOUMessage)?.paymentType !== CONST.IOU.PAYMENT_TYPE.EXPENSIFY, ); } From 652298dd7c4c8712934d600ff80ea4e3b571506b Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 5 Feb 2024 10:53:06 +0700 Subject: [PATCH 4/9] lint fix --- src/libs/ReportUtils.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 1a5883909009c..92e24694a56b7 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4770,14 +4770,12 @@ function hasAddBankAccountAction(iouReportID: string): boolean { const isSubmitterOfUnsettledReport = isCurrentUserSubmitter(iouReportID) && !isSettled(iouReportID); const hasCreditBankAccount = store.hasCreditBankAccount(); - if(!isSubmitterOfUnsettledReport || hasCreditBankAccount){ + if (!isSubmitterOfUnsettledReport || hasCreditBankAccount) { return false; } - + return !!Object.values(reportActions).find( - (action) => - action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED && - (action.originalMessage as IOUMessage)?.paymentType !== CONST.IOU.PAYMENT_TYPE.EXPENSIFY, + (action) => action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED && (action.originalMessage as IOUMessage)?.paymentType !== CONST.IOU.PAYMENT_TYPE.EXPENSIFY, ); } From 58bb076836e979123feb3471f7b88ce087cc3db4 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 14 Feb 2024 21:35:48 +0700 Subject: [PATCH 5/9] lint fix --- src/components/ReportActionItem/ReportPreview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index 1726e0f5879d6..043c73dab90d6 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -233,7 +233,7 @@ function ReportPreview({ const shouldPromptUserToAddBankAccount = ReportUtils.hasAddBankAccountAction(iouReportID); const shouldShowRBR = !iouSettled && hasErrors; - + /* Show subtitle if at least one of the money requests is not being smart scanned, and either: - There is more than one money request – in this case, the "X requests, Y scanning" subtitle is shown; From ee483b5dcb3c9bf592a9f0abb7157a2c6319cc22 Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 19 Feb 2024 18:24:37 +0700 Subject: [PATCH 6/9] fix: refactor --- .../ReportActionItem/ReportPreview.tsx | 11 ++++-- src/libs/ReportUtils.ts | 35 ++++++++++++------- src/pages/home/report/ReportActionItem.js | 13 ++----- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx index dd7018c50b9b3..6e1dfccd52ab4 100644 --- a/src/components/ReportActionItem/ReportPreview.tsx +++ b/src/components/ReportActionItem/ReportPreview.tsx @@ -30,7 +30,7 @@ import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {Policy, Report, ReportAction, Session, Transaction, TransactionViolations} from '@src/types/onyx'; +import type {Policy, Report, ReportAction, Session, Transaction, TransactionViolations, UserWallet} from '@src/types/onyx'; import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import ReportActionItemImages from './ReportActionItemImages'; @@ -52,6 +52,9 @@ type ReportPreviewOnyxProps = { /** All of the transaction violations */ transactionViolations: OnyxCollection; + + /** The user's wallet account */ + userWallet: OnyxEntry; }; type ReportPreviewProps = ReportPreviewOnyxProps & { @@ -99,6 +102,7 @@ function ReportPreview({ isHovered = false, isWhisper = false, checkIfContextMenuActive = () => {}, + userWallet, }: ReportPreviewProps) { const theme = useTheme(); const styles = useThemeStyles(); @@ -231,7 +235,7 @@ function ReportPreview({ }, [isPaidGroupPolicy, isCurrentUserManager, isDraftExpenseReport, isApproved, isOnInstantSubmitPolicy, isOnSubmitAndClosePolicy, iouSettled]); const shouldShowSettlementButton = shouldShowPayButton || shouldShowApproveButton; - const shouldPromptUserToAddBankAccount = ReportUtils.hasAddBankAccountAction(iouReportID); + const shouldPromptUserToAddBankAccount = ReportUtils.hasMissingPaymentMethod(userWallet, iouReportID); const shouldShowRBR = !iouSettled && hasErrors; /* @@ -371,4 +375,7 @@ export default withOnyx({ transactionViolations: { key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, }, + userWallet: { + key: ONYXKEYS.USER_WALLET, + }, })(ReportPreview); diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 91dbee0355168..ae7edf7739388 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -28,6 +28,7 @@ import type { Session, Transaction, TransactionViolation, + UserWallet, } from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; @@ -421,6 +422,8 @@ type AncestorIDs = { reportActionsIDs: string[]; }; +type MissingPaymentMethod = 'bankAccount' | 'wallet'; + let currentUserEmail: string | undefined; let currentUserAccountID: number | undefined; let isAnonymousUser = false; @@ -5009,20 +5012,27 @@ function canBeAutoReimbursed(report: OnyxEntry, policy: OnyxEntry, reportId: string, reportAction: ReportAction): MissingPaymentMethod | undefined { + const isSubmitterOfUnsettledReport = isCurrentUserSubmitter(reportId) && !isSettled(reportId); + if (!isSubmitterOfUnsettledReport || reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED) { + return undefined; + } + const paymentType = reportAction.originalMessage?.paymentType; + if (paymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY) { + return isEmpty(userWallet) || userWallet.tierName === CONST.WALLET.TIER_NAME.SILVER ? 'wallet' : undefined; } - return !!Object.values(reportActions).find( - (action) => action.actionName === CONST.REPORT.ACTIONS.TYPE.REIMBURSEMENTQUEUED && action.originalMessage?.paymentType !== CONST.IOU.PAYMENT_TYPE.EXPENSIFY, - ); + return !store.hasCreditBankAccount() ? 'bankAccount' : undefined; +} + +/** + * Checks if report chat contains add bank account action + */ +function hasMissingPaymentMethod(userWallet: OnyxEntry, iouReportID: string): boolean { + const reportActions = ReportActionsUtils.getAllReportActions(iouReportID); + return Object.values(reportActions).some((action) => getIndicatedMissingPaymentMethod(userWallet, iouReportID, action) !== undefined); } export { @@ -5216,7 +5226,7 @@ export { isValidReport, getReportDescriptionText, isReportFieldOfTypeTitle, - hasAddBankAccountAction, + hasMissingPaymentMethod, isIOUReportUsingReport, hasUpdatedTotal, isReportFieldDisabled, @@ -5225,6 +5235,7 @@ export { getAllAncestorReportActionIDs, canEditPolicyDescription, getPolicyDescriptionText, + getIndicatedMissingPaymentMethod, }; export type { diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 39a5fcaa4ee00..d8232150b6a15 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -54,7 +54,6 @@ import {ReactionListContext} from '@pages/home/ReportScreenContext'; import reportPropTypes from '@pages/reportPropTypes'; import * as BankAccounts from '@userActions/BankAccounts'; import * as EmojiPickerAction from '@userActions/EmojiPickerAction'; -import * as store from '@userActions/ReimbursementAccount/store'; import * as Report from '@userActions/Report'; import * as ReportActions from '@userActions/ReportActions'; import * as Session from '@userActions/Session'; @@ -416,19 +415,13 @@ function ReportActionItem(props) { const submitterDisplayName = PersonalDetailsUtils.getDisplayNameOrDefault(lodashGet(personalDetails, props.report.ownerAccountID)); const paymentType = lodashGet(props.action, 'originalMessage.paymentType', ''); - const isSubmitterOfUnsettledReport = ReportUtils.isCurrentUserSubmitter(props.report.reportID) && !ReportUtils.isSettled(props.report.reportID); - const shouldShowAddCreditBankAccountButton = isSubmitterOfUnsettledReport && !store.hasCreditBankAccount() && paymentType !== CONST.IOU.PAYMENT_TYPE.EXPENSIFY; - const shouldShowEnableWalletButton = - isSubmitterOfUnsettledReport && - (_.isEmpty(props.userWallet) || props.userWallet.tierName === CONST.WALLET.TIER_NAME.SILVER) && - paymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY; - + const missingPaymentMethod = ReportUtils.getIndicatedMissingPaymentMethod(props.userWallet, props.report.reportID, props.action); children = ( <> - {shouldShowAddCreditBankAccountButton && ( + {missingPaymentMethod === 'bankAccount' && (