diff --git a/src/CONST.ts b/src/CONST.ts index 051ff1b71ae5..9c7754dcce4d 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1388,6 +1388,10 @@ const CONST = { 4: 'enterCredentials', }, IMPORT_CUSTOM_FIELDS: ['customSegments', 'customLists'], + CUSTOM_FORM_ID_TYPE: { + REIMBURSABLE: 'reimbursable', + NON_REIMBURSABLE: 'nonReimbursable', + }, SYNC_OPTIONS: { SYNC_REIMBURSED_REPORTS: 'syncReimbursedReports', SYNC_PEOPLE: 'syncPeople', @@ -1456,6 +1460,17 @@ const CONST = { JOURNALS_APPROVED: 'JOURNALS_APPROVED', }, + NETSUITE_ACCOUNT_TYPE: { + ACCOUNTS_PAYABLE: '_accountsPayable', + ACCOUNTS_RECEIVABLE: '_accountsReceivable', + OTHER_CURRENT_LIABILITY: '_otherCurrentLiability', + CREDIT_CARD: '_creditCard', + BANK: '_bank', + OTHER_CURRENT_ASSET: '_otherCurrentAsset', + LONG_TERM_LIABILITY: '_longTermLiability', + EXPENSE: '_expense', + }, + NETSUITE_APPROVAL_ACCOUNT_DEFAULT: 'APPROVAL_ACCOUNT_DEFAULT', /** diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 906f8ef7095e..5d6b5492d15c 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -562,6 +562,8 @@ const ONYXKEYS = { SAGE_INTACCT_CREDENTIALS_FORM_DRAFT: 'sageIntacctCredentialsFormDraft', NETSUITE_TOKEN_INPUT_FORM: 'netsuiteTokenInputForm', NETSUITE_TOKEN_INPUT_FORM_DRAFT: 'netsuiteTokenInputFormDraft', + NETSUITE_CUSTOM_FORM_ID_FORM: 'netsuiteCustomFormIDForm', + NETSUITE_CUSTOM_FORM_ID_FORM_DRAFT: 'netsuiteCustomFormIDFormDraft', }, } as const; @@ -626,6 +628,7 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.ISSUE_NEW_EXPENSIFY_CARD_FORM]: FormTypes.IssueNewExpensifyCardForm; [ONYXKEYS.FORMS.SAGE_INTACCT_CREDENTIALS_FORM]: FormTypes.SageIntactCredentialsForm; [ONYXKEYS.FORMS.NETSUITE_TOKEN_INPUT_FORM]: FormTypes.NetSuiteTokenInputForm; + [ONYXKEYS.FORMS.NETSUITE_CUSTOM_FORM_ID_FORM]: FormTypes.NetSuiteCustomFormIDForm; }; type OnyxFormDraftValuesMapping = { diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 82e49e31a166..149af6b16828 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -1070,6 +1070,35 @@ const ROUTES = { route: 'settings/workspaces/:policyID/connections/netsuite/advanced/', getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/advanced/` as const, }, + POLICY_ACCOUNTING_NETSUITE_REIMBURSEMENT_ACCOUNT_SELECT: { + route: 'settings/workspaces/:policyID/connections/netsuite/advanced/reimbursement-account/select', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/advanced/reimbursement-account/select` as const, + }, + POLICY_ACCOUNTING_NETSUITE_COLLECTION_ACCOUNT_SELECT: { + route: 'settings/workspaces/:policyID/connections/netsuite/advanced/collection-account/select', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/advanced/collection-account/select` as const, + }, + POLICY_ACCOUNTING_NETSUITE_EXPENSE_REPORT_APPROVAL_LEVEL_SELECT: { + route: 'settings/workspaces/:policyID/connections/netsuite/advanced/expense-report-approval-level/select', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/advanced/expense-report-approval-level/select` as const, + }, + POLICY_ACCOUNTING_NETSUITE_VENDOR_BILL_APPROVAL_LEVEL_SELECT: { + route: 'settings/workspaces/:policyID/connections/netsuite/advanced/vendor-bill-approval-level/select', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/advanced/vendor-bill-approval-level/select` as const, + }, + POLICY_ACCOUNTING_NETSUITE_JOURNAL_ENTRY_APPROVAL_LEVEL_SELECT: { + route: 'settings/workspaces/:policyID/connections/netsuite/advanced/journal-entry-approval-level/select', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/advanced/journal-entry-approval-level/select` as const, + }, + POLICY_ACCOUNTING_NETSUITE_APPROVAL_ACCOUNT_SELECT: { + route: 'settings/workspaces/:policyID/connections/netsuite/advanced/approval-account/select', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/connections/netsuite/advanced/approval-account/select` as const, + }, + POLICY_ACCOUNTING_NETSUITE_CUSTOM_FORM_ID: { + route: 'settings/workspaces/:policyID/connections/netsuite/advanced/custom-form-id/:expenseType', + getRoute: (policyID: string, expenseType: ValueOf) => + `settings/workspaces/${policyID}/connections/netsuite/advanced/custom-form-id/${expenseType}` as const, + }, POLICY_ACCOUNTING_SAGE_INTACCT_PREREQUISITES: { route: 'settings/workspaces/:policyID/accounting/sage-intacct/prerequisites', getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/sage-intacct/prerequisites` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 875de4363028..418d0559c380 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -299,6 +299,13 @@ const SCREENS = { NETSUITE_TAX_POSTING_ACCOUNT_SELECT: 'Policy_Accounting_NetSuite_Tax_Posting_Account_Select', NETSUITE_PROVINCIAL_TAX_POSTING_ACCOUNT_SELECT: 'Policy_Accounting_NetSuite_Provincial_Tax_Posting_Account_Select', NETSUITE_ADVANCED: 'Policy_Accounting_NetSuite_Advanced', + NETSUITE_REIMBURSEMENT_ACCOUNT_SELECT: 'Policy_Accounting_NetSuite_Reimbursement_Account_Select', + NETSUITE_COLLECTION_ACCOUNT_SELECT: 'Policy_Accounting_NetSuite_Collection_Account_Select', + NETSUITE_EXPENSE_REPORT_APPROVAL_LEVEL_SELECT: 'Policy_Accounting_NetSuite_Expense_Report_Approval_Level_Select', + NETSUITE_VENDOR_BILL_APPROVAL_LEVEL_SELECT: 'Policy_Accounting_NetSuite_Vendor_Bill_Approval_Level_Select', + NETSUITE_JOURNAL_ENTRY_APPROVAL_LEVEL_SELECT: 'Policy_Accounting_NetSuite_Journal_Entry_Approval_Level_Select', + NETSUITE_APPROVAL_ACCOUNT_SELECT: 'Policy_Accounting_NetSuite_Approval_Account_Select', + NETSUITE_CUSTOM_FORM_ID: 'Policy_Accounting_NetSuite_Custom_Form_ID', SAGE_INTACCT_PREREQUISITES: 'Policy_Accounting_Sage_Intacct_Prerequisites', ENTER_SAGE_INTACCT_CREDENTIALS: 'Policy_Enter_Sage_Intacct_Credentials', EXISTING_SAGE_INTACCT_CONNECTIONS: 'Policy_Existing_Sage_Intacct_Connections', diff --git a/src/components/ConnectionLayout.tsx b/src/components/ConnectionLayout.tsx index dc8638f018d4..4bcfdc61077f 100644 --- a/src/components/ConnectionLayout.tsx +++ b/src/components/ConnectionLayout.tsx @@ -66,6 +66,9 @@ type ConnectionLayoutProps = { /** Handler for back button press */ onBackButtonPress?: () => void; + + /** Whether or not to block user from accessing the page */ + shouldBeBlocked?: boolean; }; type ConnectionLayoutContentProps = Pick; @@ -99,6 +102,7 @@ function ConnectionLayout({ titleAlreadyTranslated, reverseConnectionEmptyCheck = false, onBackButtonPress = () => Navigation.goBack(), + shouldBeBlocked = false, }: ConnectionLayoutProps) { const {translate} = useLocalize(); @@ -123,7 +127,7 @@ function ConnectionLayout({ policyID={policyID} accessVariants={accessVariants} featureName={featureName} - shouldBeBlocked={reverseConnectionEmptyCheck ? !isConnectionEmpty : isConnectionEmpty} + shouldBeBlocked={(reverseConnectionEmptyCheck ? !isConnectionEmpty : isConnectionEmpty) || shouldBeBlocked} > ; +}; + +export default UpdateNetSuiteCustomFormIDParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 848af7e34634..dae5d022baa9 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -243,3 +243,4 @@ export type {default as CreateWorkspaceReportFieldParams} from './CreateWorkspac export type {default as OpenPolicyExpensifyCardsPageParams} from './OpenPolicyExpensifyCardsPageParams'; export type {default as RequestExpensifyCardLimitIncreaseParams} from './RequestExpensifyCardLimitIncreaseParams'; export type {default as UpdateNetSuiteGenericTypeParams} from './UpdateNetSuiteGenericTypeParams'; +export type {default as UpdateNetSuiteCustomFormIDParams} from './UpdateNetSuiteCustomFormIDParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 1bf1efc8af24..3c6b0751398b 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -263,6 +263,14 @@ const WRITE_COMMANDS = { UPDATE_NETSUITE_AUTO_CREATE_ENTITIES: 'UpdateNetSuiteAutoCreateEntities', UPDATE_NETSUITE_ENABLE_NEW_CATEGORIES: 'UpdateNetSuiteEnableNewCategories', UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_ENABLED: 'UpdateNetSuiteCustomFormIDOptionsEnabled', + UPDATE_NETSUITE_REIMBURSEMENT_ACCOUNT_ID: 'UpdateNetSuiteReimbursementAccountID', + UPDATE_NETSUITE_COLLECTION_ACCOUNT: 'UpdateNetSuiteCollectionAccount', + UPDATE_NETSUITE_EXPORT_REPORTS_TO: 'UpdateNetSuiteExportReportsTo', + UPDATE_NETSUITE_VENDOR_BILLS_TO: 'UpdateNetSuiteExportVendorBillsTo', + UPDATE_NETSUITE_JOURNALS_TO: 'UpdateNetSuiteExportJournalsTo', + UPDATE_NETSUITE_APPROVAL_ACCOUNT: 'UpdateNetSuiteApprovalAccount', + UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_REIMBURSABLE: 'UpdateNetSuiteCustomFormIDOptionsReimbursable', + UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_NON_REIMBURSABLE: 'UpdateNetSuiteCustomFormIDOptionsNonReimbursable', REQUEST_EXPENSIFY_CARD_LIMIT_INCREASE: 'RequestExpensifyCardLimitIncrease', CONNECT_POLICY_TO_SAGE_INTACCT: 'ConnectPolicyToSageIntacct', CONNECT_POLICY_TO_NETSUITE: 'ConnectPolicyToNetSuite', @@ -540,6 +548,14 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_NETSUITE_AUTO_CREATE_ENTITIES]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; [WRITE_COMMANDS.UPDATE_NETSUITE_ENABLE_NEW_CATEGORIES]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_ENABLED]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_NETSUITE_REIMBURSEMENT_ACCOUNT_ID]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; + [WRITE_COMMANDS.UPDATE_NETSUITE_COLLECTION_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'bankAccountID', string>; + [WRITE_COMMANDS.UPDATE_NETSUITE_EXPORT_REPORTS_TO]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_VENDOR_BILLS_TO]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_JOURNALS_TO]: Parameters.UpdateNetSuiteGenericTypeParams<'value', ValueOf>; + [WRITE_COMMANDS.UPDATE_NETSUITE_APPROVAL_ACCOUNT]: Parameters.UpdateNetSuiteGenericTypeParams<'value', string>; + [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_REIMBURSABLE]: Parameters.UpdateNetSuiteCustomFormIDParams; + [WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_NON_REIMBURSABLE]: Parameters.UpdateNetSuiteCustomFormIDParams; }; const READ_COMMANDS = { diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index fe631e4cd0b1..1d13d5d21dc1 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -352,6 +352,19 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/accounting/netsuite/export/NetSuiteProvincialTaxPostingAccountSelectPage').default, [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_ADVANCED]: () => require('../../../../pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage').default, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_REIMBURSEMENT_ACCOUNT_SELECT]: () => + require('../../../../pages/workspace/accounting/netsuite/advanced/NetSuiteReimbursementAccountSelectPage').default, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_COLLECTION_ACCOUNT_SELECT]: () => + require('../../../../pages/workspace/accounting/netsuite/advanced/NetSuiteCollectionAccountSelectPage').default, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_EXPENSE_REPORT_APPROVAL_LEVEL_SELECT]: () => + require('../../../../pages/workspace/accounting/netsuite/advanced/NetSuiteExpenseReportApprovalLevelSelectPage').default, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_VENDOR_BILL_APPROVAL_LEVEL_SELECT]: () => + require('../../../../pages/workspace/accounting/netsuite/advanced/NetSuiteVendorBillApprovalLevelSelectPage').default, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_JOURNAL_ENTRY_APPROVAL_LEVEL_SELECT]: () => + require('../../../../pages/workspace/accounting/netsuite/advanced/NetSuiteJournalEntryApprovalLevelSelectPage').default, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_APPROVAL_ACCOUNT_SELECT]: () => + require('../../../../pages/workspace/accounting/netsuite/advanced/NetSuiteApprovalAccountSelectPage').default, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_CUSTOM_FORM_ID]: () => require('../../../../pages/workspace/accounting/netsuite/advanced/NetSuiteCustomFormIDPage').default, [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_PREREQUISITES]: () => require('../../../../pages/workspace/accounting/intacct/IntacctPrerequisitesPage').default, [SCREENS.WORKSPACE.ACCOUNTING.ENTER_SAGE_INTACCT_CREDENTIALS]: () => 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 78732767f4c1..e5ea2d9fa2e4 100755 --- a/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts +++ b/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts @@ -75,6 +75,13 @@ const FULL_SCREEN_TO_RHP_MAPPING: Partial> = { SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_TAX_POSTING_ACCOUNT_SELECT, SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_PROVINCIAL_TAX_POSTING_ACCOUNT_SELECT, SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_ADVANCED, + SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_REIMBURSEMENT_ACCOUNT_SELECT, + SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_COLLECTION_ACCOUNT_SELECT, + SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_EXPENSE_REPORT_APPROVAL_LEVEL_SELECT, + SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_VENDOR_BILL_APPROVAL_LEVEL_SELECT, + SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_JOURNAL_ENTRY_APPROVAL_LEVEL_SELECT, + SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_APPROVAL_ACCOUNT_SELECT, + SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_CUSTOM_FORM_ID, SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_PREREQUISITES, SCREENS.WORKSPACE.ACCOUNTING.ENTER_SAGE_INTACCT_CREDENTIALS, SCREENS.WORKSPACE.ACCOUNTING.EXISTING_SAGE_INTACCT_CONNECTIONS, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index eb2646a048c7..ff83a64d580e 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -401,6 +401,27 @@ const config: LinkingOptions['config'] = { [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_ADVANCED]: { path: ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.route, }, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_REIMBURSEMENT_ACCOUNT_SELECT]: { + path: ROUTES.POLICY_ACCOUNTING_NETSUITE_REIMBURSEMENT_ACCOUNT_SELECT.route, + }, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_COLLECTION_ACCOUNT_SELECT]: { + path: ROUTES.POLICY_ACCOUNTING_NETSUITE_COLLECTION_ACCOUNT_SELECT.route, + }, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_EXPENSE_REPORT_APPROVAL_LEVEL_SELECT]: { + path: ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPENSE_REPORT_APPROVAL_LEVEL_SELECT.route, + }, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_VENDOR_BILL_APPROVAL_LEVEL_SELECT]: { + path: ROUTES.POLICY_ACCOUNTING_NETSUITE_VENDOR_BILL_APPROVAL_LEVEL_SELECT.route, + }, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_JOURNAL_ENTRY_APPROVAL_LEVEL_SELECT]: { + path: ROUTES.POLICY_ACCOUNTING_NETSUITE_JOURNAL_ENTRY_APPROVAL_LEVEL_SELECT.route, + }, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_APPROVAL_ACCOUNT_SELECT]: { + path: ROUTES.POLICY_ACCOUNTING_NETSUITE_APPROVAL_ACCOUNT_SELECT.route, + }, + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_CUSTOM_FORM_ID]: { + path: ROUTES.POLICY_ACCOUNTING_NETSUITE_CUSTOM_FORM_ID.route, + }, [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_PREREQUISITES]: {path: ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_PREREQUISITES.route}, [SCREENS.WORKSPACE.ACCOUNTING.ENTER_SAGE_INTACCT_CREDENTIALS]: {path: ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ENTER_CREDENTIALS.route}, [SCREENS.WORKSPACE.ACCOUNTING.EXISTING_SAGE_INTACCT_CONNECTIONS]: {path: ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_EXISTING_CONNECTIONS.route}, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 183e21fc67b4..746b37bbe26a 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -479,6 +479,28 @@ type SettingsNavigatorParamList = { [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_ADVANCED]: { policyID: string; }; + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_REIMBURSEMENT_ACCOUNT_SELECT]: { + policyID: string; + }; + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_COLLECTION_ACCOUNT_SELECT]: { + policyID: string; + }; + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_EXPENSE_REPORT_APPROVAL_LEVEL_SELECT]: { + policyID: string; + }; + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_VENDOR_BILL_APPROVAL_LEVEL_SELECT]: { + policyID: string; + }; + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_JOURNAL_ENTRY_APPROVAL_LEVEL_SELECT]: { + policyID: string; + }; + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_APPROVAL_ACCOUNT_SELECT]: { + policyID: string; + }; + [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_CUSTOM_FORM_ID]: { + policyID: string; + expenseType: ValueOf; + }; [SCREENS.GET_ASSISTANCE]: { backTo: Routes; }; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 4c071317907b..fc9a04e2507c 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -8,9 +8,10 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {OnyxInputOrEntry, Policy, PolicyCategories, PolicyEmployeeList, PolicyTagList, PolicyTags, TaxRate} from '@src/types/onyx'; -import type {ConnectionLastSync, Connections, CustomUnit, NetSuiteConnection, PolicyFeatureName, Rate, Tenant} from '@src/types/onyx/Policy'; +import type {ConnectionLastSync, Connections, CustomUnit, NetSuiteAccount, NetSuiteConnection, PolicyFeatureName, Rate, Tenant} from '@src/types/onyx/Policy'; import type PolicyEmployee from '@src/types/onyx/PolicyEmployee'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import * as Localize from './Localize'; import Navigation from './Navigation/Navigation'; import * as NetworkStore from './Network/NetworkStore'; import {getAccountIDsByLogins, getLoginsByAccountIDs, getPersonalDetailByEmail} from './PersonalDetailsUtils'; @@ -538,6 +539,47 @@ function canUseProvincialTaxNetSuite(subsidiaryCountry?: string) { return subsidiaryCountry === '_canada'; } +function getNetSuiteReimbursableAccountOptions(policy: Policy | undefined, selectedBankAccountId: string | undefined): SelectorType[] { + const payableAccounts = policy?.connections?.netsuite.options.data.payableList ?? []; + const accountOptions = (payableAccounts ?? []).filter(({type}) => type === CONST.NETSUITE_ACCOUNT_TYPE.BANK || type === CONST.NETSUITE_ACCOUNT_TYPE.CREDIT_CARD); + + return accountOptions.map(({id, name}) => ({ + value: id, + text: name, + keyForList: id, + isSelected: selectedBankAccountId === id, + })); +} + +function getNetSuiteCollectionAccountOptions(policy: Policy | undefined, selectedBankAccountId: string | undefined): SelectorType[] { + const payableAccounts = policy?.connections?.netsuite.options.data.payableList ?? []; + const accountOptions = (payableAccounts ?? []).filter(({type}) => type === CONST.NETSUITE_ACCOUNT_TYPE.BANK); + + return accountOptions.map(({id, name}) => ({ + value: id, + text: name, + keyForList: id, + isSelected: selectedBankAccountId === id, + })); +} + +function getNetSuiteApprovalAccountOptions(policy: Policy | undefined, selectedBankAccountId: string | undefined): SelectorType[] { + const payableAccounts = policy?.connections?.netsuite.options.data.payableList ?? []; + const defaultApprovalAccount: NetSuiteAccount = { + id: CONST.NETSUITE_APPROVAL_ACCOUNT_DEFAULT, + name: Localize.translateLocal('workspace.netsuite.advancedConfig.defaultApprovalAccount'), + type: CONST.NETSUITE_ACCOUNT_TYPE.ACCOUNTS_PAYABLE, + }; + const accountOptions = [defaultApprovalAccount].concat((payableAccounts ?? []).filter(({type}) => type === CONST.NETSUITE_ACCOUNT_TYPE.ACCOUNTS_PAYABLE)); + + return accountOptions.map(({id, name}) => ({ + value: id, + text: name, + keyForList: id, + isSelected: selectedBankAccountId === id, + })); +} + function getCustomersOrJobsLabelNetSuite(policy: Policy | undefined, translate: LocaleContextProps['translate']): string | undefined { const importMapping = policy?.connections?.netsuite?.options?.config?.syncOptions?.mapping; if (!importMapping?.customers && !importMapping?.jobs) { @@ -670,6 +712,9 @@ export { getNetSuiteVendorOptions, canUseTaxNetSuite, canUseProvincialTaxNetSuite, + getNetSuiteReimbursableAccountOptions, + getNetSuiteCollectionAccountOptions, + getNetSuiteApprovalAccountOptions, getNetSuitePayableAccountOptions, getNetSuiteReceivableAccountOptions, getNetSuiteInvoiceItemOptions, diff --git a/src/libs/actions/connections/NetSuiteCommands.ts b/src/libs/actions/connections/NetSuiteCommands.ts index 20f7fcd6e483..66bf482d6ef2 100644 --- a/src/libs/actions/connections/NetSuiteCommands.ts +++ b/src/libs/actions/connections/NetSuiteCommands.ts @@ -7,7 +7,7 @@ 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 {Connections} from '@src/types/onyx/Policy'; +import type {Connections, NetSuiteCustomFormID} from '@src/types/onyx/Policy'; import type {OnyxData} from '@src/types/onyx/Request'; type SubsidiaryParam = { @@ -729,7 +729,107 @@ function updateNetSuiteCustomFormIDOptionsEnabled(policyID: string, value: boole API.write(WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_ENABLED, parameters, onyxData); } +function updateNetSuiteReimbursementAccountID(policyID: string, bankAccountID: string, oldBankAccountID?: string) { + const onyxData = updateNetSuiteOnyxData(policyID, CONST.NETSUITE_CONFIG.REIMBURSEMENT_ACCOUNT_ID, bankAccountID, oldBankAccountID); + + const parameters = { + policyID, + bankAccountID, + }; + API.write(WRITE_COMMANDS.UPDATE_NETSUITE_REIMBURSEMENT_ACCOUNT_ID, parameters, onyxData); +} + +function updateNetSuiteCollectionAccount(policyID: string, bankAccountID: string, oldBankAccountID?: string) { + const onyxData = updateNetSuiteOnyxData(policyID, CONST.NETSUITE_CONFIG.COLLECTION_ACCOUNT, bankAccountID, oldBankAccountID); + + const parameters = { + policyID, + bankAccountID, + }; + API.write(WRITE_COMMANDS.UPDATE_NETSUITE_COLLECTION_ACCOUNT, parameters, onyxData); +} + +function updateNetSuiteExportReportsTo( + policyID: string, + approvalLevel: ValueOf, + oldApprovalLevel: ValueOf, +) { + const onyxData = updateNetSuiteSyncOptionsOnyxData(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_REPORTS_TO, approvalLevel, oldApprovalLevel); + + const parameters = { + policyID, + value: approvalLevel, + }; + API.write(WRITE_COMMANDS.UPDATE_NETSUITE_EXPORT_REPORTS_TO, parameters, onyxData); +} + +function updateNetSuiteExportVendorBillsTo( + policyID: string, + approvalLevel: ValueOf, + oldApprovalLevel: ValueOf, +) { + const onyxData = updateNetSuiteSyncOptionsOnyxData(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_VENDOR_BILLS_TO, approvalLevel, oldApprovalLevel); + + const parameters = { + policyID, + value: approvalLevel, + }; + API.write(WRITE_COMMANDS.UPDATE_NETSUITE_VENDOR_BILLS_TO, parameters, onyxData); +} + +function updateNetSuiteExportJournalsTo( + policyID: string, + approvalLevel: ValueOf, + oldApprovalLevel: ValueOf, +) { + const onyxData = updateNetSuiteSyncOptionsOnyxData(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_JOURNALS_TO, approvalLevel, oldApprovalLevel); + + const parameters = { + policyID, + value: approvalLevel, + }; + API.write(WRITE_COMMANDS.UPDATE_NETSUITE_JOURNALS_TO, parameters, onyxData); +} + +function updateNetSuiteApprovalAccount(policyID: string, value: string, oldValue: string) { + const onyxData = updateNetSuiteOnyxData(policyID, CONST.NETSUITE_CONFIG.APPROVAL_ACCOUNT, value, oldValue); + + const parameters = { + policyID, + value, + }; + API.write(WRITE_COMMANDS.UPDATE_NETSUITE_APPROVAL_ACCOUNT, parameters, onyxData); +} + +function updateNetSuiteCustomFormIDOptions( + policyID: string, + value: string, + isReimbursable: boolean, + exportDestination: ValueOf, + oldCustomFormID?: NetSuiteCustomFormID, +) { + const customFormIDKey = isReimbursable ? CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_TYPE.REIMBURSABLE : CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_TYPE.NON_REIMBURSABLE; + const data = { + [customFormIDKey]: { + [CONST.NETSUITE_MAP_EXPORT_DESTINATION[exportDestination]]: value, + }, + }; + const oldData = { + [customFormIDKey]: oldCustomFormID?.[customFormIDKey] ?? null, + }; + const onyxData = updateNetSuiteOnyxData(policyID, CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_OPTIONS, data, oldData); + + const commandName = isReimbursable ? WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_REIMBURSABLE : WRITE_COMMANDS.UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_NON_REIMBURSABLE; + const parameters = { + policyID, + formType: CONST.NETSUITE_MAP_EXPORT_DESTINATION[exportDestination], + formID: value, + }; + API.write(commandName, parameters, onyxData); +} + export { + connectPolicyToNetSuite, updateNetSuiteSubsidiary, updateNetSuiteSyncTaxConfiguration, updateNetSuiteExporter, @@ -755,5 +855,11 @@ export { updateNetSuiteAutoCreateEntities, updateNetSuiteEnableNewCategories, updateNetSuiteCustomFormIDOptionsEnabled, - connectPolicyToNetSuite, + updateNetSuiteReimbursementAccountID, + updateNetSuiteCollectionAccount, + updateNetSuiteExportReportsTo, + updateNetSuiteExportVendorBillsTo, + updateNetSuiteExportJournalsTo, + updateNetSuiteApprovalAccount, + updateNetSuiteCustomFormIDOptions, }; diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx index 741395555f4a..eb2c6489241f 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx @@ -7,12 +7,14 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections/NetSuiteCommands'; import * as ErrorUtils from '@libs/ErrorUtils'; +import Navigation from '@libs/Navigation/Navigation'; import type {DividerLineItem, MenuItem, ToggleItem} from '@pages/workspace/accounting/netsuite/types'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); @@ -72,26 +74,29 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.reimbursementsAccount'), - onPress: () => {}, // TODO: This will be implemented in a future PR + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_REIMBURSEMENT_ACCOUNT_SELECT.getRoute(policyID)), brickRoadIndicator: config?.errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: selectedReimbursementAccount ? selectedReimbursementAccount.name : undefined, pendingAction: config?.pendingFields?.reimbursementAccountID, errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.REIMBURSEMENT_ACCOUNT_ID), onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.REIMBURSEMENT_ACCOUNT_ID), + shouldHide: config?.reimbursableExpensesExportDestination === CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY, }, { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.collectionsAccount'), - onPress: () => {}, // TODO: This will be implemented in a future PR + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_COLLECTION_ACCOUNT_SELECT.getRoute(policyID)), brickRoadIndicator: config?.errorFields?.collectionAccount ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: selectedCollectionAccount ? selectedCollectionAccount.name : undefined, pendingAction: config?.pendingFields?.collectionAccount, errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.COLLECTION_ACCOUNT), onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.COLLECTION_ACCOUNT), + shouldHide: config?.reimbursableExpensesExportDestination === CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY, }, { type: 'divider', key: 'divider2', + shouldHide: config?.reimbursableExpensesExportDestination === CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY, }, { type: 'toggle', @@ -137,7 +142,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.exportReportsTo.label'), - onPress: () => {}, // TODO: This will be implemented in a future PR + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPENSE_REPORT_APPROVAL_LEVEL_SELECT.getRoute(policyID)), brickRoadIndicator: config?.errorFields?.exportReportsTo ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: config?.syncOptions.exportReportsTo ? translate(`workspace.netsuite.advancedConfig.exportReportsTo.values.${config.syncOptions.exportReportsTo}`) : undefined, pendingAction: config?.syncOptions.pendingFields?.exportReportsTo, @@ -148,7 +153,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.exportVendorBillsTo.label'), - onPress: () => {}, // TODO: This will be implemented in a future PR + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_VENDOR_BILL_APPROVAL_LEVEL_SELECT.getRoute(policyID)), brickRoadIndicator: config?.errorFields?.exportVendorBillsTo ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: config?.syncOptions.exportVendorBillsTo ? translate(`workspace.netsuite.advancedConfig.exportVendorBillsTo.values.${config.syncOptions.exportVendorBillsTo}`) : undefined, pendingAction: config?.syncOptions.pendingFields?.exportVendorBillsTo, @@ -161,7 +166,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.exportJournalsTo.label'), - onPress: () => {}, // TODO: This will be implemented in a future PR + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_JOURNAL_ENTRY_APPROVAL_LEVEL_SELECT.getRoute(policyID)), brickRoadIndicator: config?.errorFields?.exportJournalsTo ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: config?.syncOptions.exportJournalsTo ? translate(`workspace.netsuite.advancedConfig.exportJournalsTo.values.${config.syncOptions.exportJournalsTo}`) : undefined, pendingAction: config?.syncOptions.pendingFields?.exportJournalsTo, @@ -174,7 +179,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.approvalAccount'), - onPress: () => {}, // TODO: This will be implemented in a future PR + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_APPROVAL_ACCOUNT_SELECT.getRoute(policyID)), brickRoadIndicator: config?.errorFields?.approvalAccount ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: selectedApprovalAccount ? selectedApprovalAccount.name : undefined, pendingAction: config?.pendingFields?.approvalAccount, @@ -200,7 +205,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.customFormIDReimbursable'), - onPress: () => {}, // TODO: This will be implemented in a future PR + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_CUSTOM_FORM_ID.getRoute(policyID, CONST.NETSUITE_EXPENSE_TYPE.REIMBURSABLE)), brickRoadIndicator: config?.errorFields?.customFormIDOptions ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: config?.customFormIDOptions?.reimbursable[CONST.NETSUITE_MAP_EXPORT_DESTINATION[config.reimbursableExpensesExportDestination]], pendingAction: config?.pendingFields?.customFormIDOptions, @@ -211,9 +216,9 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.customFormIDNonReimbursable'), - onPress: () => {}, // TODO: This will be implemented in a future PR + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_CUSTOM_FORM_ID.getRoute(policyID, CONST.NETSUITE_EXPENSE_TYPE.NON_REIMBURSABLE)), brickRoadIndicator: config?.errorFields?.customFormIDOptions ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - title: config?.customFormIDOptions?.reimbursable[CONST.NETSUITE_MAP_EXPORT_DESTINATION[config.nonreimbursableExpensesExportDestination]], + title: config?.customFormIDOptions?.nonReimbursable[CONST.NETSUITE_MAP_EXPORT_DESTINATION[config.nonreimbursableExpensesExportDestination]], pendingAction: config?.pendingFields?.customFormIDOptions, errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_OPTIONS), onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_OPTIONS), diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteApprovalAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteApprovalAccountSelectPage.tsx new file mode 100644 index 000000000000..ed823d698d2f --- /dev/null +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteApprovalAccountSelectPage.tsx @@ -0,0 +1,90 @@ +import React, {useCallback, useMemo} from 'react'; +import {View} from 'react-native'; +import BlockingView from '@components/BlockingViews/BlockingView'; +import * as Illustrations from '@components/Icon/Illustrations'; +import RadioListItem from '@components/SelectionList/RadioListItem'; +import type {SelectorType} from '@components/SelectionScreen'; +import SelectionScreen from '@components/SelectionScreen'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as Connections from '@libs/actions/connections/NetSuiteCommands'; +import Navigation from '@libs/Navigation/Navigation'; +import {getNetSuiteApprovalAccountOptions} from '@libs/PolicyUtils'; +import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; +import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import variables from '@styles/variables'; +import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; + +function NetSuiteApprovalAccountSelectPage({policy}: WithPolicyConnectionsProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + const policyID = policy?.id ?? '-1'; + + const config = policy?.connections?.netsuite.options.config; + const netsuiteApprovalAccountOptions = useMemo( + () => getNetSuiteApprovalAccountOptions(policy ?? undefined, config?.approvalAccount), + // The default option will be language dependent, so we need to recompute the options when the language changes + // eslint-disable-next-line react-hooks/exhaustive-deps + [config?.approvalAccount, policy, translate], + ); + + const initiallyFocusedOptionKey = useMemo(() => netsuiteApprovalAccountOptions?.find((mode) => mode.isSelected)?.keyForList, [netsuiteApprovalAccountOptions]); + + const updateCollectionAccount = useCallback( + ({value}: SelectorType) => { + if (config?.approvalAccount !== value) { + Connections.updateNetSuiteApprovalAccount(policyID, value, config?.approvalAccount ?? CONST.NETSUITE_APPROVAL_ACCOUNT_DEFAULT); + } + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID)); + }, + [policyID, config?.approvalAccount], + ); + + const listEmptyContent = useMemo( + () => ( + + ), + [translate, styles.pb10], + ); + + const headerContent = useMemo( + () => ( + + {translate('workspace.netsuite.advancedConfig.approvalAccountDescription')} + + ), + [translate, styles.pb5, styles.ph5], + ); + + return ( + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID))} + title="workspace.netsuite.advancedConfig.approvalAccount" + listEmptyContent={listEmptyContent} + connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} + /> + ); +} + +NetSuiteApprovalAccountSelectPage.displayName = 'NetSuiteApprovalAccountSelectPage'; + +export default withPolicyConnections(NetSuiteApprovalAccountSelectPage); diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCollectionAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCollectionAccountSelectPage.tsx new file mode 100644 index 000000000000..c1851a84f384 --- /dev/null +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCollectionAccountSelectPage.tsx @@ -0,0 +1,89 @@ +import React, {useCallback, useMemo} from 'react'; +import {View} from 'react-native'; +import BlockingView from '@components/BlockingViews/BlockingView'; +import * as Illustrations from '@components/Icon/Illustrations'; +import RadioListItem from '@components/SelectionList/RadioListItem'; +import type {SelectorType} from '@components/SelectionScreen'; +import SelectionScreen from '@components/SelectionScreen'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as Connections from '@libs/actions/connections/NetSuiteCommands'; +import Navigation from '@libs/Navigation/Navigation'; +import {getNetSuiteCollectionAccountOptions} from '@libs/PolicyUtils'; +import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; +import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import variables from '@styles/variables'; +import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; + +function NetSuiteCollectionAccountSelectPage({policy}: WithPolicyConnectionsProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + const policyID = policy?.id ?? '-1'; + + const config = policy?.connections?.netsuite.options.config; + const netsuiteCollectionAccountOptions = useMemo( + () => getNetSuiteCollectionAccountOptions(policy ?? undefined, config?.collectionAccount), + [config?.collectionAccount, policy], + ); + + const initiallyFocusedOptionKey = useMemo(() => netsuiteCollectionAccountOptions?.find((mode) => mode.isSelected)?.keyForList, [netsuiteCollectionAccountOptions]); + + const updateCollectionAccount = useCallback( + ({value}: SelectorType) => { + if (config?.collectionAccount !== value) { + Connections.updateNetSuiteCollectionAccount(policyID, value, config?.collectionAccount); + } + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID)); + }, + [policyID, config?.collectionAccount], + ); + + const listEmptyContent = useMemo( + () => ( + + ), + [translate, styles.pb10], + ); + + const headerContent = useMemo( + () => ( + + {translate('workspace.netsuite.advancedConfig.collectionsAccountDescription')} + + ), + [translate, styles.pb5, styles.ph5], + ); + + return ( + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID))} + title="workspace.netsuite.advancedConfig.collectionsAccount" + listEmptyContent={listEmptyContent} + connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} + shouldBeBlocked={config?.reimbursableExpensesExportDestination === CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY} + /> + ); +} + +NetSuiteCollectionAccountSelectPage.displayName = 'NetSuiteCollectionAccountSelectPage'; + +export default withPolicyConnections(NetSuiteCollectionAccountSelectPage); diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCustomFormIDPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCustomFormIDPage.tsx new file mode 100644 index 000000000000..696d9ec3e0c9 --- /dev/null +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCustomFormIDPage.tsx @@ -0,0 +1,101 @@ +import {useRoute} from '@react-navigation/native'; +import React, {useCallback} from 'react'; +import {View} from 'react-native'; +import ConnectionLayout from '@components/ConnectionLayout'; +import FormProvider from '@components/Form/FormProvider'; +import InputWrapper from '@components/Form/InputWrapper'; +import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; +import TextInput from '@components/TextInput'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as Connections from '@libs/actions/connections/NetSuiteCommands'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import Navigation from '@libs/Navigation/Navigation'; +import * as ValidationUtils from '@libs/ValidationUtils'; +import type {ExpenseRouteParams} from '@pages/workspace/accounting/netsuite/types'; +import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; +import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; + +function NetSuiteCustomFormIDPage({policy}: WithPolicyConnectionsProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + const policyID = policy?.id ?? '-1'; + const route = useRoute(); + const params = route.params as ExpenseRouteParams; + const isReimbursable = params.expenseType === CONST.NETSUITE_EXPENSE_TYPE.REIMBURSABLE; + + const config = policy?.connections?.netsuite?.options.config; + + const exportDestination = + (isReimbursable ? config?.reimbursableExpensesExportDestination : config?.nonreimbursableExpensesExportDestination) ?? CONST.NETSUITE_EXPORT_DESTINATION.EXPENSE_REPORT; + const customFormIDKey = isReimbursable ? CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_TYPE.REIMBURSABLE : CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_TYPE.NON_REIMBURSABLE; + + const validate = useCallback( + (values: FormOnyxValues): FormInputErrors => { + const errors: FormInputErrors = {}; + + if (values[params.expenseType] && !ValidationUtils.isNumeric(values[params.expenseType])) { + ErrorUtils.addErrorMessage(errors, params.expenseType, translate('workspace.netsuite.advancedConfig.error.customFormID')); + } + + return errors; + }, + [params.expenseType, translate], + ); + + const updateCustomFormID = useCallback( + (formValues: FormOnyxValues) => { + if (config?.customFormIDOptions?.[customFormIDKey]?.[CONST.NETSUITE_MAP_EXPORT_DESTINATION[exportDestination]] !== formValues[params.expenseType]) { + Connections.updateNetSuiteCustomFormIDOptions(policyID, formValues[params.expenseType], isReimbursable, exportDestination, config?.customFormIDOptions); + } + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID)); + }, + [config?.customFormIDOptions, customFormIDKey, exportDestination, isReimbursable, params.expenseType, policyID], + ); + + return ( + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID))} + headerTitle={`workspace.netsuite.advancedConfig.${isReimbursable ? 'customFormIDReimbursable' : 'customFormIDNonReimbursable'}`} + accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]} + policyID={policyID} + featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} + contentContainerStyle={[styles.flex1]} + titleStyle={styles.ph5} + connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} + shouldIncludeSafeAreaPaddingBottom + shouldBeBlocked={!config?.customFormIDOptions?.enabled} + > + + + + + + + ); +} + +NetSuiteCustomFormIDPage.displayName = 'NetSuiteCustomFormIDPage'; + +export default withPolicyConnections(NetSuiteCustomFormIDPage); diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteExpenseReportApprovalLevelSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteExpenseReportApprovalLevelSelectPage.tsx new file mode 100644 index 000000000000..ed70da6f1608 --- /dev/null +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteExpenseReportApprovalLevelSelectPage.tsx @@ -0,0 +1,74 @@ +import React, {useCallback, useMemo} from 'react'; +import {View} from 'react-native'; +import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/RadioListItem'; +import type {ListItem} from '@components/SelectionList/types'; +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 * as Connections from '@libs/actions/connections/NetSuiteCommands'; +import Navigation from '@navigation/Navigation'; +import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; +import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; + +type MenuListItem = ListItem & { + value: ValueOf; +}; + +function NetSuiteExpenseReportApprovalLevelSelectPage({policy}: WithPolicyConnectionsProps) { + const {translate} = useLocalize(); + const policyID = policy?.id ?? '-1'; + const styles = useThemeStyles(); + const config = policy?.connections?.netsuite.options.config; + const data: MenuListItem[] = Object.values(CONST.NETSUITE_REPORTS_APPROVAL_LEVEL).map((approvalType) => ({ + value: approvalType, + text: translate(`workspace.netsuite.advancedConfig.exportReportsTo.values.${approvalType}`), + keyForList: approvalType, + isSelected: config?.syncOptions.exportReportsTo === approvalType, + })); + + const headerContent = useMemo( + () => ( + + {translate('workspace.netsuite.advancedConfig.exportReportsTo.description')} + + ), + [translate, styles.pb5, styles.ph5], + ); + + const selectExpenseReportApprovalLevel = useCallback( + (row: MenuListItem) => { + if (row.value !== config?.syncOptions.exportReportsTo) { + Connections.updateNetSuiteExportReportsTo(policyID, row.value, config?.syncOptions.exportReportsTo ?? CONST.NETSUITE_REPORTS_APPROVAL_LEVEL.REPORTS_APPROVED_NONE); + } + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID)); + }, + [config?.syncOptions.exportReportsTo, policyID], + ); + + return ( + selectExpenseReportApprovalLevel(selection as MenuListItem)} + initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} + policyID={policyID} + accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN]} + featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} + onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID))} + connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} + shouldBeBlocked={config?.reimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.EXPENSE_REPORT} + /> + ); +} + +NetSuiteExpenseReportApprovalLevelSelectPage.displayName = 'NetSuiteExpenseReportApprovalLevelSelectPage'; + +export default withPolicyConnections(NetSuiteExpenseReportApprovalLevelSelectPage); diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteJournalEntryApprovalLevelSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteJournalEntryApprovalLevelSelectPage.tsx new file mode 100644 index 000000000000..ee1d1108ffd6 --- /dev/null +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteJournalEntryApprovalLevelSelectPage.tsx @@ -0,0 +1,77 @@ +import React, {useCallback, useMemo} from 'react'; +import {View} from 'react-native'; +import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/RadioListItem'; +import type {ListItem} from '@components/SelectionList/types'; +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 * as Connections from '@libs/actions/connections/NetSuiteCommands'; +import Navigation from '@navigation/Navigation'; +import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; +import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; + +type MenuListItem = ListItem & { + value: ValueOf; +}; + +function NetSuiteJournalEntryApprovalLevelSelectPage({policy}: WithPolicyConnectionsProps) { + const {translate} = useLocalize(); + const policyID = policy?.id ?? '-1'; + const styles = useThemeStyles(); + const config = policy?.connections?.netsuite.options.config; + const data: MenuListItem[] = Object.values(CONST.NETSUITE_JOURNALS_APPROVAL_LEVEL).map((approvalType) => ({ + value: approvalType, + text: translate(`workspace.netsuite.advancedConfig.exportJournalsTo.values.${approvalType}`), + keyForList: approvalType, + isSelected: config?.syncOptions.exportJournalsTo === approvalType, + })); + + const headerContent = useMemo( + () => ( + + {translate('workspace.netsuite.advancedConfig.exportJournalsTo.description')} + + ), + [translate, styles.pb5, styles.ph5], + ); + + const selectJournalApprovalLevel = useCallback( + (row: MenuListItem) => { + if (row.value !== config?.syncOptions.exportJournalsTo) { + Connections.updateNetSuiteExportJournalsTo(policyID, row.value, config?.syncOptions.exportJournalsTo ?? CONST.NETSUITE_JOURNALS_APPROVAL_LEVEL.JOURNALS_APPROVED_NONE); + } + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID)); + }, + [config?.syncOptions.exportJournalsTo, policyID], + ); + + return ( + selectJournalApprovalLevel(selection as MenuListItem)} + initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} + policyID={policyID} + accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN]} + featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} + onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID))} + connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} + shouldBeBlocked={ + config?.reimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY && + config?.nonreimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY + } + /> + ); +} + +NetSuiteJournalEntryApprovalLevelSelectPage.displayName = 'NetSuiteJournalEntryApprovalLevelSelectPage'; + +export default withPolicyConnections(NetSuiteJournalEntryApprovalLevelSelectPage); diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteReimbursementAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteReimbursementAccountSelectPage.tsx new file mode 100644 index 000000000000..4a9898fb187e --- /dev/null +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteReimbursementAccountSelectPage.tsx @@ -0,0 +1,89 @@ +import React, {useCallback, useMemo} from 'react'; +import {View} from 'react-native'; +import BlockingView from '@components/BlockingViews/BlockingView'; +import * as Illustrations from '@components/Icon/Illustrations'; +import RadioListItem from '@components/SelectionList/RadioListItem'; +import type {SelectorType} from '@components/SelectionScreen'; +import SelectionScreen from '@components/SelectionScreen'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as Connections from '@libs/actions/connections/NetSuiteCommands'; +import Navigation from '@libs/Navigation/Navigation'; +import {getNetSuiteReimbursableAccountOptions} from '@libs/PolicyUtils'; +import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; +import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import variables from '@styles/variables'; +import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; + +function NetSuiteReimbursementAccountSelectPage({policy}: WithPolicyConnectionsProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + const policyID = policy?.id ?? '-1'; + + const config = policy?.connections?.netsuite.options.config; + const netsuiteReimbursableAccountOptions = useMemo( + () => getNetSuiteReimbursableAccountOptions(policy ?? undefined, config?.reimbursementAccountID), + [config?.reimbursementAccountID, policy], + ); + + const initiallyFocusedOptionKey = useMemo(() => netsuiteReimbursableAccountOptions?.find((mode) => mode.isSelected)?.keyForList, [netsuiteReimbursableAccountOptions]); + + const updateReimbursementAccount = useCallback( + ({value}: SelectorType) => { + if (config?.reimbursementAccountID !== value) { + Connections.updateNetSuiteReimbursementAccountID(policyID, value, config?.reimbursementAccountID); + } + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID)); + }, + [policyID, config?.reimbursementAccountID], + ); + + const listEmptyContent = useMemo( + () => ( + + ), + [translate, styles.pb10], + ); + + const headerContent = useMemo( + () => ( + + {translate('workspace.netsuite.advancedConfig.reimbursementsAccountDescription')} + + ), + [translate, styles.pb5, styles.ph5], + ); + + return ( + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID))} + title="workspace.netsuite.advancedConfig.reimbursementsAccount" + listEmptyContent={listEmptyContent} + connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} + shouldBeBlocked={config?.reimbursableExpensesExportDestination === CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY} + /> + ); +} + +NetSuiteReimbursementAccountSelectPage.displayName = 'NetSuiteReimbursementAccountSelectPage'; + +export default withPolicyConnections(NetSuiteReimbursementAccountSelectPage); diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteVendorBillApprovalLevelSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteVendorBillApprovalLevelSelectPage.tsx new file mode 100644 index 000000000000..ecbaacd46bad --- /dev/null +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteVendorBillApprovalLevelSelectPage.tsx @@ -0,0 +1,81 @@ +import React, {useCallback, useMemo} from 'react'; +import {View} from 'react-native'; +import type {ValueOf} from 'type-fest'; +import RadioListItem from '@components/SelectionList/RadioListItem'; +import type {ListItem} from '@components/SelectionList/types'; +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 * as Connections from '@libs/actions/connections/NetSuiteCommands'; +import Navigation from '@navigation/Navigation'; +import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; +import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; + +type MenuListItem = ListItem & { + value: ValueOf; +}; + +function NetSuiteVendorBillApprovalLevelSelectPage({policy}: WithPolicyConnectionsProps) { + const {translate} = useLocalize(); + const policyID = policy?.id ?? '-1'; + const styles = useThemeStyles(); + const config = policy?.connections?.netsuite.options.config; + const data: MenuListItem[] = Object.values(CONST.NETSUITE_VENDOR_BILLS_APPROVAL_LEVEL).map((approvalType) => ({ + value: approvalType, + text: translate(`workspace.netsuite.advancedConfig.exportVendorBillsTo.values.${approvalType}`), + keyForList: approvalType, + isSelected: config?.syncOptions.exportVendorBillsTo === approvalType, + })); + + const headerContent = useMemo( + () => ( + + {translate('workspace.netsuite.advancedConfig.exportVendorBillsTo.description')} + + ), + [translate, styles.pb5, styles.ph5], + ); + + const selectVendorBillApprovalLevel = useCallback( + (row: MenuListItem) => { + if (row.value !== config?.syncOptions.exportVendorBillsTo) { + Connections.updateNetSuiteExportVendorBillsTo( + policyID, + row.value, + config?.syncOptions.exportVendorBillsTo ?? CONST.NETSUITE_VENDOR_BILLS_APPROVAL_LEVEL.VENDOR_BILLS_APPROVED_NONE, + ); + } + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID)); + }, + [config?.syncOptions.exportVendorBillsTo, policyID], + ); + + return ( + selectVendorBillApprovalLevel(selection as MenuListItem)} + initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} + policyID={policyID} + accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN]} + featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} + onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID))} + connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} + shouldBeBlocked={ + config?.reimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.VENDOR_BILL && + config?.nonreimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.VENDOR_BILL + } + /> + ); +} + +NetSuiteVendorBillApprovalLevelSelectPage.displayName = 'NetSuiteVendorBillApprovalLevelSelectPage'; + +export default withPolicyConnections(NetSuiteVendorBillApprovalLevelSelectPage); diff --git a/src/types/form/NetSuiteCustomFormIDForm.ts b/src/types/form/NetSuiteCustomFormIDForm.ts new file mode 100644 index 000000000000..eb1ea8625075 --- /dev/null +++ b/src/types/form/NetSuiteCustomFormIDForm.ts @@ -0,0 +1,16 @@ +import type {ValueOf} from 'type-fest'; +import type CONST from '@src/CONST'; +import type Form from './Form'; + +type InputID = ValueOf; + +type NetSuiteCustomFormIDForm = Form< + InputID, + { + [CONST.NETSUITE_EXPENSE_TYPE.REIMBURSABLE]: string; + [CONST.NETSUITE_EXPENSE_TYPE.NON_REIMBURSABLE]: string; + } +>; + +// eslint-disable-next-line import/prefer-default-export +export type {NetSuiteCustomFormIDForm}; diff --git a/src/types/form/index.ts b/src/types/form/index.ts index b3503099b4b3..44c0cb81cb91 100644 --- a/src/types/form/index.ts +++ b/src/types/form/index.ts @@ -57,4 +57,5 @@ export type {SubscriptionSizeForm} from './SubscriptionSizeForm'; export type {WorkspaceReportFieldsForm} from './WorkspaceReportFieldsForm'; export type {SageIntactCredentialsForm} from './SageIntactCredentialsForm'; export type {NetSuiteTokenInputForm} from './NetSuiteTokenInputForm'; +export type {NetSuiteCustomFormIDForm} from './NetSuiteCustomFormIDForm'; export type {default as Form} from './Form'; diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 098869d7bf8e..86560166cb4e 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -718,6 +718,18 @@ type NetSuiteCustomFormIDOptions = { journalEntry?: string; }; +/** The custom form ID object */ +type NetSuiteCustomFormID = { + /** The custom form selections for reimbursable transactions */ + reimbursable: NetSuiteCustomFormIDOptions; + + /** The custom form selections for non-reimbursable transactions */ + nonReimbursable: NetSuiteCustomFormIDOptions; + + /** Whether we'll use the custom form selections upon export to NetSuite */ + enabled: boolean; +}; + /** User configuration for the NetSuite accounting integration. */ type NetSuiteConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback<{ /** Invoice Item Preference */ @@ -880,16 +892,7 @@ type NetSuiteConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback<{ payableAcct: string; /** Configurations for customer to set custom forms for which reimbursable and non-reimbursable transactions will export to in NetSuite */ - customFormIDOptions?: { - /** The custom form selections for reimbursable transactions */ - reimbursable: NetSuiteCustomFormIDOptions; - - /** The custom form selections for non-reimbursable transactions */ - nonReimbursable: NetSuiteCustomFormIDOptions; - - /** Whether we'll use the custom form selections upon export to NetSuite */ - enabled: boolean; - }; + customFormIDOptions?: NetSuiteCustomFormID; /** The account to use for Invoices export to NetSuite */ collectionAccount?: string; @@ -1355,4 +1358,7 @@ export type { NetSuiteConnection, ConnectionLastSync, NetSuiteSubsidiary, + NetSuiteAccount, + NetSuiteCustomFormIDOptions, + NetSuiteCustomFormID, };