From 8bdb5af0a7b5abfece5c555aa77ab08f209ba210 Mon Sep 17 00:00:00 2001 From: Alex Beaman Date: Wed, 27 May 2026 12:53:32 -0600 Subject: [PATCH] Add CC/DC default vendor row in QBO export settings (Phase 2) Mirrors the existing Vendor Bill default vendor flow, gated by the `vendorMatching` beta + QBO Credit/Debit-card export config so the row only appears for workspaces where the Phase 1 fuzzy matcher can actually use it. Uses the `updateQuickbooksOnlineNonReimbursableCreditCardDefaultVendor` action shipped in Phase 1 (#91235). --- src/ROUTES.ts | 9 ++ src/SCREENS.ts | 1 + .../ModalStackNavigators/index.tsx | 2 + .../RELATIONS/WORKSPACE_TO_RHP.ts | 1 + src/libs/Navigation/linkingConfig/config.ts | 3 + src/libs/Navigation/types.ts | 3 + ...uickbooksCompanyCardExpenseAccountPage.tsx | 21 ++++- ...sableCreditCardDefaultVendorSelectPage.tsx | 87 +++++++++++++++++++ 8 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableCreditCardDefaultVendorSelectPage.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index cf6f8f95f7a5..76d22411a4a9 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -2092,6 +2092,15 @@ const ROUTES = { return `workspaces/${policyID}/accounting/quickbooks-online/export/company-card-expense-account/default-vendor-select` as const; }, }, + POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_CREDIT_CARD_DEFAULT_VENDOR_SELECT: { + route: 'workspaces/:policyID/accounting/quickbooks-online/export/company-card-expense-account/credit-card-default-vendor-select', + getRoute: (policyID: string | undefined) => { + if (!policyID) { + Log.warn('Invalid policyID is used to build the POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_CREDIT_CARD_DEFAULT_VENDOR_SELECT route'); + } + return `workspaces/${policyID}/accounting/quickbooks-online/export/company-card-expense-account/credit-card-default-vendor-select` as const; + }, + }, POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_SELECT: { route: 'workspaces/:policyID/accounting/quickbooks-online/export/company-card-expense-account/card-select', getRoute: (policyID: string | undefined, backTo?: string) => { diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 66956e3afc50..a7b8a72a0e91 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -560,6 +560,7 @@ const SCREENS = { DYNAMIC_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT: 'Dynamic_Workspace_Accounting_Quickbooks_Online_Export_Company_Card_Expense', DYNAMIC_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT_SELECT: 'Dynamic_Workspace_Accounting_Quickbooks_Online_Export_Company_Card_Expense_Account_Select', QUICKBOOKS_ONLINE_NON_REIMBURSABLE_DEFAULT_VENDOR_SELECT: 'Workspace_Accounting_Quickbooks_Online_Export_Non_Reimbursable_Default_Vendor_Select', + QUICKBOOKS_ONLINE_NON_REIMBURSABLE_CREDIT_CARD_DEFAULT_VENDOR_SELECT: 'Workspace_Accounting_Quickbooks_Online_Export_Non_Reimbursable_Credit_Card_Default_Vendor_Select', DYNAMIC_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT_COMPANY_CARD_SELECT: 'Dynamic_Workspace_Accounting_Quickbooks_Online_Export_Company_Card_Expense_Select', DYNAMIC_QUICKBOOKS_ONLINE_EXPORT_PREFERRED_EXPORTER: 'Dynamic_Workspace_Accounting_Quickbooks_Online_Export_Preferred_Exporter', QUICKBOOKS_ONLINE_TRAVEL_INVOICING_CONFIGURATION: 'Workspace_Accounting_Quickbooks_Online_Travel_Invoicing_Configuration', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 24eb086ebc38..9a8f65c526b7 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -684,6 +684,8 @@ const SettingsModalStackNavigator = createModalStackNavigator('../../../../pages/workspace/accounting/qbo/export/DynamicQuickbooksOutOfPocketExpenseEntitySelectPage').default, [SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_ONLINE_NON_REIMBURSABLE_DEFAULT_VENDOR_SELECT]: () => require('../../../../pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage').default, + [SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_ONLINE_NON_REIMBURSABLE_CREDIT_CARD_DEFAULT_VENDOR_SELECT]: () => + require('../../../../pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableCreditCardDefaultVendorSelectPage').default, [SCREENS.WORKSPACE.ACCOUNTING.DYNAMIC_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT_SELECT]: () => require('@pages/workspace/accounting/qbo/export/DynamicQuickbooksCompanyCardExpenseAccountSelectPage').default, [SCREENS.WORKSPACE.ACCOUNTING.DYNAMIC_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT_COMPANY_CARD_SELECT]: () => diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts index b6c64e0ddddf..f40d89044b79 100755 --- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts +++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts @@ -58,6 +58,7 @@ const WORKSPACE_TO_RHP: Partial['config'] = { [SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_ONLINE_NON_REIMBURSABLE_DEFAULT_VENDOR_SELECT]: { path: ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_DEFAULT_VENDOR_SELECT.route, }, + [SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_ONLINE_NON_REIMBURSABLE_CREDIT_CARD_DEFAULT_VENDOR_SELECT]: { + path: ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_CREDIT_CARD_DEFAULT_VENDOR_SELECT.route, + }, [SCREENS.WORKSPACE.ACCOUNTING.DYNAMIC_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT]: DYNAMIC_ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT.path, [SCREENS.WORKSPACE.ACCOUNTING.DYNAMIC_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT_COMPANY_CARD_SELECT]: diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 4957871c9dc0..e813ea72b60b 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -740,6 +740,9 @@ type SettingsNavigatorParamList = { [SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_ONLINE_NON_REIMBURSABLE_DEFAULT_VENDOR_SELECT]: { policyID: string; }; + [SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_ONLINE_NON_REIMBURSABLE_CREDIT_CARD_DEFAULT_VENDOR_SELECT]: { + policyID: string; + }; [SCREENS.WORKSPACE.ACCOUNTING.DYNAMIC_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT_SELECT]: { policyID: string; }; diff --git a/src/pages/workspace/accounting/qbo/export/DynamicQuickbooksCompanyCardExpenseAccountPage.tsx b/src/pages/workspace/accounting/qbo/export/DynamicQuickbooksCompanyCardExpenseAccountPage.tsx index d1e22c153dd5..107b422dace1 100644 --- a/src/pages/workspace/accounting/qbo/export/DynamicQuickbooksCompanyCardExpenseAccountPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/DynamicQuickbooksCompanyCardExpenseAccountPage.tsx @@ -6,12 +6,13 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useDynamicBackPath from '@hooks/useDynamicBackPath'; import useLocalize from '@hooks/useLocalize'; +import usePermissions from '@hooks/usePermissions'; import useThemeStyles from '@hooks/useThemeStyles'; import {updateManyPolicyConnectionConfigs} from '@libs/actions/connections'; import {getQBONonReimbursableExportAccountType} from '@libs/ConnectionUtils'; import {getLatestErrorField} from '@libs/ErrorUtils'; import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute'; -import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; +import {areSettingsInErrorFields, getQBOVendorByID, hasVendorFeature, settingsPendingAction} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; @@ -23,10 +24,13 @@ import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES'; function DynamicQuickbooksCompanyCardExpenseAccountPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const {isBetaEnabled} = usePermissions(); const policyID = policy?.id; const qboConfig = policy?.connections?.quickbooksOnline?.config; const {vendors} = policy?.connections?.quickbooksOnline?.data ?? {}; const nonReimbursableBillDefaultVendorObject = vendors?.find((vendor) => vendor.id === qboConfig?.nonReimbursableBillDefaultVendor); + const nonReimbursableCreditCardDefaultVendorObject = getQBOVendorByID(policy, qboConfig?.nonReimbursableCreditCardDefaultVendor); + const isVendorFeatureAvailable = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING)); const backPath = useDynamicBackPath(DYNAMIC_ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT.path); const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(!!qboConfig?.autoCreateVendor); @@ -79,6 +83,21 @@ function DynamicQuickbooksCompanyCardExpenseAccountPage({policy}: WithPolicyConn /> ))} + {isVendorFeatureAvailable && ( + + Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_CREDIT_CARD_DEFAULT_VENDOR_SELECT.getRoute(policyID))} + brickRoadIndicator={ + areSettingsInErrorFields([CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_DEFAULT_VENDOR], qboConfig?.errorFields) + ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR + : undefined + } + shouldShowRightIcon + /> + + )} {qboConfig?.nonReimbursableExpensesExportDestination === CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.VENDOR_BILL && ( <> + vendors?.map((vendor) => ({ + value: vendor.id, + text: vendor.name, + keyForList: vendor.name, + isSelected: vendor.id === qboConfig?.nonReimbursableCreditCardDefaultVendor, + })) ?? [], + [qboConfig?.nonReimbursableCreditCardDefaultVendor, vendors], + ); + + const selectVendor = useCallback( + (row: CardListItem) => { + if (row.value !== qboConfig?.nonReimbursableCreditCardDefaultVendor) { + updateQuickbooksOnlineNonReimbursableCreditCardDefaultVendor(policyID, row.value, qboConfig?.nonReimbursableCreditCardDefaultVendor); + } + Navigation.goBack(); + }, + [qboConfig?.nonReimbursableCreditCardDefaultVendor, policyID], + ); + + const listEmptyContent = useMemo( + () => ( + + ), + [illustrations.Telescope, translate, styles.pb10], + ); + + return ( + mode.isSelected)?.keyForList} + listEmptyContent={listEmptyContent} + connectionName={CONST.POLICY.CONNECTIONS.NAME.QBO} + onBackButtonPress={() => Navigation.goBack()} + pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_DEFAULT_VENDOR], qboConfig?.pendingFields)} + errors={getLatestErrorField(qboConfig, CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_DEFAULT_VENDOR)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_DEFAULT_VENDOR)} + /> + ); +} + +export default withPolicyConnections(QuickbooksNonReimbursableCreditCardDefaultVendorSelectPage);