Skip to content

Commit

Permalink
Merge pull request #50216 from hoangzinh/ft/49697-init-QBD-connection
Browse files Browse the repository at this point in the history
[QBD] Handle the initial connection for QBD
  • Loading branch information
lakchote authored Oct 9, 2024
2 parents 3777223 + b736632 commit 1c0d2fa
Show file tree
Hide file tree
Showing 28 changed files with 736 additions and 6 deletions.
1 change: 1 addition & 0 deletions assets/images/integrationicons/qbd-icon-square.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
213 changes: 213 additions & 0 deletions assets/images/laptop-with-second-screen-sync.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
150 changes: 150 additions & 0 deletions assets/images/laptop-with-second-screen-x.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2305,10 +2305,10 @@ const CONST = {
NAME: {
// Here we will add other connections names when we add support for them
QBO: 'quickbooksOnline',
QBD: 'quickbooksDesktop',
XERO: 'xero',
NETSUITE: 'netsuite',
SAGE_INTACCT: 'intacct',
QBD: 'quickbooksDesktop',
},
ROUTE: {
QBO: 'quickbooks-online',
Expand Down
12 changes: 12 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,18 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/accounting/sage-intacct/advanced/payment-account',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/sage-intacct/advanced/payment-account` as const,
},
POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_SETUP_MODAL: {
route: 'settings/workspaces/:policyID/accounting/quickbooks-desktop/setup-modal',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/quickbooks-desktop/setup-modal` as const,
},
POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_SETUP_REQUIRED_DEVICE_MODAL: {
route: 'settings/workspaces/:policyID/accounting/quickbooks-desktop/setup-required-device',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/quickbooks-desktop/setup-required-device` as const,
},
POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_TRIGGER_FIRST_SYNC: {
route: 'settings/workspaces/:policyID/accounting/quickbooks-desktop/trigger-first-sync',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/quickbooks-desktop/trigger-first-sync` as const,
},
DEBUG_REPORT: {
route: 'debug/report/:reportID',
getRoute: (reportID: string) => `debug/report/${reportID}` as const,
Expand Down
3 changes: 3 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,9 @@ const SCREENS = {
SAGE_INTACCT_NON_REIMBURSABLE_CREDIT_CARD_ACCOUNT: 'Policy_Accounting_Sage_Intacct_Non_Reimbursable_Credit_Card_Account',
SAGE_INTACCT_ADVANCED: 'Policy_Accounting_Sage_Intacct_Advanced',
SAGE_INTACCT_PAYMENT_ACCOUNT: 'Policy_Accounting_Sage_Intacct_Payment_Account',
QUICKBOOKS_DESKTOP_SETUP_MODAL: 'Policy_Accouting_Quickbooks_Desktop_Setup_Modal',
QUICKBOOKS_DESKTOP_SETUP_REQUIRED_DEVICE_MODAL: 'Policy_Accouting_Quickbooks_Desktop_Setup_Required_Device_Modal',
QUICKBOOKS_DESKTOP_TRIGGER_FIRST_SYNC: 'Policy_Accouting_Quickbooks_Desktop_Trigger_First_Sync',
CARD_RECONCILIATION: 'Policy_Accounting_Card_Reconciliation',
RECONCILIATION_ACCOUNT_SETTINGS: 'Policy_Accounting_Reconciliation_Account_Settings',
},
Expand Down
18 changes: 18 additions & 0 deletions src/components/ConnectToQuickbooksDesktopFlow/index.native.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {useEffect} from 'react';
import Navigation from '@libs/Navigation/Navigation';
import ROUTES from '@src/ROUTES';
import type {ConnectToQuickbooksDesktopFlowProps} from './types';

function ConnectToQuickbooksDesktopFlow({policyID}: ConnectToQuickbooksDesktopFlowProps) {
useEffect(() => {
Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_SETUP_REQUIRED_DEVICE_MODAL.getRoute(policyID));
// eslint-disable-next-line react-compiler/react-compiler
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return null;
}

ConnectToQuickbooksDesktopFlow.displayName = 'ConnectToQuickbooksDesktopFlow';

export default ConnectToQuickbooksDesktopFlow;
26 changes: 26 additions & 0 deletions src/components/ConnectToQuickbooksDesktopFlow/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {useEffect} from 'react';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import Navigation from '@libs/Navigation/Navigation';
import * as PolicyAction from '@userActions/Policy/Policy';
import ROUTES from '@src/ROUTES';
import type {ConnectToQuickbooksDesktopFlowProps} from './types';

function ConnectToQuickbooksDesktopFlow({policyID}: ConnectToQuickbooksDesktopFlowProps) {
const {isSmallScreenWidth} = useResponsiveLayout();

useEffect(() => {
if (isSmallScreenWidth) {
Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_SETUP_REQUIRED_DEVICE_MODAL.getRoute(policyID));
} else {
// Since QBD doesn't support Taxes, we should disable them from the LHN when connecting to QBD
PolicyAction.enablePolicyTaxes(policyID, false);
Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_SETUP_MODAL.getRoute(policyID));
}
}, [isSmallScreenWidth, policyID]);

return null;
}

ConnectToQuickbooksDesktopFlow.displayName = 'ConnectToQuickbooksDesktopFlow';

export default ConnectToQuickbooksDesktopFlow;
6 changes: 6 additions & 0 deletions src/components/ConnectToQuickbooksDesktopFlow/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type ConnectToQuickbooksDesktopFlowProps = {
policyID: string;
};

// eslint-disable-next-line import/prefer-default-export
export type {ConnectToQuickbooksDesktopFlowProps};
2 changes: 2 additions & 0 deletions src/components/Icon/Expensicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ import ImageCropSquareMask from '@assets/images/image-crop-square-mask.svg';
import Inbox from '@assets/images/inbox.svg';
import Info from '@assets/images/info.svg';
import NetSuiteSquare from '@assets/images/integrationicons/netsuite-icon-square.svg';
import QBDSquare from '@assets/images/integrationicons/qbd-icon-square.svg';
import QBOCircle from '@assets/images/integrationicons/qbo-icon-circle.svg';
import QBOSquare from '@assets/images/integrationicons/qbo-icon-square.svg';
import SageIntacctSquare from '@assets/images/integrationicons/sage-intacct-icon-square.svg';
Expand Down Expand Up @@ -402,4 +403,5 @@ export {
SpreadsheetComputer,
Bookmark,
Star,
QBDSquare,
};
11 changes: 11 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2358,6 +2358,16 @@ const translations = {
},
qbd: {
exportDescription: 'Configure how Expensify data exports to QuickBooks Desktop.',
qbdSetup: 'QuickBooks Desktop setup',
requiredSetupDevice: {
title: "Can't connect from this device",
body1: "You'll need to setup this connection from the computer that hosts your QuickBooks Desktop company file.",
body2: "Once you're connected, you'll be able to sync and export from anywhere.",
},
setupPage: {
title: 'Open this link to connect',
body: 'To complete setup, open the following link on the computer where QuickBooks Desktop is running.',
},
},
qbo: {
importDescription: 'Choose which coding configurations to import from QuickBooks Online to Expensify.',
Expand Down Expand Up @@ -3429,6 +3439,7 @@ const translations = {
title: 'Connections',
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',
qbd: 'Quickbooks Desktop',
xero: 'Xero',
netsuite: 'NetSuite',
intacct: 'Sage Intacct',
Expand Down
11 changes: 11 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2380,6 +2380,16 @@ const translations = {
},
qbd: {
exportDescription: 'Configura cómo se exportan los datos de Expensify a QuickBooks Desktop.',
qbdSetup: 'Configuración de QuickBooks Desktop',
requiredSetupDevice: {
title: 'No se puede conectar desde este dispositivo',
body1: 'Deberás configurar esta conexión desde la computadora que hospeda tu archivo de empresa de QuickBooks Desktop.',
body2: 'Una vez que estés conectado, podrás sincronizar y exportar desde cualquier lugar.',
},
setupPage: {
title: 'Abre este enlace para conectar',
body: 'Para completar la configuración, abre el siguiente enlace en la computadora donde se está ejecutando QuickBooks Desktop.',
},
},
qbo: {
importDescription: 'Elige que configuraciónes de codificación son importadas desde QuickBooks Online a Expensify.',
Expand Down Expand Up @@ -3434,6 +3444,7 @@ const translations = {
title: 'Conexiones',
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',
qbd: 'Quickbooks Desktop',
xero: 'Xero',
netsuite: 'NetSuite',
intacct: 'Sage Intacct',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type ConnectPolicyToQuickBooksDesktopParams = {
/** ID of the policy */
policyID: string;
};

export default ConnectPolicyToQuickBooksDesktopParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,3 +330,4 @@ export type {default as UpdateCompanyCardNameParams} from './UpdateCompanyCardNa
export type {default as SetCompanyCardExportAccountParams} from './SetCompanyCardExportAccountParams';
export type {default as SetMissingPersonalDetailsAndShipExpensifyCardParams} from './SetMissingPersonalDetailsAndShipExpensifyCardParams';
export type {default as SetInvoicingTransferBankAccountParams} from './SetInvoicingTransferBankAccountParams';
export type {default as ConnectPolicyToQuickBooksDesktopParams} from './ConnectPolicyToQuickBooksDesktopParams';
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,7 @@ const SIDE_EFFECT_REQUEST_COMMANDS = {
CONNECT_AS_DELEGATE: 'ConnectAsDelegate',
DISCONNECT_AS_DELEGATE: 'DisconnectAsDelegate',
COMPLETE_HYBRID_APP_ONBOARDING: 'CompleteHybridAppOnboarding',
CONNECT_POLICY_TO_QUICKBOOKS_DESKTOP: 'ConnectPolicyToQuickbooksDesktop',
} as const;

type SideEffectRequestCommand = ValueOf<typeof SIDE_EFFECT_REQUEST_COMMANDS>;
Expand All @@ -980,6 +981,7 @@ type SideEffectRequestCommandParameters = {
[SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_AS_DELEGATE]: Parameters.ConnectAsDelegateParams;
[SIDE_EFFECT_REQUEST_COMMANDS.DISCONNECT_AS_DELEGATE]: EmptyObject;
[SIDE_EFFECT_REQUEST_COMMANDS.COMPLETE_HYBRID_APP_ONBOARDING]: EmptyObject;
[SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_POLICY_TO_QUICKBOOKS_DESKTOP]: Parameters.ConnectPolicyToQuickBooksDesktopParams;
};

type ApiRequestCommandParameters = WriteCommandParameters & ReadCommandParameters & SideEffectRequestCommandParameters;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_ONLINE_EXPORT_PREFERRED_EXPORTER]: () =>
require<ReactComponentModule>('../../../../pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage').default,
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_EXPORT]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/qbd/export/QuickbooksDesktopExportPage').default,
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_SETUP_MODAL]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/qbd/QuickBooksDesktopSetupPage').default,
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_SETUP_REQUIRED_DEVICE_MODAL]: () =>
require<ReactComponentModule>('../../../../pages/workspace/accounting/qbd/RequireQuickBooksDesktopPage').default,
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_TRIGGER_FIRST_SYNC]: () =>
require<ReactComponentModule>('../../../../pages/workspace/accounting/qbd/QuickBooksDesktopSetupFlowSyncPage').default,
[SCREENS.REIMBURSEMENT_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/ReimbursementAccount/ReimbursementAccountPage').default,
[SCREENS.GET_ASSISTANCE]: () => require<ReactComponentModule>('../../../../pages/GetAssistancePage').default,
[SCREENS.SETTINGS.TWO_FACTOR_AUTH]: () => require<ReactComponentModule>('../../../../pages/settings/Security/TwoFactorAuth/TwoFactorAuthPage').default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ const FULL_SCREEN_TO_RHP_MAPPING: Partial<Record<FullScreenName, string[]>> = {
SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_ONLINE_ACCOUNT_SELECTOR,
SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_ONLINE_INVOICE_ACCOUNT_SELECTOR,
SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_EXPORT,
SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_SETUP_MODAL,
SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_SETUP_REQUIRED_DEVICE_MODAL,
SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_TRIGGER_FIRST_SYNC,
SCREENS.WORKSPACE.ACCOUNTING.XERO_IMPORT,
SCREENS.WORKSPACE.ACCOUNTING.XERO_CHART_OF_ACCOUNTS,
SCREENS.WORKSPACE.ACCOUNTING.XERO_ORGANIZATION,
Expand Down
9 changes: 9 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,15 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
path: ROUTES.WORKSPACE_ACCOUNTING_QUICKBOOKS_ONLINE_INVOICE_ACCOUNT_SELECTOR.route,
},
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_EXPORT]: {path: ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_EXPORT.route},
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_SETUP_MODAL]: {
path: ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_SETUP_MODAL.route,
},
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_SETUP_REQUIRED_DEVICE_MODAL]: {
path: ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_SETUP_REQUIRED_DEVICE_MODAL.route,
},
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_TRIGGER_FIRST_SYNC]: {
path: ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_TRIGGER_FIRST_SYNC.route,
},
[SCREENS.WORKSPACE.ACCOUNTING.XERO_IMPORT]: {path: ROUTES.POLICY_ACCOUNTING_XERO_IMPORT.route},
[SCREENS.WORKSPACE.ACCOUNTING.XERO_CHART_OF_ACCOUNTS]: {path: ROUTES.POLICY_ACCOUNTING_XERO_CHART_OF_ACCOUNTS.route},
[SCREENS.WORKSPACE.ACCOUNTING.XERO_ORGANIZATION]: {path: ROUTES.POLICY_ACCOUNTING_XERO_ORGANIZATION.route},
Expand Down
6 changes: 6 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,12 @@ type SettingsNavigatorParamList = {
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_EXPORT]: {
policyID: string;
};
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_SETUP_MODAL]: {
policyID: string;
};
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_DESKTOP_SETUP_REQUIRED_DEVICE_MODAL]: {
policyID: string;
};
[SCREENS.WORKSPACE.ACCOUNTING.XERO_IMPORT]: {
policyID: string;
};
Expand Down
14 changes: 14 additions & 0 deletions src/libs/actions/connections/QuickBooksDesktop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as API from '@libs/API';
import type {ConnectPolicyToQuickBooksDesktopParams} from '@libs/API/parameters';
import {SIDE_EFFECT_REQUEST_COMMANDS} from '@libs/API/types';

function getQuickbooksDesktopCodatSetupLink(policyID: string) {
const params: ConnectPolicyToQuickBooksDesktopParams = {policyID};

// eslint-disable-next-line rulesdir/no-api-side-effects-method
return API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_POLICY_TO_QUICKBOOKS_DESKTOP, params);
}

// Disable because we will have more utils will be added in this file
// eslint-disable-next-line import/prefer-default-export
export {getQuickbooksDesktopCodatSetupLink};
6 changes: 4 additions & 2 deletions src/pages/workspace/accounting/PolicyAccountingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) {
const [isDisconnectModalOpen, setIsDisconnectModalOpen] = useState(false);
const [datetimeToRelative, setDateTimeToRelative] = useState('');
const threeDotsMenuContainerRef = useRef<View>(null);
const {canUseWorkspaceFeeds} = usePermissions();
const {canUseWorkspaceFeeds, canUseNewDotQBD} = usePermissions();
const {startIntegrationFlow, popoverAnchorRefs} = useAccountingContext();

const route = useRoute();
Expand All @@ -84,7 +84,9 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) {

const isSyncInProgress = isConnectionInProgress(connectionSyncProgress, policy);

const accountingIntegrations = Object.values(CONST.POLICY.CONNECTIONS.NAME);
const {QBD: qbdConnectionName, ...allConnectionNamesWithoutQBD} = CONST.POLICY.CONNECTIONS.NAME;
const connectionNames = canUseNewDotQBD ? CONST.POLICY.CONNECTIONS.NAME : allConnectionNamesWithoutQBD;
const accountingIntegrations = Object.values(connectionNames);
const connectedIntegration = getConnectedIntegration(policy, accountingIntegrations) ?? connectionSyncProgress?.connectionName;
const synchronizationError = connectedIntegration && getSynchronizationErrorMessage(policy, connectedIntegration, isSyncInProgress, translate, styles);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';

function QuickBooksDesktopSetupFlowSyncPage() {
// TODO: will be implemented in https://github.com/Expensify/App/issues/49698
return <FullScreenLoadingIndicator />;
}

QuickBooksDesktopSetupFlowSyncPage.displayName = 'QuickBooksDesktopSetupFlowSyncPage';

export default QuickBooksDesktopSetupFlowSyncPage;
Loading

0 comments on commit 1c0d2fa

Please sign in to comment.