From d11de01bda9b5b4db1bc57083bb5c38fdca2e226 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 16 Jul 2024 12:47:06 +0200 Subject: [PATCH 01/21] apply offline and errors pattern for xero export --- src/CONST.ts | 4 + src/libs/actions/connections/index.ts | 45 +++--- .../xero/export/XeroBankAccountSelectPage.tsx | 13 +- .../export/XeroExportConfigurationPage.tsx | 13 +- .../XeroPreferredExporterSelectPage.tsx | 16 ++- .../export/XeroPurchaseBillDateSelectPage.tsx | 14 +- .../XeroPurchaseBillStatusSelectorPage.tsx | 18 ++- src/types/onyx/Policy.ts | 132 +++++++++--------- 8 files changed, 150 insertions(+), 105 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 7fb0d320c43a..c4028ac1efd5 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1329,6 +1329,10 @@ const CONST = { SYNC: 'sync', ENABLE_NEW_CATEGORIES: 'enableNewCategories', EXPORT: 'export', + EXPORTER: 'exporter', + BILL_DATE: 'billDate', + BILL_STATUS: 'billStatus', + NON_REIMBURSABLE_ACCOUNT: 'nonReimbursableAccount', TENANT_ID: 'tenantID', IMPORT_CUSTOMERS: 'importCustomers', IMPORT_TAX_RATES: 'importTaxRates', diff --git a/src/libs/actions/connections/index.ts b/src/libs/actions/connections/index.ts index 9fb47a80fc50..ad32796683fe 100644 --- a/src/libs/actions/connections/index.ts +++ b/src/libs/actions/connections/index.ts @@ -6,6 +6,7 @@ import {READ_COMMANDS, 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 {ConnectionName, Connections, PolicyConnectionName} from '@src/types/onyx/Policy'; import type Policy from '@src/types/onyx/Policy'; @@ -36,6 +37,26 @@ function removePolicyConnection(policyID: string, connectionName: PolicyConnecti API.write(WRITE_COMMANDS.REMOVE_POLICY_CONNECTION, parameters, {optimisticData}); } +function createPendingFields( + settingValue: Partial, + pendingValue: OnyxCommon.PendingAction, +) { + return Object.keys(settingValue).reduce>((acc, setting) => { + acc[setting] = pendingValue; + return acc; + }, {}); +} + +function createErrorFields( + settingValue: Partial, + errorValue: OnyxCommon.Errors | null, +) { + return Object.keys(settingValue).reduce((acc, setting) => { + acc[setting] = errorValue; + return acc; + }, {}); +} + function updatePolicyConnectionConfig( policyID: string, connectionName: TConnectionName, @@ -51,12 +72,8 @@ function updatePolicyConnectionConfig(() => getXeroBankAccountsWithDefaultSelect(policy ?? undefined, nonReimbursableAccountID), [nonReimbursableAccountID, policy]); + const {config} = policy?.connections?.xero ?? {}; + const xeroSelectorOptions = useMemo( + () => getXeroBankAccountsWithDefaultSelect(policy ?? undefined, config?.export?.nonReimbursableAccount), + [config?.export?.nonReimbursableAccount, policy], + ); const listHeaderComponent = useMemo( () => ( @@ -78,6 +83,10 @@ function XeroBankAccountSelectPage({policy}: WithPolicyConnectionsProps) { title="workspace.xero.xeroBankAccount" listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} + pendingAction={config?.pendingFields?.nonReimbursableAccount} + errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT)} /> ); } diff --git a/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx b/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx index 00ce63b1dccc..f4909f8a300c 100644 --- a/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx @@ -39,8 +39,7 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { }, brickRoadIndicator: errorFields?.exporter ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: exportConfiguration?.exporter ?? policyOwner, - pendingAction: pendingFields?.export, - errorText: errorFields?.exporter ? translate('common.genericErrorMessage') : undefined, + pendingAction: pendingFields?.exporter, }, { description: translate('workspace.xero.exportExpenses'), @@ -54,15 +53,14 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_PURCHASE_BILL_DATE_SELECT.getRoute(policyID)), brickRoadIndicator: errorFields?.billDate ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: exportConfiguration?.billDate ? translate(`workspace.xero.exportDate.values.${exportConfiguration.billDate}.label`) : undefined, - pendingAction: pendingFields?.export, - errorText: errorFields?.billDate ? translate('common.genericErrorMessage') : undefined, + pendingAction: pendingFields?.billDate, }, { description: translate('workspace.xero.advancedConfig.purchaseBillStatusTitle'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_BILL_STATUS_SELECTOR.getRoute(policyID)), + brickRoadIndicator: errorFields?.billStatus ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: exportConfiguration?.billStatus?.purchase ? translate(`workspace.xero.invoiceStatus.values.${exportConfiguration.billStatus.purchase}`) : undefined, - pendingAction: pendingFields?.export, - errorText: errorFields?.purchase ? translate('common.genericErrorMessage') : undefined, + pendingAction: pendingFields?.billStatus, }, { description: translate('workspace.xero.exportInvoices'), @@ -83,8 +81,7 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_BANK_ACCOUNT_SELECT.getRoute(policyID)), brickRoadIndicator: errorFields?.nonReimbursableAccount ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: selectedBankAccountName, - pendingAction: pendingFields?.export, - errorText: errorFields?.nonReimbursableAccount ? translate('common.genericErrorMessage') : undefined, + pendingAction: pendingFields?.nonReimbursableAccount, }, ]; diff --git a/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx index 9b762cef9b52..9089ecb79642 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.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'; +import * as ErrorUtils from '@libs/ErrorUtils'; import {getAdminEmployees, isExpensifyTeam} 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'; @@ -21,7 +23,7 @@ type CardListItem = ListItem & { }; function XeroPreferredExporterSelectPage({policy}: WithPolicyConnectionsProps) { - const {export: exportConfiguration} = policy?.connections?.xero?.config ?? {}; + const {config} = policy?.connections?.xero ?? {}; const {translate} = useLocalize(); const styles = useThemeStyles(); const policyOwner = policy?.owner ?? ''; @@ -55,20 +57,20 @@ function XeroPreferredExporterSelectPage({policy}: WithPolicyConnectionsProps) { value: exporter.email, text: exporter.email, keyForList: exporter.email, - isSelected: exportConfiguration?.exporter === exporter.email, + isSelected: config?.export?.exporter === exporter.email, }); return options; }, []); - }, [exportConfiguration, exporters, policyOwner, currentUserLogin]); + }, [config?.export?.exporter, exporters, policyOwner, currentUserLogin]); const selectExporter = useCallback( (row: CardListItem) => { - if (row.value !== exportConfiguration?.exporter) { + if (row.value !== config?.export?.exporter) { Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, {exporter: row.value}); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID)); }, - [policyID, exportConfiguration], + [policyID, config?.export?.exporter], ); const headerContent = useMemo( @@ -95,6 +97,10 @@ function XeroPreferredExporterSelectPage({policy}: WithPolicyConnectionsProps) { onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID))} title="workspace.accounting.preferredExporter" connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} + pendingAction={config?.pendingFields?.exporter} + errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.EXPORTER)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.EXPORTER)} /> ); } diff --git a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx index 45b98c110a51..d1217742c1b3 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx @@ -9,9 +9,11 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; +import * as ErrorUtils from '@libs/ErrorUtils'; 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'; @@ -23,13 +25,13 @@ function XeroPurchaseBillDateSelectPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const policyID = policy?.id ?? '-1'; const styles = useThemeStyles(); - const {billDate} = policy?.connections?.xero?.config?.export ?? {}; + const {config} = policy?.connections?.xero ?? {}; const data: MenuListItem[] = Object.values(CONST.XERO_EXPORT_DATE).map((dateType) => ({ value: dateType, text: translate(`workspace.xero.exportDate.values.${dateType}.label`), alternateText: translate(`workspace.xero.exportDate.values.${dateType}.description`), keyForList: dateType, - isSelected: billDate === dateType, + isSelected: config?.export?.billDate === dateType, })); const headerContent = useMemo( @@ -43,12 +45,12 @@ function XeroPurchaseBillDateSelectPage({policy}: WithPolicyConnectionsProps) { const selectExportDate = useCallback( (row: MenuListItem) => { - if (row.value !== billDate) { + if (row.value !== config?.export?.billDate) { Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, {billDate: row.value}); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_PURCHASE_BILL_DATE_SELECT.getRoute(policyID)); }, - [billDate, policyID], + [config?.export?.billDate, policyID], ); return ( @@ -65,6 +67,10 @@ function XeroPurchaseBillDateSelectPage({policy}: WithPolicyConnectionsProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID))} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} + pendingAction={config?.pendingFields?.billDate} + errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.BILL_DATE)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.BILL_DATE)} /> ); } diff --git a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx index 0fbf1ff5c285..39afb125c3ea 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx @@ -10,9 +10,11 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; +import * as ErrorUtils from '@libs/ErrorUtils'; 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'; @@ -24,8 +26,8 @@ function XeroPurchaseBillStatusSelectorPage({policy}: WithPolicyConnectionsProps const {translate} = useLocalize(); const policyID = policy?.id ?? ''; const styles = useThemeStyles(); - const {billStatus} = policy?.connections?.xero?.config?.export ?? {}; - const invoiceStatus = billStatus?.purchase; + const {config} = policy?.connections?.xero ?? {}; + const invoiceStatus = config?.export?.billStatus?.purchase; const data: MenuListItem[] = Object.values(CONST.XERO_CONFIG.INVOICE_STATUS).map((status) => ({ value: status, @@ -45,15 +47,17 @@ function XeroPurchaseBillStatusSelectorPage({policy}: WithPolicyConnectionsProps const selectPurchaseBillStatus = useCallback( (row: MenuListItem) => { - if (isEmpty(billStatus)) { + if (isEmpty(config?.export?.billStatus)) { return; } if (row.value !== invoiceStatus) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, {billStatus: {...billStatus, purchase: row.value}}); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, { + billStatus: {...config?.export?.billStatus, purchase: row.value}, + }); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_BILL_STATUS_SELECTOR.getRoute(policyID)); }, - [billStatus, invoiceStatus, policyID], + [config?.export?.billStatus, invoiceStatus, policyID], ); return ( @@ -70,6 +74,10 @@ function XeroPurchaseBillStatusSelectorPage({policy}: WithPolicyConnectionsProps featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID))} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} + pendingAction={config?.pendingFields?.billStatus} + errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.BILL_STATUS)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.BILL_STATUS)} /> ); } diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 93c7351e8209..ee9ed55865f8 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -503,96 +503,102 @@ type XeroMappingType = { [key in `trackingCategory_${string}`]: string; }; -/** - * User configuration for the Xero accounting integration. - * - * TODO: Xero remaining comments will be handled here (https://github.com/Expensify/App/issues/43033) - */ -type XeroConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback<{ - /** Xero auto synchronization configs */ - autoSync: { - /** Whether data should be automatically synched between the app and Xero */ - enabled: boolean; +/** Xero export configs */ +type XeroExportConfig = { + /** Current bill status */ + billDate: BillDateValues; - /** TODO: Will be handled in another issue */ - jobID: string; + /** TODO: Will be handled in another issue */ + billStatus: { + /** Current status of the purchase bill */ + purchase: BillStatusValues; + + /** Current status of the sales bill */ + sales: BillStatusValues; }; /** TODO: Will be handled in another issue */ - enableNewCategories: boolean; + billable: ExpenseTypesValues; - /** Xero export configs */ - export: { - /** Current bill status */ - billDate: BillDateValues; - - /** TODO: Will be handled in another issue */ - billStatus: { - /** Current status of the purchase bill */ - purchase: BillStatusValues; + /** The e-mail of the exporter */ + exporter: string; - /** Current status of the sales bill */ - sales: BillStatusValues; - }; + /** TODO: Will be handled in another issue */ + nonReimbursable: ExpenseTypesValues; - /** TODO: Will be handled in another issue */ - billable: ExpenseTypesValues; + /** TODO: Will be handled in another issue */ + nonReimbursableAccount: string; - /** The e-mail of the exporter */ - exporter: string; + /** TODO: Will be handled in another issue */ + reimbursable: ExpenseTypesValues; +}; - /** TODO: Will be handled in another issue */ - nonReimbursable: ExpenseTypesValues; +/** + * User configuration for the Xero accounting integration. + * + * TODO: Xero remaining comments will be handled here (https://github.com/Expensify/App/issues/43033) + */ +type XeroConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback< + { + /** Xero auto synchronization configs */ + autoSync: { + /** Whether data should be automatically synched between the app and Xero */ + enabled: boolean; - /** TODO: Will be handled in another issue */ - nonReimbursableAccount: string; + /** TODO: Will be handled in another issue */ + jobID: string; + }; /** TODO: Will be handled in another issue */ - reimbursable: ExpenseTypesValues; - }; + enableNewCategories: boolean; - /** Whether customers should be imported from Xero */ - importCustomers: boolean; + /** Xero export configs */ + export: XeroExportConfig; - /** Whether tax rates should be imported from Xero */ - importTaxRates: boolean; + /** Whether customers should be imported from Xero */ + importCustomers: boolean; - /** Whether tracking categories should be imported from Xero */ - importTrackingCategories: boolean; + /** Whether tax rates should be imported from Xero */ + importTaxRates: boolean; - /** TODO: Will be handled in another issue */ - isConfigured: boolean; + /** Whether tracking categories should be imported from Xero */ + importTrackingCategories: boolean; - /** TODO: Will be handled in another issue */ - mappings: XeroMappingType; + /** TODO: Will be handled in another issue */ + isConfigured: boolean; - /** TODO: Will be handled in another issue */ - sync: { /** TODO: Will be handled in another issue */ - hasChosenAutoSyncOption: boolean; + mappings: XeroMappingType; /** TODO: Will be handled in another issue */ - hasChosenSyncReimbursedReportsOption: boolean; + sync: { + /** TODO: Will be handled in another issue */ + hasChosenAutoSyncOption: boolean; - /** ID of the bank account for Xero invoice collections */ - invoiceCollectionsAccountID: string; + /** TODO: Will be handled in another issue */ + hasChosenSyncReimbursedReportsOption: boolean; - /** ID of the bank account for Xero bill payment account */ - reimbursementAccountID: string; + /** ID of the bank account for Xero invoice collections */ + invoiceCollectionsAccountID: string; - /** Whether the reimbursed reports should be synched */ - syncReimbursedReports: boolean; - }; + /** ID of the bank account for Xero bill payment account */ + reimbursementAccountID: string; - /** ID of Xero organization */ - tenantID: string; + /** Whether the reimbursed reports should be synched */ + syncReimbursedReports: boolean; + }; - /** TODO: Will be handled in another issue */ - errors?: OnyxCommon.Errors; + /** ID of Xero organization */ + tenantID: string; - /** Collection of form field errors */ - errorFields?: OnyxCommon.ErrorFields; -}>; + /** TODO: Will be handled in another issue */ + errors?: OnyxCommon.Errors; + + /** Collection of form field errors */ + errorFields?: OnyxCommon.ErrorFields; + }, + keyof XeroExportConfig +>; /** Data stored about subsidiaries from NetSuite */ type NetSuiteSubsidiary = { From 564d2299958a34c2c3a7753236bdd2ec5f0e1bf1 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 16 Jul 2024 16:12:39 +0200 Subject: [PATCH 02/21] update xero advanced page --- src/CONST.ts | 6 ++- src/libs/actions/connections/index.ts | 23 +++++--- .../xero/advanced/XeroAdvancedPage.tsx | 20 +++---- .../XeroBillPaymentAccountSelectorPage.tsx | 7 +++ .../XeroInvoiceAccountSelectorPage.tsx | 7 +++ src/types/onyx/Policy.ts | 54 ++++++++++--------- 6 files changed, 77 insertions(+), 40 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index c4028ac1efd5..16fe0ed3213d 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1063,7 +1063,7 @@ const CONST = { PROCESS_REQUEST_DELAY_MS: 1000, MAX_PENDING_TIME_MS: 10 * 1000, RECHECK_INTERVAL_MS: 60 * 1000, - MAX_REQUEST_RETRIES: 10, + MAX_REQUEST_RETRIES: 0, NETWORK_STATUS: { ONLINE: 'online', OFFLINE: 'offline', @@ -1326,7 +1326,11 @@ const CONST = { XERO_CONFIG: { AUTO_SYNC: 'autoSync', + ENABLED: 'enabled', + REIMBURSEMENT_ACCOUNT_ID: 'reimbursementAccountID', + INVOICE_COLLECTIONS_ACCOUNT_ID: 'invoiceCollectionsAccountID', SYNC: 'sync', + SYNC_REIMBURSED_REPORTS: 'syncReimbursedReports', ENABLE_NEW_CATEGORIES: 'enableNewCategories', EXPORT: 'export', EXPORTER: 'exporter', diff --git a/src/libs/actions/connections/index.ts b/src/libs/actions/connections/index.ts index ad32796683fe..d5b4c3d807f2 100644 --- a/src/libs/actions/connections/index.ts +++ b/src/libs/actions/connections/index.ts @@ -1,3 +1,4 @@ +import isObject from 'lodash/isObject'; import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import * as API from '@libs/API'; @@ -38,9 +39,14 @@ function removePolicyConnection(policyID: string, connectionName: PolicyConnecti } function createPendingFields( + 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; @@ -48,9 +54,14 @@ function createPendingFields( + 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; @@ -72,8 +83,8 @@ function updatePolicyConnectionConfig Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.AUTO_SYNC)} + pendingAction={pendingFields?.enabled} + errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.ENABLED)} + onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.ENABLED)} /> Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.SYNC)} + pendingAction={pendingFields?.syncReimbursedReports} + errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS)} + onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS)} /> {sync?.syncReimbursedReports && ( <> - + Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_BILL_PAYMENT_ACCOUNT_SELECTOR.getRoute(policyID))} + brickRoadIndicator={errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} /> - + { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_INVOICE_SELECTOR.getRoute(policyID)); }} + brickRoadIndicator={errorFields?.invoiceCollectionsAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} /> diff --git a/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx index 05b7cf877d33..72d9df9c43bd 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.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'; +import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {getXeroBankAccountsWithDefaultSelect} 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'; @@ -23,6 +25,7 @@ function XeroBillPaymentAccountSelectorPage({policy}: WithPolicyConnectionsProps const policyID = policy?.id ?? '-1'; + const {config} = policy?.connections?.xero ?? {}; const {reimbursementAccountID, syncReimbursedReports} = policy?.connections?.xero?.config.sync ?? {}; const xeroSelectorOptions = useMemo(() => getXeroBankAccountsWithDefaultSelect(policy ?? undefined, reimbursementAccountID), [reimbursementAccountID, policy]); @@ -77,6 +80,10 @@ function XeroBillPaymentAccountSelectorPage({policy}: WithPolicyConnectionsProps onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID))} title="workspace.xero.advancedConfig.xeroBillPaymentAccount" listEmptyContent={listEmptyContent} + pendingAction={config?.pendingFields?.reimbursementAccountID} + errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID)} /> ); } diff --git a/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx index 49fac2e38a9b..8a46fb7b3474 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.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'; +import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {getXeroBankAccountsWithDefaultSelect} 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'; @@ -23,6 +25,7 @@ function XeroInvoiceAccountSelectorPage({policy}: WithPolicyConnectionsProps) { const policyID = policy?.id ?? '-1'; + const {config} = policy?.connections?.xero ?? {}; const {invoiceCollectionsAccountID, syncReimbursedReports} = policy?.connections?.xero?.config.sync ?? {}; const xeroSelectorOptions = useMemo(() => getXeroBankAccountsWithDefaultSelect(policy ?? undefined, invoiceCollectionsAccountID), [invoiceCollectionsAccountID, policy]); @@ -77,6 +80,10 @@ function XeroInvoiceAccountSelectorPage({policy}: WithPolicyConnectionsProps) { onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID))} title="workspace.xero.advancedConfig.xeroInvoiceCollectionAccount" listEmptyContent={listEmptyContent} + pendingAction={config?.pendingFields?.invoiceCollectionsAccountID} + errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID)} /> ); } diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index ee9ed55865f8..22056b71356c 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -503,6 +503,15 @@ type XeroMappingType = { [key in `trackingCategory_${string}`]: string; }; +/** Xero auto synchronization configs */ +type XeroAutoSyncConfig = { + /** Whether data should be automatically synched between the app and Xero */ + enabled: boolean; + + /** TODO: Will be handled in another issue */ + jobID: string; +}; + /** Xero export configs */ type XeroExportConfig = { /** Current bill status */ @@ -533,6 +542,24 @@ type XeroExportConfig = { reimbursable: ExpenseTypesValues; }; +/** TODO: Will be handled in another issue */ +type XeroSyncConfig = { + /** TODO: Will be handled in another issue */ + hasChosenAutoSyncOption: boolean; + + /** TODO: Will be handled in another issue */ + hasChosenSyncReimbursedReportsOption: boolean; + + /** ID of the bank account for Xero invoice collections */ + invoiceCollectionsAccountID: string; + + /** ID of the bank account for Xero bill payment account */ + reimbursementAccountID: string; + + /** Whether the reimbursed reports should be synched */ + syncReimbursedReports: boolean; +}; + /** * User configuration for the Xero accounting integration. * @@ -541,13 +568,7 @@ type XeroExportConfig = { type XeroConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback< { /** Xero auto synchronization configs */ - autoSync: { - /** Whether data should be automatically synched between the app and Xero */ - enabled: boolean; - - /** TODO: Will be handled in another issue */ - jobID: string; - }; + autoSync: XeroAutoSyncConfig; /** TODO: Will be handled in another issue */ enableNewCategories: boolean; @@ -571,22 +592,7 @@ type XeroConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback< mappings: XeroMappingType; /** TODO: Will be handled in another issue */ - sync: { - /** TODO: Will be handled in another issue */ - hasChosenAutoSyncOption: boolean; - - /** TODO: Will be handled in another issue */ - hasChosenSyncReimbursedReportsOption: boolean; - - /** ID of the bank account for Xero invoice collections */ - invoiceCollectionsAccountID: string; - - /** ID of the bank account for Xero bill payment account */ - reimbursementAccountID: string; - - /** Whether the reimbursed reports should be synched */ - syncReimbursedReports: boolean; - }; + sync: XeroSyncConfig; /** ID of Xero organization */ tenantID: string; @@ -597,7 +603,7 @@ type XeroConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback< /** Collection of form field errors */ errorFields?: OnyxCommon.ErrorFields; }, - keyof XeroExportConfig + keyof XeroAutoSyncConfig | keyof XeroExportConfig | keyof XeroSyncConfig >; /** Data stored about subsidiaries from NetSuite */ From d629d704081ae6553288ecb22210bc655b013d8d Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 16 Jul 2024 16:47:33 +0200 Subject: [PATCH 03/21] revert max retries --- src/CONST.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CONST.ts b/src/CONST.ts index 16fe0ed3213d..3bea7683b8c9 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1063,7 +1063,7 @@ const CONST = { PROCESS_REQUEST_DELAY_MS: 1000, MAX_PENDING_TIME_MS: 10 * 1000, RECHECK_INTERVAL_MS: 60 * 1000, - MAX_REQUEST_RETRIES: 0, + MAX_REQUEST_RETRIES: 10, NETWORK_STATUS: { ONLINE: 'online', OFFLINE: 'offline', From e0d0e53521680472fab048f7bf0d164f19c82d67 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 16 Jul 2024 17:09:29 +0200 Subject: [PATCH 04/21] update XeroOrganizationConfigurationPage --- src/CONST.ts | 2 +- src/components/SelectionScreen.tsx | 5 ++ .../XeroOrganizationConfigurationPage.tsx | 72 ++++++++++++------- 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 3bea7683b8c9..16fe0ed3213d 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1063,7 +1063,7 @@ const CONST = { PROCESS_REQUEST_DELAY_MS: 1000, MAX_PENDING_TIME_MS: 10 * 1000, RECHECK_INTERVAL_MS: 60 * 1000, - MAX_REQUEST_RETRIES: 10, + MAX_REQUEST_RETRIES: 0, NETWORK_STATUS: { ONLINE: 'online', OFFLINE: 'offline', diff --git a/src/components/SelectionScreen.tsx b/src/components/SelectionScreen.tsx index 0e3f0d84e10e..427577206aeb 100644 --- a/src/components/SelectionScreen.tsx +++ b/src/components/SelectionScreen.tsx @@ -82,6 +82,9 @@ type SelectionScreenProps = { /** A function to run when the X button next to the error is clicked */ onClose?: () => void; + + /** Whether to debounce `onRowSelect` */ + shouldDebounceRowSelect?: boolean; }; function SelectionScreen({ @@ -104,6 +107,7 @@ function SelectionScreen({ errors, errorRowStyles, onClose, + shouldDebounceRowSelect, }: SelectionScreenProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -142,6 +146,7 @@ function SelectionScreen({ listEmptyContent={listEmptyContent} listFooterContent={listFooterContent} sectionListStyle={[styles.flexGrow0]} + shouldDebounceRowSelect={shouldDebounceRowSelect} > ; @@ -36,11 +39,21 @@ function XeroOrganizationConfigurationPage({ const sections = policy?.connections?.xero?.data?.tenants.map((tenant) => ({ + value: tenant.id, text: tenant.name, keyForList: tenant.id, isSelected: tenant.id === organizationID, })) ?? []; + const listHeaderComponent = useMemo( + () => ( + + {translate('workspace.xero.organizationDescription')} + + ), + [translate, styles.pb2, styles.ph5, styles.pb5, styles.textNormal], + ); + const saveSelection = ({keyForList}: ListItem) => { if (!keyForList) { return; @@ -50,32 +63,41 @@ function XeroOrganizationConfigurationPage({ Navigation.goBack(); }; + const listEmptyContent = useMemo( + () => ( + + ), + [translate, styles.pb10], + ); + return ( - - Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.TENANT_ID)} - > - {translate('workspace.xero.organizationDescription')} - - - + onSelectRow={saveSelection} + initiallyFocusedOptionKey={currentXeroOrganization?.id} + headerContent={listHeaderComponent} + onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING.getRoute(policyID))} + title="workspace.xero.organization" + listEmptyContent={listEmptyContent} + pendingAction={xeroConfig?.pendingFields?.tenantID} + errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.TENANT_ID)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.TENANT_ID)} + shouldDebounceRowSelect + /> ); } From 9ed5911efda29e99290c618e4c1cb36a23219ba5 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 16 Jul 2024 17:59:22 +0200 Subject: [PATCH 05/21] update XeroTrackingCategoryConfigurationPage --- ...roMapTrackingCategoryConfigurationPage.tsx | 51 ++++++++++++------- .../XeroTrackingCategoryConfigurationPage.tsx | 7 +-- src/types/onyx/Policy.ts | 2 +- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx index ace9f5582523..1087b502852a 100644 --- a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx @@ -1,14 +1,17 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useMemo} from 'react'; -import ConnectionLayout from '@components/ConnectionLayout'; -import SelectionList from '@components/SelectionList'; +import {View} from 'react-native'; import RadioListItem from '@components/SelectionList/RadioListItem'; +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'; +import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ROUTES from '@src/ROUTES'; @@ -28,6 +31,7 @@ function XeroMapTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { const categoryId = params?.categoryId ?? ''; const categoryName = decodeURIComponent(params?.categoryName ?? ''); const policyID = policy?.id ?? '-1'; + const {config} = policy?.connections?.xero ?? {}; const {trackingCategories} = policy?.connections?.xero?.data ?? {}; const {mappings} = policy?.connections?.xero?.config ?? {}; @@ -45,6 +49,15 @@ function XeroMapTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { [translate, currentTrackingCategoryValue], ); + const listHeaderComponent = useMemo( + () => ( + + {translate('workspace.xero.mapTrackingCategoryToDescription', {categoryName})} + + ), + [translate, styles.pb2, styles.ph5, styles.pb5, styles.textNormal, categoryName], + ); + const updateMapping = useCallback( (option: {value: string}) => { if (option.value !== categoryName) { @@ -59,26 +72,26 @@ function XeroMapTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { ); return ( - option.isSelected)?.keyForList} + headerContent={listHeaderComponent} + onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_TRACKING_CATEGORIES.getRoute(policyID))} + // TODO: change title + title="workspace.xero.accountsDescription" connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} - > - option.isSelected)?.keyForList} - shouldDebounceRowSelect - /> - + pendingAction={config?.pendingFields?.[`trackingCategory_${categoryId}`]} + errors={ErrorUtils.getLatestErrorField(config ?? {}, `trackingCategory_${categoryId}`)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearXeroErrorField(policyID, `trackingCategory_${categoryId}`)} + shouldDebounceRowSelect + /> ); } diff --git a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx index c566d1262590..3553cab9a8b7 100644 --- a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx @@ -1,7 +1,6 @@ import React, {useMemo} from 'react'; import {View} from 'react-native'; import ConnectionLayout from '@components/ConnectionLayout'; -import type {MenuItemProps} from '@components/MenuItem'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -25,9 +24,10 @@ function XeroTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { const xeroConfig = policy?.connections?.xero?.config; const isSwitchOn = !!xeroConfig?.importTrackingCategories; - const menuItems: MenuItemProps[] = useMemo(() => { + const menuItems = useMemo(() => { const trackingCategories = getTrackingCategories(policy); return trackingCategories.map((category: XeroTrackingCategory & {value: string}) => ({ + id: category.id, description: translate('workspace.xero.mapTrackingCategoryTo', {categoryName: category.name}) as TranslationPaths, onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_TRACKING_CATEGORIES_MAP.getRoute(policyID, category.id, category.name)), title: translate(`workspace.xero.trackingCategoriesOptions.${category.value.toLowerCase()}` as TranslationPaths), @@ -63,7 +63,7 @@ function XeroTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { /> {xeroConfig?.importTrackingCategories && ( - {menuItems.map((menuItem: MenuItemProps) => ( + {menuItems.map((menuItem) => ( ))} diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 22056b71356c..382e10ee6a5d 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -603,7 +603,7 @@ type XeroConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback< /** Collection of form field errors */ errorFields?: OnyxCommon.ErrorFields; }, - keyof XeroAutoSyncConfig | keyof XeroExportConfig | keyof XeroSyncConfig + keyof XeroAutoSyncConfig | keyof XeroExportConfig | keyof XeroSyncConfig | keyof XeroMappingType >; /** Data stored about subsidiaries from NetSuite */ From f2ed76e1daabd72634b1637ef76fc096af39c382 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 16 Jul 2024 18:15:58 +0200 Subject: [PATCH 06/21] add translated title to Selection Screen --- src/components/SelectionScreen.tsx | 8 ++++++-- .../xero/XeroMapTrackingCategoryConfigurationPage.tsx | 3 +-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/SelectionScreen.tsx b/src/components/SelectionScreen.tsx index 4ea7c9da8b50..45492c77ec98 100644 --- a/src/components/SelectionScreen.tsx +++ b/src/components/SelectionScreen.tsx @@ -32,7 +32,7 @@ type SelectionScreenProps = { displayName: string; /** Title of the selection component */ - title: TranslationPaths; + title?: TranslationPaths; /** Custom content to display in the header */ headerContent?: React.ReactNode; @@ -87,6 +87,9 @@ type SelectionScreenProps = { /** Whether to debounce `onRowSelect` */ shouldDebounceRowSelect?: boolean; + + /** Used for dynamic header title translation with parameters */ + headerTitleAlreadyTranslated?: string; }; function SelectionScreen({ @@ -110,6 +113,7 @@ function SelectionScreen({ errorRowStyles, onClose, shouldDebounceRowSelect, + headerTitleAlreadyTranslated, }: SelectionScreenProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -129,7 +133,7 @@ function SelectionScreen({ testID={displayName} > {headerContent} diff --git a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx index 1087b502852a..b9b2102c89dd 100644 --- a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx @@ -83,8 +83,7 @@ function XeroMapTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { initiallyFocusedOptionKey={optionsList.find((option) => option.isSelected)?.keyForList} headerContent={listHeaderComponent} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_TRACKING_CATEGORIES.getRoute(policyID))} - // TODO: change title - title="workspace.xero.accountsDescription" + headerTitleAlreadyTranslated={translate('workspace.xero.mapTrackingCategoryTo', {categoryName})} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} pendingAction={config?.pendingFields?.[`trackingCategory_${categoryId}`]} errors={ErrorUtils.getLatestErrorField(config ?? {}, `trackingCategory_${categoryId}`)} From 5d8ec28fdb7e589aa3f1e94c050e18711c0d5e32 Mon Sep 17 00:00:00 2001 From: war-in Date: Wed, 17 Jul 2024 16:30:46 +0200 Subject: [PATCH 07/21] show RBRs everywhere --- src/libs/PolicyUtils.ts | 16 ++++++++++- .../accounting/PolicyAccountingPage.tsx | 28 ++++++++++++++++++- .../accounting/xero/XeroImportPage.tsx | 19 +++++++------ ...roMapTrackingCategoryConfigurationPage.tsx | 12 ++++---- .../XeroTrackingCategoryConfigurationPage.tsx | 2 +- .../xero/advanced/XeroAdvancedPage.tsx | 11 ++++++-- .../export/XeroExportConfigurationPage.tsx | 18 +++++------- 7 files changed, 77 insertions(+), 29 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index bfce8a91e71a..592eda2c774b 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -1,7 +1,7 @@ import {Str} from 'expensify-common'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; -import type {ValueOf} from 'type-fest'; +import type {Except, ValueOf} from 'type-fest'; import type {LocaleContextProps} from '@components/LocaleContextProvider'; import type {SelectorType} from '@components/SelectionScreen'; import CONST from '@src/CONST'; @@ -9,6 +9,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import INPUT_IDS from '@src/types/form/NetSuiteCustomFieldForm'; import type {OnyxInputOrEntry, Policy, PolicyCategories, PolicyEmployeeList, PolicyTagList, PolicyTags, TaxRate} from '@src/types/onyx'; +import type {ErrorFields} from '@src/types/onyx/OnyxCommon'; import type { ConnectionLastSync, ConnectionName, @@ -497,6 +498,18 @@ function getXeroBankAccountsWithDefaultSelect(policy: Policy | undefined, select })); } +function areXeroSettingsInErrorFields( + settings: Array>>, + errorFields?: ErrorFields, +) { + if (errorFields === undefined) { + return false; + } + + const keys = Object.keys(errorFields); + return settings.some((setting) => keys.includes(setting)); +} + function getNetSuiteVendorOptions(policy: Policy | undefined, selectedVendorId: string | undefined): SelectorType[] { const vendors = policy?.connections?.netsuite.options.data.vendors ?? []; @@ -837,6 +850,7 @@ export { getNameFromNetSuiteCustomField, isNetSuiteCustomFieldPropertyEditable, getCurrentSageIntacctEntityName, + areXeroSettingsInErrorFields, }; export type {MemberEmailsToAccountIDs}; diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index 4fe83366047e..cb206c3804f0 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -37,6 +37,7 @@ import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import type {AnchorPosition} from '@styles/index'; +import {getTrackingCategories} from '@userActions/connections/ConnectToXero'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -62,8 +63,11 @@ type AccountingIntegration = { icon: IconAsset; setupConnectionButton: React.ReactNode; onImportPagePress: () => void; + hasImportError?: boolean; onExportPagePress: () => void; + hasExportError?: boolean; onAdvancedPagePress: () => void; + hasAdvancedError?: boolean; onCardReconciliationPagePress: () => void; }; function accountingIntegrationData( @@ -72,6 +76,7 @@ function accountingIntegrationData( translate: LocaleContextProps['translate'], isConnectedToIntegration?: boolean, integrationToDisconnect?: PolicyConnectionName, + policy?: Policy, ): AccountingIntegration | undefined { switch (connectionName) { case CONST.POLICY.CONNECTIONS.NAME.QBO: @@ -102,9 +107,27 @@ function accountingIntegrationData( /> ), onImportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_IMPORT.getRoute(policyID)), + hasImportError: PolicyUtils.areXeroSettingsInErrorFields( + [ + CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES, + CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, + CONST.XERO_CONFIG.IMPORT_CUSTOMERS, + CONST.XERO_CONFIG.IMPORT_TAX_RATES, + ...getTrackingCategories(policy).map((category) => `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${category.id}`), + ], + policy?.connections?.xero?.config?.errorFields ?? {}, + ), onExportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID)), + hasExportError: PolicyUtils.areXeroSettingsInErrorFields( + [CONST.XERO_CONFIG.EXPORTER, CONST.XERO_CONFIG.BILL_DATE, CONST.XERO_CONFIG.BILL_STATUS, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], + policy?.connections?.xero?.config?.errorFields ?? {}, + ), onCardReconciliationPagePress: () => Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_CARD_RECONCILIATION.getRoute(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO)), onAdvancedPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID)), + hasAdvancedError: PolicyUtils.areXeroSettingsInErrorFields( + [CONST.XERO_CONFIG.ENABLED, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], + policy?.connections?.xero?.config?.errorFields ?? {}, + ), }; case CONST.POLICY.CONNECTIONS.NAME.NETSUITE: return { @@ -284,7 +307,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { return []; } const shouldShowSynchronizationError = hasSynchronizationError(policy, connectedIntegration, isSyncInProgress); - const integrationData = accountingIntegrationData(connectedIntegration, policyID, translate); + const integrationData = accountingIntegrationData(connectedIntegration, policyID, translate, undefined, undefined, policy); const iconProps = integrationData?.icon ? {icon: integrationData.icon, iconType: CONST.ICON_TYPE_AVATAR} : {}; return [ { @@ -333,6 +356,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { title: translate('workspace.accounting.import'), wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onImportPagePress, + brickRoadIndicator: integrationData?.hasImportError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }, { icon: Expensicons.Send, @@ -341,6 +365,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { title: translate('workspace.accounting.export'), wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onExportPagePress, + brickRoadIndicator: integrationData?.hasExportError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }, { icon: Expensicons.ExpensifyCard, @@ -358,6 +383,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { title: translate('workspace.accounting.advanced'), wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onAdvancedPagePress, + brickRoadIndicator: integrationData?.hasAdvancedError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }, ]), ]; diff --git a/src/pages/workspace/accounting/xero/XeroImportPage.tsx b/src/pages/workspace/accounting/xero/XeroImportPage.tsx index d1ab01ea4570..db29dffca08b 100644 --- a/src/pages/workspace/accounting/xero/XeroImportPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroImportPage.tsx @@ -7,8 +7,10 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import {getCurrentXeroOrganizationName} from '@libs/PolicyUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import withPolicy from '@pages/workspace/withPolicy'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; +import {getTrackingCategories} from '@userActions/connections/ConnectToXero'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -27,13 +29,16 @@ function XeroImportPage({policy}: WithPolicyProps) { description: translate('workspace.accounting.accounts'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_CHART_OF_ACCOUNTS.getRoute(policyID)), title: translate('workspace.accounting.importAsCategory'), - hasError: !!errorFields?.enableNewCategories, + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES], errorFields), pendingAction: pendingFields?.enableNewCategories, }, { description: translate('workspace.xero.trackingCategories'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_TRACKING_CATEGORIES.getRoute(policyID)), - hasError: !!errorFields?.importTrackingCategories, + hasError: PolicyUtils.areXeroSettingsInErrorFields( + [CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, ...getTrackingCategories(policy).map((category) => `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${category.id}`)], + errorFields, + ), title: importTrackingCategories ? translate('workspace.accounting.imported') : translate('workspace.xero.notImported'), pendingAction: pendingFields?.importTrackingCategories, }, @@ -42,24 +47,21 @@ function XeroImportPage({policy}: WithPolicyProps) { action: () => { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_CUSTOMER.getRoute(policyID)); }, - hasError: !!errorFields?.importCustomers, + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.IMPORT_CUSTOMERS], errorFields), title: importCustomers ? translate('workspace.accounting.importTypes.TAG') : translate('workspace.xero.notImported'), pendingAction: pendingFields?.importCustomers, }, { description: translate('workspace.accounting.taxes'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_TAXES.getRoute(policyID)), - hasError: !!errorFields?.importTaxRates, + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.IMPORT_TAX_RATES], errorFields), title: importTaxRates ? translate('workspace.accounting.imported') : translate('workspace.xero.notImported'), pendingAction: pendingFields?.importTaxRates, }, ], [ translate, - errorFields?.enableNewCategories, - errorFields?.importTrackingCategories, - errorFields?.importCustomers, - errorFields?.importTaxRates, + errorFields, pendingFields?.enableNewCategories, pendingFields?.importTrackingCategories, pendingFields?.importCustomers, @@ -68,6 +70,7 @@ function XeroImportPage({policy}: WithPolicyProps) { importCustomers, importTaxRates, policyID, + policy, ], ); diff --git a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx index b9b2102c89dd..9b8b170c6013 100644 --- a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx @@ -61,14 +61,16 @@ function XeroMapTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { const updateMapping = useCallback( (option: {value: string}) => { if (option.value !== categoryName) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.MAPPINGS, { - ...(policy?.connections?.xero?.config?.mappings ?? {}), - ...(categoryId ? {[`${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${categoryId}`]: option.value} : {}), - }); + Connections.updatePolicyConnectionConfig( + policyID, + CONST.POLICY.CONNECTIONS.NAME.XERO, + CONST.XERO_CONFIG.MAPPINGS, + categoryId ? {[`${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${categoryId}`]: option.value} : {}, + ); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_TRACKING_CATEGORIES.getRoute(policyID)); }, - [categoryId, categoryName, policyID, policy?.connections?.xero?.config?.mappings], + [categoryId, categoryName, policyID], ); return ( diff --git a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx index 3553cab9a8b7..1f76de45ff22 100644 --- a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx @@ -71,7 +71,7 @@ function XeroTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { shouldShowRightIcon onPress={menuItem.onPress} wrapperStyle={styles.sectionMenuItemTopDescription} - brickRoadIndicator={xeroConfig?.errorFields?.[`trackingCategory_${menuItem.id}`] ? 'error' : undefined} + brickRoadIndicator={xeroConfig?.errorFields?.[`${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${menuItem.id}`] ? 'error' : undefined} /> ))} diff --git a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx index 2e6ad0bf2b27..b75d632a04d2 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx @@ -8,6 +8,7 @@ import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {getCurrentXeroOrganizationName} from '@libs/PolicyUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -93,7 +94,9 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { key={translate('workspace.xero.advancedConfig.xeroBillPaymentAccount')} wrapperStyle={[styles.sectionMenuItemTopDescription]} onPress={() => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_BILL_PAYMENT_ACCOUNT_SELECTOR.getRoute(policyID))} - brickRoadIndicator={errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} + brickRoadIndicator={ + PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID], errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined + } /> @@ -106,7 +109,11 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { onPress={() => { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_INVOICE_SELECTOR.getRoute(policyID)); }} - brickRoadIndicator={errorFields?.invoiceCollectionsAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} + brickRoadIndicator={ + PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], errorFields) + ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR + : undefined + } /> diff --git a/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx b/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx index f4909f8a300c..f857fb3671dd 100644 --- a/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx @@ -1,20 +1,17 @@ import React, {useMemo} from 'react'; import ConnectionLayout from '@components/ConnectionLayout'; -import type {MenuItemProps} from '@components/MenuItem'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import type {OfflineWithFeedbackProps} from '@components/OfflineWithFeedback'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import {getCurrentXeroOrganizationName} from '@libs/PolicyUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; -type MenuItem = MenuItemProps & {pendingAction?: OfflineWithFeedbackProps['pendingAction']}; - function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -31,13 +28,13 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { const currentXeroOrganizationName = useMemo(() => getCurrentXeroOrganizationName(policy ?? undefined), [policy]); - const menuItems: MenuItem[] = [ + const menuItems = [ { description: translate('workspace.accounting.preferredExporter'), onPress: () => { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_PREFERRED_EXPORTER_SELECT.getRoute(policyID)); }, - brickRoadIndicator: errorFields?.exporter ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.EXPORTER], errorFields), title: exportConfiguration?.exporter ?? policyOwner, pendingAction: pendingFields?.exporter, }, @@ -51,14 +48,14 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { { description: translate('workspace.xero.purchaseBillDate'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_PURCHASE_BILL_DATE_SELECT.getRoute(policyID)), - brickRoadIndicator: errorFields?.billDate ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.BILL_DATE], errorFields), title: exportConfiguration?.billDate ? translate(`workspace.xero.exportDate.values.${exportConfiguration.billDate}.label`) : undefined, pendingAction: pendingFields?.billDate, }, { description: translate('workspace.xero.advancedConfig.purchaseBillStatusTitle'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_BILL_STATUS_SELECTOR.getRoute(policyID)), - brickRoadIndicator: errorFields?.billStatus ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.BILL_STATUS], errorFields), title: exportConfiguration?.billStatus?.purchase ? translate(`workspace.xero.invoiceStatus.values.${exportConfiguration.billStatus.purchase}`) : undefined, pendingAction: pendingFields?.billStatus, }, @@ -79,7 +76,7 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { { description: translate('workspace.xero.xeroBankAccount'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_BANK_ACCOUNT_SELECT.getRoute(policyID)), - brickRoadIndicator: errorFields?.nonReimbursableAccount ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], errorFields), title: selectedBankAccountName, pendingAction: pendingFields?.nonReimbursableAccount, }, @@ -109,9 +106,8 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { description={menuItem.description} shouldShowRightIcon={menuItem?.shouldShowRightIcon ?? true} onPress={menuItem?.onPress} - brickRoadIndicator={menuItem?.brickRoadIndicator} + brickRoadIndicator={menuItem?.hasError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} helperText={menuItem?.helperText} - errorText={menuItem?.errorText} /> ))} From a6861e40fa7c2f9452f8ce4ff8d82a9363c508cc Mon Sep 17 00:00:00 2001 From: war-in Date: Wed, 17 Jul 2024 16:48:42 +0200 Subject: [PATCH 08/21] fix typescript errors --- src/CONST.ts | 2 +- src/libs/PolicyUtils.ts | 9 +++------ src/pages/workspace/accounting/PolicyAccountingPage.tsx | 6 +++--- src/pages/workspace/accounting/xero/XeroImportPage.tsx | 8 ++++---- .../accounting/xero/advanced/XeroAdvancedPage.tsx | 6 ++---- .../xero/export/XeroExportConfigurationPage.tsx | 8 ++++---- 6 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index fcdf0bbcd694..af5f8f138f46 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1067,7 +1067,7 @@ const CONST = { PROCESS_REQUEST_DELAY_MS: 1000, MAX_PENDING_TIME_MS: 10 * 1000, RECHECK_INTERVAL_MS: 60 * 1000, - MAX_REQUEST_RETRIES: 0, + MAX_REQUEST_RETRIES: 10, NETWORK_STATUS: { ONLINE: 'online', OFFLINE: 'offline', diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 592eda2c774b..6814473a2f30 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -1,7 +1,7 @@ import {Str} from 'expensify-common'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; -import type {Except, ValueOf} from 'type-fest'; +import type {ValueOf} from 'type-fest'; import type {LocaleContextProps} from '@components/LocaleContextProvider'; import type {SelectorType} from '@components/SelectionScreen'; import CONST from '@src/CONST'; @@ -498,10 +498,7 @@ function getXeroBankAccountsWithDefaultSelect(policy: Policy | undefined, select })); } -function areXeroSettingsInErrorFields( - settings: Array>>, - errorFields?: ErrorFields, -) { +function areSettingsInErrorFields(settings: string[], errorFields?: ErrorFields) { if (errorFields === undefined) { return false; } @@ -850,7 +847,7 @@ export { getNameFromNetSuiteCustomField, isNetSuiteCustomFieldPropertyEditable, getCurrentSageIntacctEntityName, - areXeroSettingsInErrorFields, + areSettingsInErrorFields, }; export type {MemberEmailsToAccountIDs}; diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index cb206c3804f0..63289a9fd643 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -107,7 +107,7 @@ function accountingIntegrationData( /> ), onImportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_IMPORT.getRoute(policyID)), - hasImportError: PolicyUtils.areXeroSettingsInErrorFields( + hasImportError: PolicyUtils.areSettingsInErrorFields( [ CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES, CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, @@ -118,13 +118,13 @@ function accountingIntegrationData( policy?.connections?.xero?.config?.errorFields ?? {}, ), onExportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID)), - hasExportError: PolicyUtils.areXeroSettingsInErrorFields( + hasExportError: PolicyUtils.areSettingsInErrorFields( [CONST.XERO_CONFIG.EXPORTER, CONST.XERO_CONFIG.BILL_DATE, CONST.XERO_CONFIG.BILL_STATUS, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], policy?.connections?.xero?.config?.errorFields ?? {}, ), onCardReconciliationPagePress: () => Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_CARD_RECONCILIATION.getRoute(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO)), onAdvancedPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID)), - hasAdvancedError: PolicyUtils.areXeroSettingsInErrorFields( + hasAdvancedError: PolicyUtils.areSettingsInErrorFields( [CONST.XERO_CONFIG.ENABLED, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], policy?.connections?.xero?.config?.errorFields ?? {}, ), diff --git a/src/pages/workspace/accounting/xero/XeroImportPage.tsx b/src/pages/workspace/accounting/xero/XeroImportPage.tsx index db29dffca08b..67c47a88c5b6 100644 --- a/src/pages/workspace/accounting/xero/XeroImportPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroImportPage.tsx @@ -29,13 +29,13 @@ function XeroImportPage({policy}: WithPolicyProps) { description: translate('workspace.accounting.accounts'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_CHART_OF_ACCOUNTS.getRoute(policyID)), title: translate('workspace.accounting.importAsCategory'), - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES], errorFields), + hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES], errorFields), pendingAction: pendingFields?.enableNewCategories, }, { description: translate('workspace.xero.trackingCategories'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_TRACKING_CATEGORIES.getRoute(policyID)), - hasError: PolicyUtils.areXeroSettingsInErrorFields( + hasError: PolicyUtils.areSettingsInErrorFields( [CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, ...getTrackingCategories(policy).map((category) => `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${category.id}`)], errorFields, ), @@ -47,14 +47,14 @@ function XeroImportPage({policy}: WithPolicyProps) { action: () => { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_CUSTOMER.getRoute(policyID)); }, - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.IMPORT_CUSTOMERS], errorFields), + hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.IMPORT_CUSTOMERS], errorFields), title: importCustomers ? translate('workspace.accounting.importTypes.TAG') : translate('workspace.xero.notImported'), pendingAction: pendingFields?.importCustomers, }, { description: translate('workspace.accounting.taxes'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_TAXES.getRoute(policyID)), - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.IMPORT_TAX_RATES], errorFields), + hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.IMPORT_TAX_RATES], errorFields), title: importTaxRates ? translate('workspace.accounting.imported') : translate('workspace.xero.notImported'), pendingAction: pendingFields?.importTaxRates, }, diff --git a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx index b75d632a04d2..35a97b69b8c9 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx @@ -95,7 +95,7 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { wrapperStyle={[styles.sectionMenuItemTopDescription]} onPress={() => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_BILL_PAYMENT_ACCOUNT_SELECTOR.getRoute(policyID))} brickRoadIndicator={ - PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID], errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined + PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID], errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined } /> @@ -110,9 +110,7 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_INVOICE_SELECTOR.getRoute(policyID)); }} brickRoadIndicator={ - PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], errorFields) - ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR - : undefined + PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined } /> diff --git a/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx b/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx index f857fb3671dd..090c4977076d 100644 --- a/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx @@ -34,7 +34,7 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { onPress: () => { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_PREFERRED_EXPORTER_SELECT.getRoute(policyID)); }, - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.EXPORTER], errorFields), + hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.EXPORTER], errorFields), title: exportConfiguration?.exporter ?? policyOwner, pendingAction: pendingFields?.exporter, }, @@ -48,14 +48,14 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { { description: translate('workspace.xero.purchaseBillDate'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_PURCHASE_BILL_DATE_SELECT.getRoute(policyID)), - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.BILL_DATE], errorFields), + hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.BILL_DATE], errorFields), title: exportConfiguration?.billDate ? translate(`workspace.xero.exportDate.values.${exportConfiguration.billDate}.label`) : undefined, pendingAction: pendingFields?.billDate, }, { description: translate('workspace.xero.advancedConfig.purchaseBillStatusTitle'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_BILL_STATUS_SELECTOR.getRoute(policyID)), - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.BILL_STATUS], errorFields), + hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.BILL_STATUS], errorFields), title: exportConfiguration?.billStatus?.purchase ? translate(`workspace.xero.invoiceStatus.values.${exportConfiguration.billStatus.purchase}`) : undefined, pendingAction: pendingFields?.billStatus, }, @@ -76,7 +76,7 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { { description: translate('workspace.xero.xeroBankAccount'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_BANK_ACCOUNT_SELECT.getRoute(policyID)), - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], errorFields), + hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], errorFields), title: selectedBankAccountName, pendingAction: pendingFields?.nonReimbursableAccount, }, From 25be841f37c33ea346c0341928176da1c0833d5c Mon Sep 17 00:00:00 2001 From: war-in Date: Wed, 17 Jul 2024 17:14:29 +0200 Subject: [PATCH 09/21] use more specific type --- src/CONST.ts | 2 +- src/libs/PolicyUtils.ts | 9 ++++++--- src/pages/workspace/accounting/PolicyAccountingPage.tsx | 6 +++--- src/pages/workspace/accounting/xero/XeroImportPage.tsx | 8 ++++---- .../accounting/xero/advanced/XeroAdvancedPage.tsx | 6 ++++-- .../xero/export/XeroExportConfigurationPage.tsx | 8 ++++---- 6 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index af5f8f138f46..fcdf0bbcd694 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1067,7 +1067,7 @@ const CONST = { PROCESS_REQUEST_DELAY_MS: 1000, MAX_PENDING_TIME_MS: 10 * 1000, RECHECK_INTERVAL_MS: 60 * 1000, - MAX_REQUEST_RETRIES: 10, + MAX_REQUEST_RETRIES: 0, NETWORK_STATUS: { ONLINE: 'online', OFFLINE: 'offline', diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 6814473a2f30..87ccdffeef35 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -1,7 +1,7 @@ import {Str} from 'expensify-common'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; -import type {ValueOf} from 'type-fest'; +import type {Except, LiteralUnion, ValueOf} from 'type-fest'; import type {LocaleContextProps} from '@components/LocaleContextProvider'; import type {SelectorType} from '@components/SelectionScreen'; import CONST from '@src/CONST'; @@ -498,7 +498,10 @@ function getXeroBankAccountsWithDefaultSelect(policy: Policy | undefined, select })); } -function areSettingsInErrorFields(settings: string[], errorFields?: ErrorFields) { +function areXeroSettingsInErrorFields( + settings: Array>, string>>, + errorFields?: ErrorFields, +) { if (errorFields === undefined) { return false; } @@ -847,7 +850,7 @@ export { getNameFromNetSuiteCustomField, isNetSuiteCustomFieldPropertyEditable, getCurrentSageIntacctEntityName, - areSettingsInErrorFields, + areXeroSettingsInErrorFields, }; export type {MemberEmailsToAccountIDs}; diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index 63289a9fd643..cb206c3804f0 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -107,7 +107,7 @@ function accountingIntegrationData( /> ), onImportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_IMPORT.getRoute(policyID)), - hasImportError: PolicyUtils.areSettingsInErrorFields( + hasImportError: PolicyUtils.areXeroSettingsInErrorFields( [ CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES, CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, @@ -118,13 +118,13 @@ function accountingIntegrationData( policy?.connections?.xero?.config?.errorFields ?? {}, ), onExportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID)), - hasExportError: PolicyUtils.areSettingsInErrorFields( + hasExportError: PolicyUtils.areXeroSettingsInErrorFields( [CONST.XERO_CONFIG.EXPORTER, CONST.XERO_CONFIG.BILL_DATE, CONST.XERO_CONFIG.BILL_STATUS, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], policy?.connections?.xero?.config?.errorFields ?? {}, ), onCardReconciliationPagePress: () => Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_CARD_RECONCILIATION.getRoute(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO)), onAdvancedPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID)), - hasAdvancedError: PolicyUtils.areSettingsInErrorFields( + hasAdvancedError: PolicyUtils.areXeroSettingsInErrorFields( [CONST.XERO_CONFIG.ENABLED, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], policy?.connections?.xero?.config?.errorFields ?? {}, ), diff --git a/src/pages/workspace/accounting/xero/XeroImportPage.tsx b/src/pages/workspace/accounting/xero/XeroImportPage.tsx index 67c47a88c5b6..db29dffca08b 100644 --- a/src/pages/workspace/accounting/xero/XeroImportPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroImportPage.tsx @@ -29,13 +29,13 @@ function XeroImportPage({policy}: WithPolicyProps) { description: translate('workspace.accounting.accounts'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_CHART_OF_ACCOUNTS.getRoute(policyID)), title: translate('workspace.accounting.importAsCategory'), - hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES], errorFields), + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES], errorFields), pendingAction: pendingFields?.enableNewCategories, }, { description: translate('workspace.xero.trackingCategories'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_TRACKING_CATEGORIES.getRoute(policyID)), - hasError: PolicyUtils.areSettingsInErrorFields( + hasError: PolicyUtils.areXeroSettingsInErrorFields( [CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, ...getTrackingCategories(policy).map((category) => `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${category.id}`)], errorFields, ), @@ -47,14 +47,14 @@ function XeroImportPage({policy}: WithPolicyProps) { action: () => { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_CUSTOMER.getRoute(policyID)); }, - hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.IMPORT_CUSTOMERS], errorFields), + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.IMPORT_CUSTOMERS], errorFields), title: importCustomers ? translate('workspace.accounting.importTypes.TAG') : translate('workspace.xero.notImported'), pendingAction: pendingFields?.importCustomers, }, { description: translate('workspace.accounting.taxes'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_TAXES.getRoute(policyID)), - hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.IMPORT_TAX_RATES], errorFields), + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.IMPORT_TAX_RATES], errorFields), title: importTaxRates ? translate('workspace.accounting.imported') : translate('workspace.xero.notImported'), pendingAction: pendingFields?.importTaxRates, }, diff --git a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx index 35a97b69b8c9..b75d632a04d2 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx @@ -95,7 +95,7 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { wrapperStyle={[styles.sectionMenuItemTopDescription]} onPress={() => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_BILL_PAYMENT_ACCOUNT_SELECTOR.getRoute(policyID))} brickRoadIndicator={ - PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID], errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined + PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID], errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined } /> @@ -110,7 +110,9 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_INVOICE_SELECTOR.getRoute(policyID)); }} brickRoadIndicator={ - PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined + PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], errorFields) + ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR + : undefined } /> diff --git a/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx b/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx index 090c4977076d..f857fb3671dd 100644 --- a/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx @@ -34,7 +34,7 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { onPress: () => { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_PREFERRED_EXPORTER_SELECT.getRoute(policyID)); }, - hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.EXPORTER], errorFields), + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.EXPORTER], errorFields), title: exportConfiguration?.exporter ?? policyOwner, pendingAction: pendingFields?.exporter, }, @@ -48,14 +48,14 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { { description: translate('workspace.xero.purchaseBillDate'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_PURCHASE_BILL_DATE_SELECT.getRoute(policyID)), - hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.BILL_DATE], errorFields), + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.BILL_DATE], errorFields), title: exportConfiguration?.billDate ? translate(`workspace.xero.exportDate.values.${exportConfiguration.billDate}.label`) : undefined, pendingAction: pendingFields?.billDate, }, { description: translate('workspace.xero.advancedConfig.purchaseBillStatusTitle'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_BILL_STATUS_SELECTOR.getRoute(policyID)), - hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.BILL_STATUS], errorFields), + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.BILL_STATUS], errorFields), title: exportConfiguration?.billStatus?.purchase ? translate(`workspace.xero.invoiceStatus.values.${exportConfiguration.billStatus.purchase}`) : undefined, pendingAction: pendingFields?.billStatus, }, @@ -76,7 +76,7 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { { description: translate('workspace.xero.xeroBankAccount'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_BANK_ACCOUNT_SELECT.getRoute(policyID)), - hasError: PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], errorFields), + hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], errorFields), title: selectedBankAccountName, pendingAction: pendingFields?.nonReimbursableAccount, }, From 854b71f35bdbc208c2e0889b795477c7dc1e6982 Mon Sep 17 00:00:00 2001 From: war-in Date: Wed, 17 Jul 2024 18:13:24 +0200 Subject: [PATCH 10/21] add function for pending action extraction --- src/libs/PolicyUtils.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 87ccdffeef35..86497210ffcc 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -10,6 +10,7 @@ import ROUTES from '@src/ROUTES'; import INPUT_IDS from '@src/types/form/NetSuiteCustomFieldForm'; import type {OnyxInputOrEntry, Policy, PolicyCategories, PolicyEmployeeList, PolicyTagList, PolicyTags, TaxRate} from '@src/types/onyx'; import type {ErrorFields} from '@src/types/onyx/OnyxCommon'; +import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type { ConnectionLastSync, ConnectionName, @@ -510,6 +511,18 @@ function areXeroSettingsInErrorFields( return settings.some((setting) => keys.includes(setting)); } +function xeroSettingsPendingAction( + settings: Array>, string>>, + pendingFields?: Record, +): OnyxCommon.PendingAction { + if (pendingFields === undefined) { + return null; + } + + const key = Object.keys(pendingFields).find((setting) => settings.includes(setting)); + return pendingFields[key ?? '-1']; +} + function getNetSuiteVendorOptions(policy: Policy | undefined, selectedVendorId: string | undefined): SelectorType[] { const vendors = policy?.connections?.netsuite.options.data.vendors ?? []; @@ -851,6 +864,7 @@ export { isNetSuiteCustomFieldPropertyEditable, getCurrentSageIntacctEntityName, areXeroSettingsInErrorFields, + xeroSettingsPendingAction, }; export type {MemberEmailsToAccountIDs}; From 4db4bed37a7636783e3b253dc119d8dedc8c1ac1 Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 22 Jul 2024 12:51:55 +0200 Subject: [PATCH 11/21] use unified offline flow on advanced page --- src/libs/PolicyUtils.ts | 7 +++---- .../accounting/xero/advanced/XeroAdvancedPage.tsx | 10 +++++----- .../advanced/XeroBillPaymentAccountSelectorPage.tsx | 4 ++-- .../xero/advanced/XeroInvoiceAccountSelectorPage.tsx | 4 ++-- src/types/onyx/OnyxCommon.ts | 2 +- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 2ad9d71d6b6a..90c80af36294 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -9,7 +9,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import INPUT_IDS from '@src/types/form/NetSuiteCustomFieldForm'; import type {OnyxInputOrEntry, Policy, PolicyCategories, PolicyEmployeeList, PolicyTagList, PolicyTags, TaxRate} from '@src/types/onyx'; -import type {ErrorFields} from '@src/types/onyx/OnyxCommon'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type { ConnectionLastSync, @@ -524,7 +523,7 @@ function getXeroBankAccountsWithDefaultSelect(policy: Policy | undefined, select function areXeroSettingsInErrorFields( settings: Array>, string>>, - errorFields?: ErrorFields, + errorFields?: OnyxCommon.ErrorFields, ) { if (errorFields === undefined) { return false; @@ -536,8 +535,8 @@ function areXeroSettingsInErrorFields( function xeroSettingsPendingAction( settings: Array>, string>>, - pendingFields?: Record, -): OnyxCommon.PendingAction { + pendingFields?: OnyxCommon.PendingFields, +): OnyxCommon.PendingAction | undefined { if (pendingFields === undefined) { return null; } diff --git a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx index b75d632a04d2..52f0c39b8e14 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx @@ -7,7 +7,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; -import {getCurrentXeroOrganizationName} from '@libs/PolicyUtils'; +import {getCurrentXeroOrganizationName, xeroSettingsPendingAction} from '@libs/PolicyUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; @@ -63,7 +63,7 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { enabled: !autoSync?.enabled, }) } - pendingAction={pendingFields?.enabled} + pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.ENABLED], pendingFields)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.ENABLED)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.ENABLED)} /> @@ -80,13 +80,13 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { syncReimbursedReports: !sync?.syncReimbursedReports, }) } - pendingAction={pendingFields?.syncReimbursedReports} + pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS], pendingFields)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS)} /> {sync?.syncReimbursedReports && ( <> - + - + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID))} title="workspace.xero.advancedConfig.xeroBillPaymentAccount" listEmptyContent={listEmptyContent} - pendingAction={config?.pendingFields?.reimbursementAccountID} + pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID)} diff --git a/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx index 8a46fb7b3474..150b03d295a8 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx @@ -11,7 +11,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; -import {getXeroBankAccountsWithDefaultSelect} from '@libs/PolicyUtils'; +import {getXeroBankAccountsWithDefaultSelect, xeroSettingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; @@ -80,7 +80,7 @@ function XeroInvoiceAccountSelectorPage({policy}: WithPolicyConnectionsProps) { onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID))} title="workspace.xero.advancedConfig.xeroInvoiceCollectionAccount" listEmptyContent={listEmptyContent} - pendingAction={config?.pendingFields?.invoiceCollectionsAccountID} + pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID)} diff --git a/src/types/onyx/OnyxCommon.ts b/src/types/onyx/OnyxCommon.ts index ee60b6dbf1fd..4f97df07ea26 100644 --- a/src/types/onyx/OnyxCommon.ts +++ b/src/types/onyx/OnyxCommon.ts @@ -54,4 +54,4 @@ type Icon = { fill?: string; }; -export type {Icon, PendingAction, ErrorFields, Errors, AvatarType, OnyxValueWithOfflineFeedback}; +export type {Icon, PendingAction, PendingFields, ErrorFields, Errors, AvatarType, OnyxValueWithOfflineFeedback}; From c2de3deca29518ef0ead2635456e97b0fb82988f Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 22 Jul 2024 13:50:03 +0200 Subject: [PATCH 12/21] use unified offline flow on import page --- .../accounting/PolicyAccountingPage.tsx | 31 ++++++++++++--- .../accounting/xero/XeroImportPage.tsx | 38 ++++++------------- ...roMapTrackingCategoryConfigurationPage.tsx | 7 ++-- .../xero/XeroTaxesConfigurationPage.tsx | 2 + .../XeroTrackingCategoryConfigurationPage.tsx | 27 ++++++++----- .../xero/import/XeroChartOfAccountsPage.tsx | 2 + .../import/XeroCustomerConfigurationPage.tsx | 2 + 7 files changed, 65 insertions(+), 44 deletions(-) diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index 3242e651e5f5..3c641c77b557 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -3,6 +3,7 @@ import React, {useEffect, useMemo, useRef, useState} from 'react'; import {ActivityIndicator, View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; +import type {Except, LiteralUnion, ValueOf} from 'type-fest'; import CollapsibleSection from '@components/CollapsibleSection'; import ConfirmModal from '@components/ConfirmModal'; import ConnectToNetSuiteButton from '@components/ConnectToNetSuiteButton'; @@ -64,10 +65,12 @@ type AccountingIntegration = { setupConnectionButton: React.ReactNode; onImportPagePress: () => void; hasImportError?: boolean; + importPendingAction?: OfflineWithFeedbackProps['pendingAction']; onExportPagePress: () => void; hasExportError?: boolean; onAdvancedPagePress: () => void; hasAdvancedError?: boolean; + advancedPendingAction?: OfflineWithFeedbackProps['pendingAction']; onCardReconciliationPagePress: () => void; }; function accountingIntegrationData( @@ -115,18 +118,32 @@ function accountingIntegrationData( CONST.XERO_CONFIG.IMPORT_TAX_RATES, ...getTrackingCategories(policy).map((category) => `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${category.id}`), ], - policy?.connections?.xero?.config?.errorFields ?? {}, + policy?.connections?.xero?.config?.errorFields, + ), + importPendingAction: PolicyUtils.xeroSettingsPendingAction( + [ + CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES, + CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, + CONST.XERO_CONFIG.IMPORT_CUSTOMERS, + CONST.XERO_CONFIG.IMPORT_TAX_RATES, + ...getTrackingCategories(policy).map((category) => `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${category.id}`), + ], + policy?.connections?.xero?.config?.pendingFields, ), onExportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID)), hasExportError: PolicyUtils.areXeroSettingsInErrorFields( [CONST.XERO_CONFIG.EXPORTER, CONST.XERO_CONFIG.BILL_DATE, CONST.XERO_CONFIG.BILL_STATUS, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], - policy?.connections?.xero?.config?.errorFields ?? {}, + policy?.connections?.xero?.config?.errorFields, ), onCardReconciliationPagePress: () => Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_CARD_RECONCILIATION.getRoute(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO)), onAdvancedPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID)), hasAdvancedError: PolicyUtils.areXeroSettingsInErrorFields( [CONST.XERO_CONFIG.ENABLED, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], - policy?.connections?.xero?.config?.errorFields ?? {}, + policy?.connections?.xero?.config?.errorFields, + ), + advancedPendingAction: PolicyUtils.xeroSettingsPendingAction( + [CONST.XERO_CONFIG.ENABLED, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], + policy?.connections?.xero?.config?.pendingFields, ), }; case CONST.POLICY.CONNECTIONS.NAME.NETSUITE: @@ -243,8 +260,10 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { } Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_ORGANIZATION.getRoute(policyID, currentXeroOrganization?.id ?? '-1')); }, - pendingAction: policy?.connections?.xero?.config?.pendingFields?.tenantID, - brickRoadIndicator: policy?.connections?.xero?.config?.errorFields?.tenantID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + pendingAction: PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.TENANT_ID], policy?.connections?.xero?.config?.pendingFields), + brickRoadIndicator: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.TENANT_ID], policy?.connections?.xero?.config?.errorFields) + ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR + : undefined, }; case CONST.POLICY.CONNECTIONS.NAME.NETSUITE: return { @@ -357,6 +376,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onImportPagePress, brickRoadIndicator: integrationData?.hasImportError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + pendingAction: integrationData?.importPendingAction, }, { icon: Expensicons.Send, @@ -384,6 +404,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onAdvancedPagePress, brickRoadIndicator: integrationData?.hasAdvancedError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + pendingAction: integrationData?.advancedPendingAction, }, ]), ]; diff --git a/src/pages/workspace/accounting/xero/XeroImportPage.tsx b/src/pages/workspace/accounting/xero/XeroImportPage.tsx index db29dffca08b..636416e488e2 100644 --- a/src/pages/workspace/accounting/xero/XeroImportPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroImportPage.tsx @@ -6,7 +6,7 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; -import {getCurrentXeroOrganizationName} from '@libs/PolicyUtils'; +import {getCurrentXeroOrganizationName, xeroSettingsPendingAction} from '@libs/PolicyUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import withPolicy from '@pages/workspace/withPolicy'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; @@ -29,49 +29,33 @@ function XeroImportPage({policy}: WithPolicyProps) { description: translate('workspace.accounting.accounts'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_CHART_OF_ACCOUNTS.getRoute(policyID)), title: translate('workspace.accounting.importAsCategory'), - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES], errorFields), - pendingAction: pendingFields?.enableNewCategories, + subscribedSettings: [CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES], }, { description: translate('workspace.xero.trackingCategories'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_TRACKING_CATEGORIES.getRoute(policyID)), - hasError: PolicyUtils.areXeroSettingsInErrorFields( - [CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, ...getTrackingCategories(policy).map((category) => `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${category.id}`)], - errorFields, - ), title: importTrackingCategories ? translate('workspace.accounting.imported') : translate('workspace.xero.notImported'), - pendingAction: pendingFields?.importTrackingCategories, + subscribedSettings: [ + CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, + ...getTrackingCategories(policy).map((category) => `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${category.id}`), + ], }, { description: translate('workspace.xero.customers'), action: () => { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_CUSTOMER.getRoute(policyID)); }, - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.IMPORT_CUSTOMERS], errorFields), title: importCustomers ? translate('workspace.accounting.importTypes.TAG') : translate('workspace.xero.notImported'), - pendingAction: pendingFields?.importCustomers, + subscribedSettings: [CONST.XERO_CONFIG.IMPORT_CUSTOMERS], }, { description: translate('workspace.accounting.taxes'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_TAXES.getRoute(policyID)), - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.IMPORT_TAX_RATES], errorFields), title: importTaxRates ? translate('workspace.accounting.imported') : translate('workspace.xero.notImported'), - pendingAction: pendingFields?.importTaxRates, + subscribedSettings: [CONST.XERO_CONFIG.IMPORT_TAX_RATES], }, ], - [ - translate, - errorFields, - pendingFields?.enableNewCategories, - pendingFields?.importTrackingCategories, - pendingFields?.importCustomers, - pendingFields?.importTaxRates, - importTrackingCategories, - importCustomers, - importTaxRates, - policyID, - policy, - ], + [translate, errorFields, pendingFields, policy, importTrackingCategories, importCustomers, importTaxRates, policyID], ); return ( @@ -91,14 +75,14 @@ function XeroImportPage({policy}: WithPolicyProps) { {sections.map((section) => ( ))} diff --git a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx index 9b8b170c6013..4a0ab1e54434 100644 --- a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx @@ -9,6 +9,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; +import {xeroSettingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import * as Policy from '@userActions/Policy/Policy'; @@ -87,10 +88,10 @@ function XeroMapTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_TRACKING_CATEGORIES.getRoute(policyID))} headerTitleAlreadyTranslated={translate('workspace.xero.mapTrackingCategoryTo', {categoryName})} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} - pendingAction={config?.pendingFields?.[`trackingCategory_${categoryId}`]} - errors={ErrorUtils.getLatestErrorField(config ?? {}, `trackingCategory_${categoryId}`)} + pendingAction={xeroSettingsPendingAction([`${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${categoryId}`], config?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(config ?? {}, `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${categoryId}`)} errorRowStyles={[styles.ph5, styles.pv3]} - onClose={() => Policy.clearXeroErrorField(policyID, `trackingCategory_${categoryId}`)} + onClose={() => Policy.clearXeroErrorField(policyID, `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${categoryId}`)} shouldDebounceRowSelect /> ); diff --git a/src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx index ae54336fcc13..553541bcb25f 100644 --- a/src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx @@ -4,6 +4,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -35,6 +36,7 @@ function XeroTaxesConfigurationPage({policy}: WithPolicyProps) { onToggle={() => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.IMPORT_TAX_RATES, !xeroConfig?.importTaxRates)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.IMPORT_TAX_RATES)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.IMPORT_TAX_RATES)} + pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.IMPORT_TAX_RATES], xeroConfig?.pendingFields)} /> ); diff --git a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx index 1f76de45ff22..29dacc36b23d 100644 --- a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx @@ -2,12 +2,14 @@ import React, {useMemo} from 'react'; import {View} from 'react-native'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; +import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import {getTrackingCategories} from '@libs/actions/connections/ConnectToXero'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; +import {areXeroSettingsInErrorFields, xeroSettingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -58,21 +60,28 @@ function XeroTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { !xeroConfig?.importTrackingCategories, ) } + pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES], xeroConfig?.pendingFields)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES)} /> {xeroConfig?.importTrackingCategories && ( {menuItems.map((menuItem) => ( - + + + ))} )} diff --git a/src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx b/src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx index 9d30f4a21d7d..d0f8fa2ee3e0 100644 --- a/src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx +++ b/src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx @@ -8,6 +8,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; +import {xeroSettingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -61,6 +62,7 @@ function XeroChartOfAccountsPage({policy}: WithPolicyProps) { onToggle={() => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES, !xeroConfig?.enableNewCategories) } + pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES], xeroConfig?.pendingFields)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES)} /> diff --git a/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx b/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx index 0dedf301e6c7..fd8bf3515050 100644 --- a/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx @@ -5,6 +5,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -44,6 +45,7 @@ function XeroCustomerConfigurationPage({policy}: WithPolicyProps) { onToggle={() => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.IMPORT_CUSTOMERS, !xeroConfig?.importCustomers)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.IMPORT_CUSTOMERS)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.IMPORT_CUSTOMERS)} + pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.IMPORT_CUSTOMERS], xeroConfig?.pendingFields)} /> ); From b20bbedbf4c727cc8d5f611773fc7cf90d2f0ce7 Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 22 Jul 2024 14:03:04 +0200 Subject: [PATCH 13/21] use unified offline flow on export page --- .../accounting/PolicyAccountingPage.tsx | 6 ++++++ .../xero/export/XeroBankAccountSelectPage.tsx | 3 ++- .../xero/export/XeroExportConfigurationPage.tsx | 16 ++++++---------- .../export/XeroPreferredExporterSelectPage.tsx | 3 ++- .../export/XeroPurchaseBillDateSelectPage.tsx | 3 ++- .../XeroPurchaseBillStatusSelectorPage.tsx | 3 ++- 6 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index 3c641c77b557..cb39926d75c8 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -68,6 +68,7 @@ type AccountingIntegration = { importPendingAction?: OfflineWithFeedbackProps['pendingAction']; onExportPagePress: () => void; hasExportError?: boolean; + exportPendingAction?: OfflineWithFeedbackProps['pendingAction']; onAdvancedPagePress: () => void; hasAdvancedError?: boolean; advancedPendingAction?: OfflineWithFeedbackProps['pendingAction']; @@ -135,6 +136,10 @@ function accountingIntegrationData( [CONST.XERO_CONFIG.EXPORTER, CONST.XERO_CONFIG.BILL_DATE, CONST.XERO_CONFIG.BILL_STATUS, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], policy?.connections?.xero?.config?.errorFields, ), + exportPendingAction: PolicyUtils.xeroSettingsPendingAction( + [CONST.XERO_CONFIG.EXPORTER, CONST.XERO_CONFIG.BILL_DATE, CONST.XERO_CONFIG.BILL_STATUS, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], + policy?.connections?.xero?.config?.pendingFields, + ), onCardReconciliationPagePress: () => Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_CARD_RECONCILIATION.getRoute(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO)), onAdvancedPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID)), hasAdvancedError: PolicyUtils.areXeroSettingsInErrorFields( @@ -386,6 +391,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onExportPagePress, brickRoadIndicator: integrationData?.hasExportError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + pendingAction: integrationData?.exportPendingAction, }, { icon: Expensicons.ExpensifyCard, diff --git a/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx index 533faa0975cc..b116b6f99b28 100644 --- a/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx @@ -12,6 +12,7 @@ import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {getXeroBankAccountsWithDefaultSelect} from '@libs/PolicyUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; @@ -83,7 +84,7 @@ function XeroBankAccountSelectPage({policy}: WithPolicyConnectionsProps) { title="workspace.xero.xeroBankAccount" listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} - pendingAction={config?.pendingFields?.nonReimbursableAccount} + pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT)} diff --git a/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx b/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx index f857fb3671dd..ef54074dcef2 100644 --- a/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx @@ -34,9 +34,8 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { onPress: () => { Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_PREFERRED_EXPORTER_SELECT.getRoute(policyID)); }, - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.EXPORTER], errorFields), title: exportConfiguration?.exporter ?? policyOwner, - pendingAction: pendingFields?.exporter, + subscribedSettings: [CONST.XERO_CONFIG.EXPORTER], }, { description: translate('workspace.xero.exportExpenses'), @@ -48,16 +47,14 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { { description: translate('workspace.xero.purchaseBillDate'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_PURCHASE_BILL_DATE_SELECT.getRoute(policyID)), - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.BILL_DATE], errorFields), title: exportConfiguration?.billDate ? translate(`workspace.xero.exportDate.values.${exportConfiguration.billDate}.label`) : undefined, - pendingAction: pendingFields?.billDate, + subscribedSettings: [CONST.XERO_CONFIG.BILL_DATE], }, { description: translate('workspace.xero.advancedConfig.purchaseBillStatusTitle'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_BILL_STATUS_SELECTOR.getRoute(policyID)), - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.BILL_STATUS], errorFields), title: exportConfiguration?.billStatus?.purchase ? translate(`workspace.xero.invoiceStatus.values.${exportConfiguration.billStatus.purchase}`) : undefined, - pendingAction: pendingFields?.billStatus, + subscribedSettings: [CONST.XERO_CONFIG.BILL_STATUS], }, { description: translate('workspace.xero.exportInvoices'), @@ -76,9 +73,8 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { { description: translate('workspace.xero.xeroBankAccount'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_BANK_ACCOUNT_SELECT.getRoute(policyID)), - hasError: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], errorFields), title: selectedBankAccountName, - pendingAction: pendingFields?.nonReimbursableAccount, + subscribedSettings: [CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], }, ]; @@ -98,7 +94,7 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { {menuItems.map((menuItem) => ( diff --git a/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx index 9089ecb79642..ba5570a3836a 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx @@ -11,6 +11,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import {getAdminEmployees, isExpensifyTeam} from '@libs/PolicyUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; @@ -97,7 +98,7 @@ function XeroPreferredExporterSelectPage({policy}: WithPolicyConnectionsProps) { onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID))} title="workspace.accounting.preferredExporter" connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} - pendingAction={config?.pendingFields?.exporter} + pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.EXPORTER], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.EXPORTER)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.EXPORTER)} diff --git a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx index d1217742c1b3..c9f992bc76ed 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx @@ -10,6 +10,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; @@ -67,7 +68,7 @@ function XeroPurchaseBillDateSelectPage({policy}: WithPolicyConnectionsProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID))} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} - pendingAction={config?.pendingFields?.billDate} + pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.BILL_DATE], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.BILL_DATE)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.BILL_DATE)} diff --git a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx index 39afb125c3ea..88629013da6d 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx @@ -11,6 +11,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; @@ -74,7 +75,7 @@ function XeroPurchaseBillStatusSelectorPage({policy}: WithPolicyConnectionsProps featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID))} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} - pendingAction={config?.pendingFields?.billStatus} + pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.BILL_STATUS], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.BILL_STATUS)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.BILL_STATUS)} From 73cc0c2cedb68eab473ffbbee79745c05dc45ec4 Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 22 Jul 2024 14:08:52 +0200 Subject: [PATCH 14/21] fix lint --- src/libs/PolicyUtils.ts | 8 ++++---- src/pages/workspace/accounting/PolicyAccountingPage.tsx | 1 - src/pages/workspace/accounting/xero/XeroImportPage.tsx | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 90c80af36294..a9b357c3a66a 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -9,7 +9,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import INPUT_IDS from '@src/types/form/NetSuiteCustomFieldForm'; import type {OnyxInputOrEntry, Policy, PolicyCategories, PolicyEmployeeList, PolicyTagList, PolicyTags, TaxRate} from '@src/types/onyx'; -import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +import type {ErrorFields, PendingAction, PendingFields} from '@src/types/onyx/OnyxCommon'; import type { ConnectionLastSync, ConnectionName, @@ -523,7 +523,7 @@ function getXeroBankAccountsWithDefaultSelect(policy: Policy | undefined, select function areXeroSettingsInErrorFields( settings: Array>, string>>, - errorFields?: OnyxCommon.ErrorFields, + errorFields?: ErrorFields, ) { if (errorFields === undefined) { return false; @@ -535,8 +535,8 @@ function areXeroSettingsInErrorFields( function xeroSettingsPendingAction( settings: Array>, string>>, - pendingFields?: OnyxCommon.PendingFields, -): OnyxCommon.PendingAction | undefined { + pendingFields?: PendingFields, +): PendingAction | undefined { if (pendingFields === undefined) { return null; } diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index cb39926d75c8..e2e0a40eb770 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -3,7 +3,6 @@ import React, {useEffect, useMemo, useRef, useState} from 'react'; import {ActivityIndicator, View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; -import type {Except, LiteralUnion, ValueOf} from 'type-fest'; import CollapsibleSection from '@components/CollapsibleSection'; import ConfirmModal from '@components/ConfirmModal'; import ConnectToNetSuiteButton from '@components/ConnectToNetSuiteButton'; diff --git a/src/pages/workspace/accounting/xero/XeroImportPage.tsx b/src/pages/workspace/accounting/xero/XeroImportPage.tsx index 636416e488e2..2cc9b01c2504 100644 --- a/src/pages/workspace/accounting/xero/XeroImportPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroImportPage.tsx @@ -6,7 +6,7 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; -import {getCurrentXeroOrganizationName, xeroSettingsPendingAction} from '@libs/PolicyUtils'; +import {getCurrentXeroOrganizationName} from '@libs/PolicyUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import withPolicy from '@pages/workspace/withPolicy'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; @@ -55,7 +55,7 @@ function XeroImportPage({policy}: WithPolicyProps) { subscribedSettings: [CONST.XERO_CONFIG.IMPORT_TAX_RATES], }, ], - [translate, errorFields, pendingFields, policy, importTrackingCategories, importCustomers, importTaxRates, policyID], + [translate, policy, importTrackingCategories, importCustomers, importTaxRates, policyID], ); return ( From d8f6cd9ceec8879b2f10499425ce77bf655d5855 Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 22 Jul 2024 14:20:34 +0200 Subject: [PATCH 15/21] simplify PolicyAccountingPage --- src/libs/PolicyUtils.ts | 18 ++-- .../accounting/PolicyAccountingPage.tsx | 96 +++++++++---------- 2 files changed, 50 insertions(+), 64 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index a9b357c3a66a..a48d6692bfe2 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -42,6 +42,8 @@ type ConnectionWithLastSyncData = { lastSync?: ConnectionLastSync; }; +type XeroSettings = Array>, string>>; + let allPolicies: OnyxCollection; Onyx.connect({ @@ -521,11 +523,8 @@ function getXeroBankAccountsWithDefaultSelect(policy: Policy | undefined, select })); } -function areXeroSettingsInErrorFields( - settings: Array>, string>>, - errorFields?: ErrorFields, -) { - if (errorFields === undefined) { +function areXeroSettingsInErrorFields(settings?: XeroSettings, errorFields?: ErrorFields) { + if (settings === undefined || errorFields === undefined) { return false; } @@ -533,11 +532,8 @@ function areXeroSettingsInErrorFields( return settings.some((setting) => keys.includes(setting)); } -function xeroSettingsPendingAction( - settings: Array>, string>>, - pendingFields?: PendingFields, -): PendingAction | undefined { - if (pendingFields === undefined) { +function xeroSettingsPendingAction(settings?: XeroSettings, pendingFields?: PendingFields): PendingAction | undefined { + if (settings === undefined || pendingFields === undefined) { return null; } @@ -890,4 +886,4 @@ export { xeroSettingsPendingAction, }; -export type {MemberEmailsToAccountIDs}; +export type {MemberEmailsToAccountIDs, XeroSettings}; diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index e2e0a40eb770..fe1ac2d16131 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -30,8 +30,17 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import {hasSynchronizationError, removePolicyConnection, syncConnection} from '@libs/actions/connections'; -import * as PolicyUtils from '@libs/PolicyUtils'; -import {findCurrentXeroOrganization, getCurrentSageIntacctEntityName, getCurrentXeroOrganizationName, getIntegrationLastSuccessfulDate, getXeroTenants} from '@libs/PolicyUtils'; +import { + areXeroSettingsInErrorFields, + findCurrentXeroOrganization, + getConnectedIntegration, + getCurrentSageIntacctEntityName, + getCurrentXeroOrganizationName, + getIntegrationLastSuccessfulDate, + getXeroTenants, + xeroSettingsPendingAction, +} from '@libs/PolicyUtils'; +import type {XeroSettings} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; @@ -63,14 +72,11 @@ type AccountingIntegration = { icon: IconAsset; setupConnectionButton: React.ReactNode; onImportPagePress: () => void; - hasImportError?: boolean; - importPendingAction?: OfflineWithFeedbackProps['pendingAction']; + subscribedImportSettings?: XeroSettings; onExportPagePress: () => void; - hasExportError?: boolean; - exportPendingAction?: OfflineWithFeedbackProps['pendingAction']; + subscribedExportSettings?: XeroSettings; onAdvancedPagePress: () => void; - hasAdvancedError?: boolean; - advancedPendingAction?: OfflineWithFeedbackProps['pendingAction']; + subscribedAdvancedSettings?: XeroSettings; onCardReconciliationPagePress: () => void; }; function accountingIntegrationData( @@ -110,45 +116,23 @@ function accountingIntegrationData( /> ), onImportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_IMPORT.getRoute(policyID)), - hasImportError: PolicyUtils.areXeroSettingsInErrorFields( - [ - CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES, - CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, - CONST.XERO_CONFIG.IMPORT_CUSTOMERS, - CONST.XERO_CONFIG.IMPORT_TAX_RATES, - ...getTrackingCategories(policy).map((category) => `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${category.id}`), - ], - policy?.connections?.xero?.config?.errorFields, - ), - importPendingAction: PolicyUtils.xeroSettingsPendingAction( - [ - CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES, - CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, - CONST.XERO_CONFIG.IMPORT_CUSTOMERS, - CONST.XERO_CONFIG.IMPORT_TAX_RATES, - ...getTrackingCategories(policy).map((category) => `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${category.id}`), - ], - policy?.connections?.xero?.config?.pendingFields, - ), + subscribedImportSettings: [ + CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES, + CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, + CONST.XERO_CONFIG.IMPORT_CUSTOMERS, + CONST.XERO_CONFIG.IMPORT_TAX_RATES, + ...getTrackingCategories(policy).map((category) => `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${category.id}`), + ], onExportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID)), - hasExportError: PolicyUtils.areXeroSettingsInErrorFields( - [CONST.XERO_CONFIG.EXPORTER, CONST.XERO_CONFIG.BILL_DATE, CONST.XERO_CONFIG.BILL_STATUS, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], - policy?.connections?.xero?.config?.errorFields, - ), - exportPendingAction: PolicyUtils.xeroSettingsPendingAction( - [CONST.XERO_CONFIG.EXPORTER, CONST.XERO_CONFIG.BILL_DATE, CONST.XERO_CONFIG.BILL_STATUS, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], - policy?.connections?.xero?.config?.pendingFields, - ), + subscribedExportSettings: [CONST.XERO_CONFIG.EXPORTER, CONST.XERO_CONFIG.BILL_DATE, CONST.XERO_CONFIG.BILL_STATUS, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], onCardReconciliationPagePress: () => Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_CARD_RECONCILIATION.getRoute(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO)), onAdvancedPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID)), - hasAdvancedError: PolicyUtils.areXeroSettingsInErrorFields( - [CONST.XERO_CONFIG.ENABLED, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], - policy?.connections?.xero?.config?.errorFields, - ), - advancedPendingAction: PolicyUtils.xeroSettingsPendingAction( - [CONST.XERO_CONFIG.ENABLED, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], - policy?.connections?.xero?.config?.pendingFields, - ), + subscribedAdvancedSettings: [ + CONST.XERO_CONFIG.ENABLED, + CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS, + CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID, + CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID, + ], }; case CONST.POLICY.CONNECTIONS.NAME.NETSUITE: return { @@ -212,7 +196,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { !((name === CONST.POLICY.CONNECTIONS.NAME.NETSUITE && !canUseNetSuiteIntegration) || (name === CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT && !canUseSageIntacctIntegration)), ); - const connectedIntegration = PolicyUtils.getConnectedIntegration(policy, accountingIntegrations) ?? connectionSyncProgress?.connectionName; + const connectedIntegration = getConnectedIntegration(policy, accountingIntegrations) ?? connectionSyncProgress?.connectionName; const policyID = policy?.id ?? '-1'; const successfulDate = getIntegrationLastSuccessfulDate(connectedIntegration ? policy?.connections?.[connectedIntegration] : undefined); @@ -264,8 +248,8 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { } Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_ORGANIZATION.getRoute(policyID, currentXeroOrganization?.id ?? '-1')); }, - pendingAction: PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.TENANT_ID], policy?.connections?.xero?.config?.pendingFields), - brickRoadIndicator: PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.TENANT_ID], policy?.connections?.xero?.config?.errorFields) + pendingAction: xeroSettingsPendingAction([CONST.XERO_CONFIG.TENANT_ID], policy?.connections?.xero?.config?.pendingFields), + brickRoadIndicator: areXeroSettingsInErrorFields([CONST.XERO_CONFIG.TENANT_ID], policy?.connections?.xero?.config?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }; @@ -379,8 +363,10 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { title: translate('workspace.accounting.import'), wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onImportPagePress, - brickRoadIndicator: integrationData?.hasImportError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - pendingAction: integrationData?.importPendingAction, + brickRoadIndicator: areXeroSettingsInErrorFields(integrationData?.subscribedImportSettings, policy?.connections?.xero?.config?.errorFields) + ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR + : undefined, + pendingAction: xeroSettingsPendingAction(integrationData?.subscribedImportSettings, policy?.connections?.xero?.config?.pendingFields), }, { icon: Expensicons.Send, @@ -389,8 +375,10 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { title: translate('workspace.accounting.export'), wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onExportPagePress, - brickRoadIndicator: integrationData?.hasExportError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - pendingAction: integrationData?.exportPendingAction, + brickRoadIndicator: areXeroSettingsInErrorFields(integrationData?.subscribedExportSettings, policy?.connections?.xero?.config?.errorFields) + ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR + : undefined, + pendingAction: xeroSettingsPendingAction(integrationData?.subscribedExportSettings, policy?.connections?.xero?.config?.pendingFields), }, { icon: Expensicons.ExpensifyCard, @@ -408,8 +396,10 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { title: translate('workspace.accounting.advanced'), wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onAdvancedPagePress, - brickRoadIndicator: integrationData?.hasAdvancedError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - pendingAction: integrationData?.advancedPendingAction, + brickRoadIndicator: areXeroSettingsInErrorFields(integrationData?.subscribedAdvancedSettings, policy?.connections?.xero?.config?.errorFields) + ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR + : undefined, + pendingAction: xeroSettingsPendingAction(integrationData?.subscribedAdvancedSettings, policy?.connections?.xero?.config?.pendingFields), }, ]), ]; From b6bda6615e53b91edeaea31108b708edcec86283 Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 22 Jul 2024 14:23:09 +0200 Subject: [PATCH 16/21] revert retries --- src/CONST.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CONST.ts b/src/CONST.ts index 7ddcc13e02be..14b1de44952d 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1072,7 +1072,7 @@ const CONST = { PROCESS_REQUEST_DELAY_MS: 1000, MAX_PENDING_TIME_MS: 10 * 1000, RECHECK_INTERVAL_MS: 60 * 1000, - MAX_REQUEST_RETRIES: 0, + MAX_REQUEST_RETRIES: 10, NETWORK_STATUS: { ONLINE: 'online', OFFLINE: 'offline', From e880a1ddc4e52a7603f6dd22a5c9c8e7a0114693 Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 22 Jul 2024 16:43:24 +0200 Subject: [PATCH 17/21] use default tracking categories options value --- .../accounting/xero/XeroTrackingCategoryConfigurationPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx index 29dacc36b23d..31564997460b 100644 --- a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx @@ -32,7 +32,7 @@ function XeroTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { id: category.id, description: translate('workspace.xero.mapTrackingCategoryTo', {categoryName: category.name}) as TranslationPaths, onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_TRACKING_CATEGORIES_MAP.getRoute(policyID, category.id, category.name)), - title: translate(`workspace.xero.trackingCategoriesOptions.${category.value.toLowerCase()}` as TranslationPaths), + title: translate(`workspace.xero.trackingCategoriesOptions.${!!category.value ? category.value.toLowerCase() : 'default'}` as TranslationPaths), })); }, [translate, policy, policyID]); From 147dea1bc0f0377eed36b9b7378dc35320c82c99 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 23 Jul 2024 12:26:51 +0200 Subject: [PATCH 18/21] fix lint error --- .../accounting/xero/XeroTrackingCategoryConfigurationPage.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx index 31564997460b..7ac4a3b0d51d 100644 --- a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx @@ -10,6 +10,7 @@ import {getTrackingCategories} from '@libs/actions/connections/ConnectToXero'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {areXeroSettingsInErrorFields, xeroSettingsPendingAction} from '@libs/PolicyUtils'; +import StringUtils from '@libs/StringUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -32,7 +33,7 @@ function XeroTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { id: category.id, description: translate('workspace.xero.mapTrackingCategoryTo', {categoryName: category.name}) as TranslationPaths, onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_TRACKING_CATEGORIES_MAP.getRoute(policyID, category.id, category.name)), - title: translate(`workspace.xero.trackingCategoriesOptions.${!!category.value ? category.value.toLowerCase() : 'default'}` as TranslationPaths), + title: translate(`workspace.xero.trackingCategoriesOptions.${!StringUtils.isEmptyString(category.value) ? category.value.toLowerCase() : 'default'}` as TranslationPaths), })); }, [translate, policy, policyID]); From 0d194568adc66372982c453c0a87f2baa88b387c Mon Sep 17 00:00:00 2001 From: war-in Date: Wed, 24 Jul 2024 14:51:09 +0200 Subject: [PATCH 19/21] set `pendingFields` to `null` after failed request --- src/libs/actions/connections/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/connections/index.ts b/src/libs/actions/connections/index.ts index b186b26b5829..166363b91acf 100644 --- a/src/libs/actions/connections/index.ts +++ b/src/libs/actions/connections/index.ts @@ -101,7 +101,7 @@ function updatePolicyConnectionConfig Date: Thu, 25 Jul 2024 13:05:05 +0200 Subject: [PATCH 20/21] do not change original `updatePolicyConnectionConfig` --- src/libs/actions/connections/index.ts | 94 ++++++++++++++++++- ...roMapTrackingCategoryConfigurationPage.tsx | 2 +- .../xero/XeroTaxesConfigurationPage.tsx | 2 +- .../XeroTrackingCategoryConfigurationPage.tsx | 2 +- .../xero/advanced/XeroAdvancedPage.tsx | 4 +- .../XeroBillPaymentAccountSelectorPage.tsx | 2 +- .../XeroInvoiceAccountSelectorPage.tsx | 2 +- .../xero/export/XeroBankAccountSelectPage.tsx | 2 +- .../XeroPreferredExporterSelectPage.tsx | 2 +- .../export/XeroPurchaseBillDateSelectPage.tsx | 2 +- .../XeroPurchaseBillStatusSelectorPage.tsx | 2 +- .../xero/import/XeroChartOfAccountsPage.tsx | 2 +- .../import/XeroCustomerConfigurationPage.tsx | 2 +- 13 files changed, 105 insertions(+), 15 deletions(-) diff --git a/src/libs/actions/connections/index.ts b/src/libs/actions/connections/index.ts index 166363b91acf..01dca61cdfe9 100644 --- a/src/libs/actions/connections/index.ts +++ b/src/libs/actions/connections/index.ts @@ -68,7 +68,7 @@ function createErrorFields( +function updatePolicyXeroConnectionConfig( policyID: string, connectionName: TConnectionName, settingName: TSettingName, @@ -138,6 +138,88 @@ function updatePolicyConnectionConfig( + policyID: string, + connectionName: TConnectionName, + settingName: TSettingName, + settingValue: Partial, +) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [connectionName]: { + config: { + [settingName]: settingValue ?? null, + pendingFields: { + [settingName]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + }, + errorFields: { + [settingName]: null, + }, + }, + }, + }, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [connectionName]: { + config: { + [settingName]: settingValue ?? null, + pendingFields: { + [settingName]: null, + }, + errorFields: { + [settingName]: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + }, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [connectionName]: { + config: { + [settingName]: settingValue ?? null, + pendingFields: { + [settingName]: null, + }, + errorFields: { + [settingName]: null, + }, + }, + }, + }, + }, + }, + ]; + + const parameters: UpdatePolicyConnectionConfigParams = { + policyID, + connectionName, + settingName: String(settingName), + settingValue: JSON.stringify(settingValue), + idempotencyKey: String(settingName), + }; + API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); +} + /** * This method returns read command and stage in progres for a given accounting integration. * @@ -324,4 +406,12 @@ function copyExistingPolicyConnection(connectedPolicyID: string, targetPolicyID: ); } -export {removePolicyConnection, updatePolicyConnectionConfig, updateManyPolicyConnectionConfigs, hasSynchronizationError, syncConnection, copyExistingPolicyConnection}; +export { + removePolicyConnection, + updatePolicyConnectionConfig, + updatePolicyXeroConnectionConfig, + updateManyPolicyConnectionConfigs, + hasSynchronizationError, + syncConnection, + copyExistingPolicyConnection, +}; diff --git a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx index 4a0ab1e54434..3d662289d0d8 100644 --- a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx @@ -62,7 +62,7 @@ function XeroMapTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { const updateMapping = useCallback( (option: {value: string}) => { if (option.value !== categoryName) { - Connections.updatePolicyConnectionConfig( + Connections.updatePolicyXeroConnectionConfig( policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.MAPPINGS, diff --git a/src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx index 553541bcb25f..e5133a25dc76 100644 --- a/src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx @@ -33,7 +33,7 @@ function XeroTaxesConfigurationPage({policy}: WithPolicyProps) { title={translate('workspace.accounting.import')} switchAccessibilityLabel={translate('workspace.xero.customers')} isActive={isSwitchOn} - onToggle={() => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.IMPORT_TAX_RATES, !xeroConfig?.importTaxRates)} + onToggle={() => Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.IMPORT_TAX_RATES, !xeroConfig?.importTaxRates)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.IMPORT_TAX_RATES)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.IMPORT_TAX_RATES)} pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.IMPORT_TAX_RATES], xeroConfig?.pendingFields)} diff --git a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx index 7ac4a3b0d51d..916331763703 100644 --- a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx @@ -54,7 +54,7 @@ function XeroTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { isActive={isSwitchOn} wrapperStyle={styles.mv3} onToggle={() => - Connections.updatePolicyConnectionConfig( + Connections.updatePolicyXeroConnectionConfig( policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, diff --git a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx index 52f0c39b8e14..7b5aa44d62e2 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx @@ -59,7 +59,7 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { wrapperStyle={styles.mv3} isActive={!!autoSync?.enabled} onToggle={() => - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.AUTO_SYNC, { + Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.AUTO_SYNC, { enabled: !autoSync?.enabled, }) } @@ -76,7 +76,7 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { wrapperStyle={styles.mv3} isActive={!!sync?.syncReimbursedReports} onToggle={() => - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.SYNC, { + Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.SYNC, { syncReimbursedReports: !sync?.syncReimbursedReports, }) } diff --git a/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx index 98144a4488e1..66ce4ca04e83 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx @@ -42,7 +42,7 @@ function XeroBillPaymentAccountSelectorPage({policy}: WithPolicyConnectionsProps const updateAccount = useCallback( ({value}: SelectorType) => { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.SYNC, { + Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.SYNC, { reimbursementAccountID: value, }); Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID)); diff --git a/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx index 150b03d295a8..01f32f7f8859 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx @@ -42,7 +42,7 @@ function XeroInvoiceAccountSelectorPage({policy}: WithPolicyConnectionsProps) { const updateAccount = useCallback( ({value}: SelectorType) => { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.SYNC, { + Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.SYNC, { invoiceCollectionsAccountID: value, }); Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID)); diff --git a/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx index b116b6f99b28..0ad5bfcfbd6b 100644 --- a/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx @@ -46,7 +46,7 @@ function XeroBankAccountSelectPage({policy}: WithPolicyConnectionsProps) { const updateBankAccount = useCallback( ({value}: SelectorType) => { if (initiallyFocusedOptionKey !== value) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, { + Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, { nonReimbursableAccount: value, }); } diff --git a/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx index ba5570a3836a..f8f6fa3828a3 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx @@ -67,7 +67,7 @@ function XeroPreferredExporterSelectPage({policy}: WithPolicyConnectionsProps) { const selectExporter = useCallback( (row: CardListItem) => { if (row.value !== config?.export?.exporter) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, {exporter: row.value}); + Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, {exporter: row.value}); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID)); }, diff --git a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx index c9f992bc76ed..16ca7a4bba6d 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx @@ -47,7 +47,7 @@ function XeroPurchaseBillDateSelectPage({policy}: WithPolicyConnectionsProps) { const selectExportDate = useCallback( (row: MenuListItem) => { if (row.value !== config?.export?.billDate) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, {billDate: row.value}); + Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, {billDate: row.value}); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_PURCHASE_BILL_DATE_SELECT.getRoute(policyID)); }, diff --git a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx index 88629013da6d..5e7d06a9ca39 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx @@ -52,7 +52,7 @@ function XeroPurchaseBillStatusSelectorPage({policy}: WithPolicyConnectionsProps return; } if (row.value !== invoiceStatus) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, { + Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, { billStatus: {...config?.export?.billStatus, purchase: row.value}, }); } diff --git a/src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx b/src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx index d0f8fa2ee3e0..588e1805b010 100644 --- a/src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx +++ b/src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx @@ -60,7 +60,7 @@ function XeroChartOfAccountsPage({policy}: WithPolicyProps) { shouldPlaceSubtitleBelowSwitch isActive={!!xeroConfig?.enableNewCategories} onToggle={() => - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES, !xeroConfig?.enableNewCategories) + Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES, !xeroConfig?.enableNewCategories) } pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES], xeroConfig?.pendingFields)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES)} diff --git a/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx b/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx index fd8bf3515050..b94f51eb050a 100644 --- a/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx @@ -42,7 +42,7 @@ function XeroCustomerConfigurationPage({policy}: WithPolicyProps) { /> } isActive={isSwitchOn} - onToggle={() => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.IMPORT_CUSTOMERS, !xeroConfig?.importCustomers)} + onToggle={() => Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.IMPORT_CUSTOMERS, !xeroConfig?.importCustomers)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.IMPORT_CUSTOMERS)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.IMPORT_CUSTOMERS)} pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.IMPORT_CUSTOMERS], xeroConfig?.pendingFields)} From 4e41702aff9e6d3186605198b0f6084be0d61228 Mon Sep 17 00:00:00 2001 From: war-in Date: Thu, 25 Jul 2024 13:07:11 +0200 Subject: [PATCH 21/21] do not change original `updatePolicyConnectionConfig` --- .../accounting/xero/XeroOrganizationConfigurationPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx index 288988d86822..1a0f92f4cbbf 100644 --- a/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx @@ -9,7 +9,7 @@ import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import {updatePolicyConnectionConfig} from '@libs/actions/connections'; +import {updatePolicyXeroConnectionConfig} from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; @@ -59,7 +59,7 @@ function XeroOrganizationConfigurationPage({ return; } - updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.TENANT_ID, keyForList); + updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.TENANT_ID, keyForList); Navigation.goBack(); };