-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Fix add business bank account opens personal bank account flow in invoice room #75530
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
dfd5cc9
a329868
837c1c5
9e8f49b
1090638
556b607
600eeae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,8 +5,8 @@ | |||||||||||||||||||||
| import type {GestureResponderEvent} from 'react-native'; | ||||||||||||||||||||||
| import type {TupleToUnion} from 'type-fest'; | ||||||||||||||||||||||
| import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; | ||||||||||||||||||||||
| import * as Expensicons from '@components/Icon/Expensicons'; | ||||||||||||||||||||||
|
Check warning on line 8 in src/components/SettlementButton/index.tsx
|
||||||||||||||||||||||
| import {Bank} from '@components/Icon/Expensicons'; | ||||||||||||||||||||||
|
Check warning on line 9 in src/components/SettlementButton/index.tsx
|
||||||||||||||||||||||
| import KYCWall from '@components/KYCWall'; | ||||||||||||||||||||||
| import {KYCWallContext} from '@components/KYCWall/KYCWallContext'; | ||||||||||||||||||||||
| import type {ContinueActionParams, PaymentMethod} from '@components/KYCWall/types'; | ||||||||||||||||||||||
|
|
@@ -18,15 +18,15 @@ | |||||||||||||||||||||
| import usePermissions from '@hooks/usePermissions'; | ||||||||||||||||||||||
| import usePolicy from '@hooks/usePolicy'; | ||||||||||||||||||||||
| import useThemeStyles from '@hooks/useThemeStyles'; | ||||||||||||||||||||||
| import {isCurrencySupportedForDirectReimbursement} from '@libs/actions/Policy/Policy'; | ||||||||||||||||||||||
| import {createWorkspace, isCurrencySupportedForDirectReimbursement} from '@libs/actions/Policy/Policy'; | ||||||||||||||||||||||
| import {navigateToBankAccountRoute} from '@libs/actions/ReimbursementAccount'; | ||||||||||||||||||||||
| import {getLastPolicyBankAccountID, getLastPolicyPaymentMethod} from '@libs/actions/Search'; | ||||||||||||||||||||||
| import Navigation from '@libs/Navigation/Navigation'; | ||||||||||||||||||||||
| import {formatPaymentMethods, getActivePaymentType} from '@libs/PaymentUtils'; | ||||||||||||||||||||||
| import {getActiveAdminWorkspaces, getPolicyEmployeeAccountIDs} from '@libs/PolicyUtils'; | ||||||||||||||||||||||
| import {getActiveAdminWorkspaces, getPolicyEmployeeAccountIDs, isPaidGroupPolicy, isPolicyAdmin} from '@libs/PolicyUtils'; | ||||||||||||||||||||||
| import {hasRequestFromCurrentAccount} from '@libs/ReportActionsUtils'; | ||||||||||||||||||||||
| import { | ||||||||||||||||||||||
| doesReportBelongToWorkspace, | ||||||||||||||||||||||
| getBankAccountRoute, | ||||||||||||||||||||||
| hasViolations as hasViolationsReportUtils, | ||||||||||||||||||||||
| isBusinessInvoiceRoom, | ||||||||||||||||||||||
| isExpenseReport as isExpenseReportUtil, | ||||||||||||||||||||||
|
|
@@ -96,7 +96,7 @@ | |||||||||||||||||||||
| const {translate, localeCompare} = useLocalize(); | ||||||||||||||||||||||
| const {isOffline} = useNetwork(); | ||||||||||||||||||||||
| const policy = usePolicy(policyID); | ||||||||||||||||||||||
| const {accountID, email} = useCurrentUserPersonalDetails(); | ||||||||||||||||||||||
| const {accountID, email, localCurrencyCode} = useCurrentUserPersonalDetails(); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| // The app would crash due to subscribing to the entire report collection if chatReportID is an empty string. So we should have a fallback ID here. | ||||||||||||||||||||||
| // eslint-disable-next-line rulesdir/no-default-id-values | ||||||||||||||||||||||
|
|
@@ -119,8 +119,13 @@ | |||||||||||||||||||||
|
|
||||||||||||||||||||||
| const lastBankAccountID = getLastPolicyBankAccountID(policyIDKey, lastPaymentMethods, iouReport?.type as keyof LastPaymentMethodType); | ||||||||||||||||||||||
| const [fundList] = useOnyx(ONYXKEYS.FUND_LIST, {canBeMissing: true}); | ||||||||||||||||||||||
| const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID, {canBeMissing: true}); | ||||||||||||||||||||||
| const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true}); | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| const [invoiceReceiverPolicy] = useOnyx( | ||||||||||||||||||||||
| `${ONYXKEYS.COLLECTION.POLICY}${chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : undefined}`, | ||||||||||||||||||||||
| {canBeMissing: true}, | ||||||||||||||||||||||
| ); | ||||||||||||||||||||||
bernhardoj marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||
| const activePolicy = usePolicy(activePolicyID); | ||||||||||||||||||||||
| const activeAdminPolicies = getActiveAdminWorkspaces(policies, accountID.toString()).sort((a, b) => localeCompare(a.name || '', b.name || '')); | ||||||||||||||||||||||
| const reportID = iouReport?.reportID; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
@@ -295,7 +300,7 @@ | |||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if ((hasMultiplePolicies || hasSinglePolicy) && canUseWallet && !isPersonalOnlyOption) { | ||||||||||||||||||||||
| activeAdminPolicies.forEach((activePolicy) => { | ||||||||||||||||||||||
|
Check failure on line 303 in src/components/SettlementButton/index.tsx
|
||||||||||||||||||||||
| const policyName = activePolicy.name; | ||||||||||||||||||||||
| buttonOptions.push({ | ||||||||||||||||||||||
| text: translate('iou.payWithPolicy', {policyName: truncate(policyName, {length: CONST.ADDITIONAL_ALLOWED_CHARACTERS}), formattedAmount: ''}), | ||||||||||||||||||||||
|
|
@@ -314,20 +319,41 @@ | |||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if (isInvoiceReport) { | ||||||||||||||||||||||
| const hasActivePolicyAsAdmin = activePolicy && isPolicyAdmin(activePolicy) && isPaidGroupPolicy(activePolicy); | ||||||||||||||||||||||
bernhardoj marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| const isCurrencySupported = isCurrencySupportedForDirectReimbursement(currency as CurrencyType); | ||||||||||||||||||||||
| const isActivePolicyCurrencySupported = isCurrencySupportedForDirectReimbursement(activePolicy?.outputCurrency ?? ''); | ||||||||||||||||||||||
bernhardoj marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||
| const isUserCurrencySupported = isCurrencySupportedForDirectReimbursement(localCurrencyCode ?? ''); | ||||||||||||||||||||||
| const isInvoiceReceiverPolicyCurrencySupported = isCurrencySupportedForDirectReimbursement(invoiceReceiverPolicy?.outputCurrency ?? ''); | ||||||||||||||||||||||
bernhardoj marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| const canUseActivePolicy = hasActivePolicyAsAdmin && isActivePolicyCurrencySupported; | ||||||||||||||||||||||
bernhardoj marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||
| const isPolicyCurrencySupported = invoiceReceiverPolicy ? isInvoiceReceiverPolicyCurrencySupported : canUseActivePolicy || isUserCurrencySupported; | ||||||||||||||||||||||
|
Check failure on line 330 in src/components/SettlementButton/index.tsx
|
||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❌ Missing Error HandlingThe Why this matters:
Suggested fix: Add proper async handling: onSelected: async () => {
if (payAsBusiness) {
if (chatReport?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS) {
navigateToBankAccountRoute(chatReport?.invoiceReceiver?.policyID);
} else {
if (!canUseActivePolicy) {
try {
const {policyID} = await createWorkspace();
navigateToBankAccountRoute(policyID);
} catch (error) {
// Handle error appropriately
console.error('Failed to create workspace:', error);
}
} else {
navigateToBankAccountRoute(activePolicy.id);
}
}
} else {
Navigation.navigate(ROUTES.SETTINGS_ADD_BANK_ACCOUNT.route);
}
},Check if
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bernhardoj Can you check this comment?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I left this unresolved since I'm not sure how to handle this. We create the workspace optimistically and navigate to the bank account page. Should we show not found page if the workspace is failed to be created? App/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx Lines 426 to 435 in cb4506d
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| const getInvoicesOptions = (payAsBusiness: boolean) => { | ||||||||||||||||||||||
| const addBankAccountItem = { | ||||||||||||||||||||||
| text: translate('bankAccount.addBankAccount'), | ||||||||||||||||||||||
| icon: Expensicons.Bank, | ||||||||||||||||||||||
| onSelected: () => { | ||||||||||||||||||||||
| const bankAccountRoute = getBankAccountRoute(chatReport); | ||||||||||||||||||||||
| Navigation.navigate(bankAccountRoute); | ||||||||||||||||||||||
| if (payAsBusiness) { | ||||||||||||||||||||||
| if (chatReport?.invoiceReceiver?.type === CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS) { | ||||||||||||||||||||||
| navigateToBankAccountRoute(chatReport?.invoiceReceiver?.policyID); | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| if (!canUseActivePolicy) { | ||||||||||||||||||||||
|
Check failure on line 341 in src/components/SettlementButton/index.tsx
|
||||||||||||||||||||||
| const {policyID} = createWorkspace(); | ||||||||||||||||||||||
|
Check failure on line 342 in src/components/SettlementButton/index.tsx
|
||||||||||||||||||||||
| navigateToBankAccountRoute(policyID); | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| navigateToBankAccountRoute(activePolicy.id); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| Navigation.navigate(ROUTES.SETTINGS_ADD_BANK_ACCOUNT.route); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| }, | ||||||||||||||||||||||
| value: CONST.IOU.PAYMENT_TYPE.ELSEWHERE, | ||||||||||||||||||||||
| }; | ||||||||||||||||||||||
| return [ | ||||||||||||||||||||||
| ...(isCurrencySupported ? getPaymentSubitems(payAsBusiness) : []), | ||||||||||||||||||||||
| ...(isCurrencySupported ? [addBankAccountItem] : []), | ||||||||||||||||||||||
| ...(isCurrencySupported && isPolicyCurrencySupported ? [addBankAccountItem] : []), | ||||||||||||||||||||||
| { | ||||||||||||||||||||||
| text: translate('iou.payElsewhere', {formattedAmount: ''}), | ||||||||||||||||||||||
| icon: Expensicons.Cash, | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.