From fbb02a0ceec039a9b40ede4471870f84962b89cf Mon Sep 17 00:00:00 2001 From: Ben Limpich Date: Tue, 21 Apr 2026 11:41:07 -0700 Subject: [PATCH] [NO QA] Remove NetSuite travel invoicing vendor selector Travel invoicing vendor = employee email in all NetSuite vendor bill setups, making a separate travel vendor setting meaningless. Remove the UI selector, route, screen constant, navigator registration, action, type field, and test. Keep the payable account selector and all QBO vendor functionality. --- src/CONST/index.ts | 1 - src/ROUTES.ts | 4 - 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 - .../actions/connections/NetSuiteCommands.ts | 12 --- .../NetSuiteExportConfigurationPage.tsx | 2 +- ...tSuiteTravelInvoicingConfigurationPage.tsx | 17 +--- ...etSuiteTravelInvoicingVendorSelectPage.tsx | 82 ------------------- src/types/onyx/Policy.ts | 3 - tests/actions/connections/NetSuite.ts | 30 +------ 13 files changed, 3 insertions(+), 158 deletions(-) delete mode 100644 src/pages/workspace/accounting/netsuite/export/NetSuiteTravelInvoicingVendorSelectPage.tsx diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 14d84b9bc844..0f882fbc2f12 100644 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -2819,7 +2819,6 @@ const CONST = { REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'reimbursableExpensesExportDestination', NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'nonreimbursableExpensesExportDestination', DEFAULT_VENDOR: 'defaultVendor', - TRAVEL_INVOICING_VENDOR: 'travelInvoicingVendorID', TRAVEL_INVOICING_PAYABLE_ACCOUNT: 'travelInvoicingPayableAccountID', REIMBURSABLE_PAYABLE_ACCOUNT: 'reimbursablePayableAccount', PAYABLE_ACCT: 'payableAcct', diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 1cd0ca41d6ec..15be47d0c2b7 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -1888,10 +1888,6 @@ const ROUTES = { route: 'workspaces/:policyID/accounting/netsuite/export/travel-invoicing', getRoute: (policyID: string) => `workspaces/${policyID}/accounting/netsuite/export/travel-invoicing` as const, }, - POLICY_ACCOUNTING_NETSUITE_TRAVEL_INVOICING_VENDOR_SELECT: { - route: 'workspaces/:policyID/accounting/netsuite/export/travel-invoicing/vendor', - getRoute: (policyID: string) => `workspaces/${policyID}/accounting/netsuite/export/travel-invoicing/vendor` as const, - }, POLICY_ACCOUNTING_NETSUITE_TRAVEL_INVOICING_PAYABLE_ACCOUNT_SELECT: { route: 'workspaces/:policyID/accounting/netsuite/export/travel-invoicing/payable-account', getRoute: (policyID: string) => `workspaces/${policyID}/accounting/netsuite/export/travel-invoicing/payable-account` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 3f9ec7551053..697269f9f752 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -538,7 +538,6 @@ const SCREENS = { QUICKBOOKS_ONLINE_TRAVEL_INVOICING_VENDOR_SELECT: 'Workspace_Accounting_Quickbooks_Online_Travel_Invoicing_Vendor_Select', QUICKBOOKS_ONLINE_TRAVEL_INVOICING_PAYABLE_ACCOUNT_SELECT: 'Workspace_Accounting_Quickbooks_Online_Travel_Invoicing_Payable_Account_Select', NETSUITE_TRAVEL_INVOICING_CONFIGURATION: 'Workspace_Accounting_NetSuite_Travel_Invoicing_Configuration', - NETSUITE_TRAVEL_INVOICING_VENDOR_SELECT: 'Workspace_Accounting_NetSuite_Travel_Invoicing_Vendor_Select', NETSUITE_TRAVEL_INVOICING_PAYABLE_ACCOUNT_SELECT: 'Workspace_Accounting_NetSuite_Travel_Invoicing_Payable_Account_Select', DYNAMIC_QUICKBOOKS_ONLINE_EXPORT_OUT_OF_POCKET_EXPENSES: 'Dynamic_Workspace_Accounting_Quickbooks_Online_Export_Out_Of_Pocket_Expenses', DYNAMIC_QUICKBOOKS_ONLINE_EXPORT_OUT_OF_POCKET_EXPENSES_SELECT: 'Dynamic_Workspace_Accounting_Quickbooks_Online_Export_Out_Of_Pocket_Expenses_Select', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 71ad31690360..eca92093dc24 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -603,8 +603,6 @@ const SettingsModalStackNavigator = createModalStackNavigator('../../../../pages/workspace/accounting/qbo/export/QuickbooksExportTravelPayableAccountSelectPage').default, [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_TRAVEL_INVOICING_CONFIGURATION]: () => require('../../../../pages/workspace/accounting/netsuite/export/NetSuiteTravelInvoicingConfigurationPage').default, - [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_TRAVEL_INVOICING_VENDOR_SELECT]: () => - require('../../../../pages/workspace/accounting/netsuite/export/NetSuiteTravelInvoicingVendorSelectPage').default, [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_TRAVEL_INVOICING_PAYABLE_ACCOUNT_SELECT]: () => require('../../../../pages/workspace/accounting/netsuite/export/NetSuiteTravelInvoicingPayableAccountSelectPage').default, [SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_COMPANY_CARD_EXPENSE_ACCOUNT_SELECT]: () => diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts index 47bee27212dc..c057a05e28fc 100755 --- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts +++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts @@ -53,7 +53,6 @@ const WORKSPACE_TO_RHP: Partial['config'] = { [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_TRAVEL_INVOICING_CONFIGURATION]: { path: ROUTES.POLICY_ACCOUNTING_NETSUITE_TRAVEL_INVOICING_CONFIGURATION.route, }, - [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_TRAVEL_INVOICING_VENDOR_SELECT]: { - path: ROUTES.POLICY_ACCOUNTING_NETSUITE_TRAVEL_INVOICING_VENDOR_SELECT.route, - }, [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_TRAVEL_INVOICING_PAYABLE_ACCOUNT_SELECT]: { path: ROUTES.POLICY_ACCOUNTING_NETSUITE_TRAVEL_INVOICING_PAYABLE_ACCOUNT_SELECT.route, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index d5b8557e1722..9bf99e00727b 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -763,9 +763,6 @@ type SettingsNavigatorParamList = { [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_TRAVEL_INVOICING_CONFIGURATION]: { policyID: string; }; - [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_TRAVEL_INVOICING_VENDOR_SELECT]: { - policyID: string; - }; [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_TRAVEL_INVOICING_PAYABLE_ACCOUNT_SELECT]: { policyID: string; }; diff --git a/src/libs/actions/connections/NetSuiteCommands.ts b/src/libs/actions/connections/NetSuiteCommands.ts index 38d85845ca0d..e670d9d5ecfa 100644 --- a/src/libs/actions/connections/NetSuiteCommands.ts +++ b/src/libs/actions/connections/NetSuiteCommands.ts @@ -1062,17 +1062,6 @@ function updateNetSuiteCustomFormIDOptions( API.write(commandName, parameters, onyxData); } -function updateNetSuiteTravelInvoicingVendor(policyID: string, vendorID: string, oldVendorID?: string) { - const onyxData = updateNetSuiteOnyxData(policyID, CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_VENDOR, vendorID, oldVendorID); - const parameters: UpdateManyPolicyConnectionConfigurationsParams = { - policyID, - connectionName: CONST.POLICY.CONNECTIONS.NAME.NETSUITE, - configUpdate: JSON.stringify({[CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_VENDOR]: vendorID}), - idempotencyKey: CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_VENDOR, - }; - API.write(WRITE_COMMANDS.UPDATE_MANY_POLICY_CONNECTION_CONFIGS, parameters, onyxData); -} - function updateNetSuiteTravelInvoicingPayableAccount(policyID: string, accountID: string, oldAccountID?: string) { const onyxData = updateNetSuiteOnyxData(policyID, CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_PAYABLE_ACCOUNT, accountID, oldAccountID); const parameters: UpdateManyPolicyConnectionConfigurationsParams = { @@ -1123,6 +1112,5 @@ export { updateNetSuiteCustomFormIDOptions, updateNetSuiteCustomersJobsMapping, updateNetSuiteAccountingMethod, - updateNetSuiteTravelInvoicingVendor, updateNetSuiteTravelInvoicingPayableAccount, }; diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportConfigurationPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportConfigurationPage.tsx index fa078193054e..4bd3d4aa1506 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportConfigurationPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportConfigurationPage.tsx @@ -189,7 +189,7 @@ function NetSuiteExportConfigurationPage({policy}: WithPolicyConnectionsProps) { title: travelPayableAccount?.name, description: translate('workspace.netsuite.travelInvoicing'), onPress: !policyID ? undefined : () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_TRAVEL_INVOICING_CONFIGURATION.getRoute(policyID)), - subscribedSettings: [CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_VENDOR, CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_PAYABLE_ACCOUNT], + subscribedSettings: [CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_PAYABLE_ACCOUNT], shouldHide: !isTravelInvoicingEnabled, }, { diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteTravelInvoicingConfigurationPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteTravelInvoicingConfigurationPage.tsx index 7fbe16246ccf..bdc9c3ba492d 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteTravelInvoicingConfigurationPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteTravelInvoicingConfigurationPage.tsx @@ -22,7 +22,6 @@ type NetSuiteSectionType = { brickRoadIndicator?: ValueOf; }; -const vendorSetting = [CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_VENDOR]; const payableAccountSetting = [CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_PAYABLE_ACCOUNT]; function NetSuiteTravelInvoicingConfigurationPage({policy}: WithPolicyConnectionsProps) { @@ -32,24 +31,10 @@ function NetSuiteTravelInvoicingConfigurationPage({policy}: WithPolicyConnection const policyID = policy?.id ?? String(CONST.DEFAULT_NUMBER_ID); const config = policy?.connections?.netsuite?.options?.config; - const {vendors, payableList} = policy?.connections?.netsuite?.options?.data ?? {}; - const travelVendor = vendors?.find((vendor) => vendor.id === config?.travelInvoicingVendorID); + const {payableList} = policy?.connections?.netsuite?.options?.data ?? {}; const travelPayableAccount = payableList?.find((account) => account.id === config?.travelInvoicingPayableAccountID); const sections: NetSuiteSectionType[] = [ - { - title: travelVendor?.name, - description: translate('workspace.netsuite.travelInvoicingVendor'), - onPress: () => { - if (!policyID) { - return; - } - Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_TRAVEL_INVOICING_VENDOR_SELECT.getRoute(policyID)); - }, - subscribedSettings: vendorSetting, - pendingAction: settingsPendingAction(vendorSetting, config?.pendingFields), - brickRoadIndicator: areSettingsInErrorFields(vendorSetting, config?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - }, { title: travelPayableAccount?.name, description: translate('workspace.netsuite.travelInvoicingPayableAccount'), diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteTravelInvoicingVendorSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteTravelInvoicingVendorSelectPage.tsx deleted file mode 100644 index 7481e9f5e114..000000000000 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteTravelInvoicingVendorSelectPage.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import React from 'react'; -import BlockingView from '@components/BlockingViews/BlockingView'; -import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; -import type {ListItem} from '@components/SelectionList/types'; -import SelectionScreen from '@components/SelectionScreen'; -import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; -import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; -import {updateNetSuiteTravelInvoicingVendor} from '@libs/actions/connections/NetSuiteCommands'; -import {getLatestErrorField} from '@libs/ErrorUtils'; -import {settingsPendingAction} from '@libs/PolicyUtils'; -import Navigation from '@navigation/Navigation'; -import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; -import withPolicyConnections from '@pages/workspace/withPolicyConnections'; -import variables from '@styles/variables'; -import {clearNetSuiteErrorField} from '@userActions/Policy/Policy'; -import CONST from '@src/CONST'; -import ROUTES from '@src/ROUTES'; - -type VendorListItem = ListItem & { - value: string; -}; - -function NetSuiteTravelInvoicingVendorSelectPage({policy}: WithPolicyConnectionsProps) { - const {translate} = useLocalize(); - const styles = useThemeStyles(); - const illustrations = useMemoizedLazyIllustrations(['Telescope']); - - const {vendors} = policy?.connections?.netsuite?.options?.data ?? {}; - const config = policy?.connections?.netsuite?.options?.config; - - const policyID = policy?.id ?? String(CONST.DEFAULT_NUMBER_ID); - const data: VendorListItem[] = - vendors?.map((vendor) => ({ - value: vendor.id, - text: vendor.name, - keyForList: vendor.id, - isSelected: vendor.id === config?.travelInvoicingVendorID, - })) ?? []; - - const selectVendor = (row: VendorListItem) => { - if (row.value !== config?.travelInvoicingVendorID) { - updateNetSuiteTravelInvoicingVendor(policyID, row.value, config?.travelInvoicingVendorID); - } - Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_TRAVEL_INVOICING_CONFIGURATION.getRoute(policyID)); - }; - - const listEmptyContent = ( - - ); - - return ( - option.isSelected)?.keyForList} - listEmptyContent={listEmptyContent} - connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} - onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_TRAVEL_INVOICING_CONFIGURATION.getRoute(policyID))} - pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_VENDOR], config?.pendingFields)} - errors={getLatestErrorField(config, CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_VENDOR)} - errorRowStyles={[styles.ph5, styles.pv3]} - onClose={() => clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_VENDOR)} - /> - ); -} - -export default withPolicyConnections(NetSuiteTravelInvoicingVendorSelectPage); diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 33fb14486f05..c1b6ddcf64f1 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1074,9 +1074,6 @@ type NetSuiteConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback< /** The default vendor to use for Transactions in NetSuite */ defaultVendor?: string; - /** The vendor to use for Expensify Travel expenses when exporting to NetSuite */ - travelInvoicingVendorID?: string; - /** The payable account to use for Expensify Travel expenses when exporting to NetSuite */ travelInvoicingPayableAccountID?: string; diff --git a/tests/actions/connections/NetSuite.ts b/tests/actions/connections/NetSuite.ts index 9b64235a89b3..26706483ded9 100644 --- a/tests/actions/connections/NetSuite.ts +++ b/tests/actions/connections/NetSuite.ts @@ -1,7 +1,7 @@ import Onyx from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import {shouldUseUpdateNetSuiteTokens} from '@libs/actions/connections'; -import {connectPolicyToNetSuite, updateNetSuiteTokens, updateNetSuiteTravelInvoicingPayableAccount, updateNetSuiteTravelInvoicingVendor} from '@libs/actions/connections/NetSuiteCommands'; +import {connectPolicyToNetSuite, updateNetSuiteTokens, updateNetSuiteTravelInvoicingPayableAccount} from '@libs/actions/connections/NetSuiteCommands'; // eslint-disable-next-line no-restricted-syntax -- this is required to allow mocking import * as API from '@libs/API'; import type {WriteCommand} from '@libs/API/types'; @@ -158,34 +158,6 @@ describe('actions/connections/NetSuite', () => { }); }); - describe('updateNetSuiteTravelInvoicingVendor', () => { - it('writes the UpdateManyPolicyConnectionConfigs command with travelInvoicingVendorID', () => { - updateNetSuiteTravelInvoicingVendor(MOCK_POLICY_ID, 'vendor-123', 'old-vendor'); - - const {command} = getFirstWriteCall(); - expect(command).toBe(WRITE_COMMANDS.UPDATE_MANY_POLICY_CONNECTION_CONFIGS); - - const call = writeSpy.mock.calls.at(0); - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- API.write's params argument is typed as a broad union, so narrow to the shape this command sends - const params = call?.[1] as {connectionName: string; configUpdate: string; policyID: string}; - expect(params.policyID).toBe(MOCK_POLICY_ID); - expect(params.connectionName).toBe(CONST.POLICY.CONNECTIONS.NAME.NETSUITE); - expect(JSON.parse(params.configUpdate)).toEqual({[CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_VENDOR]: 'vendor-123'}); - }); - - it('merges travelInvoicingVendorID optimistically onto the NetSuite options config', () => { - updateNetSuiteTravelInvoicingVendor(MOCK_POLICY_ID, 'vendor-123', 'old-vendor'); - - const {onyxData} = getFirstWriteCall(); - const optimisticUpdate = onyxData?.optimisticData?.at(0); - expect(optimisticUpdate?.key).toBe(`${ONYXKEYS.COLLECTION.POLICY}${MOCK_POLICY_ID}`); - - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- optimisticData values are typed as unknown; narrow to the partial Policy shape this update writes - const value = optimisticUpdate?.value as {connections: {netsuite: {options: {config: Record}}}}; - expect(value.connections.netsuite.options.config[CONST.NETSUITE_CONFIG.TRAVEL_INVOICING_VENDOR]).toBe('vendor-123'); - }); - }); - describe('updateNetSuiteTravelInvoicingPayableAccount', () => { it('writes the UpdateManyPolicyConnectionConfigs command with travelInvoicingPayableAccountID', () => { updateNetSuiteTravelInvoicingPayableAccount(MOCK_POLICY_ID, 'account-123', 'old-account');