From a04d6e670340e63c280fedbb26b6c7a2233c644a Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 18 Jun 2024 18:01:29 +0200 Subject: [PATCH 01/30] add basic advanced page --- src/CONST.ts | 1 + src/ROUTES.ts | 4 + src/SCREENS.ts | 1 + src/languages/en.ts | 24 ++++ .../ModalStackNavigators/index.tsx | 1 + .../FULL_SCREEN_TO_RHP_MAPPING.ts | 1 + src/libs/Navigation/linkingConfig/config.ts | 1 + src/libs/Navigation/types.ts | 3 + .../accounting/PolicyAccountingPage.tsx | 15 +++ .../export/SageIntacctAdvancedPage.tsx | 108 ++++++++++++++++++ 10 files changed, 159 insertions(+) create mode 100644 src/pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage.tsx diff --git a/src/CONST.ts b/src/CONST.ts index 9311816c38a2..d4963292cb28 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1796,6 +1796,7 @@ const CONST = { // Here we will add other connections names when we add support for them QBO: 'quickbooksOnline', XERO: 'xero', + SAGE_INTACCT: 'intacct', }, SYNC_STAGE_NAME: { STARTING_IMPORT_QBO: 'startingImportQBO', diff --git a/src/ROUTES.ts b/src/ROUTES.ts index c1fdd68951fa..19dc400e5cd5 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -908,6 +908,10 @@ const ROUTES = { route: 'settings/workspaces/:policyID/accounting/quickbooks-online/import/taxes', getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/quickbooks-online/import/taxes` as const, }, + POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED: { + route: 'settings/workspaces/:policyID/accounting/sage-intacct/advanced', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/sage-intacct/advanced` as const, + }, } as const; /** diff --git a/src/SCREENS.ts b/src/SCREENS.ts index f884cca94ef5..541399bc0c89 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -263,6 +263,7 @@ const SCREENS = { XERO_EXPORT_PREFERRED_EXPORTER_SELECT: 'Workspace_Accounting_Xero_Export_Preferred_Exporter_Select', XERO_BILL_PAYMENT_ACCOUNT_SELECTOR: 'Policy_Accounting_Xero_Bill_Payment_Account_Selector', XERO_EXPORT_BANK_ACCOUNT_SELECT: 'Policy_Accounting_Xero_Export_Bank_Account_Select', + SAGE_INTACCT_ADVANCED: 'Policy_Accounting_Sage_Intacct_Advanced', }, INITIAL: 'Workspace_Initial', PROFILE: 'Workspace_Profile', diff --git a/src/languages/en.ts b/src/languages/en.ts index bf3803c7606d..25be5fd88361 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2172,6 +2172,17 @@ export default { noAccountsFound: 'No accounts found', noAccountsFoundDescription: 'Add the account in Xero and sync the connection again.', }, + sageIntacct: { + autoSync: 'Auto-sync', + autoSyncDescription: 'Sync Sage Intacct and Expensify automatically, every day.', + inviteEmployees: 'Invite employees', + inviteEmployeesDescription: + 'Import Sage Intacct employee records and invite employees to this workspace. Your approval workflow will default to manager approval and can be furthered configured on the Members page.', + syncReimbursedReports: 'Sync reimbursed reports', + syncReimbursedReportsDescription: 'When a report is reimbursed using Expensify ACH, the corresponding puchase bill will be created in the Sage Intacct account below.', + paymentAccount: 'Sage Intacct payment account', + notConfigured: 'Not configured', + }, type: { free: 'Free', control: 'Control', @@ -2392,6 +2403,19 @@ export default { subtitle: 'Connect to your accounting system to code transactions with your chart of accounts, auto-match payments, and keep your finances in sync.', qbo: 'Quickbooks Online', xero: 'Xero', + intacct: 'Sage Intacct', + integrationName: (integration?: ConnectionName): string => { + switch (integration) { + case CONST.POLICY.CONNECTIONS.NAME.QBO: + return 'Quickbooks Online'; + case CONST.POLICY.CONNECTIONS.NAME.XERO: + return 'Xero'; + case CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT: + return 'Sage Intacct'; + default: + return 'Integration'; + } + }, setup: 'Connect', lastSync: 'Last synced just now', import: 'Import', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 0577fdcfc5aa..c65f1c321d94 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -317,6 +317,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage').default as React.ComponentType, + [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_ADVANCED]: () => require('@pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage').default as React.ComponentType, [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY]: () => require('../../../../pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage').default as React.ComponentType, [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET]: () => require('../../../../pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage').default as React.ComponentType, diff --git a/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts b/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts index f91d290639ff..bebb6435e157 100755 --- a/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts +++ b/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts @@ -54,6 +54,7 @@ const FULL_SCREEN_TO_RHP_MAPPING: Partial> = { SCREENS.WORKSPACE.ACCOUNTING.XERO_EXPORT_PREFERRED_EXPORTER_SELECT, SCREENS.WORKSPACE.ACCOUNTING.XERO_BILL_PAYMENT_ACCOUNT_SELECTOR, SCREENS.WORKSPACE.ACCOUNTING.XERO_EXPORT_BANK_ACCOUNT_SELECT, + SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_ADVANCED, ], [SCREENS.WORKSPACE.TAXES]: [ SCREENS.WORKSPACE.TAXES_SETTINGS, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 1b4288a9b3a9..76dfa397a30d 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -337,6 +337,7 @@ const config: LinkingOptions['config'] = { [SCREENS.WORKSPACE.ACCOUNTING.XERO_INVOICE_ACCOUNT_SELECTOR]: {path: ROUTES.POLICY_ACCOUNTING_XERO_INVOICE_SELECTOR.route}, [SCREENS.WORKSPACE.ACCOUNTING.XERO_EXPORT_PREFERRED_EXPORTER_SELECT]: {path: ROUTES.POLICY_ACCOUNTING_XERO_PREFERRED_EXPORTER_SELECT.route}, [SCREENS.WORKSPACE.ACCOUNTING.XERO_BILL_PAYMENT_ACCOUNT_SELECTOR]: {path: ROUTES.POLICY_ACCOUNTING_XERO_BILL_PAYMENT_ACCOUNT_SELECTOR.route}, + [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_ADVANCED]: {path: ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.route}, [SCREENS.WORKSPACE.DESCRIPTION]: { path: ROUTES.WORKSPACE_PROFILE_DESCRIPTION.route, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index f90a91fe0f19..991db0535b7e 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -385,6 +385,9 @@ type SettingsNavigatorParamList = { [SCREENS.WORKSPACE.ACCOUNTING.XERO_BILL_PAYMENT_ACCOUNT_SELECTOR]: { policyID: string; }; + [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_ADVANCED]: { + policyID: string; + }; [SCREENS.GET_ASSISTANCE]: { backTo: Routes; }; diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index 78dc434b3d2c..9d5b61baa68d 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -100,6 +100,21 @@ function accountingIntegrationData( onExportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID)), onAdvancedPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID)), }; + case CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT: + return { + title: translate('workspace.accounting.intacct'), + icon: Expensicons.XeroSquare, + setupConnectionButton: ( + + ), + onImportPagePress: () => {}, + onExportPagePress: () => {}, + onAdvancedPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID)), + }; default: return undefined; } diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage.tsx new file mode 100644 index 000000000000..11e773afb152 --- /dev/null +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage.tsx @@ -0,0 +1,108 @@ +import React, {useMemo} from 'react'; +import ConnectionLayout from '@components/ConnectionLayout'; +import MenuItem from '@components/MenuItem'; +import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import withPolicy, {WithPolicyProps} from '@pages/workspace/withPolicy'; +import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; +import CONST from '@src/CONST'; + +function SageIntacctAdvancedPage({policy}: WithPolicyProps) { + const {translate} = useLocalize(); + const policyID = policy?.id ?? '-1'; + const styles = useThemeStyles(); + + const {syncReimbursedReports, reimbursementAccountID} = policy?.connections?.intacct?.config?.sync ?? {}; + const {autoSync, pendingFields, errorFields, credentials} = policy?.connections?.intacct?.config ?? {}; + + const currentSageIntacctOrganizationName = credentials?.companyID; + + const toggleSections = useMemo( + () => [ + { + label: translate('workspace.sageIntacct.autoSync'), + value: !!autoSync, + onToggle: () => {}, + pendingAction: pendingFields?.autoSync, + error: errorFields?.autoSync, + description: translate('workspace.sageIntacct.autoSyncDescription'), + }, + { + label: translate('workspace.sageIntacct.inviteEmployees'), + value: !!pendingFields?.importEmployees, + onToggle: () => {}, + pendingAction: pendingFields?.importEmployees, + error: errorFields?.importEmployees, + description: translate('workspace.sageIntacct.inviteEmployeesDescription'), + }, + { + label: translate('workspace.sageIntacct.syncReimbursedReports'), + value: !!syncReimbursedReports, + onToggle: () => {}, + pendingAction: pendingFields?.sync?.syncReimbursedReports, + error: errorFields?.sync?.syncReimbursedReports, + description: translate('workspace.sageIntacct.syncReimbursedReportsDescription'), + }, + ], + [ + autoSync, + errorFields?.autoSync, + errorFields?.importEmployees, + errorFields?.sync?.syncReimbursedReports, + pendingFields?.autoSync, + pendingFields?.importEmployees, + pendingFields?.sync?.syncReimbursedReports, + syncReimbursedReports, + translate, + ], + ); + + return ( + + {toggleSections.map((section) => ( + + {}} + wrapperStyle={[styles.ph5, styles.pv5]} + /> + + ))} + + + {}} + brickRoadIndicator={errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} + /> + + + ); +} + +SageIntacctAdvancedPage.displayName = 'PolicySageIntacctAdvancedPage'; + +export default withPolicy(SageIntacctAdvancedPage); From 5ddc8d1ae3af135103477c44782c5ca0d888a633 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 18 Jun 2024 18:27:28 +0200 Subject: [PATCH 02/30] add functionalities to toggles --- src/CONST.ts | 6 +++++ .../export/SageIntacctAdvancedPage.tsx | 22 ++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index d4963292cb28..4f0d87de2f7f 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1343,6 +1343,12 @@ const CONST = { }, }, + SAGE_INTACCT: { + APPROVAL_MODE: { + MANUAL: 'MANUAL', + }, + }, + QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE: { VENDOR_BILL: 'bill', CHECK: 'check', diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage.tsx index 11e773afb152..9d5559dffc32 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage.tsx @@ -4,7 +4,9 @@ import MenuItem from '@components/MenuItem'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import withPolicy, {WithPolicyProps} from '@pages/workspace/withPolicy'; +import * as Connections from '@libs/actions/connections'; +import type {WithPolicyProps} from '@pages/workspace/withPolicy'; +import withPolicy from '@pages/workspace/withPolicy'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; import CONST from '@src/CONST'; @@ -23,26 +25,32 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { { label: translate('workspace.sageIntacct.autoSync'), value: !!autoSync, - onToggle: () => {}, + onToggle: (enabled: boolean) => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'autoSync', {enabled: enabled}), pendingAction: pendingFields?.autoSync, error: errorFields?.autoSync, description: translate('workspace.sageIntacct.autoSyncDescription'), + isActive: policy?.connections?.intacct?.config?.autoSync?.enabled, }, { label: translate('workspace.sageIntacct.inviteEmployees'), value: !!pendingFields?.importEmployees, - onToggle: () => {}, + onToggle: (enabled) => { + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'importEmployees', enabled); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'approvalMode', enabled ? CONST.SAGE_INTACCT.APPROVAL_MODE.MANUAL : null); + }, pendingAction: pendingFields?.importEmployees, error: errorFields?.importEmployees, description: translate('workspace.sageIntacct.inviteEmployeesDescription'), + isActive: policy?.connections?.intacct?.config?.importEmployees, }, { label: translate('workspace.sageIntacct.syncReimbursedReports'), value: !!syncReimbursedReports, - onToggle: () => {}, + onToggle: (enabled) => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'sync', {syncReimbursedReports: enabled}), pendingAction: pendingFields?.sync?.syncReimbursedReports, error: errorFields?.sync?.syncReimbursedReports, description: translate('workspace.sageIntacct.syncReimbursedReportsDescription'), + isActive: syncReimbursedReports, }, ], [ @@ -53,6 +61,8 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { pendingFields?.autoSync, pendingFields?.importEmployees, pendingFields?.sync?.syncReimbursedReports, + policy?.connections?.intacct?.config?.autoSync?.enabled, + policyID, syncReimbursedReports, translate, ], @@ -80,8 +90,8 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { subtitle={section.description} shouldPlaceSubtitleBelowSwitch switchAccessibilityLabel={section.label} - isActive={true} - onToggle={() => {}} + isActive={section.isActive} + onToggle={section.onToggle} wrapperStyle={[styles.ph5, styles.pv5]} /> From 1f5c544612d05c062f868e1cb2c064d0c7e70d34 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 18 Jun 2024 18:54:16 +0200 Subject: [PATCH 03/30] add payment account page --- src/ROUTES.ts | 4 + src/SCREENS.ts | 1 + src/languages/en.ts | 1 + .../ModalStackNavigators/index.tsx | 3 +- .../FULL_SCREEN_TO_RHP_MAPPING.ts | 1 + src/libs/Navigation/linkingConfig/config.ts | 1 + src/libs/Navigation/types.ts | 3 + src/libs/PolicyUtils.ts | 14 ++++ .../SageIntacctAdvancedPage.tsx | 8 +- .../SageIntacctPaymentAccountPage.tsx | 83 +++++++++++++++++++ 10 files changed, 116 insertions(+), 3 deletions(-) rename src/pages/workspace/accounting/intacct/{export => advanced}/SageIntacctAdvancedPage.tsx (91%) create mode 100644 src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 19dc400e5cd5..fb017759c568 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -912,6 +912,10 @@ const ROUTES = { route: 'settings/workspaces/:policyID/accounting/sage-intacct/advanced', getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/sage-intacct/advanced` as const, }, + POLICY_ACCOUNTING_SAGE_INTACCT_PAYMENT_ACCOUNT: { + route: 'settings/workspaces/:policyID/accounting/sage-intacct/advanced/payment-account', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/sage-intacct/advanced/payment-account` as const, + }, } as const; /** diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 541399bc0c89..b733b844b9f4 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -264,6 +264,7 @@ const SCREENS = { XERO_BILL_PAYMENT_ACCOUNT_SELECTOR: 'Policy_Accounting_Xero_Bill_Payment_Account_Selector', XERO_EXPORT_BANK_ACCOUNT_SELECT: 'Policy_Accounting_Xero_Export_Bank_Account_Select', SAGE_INTACCT_ADVANCED: 'Policy_Accounting_Sage_Intacct_Advanced', + SAGE_INTACCT_PAYMENT_ACCOUNT: 'Policy_Accounting_Sage_Intacct_Payment_Account', }, INITIAL: 'Workspace_Initial', PROFILE: 'Workspace_Profile', diff --git a/src/languages/en.ts b/src/languages/en.ts index 25be5fd88361..e594ffd8f94e 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2182,6 +2182,7 @@ export default { syncReimbursedReportsDescription: 'When a report is reimbursed using Expensify ACH, the corresponding puchase bill will be created in the Sage Intacct account below.', paymentAccount: 'Sage Intacct payment account', notConfigured: 'Not configured', + paymentAccountDescription: 'Some desc', }, type: { free: 'Free', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index c65f1c321d94..69d8c9cc9122 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -317,7 +317,8 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage').default as React.ComponentType, - [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_ADVANCED]: () => require('@pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage').default as React.ComponentType, + [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_ADVANCED]: () => require('@pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage').default as React.ComponentType, + [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_PAYMENT_ACCOUNT]: () => require('@pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage').default as React.ComponentType, [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY]: () => require('../../../../pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage').default as React.ComponentType, [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET]: () => require('../../../../pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage').default as React.ComponentType, diff --git a/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts b/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts index bebb6435e157..55d4e5a755d3 100755 --- a/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts +++ b/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts @@ -55,6 +55,7 @@ const FULL_SCREEN_TO_RHP_MAPPING: Partial> = { SCREENS.WORKSPACE.ACCOUNTING.XERO_BILL_PAYMENT_ACCOUNT_SELECTOR, SCREENS.WORKSPACE.ACCOUNTING.XERO_EXPORT_BANK_ACCOUNT_SELECT, SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_ADVANCED, + SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_PAYMENT_ACCOUNT, ], [SCREENS.WORKSPACE.TAXES]: [ SCREENS.WORKSPACE.TAXES_SETTINGS, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 76dfa397a30d..c3d2afc57ff6 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -338,6 +338,7 @@ const config: LinkingOptions['config'] = { [SCREENS.WORKSPACE.ACCOUNTING.XERO_EXPORT_PREFERRED_EXPORTER_SELECT]: {path: ROUTES.POLICY_ACCOUNTING_XERO_PREFERRED_EXPORTER_SELECT.route}, [SCREENS.WORKSPACE.ACCOUNTING.XERO_BILL_PAYMENT_ACCOUNT_SELECTOR]: {path: ROUTES.POLICY_ACCOUNTING_XERO_BILL_PAYMENT_ACCOUNT_SELECTOR.route}, [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_ADVANCED]: {path: ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.route}, + [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_PAYMENT_ACCOUNT]: {path: ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_PAYMENT_ACCOUNT.route}, [SCREENS.WORKSPACE.DESCRIPTION]: { path: ROUTES.WORKSPACE_PROFILE_DESCRIPTION.route, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 991db0535b7e..887cbfb86934 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -388,6 +388,9 @@ type SettingsNavigatorParamList = { [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_ADVANCED]: { policyID: string; }; + [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_PAYMENT_ACCOUNT]: { + policyID: string; + }; [SCREENS.GET_ASSISTANCE]: { backTo: Routes; }; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index af3f3b264d13..1464937810ad 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -403,6 +403,19 @@ function getAdminEmployees(policy: OnyxEntry): PolicyEmployee[] { return Object.values(policy?.employeeList ?? {}).filter((employee) => employee.role === CONST.POLICY.ROLE.ADMIN); } +function getSageIntacctBankAccounts(policy: Policy | undefined, selectedVendorId: string | undefined): SelectorType[] { + const vendors = policy?.connections?.intacct?.data?.bankAccounts ?? []; + + const isMatchFound = vendors?.some(({id}) => id === selectedVendorId); + + return (vendors ?? []).map(({id, name}) => ({ + value: id, + text: name, + keyForList: id, + isSelected: isMatchFound && selectedVendorId === id, + })); +} + /** * Returns the policy of the report */ @@ -546,6 +559,7 @@ export { findCurrentXeroOrganization, getCurrentXeroOrganizationName, getXeroBankAccountsWithDefaultSelect, + getSageIntacctBankAccounts, getCustomUnit, getCustomUnitRate, sortWorkspacesBySelected, diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx similarity index 91% rename from src/pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage.tsx rename to src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 9d5559dffc32..c6d225c58f30 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -5,10 +5,12 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; +import Navigation from '@navigation/Navigation'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicy from '@pages/workspace/withPolicy'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; function SageIntacctAdvancedPage({policy}: WithPolicyProps) { const {translate} = useLocalize(); @@ -17,6 +19,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { const {syncReimbursedReports, reimbursementAccountID} = policy?.connections?.intacct?.config?.sync ?? {}; const {autoSync, pendingFields, errorFields, credentials} = policy?.connections?.intacct?.config ?? {}; + const {data} = policy?.connections?.intacct ?? {}; const currentSageIntacctOrganizationName = credentials?.companyID; @@ -62,6 +65,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { pendingFields?.importEmployees, pendingFields?.sync?.syncReimbursedReports, policy?.connections?.intacct?.config?.autoSync?.enabled, + policy?.connections?.intacct?.config?.importEmployees, policyID, syncReimbursedReports, translate, @@ -102,10 +106,10 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { pendingAction={pendingFields?.sync?.reimbursementAccountID} > bankAccount.id === reimbursementAccountID).name || translate('workspace.sageIntacct.notConfigured')} description={translate('workspace.sageIntacct.paymentAccount')} shouldShowRightIcon - onPress={() => {}} + onPress={() => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_PAYMENT_ACCOUNT.getRoute(policyID))} brickRoadIndicator={errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} /> diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx new file mode 100644 index 000000000000..22e215d0a6a1 --- /dev/null +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx @@ -0,0 +1,83 @@ +import React, {useCallback, useMemo} from 'react'; +import {View} from 'react-native'; +import BlockingView from '@components/BlockingViews/BlockingView'; +import * as Illustrations from '@components/Icon/Illustrations'; +import RadioListItem from '@components/SelectionList/RadioListItem'; +import type {SelectorType} from '@components/SelectionScreen'; +import SelectionScreen from '@components/SelectionScreen'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as Connections from '@libs/actions/connections'; +import Navigation from '@libs/Navigation/Navigation'; +import {getSageIntacctBankAccounts} from '@libs/PolicyUtils'; +import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; +import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import variables from '@styles/variables'; +import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; + +function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + const policyID = policy?.id ?? '-1'; + + const {reimbursementAccountID} = policy?.connections?.intacct?.config.sync ?? {}; + + const vendorSelectorOptions = useMemo(() => getSageIntacctBankAccounts(policy ?? undefined, reimbursementAccountID), [reimbursementAccountID, policy]); + + const listHeaderComponent = useMemo( + () => ( + + {translate('workspace.sageIntacct.paymentAccountDescription')} + + ), + [translate, styles.pb2, styles.ph5, styles.pb5, styles.textNormal], + ); + + const updateDefaultVendor = useCallback( + ({value}: SelectorType) => { + if (value !== reimbursementAccountID) { + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'sync', {reimbursementAccountID: value}); + } + Navigation.goBack(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID)); + }, + [policyID, reimbursementAccountID], + ); + + // TODO: test on empty list + const listEmptyContent = useMemo( + () => ( + + ), + [translate, styles.pb10], + ); + + return ( + mode.isSelected)?.keyForList} + headerContent={listHeaderComponent} + onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID))} + title="workspace.sageIntacct.paymentAccount" + listEmptyContent={listEmptyContent} + connectionName={CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT} + /> + ); +} + +SageIntacctPaymentAccountPage.displayName = 'PolicySageIntacctPaymentAccountPage'; + +export default withPolicyConnections(SageIntacctPaymentAccountPage); From f63b1ae5ccaea478a8722c1ab3bda1906975de17 Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 21 Jun 2024 17:01:30 +0200 Subject: [PATCH 04/30] handle undefined bank account --- .../accounting/intacct/advanced/SageIntacctAdvancedPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index c6d225c58f30..2480d0d5fc8b 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -106,7 +106,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { pendingAction={pendingFields?.sync?.reimbursementAccountID} > bankAccount.id === reimbursementAccountID).name || translate('workspace.sageIntacct.notConfigured')} + title={data.bankAccounts.find((bankAccount) => bankAccount.id === reimbursementAccountID)?.name || translate('workspace.sageIntacct.notConfigured')} description={translate('workspace.sageIntacct.paymentAccount')} shouldShowRightIcon onPress={() => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_PAYMENT_ACCOUNT.getRoute(policyID))} From 01ff51d2202a129d570954623742c825a4e065f3 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 25 Jun 2024 13:29:43 +0200 Subject: [PATCH 05/30] add connection type and update translations --- src/CONST.ts | 2 +- src/languages/en.ts | 28 ++++---- src/libs/PolicyUtils.ts | 10 ++- .../advanced/SageIntacctAdvancedPage.tsx | 35 ++++++--- .../SageIntacctPaymentAccountPage.tsx | 9 ++- src/types/onyx/Policy.ts | 71 +++++++++++++++++++ 6 files changed, 120 insertions(+), 35 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 1c740ae10e88..944e99d68c66 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1335,7 +1335,7 @@ const CONST = { SAGE_INTACCT: { APPROVAL_MODE: { - MANUAL: 'MANUAL', + APPROVAL_MANUAL: 'APPROVAL_MANUAL', }, }, diff --git a/src/languages/en.ts b/src/languages/en.ts index 2cc8daa62f74..065ae1394717 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -112,6 +112,19 @@ type States = Record; type AllCountries = Record; +function integrationName(integration: ConnectionName): string { + switch (integration) { + case CONST.POLICY.CONNECTIONS.NAME.QBO: + return 'Quickbooks Online'; + case CONST.POLICY.CONNECTIONS.NAME.XERO: + return 'Xero'; + case CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT: + return 'Sage Intacct'; + default: + return 'Integration'; + } +} + /* eslint-disable max-len */ export default { common: { @@ -1987,6 +2000,8 @@ export default { welcomeNote: ({workspaceName}: WelcomeNoteParams) => `You have been invited to ${workspaceName || 'a workspace'}! Download the Expensify mobile app at use.expensify.com/download to start tracking your expenses.`, subscription: 'Subscription', + noAccountsFound: 'No accounts found', + noAccountsFoundDescription: (integration: ConnectionName) => `Add the account in ${integrationName(integration)} and sync the connection again.`, }, qbo: { importDescription: 'Choose which coding configurations to import from QuickBooks Online to Expensify.', @@ -2422,18 +2437,7 @@ export default { qbo: 'Quickbooks Online', xero: 'Xero', intacct: 'Sage Intacct', - integrationName: (integration?: ConnectionName): string => { - switch (integration) { - case CONST.POLICY.CONNECTIONS.NAME.QBO: - return 'Quickbooks Online'; - case CONST.POLICY.CONNECTIONS.NAME.XERO: - return 'Xero'; - case CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT: - return 'Sage Intacct'; - default: - return 'Integration'; - } - }, + integrationName, setup: 'Connect', lastSync: 'Last synced just now', import: 'Import', diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 4002262fa7a8..7a99de4b835d 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -409,16 +409,14 @@ function getAdminEmployees(policy: OnyxEntry): PolicyEmployee[] { return Object.values(policy?.employeeList ?? {}).filter((employee) => employee.role === CONST.POLICY.ROLE.ADMIN); } -function getSageIntacctBankAccounts(policy: Policy | undefined, selectedVendorId: string | undefined): SelectorType[] { - const vendors = policy?.connections?.intacct?.data?.bankAccounts ?? []; +function getSageIntacctBankAccounts(policy?: Policy, selectedBankAccountId?: string): SelectorType[] { + const bankAccounts = policy?.connections?.intacct?.data?.bankAccounts ?? []; - const isMatchFound = vendors?.some(({id}) => id === selectedVendorId); - - return (vendors ?? []).map(({id, name}) => ({ + return (bankAccounts ?? []).map(({id, name}) => ({ value: id, text: name, keyForList: id, - isSelected: isMatchFound && selectedVendorId === id, + isSelected: selectedBankAccountId === id, })); } diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 2480d0d5fc8b..7c3f26fbc93a 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -11,6 +11,11 @@ import withPolicy from '@pages/workspace/withPolicy'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; +import type {SageIntacctDataElement} from '@src/types/onyx/Policy'; + +function getReimbursedAccountName(bankAccounts: SageIntacctDataElement[], reimbursementAccountID?: string): string | undefined { + return bankAccounts.find((vendor) => vendor.id === reimbursementAccountID)?.name ?? reimbursementAccountID; +} function SageIntacctAdvancedPage({policy}: WithPolicyProps) { const {translate} = useLocalize(); @@ -28,32 +33,40 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { { label: translate('workspace.sageIntacct.autoSync'), value: !!autoSync, - onToggle: (enabled: boolean) => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'autoSync', {enabled: enabled}), + onToggle: (enabled: boolean) => { + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'autoSync', {enabled}); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'isAutoSyncEnabled', enabled); + }, pendingAction: pendingFields?.autoSync, error: errorFields?.autoSync, description: translate('workspace.sageIntacct.autoSyncDescription'), - isActive: policy?.connections?.intacct?.config?.autoSync?.enabled, + isActive: policy?.connections?.intacct?.config?.autoSync?.enabled ?? false, }, { label: translate('workspace.sageIntacct.inviteEmployees'), value: !!pendingFields?.importEmployees, - onToggle: (enabled) => { + onToggle: (enabled: boolean) => { Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'importEmployees', enabled); - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'approvalMode', enabled ? CONST.SAGE_INTACCT.APPROVAL_MODE.MANUAL : null); + Connections.updatePolicyConnectionConfig( + policyID, + CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, + 'approvalMode', + enabled ? CONST.SAGE_INTACCT.APPROVAL_MODE.APPROVAL_MANUAL : null, + ); }, pendingAction: pendingFields?.importEmployees, error: errorFields?.importEmployees, description: translate('workspace.sageIntacct.inviteEmployeesDescription'), - isActive: policy?.connections?.intacct?.config?.importEmployees, + isActive: policy?.connections?.intacct?.config?.importEmployees ?? false, }, { label: translate('workspace.sageIntacct.syncReimbursedReports'), value: !!syncReimbursedReports, - onToggle: (enabled) => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'sync', {syncReimbursedReports: enabled}), - pendingAction: pendingFields?.sync?.syncReimbursedReports, + onToggle: (enabled: boolean) => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'sync', {syncReimbursedReports: enabled}), + pendingAction: pendingFields?.sync, error: errorFields?.sync?.syncReimbursedReports, description: translate('workspace.sageIntacct.syncReimbursedReportsDescription'), - isActive: syncReimbursedReports, + isActive: syncReimbursedReports ?? false, }, ], [ @@ -63,7 +76,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { errorFields?.sync?.syncReimbursedReports, pendingFields?.autoSync, pendingFields?.importEmployees, - pendingFields?.sync?.syncReimbursedReports, + pendingFields?.sync, policy?.connections?.intacct?.config?.autoSync?.enabled, policy?.connections?.intacct?.config?.importEmployees, policyID, @@ -103,10 +116,10 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { bankAccount.id === reimbursementAccountID)?.name || translate('workspace.sageIntacct.notConfigured')} + title={getReimbursedAccountName(data?.bankAccounts ?? [], reimbursementAccountID) ?? translate('workspace.sageIntacct.notConfigured')} description={translate('workspace.sageIntacct.paymentAccount')} shouldShowRightIcon onPress={() => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_PAYMENT_ACCOUNT.getRoute(policyID))} diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx index 22e215d0a6a1..2087864c0c96 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx @@ -25,7 +25,7 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { const {reimbursementAccountID} = policy?.connections?.intacct?.config.sync ?? {}; - const vendorSelectorOptions = useMemo(() => getSageIntacctBankAccounts(policy ?? undefined, reimbursementAccountID), [reimbursementAccountID, policy]); + const vendorSelectorOptions = useMemo(() => getSageIntacctBankAccounts(policy, reimbursementAccountID), [reimbursementAccountID, policy]); const listHeaderComponent = useMemo( () => ( @@ -46,18 +46,17 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { [policyID, reimbursementAccountID], ); - // TODO: test on empty list const listEmptyContent = useMemo( () => ( ), - [translate, styles.pb10], + [translate], ); return ( diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index bd8f5e7d33d9..62efeec82447 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -594,6 +594,73 @@ type XeroConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback<{ errorFields?: OnyxCommon.ErrorFields; }>; +/** One of the SageIntacctConnectionData object elements */ +type SageIntacctDataElement = { + /** Element ID */ + id: string; + + /** Element name */ + name: string; +}; + +/** + * Connection data for Sage Intacct + */ +type SageIntacctConnectionData = { + /** Collection of bank accounts */ + bankAccounts: SageIntacctDataElement[]; +}; + +/** + * Connection config for Sage Intacct + */ +type SageIntacctConnectiosConfig = OnyxCommon.OnyxValueWithOfflineFeedback<{ + /** Whether employees should be imported from Sage Intacct */ + importEmployees: boolean; + + /** Sage Intacct approval mode */ + approvalMode: ValueOf | null; + + /** Whether auto sync is enabled */ + isAutoSyncEnabled: boolean; + + /** Sage Intacct credentials */ + credentials: { + /** Sage Intacct companyID */ + companyID: string; + + /** Sage Intacct password */ + password: string; + + /** Sage Intacct userID */ + userID: string; + }; + + /** Configuration of automatic synchronization from Sage Intacct to the app */ + autoSync: { + /** ID of sync job */ + jobID: string; + + /** Whether changes made in QuickBooks Online should be reflected into the app automatically */ + enabled: boolean; + }; + + /** Sage Intacct sync */ + sync: { + /** ID of the bank account for Sage Intacct bill payment account */ + reimbursementAccountID?: string; + + /** Whether the reimbursed reports should be synched */ + syncReimbursedReports: boolean; + }; + + /** Collection of Sage Intacct config errors */ + errors?: OnyxCommon.Errors; + + /** Collection of form field errors */ + errorFields?: OnyxCommon.ErrorFields; +}>; + /** Data stored about subsidiaries from NetSuite */ type Subsidiary = { /** ID of the subsidiary */ @@ -971,6 +1038,9 @@ type Connections = { /** NetSuite integration connection */ netsuite: NetSuiteConnection; + + /** Sage Intacct integration connection */ + intacct: Connection; }; /** Names of integration connections */ @@ -1314,4 +1384,5 @@ export type { QBOReimbursableExportAccountType, QBOConnectionConfig, XeroTrackingCategory, + SageIntacctDataElement, }; From b4c27a2df267698216eafeed9917b62597317da2 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 25 Jun 2024 13:44:32 +0200 Subject: [PATCH 06/30] update es translations --- src/languages/es.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/languages/es.ts b/src/languages/es.ts index cc3ae848de6b..ca2df4b1fd67 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -103,6 +103,19 @@ import type { ZipCodeExampleFormatParams, } from './types'; +function integrationName(integration: ConnectionName): string { + switch (integration) { + case CONST.POLICY.CONNECTIONS.NAME.QBO: + return 'Quickbooks Online'; + case CONST.POLICY.CONNECTIONS.NAME.XERO: + return 'Xero'; + case CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT: + return 'Sage Intacct'; + default: + return 'Integration'; + } +} + /* eslint-disable max-len */ export default { common: { @@ -2012,6 +2025,8 @@ export default { welcomeNote: ({workspaceName}: WelcomeNoteParams) => `¡Has sido invitado a ${workspaceName}! Descargue la aplicación móvil Expensify en use.expensify.com/download para comenzar a rastrear sus gastos.`, subscription: 'Suscripción', + noAccountsFound: 'No se ha encontrado ninguna cuenta', + noAccountsFoundDescription: (integration: ConnectionName) => `Añade la cuenta en ${integrationName(integration)} y sincroniza de nuevo la conexión.`, }, qbo: { importDescription: 'Elige que configuraciónes de codificación son importadas desde QuickBooks Online a Expensify.', @@ -2217,6 +2232,19 @@ export default { noAccountsFound: 'No se ha encontrado ninguna cuenta', noAccountsFoundDescription: 'Añade la cuenta en Xero y sincroniza de nuevo la conexión.', }, + sageIntacct: { + autoSync: 'Sincronización automática', + autoSyncDescription: 'Sincronice Sage Intacct y Expensify automáticamente, todos los días.', + inviteEmployees: 'Invitar a los empleados', + inviteEmployeesDescription: + 'Importe los registros de empleados de Sage Intacct e invite a los empleados a este espacio de trabajo. Su flujo de trabajo de aprobación será por defecto la aprobación del gerente y se puede configurar aún más en la página Miembros.', + syncReimbursedReports: 'Sincronizar informes reembolsados', + syncReimbursedReportsDescription: + 'Cuando un informe se reembolsa utilizando Expensify ACH, la factura de compra correspondiente se creará en la cuenta de Sage Intacct a continuación.', + paymentAccount: 'Cuenta de pago Sage Intacct', + notConfigured: 'No configurado', + paymentAccountDescription: 'Descripción', + }, type: { free: 'Gratis', control: 'Control', @@ -2413,6 +2441,8 @@ export default { subtitle: 'Conecta a tu sistema de contabilidad para codificar transacciones con tu plan de cuentas, auto-cotejar pagos, y mantener tus finanzas sincronizadas.', qbo: 'Quickbooks Online', xero: 'Xero', + intacct: 'Sage Intacct', + integrationName, setup: 'Configurar', lastSync: 'Recién sincronizado', import: 'Importar', From 6e9e9f6074619a9e22bd45d96679f1fa5652eacb Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 25 Jun 2024 15:02:28 +0200 Subject: [PATCH 07/30] add methods for each setting --- src/CONST.ts | 6 + src/libs/actions/connections/SageIntacct.ts | 151 ++++++++++++++++++ .../advanced/SageIntacctAdvancedPage.tsx | 12 +- 3 files changed, 161 insertions(+), 8 deletions(-) create mode 100644 src/libs/actions/connections/SageIntacct.ts diff --git a/src/CONST.ts b/src/CONST.ts index 944e99d68c66..0f154aeeead2 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1333,6 +1333,12 @@ const CONST = { }, }, + SAGE_INTACCT_CONFIG: { + AUTO_SYNC: 'autoSync', + IMPORT_EMPLOYEES: 'importEmployees', + APPROVAL_MODE: 'approvalMode', + }, + SAGE_INTACCT: { APPROVAL_MODE: { APPROVAL_MANUAL: 'APPROVAL_MANUAL', diff --git a/src/libs/actions/connections/SageIntacct.ts b/src/libs/actions/connections/SageIntacct.ts new file mode 100644 index 000000000000..44620f05157d --- /dev/null +++ b/src/libs/actions/connections/SageIntacct.ts @@ -0,0 +1,151 @@ +import type {OnyxUpdate} from 'react-native-onyx'; +import Onyx from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; +import * as API from '@libs/API'; +import {WRITE_COMMANDS} from '@libs/API/types'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {ConnectionName, Connections} from '@src/types/onyx/Policy'; + +function prepareOnyxData( + 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, + }, + }, + }, + }, + }, + }, + ]; + + return {optimisticData, failureData, successData}; +} + +function updateSageIntacctAutoSync(policyID: string, enabled: boolean) { + const autoSyncSettingValue = {enabled}; + const {optimisticData, failureData, successData} = prepareOnyxData(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC, autoSyncSettingValue); + const parameters = { + policyID, + connectionName: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, + settingName: CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC, + settingValue: JSON.stringify(autoSyncSettingValue), + idempotencyKey: CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC, + }; + + API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); +} + +function updateSageIntacctImportEmployees(policyID: string, enabled: boolean) { + const {optimisticData, failureData, successData} = prepareOnyxData(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES, enabled); + const parameters = { + policyID, + connectionName: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, + settingName: CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES, + settingValue: JSON.stringify(enabled), + idempotencyKey: CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES, + }; + + API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); +} + +function updateSageIntacctApprovalMode(policyID: string, enabled: boolean) { + const approvalModeSettingValue = enabled ? CONST.SAGE_INTACCT.APPROVAL_MODE.APPROVAL_MANUAL : null; + const {optimisticData, failureData, successData} = prepareOnyxData( + policyID, + CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, + CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, + approvalModeSettingValue, + ); + const parameters = { + policyID, + connectionName: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, + settingName: CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, + settingValue: JSON.stringify(approvalModeSettingValue), + idempotencyKey: CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, + }; + + API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); +} + +function updateSageIntacctSyncReimbursedReports(policyID: string, enabled: boolean) { + const approvalModeSettingValue = enabled ? CONST.SAGE_INTACCT.APPROVAL_MODE.APPROVAL_MANUAL : null; + const {optimisticData, failureData, successData} = prepareOnyxData( + policyID, + CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, + CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, + approvalModeSettingValue, + ); + const parameters = { + policyID, + connectionName: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, + settingName: CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, + settingValue: JSON.stringify(approvalModeSettingValue), + idempotencyKey: CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, + }; + + API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); +} + +export {updateSageIntacctAutoSync, updateSageIntacctImportEmployees, updateSageIntacctApprovalMode}; diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 7c3f26fbc93a..992f6c2ff53d 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -9,6 +9,7 @@ import Navigation from '@navigation/Navigation'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicy from '@pages/workspace/withPolicy'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; +import {updateSageIntacctApprovalMode, updateSageIntacctAutoSync, updateSageIntacctImportEmployees} from '@userActions/connections/SageIntacct'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type {SageIntacctDataElement} from '@src/types/onyx/Policy'; @@ -34,7 +35,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { label: translate('workspace.sageIntacct.autoSync'), value: !!autoSync, onToggle: (enabled: boolean) => { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'autoSync', {enabled}); + updateSageIntacctAutoSync(policyID, enabled); Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'isAutoSyncEnabled', enabled); }, pendingAction: pendingFields?.autoSync, @@ -46,13 +47,8 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { label: translate('workspace.sageIntacct.inviteEmployees'), value: !!pendingFields?.importEmployees, onToggle: (enabled: boolean) => { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'importEmployees', enabled); - Connections.updatePolicyConnectionConfig( - policyID, - CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, - 'approvalMode', - enabled ? CONST.SAGE_INTACCT.APPROVAL_MODE.APPROVAL_MANUAL : null, - ); + updateSageIntacctImportEmployees(policyID, enabled); + updateSageIntacctApprovalMode(policyID, enabled); }, pendingAction: pendingFields?.importEmployees, error: errorFields?.importEmployees, From 63ad64de56c4309475b51bd4ab34dec8ecd2a432 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 25 Jun 2024 17:44:25 +0200 Subject: [PATCH 08/30] show `payment account` only when toggle enabled --- src/libs/actions/connections/SageIntacct.ts | 20 ------------- .../advanced/SageIntacctAdvancedPage.tsx | 30 ++++++++++--------- 2 files changed, 16 insertions(+), 34 deletions(-) diff --git a/src/libs/actions/connections/SageIntacct.ts b/src/libs/actions/connections/SageIntacct.ts index 44620f05157d..e6e525fb4e1b 100644 --- a/src/libs/actions/connections/SageIntacct.ts +++ b/src/libs/actions/connections/SageIntacct.ts @@ -1,6 +1,5 @@ import type {OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; -import type {ValueOf} from 'type-fest'; import * as API from '@libs/API'; import {WRITE_COMMANDS} from '@libs/API/types'; import * as ErrorUtils from '@libs/ErrorUtils'; @@ -129,23 +128,4 @@ function updateSageIntacctApprovalMode(policyID: string, enabled: boolean) { API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); } -function updateSageIntacctSyncReimbursedReports(policyID: string, enabled: boolean) { - const approvalModeSettingValue = enabled ? CONST.SAGE_INTACCT.APPROVAL_MODE.APPROVAL_MANUAL : null; - const {optimisticData, failureData, successData} = prepareOnyxData( - policyID, - CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, - CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, - approvalModeSettingValue, - ); - const parameters = { - policyID, - connectionName: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, - settingName: CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, - settingValue: JSON.stringify(approvalModeSettingValue), - idempotencyKey: CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, - }; - - API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); -} - export {updateSageIntacctAutoSync, updateSageIntacctImportEmployees, updateSageIntacctApprovalMode}; diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 992f6c2ff53d..1937e92d8100 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -1,6 +1,6 @@ import React, {useMemo} from 'react'; import ConnectionLayout from '@components/ConnectionLayout'; -import MenuItem from '@components/MenuItem'; +import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -15,7 +15,7 @@ import ROUTES from '@src/ROUTES'; import type {SageIntacctDataElement} from '@src/types/onyx/Policy'; function getReimbursedAccountName(bankAccounts: SageIntacctDataElement[], reimbursementAccountID?: string): string | undefined { - return bankAccounts.find((vendor) => vendor.id === reimbursementAccountID)?.name ?? reimbursementAccountID; + return bankAccounts.find((bankAccount) => bankAccount.id === reimbursementAccountID)?.name ?? reimbursementAccountID; } function SageIntacctAdvancedPage({policy}: WithPolicyProps) { @@ -110,18 +110,20 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { ))} - - Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_PAYMENT_ACCOUNT.getRoute(policyID))} - brickRoadIndicator={errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} - /> - + {syncReimbursedReports && ( + + Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_PAYMENT_ACCOUNT.getRoute(policyID))} + brickRoadIndicator={errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} + /> + + )} ); } From 04ee8b0459bdc9a91247ffc65013d61b38da3e20 Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 28 Jun 2024 11:51:58 +0200 Subject: [PATCH 09/30] add offline and error behaviour for auto sync --- src/CONST.ts | 1 + src/libs/actions/connections/SageIntacct.ts | 39 +++++++------------ .../advanced/SageIntacctAdvancedPage.tsx | 28 ++++++------- 3 files changed, 27 insertions(+), 41 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 0f154aeeead2..98b899614804 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1334,6 +1334,7 @@ const CONST = { }, SAGE_INTACCT_CONFIG: { + IS_AUTO_SYNC_ENABLED: 'isAutoSyncEnabled', AUTO_SYNC: 'autoSync', IMPORT_EMPLOYEES: 'importEmployees', APPROVAL_MODE: 'approvalMode', diff --git a/src/libs/actions/connections/SageIntacct.ts b/src/libs/actions/connections/SageIntacct.ts index e6e525fb4e1b..4fadaf3a691f 100644 --- a/src/libs/actions/connections/SageIntacct.ts +++ b/src/libs/actions/connections/SageIntacct.ts @@ -5,23 +5,18 @@ import {WRITE_COMMANDS} from '@libs/API/types'; import * as ErrorUtils from '@libs/ErrorUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {ConnectionName, Connections} from '@src/types/onyx/Policy'; +import type {Connections} from '@src/types/onyx/Policy'; -function prepareOnyxData( - policyID: string, - connectionName: TConnectionName, - settingName: TSettingName, - settingValue: Partial, -) { +function prepareOnyxData(policyID: string, settingName: keyof Connections['intacct']['config'], settingValue: string | boolean | null) { const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { connections: { - [connectionName]: { + intacct: { config: { - [settingName]: settingValue ?? null, + [settingName]: settingValue, pendingFields: { [settingName]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, }, @@ -41,9 +36,9 @@ function prepareOnyxData [ { label: translate('workspace.sageIntacct.autoSync'), - value: !!autoSync, onToggle: (enabled: boolean) => { updateSageIntacctAutoSync(policyID, enabled); - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'isAutoSyncEnabled', enabled); + // Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'autoSync', enabled); }, - pendingAction: pendingFields?.autoSync, - error: errorFields?.autoSync, + pendingAction: pendingFields?.isAutoSyncEnabled, + error: errorFields?.isAutoSyncEnabled, description: translate('workspace.sageIntacct.autoSyncDescription'), - isActive: policy?.connections?.intacct?.config?.autoSync?.enabled ?? false, + isActive: isAutoSyncEnabled ?? false, }, { label: translate('workspace.sageIntacct.inviteEmployees'), - value: !!pendingFields?.importEmployees, onToggle: (enabled: boolean) => { updateSageIntacctImportEmployees(policyID, enabled); updateSageIntacctApprovalMode(policyID, enabled); @@ -57,7 +55,6 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { }, { label: translate('workspace.sageIntacct.syncReimbursedReports'), - value: !!syncReimbursedReports, onToggle: (enabled: boolean) => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'sync', {syncReimbursedReports: enabled}), pendingAction: pendingFields?.sync, error: errorFields?.sync?.syncReimbursedReports, @@ -66,18 +63,17 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { }, ], [ - autoSync, - errorFields?.autoSync, - errorFields?.importEmployees, - errorFields?.sync?.syncReimbursedReports, - pendingFields?.autoSync, + translate, + pendingFields?.isAutoSyncEnabled, pendingFields?.importEmployees, pendingFields?.sync, - policy?.connections?.intacct?.config?.autoSync?.enabled, + errorFields?.isAutoSyncEnabled, + errorFields?.importEmployees, + errorFields?.sync?.syncReimbursedReports, + isAutoSyncEnabled, policy?.connections?.intacct?.config?.importEmployees, - policyID, syncReimbursedReports, - translate, + policyID, ], ); From b9e3e0fb9deb5ff2021a971ca16b96ed2d5a441d Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 28 Jun 2024 12:25:25 +0200 Subject: [PATCH 10/30] fix translations --- src/CONST.ts | 1 + src/languages/en.ts | 29 +++++------------------------ src/languages/es.ts | 27 +++++---------------------- src/types/onyx/Policy.ts | 2 +- 4 files changed, 12 insertions(+), 47 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 0330f7e87a05..8be6193895cf 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1812,6 +1812,7 @@ const CONST = { netsuite: 'NetSuite', quickbooksOnline: 'Quickbooks Online', xero: 'Xero', + intacct: 'Sage Intacct', }, SYNC_STAGE_NAME: { STARTING_IMPORT_QBO: 'startingImportQBO', diff --git a/src/languages/en.ts b/src/languages/en.ts index 566a1fb5f8ce..bda3bd61a3d0 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -113,17 +113,8 @@ type States = Record; type AllCountries = Record; -function integrationName(integration: ConnectionName): string { - switch (integration) { - case CONST.POLICY.CONNECTIONS.NAME.QBO: - return 'Quickbooks Online'; - case CONST.POLICY.CONNECTIONS.NAME.XERO: - return 'Xero'; - case CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT: - return 'Sage Intacct'; - default: - return 'Integration'; - } +function integrationName(fallbackName: string, integration?: ConnectionName): string { + return integration && CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] ? CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] : fallbackName; } /* eslint-disable max-len */ @@ -2018,7 +2009,7 @@ export default { `You have been invited to ${workspaceName || 'a workspace'}! Download the Expensify mobile app at use.expensify.com/download to start tracking your expenses.`, subscription: 'Subscription', noAccountsFound: 'No accounts found', - noAccountsFoundDescription: (integration: ConnectionName) => `Add the account in ${integrationName(integration)} and sync the connection again.`, + noAccountsFoundDescription: (integration: ConnectionName) => `Add the account in ${integrationName('this integration', integration)} and sync the connection again.`, }, qbo: { importDescription: 'Choose which coding configurations to import from QuickBooks Online to Expensify.', @@ -2463,7 +2454,6 @@ export default { xero: 'Xero', netsuite: 'NetSuite', intacct: 'Sage Intacct', - integrationName, setup: 'Connect', lastSync: 'Last synced just now', import: 'Import', @@ -2472,10 +2462,7 @@ export default { other: 'Other integrations', syncNow: 'Sync now', disconnect: 'Disconnect', - disconnectTitle: (integration?: ConnectionName): string => { - const integrationName = integration && CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] ? CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] : 'integration'; - return `Disconnect ${integrationName}`; - }, + disconnectTitle: (integration?: ConnectionName): string => `Disconnect ${integrationName('integration', integration)}`, connectTitle: (integrationToConnect: ConnectionName): string => `Connect ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integrationToConnect] ?? 'accounting integration'}`, syncError: (integration?: ConnectionName): string => { @@ -2504,13 +2491,7 @@ export default { [CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE]: 'Not imported', [CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD]: 'Imported as report fields', }, - disconnectPrompt: (currentIntegration?: ConnectionName): string => { - const integrationName = - currentIntegration && CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[currentIntegration] - ? CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[currentIntegration] - : 'this integration'; - return `Are you sure you want to disconnect ${integrationName}?`; - }, + disconnectPrompt: (currentIntegration?: ConnectionName): string => `Are you sure you want to disconnect ${integrationName('this integration', currentIntegration)}?`, connectPrompt: (integrationToConnect: ConnectionName): string => `Are you sure you want to connect ${ CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integrationToConnect] ?? 'this accounting integration' diff --git a/src/languages/es.ts b/src/languages/es.ts index 9d32d1479568..cd00d25e797c 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -104,17 +104,8 @@ import type { ZipCodeExampleFormatParams, } from './types'; -function integrationName(integration: ConnectionName): string { - switch (integration) { - case CONST.POLICY.CONNECTIONS.NAME.QBO: - return 'Quickbooks Online'; - case CONST.POLICY.CONNECTIONS.NAME.XERO: - return 'Xero'; - case CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT: - return 'Sage Intacct'; - default: - return 'Integration'; - } +function integrationName(fallbackName: string, integration?: ConnectionName): string { + return integration && CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] ? CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] : fallbackName; } /* eslint-disable max-len */ @@ -2042,7 +2033,7 @@ export default { `¡Has sido invitado a ${workspaceName}! Descargue la aplicación móvil Expensify en use.expensify.com/download para comenzar a rastrear sus gastos.`, subscription: 'Suscripción', noAccountsFound: 'No se ha encontrado ninguna cuenta', - noAccountsFoundDescription: (integration: ConnectionName) => `Añade la cuenta en ${integrationName(integration)} y sincroniza de nuevo la conexión.`, + noAccountsFoundDescription: (integration: ConnectionName) => `Añade la cuenta en ${integrationName('esta integración', integration)} y sincroniza de nuevo la conexión.`, }, qbo: { importDescription: 'Elige que configuraciónes de codificación son importadas desde QuickBooks Online a Expensify.', @@ -2467,7 +2458,6 @@ export default { xero: 'Xero', netsuite: 'NetSuite', intacct: 'Sage Intacct', - integrationName, setup: 'Configurar', lastSync: 'Recién sincronizado', import: 'Importar', @@ -2476,10 +2466,7 @@ export default { other: 'Otras integraciones', syncNow: 'Sincronizar ahora', disconnect: 'Desconectar', - disconnectTitle: (integration?: ConnectionName): string => { - const integrationName = integration && CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] ? CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] : 'integración'; - return `Desconectar ${integrationName}`; - }, + disconnectTitle: (integration?: ConnectionName): string => `Desconectar ${integrationName('integración', integration)}`, connectTitle: (integrationToConnect: ConnectionName): string => `Conectar ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integrationToConnect] ?? 'accounting integration'}`, syncError: (integration?: ConnectionName): string => { switch (integration) { @@ -2507,11 +2494,7 @@ export default { [CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE]: 'No importado', [CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD]: 'Importado como campos de informe', }, - disconnectPrompt: (currentIntegration?: ConnectionName): string => { - const integrationName = - currentIntegration && CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[currentIntegration] ? CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[currentIntegration] : 'integración'; - return `¿Estás seguro de que quieres desconectar ${integrationName}?`; - }, + disconnectPrompt: (currentIntegration?: ConnectionName): string => `¿Estás seguro de que quieres desconectar ${integrationName('integración', currentIntegration)}?`, connectPrompt: (integrationToConnect: ConnectionName): string => `¿Estás seguro de que quieres conectar a ${ CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integrationToConnect] ?? 'esta integración contable' diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 9efded36a36b..d88c0d440528 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -662,7 +662,7 @@ type SageIntacctConnectiosConfig = OnyxCommon.OnyxValueWithOfflineFeedback<{ }>; /** Data stored about subsidiaries from NetSuite */ -type Subsidiary = { +type NetSuiteSubsidiary = { /** ID of the subsidiary */ internalID: string; From 33bfa807d345cad4477e4926d53a984ed31a4fdf Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 28 Jun 2024 15:05:16 +0200 Subject: [PATCH 11/30] handle errors --- src/CONST.ts | 3 + src/libs/actions/Policy/Policy.ts | 10 ++ src/libs/actions/connections/SageIntacct.ts | 105 +++++++++++++++++- .../advanced/SageIntacctAdvancedPage.tsx | 96 +++++++++------- .../SageIntacctPaymentAccountPage.tsx | 50 +++++---- src/types/onyx/Policy.ts | 7 +- 6 files changed, 205 insertions(+), 66 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 8be6193895cf..9e8208db7f72 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1343,6 +1343,9 @@ const CONST = { AUTO_SYNC: 'autoSync', IMPORT_EMPLOYEES: 'importEmployees', APPROVAL_MODE: 'approvalMode', + SYNC: 'sync', + SYNC_REIMBURSED_REPORTS: 'syncReimbursedReports', + REIMBUSERED_ACCOUNT_ID: 'reimbursementAccountID', }, SAGE_INTACCT: { diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 0ff65daa7e5b..d8703b069333 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -531,6 +531,14 @@ function clearNetSuiteErrorField(policyID: string, fieldName: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {connections: {netsuite: {options: {config: {errorFields: {[fieldName]: null}}}}}}); } +function clearSageIntacctErrorField(policyID: string, fieldName: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {connections: {intacct: {config: {errorFields: {[fieldName]: null}}}}}); +} + +function clearSageIntacctSyncErrorField(policyID: string, fieldName: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {connections: {intacct: {config: {sync: {errorFields: {[fieldName]: null}}}}}}); +} + function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueOf, reimburserEmail: string) { const policy = getPolicy(policyID); @@ -3002,6 +3010,8 @@ export { buildPolicyData, createPolicyExpenseChats, clearNetSuiteErrorField, + clearSageIntacctErrorField, + clearSageIntacctSyncErrorField, }; export type {NewCustomUnit}; diff --git a/src/libs/actions/connections/SageIntacct.ts b/src/libs/actions/connections/SageIntacct.ts index 4fadaf3a691f..f7b6caaeed3f 100644 --- a/src/libs/actions/connections/SageIntacct.ts +++ b/src/libs/actions/connections/SageIntacct.ts @@ -77,6 +77,82 @@ function prepareOnyxData(policyID: string, settingName: keyof Connections['intac return {optimisticData, failureData, successData}; } +function prepareSyncOnyxData(policyID: string, settingName: keyof Connections['intacct']['config']['sync'], settingValue: string | boolean | null) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + intacct: { + config: { + sync: { + [settingName]: settingValue, + 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: { + intacct: { + config: { + sync: { + [settingName]: settingValue, + pendingFields: { + [settingName]: null, + }, + errorFields: { + [settingName]: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + }, + }, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + intacct: { + config: { + sync: { + [settingName]: settingValue, + pendingFields: { + [settingName]: null, + }, + errorFields: { + [settingName]: null, + }, + }, + }, + }, + }, + }, + }, + ]; + + return {optimisticData, failureData, successData}; +} + function updateSageIntacctAutoSync(policyID: string, enabled: boolean) { const {optimisticData, failureData, successData} = prepareOnyxData(policyID, CONST.SAGE_INTACCT_CONFIG.IS_AUTO_SYNC_ENABLED, enabled); const parameters = { @@ -117,4 +193,31 @@ function updateSageIntacctApprovalMode(policyID: string, enabled: boolean) { API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); } -export {updateSageIntacctAutoSync, updateSageIntacctImportEmployees, updateSageIntacctApprovalMode}; +function updateSageIntacctSyncReimbursedReports(policyID: string, vendorID: string | null) { + const settingValue = vendorID ?? false; + const {optimisticData, failureData, successData} = prepareSyncOnyxData(policyID, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS, settingValue); + const parameters = { + policyID, + connectionName: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, + settingName: CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS, + settingValue: JSON.stringify(settingValue), + idempotencyKey: CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS, + }; + + API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); +} + +function updateSageIntacctSyncReimbursementAccountID(policyID: string, vendorID: string | null) { + const {optimisticData, failureData, successData} = prepareSyncOnyxData(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID, vendorID); + const parameters = { + policyID, + connectionName: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, + settingName: CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID, + settingValue: JSON.stringify(vendorID), + idempotencyKey: CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID, + }; + + API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); +} + +export {updateSageIntacctAutoSync, updateSageIntacctImportEmployees, updateSageIntacctApprovalMode, updateSageIntacctSyncReimbursedReports, updateSageIntacctSyncReimbursementAccountID}; diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index ff371d4c146c..4f62a5a3fab1 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -1,15 +1,22 @@ -import React, {useMemo} from 'react'; +import React, {useMemo, useState} from 'react'; 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 * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicy from '@pages/workspace/withPolicy'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; -import {updateSageIntacctApprovalMode, updateSageIntacctAutoSync, updateSageIntacctImportEmployees} from '@userActions/connections/SageIntacct'; +import { + updateSageIntacctApprovalMode, + updateSageIntacctAutoSync, + updateSageIntacctImportEmployees, + updateSageIntacctSyncReimbursedReports, + updateSageIntacctSyncReimbursementAccountID, +} from '@userActions/connections/SageIntacct'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type {SageIntacctDataElement} from '@src/types/onyx/Policy'; @@ -23,10 +30,11 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { const policyID = policy?.id ?? '-1'; const styles = useThemeStyles(); - const {syncReimbursedReports, reimbursementAccountID} = policy?.connections?.intacct?.config?.sync ?? {}; - const {isAutoSyncEnabled, pendingFields, errorFields, credentials} = policy?.connections?.intacct?.config ?? {}; + const {importEmployees, isAutoSyncEnabled, sync, pendingFields, credentials} = policy?.connections?.intacct?.config ?? {}; const {data} = policy?.connections?.intacct ?? {}; + const [isSyncReimbursedReportsEnabled, setIsSyncReimbursedReportsEnabled] = useState(!!sync?.syncReimbursedReports); + const currentSageIntacctOrganizationName = credentials?.companyID; const toggleSections = useMemo( @@ -38,9 +46,10 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { // Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'autoSync', enabled); }, pendingAction: pendingFields?.isAutoSyncEnabled, - error: errorFields?.isAutoSyncEnabled, + error: ErrorUtils.getLatestErrorField(sync ?? {}, CONST.SAGE_INTACCT_CONFIG.IS_AUTO_SYNC_ENABLED), + onCloseError: () => Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.IS_AUTO_SYNC_ENABLED), description: translate('workspace.sageIntacct.autoSyncDescription'), - isActive: isAutoSyncEnabled ?? false, + isActive: !!isAutoSyncEnabled, }, { label: translate('workspace.sageIntacct.inviteEmployees'), @@ -49,32 +58,35 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { updateSageIntacctApprovalMode(policyID, enabled); }, pendingAction: pendingFields?.importEmployees, - error: errorFields?.importEmployees, + error: + ErrorUtils.getLatestErrorField(sync ?? {}, CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES) ?? + ErrorUtils.getLatestErrorField(sync ?? {}, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE), + onCloseError: () => { + Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES); + Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE); + }, description: translate('workspace.sageIntacct.inviteEmployeesDescription'), - isActive: policy?.connections?.intacct?.config?.importEmployees ?? false, + isActive: !!importEmployees, }, { label: translate('workspace.sageIntacct.syncReimbursedReports'), - onToggle: (enabled: boolean) => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'sync', {syncReimbursedReports: enabled}), - pendingAction: pendingFields?.sync, - error: errorFields?.sync?.syncReimbursedReports, + onToggle: (enabled: boolean) => { + setIsSyncReimbursedReportsEnabled(enabled); + if (!enabled) { + updateSageIntacctSyncReimbursedReports(policyID, null); + updateSageIntacctSyncReimbursementAccountID(policyID, null); + } + }, + pendingAction: sync?.pendingFields?.syncReimbursedReports, + error: ErrorUtils.getLatestErrorField(sync ?? {}, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS), + onCloseError: () => { + Policy.clearSageIntacctSyncErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS); + }, description: translate('workspace.sageIntacct.syncReimbursedReportsDescription'), - isActive: syncReimbursedReports ?? false, + isActive: isSyncReimbursedReportsEnabled, }, ], - [ - translate, - pendingFields?.isAutoSyncEnabled, - pendingFields?.importEmployees, - pendingFields?.sync, - errorFields?.isAutoSyncEnabled, - errorFields?.importEmployees, - errorFields?.sync?.syncReimbursedReports, - isAutoSyncEnabled, - policy?.connections?.intacct?.config?.importEmployees, - syncReimbursedReports, - policyID, - ], + [translate, pendingFields?.isAutoSyncEnabled, pendingFields?.importEmployees, sync, isAutoSyncEnabled, importEmployees, isSyncReimbursedReportsEnabled, policyID], ); return ( @@ -90,33 +102,31 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { connectionName={CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT} > {toggleSections.map((section) => ( - - - + errors={section.error} + onCloseError={section.onCloseError} + /> ))} - {syncReimbursedReports && ( + {isSyncReimbursedReportsEnabled && ( Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_PAYMENT_ACCOUNT.getRoute(policyID))} - brickRoadIndicator={errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} + brickRoadIndicator={sync?.errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} /> )} diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx index 2087864c0c96..4d3bae37b2d7 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx @@ -2,18 +2,21 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; import * as Illustrations from '@components/Icon/Illustrations'; +import OfflineWithFeedback from '@components/OfflineWithFeedback'; import RadioListItem from '@components/SelectionList/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as Connections from '@libs/actions/connections'; +import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {getSageIntacctBankAccounts} from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; +import {updateSageIntacctSyncReimbursedReports, updateSageIntacctSyncReimbursementAccountID} from '@userActions/connections/SageIntacct'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -23,9 +26,9 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { const policyID = policy?.id ?? '-1'; - const {reimbursementAccountID} = policy?.connections?.intacct?.config.sync ?? {}; + const {sync} = policy?.connections?.intacct?.config ?? {}; - const vendorSelectorOptions = useMemo(() => getSageIntacctBankAccounts(policy, reimbursementAccountID), [reimbursementAccountID, policy]); + const vendorSelectorOptions = useMemo(() => getSageIntacctBankAccounts(policy, sync?.reimbursementAccountID), [policy, sync?.reimbursementAccountID]); const listHeaderComponent = useMemo( () => ( @@ -38,12 +41,13 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { const updateDefaultVendor = useCallback( ({value}: SelectorType) => { - if (value !== reimbursementAccountID) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'sync', {reimbursementAccountID: value}); + if (value !== sync?.reimbursementAccountID) { + updateSageIntacctSyncReimbursementAccountID(policyID, value); + updateSageIntacctSyncReimbursedReports(policyID, value); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID)); }, - [policyID, reimbursementAccountID], + [policyID, sync?.reimbursementAccountID], ); const listEmptyContent = useMemo( @@ -60,20 +64,26 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { ); return ( - mode.isSelected)?.keyForList} - headerContent={listHeaderComponent} - onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID))} - title="workspace.sageIntacct.paymentAccount" - listEmptyContent={listEmptyContent} - connectionName={CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT} - /> + Policy.clearSageIntacctSyncErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID)} + > + mode.isSelected)?.keyForList} + headerContent={listHeaderComponent} + onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID))} + title="workspace.sageIntacct.paymentAccount" + listEmptyContent={listEmptyContent} + connectionName={CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT} + /> + ); } diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index d88c0d440528..09052ebbd6ed 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -646,13 +646,16 @@ type SageIntacctConnectiosConfig = OnyxCommon.OnyxValueWithOfflineFeedback<{ }; /** Sage Intacct sync */ - sync: { + sync: OnyxCommon.OnyxValueWithOfflineFeedback<{ /** ID of the bank account for Sage Intacct bill payment account */ reimbursementAccountID?: string; /** Whether the reimbursed reports should be synched */ syncReimbursedReports: boolean; - }; + + /** Collection of form field errors */ + errorFields?: OnyxCommon.ErrorFields; + }>; /** Collection of Sage Intacct config errors */ errors?: OnyxCommon.Errors; From f01c9a790cffa16c54d154ad11b8cd72e24a172c Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 28 Jun 2024 15:12:14 +0200 Subject: [PATCH 12/30] change type --- src/libs/actions/connections/SageIntacct.ts | 2 +- .../accounting/intacct/advanced/SageIntacctAdvancedPage.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/connections/SageIntacct.ts b/src/libs/actions/connections/SageIntacct.ts index f7b6caaeed3f..883cc2dd59f5 100644 --- a/src/libs/actions/connections/SageIntacct.ts +++ b/src/libs/actions/connections/SageIntacct.ts @@ -193,7 +193,7 @@ function updateSageIntacctApprovalMode(policyID: string, enabled: boolean) { API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); } -function updateSageIntacctSyncReimbursedReports(policyID: string, vendorID: string | null) { +function updateSageIntacctSyncReimbursedReports(policyID: string, vendorID: string | boolean) { const settingValue = vendorID ?? false; const {optimisticData, failureData, successData} = prepareSyncOnyxData(policyID, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS, settingValue); const parameters = { diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 4f62a5a3fab1..9692f958d6e1 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -73,7 +73,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { onToggle: (enabled: boolean) => { setIsSyncReimbursedReportsEnabled(enabled); if (!enabled) { - updateSageIntacctSyncReimbursedReports(policyID, null); + updateSageIntacctSyncReimbursedReports(policyID, false); updateSageIntacctSyncReimbursementAccountID(policyID, null); } }, From 892f9b563012fe1fd749886c205a33e51c96a183 Mon Sep 17 00:00:00 2001 From: war-in Date: Thu, 4 Jul 2024 15:11:21 +0200 Subject: [PATCH 13/30] fix --- .../accounting/PolicyAccountingPage.tsx | 15 -------- .../EnterSageIntacctCredentialsPage.tsx | 2 +- src/types/onyx/Policy.ts | 37 ++----------------- 3 files changed, 5 insertions(+), 49 deletions(-) diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index 2a04c39d05d4..f5331ba68114 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -130,21 +130,6 @@ function accountingIntegrationData( ), onImportPagePress: () => {}, onExportPagePress: () => {}, - onAdvancedPagePress: () => {}, - }; - case CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT: - return { - title: translate('workspace.accounting.intacct'), - icon: Expensicons.XeroSquare, - setupConnectionButton: ( - - ), - onImportPagePress: () => {}, - onExportPagePress: () => {}, onAdvancedPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID)), }; default: diff --git a/src/pages/workspace/accounting/intacct/EnterSageIntacctCredentialsPage.tsx b/src/pages/workspace/accounting/intacct/EnterSageIntacctCredentialsPage.tsx index 75f4cab3783d..cc997123a412 100644 --- a/src/pages/workspace/accounting/intacct/EnterSageIntacctCredentialsPage.tsx +++ b/src/pages/workspace/accounting/intacct/EnterSageIntacctCredentialsPage.tsx @@ -10,7 +10,7 @@ import Text from '@components/Text'; import TextInput from '@components/TextInput'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import connectToSageIntacct from '@libs/actions/connections/SageIntacct'; +import {connectToSageIntacct} from '@libs/actions/connections/SageIntacct'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 869df2ea4dad..1d1ddf9c61b4 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -603,14 +603,6 @@ type SageIntacctDataElement = { name: string; }; -/** - * Connection data for Sage Intacct - */ -type SageIntacctConnectionData = { - /** Collection of bank accounts */ - bankAccounts: SageIntacctDataElement[]; -}; - /** * Connection config for Sage Intacct */ @@ -1022,31 +1014,10 @@ type NetSuiteConnection = { /** * Connection data for Sage Intacct */ -// eslint-disable-next-line @typescript-eslint/ban-types -type SageIntacctConnectionData = {}; - -/** - * Connection config for Sage Intacct - */ -type SageIntacctConnectiosConfig = OnyxCommon.OnyxValueWithOfflineFeedback<{ - /** Sage Intacct credentials */ - credentials: { - /** Sage Intacct companyID */ - companyID: string; - - /** Sage Intacct password */ - password: string; - - /** Sage Intacct userID */ - userID: string; - }; - - /** Collection of Sage Intacct config errors */ - errors?: OnyxCommon.Errors; - - /** Collection of form field errors */ - errorFields?: OnyxCommon.ErrorFields; -}>; +type SageIntacctConnectionData = { + /** Collection of bank accounts */ + bankAccounts: SageIntacctDataElement[]; +}; /** State of integration connection */ type Connection = { From 85f1d88f3c990bd586ba798f0dcf48986c44f058 Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 5 Jul 2024 11:33:33 +0200 Subject: [PATCH 14/30] update code to match ideas from Export and Import PRs --- src/CONST.ts | 2 +- src/components/SelectionScreen.tsx | 53 ++++++-- .../UpdateSageIntacctApprovalMode.ts | 6 + .../parameters/UpdateSageIntacctAutoSync.ts | 6 + .../UpdateSageIntacctImportEmployees.ts | 6 + .../UpdateSageIntacctSyncReimbursedReports.ts | 6 + ...teSageIntacctSyncReimbursementAccountID.ts | 6 + src/libs/API/parameters/index.ts | 5 + src/libs/API/types.ts | 11 ++ src/libs/actions/Policy/Policy.ts | 5 - src/libs/actions/connections/SageIntacct.ts | 115 ++++++++--------- .../advanced/SageIntacctAdvancedPage.tsx | 70 +++++----- .../SageIntacctPaymentAccountPage.tsx | 47 ++++--- src/types/onyx/Policy.ts | 122 +++++++++--------- 14 files changed, 258 insertions(+), 202 deletions(-) create mode 100644 src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts create mode 100644 src/libs/API/parameters/UpdateSageIntacctAutoSync.ts create mode 100644 src/libs/API/parameters/UpdateSageIntacctImportEmployees.ts create mode 100644 src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts create mode 100644 src/libs/API/parameters/UpdateSageIntacctSyncReimbursementAccountID.ts diff --git a/src/CONST.ts b/src/CONST.ts index 5fae1992963a..cff2d3ccd902 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1344,8 +1344,8 @@ const CONST = { }, SAGE_INTACCT_CONFIG: { - IS_AUTO_SYNC_ENABLED: 'isAutoSyncEnabled', AUTO_SYNC: 'autoSync', + AUTO_SYNC_ENABLED: 'enabled', IMPORT_EMPLOYEES: 'importEmployees', APPROVAL_MODE: 'approvalMode', SYNC: 'sync', diff --git a/src/components/SelectionScreen.tsx b/src/components/SelectionScreen.tsx index af1cdfd171ea..a5bf15445648 100644 --- a/src/components/SelectionScreen.tsx +++ b/src/components/SelectionScreen.tsx @@ -1,12 +1,17 @@ import {isEmpty} from 'lodash'; import React from 'react'; +import type {StyleProp, ViewStyle} from 'react-native'; import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; import * as PolicyUtils from '@libs/PolicyUtils'; import type {AccessVariant} from '@pages/workspace/AccessOrNotFoundWrapper'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {TranslationPaths} from '@src/languages/types'; +import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type {ConnectionName, PolicyFeatureName} from '@src/types/onyx/Policy'; +import type {ReceiptErrors} from '@src/types/onyx/Transaction'; import HeaderWithBackButton from './HeaderWithBackButton'; +import OfflineWithFeedback from './OfflineWithFeedback'; import ScreenWrapper from './ScreenWrapper'; import SelectionList from './SelectionList'; import type RadioListItem from './SelectionList/RadioListItem'; @@ -63,6 +68,18 @@ type SelectionScreenProps = { /** Name of the current connection */ connectionName: ConnectionName; + + /** The type of action that's pending */ + pendingAction?: OnyxCommon.PendingAction | null; + + /** The errors to display */ + errors?: OnyxCommon.Errors | ReceiptErrors | null; + + /** Additional style object for the error row */ + errorRowStyles?: StyleProp; + + /** A function to run when the X button next to the error is clicked */ + onClose?: () => void; }; function SelectionScreen({ @@ -81,8 +98,13 @@ function SelectionScreen({ featureName, shouldBeBlocked, connectionName, + pendingAction, + errors, + errorRowStyles, + onClose, }: SelectionScreenProps) { const {translate} = useLocalize(); + const styles = useThemeStyles(); const policy = PolicyUtils.getPolicy(policyID); const isConnectionEmpty = isEmpty(policy?.connections?.[connectionName]); @@ -102,17 +124,26 @@ function SelectionScreen({ title={translate(title)} onBackButtonPress={onBackButtonPress} /> - + {headerContent} + + + ); diff --git a/src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts b/src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts new file mode 100644 index 000000000000..a0abd7b0c684 --- /dev/null +++ b/src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts @@ -0,0 +1,6 @@ +type UpdateSageIntacctApprovalMode = { + policyID: string; + value: string | null; +}; + +export default UpdateSageIntacctApprovalMode; diff --git a/src/libs/API/parameters/UpdateSageIntacctAutoSync.ts b/src/libs/API/parameters/UpdateSageIntacctAutoSync.ts new file mode 100644 index 000000000000..ebdb17c0129d --- /dev/null +++ b/src/libs/API/parameters/UpdateSageIntacctAutoSync.ts @@ -0,0 +1,6 @@ +type UpdateSageIntacctAutoSync = { + policyID: string; + enabled: boolean; +}; + +export default UpdateSageIntacctAutoSync; diff --git a/src/libs/API/parameters/UpdateSageIntacctImportEmployees.ts b/src/libs/API/parameters/UpdateSageIntacctImportEmployees.ts new file mode 100644 index 000000000000..13f33332537b --- /dev/null +++ b/src/libs/API/parameters/UpdateSageIntacctImportEmployees.ts @@ -0,0 +1,6 @@ +type UpdateSageIntacctImportEmployees = { + policyID: string; + enabled: boolean; +}; + +export default UpdateSageIntacctImportEmployees; diff --git a/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts b/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts new file mode 100644 index 000000000000..fb7f0736a786 --- /dev/null +++ b/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts @@ -0,0 +1,6 @@ +type UpdateSageIntacctSyncReimbursedReports = { + policyID: string; + value: string | false; +}; + +export default UpdateSageIntacctSyncReimbursedReports; diff --git a/src/libs/API/parameters/UpdateSageIntacctSyncReimbursementAccountID.ts b/src/libs/API/parameters/UpdateSageIntacctSyncReimbursementAccountID.ts new file mode 100644 index 000000000000..dcce935eaeff --- /dev/null +++ b/src/libs/API/parameters/UpdateSageIntacctSyncReimbursementAccountID.ts @@ -0,0 +1,6 @@ +type UpdateSageIntacctSyncReimbursementAccountID = { + policyID: string; + value: string | null; +}; + +export default UpdateSageIntacctSyncReimbursementAccountID; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 848af7e34634..420608953993 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -124,6 +124,11 @@ export type {default as DeleteMembersFromWorkspaceParams} from './DeleteMembersF export type {default as OpenWorkspaceParams} from './OpenWorkspaceParams'; export type {default as OpenWorkspaceViewParams} from './OpenWorkspaceViewParams'; export type {default as ConnectPolicyToSageIntacctParams} from './ConnectPolicyToSageIntacctParams'; +export type {default as UpdateSageIntacctAutoSync} from './UpdateSageIntacctAutoSync'; +export type {default as UpdateSageIntacctImportEmployees} from './UpdateSageIntacctImportEmployees'; +export type {default as UpdateSageIntacctApprovalMode} from './UpdateSageIntacctApprovalMode'; +export type {default as UpdateSageIntacctSyncReimbursedReports} from './UpdateSageIntacctSyncReimbursedReports'; +export type {default as UpdateSageIntacctSyncReimbursementAccountID} from './UpdateSageIntacctSyncReimbursementAccountID'; export type {default as OpenWorkspaceReimburseViewParams} from './OpenWorkspaceReimburseViewParams'; export type {default as OpenWorkspaceInvitePageParams} from './OpenWorkspaceInvitePageParams'; export type {default as OpenWorkspaceMembersPageParams} from './OpenWorkspaceMembersPageParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 5708a1659470..238df923df84 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -265,6 +265,11 @@ const WRITE_COMMANDS = { UPDATE_NETSUITE_CUSTOM_FORM_ID_OPTIONS_ENABLED: 'UpdateNetSuiteCustomFormIDOptionsEnabled', REQUEST_EXPENSIFY_CARD_LIMIT_INCREASE: 'RequestExpensifyCardLimitIncrease', CONNECT_POLICY_TO_SAGE_INTACCT: 'ConnectPolicyToSageIntacct', + UPDATE_SAGE_INTACCT_AUTO_SYNC: 'UpdateSageIntacctAutoSync', + UPDATE_SAGE_INTACCT_IMPORT_EMPLOYEES: 'UpdateSageIntacctImportEmployees', + UPDATE_SAGE_INTACCT_APPROVAL_MODE: 'UpdateSageIntacctApprovalMode', + UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS: 'UpdateSageIntacctSyncReimbursedReports', + UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_ACCOUNT_ID: 'UpdateSageIntacctSyncReimbursedAccountID', CONNECT_POLICY_TO_NETSUITE: 'ConnectPolicyToNetSuite', CLEAR_OUTSTANDING_BALANCE: 'ClearOutstandingBalance', } as const; @@ -506,6 +511,12 @@ type WriteCommandParameters = { [WRITE_COMMANDS.REQUEST_REFUND]: null; [WRITE_COMMANDS.CONNECT_POLICY_TO_SAGE_INTACCT]: Parameters.ConnectPolicyToSageIntacctParams; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_AUTO_SYNC]: Parameters.UpdateSageIntacctAutoSync; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_IMPORT_EMPLOYEES]: Parameters.UpdateSageIntacctImportEmployees; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_APPROVAL_MODE]: Parameters.UpdateSageIntacctApprovalMode; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateSageIntacctSyncReimbursedReports; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_ACCOUNT_ID]: Parameters.UpdateSageIntacctSyncReimbursementAccountID; + // Netsuite parameters [WRITE_COMMANDS.UPDATE_NETSUITE_SUBSIDIARY]: Parameters.UpdateNetSuiteSubsidiaryParams; [WRITE_COMMANDS.CONNECT_POLICY_TO_NETSUITE]: Parameters.ConnectPolicyToNetSuiteParams; diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 65b8adad655a..261047e84aea 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -541,10 +541,6 @@ function clearSageIntacctErrorField(policyID: string, fieldName: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {connections: {intacct: {config: {errorFields: {[fieldName]: null}}}}}); } -function clearSageIntacctSyncErrorField(policyID: string, fieldName: string) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {connections: {intacct: {config: {sync: {errorFields: {[fieldName]: null}}}}}}); -} - function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueOf, reimburserEmail: string) { const policy = getPolicy(policyID); @@ -3084,7 +3080,6 @@ export { requestExpensifyCardLimitIncrease, getPoliciesConnectedToSageIntacct, clearSageIntacctErrorField, - clearSageIntacctSyncErrorField, }; export type {NewCustomUnit}; diff --git a/src/libs/actions/connections/SageIntacct.ts b/src/libs/actions/connections/SageIntacct.ts index 4ed193c91e51..911cc1b5d0b8 100644 --- a/src/libs/actions/connections/SageIntacct.ts +++ b/src/libs/actions/connections/SageIntacct.ts @@ -1,12 +1,12 @@ +import type {OnyxUpdate} from 'react-native-onyx'; +import Onyx from 'react-native-onyx'; import * as API from '@libs/API'; import type ConnectPolicyToSageIntacctParams from '@libs/API/parameters/ConnectPolicyToSageIntacctParams'; import {WRITE_COMMANDS} from '@libs/API/types'; import * as ErrorUtils from '@libs/ErrorUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Connections} from '@src/types/onyx/Policy'; -import type {OnyxUpdate} from 'react-native-onyx'; -import Onyx from 'react-native-onyx'; +import type {Connections, SageIntacctConnectiosConfig} from '@src/types/onyx/Policy'; type SageIntacctCredentials = {companyID: string; userID: string; password: string}; @@ -20,7 +20,7 @@ function connectToSageIntacct(policyID: string, credentials: SageIntacctCredenti API.write(WRITE_COMMANDS.CONNECT_POLICY_TO_SAGE_INTACCT, parameters, {}); } -function prepareOnyxData(policyID: string, settingName: keyof Connections['intacct']['config'], settingValue: string | boolean | null) { +function prepareOnyxDataForConfigUpdate(policyID: string, settingName: keyof SageIntacctConnectiosConfig, settingValue: string | boolean | null) { const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -51,7 +51,6 @@ function prepareOnyxData(policyID: string, settingName: keyof Connections['intac connections: { intacct: { config: { - [settingName]: settingValue, pendingFields: { [settingName]: null, }, @@ -73,7 +72,6 @@ function prepareOnyxData(policyID: string, settingName: keyof Connections['intac connections: { intacct: { config: { - [settingName]: settingValue, pendingFields: { [settingName]: null, }, @@ -90,7 +88,13 @@ function prepareOnyxData(policyID: string, settingName: keyof Connections['intac return {optimisticData, failureData, successData}; } -function prepareSyncOnyxData(policyID: string, settingName: keyof Connections['intacct']['config']['sync'], settingValue: string | boolean | null) { +function prepareOnyxDataForSyncUpdate( + policyID: string, + settingName: keyof Connections['intacct']['config']['sync'] | keyof Connections['intacct']['config']['autoSync'], + settingValue: string | boolean | null, + auto = false, +) { + const sync = auto ? 'autoSync' : 'sync'; const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -99,14 +103,14 @@ function prepareSyncOnyxData(policyID: string, settingName: keyof Connections['i connections: { intacct: { config: { - sync: { + [sync]: { [settingName]: settingValue, - pendingFields: { - [settingName]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, - }, - errorFields: { - [settingName]: null, - }, + }, + pendingFields: { + [settingName]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + }, + errorFields: { + [settingName]: null, }, }, }, @@ -123,14 +127,11 @@ function prepareSyncOnyxData(policyID: string, settingName: keyof Connections['i connections: { intacct: { config: { - sync: { - [settingName]: settingValue, - pendingFields: { - [settingName]: null, - }, - errorFields: { - [settingName]: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), - }, + pendingFields: { + [settingName]: null, + }, + errorFields: { + [settingName]: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), }, }, }, @@ -147,14 +148,11 @@ function prepareSyncOnyxData(policyID: string, settingName: keyof Connections['i connections: { intacct: { config: { - sync: { - [settingName]: settingValue, - pendingFields: { - [settingName]: null, - }, - errorFields: { - [settingName]: null, - }, + pendingFields: { + [settingName]: null, + }, + errorFields: { + [settingName]: null, }, }, }, @@ -167,70 +165,61 @@ function prepareSyncOnyxData(policyID: string, settingName: keyof Connections['i } function updateSageIntacctAutoSync(policyID: string, enabled: boolean) { - const {optimisticData, failureData, successData} = prepareOnyxData(policyID, CONST.SAGE_INTACCT_CONFIG.IS_AUTO_SYNC_ENABLED, enabled); + const {optimisticData, failureData, successData} = prepareOnyxDataForSyncUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC_ENABLED, enabled, true); const parameters = { policyID, - connectionName: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, - settingName: CONST.SAGE_INTACCT_CONFIG.IS_AUTO_SYNC_ENABLED, - settingValue: JSON.stringify(enabled), - idempotencyKey: CONST.SAGE_INTACCT_CONFIG.IS_AUTO_SYNC_ENABLED, + enabled, }; - API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); + API.write(WRITE_COMMANDS.UPDATE_SAGE_INTACCT_AUTO_SYNC, parameters, {optimisticData, failureData, successData}); } function updateSageIntacctImportEmployees(policyID: string, enabled: boolean) { - const {optimisticData, failureData, successData} = prepareOnyxData(policyID, CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES, enabled); + const {optimisticData, failureData, successData} = prepareOnyxDataForConfigUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES, enabled); const parameters = { policyID, - connectionName: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, - settingName: CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES, - settingValue: JSON.stringify(enabled), - idempotencyKey: CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES, + enabled, }; - API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); + API.write(WRITE_COMMANDS.UPDATE_SAGE_INTACCT_IMPORT_EMPLOYEES, parameters, {optimisticData, failureData, successData}); } function updateSageIntacctApprovalMode(policyID: string, enabled: boolean) { const approvalModeSettingValue = enabled ? CONST.SAGE_INTACCT.APPROVAL_MODE.APPROVAL_MANUAL : null; - const {optimisticData, failureData, successData} = prepareOnyxData(policyID, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, approvalModeSettingValue); + const {optimisticData, failureData, successData} = prepareOnyxDataForConfigUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, approvalModeSettingValue); const parameters = { policyID, - connectionName: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, - settingName: CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, - settingValue: JSON.stringify(approvalModeSettingValue), - idempotencyKey: CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, + value: approvalModeSettingValue, }; - API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); + API.write(WRITE_COMMANDS.UPDATE_SAGE_INTACCT_APPROVAL_MODE, parameters, {optimisticData, failureData, successData}); } -function updateSageIntacctSyncReimbursedReports(policyID: string, vendorID: string | boolean) { - const settingValue = vendorID ?? false; - const {optimisticData, failureData, successData} = prepareSyncOnyxData(policyID, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS, settingValue); +function updateSageIntacctSyncReimbursedReports(policyID: string, vendorID: string | false) { + const {optimisticData, failureData, successData} = prepareOnyxDataForSyncUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS, vendorID); const parameters = { policyID, - connectionName: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, - settingName: CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS, - settingValue: JSON.stringify(settingValue), - idempotencyKey: CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS, + value: vendorID, }; - API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); + API.write(WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS, parameters, {optimisticData, failureData, successData}); } function updateSageIntacctSyncReimbursementAccountID(policyID: string, vendorID: string | null) { - const {optimisticData, failureData, successData} = prepareSyncOnyxData(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID, vendorID); + const {optimisticData, failureData, successData} = prepareOnyxDataForSyncUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID, vendorID); const parameters = { policyID, - connectionName: CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, - settingName: CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID, - settingValue: JSON.stringify(vendorID), - idempotencyKey: CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID, + value: vendorID, }; - API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); + API.write(WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_ACCOUNT_ID, parameters, {optimisticData, failureData, successData}); } -export {connectToSageIntacct, updateSageIntacctAutoSync, updateSageIntacctImportEmployees, updateSageIntacctApprovalMode, updateSageIntacctSyncReimbursedReports, updateSageIntacctSyncReimbursementAccountID}; +export { + connectToSageIntacct, + updateSageIntacctAutoSync, + updateSageIntacctImportEmployees, + updateSageIntacctApprovalMode, + updateSageIntacctSyncReimbursedReports, + updateSageIntacctSyncReimbursementAccountID, +}; diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 9692f958d6e1..549f6a6a79d2 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -1,4 +1,4 @@ -import React, {useMemo, useState} from 'react'; +import React, {useMemo} from 'react'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; @@ -9,13 +9,7 @@ import Navigation from '@navigation/Navigation'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicy from '@pages/workspace/withPolicy'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; -import { - updateSageIntacctApprovalMode, - updateSageIntacctAutoSync, - updateSageIntacctImportEmployees, - updateSageIntacctSyncReimbursedReports, - updateSageIntacctSyncReimbursementAccountID, -} from '@userActions/connections/SageIntacct'; +import {updateSageIntacctApprovalMode, updateSageIntacctAutoSync, updateSageIntacctImportEmployees, updateSageIntacctSyncReimbursedReports} from '@userActions/connections/SageIntacct'; import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -30,10 +24,8 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { const policyID = policy?.id ?? '-1'; const styles = useThemeStyles(); - const {importEmployees, isAutoSyncEnabled, sync, pendingFields, credentials} = policy?.connections?.intacct?.config ?? {}; - const {data} = policy?.connections?.intacct ?? {}; - - const [isSyncReimbursedReportsEnabled, setIsSyncReimbursedReportsEnabled] = useState(!!sync?.syncReimbursedReports); + const {importEmployees, autoSync, sync, pendingFields, errorFields, credentials} = policy?.connections?.intacct?.config ?? {}; + const {data, config} = policy?.connections?.intacct ?? {}; const currentSageIntacctOrganizationName = credentials?.companyID; @@ -41,52 +33,60 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { () => [ { label: translate('workspace.sageIntacct.autoSync'), - onToggle: (enabled: boolean) => { - updateSageIntacctAutoSync(policyID, enabled); - // Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, 'autoSync', enabled); - }, - pendingAction: pendingFields?.isAutoSyncEnabled, - error: ErrorUtils.getLatestErrorField(sync ?? {}, CONST.SAGE_INTACCT_CONFIG.IS_AUTO_SYNC_ENABLED), - onCloseError: () => Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.IS_AUTO_SYNC_ENABLED), description: translate('workspace.sageIntacct.autoSyncDescription'), - isActive: !!isAutoSyncEnabled, + isActive: !!autoSync?.enabled, + onToggle: (enabled: boolean) => updateSageIntacctAutoSync(policyID, enabled), + pendingAction: pendingFields?.autoSync, + error: ErrorUtils.getLatestErrorField(config, CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC_ENABLED), + onCloseError: () => Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC_ENABLED), }, { label: translate('workspace.sageIntacct.inviteEmployees'), + description: translate('workspace.sageIntacct.inviteEmployeesDescription'), + isActive: !!importEmployees, onToggle: (enabled: boolean) => { updateSageIntacctImportEmployees(policyID, enabled); updateSageIntacctApprovalMode(policyID, enabled); }, pendingAction: pendingFields?.importEmployees, error: - ErrorUtils.getLatestErrorField(sync ?? {}, CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES) ?? - ErrorUtils.getLatestErrorField(sync ?? {}, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE), + ErrorUtils.getLatestErrorField(config ?? {}, CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES) ?? + ErrorUtils.getLatestErrorField(config ?? {}, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE), onCloseError: () => { Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES); Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE); }, - description: translate('workspace.sageIntacct.inviteEmployeesDescription'), - isActive: !!importEmployees, }, { label: translate('workspace.sageIntacct.syncReimbursedReports'), + description: translate('workspace.sageIntacct.syncReimbursedReportsDescription'), + isActive: !!sync?.syncReimbursedReports, onToggle: (enabled: boolean) => { - setIsSyncReimbursedReportsEnabled(enabled); if (!enabled) { updateSageIntacctSyncReimbursedReports(policyID, false); - updateSageIntacctSyncReimbursementAccountID(policyID, null); + } else if (sync?.reimbursementAccountID !== undefined) { + updateSageIntacctSyncReimbursedReports(policyID, sync?.reimbursementAccountID); } }, - pendingAction: sync?.pendingFields?.syncReimbursedReports, - error: ErrorUtils.getLatestErrorField(sync ?? {}, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS), + pendingAction: pendingFields?.syncReimbursedReports, + error: ErrorUtils.getLatestErrorField(config ?? {}, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS), onCloseError: () => { - Policy.clearSageIntacctSyncErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS); + Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS); }, - description: translate('workspace.sageIntacct.syncReimbursedReportsDescription'), - isActive: isSyncReimbursedReportsEnabled, }, ], - [translate, pendingFields?.isAutoSyncEnabled, pendingFields?.importEmployees, sync, isAutoSyncEnabled, importEmployees, isSyncReimbursedReportsEnabled, policyID], + [ + translate, + autoSync?.enabled, + pendingFields?.autoSync, + pendingFields?.importEmployees, + pendingFields?.syncReimbursedReports, + config, + importEmployees, + sync?.syncReimbursedReports, + sync?.reimbursementAccountID, + policyID, + ], ); return ( @@ -116,17 +116,17 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { /> ))} - {isSyncReimbursedReportsEnabled && ( + {!!sync?.syncReimbursedReports && ( Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_PAYMENT_ACCOUNT.getRoute(policyID))} - brickRoadIndicator={sync?.errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} + brickRoadIndicator={errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} /> )} diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx index 4d3bae37b2d7..f16f2b8fe480 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx @@ -2,7 +2,6 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; import * as Illustrations from '@components/Icon/Illustrations'; -import OfflineWithFeedback from '@components/OfflineWithFeedback'; import RadioListItem from '@components/SelectionList/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; @@ -26,9 +25,9 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { const policyID = policy?.id ?? '-1'; - const {sync} = policy?.connections?.intacct?.config ?? {}; + const {config} = policy?.connections?.intacct ?? {}; - const vendorSelectorOptions = useMemo(() => getSageIntacctBankAccounts(policy, sync?.reimbursementAccountID), [policy, sync?.reimbursementAccountID]); + const vendorSelectorOptions = useMemo(() => getSageIntacctBankAccounts(policy, config?.sync?.reimbursementAccountID), [policy, config?.sync?.reimbursementAccountID]); const listHeaderComponent = useMemo( () => ( @@ -41,13 +40,13 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { const updateDefaultVendor = useCallback( ({value}: SelectorType) => { - if (value !== sync?.reimbursementAccountID) { + if (value !== config?.sync?.reimbursementAccountID) { updateSageIntacctSyncReimbursementAccountID(policyID, value); updateSageIntacctSyncReimbursedReports(policyID, value); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID)); }, - [policyID, sync?.reimbursementAccountID], + [policyID, config?.sync?.reimbursementAccountID], ); const listEmptyContent = useMemo( @@ -64,26 +63,24 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { ); return ( - Policy.clearSageIntacctSyncErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID)} - > - mode.isSelected)?.keyForList} - headerContent={listHeaderComponent} - onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID))} - title="workspace.sageIntacct.paymentAccount" - listEmptyContent={listEmptyContent} - connectionName={CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT} - /> - + mode.isSelected)?.keyForList} + headerContent={listHeaderComponent} + onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID))} + title="workspace.sageIntacct.paymentAccount" + listEmptyContent={listEmptyContent} + connectionName={CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT} + pendingAction={config?.pendingFields?.reimbursementAccountID} + errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID)} + errorRowStyles={[styles.ph5, styles.mv2]} + onClose={() => Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID)} + /> ); } diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index b7adc4de604f..f06d86da28ee 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -594,68 +594,6 @@ type XeroConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback<{ errorFields?: OnyxCommon.ErrorFields; }>; -/** One of the SageIntacctConnectionData object elements */ -type SageIntacctDataElement = { - /** Element ID */ - id: string; - - /** Element name */ - name: string; -}; - -/** - * Connection config for Sage Intacct - */ -type SageIntacctConnectiosConfig = OnyxCommon.OnyxValueWithOfflineFeedback<{ - /** Whether employees should be imported from Sage Intacct */ - importEmployees: boolean; - - /** Sage Intacct approval mode */ - approvalMode: ValueOf | null; - - /** Whether auto sync is enabled */ - isAutoSyncEnabled: boolean; - - /** Sage Intacct credentials */ - credentials: { - /** Sage Intacct companyID */ - companyID: string; - - /** Sage Intacct password */ - password: string; - - /** Sage Intacct userID */ - userID: string; - }; - - /** Configuration of automatic synchronization from Sage Intacct to the app */ - autoSync: { - /** ID of sync job */ - jobID: string; - - /** Whether changes made in QuickBooks Online should be reflected into the app automatically */ - enabled: boolean; - }; - - /** Sage Intacct sync */ - sync: OnyxCommon.OnyxValueWithOfflineFeedback<{ - /** ID of the bank account for Sage Intacct bill payment account */ - reimbursementAccountID?: string; - - /** Whether the reimbursed reports should be synched */ - syncReimbursedReports: boolean; - - /** Collection of form field errors */ - errorFields?: OnyxCommon.ErrorFields; - }>; - - /** Collection of Sage Intacct config errors */ - errors?: OnyxCommon.Errors; - - /** Collection of form field errors */ - errorFields?: OnyxCommon.ErrorFields; -}>; - /** Data stored about subsidiaries from NetSuite */ type NetSuiteSubsidiary = { /** ID of the subsidiary */ @@ -1017,6 +955,15 @@ type NetSuiteConnection = { tokenSecret: string; }; +/** One of the SageIntacctConnectionData object elements */ +type SageIntacctDataElement = { + /** Element ID */ + id: string; + + /** Element name */ + name: string; +}; + /** * Connection data for Sage Intacct */ @@ -1025,6 +972,56 @@ type SageIntacctConnectionData = { bankAccounts: SageIntacctDataElement[]; }; +/** Sage Intacct sync */ +type SageIntacctSyncConfig = { + /** ID of the bank account for Sage Intacct bill payment account */ + reimbursementAccountID?: string; + + /** Whether the reimbursed reports should be synched */ + syncReimbursedReports: boolean | string; +}; + +/** + * Connection config for Sage Intacct + */ +type SageIntacctConnectiosConfig = OnyxCommon.OnyxValueWithOfflineFeedback< + { + /** Sage Intacct credentials */ + credentials: { + /** Sage Intacct companyID */ + companyID: string; + + /** Sage Intacct password */ + password: string; + + /** Sage Intacct userID */ + userID: string; + }; + + /** Whether employees should be imported from Sage Intacct */ + importEmployees: boolean; + + /** Sage Intacct approval mode */ + approvalMode: ValueOf | null; + + /** Configuration of automatic synchronization from Sage Intacct to the app */ + autoSync: { + /** Whether changes made in Sage Intacct should be reflected into the app automatically */ + enabled: boolean; + }; + + /** Sage Intacct sync */ + sync: SageIntacctSyncConfig; + + /** Collection of Sage Intacct config errors */ + errors?: OnyxCommon.Errors; + + /** Collection of form field errors */ + errorFields?: OnyxCommon.ErrorFields; + }, + keyof SageIntacctSyncConfig +>; + /** State of integration connection */ type Connection = { /** State of the last synchronization */ @@ -1397,4 +1394,5 @@ export type { ConnectionLastSync, NetSuiteSubsidiary, SageIntacctDataElement, + SageIntacctConnectiosConfig, }; From fd4e555401342f7eb60ed47bc4f16ae1e87df08e Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 5 Jul 2024 11:50:36 +0200 Subject: [PATCH 15/30] prettier --- .../Navigation/AppNavigator/ModalStackNavigators/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index e309d12e94f5..4302bbbb1688 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -358,7 +358,8 @@ const SettingsModalStackNavigator = createModalStackNavigator('../../../../pages/workspace/accounting/intacct/EnterSageIntacctCredentialsPage').default, [SCREENS.WORKSPACE.ACCOUNTING.EXISTING_SAGE_INTACCT_CONNECTIONS]: () => require('../../../../pages/workspace/accounting/intacct/ExistingConnectionsPage').default, [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_ADVANCED]: () => require('../../../../pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage').default, - [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_PAYMENT_ACCOUNT]: () => require('../../../../pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage').default, + [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_PAYMENT_ACCOUNT]: () => + require('../../../../pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage').default, [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY]: () => require('../../../../pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage').default, [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET]: () => require('../../../../pages/workspace/workflows/WorkspaceAutoReportingMonthlyOffsetPage').default, [SCREENS.WORKSPACE.TAX_EDIT]: () => require('../../../../pages/workspace/taxes/WorkspaceEditTaxPage').default, From 23d112b0d21029255ca57417d95bff2c61739971 Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 5 Jul 2024 12:12:57 +0200 Subject: [PATCH 16/30] add case for payment account --- src/languages/en.ts | 1 - src/languages/es.ts | 1 - .../intacct/advanced/SageIntacctAdvancedPage.tsx | 12 +++++++++++- .../advanced/SageIntacctPaymentAccountPage.tsx | 10 ---------- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index ebfcdffdfb73..45c9849dbf39 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2451,7 +2451,6 @@ export default { syncReimbursedReportsDescription: 'When a report is reimbursed using Expensify ACH, the corresponding puchase bill will be created in the Sage Intacct account below.', paymentAccount: 'Sage Intacct payment account', notConfigured: 'Not configured', - paymentAccountDescription: 'Some desc', }, type: { free: 'Free', diff --git a/src/languages/es.ts b/src/languages/es.ts index f9f3dd9a3b7b..135d00abe37c 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2493,7 +2493,6 @@ export default { 'Cuando un informe se reembolsa utilizando Expensify ACH, la factura de compra correspondiente se creará en la cuenta de Sage Intacct a continuación.', paymentAccount: 'Cuenta de pago Sage Intacct', notConfigured: 'No configurado', - paymentAccountDescription: 'Descripción', }, type: { free: 'Gratis', diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 549f6a6a79d2..a8dfff9d7bbb 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -9,7 +9,13 @@ import Navigation from '@navigation/Navigation'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicy from '@pages/workspace/withPolicy'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; -import {updateSageIntacctApprovalMode, updateSageIntacctAutoSync, updateSageIntacctImportEmployees, updateSageIntacctSyncReimbursedReports} from '@userActions/connections/SageIntacct'; +import { + updateSageIntacctApprovalMode, + updateSageIntacctAutoSync, + updateSageIntacctImportEmployees, + updateSageIntacctSyncReimbursedReports, + updateSageIntacctSyncReimbursementAccountID, +} from '@userActions/connections/SageIntacct'; import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -66,6 +72,10 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { updateSageIntacctSyncReimbursedReports(policyID, false); } else if (sync?.reimbursementAccountID !== undefined) { updateSageIntacctSyncReimbursedReports(policyID, sync?.reimbursementAccountID); + } else { + const reimbursementAccountID = data?.bankAccounts[0]?.id ?? '-1'; + updateSageIntacctSyncReimbursedReports(policyID, reimbursementAccountID); + updateSageIntacctSyncReimbursementAccountID(policyID, reimbursementAccountID); } }, pendingAction: pendingFields?.syncReimbursedReports, diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx index f16f2b8fe480..0cbad250db58 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx @@ -29,15 +29,6 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { const vendorSelectorOptions = useMemo(() => getSageIntacctBankAccounts(policy, config?.sync?.reimbursementAccountID), [policy, config?.sync?.reimbursementAccountID]); - const listHeaderComponent = useMemo( - () => ( - - {translate('workspace.sageIntacct.paymentAccountDescription')} - - ), - [translate, styles.pb2, styles.ph5, styles.pb5, styles.textNormal], - ); - const updateDefaultVendor = useCallback( ({value}: SelectorType) => { if (value !== config?.sync?.reimbursementAccountID) { @@ -71,7 +62,6 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { listItem={RadioListItem} onSelectRow={updateDefaultVendor} initiallyFocusedOptionKey={vendorSelectorOptions.find((mode) => mode.isSelected)?.keyForList} - headerContent={listHeaderComponent} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID))} title="workspace.sageIntacct.paymentAccount" listEmptyContent={listEmptyContent} From ab491dffb69330b6b94035d673d01a274860c3b5 Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 5 Jul 2024 12:15:26 +0200 Subject: [PATCH 17/30] fix lint --- .../accounting/intacct/advanced/SageIntacctAdvancedPage.tsx | 1 + .../intacct/advanced/SageIntacctPaymentAccountPage.tsx | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index a8dfff9d7bbb..887b379042c5 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -96,6 +96,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { sync?.syncReimbursedReports, sync?.reimbursementAccountID, policyID, + data?.bankAccounts, ], ); diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx index 0cbad250db58..281ca9c312c5 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx @@ -1,11 +1,9 @@ import React, {useCallback, useMemo} from 'react'; -import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; import * as Illustrations from '@components/Icon/Illustrations'; import RadioListItem from '@components/SelectionList/RadioListItem'; import type {SelectorType} from '@components/SelectionScreen'; import SelectionScreen from '@components/SelectionScreen'; -import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; From b244a9c52ef4c0b755c3575ee397b0214a11de8e Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 5 Jul 2024 12:59:30 +0200 Subject: [PATCH 18/30] offline state for auto sync toggle --- .../intacct/advanced/SageIntacctAdvancedPage.tsx | 2 +- src/types/onyx/Policy.ts | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 887b379042c5..2bf72572efe2 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -42,7 +42,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { description: translate('workspace.sageIntacct.autoSyncDescription'), isActive: !!autoSync?.enabled, onToggle: (enabled: boolean) => updateSageIntacctAutoSync(policyID, enabled), - pendingAction: pendingFields?.autoSync, + pendingAction: pendingFields?.enabled, error: ErrorUtils.getLatestErrorField(config, CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC_ENABLED), onCloseError: () => Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC_ENABLED), }, diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index f06d86da28ee..b7e142c75371 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -972,6 +972,12 @@ type SageIntacctConnectionData = { bankAccounts: SageIntacctDataElement[]; }; +/** Configuration of automatic synchronization from Sage Intacct to the app */ +type SageIntacctAutoSyncConfig = { + /** Whether changes made in Sage Intacct should be reflected into the app automatically */ + enabled: boolean; +}; + /** Sage Intacct sync */ type SageIntacctSyncConfig = { /** ID of the bank account for Sage Intacct bill payment account */ @@ -1005,10 +1011,7 @@ type SageIntacctConnectiosConfig = OnyxCommon.OnyxValueWithOfflineFeedback< approvalMode: ValueOf | null; /** Configuration of automatic synchronization from Sage Intacct to the app */ - autoSync: { - /** Whether changes made in Sage Intacct should be reflected into the app automatically */ - enabled: boolean; - }; + autoSync: SageIntacctAutoSyncConfig; /** Sage Intacct sync */ sync: SageIntacctSyncConfig; @@ -1019,7 +1022,7 @@ type SageIntacctConnectiosConfig = OnyxCommon.OnyxValueWithOfflineFeedback< /** Collection of form field errors */ errorFields?: OnyxCommon.ErrorFields; }, - keyof SageIntacctSyncConfig + keyof SageIntacctSyncConfig | keyof SageIntacctAutoSyncConfig >; /** State of integration connection */ From 0ae9d8af3fb265b57fae449b88d1fcf6781b2bb0 Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 8 Jul 2024 08:53:40 +0200 Subject: [PATCH 19/30] safe area padding bottom --- src/components/SelectionScreen.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SelectionScreen.tsx b/src/components/SelectionScreen.tsx index a5bf15445648..bcc80a5970b1 100644 --- a/src/components/SelectionScreen.tsx +++ b/src/components/SelectionScreen.tsx @@ -117,7 +117,7 @@ function SelectionScreen({ shouldBeBlocked={isConnectionEmpty || shouldBeBlocked} > Date: Mon, 8 Jul 2024 14:14:49 +0200 Subject: [PATCH 20/30] update API use --- src/CONST.ts | 2 +- .../UpdateSageIntacctSyncReimbursedReports.ts | 2 +- src/libs/API/types.ts | 4 ++-- src/libs/actions/connections/SageIntacct.ts | 10 +++++----- .../intacct/advanced/SageIntacctAdvancedPage.tsx | 11 ++++------- .../advanced/SageIntacctPaymentAccountPage.tsx | 7 +++---- 6 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index ddb15d2dcf78..10282ef1e356 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1351,7 +1351,7 @@ const CONST = { APPROVAL_MODE: 'approvalMode', SYNC: 'sync', SYNC_REIMBURSED_REPORTS: 'syncReimbursedReports', - REIMBUSERED_ACCOUNT_ID: 'reimbursementAccountID', + REIMBURSEMENT_ACCOUNT_ID: 'reimbursementAccountID', }, SAGE_INTACCT: { diff --git a/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts b/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts index fb7f0736a786..4004ef37affc 100644 --- a/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts +++ b/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts @@ -1,6 +1,6 @@ type UpdateSageIntacctSyncReimbursedReports = { policyID: string; - value: string | false; + value: boolean; }; export default UpdateSageIntacctSyncReimbursedReports; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 4148453d7a75..b3405d8c0346 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -272,7 +272,7 @@ const WRITE_COMMANDS = { UPDATE_SAGE_INTACCT_IMPORT_EMPLOYEES: 'UpdateSageIntacctImportEmployees', UPDATE_SAGE_INTACCT_APPROVAL_MODE: 'UpdateSageIntacctApprovalMode', UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS: 'UpdateSageIntacctSyncReimbursedReports', - UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_ACCOUNT_ID: 'UpdateSageIntacctSyncReimbursedAccountID', + UPDATE_SAGE_INTACCT_SYNC_REIMBURSEMENT_ACCOUNT_ID: 'UpdateSageIntacctSyncReimbursementAccountID', CONNECT_POLICY_TO_NETSUITE: 'ConnectPolicyToNetSuite', CLEAR_OUTSTANDING_BALANCE: 'ClearOutstandingBalance', } as const; @@ -520,7 +520,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_IMPORT_EMPLOYEES]: Parameters.UpdateSageIntacctImportEmployees; [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_APPROVAL_MODE]: Parameters.UpdateSageIntacctApprovalMode; [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateSageIntacctSyncReimbursedReports; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_ACCOUNT_ID]: Parameters.UpdateSageIntacctSyncReimbursementAccountID; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSEMENT_ACCOUNT_ID]: Parameters.UpdateSageIntacctSyncReimbursementAccountID; // Netsuite parameters [WRITE_COMMANDS.UPDATE_NETSUITE_SUBSIDIARY]: Parameters.UpdateNetSuiteSubsidiaryParams; diff --git a/src/libs/actions/connections/SageIntacct.ts b/src/libs/actions/connections/SageIntacct.ts index 911cc1b5d0b8..808352764aac 100644 --- a/src/libs/actions/connections/SageIntacct.ts +++ b/src/libs/actions/connections/SageIntacct.ts @@ -195,24 +195,24 @@ function updateSageIntacctApprovalMode(policyID: string, enabled: boolean) { API.write(WRITE_COMMANDS.UPDATE_SAGE_INTACCT_APPROVAL_MODE, parameters, {optimisticData, failureData, successData}); } -function updateSageIntacctSyncReimbursedReports(policyID: string, vendorID: string | false) { - const {optimisticData, failureData, successData} = prepareOnyxDataForSyncUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS, vendorID); +function updateSageIntacctSyncReimbursedReports(policyID: string, enabled: boolean) { + const {optimisticData, failureData, successData} = prepareOnyxDataForSyncUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS, enabled); const parameters = { policyID, - value: vendorID, + value: enabled, }; API.write(WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS, parameters, {optimisticData, failureData, successData}); } function updateSageIntacctSyncReimbursementAccountID(policyID: string, vendorID: string | null) { - const {optimisticData, failureData, successData} = prepareOnyxDataForSyncUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID, vendorID); + const {optimisticData, failureData, successData} = prepareOnyxDataForSyncUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBURSEMENT_ACCOUNT_ID, vendorID); const parameters = { policyID, value: vendorID, }; - API.write(WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_ACCOUNT_ID, parameters, {optimisticData, failureData, successData}); + API.write(WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSEMENT_ACCOUNT_ID, parameters, {optimisticData, failureData, successData}); } export { diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 2bf72572efe2..62cf83e7281e 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -68,13 +68,10 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { description: translate('workspace.sageIntacct.syncReimbursedReportsDescription'), isActive: !!sync?.syncReimbursedReports, onToggle: (enabled: boolean) => { - if (!enabled) { - updateSageIntacctSyncReimbursedReports(policyID, false); - } else if (sync?.reimbursementAccountID !== undefined) { - updateSageIntacctSyncReimbursedReports(policyID, sync?.reimbursementAccountID); - } else { + updateSageIntacctSyncReimbursedReports(policyID, enabled); + + if (enabled && sync?.reimbursementAccountID === undefined) { const reimbursementAccountID = data?.bankAccounts[0]?.id ?? '-1'; - updateSageIntacctSyncReimbursedReports(policyID, reimbursementAccountID); updateSageIntacctSyncReimbursementAccountID(policyID, reimbursementAccountID); } }, @@ -88,7 +85,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { [ translate, autoSync?.enabled, - pendingFields?.autoSync, + pendingFields?.enabled, pendingFields?.importEmployees, pendingFields?.syncReimbursedReports, config, diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx index 281ca9c312c5..aadcd8520ea0 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx @@ -12,7 +12,7 @@ import {getSageIntacctBankAccounts} from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; -import {updateSageIntacctSyncReimbursedReports, updateSageIntacctSyncReimbursementAccountID} from '@userActions/connections/SageIntacct'; +import {updateSageIntacctSyncReimbursementAccountID} from '@userActions/connections/SageIntacct'; import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -31,7 +31,6 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { ({value}: SelectorType) => { if (value !== config?.sync?.reimbursementAccountID) { updateSageIntacctSyncReimbursementAccountID(policyID, value); - updateSageIntacctSyncReimbursedReports(policyID, value); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_ADVANCED.getRoute(policyID)); }, @@ -65,9 +64,9 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT} pendingAction={config?.pendingFields?.reimbursementAccountID} - errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID)} + errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.SAGE_INTACCT_CONFIG.REIMBURSEMENT_ACCOUNT_ID)} errorRowStyles={[styles.ph5, styles.mv2]} - onClose={() => Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBUSERED_ACCOUNT_ID)} + onClose={() => Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBURSEMENT_ACCOUNT_ID)} /> ); } From 14a677c463a88ee4686063e1fc76c9a4c09598ec Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 8 Jul 2024 16:04:21 +0200 Subject: [PATCH 21/30] use correct arguments in endpoints --- src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts | 2 +- .../parameters/UpdateSageIntacctSyncReimbursedReports.ts | 2 +- .../UpdateSageIntacctSyncReimbursementAccountID.ts | 2 +- src/libs/actions/connections/SageIntacct.ts | 6 +++--- .../accounting/intacct/advanced/SageIntacctAdvancedPage.tsx | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts b/src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts index a0abd7b0c684..7e90a97210e4 100644 --- a/src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts +++ b/src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts @@ -1,6 +1,6 @@ type UpdateSageIntacctApprovalMode = { policyID: string; - value: string | null; + value: string; }; export default UpdateSageIntacctApprovalMode; diff --git a/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts b/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts index 4004ef37affc..a073702a43b0 100644 --- a/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts +++ b/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts @@ -1,6 +1,6 @@ type UpdateSageIntacctSyncReimbursedReports = { policyID: string; - value: boolean; + enabled: boolean; }; export default UpdateSageIntacctSyncReimbursedReports; diff --git a/src/libs/API/parameters/UpdateSageIntacctSyncReimbursementAccountID.ts b/src/libs/API/parameters/UpdateSageIntacctSyncReimbursementAccountID.ts index dcce935eaeff..b992a100585b 100644 --- a/src/libs/API/parameters/UpdateSageIntacctSyncReimbursementAccountID.ts +++ b/src/libs/API/parameters/UpdateSageIntacctSyncReimbursementAccountID.ts @@ -1,6 +1,6 @@ type UpdateSageIntacctSyncReimbursementAccountID = { policyID: string; - value: string | null; + vendorID: string | null; }; export default UpdateSageIntacctSyncReimbursementAccountID; diff --git a/src/libs/actions/connections/SageIntacct.ts b/src/libs/actions/connections/SageIntacct.ts index 808352764aac..da3091a26476 100644 --- a/src/libs/actions/connections/SageIntacct.ts +++ b/src/libs/actions/connections/SageIntacct.ts @@ -185,7 +185,7 @@ function updateSageIntacctImportEmployees(policyID: string, enabled: boolean) { } function updateSageIntacctApprovalMode(policyID: string, enabled: boolean) { - const approvalModeSettingValue = enabled ? CONST.SAGE_INTACCT.APPROVAL_MODE.APPROVAL_MANUAL : null; + const approvalModeSettingValue = enabled ? CONST.SAGE_INTACCT.APPROVAL_MODE.APPROVAL_MANUAL : ''; const {optimisticData, failureData, successData} = prepareOnyxDataForConfigUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE, approvalModeSettingValue); const parameters = { policyID, @@ -199,7 +199,7 @@ function updateSageIntacctSyncReimbursedReports(policyID: string, enabled: boole const {optimisticData, failureData, successData} = prepareOnyxDataForSyncUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS, enabled); const parameters = { policyID, - value: enabled, + enabled, }; API.write(WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS, parameters, {optimisticData, failureData, successData}); @@ -209,7 +209,7 @@ function updateSageIntacctSyncReimbursementAccountID(policyID: string, vendorID: const {optimisticData, failureData, successData} = prepareOnyxDataForSyncUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBURSEMENT_ACCOUNT_ID, vendorID); const parameters = { policyID, - value: vendorID, + vendorID, }; API.write(WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSEMENT_ACCOUNT_ID, parameters, {optimisticData, failureData, successData}); diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 62cf83e7281e..d4b21d76d1e7 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -70,7 +70,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { onToggle: (enabled: boolean) => { updateSageIntacctSyncReimbursedReports(policyID, enabled); - if (enabled && sync?.reimbursementAccountID === undefined) { + if (enabled && !sync?.reimbursementAccountID) { const reimbursementAccountID = data?.bankAccounts[0]?.id ?? '-1'; updateSageIntacctSyncReimbursementAccountID(policyID, reimbursementAccountID); } From 4f3b790559ab2b3dd6a27d3b20d5932f55449835 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 9 Jul 2024 12:15:14 +0200 Subject: [PATCH 22/30] address review comments --- src/libs/actions/connections/SageIntacct.ts | 2 +- .../accounting/intacct/advanced/SageIntacctAdvancedPage.tsx | 4 +++- .../intacct/advanced/SageIntacctPaymentAccountPage.tsx | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/connections/SageIntacct.ts b/src/libs/actions/connections/SageIntacct.ts index da3091a26476..db8aaca0ccae 100644 --- a/src/libs/actions/connections/SageIntacct.ts +++ b/src/libs/actions/connections/SageIntacct.ts @@ -94,7 +94,7 @@ function prepareOnyxDataForSyncUpdate( settingValue: string | boolean | null, auto = false, ) { - const sync = auto ? 'autoSync' : 'sync'; + const sync = auto ? CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC : CONST.SAGE_INTACCT_CONFIG.SYNC; const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index d4b21d76d1e7..4e268e933f96 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -108,9 +108,11 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { contentContainerStyle={styles.pb2} titleStyle={styles.ph5} connectionName={CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT} + onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING.getRoute(policyID))} > {toggleSections.map((section) => ( Date: Tue, 9 Jul 2024 13:12:48 +0200 Subject: [PATCH 23/30] include safe area padding bottom on errors --- src/components/SelectionScreen.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/SelectionScreen.tsx b/src/components/SelectionScreen.tsx index bcc80a5970b1..8e1b0a88c875 100644 --- a/src/components/SelectionScreen.tsx +++ b/src/components/SelectionScreen.tsx @@ -10,6 +10,7 @@ import type {TranslationPaths} from '@src/languages/types'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type {ConnectionName, PolicyFeatureName} from '@src/types/onyx/Policy'; import type {ReceiptErrors} from '@src/types/onyx/Transaction'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; import HeaderWithBackButton from './HeaderWithBackButton'; import OfflineWithFeedback from './OfflineWithFeedback'; import ScreenWrapper from './ScreenWrapper'; @@ -117,7 +118,7 @@ function SelectionScreen({ shouldBeBlocked={isConnectionEmpty || shouldBeBlocked} > Date: Tue, 9 Jul 2024 13:31:21 +0200 Subject: [PATCH 24/30] fix -1 as reimbursementaccountid --- .../accounting/intacct/advanced/SageIntacctAdvancedPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 4e268e933f96..50a5256ebd72 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -71,7 +71,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { updateSageIntacctSyncReimbursedReports(policyID, enabled); if (enabled && !sync?.reimbursementAccountID) { - const reimbursementAccountID = data?.bankAccounts[0]?.id ?? '-1'; + const reimbursementAccountID = data?.bankAccounts[0]?.id ?? null; updateSageIntacctSyncReimbursementAccountID(policyID, reimbursementAccountID); } }, From b4fce17e9d09999a32de6fc82c7d11db6a1cf5b8 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 9 Jul 2024 17:48:52 +0200 Subject: [PATCH 25/30] fix translations after the merge --- src/languages/en.ts | 19 ++++++++----------- src/languages/es.ts | 21 +++++++++------------ 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 4d33629852ae..bbd2de94adc2 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2267,6 +2267,14 @@ export default { exportPreferredExporterSubNote: 'Once set, the preferred exporter will see reports for export in their account.', noAccountsFound: 'No accounts found', noAccountsFoundDescription: `Add the account in Sage Intacct and sync the connection again.`, + autoSync: 'Auto-sync', + autoSyncDescription: 'Sync Sage Intacct and Expensify automatically, every day.', + inviteEmployees: 'Invite employees', + inviteEmployeesDescription: + 'Import Sage Intacct employee records and invite employees to this workspace. Your approval workflow will default to manager approval and can be furthered configured on the Members page.', + syncReimbursedReports: 'Sync reimbursed reports', + syncReimbursedReportsDescription: 'When a report is reimbursed using Expensify ACH, the corresponding puchase bill will be created in the Sage Intacct account below.', + paymentAccount: 'Sage Intacct payment account', }, netsuite: { subsidiary: 'Subsidiary', @@ -2505,17 +2513,6 @@ export default { existingConnections: 'Existing connections', sageIntacctLastSync: (formattedDate: string) => `Sage Intacct - Last synced ${formattedDate}`, }, - sageIntacct: { - autoSync: 'Auto-sync', - autoSyncDescription: 'Sync Sage Intacct and Expensify automatically, every day.', - inviteEmployees: 'Invite employees', - inviteEmployeesDescription: - 'Import Sage Intacct employee records and invite employees to this workspace. Your approval workflow will default to manager approval and can be furthered configured on the Members page.', - syncReimbursedReports: 'Sync reimbursed reports', - syncReimbursedReportsDescription: 'When a report is reimbursed using Expensify ACH, the corresponding puchase bill will be created in the Sage Intacct account below.', - paymentAccount: 'Sage Intacct payment account', - notConfigured: 'Not configured', - }, type: { free: 'Free', control: 'Control', diff --git a/src/languages/es.ts b/src/languages/es.ts index a3ba4682503e..a4277b1c53c6 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2308,6 +2308,15 @@ export default { exportPreferredExporterSubNote: 'Una vez configurado, el exportador preferido verá los informes para exportar en su cuenta.', noAccountsFound: 'No se ha encontrado ninguna cuenta', noAccountsFoundDescription: 'Añade la cuenta en Sage Intacct y sincroniza de nuevo la conexión.', + autoSync: 'Sincronización automática', + autoSyncDescription: 'Sincronice Sage Intacct y Expensify automáticamente, todos los días.', + inviteEmployees: 'Invitar a los empleados', + inviteEmployeesDescription: + 'Importe los registros de empleados de Sage Intacct e invite a los empleados a este espacio de trabajo. Su flujo de trabajo de aprobación será por defecto la aprobación del gerente y se puede configurar aún más en la página Miembros.', + syncReimbursedReports: 'Sincronizar informes reembolsados', + syncReimbursedReportsDescription: + 'Cuando un informe se reembolsa utilizando Expensify ACH, la factura de compra correspondiente se creará en la cuenta de Sage Intacct a continuación.', + paymentAccount: 'Cuenta de pago Sage Intacct', }, netsuite: { subsidiary: 'Subsidiaria', @@ -2549,18 +2558,6 @@ export default { existingConnections: 'Conexiones existentes', sageIntacctLastSync: (formattedDate: string) => `Sage Intacct - Última sincronización ${formattedDate}`, }, - sageIntacct: { - autoSync: 'Sincronización automática', - autoSyncDescription: 'Sincronice Sage Intacct y Expensify automáticamente, todos los días.', - inviteEmployees: 'Invitar a los empleados', - inviteEmployeesDescription: - 'Importe los registros de empleados de Sage Intacct e invite a los empleados a este espacio de trabajo. Su flujo de trabajo de aprobación será por defecto la aprobación del gerente y se puede configurar aún más en la página Miembros.', - syncReimbursedReports: 'Sincronizar informes reembolsados', - syncReimbursedReportsDescription: - 'Cuando un informe se reembolsa utilizando Expensify ACH, la factura de compra correspondiente se creará en la cuenta de Sage Intacct a continuación.', - paymentAccount: 'Cuenta de pago Sage Intacct', - notConfigured: 'No configurado', - }, type: { free: 'Gratis', control: 'Control', From efec0aac561db2b8426540c579acc45e5ab0f7e8 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 9 Jul 2024 17:49:13 +0200 Subject: [PATCH 26/30] use generic type params pattern --- .../API/parameters/UpdateSageIntacctApprovalMode.ts | 6 ------ src/libs/API/parameters/UpdateSageIntacctAutoSync.ts | 6 ------ .../API/parameters/UpdateSageIntacctImportEmployees.ts | 6 ------ .../UpdateSageIntacctSyncReimbursedReports.ts | 6 ------ .../UpdateSageIntacctSyncReimbursementAccountID.ts | 6 ------ src/libs/API/parameters/index.ts | 5 ----- src/libs/API/types.ts | 10 +++++----- src/libs/actions/connections/SageIntacct.ts | 2 +- .../intacct/advanced/SageIntacctAdvancedPage.tsx | 2 +- 9 files changed, 7 insertions(+), 42 deletions(-) delete mode 100644 src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts delete mode 100644 src/libs/API/parameters/UpdateSageIntacctAutoSync.ts delete mode 100644 src/libs/API/parameters/UpdateSageIntacctImportEmployees.ts delete mode 100644 src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts delete mode 100644 src/libs/API/parameters/UpdateSageIntacctSyncReimbursementAccountID.ts diff --git a/src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts b/src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts deleted file mode 100644 index 7e90a97210e4..000000000000 --- a/src/libs/API/parameters/UpdateSageIntacctApprovalMode.ts +++ /dev/null @@ -1,6 +0,0 @@ -type UpdateSageIntacctApprovalMode = { - policyID: string; - value: string; -}; - -export default UpdateSageIntacctApprovalMode; diff --git a/src/libs/API/parameters/UpdateSageIntacctAutoSync.ts b/src/libs/API/parameters/UpdateSageIntacctAutoSync.ts deleted file mode 100644 index ebdb17c0129d..000000000000 --- a/src/libs/API/parameters/UpdateSageIntacctAutoSync.ts +++ /dev/null @@ -1,6 +0,0 @@ -type UpdateSageIntacctAutoSync = { - policyID: string; - enabled: boolean; -}; - -export default UpdateSageIntacctAutoSync; diff --git a/src/libs/API/parameters/UpdateSageIntacctImportEmployees.ts b/src/libs/API/parameters/UpdateSageIntacctImportEmployees.ts deleted file mode 100644 index 13f33332537b..000000000000 --- a/src/libs/API/parameters/UpdateSageIntacctImportEmployees.ts +++ /dev/null @@ -1,6 +0,0 @@ -type UpdateSageIntacctImportEmployees = { - policyID: string; - enabled: boolean; -}; - -export default UpdateSageIntacctImportEmployees; diff --git a/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts b/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts deleted file mode 100644 index a073702a43b0..000000000000 --- a/src/libs/API/parameters/UpdateSageIntacctSyncReimbursedReports.ts +++ /dev/null @@ -1,6 +0,0 @@ -type UpdateSageIntacctSyncReimbursedReports = { - policyID: string; - enabled: boolean; -}; - -export default UpdateSageIntacctSyncReimbursedReports; diff --git a/src/libs/API/parameters/UpdateSageIntacctSyncReimbursementAccountID.ts b/src/libs/API/parameters/UpdateSageIntacctSyncReimbursementAccountID.ts deleted file mode 100644 index b992a100585b..000000000000 --- a/src/libs/API/parameters/UpdateSageIntacctSyncReimbursementAccountID.ts +++ /dev/null @@ -1,6 +0,0 @@ -type UpdateSageIntacctSyncReimbursementAccountID = { - policyID: string; - vendorID: string | null; -}; - -export default UpdateSageIntacctSyncReimbursementAccountID; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 79fb9bfcee45..c2b6b90a4fc4 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -126,11 +126,6 @@ export type {default as DeleteMembersFromWorkspaceParams} from './DeleteMembersF export type {default as OpenWorkspaceParams} from './OpenWorkspaceParams'; export type {default as OpenWorkspaceViewParams} from './OpenWorkspaceViewParams'; export type {default as ConnectPolicyToSageIntacctParams} from './ConnectPolicyToSageIntacctParams'; -export type {default as UpdateSageIntacctAutoSync} from './UpdateSageIntacctAutoSync'; -export type {default as UpdateSageIntacctImportEmployees} from './UpdateSageIntacctImportEmployees'; -export type {default as UpdateSageIntacctApprovalMode} from './UpdateSageIntacctApprovalMode'; -export type {default as UpdateSageIntacctSyncReimbursedReports} from './UpdateSageIntacctSyncReimbursedReports'; -export type {default as UpdateSageIntacctSyncReimbursementAccountID} from './UpdateSageIntacctSyncReimbursementAccountID'; export type {default as OpenWorkspaceReimburseViewParams} from './OpenWorkspaceReimburseViewParams'; export type {default as OpenWorkspaceInvitePageParams} from './OpenWorkspaceInvitePageParams'; export type {default as OpenWorkspaceMembersPageParams} from './OpenWorkspaceMembersPageParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index dc15019005cf..925fde3330ed 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -538,13 +538,13 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_CREDIT_CARD_CHARGE_EXPORT_DEFAULT_VENDOR]: Parameters.UpdateSageIntacctGenericTypeParams<'vendorID', string>; [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_ACCOUNT]: Parameters.UpdateSageIntacctGenericTypeParams<'creditCardAccountID', string>; [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_VENDOR]: Parameters.UpdateSageIntacctGenericTypeParams<'vendorID', string>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_AUTO_SYNC]: Parameters.UpdateSageIntacctGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_IMPORT_EMPLOYEES]: Parameters.UpdateSageIntacctGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_APPROVAL_MODE]: Parameters.UpdateSageIntacctGenericTypeParams<'value', string>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateSageIntacctGenericTypeParams<'enabled', boolean>; + [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSEMENT_ACCOUNT_ID]: Parameters.UpdateSageIntacctGenericTypeParams<'vendorID', string>; [WRITE_COMMANDS.UPGRADE_TO_CORPORATE]: Parameters.UpgradeToCorporateParams; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_AUTO_SYNC]: Parameters.UpdateSageIntacctAutoSync; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_IMPORT_EMPLOYEES]: Parameters.UpdateSageIntacctImportEmployees; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_APPROVAL_MODE]: Parameters.UpdateSageIntacctApprovalMode; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateSageIntacctSyncReimbursedReports; - [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSEMENT_ACCOUNT_ID]: Parameters.UpdateSageIntacctSyncReimbursementAccountID; // Netsuite parameters [WRITE_COMMANDS.UPDATE_NETSUITE_SUBSIDIARY]: Parameters.UpdateNetSuiteSubsidiaryParams; diff --git a/src/libs/actions/connections/SageIntacct.ts b/src/libs/actions/connections/SageIntacct.ts index 5251d3a2d8e5..ff452d477f6b 100644 --- a/src/libs/actions/connections/SageIntacct.ts +++ b/src/libs/actions/connections/SageIntacct.ts @@ -372,7 +372,7 @@ function updateSageIntacctSyncReimbursedReports(policyID: string, enabled: boole API.write(WRITE_COMMANDS.UPDATE_SAGE_INTACCT_SYNC_REIMBURSED_REPORTS, parameters, {optimisticData, failureData, successData}); } -function updateSageIntacctSyncReimbursementAccountID(policyID: string, vendorID: string | null) { +function updateSageIntacctSyncReimbursementAccountID(policyID: string, vendorID: string) { const {optimisticData, failureData, successData} = prepareOnyxDataForSyncUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBURSEMENT_ACCOUNT_ID, vendorID); const parameters = { policyID, diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 50a5256ebd72..b098000f47f2 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -71,7 +71,7 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { updateSageIntacctSyncReimbursedReports(policyID, enabled); if (enabled && !sync?.reimbursementAccountID) { - const reimbursementAccountID = data?.bankAccounts[0]?.id ?? null; + const reimbursementAccountID = data?.bankAccounts[0]?.id ?? ''; updateSageIntacctSyncReimbursementAccountID(policyID, reimbursementAccountID); } }, From 207c13ec591aed5943d1c0dea5141d340a3ea4ad Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 9 Jul 2024 17:51:39 +0200 Subject: [PATCH 27/30] fix review comments --- src/libs/PolicyUtils.ts | 1 - src/libs/actions/connections/SageIntacct.ts | 4 ++-- src/types/onyx/Policy.ts | 8 ++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 9305d8f36a52..8a967d96729b 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -620,7 +620,6 @@ function getIntegrationLastSuccessfulDate(connection?: Connections[keyof Connect function getSageIntacctBankAccounts(policy?: Policy, selectedBankAccountId?: string): SelectorType[] { const bankAccounts = policy?.connections?.intacct?.data?.bankAccounts ?? []; - return (bankAccounts ?? []).map(({id, name}) => ({ value: id, text: name, diff --git a/src/libs/actions/connections/SageIntacct.ts b/src/libs/actions/connections/SageIntacct.ts index ff452d477f6b..f2cafc597729 100644 --- a/src/libs/actions/connections/SageIntacct.ts +++ b/src/libs/actions/connections/SageIntacct.ts @@ -7,7 +7,7 @@ import {WRITE_COMMANDS} from '@libs/API/types'; import * as ErrorUtils from '@libs/ErrorUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Connections, SageIntacctConnectiosConfig} from '@src/types/onyx/Policy'; +import type {Connections, SageIntacctConnectionsConfig} from '@src/types/onyx/Policy'; type SageIntacctCredentials = {companyID: string; userID: string; password: string}; @@ -21,7 +21,7 @@ function connectToSageIntacct(policyID: string, credentials: SageIntacctCredenti API.write(WRITE_COMMANDS.CONNECT_POLICY_TO_SAGE_INTACCT, parameters, {}); } -function prepareOnyxDataForConfigUpdate(policyID: string, settingName: keyof SageIntacctConnectiosConfig, settingValue: string | boolean | null) { +function prepareOnyxDataForConfigUpdate(policyID: string, settingName: keyof SageIntacctConnectionsConfig, settingValue: string | boolean | null) { const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 05e59e771820..1a377897282a 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -998,14 +998,14 @@ type SageIntacctSyncConfig = { /** ID of the bank account for Sage Intacct bill payment account */ reimbursementAccountID?: string; - /** Whether the reimbursed reports should be synched */ + /** Whether the reimbursed reports should be synced */ syncReimbursedReports: boolean | string; }; /** * Connection config for Sage Intacct */ -type SageIntacctConnectiosConfig = OnyxCommon.OnyxValueWithOfflineFeedback< +type SageIntacctConnectionsConfig = OnyxCommon.OnyxValueWithOfflineFeedback< { /** Sage Intacct credentials */ credentials: { @@ -1094,7 +1094,7 @@ type Connections = { netsuite: NetSuiteConnection; /** Sage Intacct integration connection */ - intacct: Connection; + intacct: Connection; }; /** Names of integration connections */ @@ -1461,5 +1461,5 @@ export type { NetSuiteCustomFormID, SageIntacctDataElementWithValue, SageIntacctDataElement, - SageIntacctConnectiosConfig, + SageIntacctConnectionsConfig, }; From 39b4acf0a509d02c23ec26fb8743bf19ec8b3cf9 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 9 Jul 2024 17:58:26 +0200 Subject: [PATCH 28/30] revert integrationName in translations --- src/languages/en.ts | 19 +++++++++++-------- src/languages/es.ts | 17 +++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index bbd2de94adc2..d3cba1e83436 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -127,10 +127,6 @@ type States = Record; type AllCountries = Record; -function integrationName(fallbackName: string, integration?: ConnectionName): string { - return integration && CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] ? CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] : fallbackName; -} - /* eslint-disable max-len */ export default { common: { @@ -2041,8 +2037,6 @@ export default { welcomeNote: ({workspaceName}: WelcomeNoteParams) => `You have been invited to ${workspaceName || 'a workspace'}! Download the Expensify mobile app at use.expensify.com/download to start tracking your expenses.`, subscription: 'Subscription', - noAccountsFound: 'No accounts found', - noAccountsFoundDescription: (integration: ConnectionName) => `Add the account in ${integrationName('this integration', integration)} and sync the connection again.`, }, qbo: { importDescription: 'Choose which coding configurations to import from QuickBooks Online to Expensify.', @@ -2860,7 +2854,10 @@ export default { other: 'Other integrations', syncNow: 'Sync now', disconnect: 'Disconnect', - disconnectTitle: (integration?: ConnectionName): string => `Disconnect ${integrationName('integration', integration)}`, + disconnectTitle: (integration?: ConnectionName): string => { + const integrationName = integration && CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] ? CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] : 'integration'; + return `Disconnect ${integrationName}`; + }, connectTitle: (integrationToConnect: ConnectionName): string => `Connect ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integrationToConnect] ?? 'accounting integration'}`, syncError: (integration?: ConnectionName): string => { @@ -2890,7 +2887,13 @@ export default { [CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD]: 'Imported as report fields', [CONST.INTEGRATION_ENTITY_MAP_TYPES.NETSUITE_DEFAULT]: 'NetSuite employee default', }, - disconnectPrompt: (currentIntegration?: ConnectionName): string => `Are you sure you want to disconnect ${integrationName('this integration', currentIntegration)}?`, + disconnectPrompt: (currentIntegration?: ConnectionName): string => { + const integrationName = + currentIntegration && CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[currentIntegration] + ? CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[currentIntegration] + : 'this integration'; + return `Are you sure you want to disconnect ${integrationName}?`; + }, connectPrompt: (integrationToConnect: ConnectionName): string => `Are you sure you want to connect ${ CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integrationToConnect] ?? 'this accounting integration' diff --git a/src/languages/es.ts b/src/languages/es.ts index a4277b1c53c6..5e5dcf0057a8 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -117,10 +117,6 @@ import type { ZipCodeExampleFormatParams, } from './types'; -function integrationName(fallbackName: string, integration?: ConnectionName): string { - return integration && CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] ? CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] : fallbackName; -} - /* eslint-disable max-len */ export default { common: { @@ -2072,8 +2068,6 @@ export default { welcomeNote: ({workspaceName}: WelcomeNoteParams) => `¡Has sido invitado a ${workspaceName}! Descargue la aplicación móvil Expensify en use.expensify.com/download para comenzar a rastrear sus gastos.`, subscription: 'Suscripción', - noAccountsFound: 'No se ha encontrado ninguna cuenta', - noAccountsFoundDescription: (integration: ConnectionName) => `Añade la cuenta en ${integrationName('esta integración', integration)} y sincroniza de nuevo la conexión.`, }, qbo: { importDescription: 'Elige que configuraciónes de codificación son importadas desde QuickBooks Online a Expensify.', @@ -2846,7 +2840,10 @@ export default { other: 'Otras integraciones', syncNow: 'Sincronizar ahora', disconnect: 'Desconectar', - disconnectTitle: (integration?: ConnectionName): string => `Desconectar ${integrationName('integración', integration)}`, + disconnectTitle: (integration?: ConnectionName): string => { + const integrationName = integration && CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] ? CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integration] : 'integración'; + return `Desconectar ${integrationName}`; + }, connectTitle: (integrationToConnect: ConnectionName): string => `Conectar ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integrationToConnect] ?? 'accounting integration'}`, syncError: (integration?: ConnectionName): string => { switch (integration) { @@ -2875,7 +2872,11 @@ export default { [CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD]: 'Importado como campos de informe', [CONST.INTEGRATION_ENTITY_MAP_TYPES.NETSUITE_DEFAULT]: 'Predeterminado del empleado NetSuite', }, - disconnectPrompt: (currentIntegration?: ConnectionName): string => `¿Estás seguro de que quieres desconectar ${integrationName('integración', currentIntegration)}?`, + disconnectPrompt: (currentIntegration?: ConnectionName): string => { + const integrationName = + currentIntegration && CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[currentIntegration] ? CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[currentIntegration] : 'integración'; + return `¿Estás seguro de que quieres desconectar ${integrationName}?`; + }, connectPrompt: (integrationToConnect: ConnectionName): string => `¿Estás seguro de que quieres conectar a ${ CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[integrationToConnect] ?? 'esta integración contable' From 06c110f36e8d0a37e96b30a4dbbb94323e5f286a Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 9 Jul 2024 18:06:56 +0200 Subject: [PATCH 29/30] fix translations in one more place --- .../intacct/advanced/SageIntacctPaymentAccountPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx index 5125a0f21267..dadd1dc0af2c 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctPaymentAccountPage.tsx @@ -43,8 +43,8 @@ function SageIntacctPaymentAccountPage({policy}: WithPolicyConnectionsProps) { icon={Illustrations.TeleScope} iconWidth={variables.emptyListIconWidth} iconHeight={variables.emptyListIconHeight} - title={translate('workspace.common.noAccountsFound')} - subtitle={translate('workspace.common.noAccountsFoundDescription', CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT)} + title={translate('workspace.sageIntacct.noAccountsFound')} + subtitle={translate('workspace.sageIntacct.noAccountsFoundDescription')} /> ), [translate], From 094759f8e2ac37ec852b3413dccc22a99ce7755d Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 9 Jul 2024 18:25:44 +0200 Subject: [PATCH 30/30] split sync and autosync commands in SageIntacct.ts --- src/libs/actions/connections/SageIntacct.ts | 82 ++++++++++++++++++--- 1 file changed, 73 insertions(+), 9 deletions(-) diff --git a/src/libs/actions/connections/SageIntacct.ts b/src/libs/actions/connections/SageIntacct.ts index f2cafc597729..1058287f9f3b 100644 --- a/src/libs/actions/connections/SageIntacct.ts +++ b/src/libs/actions/connections/SageIntacct.ts @@ -89,13 +89,7 @@ function prepareOnyxDataForConfigUpdate(policyID: string, settingName: keyof Sag return {optimisticData, failureData, successData}; } -function prepareOnyxDataForSyncUpdate( - policyID: string, - settingName: keyof Connections['intacct']['config']['sync'] | keyof Connections['intacct']['config']['autoSync'], - settingValue: string | boolean | null, - auto = false, -) { - const sync = auto ? CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC : CONST.SAGE_INTACCT_CONFIG.SYNC; +function prepareOnyxDataForSyncUpdate(policyID: string, settingName: keyof Connections['intacct']['config']['sync'], settingValue: string | boolean) { const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -104,7 +98,77 @@ function prepareOnyxDataForSyncUpdate( connections: { intacct: { config: { - [sync]: { + sync: { + [settingName]: settingValue, + }, + 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: { + intacct: { + config: { + pendingFields: { + [settingName]: null, + }, + errorFields: { + [settingName]: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + }, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + intacct: { + config: { + pendingFields: { + [settingName]: null, + }, + errorFields: { + [settingName]: null, + }, + }, + }, + }, + }, + }, + ]; + + return {optimisticData, failureData, successData}; +} + +function prepareOnyxDataForAutoSyncUpdate(policyID: string, settingName: keyof Connections['intacct']['config']['autoSync'], settingValue: boolean) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + intacct: { + config: { + autoSync: { [settingName]: settingValue, }, pendingFields: { @@ -332,7 +396,7 @@ function updateSageIntacctDefaultVendor(policyID: string, settingName: keyof Con } function updateSageIntacctAutoSync(policyID: string, enabled: boolean) { - const {optimisticData, failureData, successData} = prepareOnyxDataForSyncUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC_ENABLED, enabled, true); + const {optimisticData, failureData, successData} = prepareOnyxDataForAutoSyncUpdate(policyID, CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC_ENABLED, enabled); const parameters = { policyID, enabled,