From 549bf279e2f68a96c8f0752f614517f9753dffc6 Mon Sep 17 00:00:00 2001 From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com> Date: Fri, 24 Jul 2026 23:00:45 +0530 Subject: [PATCH 1/2] fix(certinia): allow FFA company selection --- src/pages/workspace/accounting/PolicyAccountingPage.tsx | 4 ++-- .../accounting/certinia/CertiniaCompanySelectorPage.tsx | 4 ++-- src/pages/workspace/accounting/certinia/utils.ts | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index b110735649e0..1ed5e93762e8 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -77,7 +77,7 @@ import {View} from 'react-native'; import type {MenuItemData, PolicyAccountingPageProps} from './types'; import {AccountingContextProvider, useAccountingActions, useAccountingState} from './AccountingContext'; -import {isCertiniaSRPConnection} from './certinia/utils'; +import {isCertiniaFFAConnection} from './certinia/utils'; import {getAccountingIntegrationData, getSynchronizationErrorMessage} from './utils'; type RouteParams = { @@ -360,7 +360,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { interactive: false, }; case CONST.POLICY.CONNECTIONS.NAME.CERTINIA: - return !isCertiniaSRPConnection(certiniaConfig) + return !isCertiniaFFAConnection(certiniaConfig) ? {} : { description: translate('workspace.certinia.company'), diff --git a/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx b/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx index 70a8200275c7..cc15509f745e 100644 --- a/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx +++ b/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx @@ -21,7 +21,7 @@ import ROUTES from '@src/ROUTES'; import React from 'react'; -import {isCertiniaSRPConnection} from './utils'; +import {isCertiniaFFAConnection} from './utils'; type CompanyListItem = ListItem & { value: string; @@ -66,7 +66,7 @@ function CertiniaCompanySelectorPage({policy}: WithPolicyConnectionsProps) { accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]} featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} displayName="CertiniaCompanySelectorPage" - shouldBeBlocked={!isCertiniaSRPConnection(config)} + shouldBeBlocked={!isCertiniaFFAConnection(config)} data={dataOptions} onSelectRow={selectCompany} shouldSingleExecuteRowSelect diff --git a/src/pages/workspace/accounting/certinia/utils.ts b/src/pages/workspace/accounting/certinia/utils.ts index 1c2def3b28a6..ac101191ada2 100644 --- a/src/pages/workspace/accounting/certinia/utils.ts +++ b/src/pages/workspace/accounting/certinia/utils.ts @@ -118,8 +118,8 @@ function isCertiniaDimensionParam(dimension: string): dimension is CertiniaDimen return (CERTINIA_DIMENSION_PARAMS as readonly string[]).includes(dimension); } -function isCertiniaSRPConnection(config: FinancialForceConnectionConfig | undefined): boolean { - return !!config?.hasPSA && config?.hasPSAOnly === false; +function isCertiniaFFAConnection(config: FinancialForceConnectionConfig | undefined): boolean { + return config?.hasPSAOnly === false; } export { @@ -131,7 +131,7 @@ export { getDimensionLabel, getDisplayTypeLabel, getParentTagMappingLabel, - isCertiniaSRPConnection, + isCertiniaFFAConnection, isCertiniaDimensionParam, updateFinancialForceDimensionMapping, }; From 6ad10cbe9a5965757aea935b2291b9788892a5d7 Mon Sep 17 00:00:00 2001 From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com> Date: Tue, 28 Jul 2026 10:01:18 +0530 Subject: [PATCH 2/2] fix(certinia): use product company config --- .../actions/connections/FinancialForce.ts | 23 ++++++++----------- .../accounting/PolicyAccountingPage.tsx | 9 ++++---- .../certinia/CertiniaCompanySelectorPage.tsx | 13 ++++++----- .../workspace/accounting/certinia/utils.ts | 5 ++++ src/types/onyx/Policy.ts | 5 +++- 5 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/libs/actions/connections/FinancialForce.ts b/src/libs/actions/connections/FinancialForce.ts index dd95368b8c69..102e53c5e25c 100644 --- a/src/libs/actions/connections/FinancialForce.ts +++ b/src/libs/actions/connections/FinancialForce.ts @@ -536,7 +536,8 @@ function updateFinancialForceExportForeignCurrency(policyID: string, enabled: bo write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_EXPORT_FOREIGN_CURRENCY, {policyID, enabled}, {optimisticData, failureData, successData}); } -function updateFinancialForceCompany(policyID: string, companyID: string, previousCompanyID: string | null) { +function updateFinancialForceCompany(policyID: string, companyID: string, previousCompanyID: string | null, hasPSA: boolean) { + const companyField = hasPSA ? CONST.CERTINIA_CONFIG.COMPANY_ID : CONST.CERTINIA_CONFIG.COMPANY; const optimisticData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -545,14 +546,12 @@ function updateFinancialForceCompany(policyID: string, companyID: string, previo connections: { [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: { config: { - credentials: { - [CONST.CERTINIA_CONFIG.COMPANY_ID]: companyID, - }, + ...(hasPSA ? {export: {[CONST.CERTINIA_CONFIG.COMPANY_ID]: companyID}} : {[CONST.CERTINIA_CONFIG.COMPANY]: companyID}), pendingFields: { - [CONST.CERTINIA_CONFIG.COMPANY_ID]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + [companyField]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, }, errorFields: { - [CONST.CERTINIA_CONFIG.COMPANY_ID]: null, + [companyField]: null, }, }, }, @@ -569,14 +568,12 @@ function updateFinancialForceCompany(policyID: string, companyID: string, previo connections: { [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: { config: { - credentials: { - [CONST.CERTINIA_CONFIG.COMPANY_ID]: previousCompanyID ?? null, - }, + ...(hasPSA ? {export: {[CONST.CERTINIA_CONFIG.COMPANY_ID]: previousCompanyID ?? null}} : {[CONST.CERTINIA_CONFIG.COMPANY]: previousCompanyID ?? null}), pendingFields: { - [CONST.CERTINIA_CONFIG.COMPANY_ID]: null, + [companyField]: null, }, errorFields: { - [CONST.CERTINIA_CONFIG.COMPANY_ID]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + [companyField]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), }, }, }, @@ -594,10 +591,10 @@ function updateFinancialForceCompany(policyID: string, companyID: string, previo [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: { config: { pendingFields: { - [CONST.CERTINIA_CONFIG.COMPANY_ID]: null, + [companyField]: null, }, errorFields: { - [CONST.CERTINIA_CONFIG.COMPANY_ID]: null, + [companyField]: null, }, }, }, diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index 1ed5e93762e8..cac5d33386be 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -77,7 +77,7 @@ import {View} from 'react-native'; import type {MenuItemData, PolicyAccountingPageProps} from './types'; import {AccountingContextProvider, useAccountingActions, useAccountingState} from './AccountingContext'; -import {isCertiniaFFAConnection} from './certinia/utils'; +import {getCertiniaSelectedCompanyID, isCertiniaFFAConnection} from './certinia/utils'; import {getAccountingIntegrationData, getSynchronizationErrorMessage} from './utils'; type RouteParams = { @@ -285,7 +285,8 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { const rilletSubsidiaryList = policy?.connections?.rillet?.data?.subsidiaries; const certiniaConfig = policy?.connections?.financialforce?.config; const certiniaCompanies = policy?.connections?.financialforce?.data?.companies ?? []; - const certiniaCompanyID = certiniaConfig?.credentials?.companyID; + const certiniaCompanyID = getCertiniaSelectedCompanyID(certiniaConfig); + const certiniaCompanyField = certiniaConfig?.hasPSA ? CONST.CERTINIA_CONFIG.COMPANY_ID : CONST.CERTINIA_CONFIG.COMPANY; const selectedCertiniaCompany = certiniaCompanies.find((company) => company.id === certiniaCompanyID); switch (connectedIntegration) { case CONST.POLICY.CONNECTIONS.NAME.XERO: @@ -371,8 +372,8 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { shouldShowRightIcon: canWriteAccounting, shouldShowDescriptionOnTop: true, interactive: canWriteAccounting, - pendingAction: settingsPendingAction([CONST.CERTINIA_CONFIG.COMPANY_ID], certiniaConfig?.pendingFields), - brickRoadIndicator: areSettingsInErrorFields([CONST.CERTINIA_CONFIG.COMPANY_ID], certiniaConfig?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + pendingAction: settingsPendingAction([certiniaCompanyField], certiniaConfig?.pendingFields), + brickRoadIndicator: areSettingsInErrorFields([certiniaCompanyField], certiniaConfig?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, onPress: canWriteAccounting ? () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_CERTINIA_COMPANY_SELECTOR.getRoute(policyID)) : undefined, }; case CONST.POLICY.CONNECTIONS.NAME.RILLET: diff --git a/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx b/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx index cc15509f745e..404e697f179a 100644 --- a/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx +++ b/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx @@ -21,7 +21,7 @@ import ROUTES from '@src/ROUTES'; import React from 'react'; -import {isCertiniaFFAConnection} from './utils'; +import {getCertiniaSelectedCompanyID, isCertiniaFFAConnection} from './utils'; type CompanyListItem = ListItem & { value: string; @@ -32,7 +32,8 @@ function CertiniaCompanySelectorPage({policy}: WithPolicyConnectionsProps) { const styles = useThemeStyles(); const policyID = policy?.id; const {config, data} = policy?.connections?.financialforce ?? {}; - const companyID = config?.credentials?.companyID; + const companyID = getCertiniaSelectedCompanyID(config); + const companyField = config?.hasPSA ? CONST.CERTINIA_CONFIG.COMPANY_ID : CONST.CERTINIA_CONFIG.COMPANY; const companies = data?.companies ?? []; const illustrations = useMemoizedLazyIllustrations(['Telescope']); @@ -55,7 +56,7 @@ function CertiniaCompanySelectorPage({policy}: WithPolicyConnectionsProps) { const selectCompany = (row: CompanyListItem) => { if (row.value !== companyID && policyID) { - updateFinancialForceCompany(policyID, row.value, companyID ?? null); + updateFinancialForceCompany(policyID, row.value, companyID ?? null, !!config?.hasPSA); } Navigation.goBack(policyID ? ROUTES.POLICY_ACCOUNTING.getRoute(policyID) : undefined); }; @@ -75,10 +76,10 @@ function CertiniaCompanySelectorPage({policy}: WithPolicyConnectionsProps) { title="workspace.certinia.company" listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.CERTINIA} - pendingAction={settingsPendingAction([CONST.CERTINIA_CONFIG.COMPANY_ID], config?.pendingFields)} - errors={getLatestErrorField(config, CONST.CERTINIA_CONFIG.COMPANY_ID)} + pendingAction={settingsPendingAction([companyField], config?.pendingFields)} + errors={getLatestErrorField(config, companyField)} errorRowStyles={[styles.ph5, styles.pv3]} - onClose={() => clearFinancialForceErrorField(policyID, CONST.CERTINIA_CONFIG.COMPANY_ID)} + onClose={() => clearFinancialForceErrorField(policyID, companyField)} /> ); } diff --git a/src/pages/workspace/accounting/certinia/utils.ts b/src/pages/workspace/accounting/certinia/utils.ts index ac101191ada2..da1f7b115a9d 100644 --- a/src/pages/workspace/accounting/certinia/utils.ts +++ b/src/pages/workspace/accounting/certinia/utils.ts @@ -122,10 +122,15 @@ function isCertiniaFFAConnection(config: FinancialForceConnectionConfig | undefi return config?.hasPSAOnly === false; } +function getCertiniaSelectedCompanyID(config: FinancialForceConnectionConfig | undefined): string | undefined { + return config?.hasPSA ? config.export?.companyID : config?.company; +} + export { CERTINIA_DIMENSION_PARAMS, CERTINIA_FFA_EXPORT_STATUSES, dimensionParamToNumber, + getCertiniaSelectedCompanyID, getCertiniaReportExportStatusValue, getCertiniaFFAExportStatusValue, getDimensionLabel, diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index adf4c8561ee7..ab46802f434a 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1473,7 +1473,7 @@ type FinancialForceConnectionData = { /** Certinia credentials (Salesforce / Certinia org); fields populate as OAuth / sync complete */ type FinancialForceCredentials = { - /** Certinia company ID */ + /** Salesforce organization ID */ companyID?: string; /** Salesforce enterprise / instance URL */ @@ -1564,6 +1564,9 @@ type FinancialForceConnectionConfig = OnyxCommon.OnyxValueWithOfflineFeedback< /** Whether the connection has been fully set up */ isConfigured?: boolean; + /** FFA Accounting Company ID */ + company?: string; + /** Certinia import / coding settings */ coding: FinancialForceCodingConfig;