diff --git a/src/CONST.ts b/src/CONST.ts index d0695b1e285f..6167d92514d3 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -722,6 +722,7 @@ const CONST = { ADMIN_POLICIES_URL: 'admin_policies', ADMIN_DOMAINS_URL: 'admin_domains', INBOX: 'inbox', + POLICY_CONNECTIONS_URL: (policyID: string) => `policy?param={"policyID":"${policyID}"}#connections`, }, EXPENSIFY_POLICY_DOMAIN: 'expensify-policy', diff --git a/src/languages/en.ts b/src/languages/en.ts index e61eba949a8b..6fb4ae5c9369 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3276,6 +3276,8 @@ export default { } } }, + errorODIntegration: "There's an error with a connection that's been set up in Expensify Classic. ", + goToODToFix: 'Go to Expensiy Classic to fix this issue.', setup: 'Connect', lastSync: (relativeDate: string) => `Last synced ${relativeDate}`, import: 'Import', diff --git a/src/languages/es.ts b/src/languages/es.ts index 174266ba5d66..810ddadba871 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -3258,6 +3258,8 @@ export default { } } }, + errorODIntegration: 'Hay un error con una conexión que se ha configurado en Expensify Classic. ', + goToODToFix: 'Ve a Expensify Classic para solucionar este problema.', setup: 'Configurar', lastSync: (relativeDate: string) => `Recién sincronizado ${relativeDate}`, import: 'Importar', diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index f62935fc6721..43b02191429b 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -945,6 +945,10 @@ function hasIntegrationAutoSync(policy: Policy | undefined, connectedIntegration return (connectedIntegration && policy?.connections?.[connectedIntegration]?.config?.autoSync?.enabled) ?? false; } +function hasUnsupportedIntegration(policy: Policy | undefined, accountingIntegrations?: ConnectionName[]) { + return !(accountingIntegrations ?? Object.values(CONST.POLICY.CONNECTIONS.NAME)).some((integration) => !!policy?.connections?.[integration]); +} + function getCurrentConnectionName(policy: Policy | undefined): string | undefined { const accountingIntegrations = Object.values(CONST.POLICY.CONNECTIONS.NAME); const connectionKey = accountingIntegrations.find((integration) => !!policy?.connections?.[integration]); @@ -1097,6 +1101,7 @@ export { getAllTaxRatesNamesAndKeys as getAllTaxRates, getTagNamesFromTagsLists, getDomainNameForPolicy, + hasUnsupportedIntegration, getWorkflowApprovalsUnavailable, }; diff --git a/src/libs/actions/Link.ts b/src/libs/actions/Link.ts index 50a4582dffc1..886f8b06fc6f 100644 --- a/src/libs/actions/Link.ts +++ b/src/libs/actions/Link.ts @@ -39,8 +39,15 @@ Onyx.connect({ }); function buildOldDotURL(url: string, shortLivedAuthToken?: string): Promise { - const hasHashParams = url.indexOf('#') !== -1; + const hashIndex = url.lastIndexOf('#'); + const hasHashParams = hashIndex !== -1; const hasURLParams = url.indexOf('?') !== -1; + let originURL = url; + let hashParams = ''; + if (hasHashParams) { + originURL = url.substring(0, hashIndex); + hashParams = url.substring(hashIndex); + } const authTokenParam = shortLivedAuthToken ? `authToken=${shortLivedAuthToken}` : ''; const emailParam = `email=${encodeURIComponent(currentUserEmail)}`; @@ -51,7 +58,7 @@ function buildOldDotURL(url: string, shortLivedAuthToken?: string): Promise getXeroTenants(policy), [policy]); const currentXeroOrganization = findCurrentXeroOrganization(tenants, policy?.connections?.xero?.config?.tenantID); @@ -368,7 +376,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { ]); const otherIntegrationsItems = useMemo(() => { - if (isEmptyObject(policy?.connections) && !isSyncInProgress) { + if (isEmptyObject(policy?.connections) && !isSyncInProgress && !(hasUnsupportedNDIntegration && hasSyncError)) { return; } const otherIntegrations = accountingIntegrations.filter( @@ -419,6 +427,8 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { isOffline, startIntegrationFlow, popoverAnchorRefs, + hasUnsupportedNDIntegration, + hasSyncError, ]); return ( @@ -448,20 +458,40 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { titleStyles={styles.accountSettingsSectionTitle} childrenStyles={styles.pt5} > - {connectionsMenuItems.map((menuItem) => ( - - ( + - - ))} + shouldDisableStrikeThrough + > + + + ))} + {hasUnsupportedNDIntegration && hasSyncError && ( + + + {translate('workspace.accounting.errorODIntegration')} + { + // Go to Expensify Classic. + Link.openOldDotLink(CONST.OLDDOT_URLS.POLICY_CONNECTIONS_URL(policyID)); + }} + > + {translate('workspace.accounting.goToODToFix')} + + + + )} {otherIntegrationsItems && (