From 8f961ac7430dab15850570a523ea474b70dcfaed Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Sat, 21 Oct 2023 00:00:14 +0100 Subject: [PATCH 01/71] Add a new button to the payment methods popover --- src/CONST.ts | 1 + src/components/AddPaymentMethodMenu.js | 31 +++++++++++++++++++++++++- src/components/KYCWall/BaseKYCWall.js | 1 + src/languages/en.ts | 2 ++ src/languages/es.ts | 2 ++ src/libs/ReportActionsUtils.ts | 21 +++++++++++++++++ 6 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/CONST.ts b/src/CONST.ts index 048c2dee5bab..dd6df949c3fa 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1101,6 +1101,7 @@ const CONST = { PAYMENT_METHODS: { DEBIT_CARD: 'debitCard', BANK_ACCOUNT: 'bankAccount', + BUSINESS_BANK_ACCOUNT: 'businessBankAccount', }, PAYMENT_METHOD_ID_KEYS: { diff --git a/src/components/AddPaymentMethodMenu.js b/src/components/AddPaymentMethodMenu.js index 2c3af95a3fad..7ced56b5b63a 100644 --- a/src/components/AddPaymentMethodMenu.js +++ b/src/components/AddPaymentMethodMenu.js @@ -2,6 +2,7 @@ import _ from 'underscore'; import React from 'react'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; +import lodashGet from 'lodash/get'; import * as Expensicons from './Icon/Expensicons'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import compose from '../libs/compose'; @@ -11,6 +12,9 @@ import withWindowDimensions from './withWindowDimensions'; import Permissions from '../libs/Permissions'; import PopoverMenu from './PopoverMenu'; import refPropTypes from './refPropTypes'; +import iouReportPropTypes from '../pages/iouReportPropTypes'; +import * as ReportUtils from '../libs/ReportUtils'; +import * as ReportActionsUtils from '../libs/ReportActionsUtils'; const propTypes = { /** Should the component be visible? */ @@ -19,6 +23,9 @@ const propTypes = { /** Callback to execute when the component closes. */ onClose: PropTypes.func.isRequired, + /** The IOU/Expense report we are paying */ + iouReport: iouReportPropTypes, + /** Anchor position for the AddPaymentMenu. */ anchorPosition: PropTypes.shape({ horizontal: PropTypes.number, @@ -37,10 +44,17 @@ const propTypes = { /** Popover anchor ref */ anchorRef: refPropTypes, + /** Session info for the currently logged in user. */ + session: PropTypes.shape({ + /** Currently logged in user accountID */ + accountID: PropTypes.number, + }), + ...withLocalizePropTypes, }; const defaultProps = { + iouReport: {}, anchorPosition: {}, anchorAlignment: { horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, @@ -48,6 +62,9 @@ const defaultProps = { }, betas: [], anchorRef: () => {}, + session: { + accountID: 0, + }, }; function AddPaymentMethodMenu(props) { @@ -61,12 +78,21 @@ function AddPaymentMethodMenu(props) { onItemSelected={props.onClose} menuItems={[ { - text: props.translate('common.bankAccount'), + text: props.translate('common.personalBankAccount'), icon: Expensicons.Bank, onSelected: () => { props.onItemSelected(CONST.PAYMENT_METHODS.BANK_ACCOUNT); }, }, + ...(ReportUtils.isIOUReport(this.props.iouReport) && ReportActionsUtils.hasRequestFromPayer(lodashGet(this.props.iouReport, "reportID", 0), this.props.session.accountID) + ? [ + { + text: props.translate('common.businessBankAccount'), + icon: Expensicons.Workspace, + onSelected: () => props.onItemSelected(CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT), + }, + ] + : []), ...(Permissions.canUseWallet(props.betas) ? [ { @@ -93,5 +119,8 @@ export default compose( betas: { key: ONYXKEYS.BETAS, }, + session: { + key: ONYXKEYS.SESSION, + }, }), )(AddPaymentMethodMenu); diff --git a/src/components/KYCWall/BaseKYCWall.js b/src/components/KYCWall/BaseKYCWall.js index ccee8bc4e6a0..969cbfc20dcd 100644 --- a/src/components/KYCWall/BaseKYCWall.js +++ b/src/components/KYCWall/BaseKYCWall.js @@ -164,6 +164,7 @@ class KYCWall extends React.Component { <> this.setState({shouldShowAddPaymentMenu: false})} anchorRef={this.anchorRef} anchorPosition={{ diff --git a/src/languages/en.ts b/src/languages/en.ts index 11637846130a..0a97a47cd770 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -214,6 +214,8 @@ export default { more: 'More', debitCard: 'Debit card', bankAccount: 'Bank account', + personalBankAccount: 'Personal bank account', + businessBankAccount: 'Business bank account', join: 'Join', joinThread: 'Join thread', decline: 'Decline', diff --git a/src/languages/es.ts b/src/languages/es.ts index e4a5c37241f2..8df14012ac9a 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -204,6 +204,8 @@ export default { more: 'Más', debitCard: 'Tarjeta de débito', bankAccount: 'Cuenta bancaria', + personalBankAccount: 'Personal bank account', + businessBankAccount: 'Business bank account', join: 'Unirse', joinThread: 'Unirse al hilo', decline: 'Rechazar', diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index c795e5d1c3b1..5a763bbea895 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -605,6 +605,26 @@ function isNotifiableReportAction(reportAction: OnyxEntry): boolea return actions.includes(reportAction.actionName); } +/** + * Helper method to determine if the provided accountID has made a request on the specified report. + * + * @param reportID + * @param currentAccountID + * @returns + */ +function hasRequestFromPayer(reportID: string, currentAccountID: number): boolean { + if (!reportID) { + return false; + } + + const reportActions = Object.values(getAllReportActions(reportID)); + if (reportActions.length === 0) { + return false; + } + + return reportActions.some((action) => action.actionName === CONST.REPORT.ACTIONS.TYPE.IOU && action.actorAccountID === currentAccountID); +} + export { extractLinksFromMessageHtml, getAllReportActions, @@ -644,4 +664,5 @@ export { isWhisperAction, shouldReportActionBeVisible, shouldReportActionBeVisibleAsLastAction, + hasRequestFromPayer, }; From 6c8bd199c0c73c752c58bd616fbeaaa5e500fb6b Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Sat, 21 Oct 2023 01:07:15 +0100 Subject: [PATCH 02/71] Add the business bank account option --- src/components/KYCWall/BaseKYCWall.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/KYCWall/BaseKYCWall.js b/src/components/KYCWall/BaseKYCWall.js index 969cbfc20dcd..a9814cac7492 100644 --- a/src/components/KYCWall/BaseKYCWall.js +++ b/src/components/KYCWall/BaseKYCWall.js @@ -97,6 +97,8 @@ class KYCWall extends React.Component { Navigation.navigate(this.props.addBankAccountRoute); } else if (paymentMethod === CONST.PAYMENT_METHODS.DEBIT_CARD) { Navigation.navigate(this.props.addDebitCardRoute); + } else if (paymentMethod === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT) { + // Start the Bottom up flow } } From 1a46590703a67280313606cac66002fc750219cd Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Sun, 22 Oct 2023 21:23:54 +0100 Subject: [PATCH 03/71] Work on the Bottom Up flow command --- src/CONST.ts | 4 +- src/components/KYCWall/BaseKYCWall.js | 3 +- src/libs/actions/Policy.js | 262 ++++++++++++++++++++++++++ 3 files changed, 266 insertions(+), 3 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index dd6df949c3fa..d1db6431eecb 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1190,8 +1190,8 @@ const CONST = { TYPE: { FREE: 'free', PERSONAL: 'personal', - CORPORATE: 'corporate', - TEAM: 'team', + CORPORATE: 'corporate', // aka Control + TEAM: 'team', // aka Collect }, ROLE: { ADMIN: 'admin', diff --git a/src/components/KYCWall/BaseKYCWall.js b/src/components/KYCWall/BaseKYCWall.js index a9814cac7492..e7f4b6ac1b31 100644 --- a/src/components/KYCWall/BaseKYCWall.js +++ b/src/components/KYCWall/BaseKYCWall.js @@ -9,6 +9,7 @@ import AddPaymentMethodMenu from '../AddPaymentMethodMenu'; import getClickedTargetLocation from '../../libs/getClickedTargetLocation'; import * as PaymentUtils from '../../libs/PaymentUtils'; import * as PaymentMethods from '../../libs/actions/PaymentMethods'; +import * as Policy from '../../libs/actions/Policy'; import ONYXKEYS from '../../ONYXKEYS'; import Log from '../../libs/Log'; import {propTypes, defaultProps} from './kycWallPropTypes'; @@ -98,7 +99,7 @@ class KYCWall extends React.Component { } else if (paymentMethod === CONST.PAYMENT_METHODS.DEBIT_CARD) { Navigation.navigate(this.props.addDebitCardRoute); } else if (paymentMethod === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT) { - // Start the Bottom up flow + Policy.startCollectFlow(this.props.iouReport); } } diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js index 89324dd35485..02b56a079dbe 100644 --- a/src/libs/actions/Policy.js +++ b/src/libs/actions/Policy.js @@ -1289,6 +1289,267 @@ function buildOptimisticPolicyRecentlyUsedCategories(policyID, category) { return lodashUnion([category], policyRecentlyUsedCategories); } + +function startCollectBottomUpFlow(iouReport, firstName, lastName) { + + // This flow only works for IOU reports + if (!ReportUtils.isIOUReport(iouReport)) { + return; + } + + // Generate new vairbales for the policy + const policyID = generatePolicyID() + const workspaceName = generateDefaultWorkspaceName(sessionEmail); + const employeeAccountID = iouReport.ownerAccountID; + const employeeEmail = iouReport.ownerEmail; + const {customUnits, customUnitID, customUnitRateID} = buildOptimisticCustomUnits(); + + const { + announceChatReportID, + announceChatData, + announceReportActionData, + announceCreatedReportActionID, + adminsChatReportID, + adminsChatData, + adminsReportActionData, + adminsCreatedReportActionID, + expenseChatReportID: workspaceChatReportID, + expenseChatData: workspaceChatData, + expenseReportActionData: workspaceChatReportActionData, + expenseCreatedReportActionID: workspaceChatCreatedReportActionID, + } = ReportUtils.buildOptimisticWorkspaceChats(policyID, workspaceName); + + // Create the workspace chat for the employee + const employeeWorkspaceChat = createPolicyExpenseChats(policyID, {[employeeEmail]: employeeAccountID}); + + const optimisticData = [ + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + id: policyID, + type: CONST.POLICY.TYPE.TEAM, // We are creating a collect policy in this case + name: workspaceName, + role: CONST.POLICY.ROLE.ADMIN, + owner: sessionEmail, + isPolicyExpenseChatEnabled: true, + outputCurrency: lodashGet(allPersonalDetails, [sessionAccountID, 'localCurrencyCode'], CONST.CURRENCY.USD), + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + customUnits, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, + value: { + [sessionAccountID]: { + role: CONST.POLICY.ROLE.ADMIN, + errors: {}, + }, + [employeeAccountID]: { + role: CONST.POLICY.ROLE.USER, + errors: {}, + }, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${announceChatReportID}`, + value: { + pendingFields: { + addWorkspaceRoom: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }, + ...announceChatData, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${announceChatReportID}`, + value: announceReportActionData, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${adminsChatReportID}`, + value: { + pendingFields: { + addWorkspaceRoom: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }, + ...adminsChatData, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${adminsChatReportID}`, + value: adminsReportActionData, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${workspaceChatReportID}`, + value: { + pendingFields: { + addWorkspaceRoom: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }, + ...workspaceChatData, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${workspaceChatReportID}`, + value: workspaceChatReportActionData, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${policyID}`, + value: null, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS}${policyID}`, + value: null, + }, + ...employeeWorkspaceChat.onyxOptimisticData, + ]; + + const successData = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: {pendingAction: null}, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${announceChatReportID}`, + value: { + pendingFields: { + addWorkspaceRoom: null, + }, + pendingAction: null, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${announceChatReportID}`, + value: { + [_.keys(announceChatData)[0]]: { + pendingAction: null, + }, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${adminsChatReportID}`, + value: { + pendingFields: { + addWorkspaceRoom: null, + }, + pendingAction: null, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${adminsChatReportID}`, + value: { + [_.keys(adminsChatData)[0]]: { + pendingAction: null, + }, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${workspaceChatReportID}`, + value: { + pendingFields: { + addWorkspaceRoom: null, + }, + pendingAction: null, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${workspaceChatReportID}`, + value: { + [_.keys(workspaceChatData)[0]]: { + pendingAction: null, + }, + }, + }, + ...employeeWorkspaceChat.onyxSuccessData + ]; + const failureData = [ + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, + value: null, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${announceChatReportID}`, + value: null, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${announceChatReportID}`, + value: null, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${adminsChatReportID}`, + value: null, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${adminsChatReportID}`, + value: null, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${workspaceChatReportID}`, + value: null, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${workspaceChatReportID}`, + value: null, + }, + ]; + + // Next we need to convert the IOU report to Expense report and clean up the DM chat + // Get the 1on1 chat where the request was originally made + const chatReportID = iouReport.chatReportID; ReportUtils.getReport(iouReport.chatReportID); + const reportPreviewID = iouReport.parentReportActionID; + + + const membersData = [{ + accountID: employeeAccountID, + email: employeeEmail, + workspaceChatReportID: employeeWorkspaceChat.reportCreationData[employeeEmail].reportID, + workspaceChatCreatedReportActionID: employeeWorkspaceChat.reportCreationData[employeeEmail].reportActionID, + }]; + + API.write( + 'BottomUpCollectFlow', + { + policyID, + announceChatReportID, + adminsChatReportID, + expenseChatReportID: workspaceChatReportID, + ownerEmail: sessionEmail, + makeMeAdmin: false, + policyName: workspaceName, + type: CONST.POLICY.TYPE.TEAM, + announceCreatedReportActionID, + adminsCreatedReportActionID, + expenseCreatedReportActionID: workspaceChatCreatedReportActionID, + customUnitID, + customUnitRateID, + iouReportID: iouReport.reportID, + membersData: JSON.stringify(membersData), + }, + {optimisticData, successData, failureData}, + ); + // Navigation.dismissModal(CONST.TEACHERS_UNITE.PUBLIC_ROOM_ID); +} + export { removeMembers, addMembersToWorkspace, @@ -1320,4 +1581,5 @@ export { openDraftWorkspaceRequest, buildOptimisticPolicyRecentlyUsedCategories, createDraftInitialWorkspace, + startCollectBottomUpFlow, }; From 02871ac9d817b17ca21a4e8bf1cbd4f38469403f Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Fri, 27 Oct 2023 18:17:30 +0200 Subject: [PATCH 04/71] Add FormProvider to BankAccountManualStep --- .../BankAccountManualStep.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/pages/ReimbursementAccount/BankAccountManualStep.js b/src/pages/ReimbursementAccount/BankAccountManualStep.js index 9d0b0c1f5bed..dd46bd3d22c0 100644 --- a/src/pages/ReimbursementAccount/BankAccountManualStep.js +++ b/src/pages/ReimbursementAccount/BankAccountManualStep.js @@ -15,10 +15,11 @@ import {withLocalizePropTypes} from '../../components/withLocalize'; import * as ValidationUtils from '../../libs/ValidationUtils'; import ONYXKEYS from '../../ONYXKEYS'; import exampleCheckImage from './exampleCheckImage'; -import Form from '../../components/Form'; import shouldDelayFocus from '../../libs/shouldDelayFocus'; import ScreenWrapper from '../../components/ScreenWrapper'; import StepPropTypes from './StepPropTypes'; +import FormProvider from '../../components/Form/FormProvider'; +import InputWrapper from '../../components/Form/InputWrapper'; const propTypes = { ..._.omit(StepPropTypes, _.keys(withLocalizePropTypes)), @@ -84,7 +85,7 @@ function BankAccountManualStep(props) { guidesCallTaskID={CONST.GUIDES_CALL_TASK_IDS.WORKSPACE_BANK_ACCOUNT} onBackButtonPress={props.onBackButtonPress} /> -
- - - - + ); } From e44331715595fa03d6f443350ba99973fb9aa65a Mon Sep 17 00:00:00 2001 From: tienifr Date: Sat, 28 Oct 2023 16:13:07 +0700 Subject: [PATCH 05/71] fix: 30465 --- src/components/TagPicker/index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/TagPicker/index.js b/src/components/TagPicker/index.js index 05eca664bd0f..ea29305c16b9 100644 --- a/src/components/TagPicker/index.js +++ b/src/components/TagPicker/index.js @@ -17,7 +17,8 @@ function TagPicker({selectedTag, tag, policyTags, policyRecentlyUsedTags, onSubm const policyRecentlyUsedTagsList = lodashGet(policyRecentlyUsedTags, tag, []); const policyTagList = PolicyUtils.getTagList(policyTags, tag); - const policyTagsCount = _.size(_.filter(policyTagList, (policyTag) => policyTag.enabled)); + const enabledTags = _.filter(policyTagList, (policyTag) => policyTag.enabled); + const policyTagsCount = _.size(enabledTags); const isTagsCountBelowThreshold = policyTagsCount < CONST.TAG_LIST_THRESHOLD; const shouldShowTextInput = !isTagsCountBelowThreshold; @@ -38,14 +39,14 @@ function TagPicker({selectedTag, tag, policyTags, policyRecentlyUsedTags, onSubm const initialFocusedIndex = useMemo(() => { if (isTagsCountBelowThreshold && selectedOptions.length > 0) { - return _.chain(policyTagList) + return _.chain(enabledTags) .values() .findIndex((policyTag) => policyTag.name === selectedOptions[0].name, true) .value(); } return 0; - }, [policyTagList, selectedOptions, isTagsCountBelowThreshold]); + }, [enabledTags, selectedOptions, isTagsCountBelowThreshold]); const sections = useMemo( () => From 241793718d6f274ea70e229b915bee5e4961946c Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Mon, 30 Oct 2023 13:18:37 +0100 Subject: [PATCH 06/71] fix CheckboxWithLabel forwardedRef typing --- src/components/CheckboxWithLabel.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/CheckboxWithLabel.js b/src/components/CheckboxWithLabel.js index 4bffadecb733..f18ec346dfa2 100644 --- a/src/components/CheckboxWithLabel.js +++ b/src/components/CheckboxWithLabel.js @@ -7,6 +7,7 @@ import variables from '@styles/variables'; import Checkbox from './Checkbox'; import FormHelpMessage from './FormHelpMessage'; import PressableWithFeedback from './Pressable/PressableWithFeedback'; +import refPropTypes from './refPropTypes'; import Text from './Text'; /** @@ -54,7 +55,7 @@ const propTypes = { defaultValue: PropTypes.bool, /** React ref being forwarded to the Checkbox input */ - forwardedRef: PropTypes.func, + forwardedRef: refPropTypes, /** The ID used to uniquely identify the input in a Form */ /* eslint-disable-next-line react/no-unused-prop-types */ From b1b83496b5473ef4a813da9c0a4f00155755d30b Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Wed, 1 Nov 2023 17:06:51 +0000 Subject: [PATCH 07/71] Fix merge conflict --- src/components/AddPaymentMethodMenu.js | 2 +- src/libs/actions/Policy.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/AddPaymentMethodMenu.js b/src/components/AddPaymentMethodMenu.js index a0b839e736de..813e27e3b821 100644 --- a/src/components/AddPaymentMethodMenu.js +++ b/src/components/AddPaymentMethodMenu.js @@ -84,7 +84,7 @@ function AddPaymentMethodMenu(props) { props.onItemSelected(CONST.PAYMENT_METHODS.BANK_ACCOUNT); }, }, - ...(ReportUtils.isIOUReport(this.props.iouReport) && ReportActionsUtils.hasRequestFromPayer(lodashGet(this.props.iouReport, 'reportID', 0), this.props.session.accountID) + ...(ReportUtils.isIOUReport(props.iouReport) && ReportActionsUtils.hasRequestFromPayer(lodashGet(props.iouReport, 'reportID', 0), props.session.accountID) ? [ { text: props.translate('common.businessBankAccount'), diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js index 0187af2c76a8..06b8970794d2 100644 --- a/src/libs/actions/Policy.js +++ b/src/libs/actions/Policy.js @@ -1598,7 +1598,7 @@ function startCollectBottomUpFlow(iouReport, firstName, lastName) { ]; API.write( - 'BottomUpCollectFlow', + 'CreateWorkspaceFromIOUPayment', { policyID, announceChatReportID, From c814adedbb12d5d2d5be64d8d8ec4b0aa412ce45 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 2 Nov 2023 16:32:42 +0000 Subject: [PATCH 08/71] Fix issues in the flow --- src/components/AddPaymentMethodMenu.js | 4 +-- src/components/KYCWall/BaseKYCWall.js | 1 + src/components/MoneyReportHeader.js | 2 -- .../MoneyRequestConfirmationList.js | 1 - .../ReportActionItem/ReportPreview.js | 1 - src/components/SettlementButton.js | 32 ++----------------- 6 files changed, 5 insertions(+), 36 deletions(-) diff --git a/src/components/AddPaymentMethodMenu.js b/src/components/AddPaymentMethodMenu.js index 813e27e3b821..186cab115a39 100644 --- a/src/components/AddPaymentMethodMenu.js +++ b/src/components/AddPaymentMethodMenu.js @@ -84,11 +84,11 @@ function AddPaymentMethodMenu(props) { props.onItemSelected(CONST.PAYMENT_METHODS.BANK_ACCOUNT); }, }, - ...(ReportUtils.isIOUReport(props.iouReport) && ReportActionsUtils.hasRequestFromPayer(lodashGet(props.iouReport, 'reportID', 0), props.session.accountID) + ...(ReportUtils.isIOUReport(props.iouReport) && !ReportActionsUtils.hasRequestFromPayer(lodashGet(props.iouReport, 'reportID', 0), props.session.accountID) ? [ { text: props.translate('common.businessBankAccount'), - icon: Expensicons.Workspace, + icon: Expensicons.Building, onSelected: () => props.onItemSelected(CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT), }, ] diff --git a/src/components/KYCWall/BaseKYCWall.js b/src/components/KYCWall/BaseKYCWall.js index 6093aae43d35..034f62466979 100644 --- a/src/components/KYCWall/BaseKYCWall.js +++ b/src/components/KYCWall/BaseKYCWall.js @@ -10,6 +10,7 @@ import Navigation from '@libs/Navigation/Navigation'; import * as PaymentUtils from '@libs/PaymentUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as PaymentMethods from '@userActions/PaymentMethods'; +import * as Policy from '@userActions/Policy'; import * as Wallet from '@userActions/Wallet'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; diff --git a/src/components/MoneyReportHeader.js b/src/components/MoneyReportHeader.js index a8fb5390ebb6..b3f0c52d5cdc 100644 --- a/src/components/MoneyReportHeader.js +++ b/src/components/MoneyReportHeader.js @@ -118,7 +118,6 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt onPress={(paymentType) => IOU.payMoneyRequest(paymentType, chatReport, moneyRequestReport)} enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS} addBankAccountRoute={bankAccountRoute} - shouldShowPaymentOptions style={[styles.pv2]} formattedAmount={formattedAmount} /> @@ -163,7 +162,6 @@ function MoneyReportHeader({session, personalDetails, policy, chatReport, nextSt onPress={(paymentType) => IOU.payMoneyRequest(paymentType, chatReport, moneyRequestReport)} enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS} addBankAccountRoute={bankAccountRoute} - shouldShowPaymentOptions formattedAmount={formattedAmount} /> diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index da1e03bd28e8..a8b4f95cae69 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -512,7 +512,6 @@ function MoneyRequestConfirmationList(props) { addDebitCardRoute={ROUTES.IOU_SEND_ADD_DEBIT_CARD} currency={props.iouCurrencyCode} policyID={props.policyID} - shouldShowPaymentOptions buttonSize={CONST.DROPDOWN_BUTTON_SIZE.LARGE} kycWallAnchorAlignment={{ horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, diff --git a/src/components/ReportActionItem/ReportPreview.js b/src/components/ReportActionItem/ReportPreview.js index 00a4526b382f..b90b509fdefb 100644 --- a/src/components/ReportActionItem/ReportPreview.js +++ b/src/components/ReportActionItem/ReportPreview.js @@ -245,7 +245,6 @@ function ReportPreview(props) { onPress={(paymentType) => IOU.payMoneyRequest(paymentType, props.chatReport, props.iouReport)} enablePaymentsRoute={ROUTES.ENABLE_PAYMENTS} addBankAccountRoute={bankAccountRoute} - shouldShowPaymentOptions style={[styles.mt3]} kycWallAnchorAlignment={{ horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, diff --git a/src/components/SettlementButton.js b/src/components/SettlementButton.js index d2030eac8d7d..53b85b5e0f05 100644 --- a/src/components/SettlementButton.js +++ b/src/components/SettlementButton.js @@ -40,9 +40,6 @@ const propTypes = { /** The route to redirect if user does not have a payment method setup */ enablePaymentsRoute: PropTypes.string.isRequired, - /** Should we show the payment options? */ - shouldShowPaymentOptions: PropTypes.bool, - /** The last payment method used per policy */ nvp_lastPaymentMethod: PropTypes.objectOf(PropTypes.string), @@ -97,7 +94,6 @@ const defaultProps = { betas: CONST.EMPTY_ARRAY, iouReport: CONST.EMPTY_OBJECT, nvp_lastPaymentMethod: CONST.EMPTY_OBJECT, - shouldShowPaymentOptions: false, style: [], policyID: '', formattedAmount: '', @@ -130,7 +126,6 @@ function SettlementButton({ onPress, pressOnEnter, policyID, - shouldShowPaymentOptions, style, }) { const {translate} = useLocalize(); @@ -165,33 +160,10 @@ function SettlementButton({ // To achieve the one tap pay experience we need to choose the correct payment type as default, // if user already paid for some request or expense, let's use the last payment method or use default. let paymentMethod = nvp_lastPaymentMethod[policyID] || ''; - if (!shouldShowPaymentOptions) { - if (!paymentMethod) { - // In case the user hasn't paid a request yet, let's default to VBBA payment type in case of expense reports - if (isExpenseReport) { - paymentMethod = CONST.IOU.PAYMENT_TYPE.VBBA; - } else if (canUseWallet) { - // If they have Wallet set up, use that payment method as default - paymentMethod = CONST.IOU.PAYMENT_TYPE.EXPENSIFY; - } else { - paymentMethod = CONST.IOU.PAYMENT_TYPE.ELSEWHERE; - } - } - - // In case of the settlement button in the report preview component, we do not show payment options and the label for Wallet and ACH type is simply "Pay". - return [ - { - ...paymentMethods[paymentMethod], - text: paymentMethod === CONST.IOU.PAYMENT_TYPE.ELSEWHERE ? translate('iou.payElsewhere') : translate('iou.pay'), - }, - ]; - } if (canUseWallet) { buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.EXPENSIFY]); } - if (isExpenseReport) { - buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.VBBA]); - } + buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.VBBA]); buttonOptions.push(paymentMethods[CONST.IOU.PAYMENT_TYPE.ELSEWHERE]); // Put the preferred payment method to the front of the array so its shown as default @@ -199,7 +171,7 @@ function SettlementButton({ return _.sortBy(buttonOptions, (method) => (method.value === paymentMethod ? 0 : 1)); } return buttonOptions; - }, [betas, currency, formattedAmount, iouReport, nvp_lastPaymentMethod, policyID, shouldShowPaymentOptions, translate]); + }, [betas, currency, formattedAmount, iouReport, nvp_lastPaymentMethod, policyID, translate]); const selectPaymentType = (event, iouPaymentType, triggerKYCFlow) => { if (iouPaymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY || iouPaymentType === CONST.IOU.PAYMENT_TYPE.VBBA) { From cfe141bd6af6755d84cb1fc677bb7346372e9a48 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 2 Nov 2023 16:33:19 +0000 Subject: [PATCH 09/71] Update the personal bank account const name --- src/CONST.ts | 2 +- src/components/AddPaymentMethodMenu.js | 2 +- src/components/KYCWall/BaseKYCWall.js | 4 ++-- src/libs/PaymentUtils.ts | 2 +- src/libs/actions/PaymentMethods.ts | 10 +++++----- .../Wallet/ChooseTransferAccountPage.js | 4 ++-- src/pages/settings/Wallet/PaymentMethodList.js | 6 +++--- .../settings/Wallet/TransferBalancePage.js | 6 +++--- .../settings/Wallet/WalletPage/WalletPage.js | 18 +++++++++--------- .../settings/Wallet/walletTransferPropTypes.js | 2 +- src/types/onyx/BankAccount.ts | 2 +- src/types/onyx/WalletTransfer.ts | 2 +- 12 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index e270f0066139..cb12a2a5f746 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1111,7 +1111,7 @@ const CONST = { PAYMENT_METHODS: { DEBIT_CARD: 'debitCard', - BANK_ACCOUNT: 'bankAccount', + PERSONAL_BANK_ACCOUNT: 'bankAccount', BUSINESS_BANK_ACCOUNT: 'businessBankAccount', }, diff --git a/src/components/AddPaymentMethodMenu.js b/src/components/AddPaymentMethodMenu.js index 186cab115a39..f6ed7e8254a0 100644 --- a/src/components/AddPaymentMethodMenu.js +++ b/src/components/AddPaymentMethodMenu.js @@ -81,7 +81,7 @@ function AddPaymentMethodMenu(props) { text: props.translate('common.personalBankAccount'), icon: Expensicons.Bank, onSelected: () => { - props.onItemSelected(CONST.PAYMENT_METHODS.BANK_ACCOUNT); + props.onItemSelected(CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT); }, }, ...(ReportUtils.isIOUReport(props.iouReport) && !ReportActionsUtils.hasRequestFromPayer(lodashGet(props.iouReport, 'reportID', 0), props.session.accountID) diff --git a/src/components/KYCWall/BaseKYCWall.js b/src/components/KYCWall/BaseKYCWall.js index 034f62466979..92df53353cf6 100644 --- a/src/components/KYCWall/BaseKYCWall.js +++ b/src/components/KYCWall/BaseKYCWall.js @@ -94,7 +94,7 @@ class KYCWall extends React.Component { */ selectPaymentMethod(paymentMethod) { this.props.onSelectPaymentMethod(paymentMethod); - if (paymentMethod === CONST.PAYMENT_METHODS.BANK_ACCOUNT) { + if (paymentMethod === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) { Navigation.navigate(this.props.addBankAccountRoute); } else if (paymentMethod === CONST.PAYMENT_METHODS.DEBIT_CARD) { Navigation.navigate(this.props.addDebitCardRoute); @@ -138,7 +138,7 @@ class KYCWall extends React.Component { ) { Log.info('[KYC Wallet] User does not have valid payment method'); if (!this.props.shouldIncludeDebitCard) { - this.selectPaymentMethod(CONST.PAYMENT_METHODS.BANK_ACCOUNT); + this.selectPaymentMethod(CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT); return; } const clickedElementLocation = getClickedTargetLocation(targetElement); diff --git a/src/libs/PaymentUtils.ts b/src/libs/PaymentUtils.ts index b37db2584394..5bd70fee4d83 100644 --- a/src/libs/PaymentUtils.ts +++ b/src/libs/PaymentUtils.ts @@ -26,7 +26,7 @@ function hasExpensifyPaymentMethod(fundList: Record, bankAccountLi function getPaymentMethodDescription(accountType: AccountType, account: BankAccount['accountData'] | Fund['accountData']): string { if (account) { - if (accountType === CONST.PAYMENT_METHODS.BANK_ACCOUNT && 'accountNumber' in account) { + if (accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT && 'accountNumber' in account) { return `${Localize.translateLocal('paymentMethodList.accountLastFour')} ${account.accountNumber?.slice(-4)}`; } if (accountType === CONST.PAYMENT_METHODS.DEBIT_CARD && 'cardNumber' in account) { diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts index bcc5d8142470..bc2ce95c8a43 100644 --- a/src/libs/actions/PaymentMethods.ts +++ b/src/libs/actions/PaymentMethods.ts @@ -81,7 +81,7 @@ function getMakeDefaultPaymentOnyxData( key: ONYXKEYS.USER_WALLET, value: { walletLinkedAccountID: bankAccountID || fundID, - walletLinkedAccountType: bankAccountID ? CONST.PAYMENT_METHODS.BANK_ACCOUNT : CONST.PAYMENT_METHODS.DEBIT_CARD, + walletLinkedAccountType: bankAccountID ? CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT : CONST.PAYMENT_METHODS.DEBIT_CARD, // Only clear the error if this is optimistic data. If this is failure data, we do not want to clear the error that came from the server. errors: null, }, @@ -91,7 +91,7 @@ function getMakeDefaultPaymentOnyxData( key: ONYXKEYS.USER_WALLET, value: { walletLinkedAccountID: bankAccountID || fundID, - walletLinkedAccountType: bankAccountID ? CONST.PAYMENT_METHODS.BANK_ACCOUNT : CONST.PAYMENT_METHODS.DEBIT_CARD, + walletLinkedAccountType: bankAccountID ? CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT : CONST.PAYMENT_METHODS.DEBIT_CARD, }, }, ]; @@ -99,7 +99,7 @@ function getMakeDefaultPaymentOnyxData( if (previousPaymentMethod?.methodID) { onyxData.push({ onyxMethod: Onyx.METHOD.MERGE, - key: previousPaymentMethod.accountType === CONST.PAYMENT_METHODS.BANK_ACCOUNT ? ONYXKEYS.BANK_ACCOUNT_LIST : ONYXKEYS.FUND_LIST, + key: previousPaymentMethod.accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT ? ONYXKEYS.BANK_ACCOUNT_LIST : ONYXKEYS.FUND_LIST, value: { [previousPaymentMethod.methodID]: { isDefault: !isOptimisticData, @@ -111,7 +111,7 @@ function getMakeDefaultPaymentOnyxData( if (currentPaymentMethod?.methodID) { onyxData.push({ onyxMethod: Onyx.METHOD.MERGE, - key: currentPaymentMethod.accountType === CONST.PAYMENT_METHODS.BANK_ACCOUNT ? ONYXKEYS.BANK_ACCOUNT_LIST : ONYXKEYS.FUND_LIST, + key: currentPaymentMethod.accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT ? ONYXKEYS.BANK_ACCOUNT_LIST : ONYXKEYS.FUND_LIST, value: { [currentPaymentMethod.methodID]: { isDefault: isOptimisticData, @@ -223,7 +223,7 @@ function clearDebitCardFormErrorAndSubmit() { * */ function transferWalletBalance(paymentMethod: PaymentMethod) { - const paymentMethodIDKey = paymentMethod.accountType === CONST.PAYMENT_METHODS.BANK_ACCOUNT ? CONST.PAYMENT_METHOD_ID_KEYS.BANK_ACCOUNT : CONST.PAYMENT_METHOD_ID_KEYS.DEBIT_CARD; + const paymentMethodIDKey = paymentMethod.accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT ? CONST.PAYMENT_METHOD_ID_KEYS.BANK_ACCOUNT : CONST.PAYMENT_METHOD_ID_KEYS.DEBIT_CARD; type TransferWalletBalanceParameters = Partial, number | undefined>>; diff --git a/src/pages/settings/Wallet/ChooseTransferAccountPage.js b/src/pages/settings/Wallet/ChooseTransferAccountPage.js index a44e21390b80..9fe95f477ac9 100644 --- a/src/pages/settings/Wallet/ChooseTransferAccountPage.js +++ b/src/pages/settings/Wallet/ChooseTransferAccountPage.js @@ -36,7 +36,7 @@ function ChooseTransferAccountPage(props) { * @param {Object} account of the selected account data */ const selectAccountAndNavigateBack = (event, accountType, account) => { - PaymentMethods.saveWalletTransferAccountTypeAndID(accountType, accountType === CONST.PAYMENT_METHODS.BANK_ACCOUNT ? account.bankAccountID : account.fundID); + PaymentMethods.saveWalletTransferAccountTypeAndID(accountType, accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT ? account.bankAccountID : account.fundID); Navigation.goBack(ROUTES.SETTINGS_WALLET_TRANSFER_BALANCE); }; @@ -69,7 +69,7 @@ function ChooseTransferAccountPage(props) { method.accountType === CONST.PAYMENT_METHODS.BANK_ACCOUNT || method.accountType === CONST.PAYMENT_METHODS.DEBIT_CARD, + (method) => method.accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT || method.accountType === CONST.PAYMENT_METHODS.DEBIT_CARD, ).length; return defaultablePaymentMethodCount > 1; } diff --git a/src/pages/settings/Wallet/TransferBalancePage.js b/src/pages/settings/Wallet/TransferBalancePage.js index 1df07365a1f6..fbcb7a9dc1df 100644 --- a/src/pages/settings/Wallet/TransferBalancePage.js +++ b/src/pages/settings/Wallet/TransferBalancePage.js @@ -84,7 +84,7 @@ function TransferBalancePage(props) { title: props.translate('transferAmountPage.ach'), description: props.translate('transferAmountPage.achSummary'), icon: Expensicons.Bank, - type: CONST.PAYMENT_METHODS.BANK_ACCOUNT, + type: CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT, }, ]; @@ -145,7 +145,7 @@ function TransferBalancePage(props) { { - if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.BANK_ACCOUNT) { + if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) { return paymentMethod.selectedPaymentMethod.bankAccountID; } if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.DEBIT_CARD) { @@ -150,12 +150,12 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen // The delete/default menu if (accountType) { let formattedSelectedPaymentMethod; - if (accountType === CONST.PAYMENT_METHODS.BANK_ACCOUNT) { + if (accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) { formattedSelectedPaymentMethod = { title: account.addressName, icon: account.icon, description: PaymentUtils.getPaymentMethodDescription(accountType, account), - type: CONST.PAYMENT_METHODS.BANK_ACCOUNT, + type: CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT, }; } else if (accountType === CONST.PAYMENT_METHODS.DEBIT_CARD) { formattedSelectedPaymentMethod = { @@ -200,7 +200,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen return; } - if (paymentType === CONST.PAYMENT_METHODS.BANK_ACCOUNT) { + if (paymentType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) { BankAccounts.openPersonalBankAccountSetupView(); return; } @@ -226,7 +226,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen const previousPaymentMethod = _.find(paymentMethods, (method) => method.isDefault); const currentPaymentMethod = _.find(paymentMethods, (method) => method.methodID === paymentMethod.methodID); - if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.BANK_ACCOUNT) { + if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) { PaymentMethods.makeDefaultPaymentMethod(paymentMethod.selectedPaymentMethod.bankAccountID, null, previousPaymentMethod, currentPaymentMethod); } else if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.DEBIT_CARD) { PaymentMethods.makeDefaultPaymentMethod(null, paymentMethod.selectedPaymentMethod.fundID, previousPaymentMethod, currentPaymentMethod); @@ -241,7 +241,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen ]); const deletePaymentMethod = useCallback(() => { - if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.BANK_ACCOUNT) { + if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) { BankAccounts.deletePaymentBankAccount(paymentMethod.selectedPaymentMethod.bankAccountID); } else if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.DEBIT_CARD) { PaymentMethods.deletePaymentCard(paymentMethod.selectedPaymentMethod.fundID); @@ -292,7 +292,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen // We should reset selected payment method state values and close corresponding modals if the selected payment method is deleted let shouldResetPaymentMethodData = false; - if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.BANK_ACCOUNT && _.isEmpty(bankAccountList[paymentMethod.methodID])) { + if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT && _.isEmpty(bankAccountList[paymentMethod.methodID])) { shouldResetPaymentMethodData = true; } else if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.DEBIT_CARD && _.isEmpty(fundList[paymentMethod.methodID])) { shouldResetPaymentMethodData = true; @@ -308,7 +308,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen const shouldShowMakeDefaultButton = !paymentMethod.isSelectedPaymentMethodDefault && Permissions.canUseWallet(betas) && - !(paymentMethod.formattedSelectedPaymentMethod.type === CONST.PAYMENT_METHODS.BANK_ACCOUNT && paymentMethod.selectedPaymentMethod.type === CONST.BANK_ACCOUNT.TYPE.BUSINESS); + !(paymentMethod.formattedSelectedPaymentMethod.type === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT && paymentMethod.selectedPaymentMethod.type === CONST.BANK_ACCOUNT.TYPE.BUSINESS); // Determines whether or not the modal popup is mounted from the bottom of the screen instead of the side mount on Web or Desktop screens const isPopoverBottomMount = anchorPosition.anchorPositionTop === 0 || isSmallScreenWidth; @@ -362,7 +362,7 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen navigateToWalletOrTransferBalancePage(source)} onSelectPaymentMethod={(selectedPaymentMethod) => { - if (hasActivatedWallet || selectedPaymentMethod !== CONST.PAYMENT_METHODS.BANK_ACCOUNT) { + if (hasActivatedWallet || selectedPaymentMethod !== CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT) { return; } // To allow upgrading to a gold wallet, continue with the KYC flow after adding a bank account diff --git a/src/pages/settings/Wallet/walletTransferPropTypes.js b/src/pages/settings/Wallet/walletTransferPropTypes.js index 38c65fcfd703..9e25213382e9 100644 --- a/src/pages/settings/Wallet/walletTransferPropTypes.js +++ b/src/pages/settings/Wallet/walletTransferPropTypes.js @@ -7,7 +7,7 @@ const walletTransferPropTypes = PropTypes.shape({ selectedAccountID: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), /** Type to filter the payment Method list */ - filterPaymentMethodType: PropTypes.oneOf([CONST.PAYMENT_METHODS.DEBIT_CARD, CONST.PAYMENT_METHODS.BANK_ACCOUNT, '']), + filterPaymentMethodType: PropTypes.oneOf([CONST.PAYMENT_METHODS.DEBIT_CARD, CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT, '']), /** Whether the success screen is shown to user. */ shouldShowSuccess: PropTypes.bool, diff --git a/src/types/onyx/BankAccount.ts b/src/types/onyx/BankAccount.ts index 4a7b6dac7387..2b2bee7df6b0 100644 --- a/src/types/onyx/BankAccount.ts +++ b/src/types/onyx/BankAccount.ts @@ -4,7 +4,7 @@ import * as OnyxCommon from './OnyxCommon'; type BankAccount = { /** The bank account type */ - accountType?: typeof CONST.PAYMENT_METHODS.BANK_ACCOUNT; + accountType?: typeof CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT; /** string like 'Account ending in XXXX' */ description?: string; diff --git a/src/types/onyx/WalletTransfer.ts b/src/types/onyx/WalletTransfer.ts index e1b1468d6536..cebea543884b 100644 --- a/src/types/onyx/WalletTransfer.ts +++ b/src/types/onyx/WalletTransfer.ts @@ -25,7 +25,7 @@ type WalletTransfer = { paymentMethodType?: ValueOf>; }; -type FilterMethodPaymentType = typeof CONST.PAYMENT_METHODS.DEBIT_CARD | typeof CONST.PAYMENT_METHODS.BANK_ACCOUNT | null; +type FilterMethodPaymentType = typeof CONST.PAYMENT_METHODS.DEBIT_CARD | typeof CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT | null; export default WalletTransfer; From ae33908060085d29e0ae3572b6bce00fbfa54b61 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Thu, 2 Nov 2023 23:31:23 +0000 Subject: [PATCH 10/71] Flow clean up --- src/CONST.ts | 1 + src/components/KYCWall/BaseKYCWall.js | 2 +- src/libs/ReportUtils.js | 45 +++++++++++++++++++++++ src/libs/actions/Policy.js | 41 ++++++++++++++------- src/pages/home/report/ReportActionItem.js | 2 +- 5 files changed, 75 insertions(+), 16 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index cb12a2a5f746..08a4252238d6 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -503,6 +503,7 @@ const CONST = { CREATED: 'CREATED', IOU: 'IOU', MODIFIEDEXPENSE: 'MODIFIEDEXPENSE', + MOVED: 'MOVED', REIMBURSEMENTQUEUED: 'REIMBURSEMENTQUEUED', RENAMED: 'RENAMED', REPORTPREVIEW: 'REPORTPREVIEW', diff --git a/src/components/KYCWall/BaseKYCWall.js b/src/components/KYCWall/BaseKYCWall.js index 92df53353cf6..46479d554bdf 100644 --- a/src/components/KYCWall/BaseKYCWall.js +++ b/src/components/KYCWall/BaseKYCWall.js @@ -99,7 +99,7 @@ class KYCWall extends React.Component { } else if (paymentMethod === CONST.PAYMENT_METHODS.DEBIT_CARD) { Navigation.navigate(this.props.addDebitCardRoute); } else if (paymentMethod === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT) { - Policy.startCollectFlow(this.props.iouReport); + Policy.createWorkspaceFromIOUPayment(this.props.iouReport); } } diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 10630d7fb122..d3b16a73f16f 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -2612,6 +2612,7 @@ function buildOptimisticIOUReportAction( whisperedToAccountIDs: _.contains([CONST.IOU.RECEIPT_STATE.SCANREADY, CONST.IOU.RECEIPT_STATE.SCANNING], receipt.state) ? [currentUserAccountID] : [], }; } + /** * Builds an optimistic APPROVED report action with a randomly generated reportActionID. * @@ -2650,6 +2651,49 @@ function buildOptimisticApprovedReportAction(amount, currency, expenseReportID) }; } +/** + * Builds an optimistic MOVED report action with a randomly generated reportActionID. + * This action is used when we move reports across workspaces. + * + * @param {String} fromPolicyID + * @param {String} toPolicyID + * @param {Number} newParentReportID + * @param {Number} movedReportID An ID of the report we are moveing across workspaces + * + * @returns {Object} + */ +function buildOptimisticMovedReportAction(fromPolicyID, toPolicyID, newParentReportID, movedReportID) { + const originalMessage = { + fromPolicyID, + toPolicyID, + newParentReportID, + movedReportID, + }; + + const policyName = getPolicyName(allReports[`${ONYXKEYS.COLLECTION.REPORT}${newParentReportID}`]); + + return { + actionName: CONST.REPORT.ACTIONS.TYPE.MOVED, + actorAccountID: currentUserAccountID, + automatic: false, + avatar: lodashGet(currentUserPersonalDetails, 'avatar', UserUtils.getDefaultAvatarURL(currentUserAccountID)), + isAttachment: false, + originalMessage, + message: "moved report", + person: [ + { + style: 'strong', + text: lodashGet(currentUserPersonalDetails, 'displayName', currentUserEmail), + type: 'TEXT', + }, + ], + reportActionID: NumberUtils.rand64(), + shouldShow: true, + created: DateUtils.getDBTime(), + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }; +} + /** * Builds an optimistic SUBMITTED report action with a randomly generated reportActionID. * @@ -4216,6 +4260,7 @@ export { buildOptimisticEditedTaskReportAction, buildOptimisticIOUReport, buildOptimisticApprovedReportAction, + buildOptimisticMovedReportAction, buildOptimisticSubmittedReportAction, buildOptimisticExpenseReport, buildOptimisticIOUReportAction, diff --git a/src/libs/actions/Policy.js b/src/libs/actions/Policy.js index 941fa814a9b4..a022d8f61f18 100644 --- a/src/libs/actions/Policy.js +++ b/src/libs/actions/Policy.js @@ -1360,7 +1360,7 @@ function buildOptimisticPolicyRecentlyUsedCategories(policyID, category) { return lodashUnion([category], policyRecentlyUsedCategories); } -function startCollectBottomUpFlow(iouReport, firstName, lastName) { +function createWorkspaceFromIOUPayment(iouReport) { // This flow only works for IOU reports if (!ReportUtils.isIOUReport(iouReport)) { return; @@ -1544,6 +1544,7 @@ function startCollectBottomUpFlow(iouReport, firstName, lastName) { }, ...employeeWorkspaceChat.onyxSuccessData, ]; + const failureData = [ { onyxMethod: Onyx.METHOD.SET, @@ -1585,17 +1586,29 @@ function startCollectBottomUpFlow(iouReport, firstName, lastName) { // Next we need to convert the IOU report to Expense report and clean up the DM chat // Get the 1on1 chat where the request was originally made const chatReportID = iouReport.chatReportID; - ReportUtils.getReport(iouReport.chatReportID); + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, + value: { + ...iouReport, + type: CONST.REPORT.TYPE.EXPENSE + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, + value: iouReport, + }); + + const chatReport = ReportUtils.getReport(iouReport.chatReportID); const reportPreviewID = iouReport.parentReportActionID; - const membersData = [ - { - accountID: employeeAccountID, - email: employeeEmail, - workspaceChatReportID: employeeWorkspaceChat.reportCreationData[employeeEmail].reportID, - workspaceChatCreatedReportActionID: employeeWorkspaceChat.reportCreationData[employeeEmail].reportActionID, - }, - ]; + const memberData = { + accountID: Number(employeeAccountID), + email: employeeEmail, + workspaceChatReportID: Number(employeeWorkspaceChat.reportCreationData[employeeEmail].reportID), + workspaceChatCreatedReportActionID: Number(employeeWorkspaceChat.reportCreationData[employeeEmail].reportActionID), + }; API.write( 'CreateWorkspaceFromIOUPayment', @@ -1604,7 +1617,7 @@ function startCollectBottomUpFlow(iouReport, firstName, lastName) { announceChatReportID, adminsChatReportID, expenseChatReportID: workspaceChatReportID, - ownerEmail: sessionEmail, + ownerEmail: '', makeMeAdmin: false, policyName: workspaceName, type: CONST.POLICY.TYPE.TEAM, @@ -1614,11 +1627,11 @@ function startCollectBottomUpFlow(iouReport, firstName, lastName) { customUnitID, customUnitRateID, iouReportID: iouReport.reportID, - membersData: JSON.stringify(membersData), + memberData: JSON.stringify(memberData), + reportActionID: 0, }, {optimisticData, successData, failureData}, ); - // Navigation.dismissModal(CONST.TEACHERS_UNITE.PUBLIC_ROOM_ID); } export { @@ -1647,11 +1660,11 @@ export { openWorkspaceMembersPage, openWorkspaceInvitePage, removeWorkspace, + createWorkspaceFromIOUPayment, setWorkspaceInviteMembersDraft, clearErrors, dismissAddedWithPrimaryLoginMessages, openDraftWorkspaceRequest, buildOptimisticPolicyRecentlyUsedCategories, createDraftInitialWorkspace, - startCollectBottomUpFlow, }; diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index a7a3bc0739f3..eb0ae4f8978a 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -422,7 +422,7 @@ function ReportActionItem(props) { isHidden={isHidden} style={[ _.contains( - [..._.values(CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG), CONST.REPORT.ACTIONS.TYPE.IOU, CONST.REPORT.ACTIONS.TYPE.APPROVED], + [..._.values(CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG), CONST.REPORT.ACTIONS.TYPE.IOU, CONST.REPORT.ACTIONS.TYPE.APPROVED, CONST.REPORT.ACTIONS.TYPE.MOVED], props.action.actionName, ) ? styles.colorMuted From 93d176c82676d091313aea251db3ab48a94fac56 Mon Sep 17 00:00:00 2001 From: Vit Horacek Date: Fri, 3 Nov 2023 14:26:39 +0000 Subject: [PATCH 11/71] Offer correct payment options --- src/components/AddPaymentMethodMenu.js | 18 +++++++++++------- src/components/KYCWall/BaseKYCWall.js | 6 +++++- src/pages/home/report/ReportActionItem.js | 17 +++++++++-------- .../home/report/ReportActionItemFragment.js | 2 +- .../home/report/ReportActionItemMessage.js | 1 - 5 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/components/AddPaymentMethodMenu.js b/src/components/AddPaymentMethodMenu.js index f6ed7e8254a0..85419387cc6e 100644 --- a/src/components/AddPaymentMethodMenu.js +++ b/src/components/AddPaymentMethodMenu.js @@ -77,14 +77,18 @@ function AddPaymentMethodMenu(props) { anchorRef={props.anchorRef} onItemSelected={props.onClose} menuItems={[ - { - text: props.translate('common.personalBankAccount'), - icon: Expensicons.Bank, - onSelected: () => { - props.onItemSelected(CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT); + ...(ReportUtils.isIOUReport(props.iouReport) + ?[ + { + text: props.translate('common.personalBankAccount'), + icon: Expensicons.Bank, + onSelected: () => { + props.onItemSelected(CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT); + }, }, - }, - ...(ReportUtils.isIOUReport(props.iouReport) && !ReportActionsUtils.hasRequestFromPayer(lodashGet(props.iouReport, 'reportID', 0), props.session.accountID) + ] + : []), + ...(!ReportActionsUtils.hasRequestFromPayer(lodashGet(props.iouReport, 'reportID', 0), props.session.accountID) ? [ { text: props.translate('common.businessBankAccount'), diff --git a/src/components/KYCWall/BaseKYCWall.js b/src/components/KYCWall/BaseKYCWall.js index 46479d554bdf..add5d4ba042b 100644 --- a/src/components/KYCWall/BaseKYCWall.js +++ b/src/components/KYCWall/BaseKYCWall.js @@ -99,7 +99,11 @@ class KYCWall extends React.Component { } else if (paymentMethod === CONST.PAYMENT_METHODS.DEBIT_CARD) { Navigation.navigate(this.props.addDebitCardRoute); } else if (paymentMethod === CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT) { - Policy.createWorkspaceFromIOUPayment(this.props.iouReport); + if (ReportUtils.isIOUReport(this.props.iouReport)) { + Policy.createWorkspaceFromIOUPayment(this.props.iouReport); + return; + } + Navigation.navigate(this.props.addBankAccountRoute); } } diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index 39d3f04b3961..ace51be25ea3 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -425,14 +425,15 @@ function ReportActionItem(props) { action={props.action} displayAsGroup={props.displayAsGroup} isHidden={isHidden} - style={[ - _.contains( - [..._.values(CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG), CONST.REPORT.ACTIONS.TYPE.IOU, CONST.REPORT.ACTIONS.TYPE.APPROVED, CONST.REPORT.ACTIONS.TYPE.MOVED], - props.action.actionName, - ) - ? styles.colorMuted - : undefined, - ]} + // style={[ + // _.contains( + // [..._.values(CONST.REPORT.ACTIONS.TYPE.POLICYCHANGELOG), CONST.REPORT.ACTIONS.TYPE.IOU, CONST.REPORT.ACTIONS.TYPE.APPROVED, CONST.REPORT.ACTIONS.TYPE.MOVED], + // props.action.actionName, + // ) + // ? styles.colorMuted + // : undefined, + // ]} + style={[styles.colorMuted]} /> {hasBeenFlagged && (