diff --git a/src/CONST.ts b/src/CONST.ts index be14ba241404..91644a2f9471 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1519,6 +1519,7 @@ const CONST = { }, CUSTOM_SEGMENT_FIELDS: ['segmentName', 'internalID', 'scriptID', 'mapping'], CUSTOM_LIST_FIELDS: ['listName', 'internalID', 'transactionFieldID', 'mapping'], + CUSTOM_FORM_ID_ENABLED: 'enabled', CUSTOM_FORM_ID_TYPE: { REIMBURSABLE: 'reimbursable', NON_REIMBURSABLE: 'nonReimbursable', diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 87998f780641..1516d0dc202f 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -78,7 +78,7 @@ import type { Transaction, } from '@src/types/onyx'; import type {Errors} from '@src/types/onyx/OnyxCommon'; -import type {Attributes, CompanyAddress, CustomUnit, Rate, TaxRate, Unit} from '@src/types/onyx/Policy'; +import type {Attributes, CompanyAddress, CustomUnit, NetSuiteCustomList, NetSuiteCustomSegment, Rate, TaxRate, Unit} from '@src/types/onyx/Policy'; import type {OnyxData} from '@src/types/onyx/Request'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import {buildOptimisticPolicyCategories} from './Category'; @@ -602,6 +602,28 @@ function clearNetSuiteErrorField(policyID: string, fieldName: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {connections: {netsuite: {options: {config: {errorFields: {[fieldName]: null}}}}}}); } +function clearNetSuitePendingField(policyID: string, fieldName: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {connections: {netsuite: {options: {config: {pendingFields: {[fieldName]: null}}}}}}); +} + +function removeNetSuiteCustomFieldByIndex(allRecords: NetSuiteCustomSegment[] | NetSuiteCustomList[], policyID: string, importCustomField: string, valueIndex: number) { + // We allow multiple custom list records with the same internalID. Hence it is safe to remove by index. + const filteredRecords = allRecords.filter((_, index) => index !== Number(valueIndex)); + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { + connections: { + netsuite: { + options: { + config: { + syncOptions: { + [importCustomField]: filteredRecords, + }, + }, + }, + }, + }, + }); +} + function clearSageIntacctErrorField(policyID: string, fieldName: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {connections: {intacct: {config: {errorFields: {[fieldName]: null}}}}}); } @@ -3798,7 +3820,9 @@ export { clearXeroErrorField, clearSageIntacctErrorField, clearNetSuiteErrorField, + clearNetSuitePendingField, clearNetSuiteAutoSyncErrorField, + removeNetSuiteCustomFieldByIndex, clearWorkspaceReimbursementErrors, setWorkspaceCurrencyDefault, setForeignCurrencyDefault, diff --git a/src/libs/actions/connections/NetSuiteCommands.ts b/src/libs/actions/connections/NetSuiteCommands.ts index 8be8d2cb077a..ad3693ef3654 100644 --- a/src/libs/actions/connections/NetSuiteCommands.ts +++ b/src/libs/actions/connections/NetSuiteCommands.ts @@ -1,3 +1,4 @@ +import isObject from 'lodash/isObject'; import type {OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; @@ -7,6 +8,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 * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type {Connections, NetSuiteCustomFormID, NetSuiteCustomList, NetSuiteCustomSegment, NetSuiteMappingValues} from '@src/types/onyx/Policy'; import type {OnyxData} from '@src/types/onyx/Request'; @@ -34,6 +36,36 @@ function connectPolicyToNetSuite(policyID: string, credentials: Omit( + settingName: TSettingName, + settingValue: Partial, + pendingValue: OnyxCommon.PendingAction, +) { + if (!isObject(settingValue)) { + return {[settingName]: pendingValue}; + } + + return Object.keys(settingValue).reduce>((acc, setting) => { + acc[setting] = pendingValue; + return acc; + }, {}); +} + +function createErrorFields( + settingName: TSettingName, + settingValue: Partial, + errorValue: OnyxCommon.Errors | null, +) { + if (!isObject(settingValue)) { + return {[settingName]: errorValue}; + } + + return Object.keys(settingValue).reduce((acc, setting) => { + acc[setting] = errorValue; + return acc; + }, {}); +} + function updateNetSuiteOnyxData( policyID: string, settingName: TSettingName, @@ -50,12 +82,8 @@ function updateNetSuiteOnyxData, oldSettingValue: Partial, + modifiedFieldID?: string, + pendingAction?: OnyxCommon.PendingAction, ) { + let syncOptionsOptimisticValue; + if (pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) { + syncOptionsOptimisticValue = { + [settingName]: settingValue ?? null, + }; + } const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -129,14 +157,12 @@ function updateNetSuiteSyncOptionsOnyxData, - oldMappingValue?: ValueOf, + oldMappingValue?: ValueOf | null, ) { const onyxData: OnyxData = { optimisticData: [ @@ -302,14 +331,14 @@ function updateNetSuiteImportMapping({horizontal: 0, vertical: 0}); @@ -232,7 +233,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { } const shouldShowSynchronizationError = !!synchronizationError; const shouldHideConfigurationOptions = isConnectionUnverified(policy, connectedIntegration); - const integrationData = getAccountingIntegrationData(connectedIntegration, policyID, translate, policy); + const integrationData = getAccountingIntegrationData(connectedIntegration, policyID, translate, policy, undefined, canUseNetSuiteUSATax); const iconProps = integrationData?.icon ? {icon: integrationData.icon, iconType: CONST.ICON_TYPE_AVATAR} : {}; const configurationOptions = [ @@ -342,6 +343,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { isOffline, startIntegrationFlow, popoverAnchorRefs, + canUseNetSuiteUSATax, ]); const otherIntegrationsItems = useMemo(() => { @@ -429,6 +431,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { ( - Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SUBSIDIARY)} - > - {translate('workspace.netsuite.subsidiarySelectDescription')} - + + {translate('workspace.netsuite.subsidiarySelectDescription')} + ), - [netsuiteConfig, styles.ph5, styles.mt2, styles.pb5, styles.mb4, translate, policyID], + [styles.pb2, styles.ph5, styles.textNormal, translate], ); return ( @@ -96,6 +93,10 @@ function NetSuiteSubsidiarySelector({policy}: WithPolicyConnectionsProps) { onBackButtonPress={() => Navigation.goBack()} title="workspace.netsuite.subsidiary" listEmptyContent={listEmptyContent} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.SUBSIDIARY], netsuiteConfig?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(netsuiteConfig ?? {}, CONST.NETSUITE_CONFIG.SUBSIDIARY)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SUBSIDIARY)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx index 1b86832c374a..50b2b966c73b 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx @@ -8,8 +8,22 @@ 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 {findSelectedBankAccountWithDefaultSelect, getFilteredApprovalAccountOptions, getFilteredCollectionAccountOptions, getFilteredReimbursableAccountOptions} from '@libs/PolicyUtils'; +import { + areSettingsInErrorFields, + findSelectedBankAccountWithDefaultSelect, + getFilteredApprovalAccountOptions, + getFilteredCollectionAccountOptions, + getFilteredReimbursableAccountOptions, + settingsPendingAction, +} from '@libs/PolicyUtils'; import type {DividerLineItem, MenuItem, ToggleItem} from '@pages/workspace/accounting/netsuite/types'; +import { + shouldHideCustomFormIDOptions, + shouldHideExportJournalsTo, + shouldHideExportVendorBillsTo, + shouldHideReimbursedReportsSection, + shouldHideReportsExportTo, +} from '@pages/workspace/accounting/netsuite/utils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -17,6 +31,8 @@ import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; +type MenuItemWithSubscribedSettings = Pick & {subscribedSettings?: string[]}; + function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -45,7 +61,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { return findSelectedBankAccountWithDefaultSelect(getFilteredApprovalAccountOptions(payableList), config?.approvalAccount); }, [config?.approvalAccount, payableList, translate]); - const menuItems: Array = [ + const menuItems: Array = [ { type: 'toggle', title: translate('workspace.accounting.autoSync'), @@ -55,7 +71,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { shouldPlaceSubtitleBelowSwitch: true, onCloseError: () => Policy.clearNetSuiteAutoSyncErrorField(policyID), onToggle: (isEnabled) => Connections.updateNetSuiteAutoSync(policyID, isEnabled), - pendingAction: autoSyncConfig?.pendingFields?.autoSync, + pendingAction: settingsPendingAction([CONST.NETSUITE_CONFIG.AUTO_SYNC], autoSyncConfig?.pendingFields), errors: ErrorUtils.getLatestErrorField(autoSyncConfig, CONST.NETSUITE_CONFIG.AUTO_SYNC), }, { @@ -71,36 +87,30 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { shouldPlaceSubtitleBelowSwitch: true, onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.SYNC_REIMBURSED_REPORTS), onToggle: (isEnabled) => Connections.updateNetSuiteSyncReimbursedReports(policyID, isEnabled), - pendingAction: config?.syncOptions.pendingFields?.syncReimbursedReports, + pendingAction: settingsPendingAction([CONST.NETSUITE_CONFIG.SYNC_OPTIONS.SYNC_REIMBURSED_REPORTS], config?.pendingFields), errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.SYNC_REIMBURSED_REPORTS), - shouldHide: config?.reimbursableExpensesExportDestination === CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY, + shouldHide: shouldHideReimbursedReportsSection(config), }, { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.reimbursementsAccount'), 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, + subscribedSettings: [CONST.NETSUITE_CONFIG.REIMBURSEMENT_ACCOUNT_ID], + shouldHide: shouldHideReimbursedReportsSection(config), }, { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.collectionsAccount'), 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, + subscribedSettings: [CONST.NETSUITE_CONFIG.COLLECTION_ACCOUNT], + shouldHide: shouldHideReimbursedReportsSection(config), }, { type: 'divider', key: 'divider2', - shouldHide: config?.reimbursableExpensesExportDestination === CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY, + shouldHide: shouldHideReimbursedReportsSection(config), }, { type: 'toggle', @@ -112,7 +122,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { shouldParseSubtitle: true, onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.SYNC_PEOPLE), onToggle: (isEnabled) => Connections.updateNetSuiteSyncPeople(policyID, isEnabled), - pendingAction: config?.syncOptions.pendingFields?.syncPeople, + pendingAction: settingsPendingAction([CONST.NETSUITE_CONFIG.SYNC_OPTIONS.SYNC_PEOPLE], config?.pendingFields), errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.SYNC_PEOPLE), }, { @@ -122,7 +132,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { switchAccessibilityLabel: translate('workspace.netsuite.advancedConfig.autoCreateEntities'), onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.AUTO_CREATE_ENTITIES), onToggle: (isEnabled) => Connections.updateNetSuiteAutoCreateEntities(policyID, isEnabled), - pendingAction: config?.pendingFields?.autoCreateEntities, + pendingAction: settingsPendingAction([CONST.NETSUITE_CONFIG.AUTO_CREATE_ENTITIES], config?.pendingFields), errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.AUTO_CREATE_ENTITIES), }, { @@ -136,7 +146,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { switchAccessibilityLabel: translate('workspace.netsuite.advancedConfig.enableCategories'), onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.ENABLE_NEW_CATEGORIES), onToggle: (isEnabled) => Connections.updateNetSuiteEnableNewCategories(policyID, isEnabled), - pendingAction: config?.syncOptions.pendingFields?.enableNewCategories, + pendingAction: settingsPendingAction([CONST.NETSUITE_CONFIG.SYNC_OPTIONS.ENABLE_NEW_CATEGORIES], config?.pendingFields), errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.ENABLE_NEW_CATEGORIES), }, { @@ -147,48 +157,32 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.exportReportsTo.label'), 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, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_REPORTS_TO), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_REPORTS_TO), - shouldHide: config?.reimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.EXPENSE_REPORT, + subscribedSettings: [CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_REPORTS_TO], + shouldHide: shouldHideReportsExportTo(config), }, { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.exportVendorBillsTo.label'), 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, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_VENDOR_BILLS_TO), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_VENDOR_BILLS_TO), - shouldHide: - config?.reimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.VENDOR_BILL && - config?.nonreimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.VENDOR_BILL, + subscribedSettings: [CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_VENDOR_BILLS_TO], + shouldHide: shouldHideExportVendorBillsTo(config), }, { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.exportJournalsTo.label'), 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, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_JOURNALS_TO), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_JOURNALS_TO), - shouldHide: - config?.reimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY && - config?.nonreimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY, + subscribedSettings: [CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_JOURNALS_TO], + shouldHide: shouldHideExportJournalsTo(config), }, { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.approvalAccount'), 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, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.APPROVAL_ACCOUNT), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.APPROVAL_ACCOUNT), + subscribedSettings: [CONST.NETSUITE_CONFIG.APPROVAL_ACCOUNT], }, { type: 'divider', @@ -201,32 +195,26 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { isActive: !!config?.customFormIDOptions?.enabled, switchAccessibilityLabel: translate('workspace.netsuite.advancedConfig.customFormIDDescription'), shouldPlaceSubtitleBelowSwitch: true, - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_OPTIONS), + onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_ENABLED), onToggle: (isEnabled) => Connections.updateNetSuiteCustomFormIDOptionsEnabled(policyID, isEnabled), - pendingAction: config?.pendingFields?.customFormIDOptions, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_OPTIONS), + pendingAction: settingsPendingAction([CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_ENABLED], config?.pendingFields), + errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_ENABLED), }, { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.customFormIDReimbursable'), 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, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_OPTIONS), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_OPTIONS), - shouldHide: !config?.customFormIDOptions?.enabled, + subscribedSettings: [CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_TYPE.REIMBURSABLE], + shouldHide: shouldHideCustomFormIDOptions(config), }, { type: 'menuitem', description: translate('workspace.netsuite.advancedConfig.customFormIDNonReimbursable'), 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?.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), - shouldHide: !config?.customFormIDOptions?.enabled, + subscribedSettings: [CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_TYPE.NON_REIMBURSABLE], + shouldHide: shouldHideCustomFormIDOptions(config), }, ]; @@ -268,19 +256,14 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { return ( ); @@ -293,3 +276,5 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { NetSuiteAdvancedPage.displayName = 'NetSuiteAdvancedPage'; export default withPolicyConnections(NetSuiteAdvancedPage); + +export {shouldHideReimbursedReportsSection}; diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteApprovalAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteApprovalAccountSelectPage.tsx index 98cf607e30ab..29df47e852c6 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteApprovalAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteApprovalAccountSelectPage.tsx @@ -9,11 +9,13 @@ import Text from '@components/Text'; 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 {getNetSuiteApprovalAccountOptions} from '@libs/PolicyUtils'; +import {getNetSuiteApprovalAccountOptions, settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -81,6 +83,10 @@ function NetSuiteApprovalAccountSelectPage({policy}: WithPolicyConnectionsProps) title="workspace.netsuite.advancedConfig.approvalAccount" listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.APPROVAL_ACCOUNT], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.APPROVAL_ACCOUNT)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.APPROVAL_ACCOUNT)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCollectionAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCollectionAccountSelectPage.tsx index a8ad5cff5895..6062ee3ca175 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCollectionAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCollectionAccountSelectPage.tsx @@ -9,11 +9,13 @@ import Text from '@components/Text'; 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 {getNetSuiteCollectionAccountOptions} from '@libs/PolicyUtils'; +import {getNetSuiteCollectionAccountOptions, settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -80,6 +82,10 @@ function NetSuiteCollectionAccountSelectPage({policy}: WithPolicyConnectionsProp listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} shouldBeBlocked={config?.reimbursableExpensesExportDestination === CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.COLLECTION_ACCOUNT], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.COLLECTION_ACCOUNT)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.COLLECTION_ACCOUNT)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCustomFormIDPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCustomFormIDPage.tsx index 9a4635dd17bb..71e1be953ace 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCustomFormIDPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteCustomFormIDPage.tsx @@ -5,6 +5,7 @@ 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 OfflineWithFeedback from '@components/OfflineWithFeedback'; import TextInput from '@components/TextInput'; import useAutoFocusInput from '@hooks/useAutoFocusInput'; import useLocalize from '@hooks/useLocalize'; @@ -12,10 +13,12 @@ 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 {settingsPendingAction} from '@libs/PolicyUtils'; 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 * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -84,17 +87,24 @@ function NetSuiteCustomFormIDPage({policy}: WithPolicyConnectionsProps) { shouldValidateOnBlur shouldValidateOnChange > - + Policy.clearNetSuiteErrorField(policyID, customFormIDKey)} + > + + diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteExpenseReportApprovalLevelSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteExpenseReportApprovalLevelSelectPage.tsx index ed70da6f1608..b475966f6f88 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteExpenseReportApprovalLevelSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteExpenseReportApprovalLevelSelectPage.tsx @@ -9,9 +9,12 @@ import Text from '@components/Text'; 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 {settingsPendingAction} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -65,6 +68,10 @@ function NetSuiteExpenseReportApprovalLevelSelectPage({policy}: WithPolicyConnec 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} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_REPORTS_TO], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_REPORTS_TO)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_REPORTS_TO)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteJournalEntryApprovalLevelSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteJournalEntryApprovalLevelSelectPage.tsx index ee1d1108ffd6..dae2db4d191a 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteJournalEntryApprovalLevelSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteJournalEntryApprovalLevelSelectPage.tsx @@ -9,9 +9,12 @@ import Text from '@components/Text'; 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 {settingsPendingAction} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -68,6 +71,10 @@ function NetSuiteJournalEntryApprovalLevelSelectPage({policy}: WithPolicyConnect config?.reimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY && config?.nonreimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY } + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_JOURNALS_TO], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_JOURNALS_TO)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_JOURNALS_TO)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteReimbursementAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteReimbursementAccountSelectPage.tsx index 4ad1a1b62633..01fbfc8d437c 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteReimbursementAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteReimbursementAccountSelectPage.tsx @@ -9,11 +9,13 @@ import Text from '@components/Text'; 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 {getNetSuiteReimbursableAccountOptions} from '@libs/PolicyUtils'; +import {getNetSuiteReimbursableAccountOptions, settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -80,6 +82,10 @@ function NetSuiteReimbursementAccountSelectPage({policy}: WithPolicyConnectionsP listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} shouldBeBlocked={config?.reimbursableExpensesExportDestination === CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.REIMBURSEMENT_ACCOUNT_ID], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.REIMBURSEMENT_ACCOUNT_ID)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.REIMBURSEMENT_ACCOUNT_ID)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteVendorBillApprovalLevelSelectPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteVendorBillApprovalLevelSelectPage.tsx index ecbaacd46bad..5a1cfe0797eb 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteVendorBillApprovalLevelSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteVendorBillApprovalLevelSelectPage.tsx @@ -9,9 +9,12 @@ import Text from '@components/Text'; 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 {settingsPendingAction} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -72,6 +75,10 @@ function NetSuiteVendorBillApprovalLevelSelectPage({policy}: WithPolicyConnectio config?.reimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.VENDOR_BILL && config?.nonreimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.VENDOR_BILL } + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_VENDOR_BILLS_TO], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_VENDOR_BILLS_TO)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.EXPORT_VENDOR_BILLS_TO)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteDateSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteDateSelectPage.tsx index 42d014ed4299..ce65db521257 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteDateSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteDateSelectPage.tsx @@ -9,9 +9,12 @@ import Text from '@components/Text'; 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 {settingsPendingAction} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -66,6 +69,10 @@ function NetSuiteDateSelectPage({policy}: WithPolicyConnectionsProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT.getRoute(policyID))} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.EXPORT_DATE], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.EXPORT_DATE)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.EXPORT_DATE)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportConfigurationPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportConfigurationPage.tsx index 648ec7d77a64..88e7934bf17f 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportConfigurationPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportConfigurationPage.tsx @@ -10,13 +10,23 @@ import * as Connections from '@libs/actions/connections/NetSuiteCommands'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import { - canUseProvincialTaxNetSuite, - canUseTaxNetSuite, + areSettingsInErrorFields, findSelectedBankAccountWithDefaultSelect, findSelectedInvoiceItemWithDefaultSelect, findSelectedTaxAccountWithDefaultSelect, + settingsPendingAction, } from '@libs/PolicyUtils'; import type {DividerLineItem, MenuItem, ToggleItem} from '@pages/workspace/accounting/netsuite/types'; +import { + shouldHideExportForeignCurrencyAmount, + shouldHideJournalPostingPreference, + shouldHideNonReimbursableJournalPostingAccount, + shouldHideProvincialTaxPostingAccountSelect, + shouldHideReimbursableDefaultVendor, + shouldHideReimbursableJournalPostingAccount, + shouldHideTaxPostingAccountSelect, + shouldShowInvoiceItemMenuItem, +} from '@pages/workspace/accounting/netsuite/utils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -24,6 +34,8 @@ import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; +type MenuItemWithSubscribedSettings = Pick & {subscribedSettings?: string[]}; + function NetSuiteExportConfigurationPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -60,18 +72,15 @@ function NetSuiteExportConfigurationPage({policy}: WithPolicyConnectionsProps) { [taxAccountsList, config?.provincialTaxPostingAccount], ); - const menuItems: Array = [ + const menuItems: Array = [ { type: 'menuitem', + title: config?.exporter ?? policyOwner, description: translate('workspace.accounting.preferredExporter'), onPress: () => { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_PREFERRED_EXPORTER_SELECT.getRoute(policyID)); }, - brickRoadIndicator: config?.errorFields?.exporter ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - title: config?.exporter ?? policyOwner, - pendingAction: config?.pendingFields?.exporter, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.EXPORTER), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.EXPORTER), + subscribedSettings: [CONST.NETSUITE_CONFIG.EXPORTER], }, { type: 'divider', @@ -79,37 +88,40 @@ function NetSuiteExportConfigurationPage({policy}: WithPolicyConnectionsProps) { }, { type: 'menuitem', - description: translate('workspace.accounting.exportDate'), - onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_DATE_SELECT.getRoute(policyID)), - brickRoadIndicator: config?.errorFields?.exportDate ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: config?.exportDate ? translate(`workspace.netsuite.exportDate.values.${config.exportDate}.label`) : translate(`workspace.netsuite.exportDate.values.${CONST.NETSUITE_EXPORT_DATE.LAST_EXPENSE}.label`), - pendingAction: config?.pendingFields?.exportDate, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.EXPORT_DATE), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.EXPORT_DATE), + description: translate('workspace.accounting.exportDate'), + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_DATE_SELECT.getRoute(policyID)), + subscribedSettings: [CONST.NETSUITE_CONFIG.EXPORT_DATE], }, { type: 'menuitem', + title: config?.reimbursableExpensesExportDestination ? translate(`workspace.netsuite.exportDestination.values.${config.reimbursableExpensesExportDestination}.label`) : undefined, description: translate('workspace.accounting.exportOutOfPocket'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES.getRoute(policyID, CONST.NETSUITE_EXPENSE_TYPE.REIMBURSABLE)), - brickRoadIndicator: config?.errorFields?.reimbursableExpensesExportDestination ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - title: config?.reimbursableExpensesExportDestination ? translate(`workspace.netsuite.exportDestination.values.${config.reimbursableExpensesExportDestination}.label`) : undefined, - pendingAction: config?.pendingFields?.reimbursableExpensesExportDestination, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.REIMBURSABLE_EXPENSES_EXPORT_DESTINATION), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.REIMBURSABLE_EXPENSES_EXPORT_DESTINATION), + subscribedSettings: [ + CONST.NETSUITE_CONFIG.REIMBURSABLE_EXPENSES_EXPORT_DESTINATION, + ...(!shouldHideReimbursableDefaultVendor(true, config) ? [CONST.NETSUITE_CONFIG.DEFAULT_VENDOR] : []), + ...(!shouldHideNonReimbursableJournalPostingAccount(true, config) ? [CONST.NETSUITE_CONFIG.PAYABLE_ACCT] : []), + ...(!shouldHideReimbursableJournalPostingAccount(true, config) ? [CONST.NETSUITE_CONFIG.REIMBURSABLE_PAYABLE_ACCOUNT] : []), + ...(!shouldHideJournalPostingPreference(true, config) ? [CONST.NETSUITE_CONFIG.JOURNAL_POSTING_PREFERENCE] : []), + ], }, { type: 'menuitem', - description: translate('workspace.accounting.exportCompanyCard'), - onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES.getRoute(policyID, CONST.NETSUITE_EXPENSE_TYPE.NON_REIMBURSABLE)), - brickRoadIndicator: config?.errorFields?.nonreimbursableExpensesExportDestination ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: config?.nonreimbursableExpensesExportDestination ? translate(`workspace.netsuite.exportDestination.values.${config.nonreimbursableExpensesExportDestination}.label`) : undefined, - pendingAction: config?.pendingFields?.nonreimbursableExpensesExportDestination, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION), + description: translate('workspace.accounting.exportCompanyCard'), + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES.getRoute(policyID, CONST.NETSUITE_EXPENSE_TYPE.NON_REIMBURSABLE)), + subscribedSettings: [ + CONST.NETSUITE_CONFIG.NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION, + ...(!shouldHideReimbursableDefaultVendor(false, config) ? [CONST.NETSUITE_CONFIG.DEFAULT_VENDOR] : []), + ...(!shouldHideNonReimbursableJournalPostingAccount(false, config) ? [CONST.NETSUITE_CONFIG.PAYABLE_ACCT] : []), + ...(!shouldHideReimbursableJournalPostingAccount(false, config) ? [CONST.NETSUITE_CONFIG.REIMBURSABLE_PAYABLE_ACCOUNT] : []), + ...(!shouldHideJournalPostingPreference(false, config) ? [CONST.NETSUITE_CONFIG.JOURNAL_POSTING_PREFERENCE] : []), + ], }, { type: 'divider', @@ -117,23 +129,17 @@ function NetSuiteExportConfigurationPage({policy}: WithPolicyConnectionsProps) { }, { type: 'menuitem', + title: selectedReceivable ? selectedReceivable.name : undefined, description: translate('workspace.netsuite.exportInvoices'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_RECEIVABLE_ACCOUNT_SELECT.getRoute(policyID)), - brickRoadIndicator: config?.errorFields?.receivableAccount ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - title: selectedReceivable ? selectedReceivable.name : undefined, - pendingAction: config?.pendingFields?.receivableAccount, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.RECEIVABLE_ACCOUNT), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.RECEIVABLE_ACCOUNT), + subscribedSettings: [CONST.NETSUITE_CONFIG.RECEIVABLE_ACCOUNT], }, { type: 'menuitem', + title: invoiceItemValue, description: translate('workspace.netsuite.invoiceItem.label'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_INVOICE_ITEM_PREFERENCE_SELECT.getRoute(policyID)), - brickRoadIndicator: config?.errorFields?.invoiceItemPreference ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - title: invoiceItemValue, - pendingAction: config?.pendingFields?.invoiceItemPreference, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.INVOICE_ITEM_PREFERENCE), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.INVOICE_ITEM_PREFERENCE), + subscribedSettings: [CONST.NETSUITE_CONFIG.INVOICE_ITEM_PREFERENCE, ...(shouldShowInvoiceItemMenuItem(config) ? [CONST.NETSUITE_CONFIG.INVOICE_ITEM] : [])], }, { type: 'divider', @@ -141,25 +147,19 @@ function NetSuiteExportConfigurationPage({policy}: WithPolicyConnectionsProps) { }, { type: 'menuitem', + title: selectedProvTaxPostingAccount ? selectedProvTaxPostingAccount.name : undefined, description: translate('workspace.netsuite.journalEntriesProvTaxPostingAccount'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_PROVINCIAL_TAX_POSTING_ACCOUNT_SELECT.getRoute(policyID)), - brickRoadIndicator: config?.errorFields?.provincialTaxPostingAccount ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - title: selectedProvTaxPostingAccount ? selectedProvTaxPostingAccount.name : undefined, - pendingAction: config?.pendingFields?.provincialTaxPostingAccount, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.PROVINCIAL_TAX_POSTING_ACCOUNT), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.PROVINCIAL_TAX_POSTING_ACCOUNT), - shouldHide: !!config?.suiteTaxEnabled || !config?.syncOptions.syncTax || !canUseProvincialTaxNetSuite(selectedSubsidiary?.country), + subscribedSettings: [CONST.NETSUITE_CONFIG.PROVINCIAL_TAX_POSTING_ACCOUNT], + shouldHide: shouldHideProvincialTaxPostingAccountSelect(selectedSubsidiary, config), }, { type: 'menuitem', + title: selectedTaxPostingAccount ? selectedTaxPostingAccount.name : undefined, description: translate('workspace.netsuite.journalEntriesTaxPostingAccount'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_TAX_POSTING_ACCOUNT_SELECT.getRoute(policyID)), - brickRoadIndicator: config?.errorFields?.taxPostingAccount ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - title: selectedTaxPostingAccount ? selectedTaxPostingAccount.name : undefined, - pendingAction: config?.pendingFields?.taxPostingAccount, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.TAX_POSTING_ACCOUNT), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.TAX_POSTING_ACCOUNT), - shouldHide: !!config?.suiteTaxEnabled || !config?.syncOptions.syncTax || !canUseTaxNetSuite(canUseNetSuiteUSATax, selectedSubsidiary?.country), + subscribedSettings: [CONST.NETSUITE_CONFIG.TAX_POSTING_ACCOUNT], + shouldHide: shouldHideTaxPostingAccountSelect(canUseNetSuiteUSATax, selectedSubsidiary, config), }, { type: 'toggle', @@ -168,11 +168,9 @@ function NetSuiteExportConfigurationPage({policy}: WithPolicyConnectionsProps) { switchAccessibilityLabel: translate('workspace.netsuite.foreignCurrencyAmount'), onToggle: () => Connections.updateNetSuiteAllowForeignCurrency(policyID, !config?.allowForeignCurrency, config?.allowForeignCurrency), onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.ALLOW_FOREIGN_CURRENCY), - pendingAction: config?.pendingFields?.allowForeignCurrency, + pendingAction: settingsPendingAction([CONST.NETSUITE_CONFIG.ALLOW_FOREIGN_CURRENCY], config?.pendingFields), errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.ALLOW_FOREIGN_CURRENCY), - shouldHide: - config?.reimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.EXPENSE_REPORT && - config?.nonreimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.EXPENSE_REPORT, + shouldHide: shouldHideExportForeignCurrencyAmount(config), }, { type: 'toggle', @@ -181,7 +179,7 @@ function NetSuiteExportConfigurationPage({policy}: WithPolicyConnectionsProps) { switchAccessibilityLabel: translate('workspace.netsuite.exportToNextOpenPeriod'), onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.EXPORT_TO_NEXT_OPEN_PERIOD), onToggle: () => Connections.updateNetSuiteExportToNextOpenPeriod(policyID, !config?.exportToNextOpenPeriod, config?.exportToNextOpenPeriod ?? false), - pendingAction: config?.pendingFields?.exportToNextOpenPeriod, + pendingAction: settingsPendingAction([CONST.NETSUITE_CONFIG.EXPORT_TO_NEXT_OPEN_PERIOD], config?.pendingFields), errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.EXPORT_TO_NEXT_OPEN_PERIOD), }, ]; @@ -225,19 +223,14 @@ function NetSuiteExportConfigurationPage({policy}: WithPolicyConnectionsProps) { return ( ); diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesDestinationSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesDestinationSelectPage.tsx index 535951a51f87..403f6b6a192d 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesDestinationSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesDestinationSelectPage.tsx @@ -6,11 +6,16 @@ import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; 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 {settingsPendingAction} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {ExpenseRouteParams} from '@pages/workspace/accounting/netsuite/types'; +import {exportExpensesDestinationSettingName} from '@pages/workspace/accounting/netsuite/utils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -20,6 +25,7 @@ type MenuListItem = ListItem & { function NetSuiteExportExpensesDestinationSelectPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); + const styles = useThemeStyles(); const policyID = policy?.id ?? '-1'; const config = policy?.connections?.netsuite.options.config; @@ -27,7 +33,8 @@ function NetSuiteExportExpensesDestinationSelectPage({policy}: WithPolicyConnect const params = route.params as ExpenseRouteParams; const isReimbursable = params.expenseType === CONST.NETSUITE_EXPENSE_TYPE.REIMBURSABLE; - const currentDestination = isReimbursable ? config?.reimbursableExpensesExportDestination : config?.nonreimbursableExpensesExportDestination; + const currentSettingName = exportExpensesDestinationSettingName(isReimbursable); + const currentDestination = config?.[currentSettingName]; const data: MenuListItem[] = Object.values(CONST.NETSUITE_EXPORT_DESTINATION).map((dateType) => ({ value: dateType, @@ -63,6 +70,10 @@ function NetSuiteExportExpensesDestinationSelectPage({policy}: WithPolicyConnect featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES.getRoute(policyID, params.expenseType))} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} + pendingAction={settingsPendingAction([currentSettingName], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, currentSettingName)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, currentSettingName)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesJournalPostingPreferenceSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesJournalPostingPreferenceSelectPage.tsx index 544cd0cc20cd..f381bdfec3be 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesJournalPostingPreferenceSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesJournalPostingPreferenceSelectPage.tsx @@ -6,11 +6,15 @@ import type {ListItem} from '@components/SelectionList/types'; import SelectionScreen from '@components/SelectionScreen'; import type {SelectorType} from '@components/SelectionScreen'; 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 {settingsPendingAction} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {ExpenseRouteParams} from '@pages/workspace/accounting/netsuite/types'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -20,6 +24,7 @@ type MenuListItem = ListItem & { function NetSuiteExportExpensesJournalPostingPreferenceSelectPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); + const styles = useThemeStyles(); const policyID = policy?.id ?? '-1'; const config = policy?.connections?.netsuite.options.config; @@ -66,6 +71,10 @@ function NetSuiteExportExpensesJournalPostingPreferenceSelectPage({policy}: With ? config?.reimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY : config?.nonreimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY } + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.JOURNAL_POSTING_PREFERENCE], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.JOURNAL_POSTING_PREFERENCE)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.JOURNAL_POSTING_PREFERENCE)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesPage.tsx index c3ffe000e1e5..ad92c53acad1 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesPage.tsx @@ -5,17 +5,25 @@ import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; -import {findSelectedBankAccountWithDefaultSelect, findSelectedVendorWithDefaultSelect} from '@libs/PolicyUtils'; +import {areSettingsInErrorFields, findSelectedBankAccountWithDefaultSelect, findSelectedVendorWithDefaultSelect, settingsPendingAction} from '@libs/PolicyUtils'; import type {ExpenseRouteParams, MenuItem} from '@pages/workspace/accounting/netsuite/types'; +import { + exportExpensesDestinationSettingName, + shouldHideJournalPostingPreference, + shouldHideNonReimbursableJournalPostingAccount, + shouldHideReimbursableDefaultVendor, + shouldHideReimbursableJournalPostingAccount, +} from '@pages/workspace/accounting/netsuite/utils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; -type MenuItemWithoutType = Omit; +type MenuItemWithSubscribedSettings = Pick & { + subscribedSettings?: string[]; +}; function NetSuiteExportExpensesPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); @@ -27,11 +35,9 @@ function NetSuiteExportExpensesPage({policy}: WithPolicyConnectionsProps) { const config = policy?.connections?.netsuite?.options.config; - const exportDestination = isReimbursable ? config?.reimbursableExpensesExportDestination : config?.nonreimbursableExpensesExportDestination; - const exportDestinationError = isReimbursable ? config?.errorFields?.reimbursableExpensesExportDestination : config?.errorFields?.nonreimbursableExpensesExportDestination; - const exportDestinationPending = isReimbursable ? config?.pendingFields?.reimbursableExpensesExportDestination : config?.pendingFields?.nonreimbursableExpensesExportDestination; + const exportDestinationSettingName = exportExpensesDestinationSettingName(isReimbursable); + const exportDestination = config?.[exportDestinationSettingName]; const helperTextType = isReimbursable ? 'reimbursableDescription' : 'nonReimbursableDescription'; - const configType = isReimbursable ? CONST.NETSUITE_CONFIG.REIMBURSABLE_EXPENSES_EXPORT_DESTINATION : CONST.NETSUITE_CONFIG.NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION; const {vendors, payableList} = policy?.connections?.netsuite?.options?.data ?? {}; @@ -44,59 +50,49 @@ function NetSuiteExportExpensesPage({policy}: WithPolicyConnectionsProps) { [payableList, config?.reimbursablePayableAccount], ); - const menuItems: MenuItemWithoutType[] = [ + const menuItems: MenuItemWithSubscribedSettings[] = [ { description: translate('workspace.accounting.exportAs'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES_DESTINATION_SELECT.getRoute(policyID, params.expenseType)), - brickRoadIndicator: exportDestinationError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: exportDestination ? translate(`workspace.netsuite.exportDestination.values.${exportDestination}.label`) : undefined, - pendingAction: exportDestinationPending, - errors: ErrorUtils.getLatestErrorField(config, configType), - onCloseError: () => Policy.clearNetSuiteErrorField(policyID, configType), + subscribedSettings: [exportDestinationSettingName], + onCloseError: () => Policy.clearNetSuiteErrorField(policyID, exportDestinationSettingName), helperText: exportDestination ? translate(`workspace.netsuite.exportDestination.values.${exportDestination}.${helperTextType}`) : undefined, shouldParseHelperText: true, }, { description: translate('workspace.accounting.defaultVendor'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES_VENDOR_SELECT.getRoute(policyID, params.expenseType)), - brickRoadIndicator: config?.errorFields?.defaultVendor ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: defaultVendor ? defaultVendor.name : undefined, - pendingAction: config?.pendingFields?.defaultVendor, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.DEFAULT_VENDOR), + subscribedSettings: [CONST.NETSUITE_CONFIG.DEFAULT_VENDOR], onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.DEFAULT_VENDOR), - shouldHide: isReimbursable || exportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.VENDOR_BILL, + shouldHide: shouldHideReimbursableDefaultVendor(isReimbursable, config), }, { description: translate('workspace.netsuite.nonReimbursableJournalPostingAccount'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES_PAYABLE_ACCOUNT_SELECT.getRoute(policyID, params.expenseType)), - brickRoadIndicator: config?.errorFields?.payableAcct ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: selectedPayableAccount ? selectedPayableAccount.name : undefined, - pendingAction: config?.pendingFields?.payableAcct, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.PAYABLE_ACCT), + subscribedSettings: [CONST.NETSUITE_CONFIG.PAYABLE_ACCT], onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.PAYABLE_ACCT), - shouldHide: isReimbursable || exportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY, + shouldHide: shouldHideNonReimbursableJournalPostingAccount(isReimbursable, config), }, { description: translate('workspace.netsuite.reimbursableJournalPostingAccount'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES_PAYABLE_ACCOUNT_SELECT.getRoute(policyID, params.expenseType)), - brickRoadIndicator: config?.errorFields?.reimbursablePayableAccount ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: selectedReimbursablePayableAccount ? selectedReimbursablePayableAccount.name : undefined, - pendingAction: config?.pendingFields?.reimbursablePayableAccount, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.REIMBURSABLE_PAYABLE_ACCOUNT), + subscribedSettings: [CONST.NETSUITE_CONFIG.REIMBURSABLE_PAYABLE_ACCOUNT], onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.REIMBURSABLE_PAYABLE_ACCOUNT), - shouldHide: !isReimbursable || exportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY, + shouldHide: shouldHideReimbursableJournalPostingAccount(isReimbursable, config), }, { description: translate('workspace.netsuite.journalPostingPreference.label'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES_JOURNAL_POSTING_PREFERENCE_SELECT.getRoute(policyID, params.expenseType)), - brickRoadIndicator: config?.errorFields?.journalPostingPreference ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: config?.journalPostingPreference ? translate(`workspace.netsuite.journalPostingPreference.values.${config.journalPostingPreference}`) : translate(`workspace.netsuite.journalPostingPreference.values.${CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE}`), - pendingAction: config?.pendingFields?.journalPostingPreference, - errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.JOURNAL_POSTING_PREFERENCE), + subscribedSettings: [CONST.NETSUITE_CONFIG.JOURNAL_POSTING_PREFERENCE], onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.JOURNAL_POSTING_PREFERENCE), - shouldHide: exportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY, + shouldHide: shouldHideJournalPostingPreference(isReimbursable, config), }, ]; @@ -117,19 +113,15 @@ function NetSuiteExportExpensesPage({policy}: WithPolicyConnectionsProps) { .map((item) => ( diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesPayableAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesPayableAccountSelectPage.tsx index 0461171920d4..97e470776281 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesPayableAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesPayableAccountSelectPage.tsx @@ -8,12 +8,14 @@ import SelectionScreen from '@components/SelectionScreen'; 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 {getNetSuitePayableAccountOptions} from '@libs/PolicyUtils'; +import {getNetSuitePayableAccountOptions, settingsPendingAction} from '@libs/PolicyUtils'; import type {ExpenseRouteParams} from '@pages/workspace/accounting/netsuite/types'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -28,7 +30,8 @@ function NetSuiteExportExpensesPayableAccountSelectPage({policy}: WithPolicyConn const isReimbursable = params.expenseType === CONST.NETSUITE_EXPENSE_TYPE.REIMBURSABLE; const config = policy?.connections?.netsuite.options.config; - const currentPayableAccountID = isReimbursable ? config?.reimbursablePayableAccount : config?.payableAcct; + const currentSettingName = isReimbursable ? CONST.NETSUITE_CONFIG.REIMBURSABLE_PAYABLE_ACCOUNT : CONST.NETSUITE_CONFIG.PAYABLE_ACCT; + const currentPayableAccountID = config?.[currentSettingName]; const netsuitePayableAccountOptions = useMemo(() => getNetSuitePayableAccountOptions(policy ?? undefined, currentPayableAccountID), [currentPayableAccountID, policy]); const initiallyFocusedOptionKey = useMemo(() => netsuitePayableAccountOptions?.find((mode) => mode.isSelected)?.keyForList, [netsuitePayableAccountOptions]); @@ -80,6 +83,10 @@ function NetSuiteExportExpensesPayableAccountSelectPage({policy}: WithPolicyConn ? config?.reimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY : config?.nonreimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.JOURNAL_ENTRY } + pendingAction={settingsPendingAction([currentSettingName], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, currentSettingName)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, currentSettingName)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesVendorSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesVendorSelectPage.tsx index b6034a29a949..6f4cfe9817c3 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesVendorSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteExportExpensesVendorSelectPage.tsx @@ -8,12 +8,14 @@ import SelectionScreen from '@components/SelectionScreen'; 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 {getNetSuiteVendorOptions} from '@libs/PolicyUtils'; +import {getNetSuiteVendorOptions, settingsPendingAction} from '@libs/PolicyUtils'; import type {ExpenseRouteParams} from '@pages/workspace/accounting/netsuite/types'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -71,6 +73,10 @@ function NetSuiteExportExpensesVendorSelectPage({policy}: WithPolicyConnectionsP listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} shouldBeBlocked={isReimbursable || config?.nonreimbursableExpensesExportDestination !== CONST.NETSUITE_EXPORT_DESTINATION.VENDOR_BILL} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.DEFAULT_VENDOR], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.DEFAULT_VENDOR)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.DEFAULT_VENDOR)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemPreferenceSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemPreferenceSelectPage.tsx index 73a452c81745..f07edd7bd610 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemPreferenceSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemPreferenceSelectPage.tsx @@ -1,18 +1,18 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import SelectionList from '@components/SelectionList'; 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 * as ErrorUtils from '@libs/ErrorUtils'; -import {findSelectedInvoiceItemWithDefaultSelect} from '@libs/PolicyUtils'; +import {areSettingsInErrorFields, findSelectedInvoiceItemWithDefaultSelect, settingsPendingAction} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; @@ -54,40 +54,43 @@ function NetSuiteInvoiceItemPreferenceSelectPage({policy}: WithPolicyConnections [config?.invoiceItemPreference, policyID], ); - const headerContent = useMemo( - () => ( - - - {translate(`workspace.netsuite.invoiceItem.values.${config?.invoiceItemPreference ?? CONST.NETSUITE_INVOICE_ITEM_PREFERENCE.CREATE}.description`)} - - - ), - [styles.pb2, styles.ph5, styles.textNormal, translate, config?.invoiceItemPreference], - ); - return ( - selectInvoicePreference(selection as MenuListItem)} - initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} - policyID={policyID} + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT.getRoute(policyID))} accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN]} featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} - onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT.getRoute(policyID))} + displayName={NetSuiteInvoiceItemPreferenceSelectPage.displayName} + policyID={policyID} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} - shouldUpdateFocusedIndex - listFooterContent={ - config?.invoiceItemPreference === CONST.NETSUITE_INVOICE_ITEM_PREFERENCE.SELECT ? ( + shouldUseScrollView={false} + shouldIncludeSafeAreaPaddingBottom + > + Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.INVOICE_ITEM_PREFERENCE)} + style={[styles.flexGrow1, styles.flexShrink1]} + contentContainerStyle={[styles.flexGrow1, styles.flexShrink1]} + > + selectInvoicePreference(selection as MenuListItem)} + sections={[{data}]} + ListItem={RadioListItem} + showScrollIndicator + shouldUpdateFocusedIndex + initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} + containerStyle={[styles.flexReset, styles.flexGrow1, styles.flexShrink1, styles.pb0]} + /> + + {config?.invoiceItemPreference === CONST.NETSUITE_INVOICE_ITEM_PREFERENCE.SELECT && ( + Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.INVOICE_ITEM)} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.INVOICE_ITEM], config?.pendingFields)} > Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_INVOICE_ITEM_SELECT.getRoute(policyID))} - brickRoadIndicator={config?.errorFields?.invoiceItem ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} + brickRoadIndicator={areSettingsInErrorFields([CONST.NETSUITE_CONFIG.INVOICE_ITEM], config?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} /> - ) : null - } - /> + + )} + ); } diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemSelectPage.tsx index 26af047a3ef4..cfe0cdc89f93 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteInvoiceItemSelectPage.tsx @@ -7,11 +7,13 @@ import SelectionScreen from '@components/SelectionScreen'; 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 {getNetSuiteInvoiceItemOptions} from '@libs/PolicyUtils'; +import {getNetSuiteInvoiceItemOptions, settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -65,6 +67,10 @@ function NetSuiteInvoiceItemSelectPage({policy}: WithPolicyConnectionsProps) { listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} shouldBeBlocked={config?.invoiceItemPreference !== CONST.NETSUITE_INVOICE_ITEM_PREFERENCE.SELECT} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.INVOICE_ITEM], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.INVOICE_ITEM)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.INVOICE_ITEM)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuitePreferredExporterSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuitePreferredExporterSelectPage.tsx index 92d9a76bf9e4..b07a717a7abb 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuitePreferredExporterSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuitePreferredExporterSelectPage.tsx @@ -9,10 +9,12 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails' import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections/NetSuiteCommands'; -import {getAdminEmployees, isExpensifyTeam} from '@libs/PolicyUtils'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import {getAdminEmployees, isExpensifyTeam, settingsPendingAction} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -95,6 +97,10 @@ function NetSuitePreferredExporterSelectPage({policy}: WithPolicyConnectionsProp onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_EXPORT.getRoute(policyID))} title="workspace.accounting.preferredExporter" connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.EXPORTER], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.EXPORTER)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.EXPORTER)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteProvincialTaxPostingAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteProvincialTaxPostingAccountSelectPage.tsx index 71a10432d1ed..b0edc94cede9 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteProvincialTaxPostingAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteProvincialTaxPostingAccountSelectPage.tsx @@ -7,11 +7,13 @@ import SelectionScreen from '@components/SelectionScreen'; 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 {canUseProvincialTaxNetSuite, getNetSuiteTaxAccountOptions} from '@libs/PolicyUtils'; +import {canUseProvincialTaxNetSuite, getNetSuiteTaxAccountOptions, settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -71,6 +73,10 @@ function NetSuiteProvincialTaxPostingAccountSelectPage({policy}: WithPolicyConne listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} shouldBeBlocked={!!config?.suiteTaxEnabled || !config?.syncOptions.syncTax || !canUseProvincialTaxNetSuite(selectedSubsidiary?.country)} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.PROVINCIAL_TAX_POSTING_ACCOUNT], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.PROVINCIAL_TAX_POSTING_ACCOUNT)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.PROVINCIAL_TAX_POSTING_ACCOUNT)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteReceivableAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteReceivableAccountSelectPage.tsx index 4c1e62d66674..2bbd2fe37dc8 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteReceivableAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteReceivableAccountSelectPage.tsx @@ -7,11 +7,13 @@ import SelectionScreen from '@components/SelectionScreen'; 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 {getNetSuiteReceivableAccountOptions} from '@libs/PolicyUtils'; +import {getNetSuiteReceivableAccountOptions, settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -67,6 +69,10 @@ function NetSuiteReceivableAccountSelectPage({policy}: WithPolicyConnectionsProp title="workspace.netsuite.exportInvoices" listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.RECEIVABLE_ACCOUNT], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.RECEIVABLE_ACCOUNT)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.RECEIVABLE_ACCOUNT)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/export/NetSuiteTaxPostingAccountSelectPage.tsx b/src/pages/workspace/accounting/netsuite/export/NetSuiteTaxPostingAccountSelectPage.tsx index f7b7295e3a3a..5d749a433606 100644 --- a/src/pages/workspace/accounting/netsuite/export/NetSuiteTaxPostingAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/netsuite/export/NetSuiteTaxPostingAccountSelectPage.tsx @@ -8,11 +8,13 @@ import useLocalize from '@hooks/useLocalize'; import usePermissions from '@hooks/usePermissions'; 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 {canUseTaxNetSuite, getNetSuiteTaxAccountOptions} from '@libs/PolicyUtils'; +import {canUseTaxNetSuite, getNetSuiteTaxAccountOptions, settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -73,6 +75,10 @@ function NetSuiteTaxPostingAccountSelectPage({policy}: WithPolicyConnectionsProp listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} shouldBeBlocked={!!config?.suiteTaxEnabled || !config?.syncOptions.syncTax || !canUseTaxNetSuite(canUseNetSuiteUSATax, selectedSubsidiary?.country)} + pendingAction={settingsPendingAction([CONST.NETSUITE_CONFIG.TAX_POSTING_ACCOUNT], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.TAX_POSTING_ACCOUNT)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.TAX_POSTING_ACCOUNT)} /> ); } diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldEdit.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldEdit.tsx index d3f5082d47cb..9faea6197215 100644 --- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldEdit.tsx +++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldEdit.tsx @@ -12,6 +12,7 @@ import {updateNetSuiteCustomLists, updateNetSuiteCustomSegments} from '@libs/act import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; +import {settingsPendingAction} from '@libs/PolicyUtils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import CONST from '@src/CONST'; @@ -72,9 +73,21 @@ function NetSuiteImportCustomFieldEdit({ }); if (PolicyUtils.isNetSuiteCustomSegmentRecord(customField)) { - updateNetSuiteCustomSegments(policyID, updatedRecords as NetSuiteCustomSegment[], allRecords as NetSuiteCustomSegment[]); + updateNetSuiteCustomSegments( + policyID, + updatedRecords as NetSuiteCustomSegment[], + allRecords as NetSuiteCustomSegment[], + `${importCustomField}_${valueIndex}`, + CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + ); } else { - updateNetSuiteCustomLists(policyID, updatedRecords as NetSuiteCustomList[], allRecords as NetSuiteCustomList[]); + updateNetSuiteCustomLists( + policyID, + updatedRecords as NetSuiteCustomList[], + allRecords as NetSuiteCustomList[], + `${importCustomField}_${valueIndex}`, + CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + ); } } @@ -115,7 +128,7 @@ function NetSuiteImportCustomFieldEdit({ submitButtonText={translate('common.save')} shouldValidateOnBlur shouldValidateOnChange - isSubmitDisabled={!!config?.syncOptions?.pendingFields?.[importCustomField]} + isSubmitDisabled={!!settingsPendingAction([`${importCustomField}_${valueIndex}`], config?.pendingFields)} > ), - [config?.syncOptions?.pendingFields, customField, fieldName, fieldValue, importCustomField, inputCallbackRef, styles.flexGrow1, styles.ph5, translate, updateRecord, validate], + [config?.pendingFields, customField, fieldName, fieldValue, importCustomField, inputCallbackRef, styles.flexGrow1, styles.ph5, translate, updateRecord, validate, valueIndex], ); const renderSelection = useMemo( diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomListPage.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomListPage.tsx index e08cf4dac6c4..794ecc4b118a 100644 --- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomListPage.tsx +++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomListPage.tsx @@ -110,7 +110,13 @@ function NetSuiteImportAddCustomListPage({policy}: WithPolicyConnectionsProps) { mapping: formValues[INPUT_IDS.MAPPING] ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG, }, ]); - Connections.updateNetSuiteCustomLists(policyID, updatedCustomLists, customLists); + Connections.updateNetSuiteCustomLists( + policyID, + updatedCustomLists, + customLists, + `${CONST.NETSUITE_CONFIG.IMPORT_CUSTOM_FIELDS.CUSTOM_LISTS}_${customLists.length}`, + CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + ); nextScreen(); }, [customLists, nextScreen, policyID], @@ -153,7 +159,7 @@ function NetSuiteImportAddCustomListPage({policy}: WithPolicyConnectionsProps) { submitButtonStyles={[styles.ph5, styles.mb0]} shouldUseScrollView={!selectionListForm} enabledWhenOffline - isSubmitDisabled={!!config?.syncOptions?.pendingFields?.customLists} + isSubmitDisabled={!!config?.pendingFields?.customLists} submitFlexEnabled={submitFlexAllowed} > diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldPage.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldPage.tsx index 0a749b01399f..fa979cd7454c 100644 --- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldPage.tsx +++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldPage.tsx @@ -14,12 +14,11 @@ import TextLink from '@components/TextLink'; import WorkspaceEmptyStateSection from '@components/WorkspaceEmptyStateSection'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; +import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import type {ThemeStyles} from '@styles/index'; -import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -123,29 +122,27 @@ function NetSuiteImportCustomFieldPage({ onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_IMPORT.getRoute(policyID))} > {data.length === 0 ? listEmptyComponent : listHeaderComponent} - Policy.clearNetSuiteErrorField(policyID, importCustomField)} - > - {data.map((record, index) => ( + {data.map((record, index) => ( + Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_IMPORT_CUSTOM_FIELD_VIEW.getRoute(policyID, importCustomField, index))} + brickRoadIndicator={areSettingsInErrorFields([`${importCustomField}_${index}`], config?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} /> - ))} - + + ))}