diff --git a/assets/images/integrationicons/netsuite-icon-square.svg b/assets/images/integrationicons/netsuite-icon-square.svg
new file mode 100644
index 000000000000..d4f19f4f44c0
--- /dev/null
+++ b/assets/images/integrationicons/netsuite-icon-square.svg
@@ -0,0 +1,57 @@
+
+
+
diff --git a/src/CONST.ts b/src/CONST.ts
index f8ce1a574d49..e71ad55a452c 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -1333,6 +1333,10 @@ const CONST = {
},
},
+ NETSUITE_CONFIG: {
+ SUBSIDIARY: 'subsidiary',
+ },
+
QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE: {
VENDOR_BILL: 'bill',
CHECK: 'check',
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index db40c142a22d..c38ec192127e 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -917,6 +917,10 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/accounting/quickbooks-online/import/taxes',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/quickbooks-online/import/taxes` as const,
},
+ POLICY_ACCOUNTING_NETSUITE_SUBSIDIARY_SELECTOR: {
+ route: 'settings/workspaces/:policyID/accounting/net-suite/subsidiary-selector',
+ getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/net-suite/subsidiary-selector` as const,
+ },
RESTRICTED_ACTION: {
route: 'restricted-action/workspace/:policyID',
getRoute: (policyID: string) => `restricted-action/workspace/${policyID}` as const,
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index d8a2d166099e..6e3d1f3276e9 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -269,6 +269,7 @@ const SCREENS = {
XERO_EXPORT_PREFERRED_EXPORTER_SELECT: 'Workspace_Accounting_Xero_Export_Preferred_Exporter_Select',
XERO_BILL_PAYMENT_ACCOUNT_SELECTOR: 'Policy_Accounting_Xero_Bill_Payment_Account_Selector',
XERO_EXPORT_BANK_ACCOUNT_SELECT: 'Policy_Accounting_Xero_Export_Bank_Account_Select',
+ NETSUITE_SUBSIDIARY_SELECTOR: 'Policy_Accounting_Net_Suite_Subsidiary_Selector',
},
INITIAL: 'Workspace_Initial',
PROFILE: 'Workspace_Profile',
diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts
index c3e50cff3178..3b6d51e786a3 100644
--- a/src/components/Icon/Expensicons.ts
+++ b/src/components/Icon/Expensicons.ts
@@ -98,6 +98,7 @@ import ImageCropCircleMask from '@assets/images/image-crop-circle-mask.svg';
import ImageCropSquareMask from '@assets/images/image-crop-square-mask.svg';
import Inbox from '@assets/images/inbox.svg';
import Info from '@assets/images/info.svg';
+import NetSuiteSquare from '@assets/images/integrationicons/netsuite-icon-square.svg';
import QBOSquare from '@assets/images/integrationicons/qbo-icon-square.svg';
import XeroSquare from '@assets/images/integrationicons/xero-icon-square.svg';
import InvoiceGeneric from '@assets/images/invoice-generic.svg';
@@ -366,4 +367,5 @@ export {
Clear,
CheckCircle,
CheckmarkCircle,
+ NetSuiteSquare,
};
diff --git a/src/languages/en.ts b/src/languages/en.ts
index b8c248704b62..2475bd2dd56e 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2182,6 +2182,12 @@ export default {
noAccountsFound: 'No accounts found',
noAccountsFoundDescription: 'Add the account in Xero and sync the connection again.',
},
+ netsuite: {
+ subsidiary: 'Subsidiary',
+ subsidiarySelectDescription: "Choose the subsidiary in NetSuite that you'd like to import data from.",
+ noSubsidiariesFound: 'No subsidiaries found',
+ noSubsidiariesFoundDescription: 'Add the subsidiary in NetSuite and sync the connection again.',
+ },
type: {
free: 'Free',
control: 'Control',
@@ -2410,6 +2416,7 @@ export default {
subtitle: 'Connect to your accounting system to code transactions with your chart of accounts, auto-match payments, and keep your finances in sync.',
qbo: 'Quickbooks Online',
xero: 'Xero',
+ netsuite: 'NetSuite',
setup: 'Connect',
lastSync: 'Last synced just now',
import: 'Import',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index ecd96d8ca582..72876757c8aa 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2218,6 +2218,12 @@ export default {
noAccountsFound: 'No se ha encontrado ninguna cuenta',
noAccountsFoundDescription: 'Añade la cuenta en Xero y sincroniza de nuevo la conexión.',
},
+ netsuite: {
+ subsidiary: 'Subsidiaria',
+ subsidiarySelectDescription: 'Elige la subsidiaria de NetSuite de la que deseas importar datos.',
+ noSubsidiariesFound: 'No se ha encontrado subsidiarias',
+ noSubsidiariesFoundDescription: 'Añade la subsidiaria en NetSuite y sincroniza de nuevo la conexión.',
+ },
type: {
free: 'Gratis',
control: 'Control',
@@ -2414,6 +2420,7 @@ export default {
subtitle: 'Conecta a tu sistema de contabilidad para codificar transacciones con tu plan de cuentas, auto-cotejar pagos, y mantener tus finanzas sincronizadas.',
qbo: 'Quickbooks Online',
xero: 'Xero',
+ netsuite: 'NetSuite',
setup: 'Configurar',
lastSync: 'Recién sincronizado',
import: 'Importar',
diff --git a/src/libs/API/parameters/UpdateNetSuiteSubsidiaryParams.ts b/src/libs/API/parameters/UpdateNetSuiteSubsidiaryParams.ts
new file mode 100644
index 000000000000..15353589663a
--- /dev/null
+++ b/src/libs/API/parameters/UpdateNetSuiteSubsidiaryParams.ts
@@ -0,0 +1,7 @@
+type UpdateNetSuiteSubsidiaryParams = {
+ policyID: string;
+ subsidiary: string;
+ subsidiaryID: string;
+};
+
+export default UpdateNetSuiteSubsidiaryParams;
diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts
index 269821318889..c43ab514b251 100644
--- a/src/libs/API/parameters/index.ts
+++ b/src/libs/API/parameters/index.ts
@@ -233,3 +233,4 @@ export type {default as UpdateSubscriptionAutoRenewParams} from './UpdateSubscri
export type {default as UpdateSubscriptionAddNewUsersAutomaticallyParams} from './UpdateSubscriptionAddNewUsersAutomaticallyParams';
export type {default as GenerateSpotnanaTokenParams} from './GenerateSpotnanaTokenParams';
export type {default as UpdateSubscriptionSizeParams} from './UpdateSubscriptionSizeParams';
+export type {default as UpdateNetSuiteSubsidiaryParams} from './UpdateNetSuiteSubsidiaryParams';
diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts
index 63473a4b2c68..1ab68bf16ad0 100644
--- a/src/libs/API/types.ts
+++ b/src/libs/API/types.ts
@@ -227,6 +227,7 @@ const WRITE_COMMANDS = {
UPDATE_SUBSCRIPTION_AUTO_RENEW: 'UpdateSubscriptionAutoRenew',
UPDATE_SUBSCRIPTION_ADD_NEW_USERS_AUTOMATICALLY: 'UpdateSubscriptionAddNewUsersAutomatically',
UPDATE_SUBSCRIPTION_SIZE: 'UpdateSubscriptionSize',
+ UPDATE_NETSUITE_SUBSIDIARY: 'UpdateNetSuiteSubsidiary',
} as const;
type WriteCommand = ValueOf;
@@ -455,6 +456,9 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.UPDATE_SUBSCRIPTION_AUTO_RENEW]: Parameters.UpdateSubscriptionAutoRenewParams;
[WRITE_COMMANDS.UPDATE_SUBSCRIPTION_ADD_NEW_USERS_AUTOMATICALLY]: Parameters.UpdateSubscriptionAddNewUsersAutomaticallyParams;
[WRITE_COMMANDS.UPDATE_SUBSCRIPTION_SIZE]: Parameters.UpdateSubscriptionSizeParams;
+
+ // Netsuite parameters
+ [WRITE_COMMANDS.UPDATE_NETSUITE_SUBSIDIARY]: Parameters.UpdateNetSuiteSubsidiaryParams;
};
const READ_COMMANDS = {
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 64f253f7aeea..cb13c347d8aa 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -318,6 +318,7 @@ const SettingsModalStackNavigator = createModalStackNavigator('../../../../pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage').default,
[SCREENS.WORKSPACE.ACCOUNTING.XERO_BILL_PAYMENT_ACCOUNT_SELECTOR]: () =>
require('../../../../pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage').default,
+ [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_SUBSIDIARY_SELECTOR]: () => require('../../../../pages/workspace/accounting/netsuite/NetSuiteSubsidiarySelector').default,
[SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY]: () => require('../../../../pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage').default,
[SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET]: () => require('../../../../pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage').default,
[SCREENS.WORKSPACE.TAX_EDIT]: () => require('../../../../pages/workspace/taxes/WorkspaceEditTaxPage').default,
diff --git a/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts b/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts
index f2897587a043..5defdd9d2e08 100755
--- a/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts
+++ b/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts
@@ -54,6 +54,7 @@ const FULL_SCREEN_TO_RHP_MAPPING: Partial> = {
SCREENS.WORKSPACE.ACCOUNTING.XERO_EXPORT_PREFERRED_EXPORTER_SELECT,
SCREENS.WORKSPACE.ACCOUNTING.XERO_BILL_PAYMENT_ACCOUNT_SELECTOR,
SCREENS.WORKSPACE.ACCOUNTING.XERO_EXPORT_BANK_ACCOUNT_SELECT,
+ SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_SUBSIDIARY_SELECTOR,
],
[SCREENS.WORKSPACE.TAXES]: [
SCREENS.WORKSPACE.TAXES_SETTINGS,
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 3ba386d63670..bba611136450 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -333,6 +333,7 @@ const config: LinkingOptions['config'] = {
[SCREENS.WORKSPACE.ACCOUNTING.XERO_INVOICE_ACCOUNT_SELECTOR]: {path: ROUTES.POLICY_ACCOUNTING_XERO_INVOICE_SELECTOR.route},
[SCREENS.WORKSPACE.ACCOUNTING.XERO_EXPORT_PREFERRED_EXPORTER_SELECT]: {path: ROUTES.POLICY_ACCOUNTING_XERO_PREFERRED_EXPORTER_SELECT.route},
[SCREENS.WORKSPACE.ACCOUNTING.XERO_BILL_PAYMENT_ACCOUNT_SELECTOR]: {path: ROUTES.POLICY_ACCOUNTING_XERO_BILL_PAYMENT_ACCOUNT_SELECTOR.route},
+ [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_SUBSIDIARY_SELECTOR]: {path: ROUTES.POLICY_ACCOUNTING_NETSUITE_SUBSIDIARY_SELECTOR.route},
[SCREENS.WORKSPACE.DESCRIPTION]: {
path: ROUTES.WORKSPACE_PROFILE_DESCRIPTION.route,
},
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index a6840b523967..4f09e3a42d58 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -385,6 +385,9 @@ type SettingsNavigatorParamList = {
[SCREENS.WORKSPACE.ACCOUNTING.XERO_BILL_PAYMENT_ACCOUNT_SELECTOR]: {
policyID: string;
};
+ [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_SUBSIDIARY_SELECTOR]: {
+ policyID: string;
+ };
[SCREENS.GET_ASSISTANCE]: {
backTo: Routes;
};
diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts
index a81dc08ba587..88aae0dcb149 100644
--- a/src/libs/actions/Policy/Policy.ts
+++ b/src/libs/actions/Policy/Policy.ts
@@ -528,6 +528,10 @@ function clearXeroErrorField(policyID: string, fieldName: string) {
Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {connections: {xero: {config: {errorFields: {[fieldName]: null}}}}});
}
+function clearNetSuiteErrorField(policyID: string, fieldName: string) {
+ Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {connections: {netsuite: {options: {config: {errorFields: {[fieldName]: null}}}}}});
+}
+
function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueOf, reimburserEmail: string) {
const policy = getPolicy(policyID);
@@ -3002,6 +3006,7 @@ export {
createDraftWorkspace,
buildPolicyData,
createPolicyExpenseChats,
+ clearNetSuiteErrorField,
};
export type {NewCustomUnit};
diff --git a/src/libs/actions/connections/NetSuiteCommands.ts b/src/libs/actions/connections/NetSuiteCommands.ts
new file mode 100644
index 000000000000..49c42a95542e
--- /dev/null
+++ b/src/libs/actions/connections/NetSuiteCommands.ts
@@ -0,0 +1,99 @@
+import Onyx from 'react-native-onyx';
+import * as API from '@libs/API';
+import {WRITE_COMMANDS} from '@libs/API/types';
+import * as ErrorUtils from '@libs/ErrorUtils';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {OnyxData} from '@src/types/onyx/Request';
+
+type SubsidiaryParam = {
+ subsidiaryID: string;
+ subsidiary: string;
+};
+
+function updateNetSuiteSubsidiary(policyID: string, newSubsidiary: SubsidiaryParam, oldSubsidiary: SubsidiaryParam) {
+ const onyxData: OnyxData = {
+ optimisticData: [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ netsuite: {
+ options: {
+ config: {
+ subsidiary: newSubsidiary.subsidiary,
+ subsidiaryID: newSubsidiary.subsidiaryID,
+ pendingFields: {
+ subsidiary: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+ },
+ errorFields: {
+ subsidiary: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ ],
+ successData: [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ netsuite: {
+ options: {
+ config: {
+ subsidiary: newSubsidiary.subsidiary,
+ subsidiaryID: newSubsidiary.subsidiaryID,
+ errorFields: {
+ subsidiary: null,
+ },
+ pendingFields: {
+ subsidiary: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ ],
+ failureData: [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ netsuite: {
+ options: {
+ config: {
+ subsidiary: oldSubsidiary.subsidiary,
+ subsidiaryID: oldSubsidiary.subsidiaryID,
+ errorFields: {
+ subsidiary: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+ },
+ pendingFields: {
+ subsidiary: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ ],
+ };
+
+ const params = {
+ policyID,
+ ...newSubsidiary,
+ };
+ API.write(WRITE_COMMANDS.UPDATE_NETSUITE_SUBSIDIARY, params, onyxData);
+}
+
+// We'll have more API calls in upcoming PRs
+// eslint-disable-next-line import/prefer-default-export
+export {updateNetSuiteSubsidiary};
diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx
index c8d0eac3ca44..3bb63dadaadc 100644
--- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx
+++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx
@@ -100,6 +100,22 @@ function accountingIntegrationData(
onExportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID)),
onAdvancedPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID)),
};
+ case CONST.POLICY.CONNECTIONS.NAME.NETSUITE:
+ return {
+ title: translate('workspace.accounting.netsuite'),
+ icon: Expensicons.NetSuiteSquare,
+ setupConnectionButton: (
+ // TODO: Will be updated in the Token Input PR
+
+ ),
+ onImportPagePress: () => {},
+ onExportPagePress: () => {},
+ onAdvancedPagePress: () => {},
+ };
default:
return undefined;
}
@@ -131,11 +147,15 @@ function PolicyAccountingPage({policy, connectionSyncProgress}: PolicyAccounting
const formattedDate = useMemo(() => (successfulDate ? new Date(successfulDate) : new Date()), [successfulDate]);
const policyConnectedToXero = connectedIntegration === CONST.POLICY.CONNECTIONS.NAME.XERO;
+ const policyConnectedToNetSuite = connectedIntegration === CONST.POLICY.CONNECTIONS.NAME.NETSUITE;
const tenants = useMemo(() => getXeroTenants(policy), [policy]);
const currentXeroOrganization = findCurrentXeroOrganization(tenants, policy?.connections?.xero?.config?.tenantID);
const currentXeroOrganizationName = useMemo(() => getCurrentXeroOrganizationName(policy), [policy]);
+ const netSuiteSubsidiaryList = policy?.connections?.netsuite?.options?.data?.subsidiaryList ?? [];
+ const netSuiteSelectedSubsidiary = policy?.connections?.netsuite?.options?.config?.subsidiary ?? '';
+
const overflowMenu: ThreeDotsMenuProps['menuItems'] = useMemo(
() => [
{
@@ -234,6 +254,27 @@ function PolicyAccountingPage({policy, connectionSyncProgress}: PolicyAccounting
},
]
: []),
+ ...(policyConnectedToNetSuite && !shouldShowSynchronizationError
+ ? [
+ {
+ description: translate('workspace.netsuite.subsidiary'),
+ iconRight: Expensicons.ArrowRight,
+ title: netSuiteSelectedSubsidiary,
+ wrapperStyle: [styles.sectionMenuItemTopDescription],
+ titleStyle: styles.fontWeightNormal,
+ shouldShowRightIcon: netSuiteSubsidiaryList.length > 1,
+ shouldShowDescriptionOnTop: true,
+ pendingAction: policy?.connections?.netsuite?.options?.config?.pendingFields?.subsidiary,
+ brickRoadIndicator: policy?.connections?.netsuite?.options?.config?.errorFields?.subsidiary ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined,
+ onPress: () => {
+ if (!(netSuiteSubsidiaryList.length > 1)) {
+ return;
+ }
+ Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_SUBSIDIARY_SELECTOR.getRoute(policyID));
+ },
+ },
+ ]
+ : []),
...(isEmptyObject(policy?.connections) || shouldShowSynchronizationError
? []
: [
@@ -275,13 +316,16 @@ function PolicyAccountingPage({policy, connectionSyncProgress}: PolicyAccounting
styles.popoverMenuIcon,
styles.fontWeightNormal,
connectionSyncProgress?.stageInProgress,
+ datetimeToRelative,
theme.spinner,
overflowMenu,
threeDotsMenuPosition,
policyConnectedToXero,
currentXeroOrganizationName,
tenants.length,
- datetimeToRelative,
+ policyConnectedToNetSuite,
+ netSuiteSelectedSubsidiary,
+ netSuiteSubsidiaryList.length,
accountingIntegrations,
currentXeroOrganization?.id,
]);
diff --git a/src/pages/workspace/accounting/netsuite/NetSuiteSubsidiarySelector.tsx b/src/pages/workspace/accounting/netsuite/NetSuiteSubsidiarySelector.tsx
new file mode 100644
index 000000000000..3e5546eceb66
--- /dev/null
+++ b/src/pages/workspace/accounting/netsuite/NetSuiteSubsidiarySelector.tsx
@@ -0,0 +1,105 @@
+import React, {useMemo} from 'react';
+import BlockingView from '@components/BlockingViews/BlockingView';
+import * as Illustrations from '@components/Icon/Illustrations';
+import OfflineWithFeedback from '@components/OfflineWithFeedback';
+import RadioListItem from '@components/SelectionList/RadioListItem';
+import SelectionScreen from '@components/SelectionScreen';
+import type {SelectorType} from '@components/SelectionScreen';
+import Text from '@components/Text';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {updateNetSuiteSubsidiary} from '@libs/actions/connections/NetSuiteCommands';
+import * as ErrorUtils from '@libs/ErrorUtils';
+import Navigation from '@libs/Navigation/Navigation';
+import withPolicyConnections from '@pages/workspace/withPolicyConnections';
+import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections';
+import variables from '@styles/variables';
+import * as Policy from '@userActions/Policy/Policy';
+import CONST from '@src/CONST';
+import type {NetSuiteSubsidiary} from '@src/types/onyx/Policy';
+
+function NetSuiteSubsidiarySelector({policy}: WithPolicyConnectionsProps) {
+ const {translate} = useLocalize();
+ const styles = useThemeStyles();
+ const subsidiaryList = policy?.connections?.netsuite?.options?.data?.subsidiaryList ?? [];
+ const netsuiteConfig = policy?.connections?.netsuite?.options?.config;
+ const currentSubsidiaryName = netsuiteConfig?.subsidiary ?? '';
+ const currentSubsidiaryID = netsuiteConfig?.subsidiaryID ?? '';
+ const policyID = policy?.id ?? '-1';
+
+ const subsidiaryListSections =
+ subsidiaryList.map((subsidiary: NetSuiteSubsidiary) => ({
+ text: subsidiary.name,
+ keyForList: subsidiary.internalID,
+ isSelected: subsidiary.name === currentSubsidiaryName,
+ value: subsidiary.name,
+ })) ?? [];
+
+ const updateSubsidiary = ({keyForList, value}: SelectorType) => {
+ if (!keyForList || keyForList === currentSubsidiaryID) {
+ return;
+ }
+
+ updateNetSuiteSubsidiary(
+ policyID,
+ {
+ subsidiary: value,
+ subsidiaryID: keyForList,
+ },
+ {
+ subsidiary: currentSubsidiaryName,
+ subsidiaryID: currentSubsidiaryID,
+ },
+ );
+ Navigation.goBack();
+ };
+
+ const listEmptyContent = useMemo(
+ () => (
+
+ ),
+ [translate, styles.pb10],
+ );
+
+ const listHeaderComponent = useMemo(
+ () => (
+ Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SUBSIDIARY)}
+ >
+ {translate('workspace.netsuite.subsidiarySelectDescription')}
+
+ ),
+ [netsuiteConfig, styles.ph5, styles.mt2, styles.pb5, styles.mb4, translate, policyID],
+ );
+
+ return (
+ 0 ? [{data: subsidiaryListSections}] : []}
+ listItem={RadioListItem}
+ connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE}
+ onSelectRow={updateSubsidiary}
+ initiallyFocusedOptionKey={netsuiteConfig?.subsidiaryID ?? subsidiaryListSections?.[0]?.keyForList}
+ headerContent={listHeaderComponent}
+ onBackButtonPress={() => Navigation.goBack()}
+ title="workspace.netsuite.subsidiary"
+ listEmptyContent={listEmptyContent}
+ />
+ );
+}
+
+NetSuiteSubsidiarySelector.displayName = 'NetSuiteSubsidiarySelector';
+
+export default withPolicyConnections(NetSuiteSubsidiarySelector);
diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts
index bd8f5e7d33d9..bc10ba51e3c9 100644
--- a/src/types/onyx/Policy.ts
+++ b/src/types/onyx/Policy.ts
@@ -595,7 +595,7 @@ type XeroConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback<{
}>;
/** Data stored about subsidiaries from NetSuite */
-type Subsidiary = {
+type NetSuiteSubsidiary = {
/** ID of the subsidiary */
internalID: string;
@@ -664,7 +664,7 @@ type InvoiceItem = {
/** Data from the NetSuite accounting integration. */
type NetSuiteConnectionData = {
/** Collection of the subsidiaries present in the NetSuite account */
- subsidiaryList: Subsidiary[];
+ subsidiaryList: NetSuiteSubsidiary[];
/** Collection of receivable accounts */
receivableList: NetSuiteAccount[];
@@ -1314,4 +1314,5 @@ export type {
QBOReimbursableExportAccountType,
QBOConnectionConfig,
XeroTrackingCategory,
+ NetSuiteSubsidiary,
};