diff --git a/assets/images/integrationicons/digits-icon-square.svg b/assets/images/integrationicons/digits-icon-square.svg
new file mode 100644
index 000000000000..b28d5f45ef17
--- /dev/null
+++ b/assets/images/integrationicons/digits-icon-square.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/knip.json b/knip.json
index 730d221fe72e..f03420b50cbb 100644
--- a/knip.json
+++ b/knip.json
@@ -46,6 +46,7 @@
"web/cloudflare-worker/**",
"src/libs/actions/connections/FinancialForce.ts",
"src/libs/actions/connections/ZohoBooks.ts",
+ "src/libs/actions/connections/Digits.ts",
"src/setup/telemetry/noopExpoUpdates.ts"
],
"eslint": {
diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 821f33fcb6b4..f5153bc7e287 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -128,7 +128,9 @@ type UnofferedOnboardingAccountingConnection =
// Covered by the Microsoft Dynamics option, and still behind the BUSINESS_CENTRAL beta.
| typeof CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL
// Still behind the ZOHO_BOOKS beta.
- | typeof CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS;
+ | typeof CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS
+ // Still behind the DIGITS beta.
+ | typeof CONST.POLICY.CONNECTIONS.NAME.DIGITS;
type UnhandledAccountingConnection = Exclude, OnboardingAccountingOption | UnofferedOnboardingAccountingConnection>;
@@ -700,6 +702,7 @@ const CONST = {
ZENEFITS: 'Zenefits',
DUALENTRY: 'DualEntry',
CAMPFIRE: 'Campfire',
+ DIGITS: 'Digits',
BUSINESS_CENTRAL: 'Dynamics 365 Business Central',
},
@@ -1434,6 +1437,7 @@ const CONST = {
INDIRECT_TAG_UPLOADS: 'indirectTagUploads',
BUSINESS_CENTRAL: 'businessCentral',
ZOHO_BOOKS: 'zohoBooks',
+ DIGITS: 'digits',
EXACT_ONLINE: 'exactOnline2026',
COMMUTER_EXCLUSIONS: 'commuterExclusions',
COMMUTER_EXCLUSIONS_ARRANGEMENTS: 'commuterExclusionsArrangements',
@@ -4395,6 +4399,59 @@ const CONST = {
EMPLOYEE: 'employee',
},
+ DIGITS_CONFIG: {
+ ENABLE_NEW_CATEGORIES: 'enableNewCategories',
+ EXPORTER: 'exporter',
+ EXPORT_DATE: 'exportDate',
+ REIMBURSABLE: 'reimbursable',
+ NON_REIMBURSABLE: 'nonReimbursable',
+ CREDIT_CARD_ACCOUNT_ID: 'creditCardAccountID',
+ EXPORT_TO_MULTIPLE_ACCOUNTS: 'exportToMultipleAccounts',
+ DEFAULT_VENDORID: 'defaultVendorID',
+ TRAVEL_BILLING_PAYABLE_ACCOUNT_ID: 'travelInvoicingPayableAccountID',
+ ACCOUNTING_METHOD: 'accountingMethod',
+ AUTO_SYNC: 'autoSync',
+ SYNC_REIMBURSED_REPORTS: 'syncReimbursedReports',
+ BILL_PAYMENT_ACCOUNT_ID: 'billPaymentAccountID',
+ SYNC_EXPENSIFY_CARD_SETTLEMENTS: 'syncExpensifyCardSettlements',
+ SETTLEMENTS_BANK_ACCOUNT_ID: 'settlementsBankAccountID',
+ SYNC_TRAVEL_BILLING_SETTLEMENTS: 'syncTravelInvoicingSettlements',
+ TRAVEL_BILLING_SETTLEMENTS_BANK_ACCOUNT_ID: 'travelInvoicingSettlementsBankAccountID',
+ FIELD_MAPPING_PREFIX: 'fieldMapping_',
+ CARD_PROGRAM_ACCOUNT_PREFIX: 'cardProgramAccount_',
+ },
+
+ // Digits dimensions that can import as tags. Departments are the only dimension the Digits API exposes so far.
+ DIGITS_FIELD: {
+ DEPARTMENTS: 'departments',
+ },
+
+ DIGITS_MAPPING_VALUE: {
+ NONE: 'NONE',
+ TAG: 'TAG',
+ },
+
+ DIGITS_EXPORT_REIMBURSABLE: {
+ VENDOR_BILL: 'VENDOR_BILL',
+ },
+
+ DIGITS_EXPORT_NON_REIMBURSABLE: {
+ TRANSACTION: 'TRANSACTION',
+ },
+
+ DIGITS_EXPORT_DATE: {
+ LAST_EXPENSE: 'LAST_EXPENSE',
+ REPORT_EXPORTED: 'REPORT_EXPORTED',
+ REPORT_SUBMITTED: 'REPORT_SUBMITTED',
+ },
+
+ // The Digits chart of accounts subtypes that account pickers filter on. Every other subtype only imports as a category.
+ DIGITS_ACCOUNT_SUBTYPE: {
+ BANK_ACCOUNTS: 'BankAccounts',
+ CREDIT_CARDS: 'CreditCards',
+ OTHER_CURRENT_LIABILITIES: 'OtherCurrentLiabilities',
+ },
+
ZOHO_BOOKS_CONFIG: {
SUBSIDIARY_ID: 'subsidiaryID',
ENABLE_NEW_CATEGORIES: 'enableNewCategories',
@@ -5324,6 +5381,7 @@ const CONST = {
RILLET: 'rillet',
DUALENTRY: 'dualEntry',
CAMPFIRE: 'campfire',
+ DIGITS: 'digits',
ZOHO_BOOKS: 'zohoBooks',
BUSINESS_CENTRAL: 'businessCentral',
EXACT_ONLINE: 'exactOnline',
@@ -5346,6 +5404,7 @@ const CONST = {
RILLET: 'rillet',
DUALENTRY: 'dualentry',
CAMPFIRE: 'campfire',
+ DIGITS: 'digits',
ZOHO_BOOKS: 'zoho-books',
BUSINESS_CENTRAL: 'business-central',
GUSTO: 'gusto',
@@ -5363,6 +5422,7 @@ const CONST = {
rillet: 'Rillet',
dualEntry: 'DualEntry',
campfire: 'Campfire',
+ digits: 'Digits',
zohoBooks: 'Zoho Books',
businessCentral: 'Dynamics 365 Business Central',
exactOnline: 'Exact Online',
@@ -5390,6 +5450,7 @@ const CONST = {
this.NAME.CERTINIA,
this.NAME.RILLET,
this.NAME.DUALENTRY,
+ this.NAME.DIGITS,
this.NAME.CAMPFIRE,
this.NAME.ZOHO_BOOKS,
this.NAME.BUSINESS_CENTRAL,
@@ -5408,6 +5469,7 @@ const CONST = {
[this.NAME.RILLET]: 'rillet',
[this.NAME.DUALENTRY]: 'dualentry',
[this.NAME.CAMPFIRE]: 'campfire',
+ [this.NAME.DIGITS]: 'digits',
[this.NAME.ZOHO_BOOKS]: 'zohoBooks',
[this.NAME.BUSINESS_CENTRAL]: 'businessCentral',
} as const;
@@ -5530,6 +5592,12 @@ const CONST = {
CAMPFIRE_SYNC_PAYMENTS: 'campfireSyncPayments',
CAMPFIRE_SYNC_CARD_SETTLEMENTS: 'campfireSyncCardSettlements',
CAMPFIRE_SYNC_TRAVEL_SETTLEMENTS: 'campfireSyncTravelSettlements',
+ DIGITS_SYNC_TITLE: 'digitsSyncTitle',
+ DIGITS_SYNC_CONNECTION: 'digitsSyncConnection',
+ DIGITS_SYNC_IMPORT_DATA: 'digitsSyncImportData',
+ DIGITS_SYNC_PAYMENTS: 'digitsSyncPayments',
+ DIGITS_SYNC_CARD_SETTLEMENTS: 'digitsSyncCardSettlements',
+ DIGITS_SYNC_TRAVEL_SETTLEMENTS: 'digitsSyncTravelSettlements',
ZOHO_BOOKS_SYNC_CONNECTION: 'zohoBooksSyncConnection',
BUSINESS_CENTRAL_SYNC_TITLE: 'businessCentralSyncTitle',
BUSINESS_CENTRAL_SYNC_CONNECTION: 'businessCentralSyncConnection',
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index f7325a02a1b7..44ff38e5c63b 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -5444,6 +5444,18 @@ const ROUTES = {
route: 'workspaces/:policyID/accounting/campfire/advanced/travel-billing-payable-account',
getRoute: (policyID: string) => `workspaces/${policyID}/accounting/campfire/advanced/travel-billing-payable-account` as const,
},
+ POLICY_ACCOUNTING_DIGITS_OAUTH: {
+ route: 'workspaces/:policyID/accounting/digits/oauth',
+ getRoute: (policyID: string) => `workspaces/${policyID}/accounting/digits/oauth` as const,
+ },
+ POLICY_ACCOUNTING_DIGITS_EXISTING_CONNECTIONS: {
+ route: 'workspaces/:policyID/accounting/digits/existing-connections',
+ getRoute: (policyID: string) => `workspaces/${policyID}/accounting/digits/existing-connections` as const,
+ },
+ POLICY_ACCOUNTING_DIGITS_IMPORT: {
+ route: 'workspaces/:policyID/accounting/digits/import',
+ getRoute: (policyID: string) => `workspaces/${policyID}/accounting/digits/import` as const,
+ },
POLICY_ACCOUNTING_BUSINESS_CENTRAL_PREREQUISITES: {
route: 'workspaces/:policyID/accounting/business-central/prerequisites',
getRoute: (policyID: string) => `workspaces/${policyID}/accounting/business-central/prerequisites` as const,
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index f78d275e709a..d1ee9e361298 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -765,6 +765,9 @@ const SCREENS = {
CAMPFIRE_EXPENSIFY_CARD_SETTLEMENT_ACCOUNT: 'Policy_Accounting_Campfire_Expensify_Card_Settlement_Account',
CAMPFIRE_TRAVEL_BILLING_SETTLEMENT_ACCOUNT: 'Policy_Accounting_Campfire_Travel_Billing_Settlement_Account',
CAMPFIRE_TRAVEL_BILLING_PAYABLE_ACCOUNT: 'Policy_Accounting_Campfire_Travel_Billing_Payable_Account',
+ DIGITS_OAUTH: 'Policy_Accounting_Digits_OAuth',
+ DIGITS_EXISTING_CONNECTIONS: 'Policy_Accounting_Digits_Existing_Connections',
+ DIGITS_IMPORT: 'Policy_Accounting_Digits_Import',
BUSINESS_CENTRAL_PREREQUISITES: 'Policy_Accounting_Business_Central_Prerequisites',
BUSINESS_CENTRAL_SETUP: 'Policy_Accounting_Business_Central_Setup',
BUSINESS_CENTRAL_COMPANY_SELECTOR: 'Policy_Accounting_Business_Central_Company_Selector',
diff --git a/src/components/Icon/chunks/expensify-icons.chunk.ts b/src/components/Icon/chunks/expensify-icons.chunk.ts
index 4fa39f38a242..7ce2d52e2c33 100644
--- a/src/components/Icon/chunks/expensify-icons.chunk.ts
+++ b/src/components/Icon/chunks/expensify-icons.chunk.ts
@@ -144,6 +144,7 @@ import ChatGPTSquare from '@assets/images/integrationicons/chatgpt-icon-square.s
import CircleSlash from '@assets/images/integrationicons/circle-slash.svg';
import ClaudeSquare from '@assets/images/integrationicons/claude-icon-square.svg';
import CursorSquare from '@assets/images/integrationicons/cursor-icon-square.svg';
+import DigitsSquare from '@assets/images/integrationicons/digits-icon-square.svg';
import DualEntrySquare from '@assets/images/integrationicons/dualentry-icon-square.svg';
import ExactOnlineSquare from '@assets/images/integrationicons/exact-online-icon-square.svg';
import NetSuiteExport from '@assets/images/integrationicons/export/netsuite-icon.svg';
@@ -617,6 +618,7 @@ const Expensicons = {
Contactless,
CampfireSquare,
ZohoBooksSquare,
+ DigitsSquare,
};
// Create the ExpensifyIcons object from the imported Expensicons
diff --git a/src/languages/de.ts b/src/languages/de.ts
index f0ec5a85aa89..c550c377ddd4 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -7513,6 +7513,8 @@ Der Control-Tarif beginnt bei 9 $ pro aktivem Mitglied und Monat.`,
return 'DualEntry';
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE:
return 'Campfire';
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS:
+ return 'Digits';
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS:
return 'Zoho Books';
case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL:
@@ -7758,6 +7760,18 @@ Der Control-Tarif beginnt bei 9 $ pro aktivem Mitglied und Monat.`,
return 'Kartenausgleiche werden synchronisiert';
case 'campfireSyncTravelSettlements':
return 'Reiseabrechnungen werden synchronisiert';
+ case 'digitsSyncTitle':
+ return 'Digits-Daten werden synchronisiert';
+ case 'digitsSyncConnection':
+ return 'Verbindung zu Digits wird initialisiert';
+ case 'digitsSyncImportData':
+ return 'Daten werden geladen';
+ case 'digitsSyncPayments':
+ return 'Lieferantenzahlungen werden synchronisiert';
+ case 'digitsSyncCardSettlements':
+ return 'Kartenausgleiche werden synchronisiert';
+ case 'digitsSyncTravelSettlements':
+ return 'Reiseabrechnungen werden synchronisiert';
case 'businessCentralSyncTitle':
return 'Dynamics 365 Business Central-Daten werden synchronisiert';
case 'businessCentralSyncConnection':
@@ -7807,6 +7821,7 @@ Der Control-Tarif beginnt bei 9 $ pro aktivem Mitglied und Monat.`,
syncTravelBillingSettlementsNoAccountTooltip: 'Zum Aktivieren legen Sie ein Konto für Ihre Exporte fest.',
syncTravelBillingSettlementsNoAutoSyncTooltip: 'Zum Entsperren automatische Synchronisierung aktivieren.',
campfire: 'Campfire',
+ digits: 'Digits',
zohoBooks: 'Zoho Books',
continuousReconciliationFeedSelection:
'Die fortlaufende Abstimmung wird pro Kartenfeed konfiguriert. Wählen Sie einen Feed aus, um zu ändern, welchen Sie konfigurieren.',
diff --git a/src/languages/el.ts b/src/languages/el.ts
index cf208a1a3120..3abe6db46d5c 100644
--- a/src/languages/el.ts
+++ b/src/languages/el.ts
@@ -7641,6 +7641,8 @@ _Για πιο αναλυτικές οδηγίες, [επισκεφθείτε τ
return 'DualEntry';
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE:
return 'Campfire';
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS:
+ return 'Digits';
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS:
return 'Zoho Books';
case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL:
@@ -7887,6 +7889,18 @@ _Για πιο αναλυτικές οδηγίες, [επισκεφθείτε τ
return 'Συγχρονισμός διακανονισμών κάρτας';
case 'campfireSyncTravelSettlements':
return 'Συγχρονισμός εκκαθαρίσεων ταξιδιών';
+ case 'digitsSyncTitle':
+ return 'Γίνεται συγχρονισμός δεδομένων Digits';
+ case 'digitsSyncConnection':
+ return 'Γίνεται αρχικοποίηση σύνδεσης με το Digits';
+ case 'digitsSyncImportData':
+ return 'Φόρτωση δεδομένων';
+ case 'digitsSyncPayments':
+ return 'Συγχρονισμός πληρωμών προμηθευτών';
+ case 'digitsSyncCardSettlements':
+ return 'Συγχρονισμός διακανονισμών κάρτας';
+ case 'digitsSyncTravelSettlements':
+ return 'Συγχρονισμός εκκαθαρίσεων ταξιδιών';
case 'businessCentralSyncTitle':
return 'Συγχρονισμός δεδομένων Dynamics 365 Business Central';
case 'businessCentralSyncConnection':
@@ -7936,6 +7950,7 @@ _Για πιο αναλυτικές οδηγίες, [επισκεφθείτε τ
syncTravelBillingSettlementsNoAccountTooltip: 'Για να το ενεργοποιήσετε, ορίστε έναν λογαριασμό για τις εξαγωγές σας.',
syncTravelBillingSettlementsNoAutoSyncTooltip: 'Για να το ξεκλειδώσετε, ενεργοποιήστε τον αυτόματο συγχρονισμό.',
campfire: 'Campfire',
+ digits: 'Digits',
zohoBooks: 'Zoho Books',
continuousReconciliationFeedSelection:
'Η συνεχής συμφωνία είναι ρυθμισμένη ανά ροή καρτών. Επιλέξτε μια ροή για να αλλάξετε ποια ρυθμίζετε.',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index ec5bed28d37e..fe7f3527e672 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -7924,6 +7924,7 @@ const translations = {
rillet: 'Rillet',
dualEntry: 'DualEntry',
campfire: 'Campfire',
+ digits: 'Digits',
zohoBooks: 'Zoho Books',
businessCentral: 'Dynamics 365 Business Central',
sap: 'SAP',
@@ -7949,6 +7950,8 @@ const translations = {
return 'DualEntry';
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE:
return 'Campfire';
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS:
+ return 'Digits';
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS:
return 'Zoho Books';
case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL:
@@ -8200,6 +8203,18 @@ const translations = {
return 'Syncing card settlements';
case 'campfireSyncTravelSettlements':
return 'Syncing travel settlements';
+ case 'digitsSyncTitle':
+ return 'Syncing Digits data';
+ case 'digitsSyncConnection':
+ return 'Initializing connection to Digits';
+ case 'digitsSyncImportData':
+ return 'Loading data';
+ case 'digitsSyncPayments':
+ return 'Syncing vendor payments';
+ case 'digitsSyncCardSettlements':
+ return 'Syncing card settlements';
+ case 'digitsSyncTravelSettlements':
+ return 'Syncing travel settlements';
case 'businessCentralSyncTitle':
return 'Syncing Dynamics 365 Business Central data';
case 'businessCentralSyncConnection':
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 6d13b9f0666f..f86bbf9661e1 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7309,6 +7309,8 @@ El plan Controlar empieza en 9 $ por miembro activo al mes.`,
return 'DualEntry';
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE:
return 'Campfire';
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS:
+ return 'Digits';
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS:
return 'Zoho Books';
case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL:
@@ -7555,6 +7557,18 @@ El plan Controlar empieza en 9 $ por miembro activo al mes.`,
return 'Sincronizando liquidaciones de tarjetas';
case 'campfireSyncTravelSettlements':
return 'Sincronizando liquidaciones de viaje';
+ case 'digitsSyncTitle':
+ return 'Sincronizando datos de Digits';
+ case 'digitsSyncConnection':
+ return 'Iniciando conexión con Digits';
+ case 'digitsSyncImportData':
+ return 'Cargando datos';
+ case 'digitsSyncPayments':
+ return 'Sincronizando pagos a proveedores';
+ case 'digitsSyncCardSettlements':
+ return 'Sincronizando liquidaciones de tarjetas';
+ case 'digitsSyncTravelSettlements':
+ return 'Sincronizando liquidaciones de viaje';
case 'businessCentralSyncTitle':
return 'Sincronizando datos de Dynamics 365 Business Central';
case 'businessCentralSyncConnection':
@@ -7604,6 +7618,7 @@ El plan Controlar empieza en 9 $ por miembro activo al mes.`,
syncTravelBillingSettlementsNoAccountTooltip: 'Para desbloquearlo, configura una cuenta para tus exportaciones.',
syncTravelBillingSettlementsNoAutoSyncTooltip: 'Para desbloquear, habilita la sincronización automática.',
campfire: 'Campfire',
+ digits: 'Digits',
zohoBooks: 'Zoho Books',
continuousReconciliationFeedSelection:
'La conciliación continua se configura por cada fuente de tarjetas. Selecciona una fuente para cambiar cuál estás configurando.',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index cf72d1909f84..276597114689 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -7533,6 +7533,8 @@ Le forfait Control commence à 9 $ par Membre actif et par mois.`,
return 'DualEntry';
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE:
return 'Campfire';
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS:
+ return 'Digits';
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS:
return 'Zoho Books';
case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL:
@@ -7779,6 +7781,18 @@ Le forfait Control commence à 9 $ par Membre actif et par mois.`,
return 'Synchronisation des règlements de carte';
case 'campfireSyncTravelSettlements':
return 'Synchronisation des règlements de voyage';
+ case 'digitsSyncTitle':
+ return 'Synchronisation des données Digits';
+ case 'digitsSyncConnection':
+ return 'Initialisation de la connexion à Digits';
+ case 'digitsSyncImportData':
+ return 'Chargement des données';
+ case 'digitsSyncPayments':
+ return 'Synchronisation des paiements fournisseurs';
+ case 'digitsSyncCardSettlements':
+ return 'Synchronisation des règlements de carte';
+ case 'digitsSyncTravelSettlements':
+ return 'Synchronisation des règlements de voyage';
case 'businessCentralSyncTitle':
return 'Synchronisation des données Dynamics 365 Business Central';
case 'businessCentralSyncConnection':
@@ -7828,6 +7842,7 @@ Le forfait Control commence à 9 $ par Membre actif et par mois.`,
syncTravelBillingSettlementsNoAccountTooltip: 'Pour le déverrouiller, définissez un compte pour vos exports.',
syncTravelBillingSettlementsNoAutoSyncTooltip: 'Pour le déverrouiller, activez la synchronisation automatique.',
campfire: 'Campfire',
+ digits: 'Digits',
zohoBooks: 'Zoho Books',
continuousReconciliationFeedSelection:
'Le rapprochement continu est configuré par flux de carte. Sélectionnez un flux pour changer celui que vous configurez.',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index a359dd417d8d..513fc2eeedd2 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -7473,6 +7473,8 @@ Il piano Control parte da 9 $ al mese per ogni membro attivo.`,
return 'DualEntry';
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE:
return 'Campfire';
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS:
+ return 'Digits';
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS:
return 'Zoho Books';
case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL:
@@ -7718,6 +7720,18 @@ Il piano Control parte da 9 $ al mese per ogni membro attivo.`,
return 'Sincronizzazione delle chiusure carta';
case 'campfireSyncTravelSettlements':
return 'Sincronizzazione dei conguagli di viaggio';
+ case 'digitsSyncTitle':
+ return 'Sincronizzazione dei dati Digits';
+ case 'digitsSyncConnection':
+ return 'Inizializzazione della connessione a Digits';
+ case 'digitsSyncImportData':
+ return 'Caricamento dei dati';
+ case 'digitsSyncPayments':
+ return 'Sincronizzazione dei pagamenti ai fornitori';
+ case 'digitsSyncCardSettlements':
+ return 'Sincronizzazione delle chiusure carta';
+ case 'digitsSyncTravelSettlements':
+ return 'Sincronizzazione dei conguagli di viaggio';
case 'businessCentralSyncTitle':
return 'Sincronizzazione dei dati Dynamics 365 Business Central';
case 'businessCentralSyncConnection':
@@ -7767,6 +7781,7 @@ Il piano Control parte da 9 $ al mese per ogni membro attivo.`,
syncTravelBillingSettlementsNoAccountTooltip: 'Per sbloccare, imposta un conto per le tue esportazioni.',
syncTravelBillingSettlementsNoAutoSyncTooltip: 'Per sbloccare, abilita la sincronizzazione automatica.',
campfire: 'Campfire',
+ digits: 'Digits',
zohoBooks: 'Zoho Books',
continuousReconciliationFeedSelection:
'La Riconciliazione continua è configurata per ogni flusso di carte. Seleziona un flusso per cambiare quello che stai configurando.',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index dc04cf45f283..9d7bc32e1ce9 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -7377,6 +7377,8 @@ Control プランは、アクティブメンバー1人あたり月額 $9 から
return 'DualEntry';
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE:
return 'Campfire';
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS:
+ return 'Digits';
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS:
return 'Zoho Books';
case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL:
@@ -7623,6 +7625,18 @@ Control プランは、アクティブメンバー1人あたり月額 $9 から
return 'カード精算を同期しています';
case 'campfireSyncTravelSettlements':
return '出張精算を同期しています';
+ case 'digitsSyncTitle':
+ return 'Digits データを同期しています';
+ case 'digitsSyncConnection':
+ return 'Digits への接続を初期化しています';
+ case 'digitsSyncImportData':
+ return 'データを読み込んでいます';
+ case 'digitsSyncPayments':
+ return '仕入先への支払いを同期しています';
+ case 'digitsSyncCardSettlements':
+ return 'カード精算を同期しています';
+ case 'digitsSyncTravelSettlements':
+ return '出張精算を同期しています';
case 'businessCentralSyncTitle':
return 'Dynamics 365 Business Central データを同期しています';
case 'businessCentralSyncConnection':
@@ -7671,6 +7685,7 @@ Control プランは、アクティブメンバー1人あたり月額 $9 から
syncTravelBillingSettlementsNoAccountTooltip: 'ロックを解除するには、エクスポート用の口座を設定してください。',
syncTravelBillingSettlementsNoAutoSyncTooltip: 'ロックを解除するには、自動同期を有効にしてください。',
campfire: 'Campfire',
+ digits: 'Digits',
zohoBooks: 'Zoho Books',
continuousReconciliationFeedSelection:
'継続的な照合はカードフィードごとに設定されます。設定するフィードを変更するには、フィードを選択してください。',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 7f66c58a20f4..1b4adc836ef5 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -7455,6 +7455,8 @@ Het Control-abonnement begint bij $9 per actieve deelnemer per maand.`,
return 'DualEntry';
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE:
return 'Campfire';
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS:
+ return 'Digits';
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS:
return 'Zoho Books';
case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL:
@@ -7700,6 +7702,18 @@ Het Control-abonnement begint bij $9 per actieve deelnemer per maand.`,
return 'Kaartafrekeningen synchroniseren';
case 'campfireSyncTravelSettlements':
return 'Reisverrekeningen synchroniseren';
+ case 'digitsSyncTitle':
+ return 'Digits-gegevens synchroniseren';
+ case 'digitsSyncConnection':
+ return 'Verbinding met Digits initialiseren';
+ case 'digitsSyncImportData':
+ return 'Gegevens laden';
+ case 'digitsSyncPayments':
+ return 'Leveranciersbetalingen synchroniseren';
+ case 'digitsSyncCardSettlements':
+ return 'Kaartafrekeningen synchroniseren';
+ case 'digitsSyncTravelSettlements':
+ return 'Reisverrekeningen synchroniseren';
case 'businessCentralSyncTitle':
return 'Dynamics 365 Business Central-gegevens synchroniseren';
case 'businessCentralSyncConnection':
@@ -7749,6 +7763,7 @@ Het Control-abonnement begint bij $9 per actieve deelnemer per maand.`,
syncTravelBillingSettlementsNoAccountTooltip: 'Om dit te ontgrendelen, stel je een rekening in voor je exporten.',
syncTravelBillingSettlementsNoAutoSyncTooltip: 'Schakel automatisch synchroniseren in om dit te ontgrendelen.',
campfire: 'Campfire',
+ digits: 'Digits',
zohoBooks: 'Zoho Books',
continuousReconciliationFeedSelection:
'Doorlopende afstemming wordt per kaartfeed geconfigureerd. Selecteer een feed om te wijzigen welke je configureert.',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 689a79bdaad3..233af57663ed 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -7483,6 +7483,8 @@ Plan Control zaczyna się od 9 USD za aktywnego członka miesięcznie.`,
return 'DualEntry';
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE:
return 'Campfire';
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS:
+ return 'Digits';
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS:
return 'Zoho Books';
case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL:
@@ -7728,6 +7730,18 @@ Plan Control zaczyna się od 9 USD za aktywnego członka miesięcznie.`,
return 'Synchronizowanie rozliczeń karty';
case 'campfireSyncTravelSettlements':
return 'Synchronizowanie rozliczeń podróży';
+ case 'digitsSyncTitle':
+ return 'Synchronizowanie danych Digits';
+ case 'digitsSyncConnection':
+ return 'Inicjowanie połączenia z Digits';
+ case 'digitsSyncImportData':
+ return 'Wczytywanie danych';
+ case 'digitsSyncPayments':
+ return 'Synchronizowanie płatności dla dostawców';
+ case 'digitsSyncCardSettlements':
+ return 'Synchronizowanie rozliczeń karty';
+ case 'digitsSyncTravelSettlements':
+ return 'Synchronizowanie rozliczeń podróży';
case 'businessCentralSyncTitle':
return 'Synchronizowanie danych Dynamics 365 Business Central';
case 'businessCentralSyncConnection':
@@ -7776,6 +7790,7 @@ Plan Control zaczyna się od 9 USD za aktywnego członka miesięcznie.`,
syncTravelBillingSettlementsNoAccountTooltip: 'Aby odblokować, ustaw konto dla swoich eksportów.',
syncTravelBillingSettlementsNoAutoSyncTooltip: 'Aby odblokować, włącz automatyczną synchronizację.',
campfire: 'Campfire',
+ digits: 'Digits',
zohoBooks: 'Zoho Books',
continuousReconciliationFeedSelection:
'Ciągłe uzgadnianie jest konfigurowane dla każdego źródła kart osobno. Wybierz źródło, aby zmienić, które konfigurujesz.',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 23c8762e1f4a..b286689a1066 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -7455,6 +7455,8 @@ O plano Control começa em US$ 9 por membro ativo por mês.`,
return 'DualEntry';
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE:
return 'Campfire';
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS:
+ return 'Digits';
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS:
return 'Zoho Books';
case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL:
@@ -7700,6 +7702,18 @@ O plano Control começa em US$ 9 por membro ativo por mês.`,
return 'Sincronizando liquidações de cartão';
case 'campfireSyncTravelSettlements':
return 'Sincronizando acertos de viagem';
+ case 'digitsSyncTitle':
+ return 'Sincronizando dados do Digits';
+ case 'digitsSyncConnection':
+ return 'Inicializando conexão com o Digits';
+ case 'digitsSyncImportData':
+ return 'Carregando dados';
+ case 'digitsSyncPayments':
+ return 'Sincronizando pagamentos a fornecedores';
+ case 'digitsSyncCardSettlements':
+ return 'Sincronizando liquidações de cartão';
+ case 'digitsSyncTravelSettlements':
+ return 'Sincronizando acertos de viagem';
case 'businessCentralSyncTitle':
return 'Sincronizando dados do Dynamics 365 Business Central';
case 'businessCentralSyncConnection':
@@ -7749,6 +7763,7 @@ O plano Control começa em US$ 9 por membro ativo por mês.`,
syncTravelBillingSettlementsNoAccountTooltip: 'Para desbloquear, defina uma conta para suas exportações.',
syncTravelBillingSettlementsNoAutoSyncTooltip: 'Para desbloquear, ative a sincronização automática.',
campfire: 'Campfire',
+ digits: 'Digits',
zohoBooks: 'Zoho Books',
continuousReconciliationFeedSelection:
'A Conciliação Contínua é configurada por feed de cartão. Selecione um feed para alterar qual você está configurando.',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index a7447e3f4ef3..7a56e2cc270c 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -7197,6 +7197,8 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
return 'DualEntry';
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE:
return 'Campfire';
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS:
+ return 'Digits';
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS:
return 'Zoho Books';
case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL:
@@ -7441,6 +7443,18 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
return '正在同步信用卡结算';
case 'campfireSyncTravelSettlements':
return '正在同步差旅结算';
+ case 'digitsSyncTitle':
+ return '正在同步 Digits 数据';
+ case 'digitsSyncConnection':
+ return '正在初始化与 Digits 的连接';
+ case 'digitsSyncImportData':
+ return '正在加载数据';
+ case 'digitsSyncPayments':
+ return '正在同步供应商付款';
+ case 'digitsSyncCardSettlements':
+ return '正在同步信用卡结算';
+ case 'digitsSyncTravelSettlements':
+ return '正在同步差旅结算';
case 'businessCentralSyncTitle':
return '同步 Dynamics 365 Business Central 数据';
case 'businessCentralSyncConnection':
@@ -7485,6 +7499,7 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
syncTravelBillingSettlementsNoAccountTooltip: '要解锁,请为导出设置一个账户。',
syncTravelBillingSettlementsNoAutoSyncTooltip: '若要解锁,请启用自动同步。',
campfire: 'Campfire',
+ digits: 'Digits',
zohoBooks: 'Zoho Books',
continuousReconciliationFeedSelection: '按卡片流水单独配置持续对账。选择一个流水以更改您正在配置的流水。',
businessCentral: 'Dynamics 365 Business Central',
diff --git a/src/libs/API/parameters/ConnectPolicyToDigitsParams.ts b/src/libs/API/parameters/ConnectPolicyToDigitsParams.ts
new file mode 100644
index 000000000000..1a5cfa3ecd81
--- /dev/null
+++ b/src/libs/API/parameters/ConnectPolicyToDigitsParams.ts
@@ -0,0 +1,5 @@
+type ConnectPolicyToDigitsParams = {
+ policyID: string;
+};
+
+export default ConnectPolicyToDigitsParams;
diff --git a/src/libs/API/parameters/SyncPolicyToDigitsParams.ts b/src/libs/API/parameters/SyncPolicyToDigitsParams.ts
new file mode 100644
index 000000000000..27c30a577469
--- /dev/null
+++ b/src/libs/API/parameters/SyncPolicyToDigitsParams.ts
@@ -0,0 +1,6 @@
+type SyncPolicyToDigitsParams = {
+ policyID: string;
+ idempotencyKey: string;
+};
+
+export default SyncPolicyToDigitsParams;
diff --git a/src/libs/API/parameters/UpdateDigitsAccountingMethodParams.ts b/src/libs/API/parameters/UpdateDigitsAccountingMethodParams.ts
new file mode 100644
index 000000000000..88361d5c6829
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsAccountingMethodParams.ts
@@ -0,0 +1,9 @@
+import type {CONST as COMMON_CONST} from 'expensify-common';
+import type {ValueOf} from 'type-fest';
+
+type UpdateDigitsAccountingMethodParams = {
+ policyID: string;
+ accountingMethod: ValueOf;
+};
+
+export default UpdateDigitsAccountingMethodParams;
diff --git a/src/libs/API/parameters/UpdateDigitsAutoSyncParams.ts b/src/libs/API/parameters/UpdateDigitsAutoSyncParams.ts
new file mode 100644
index 000000000000..0e67b16dbaad
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsAutoSyncParams.ts
@@ -0,0 +1,6 @@
+type UpdateDigitsAutoSyncParams = {
+ policyID: string;
+ enabled: boolean;
+};
+
+export default UpdateDigitsAutoSyncParams;
diff --git a/src/libs/API/parameters/UpdateDigitsBillPaymentAccountParams.ts b/src/libs/API/parameters/UpdateDigitsBillPaymentAccountParams.ts
new file mode 100644
index 000000000000..b1c5bde78870
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsBillPaymentAccountParams.ts
@@ -0,0 +1,8 @@
+import type {DigitsAccount} from '@src/types/onyx/Policy';
+
+type UpdateDigitsBillPaymentAccountParams = {
+ policyID: string;
+ billPaymentAccountID: DigitsAccount['id'];
+};
+
+export default UpdateDigitsBillPaymentAccountParams;
diff --git a/src/libs/API/parameters/UpdateDigitsCardProgramAccountParams.ts b/src/libs/API/parameters/UpdateDigitsCardProgramAccountParams.ts
new file mode 100644
index 000000000000..755f2eb32da1
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsCardProgramAccountParams.ts
@@ -0,0 +1,10 @@
+import type {CardFeedWithNumber} from '@src/types/onyx/CardFeeds';
+import type {DigitsAccount} from '@src/types/onyx/Policy';
+
+type UpdateDigitsCardProgramAccountParams = {
+ policyID: string;
+ feedKey: CardFeedWithNumber;
+ cardProgramAccountID: DigitsAccount['id'];
+};
+
+export default UpdateDigitsCardProgramAccountParams;
diff --git a/src/libs/API/parameters/UpdateDigitsCreditCardAccountParams.ts b/src/libs/API/parameters/UpdateDigitsCreditCardAccountParams.ts
new file mode 100644
index 000000000000..15db621de54e
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsCreditCardAccountParams.ts
@@ -0,0 +1,8 @@
+import type {DigitsAccount} from '@src/types/onyx/Policy';
+
+type UpdateDigitsCreditCardAccountParams = {
+ policyID: string;
+ creditCardAccountID: DigitsAccount['id'];
+};
+
+export default UpdateDigitsCreditCardAccountParams;
diff --git a/src/libs/API/parameters/UpdateDigitsDefaultVendorParams.ts b/src/libs/API/parameters/UpdateDigitsDefaultVendorParams.ts
new file mode 100644
index 000000000000..1d5abe1e5217
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsDefaultVendorParams.ts
@@ -0,0 +1,8 @@
+import type {DigitsVendor} from '@src/types/onyx/Policy';
+
+type UpdateDigitsDefaultVendorParams = {
+ policyID: string;
+ vendorID: DigitsVendor['id'];
+};
+
+export default UpdateDigitsDefaultVendorParams;
diff --git a/src/libs/API/parameters/UpdateDigitsEnableNewCategoriesParams.ts b/src/libs/API/parameters/UpdateDigitsEnableNewCategoriesParams.ts
new file mode 100644
index 000000000000..bdaff2b5b7e5
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsEnableNewCategoriesParams.ts
@@ -0,0 +1,9 @@
+type UpdateDigitsEnableNewCategoriesParams = {
+ /** The workspace where the setting is updated. */
+ policyID: string;
+
+ /** Whether categories newly created in Digits are imported. */
+ enabled: boolean;
+};
+
+export default UpdateDigitsEnableNewCategoriesParams;
diff --git a/src/libs/API/parameters/UpdateDigitsExportDateParams.ts b/src/libs/API/parameters/UpdateDigitsExportDateParams.ts
new file mode 100644
index 000000000000..f93156692503
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsExportDateParams.ts
@@ -0,0 +1,8 @@
+import type {DigitsExportDate} from '@src/types/onyx/Policy';
+
+type UpdateDigitsExportDateParams = {
+ policyID: string;
+ value: DigitsExportDate;
+};
+
+export default UpdateDigitsExportDateParams;
diff --git a/src/libs/API/parameters/UpdateDigitsExportToMultipleAccountsParams.ts b/src/libs/API/parameters/UpdateDigitsExportToMultipleAccountsParams.ts
new file mode 100644
index 000000000000..238575d5dbe9
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsExportToMultipleAccountsParams.ts
@@ -0,0 +1,6 @@
+type UpdateDigitsExportToMultipleAccountsParams = {
+ policyID: string;
+ enabled: boolean;
+};
+
+export default UpdateDigitsExportToMultipleAccountsParams;
diff --git a/src/libs/API/parameters/UpdateDigitsExporterParams.ts b/src/libs/API/parameters/UpdateDigitsExporterParams.ts
new file mode 100644
index 000000000000..4518e386fe15
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsExporterParams.ts
@@ -0,0 +1,6 @@
+type UpdateDigitsExporterParams = {
+ policyID: string;
+ email: string;
+};
+
+export default UpdateDigitsExporterParams;
diff --git a/src/libs/API/parameters/UpdateDigitsFieldMappingParams.ts b/src/libs/API/parameters/UpdateDigitsFieldMappingParams.ts
new file mode 100644
index 000000000000..229884fa1956
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsFieldMappingParams.ts
@@ -0,0 +1,16 @@
+import type CONST from '@src/CONST';
+
+import type {ValueOf} from 'type-fest';
+
+type UpdateDigitsFieldMappingParams = {
+ /** The workspace where the field mapping is updated. */
+ policyID: string;
+
+ /** The Digits dimension to map. */
+ fieldID: ValueOf;
+
+ /** The Expensify dimension mapped to the Digits dimension. */
+ mapping: ValueOf;
+};
+
+export default UpdateDigitsFieldMappingParams;
diff --git a/src/libs/API/parameters/UpdateDigitsSettlementsAccountParams.ts b/src/libs/API/parameters/UpdateDigitsSettlementsAccountParams.ts
new file mode 100644
index 000000000000..d7f343e7313b
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsSettlementsAccountParams.ts
@@ -0,0 +1,8 @@
+import type {DigitsAccount} from '@src/types/onyx/Policy';
+
+type UpdateDigitsSettlementsAccountParams = {
+ policyID: string;
+ settlementsBankAccountID: DigitsAccount['id'];
+};
+
+export default UpdateDigitsSettlementsAccountParams;
diff --git a/src/libs/API/parameters/UpdateDigitsSyncExpensifyCardSettlementsParams.ts b/src/libs/API/parameters/UpdateDigitsSyncExpensifyCardSettlementsParams.ts
new file mode 100644
index 000000000000..ab924645f9b5
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsSyncExpensifyCardSettlementsParams.ts
@@ -0,0 +1,6 @@
+type UpdateDigitsSyncExpensifyCardSettlementsParams = {
+ policyID: string;
+ enabled: boolean;
+};
+
+export default UpdateDigitsSyncExpensifyCardSettlementsParams;
diff --git a/src/libs/API/parameters/UpdateDigitsSyncReimbursedReportsParams.ts b/src/libs/API/parameters/UpdateDigitsSyncReimbursedReportsParams.ts
new file mode 100644
index 000000000000..7e033121d00f
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsSyncReimbursedReportsParams.ts
@@ -0,0 +1,6 @@
+type UpdateDigitsSyncReimbursedReportsParams = {
+ policyID: string;
+ enabled: boolean;
+};
+
+export default UpdateDigitsSyncReimbursedReportsParams;
diff --git a/src/libs/API/parameters/UpdateDigitsSyncTravelInvoicingSettlementsParams.ts b/src/libs/API/parameters/UpdateDigitsSyncTravelInvoicingSettlementsParams.ts
new file mode 100644
index 000000000000..3a1ee144b869
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsSyncTravelInvoicingSettlementsParams.ts
@@ -0,0 +1,6 @@
+type UpdateDigitsSyncTravelInvoicingSettlementsParams = {
+ policyID: string;
+ enabled: boolean;
+};
+
+export default UpdateDigitsSyncTravelInvoicingSettlementsParams;
diff --git a/src/libs/API/parameters/UpdateDigitsTravelInvoicingPayableAccountParams.ts b/src/libs/API/parameters/UpdateDigitsTravelInvoicingPayableAccountParams.ts
new file mode 100644
index 000000000000..aa7b446fb3e2
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsTravelInvoicingPayableAccountParams.ts
@@ -0,0 +1,8 @@
+import type {DigitsAccount} from '@src/types/onyx/Policy';
+
+type UpdateDigitsTravelInvoicingPayableAccountParams = {
+ policyID: string;
+ travelInvoicingPayableAccountID: DigitsAccount['id'];
+};
+
+export default UpdateDigitsTravelInvoicingPayableAccountParams;
diff --git a/src/libs/API/parameters/UpdateDigitsTravelInvoicingSettlementsAccountParams.ts b/src/libs/API/parameters/UpdateDigitsTravelInvoicingSettlementsAccountParams.ts
new file mode 100644
index 000000000000..3b4c204d936c
--- /dev/null
+++ b/src/libs/API/parameters/UpdateDigitsTravelInvoicingSettlementsAccountParams.ts
@@ -0,0 +1,8 @@
+import type {DigitsAccount} from '@src/types/onyx/Policy';
+
+type UpdateDigitsTravelInvoicingSettlementsAccountParams = {
+ policyID: string;
+ travelInvoicingSettlementsBankAccountID: DigitsAccount['id'];
+};
+
+export default UpdateDigitsTravelInvoicingSettlementsAccountParams;
diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts
index 4b8058c6a92f..1734eb9deb54 100644
--- a/src/libs/API/parameters/index.ts
+++ b/src/libs/API/parameters/index.ts
@@ -31,6 +31,7 @@ export type {default as ConnectPolicyToZenefitsParams} from './ConnectPolicyToZe
export type {default as ConnectPolicyToRilletParams} from './ConnectPolicyToRilletParams';
export type {default as ConnectPolicyToDualEntryParams} from './ConnectPolicyToDualEntryParams';
export type {default as ConnectPolicyToCampfireParams} from './ConnectPolicyToCampfireParams';
+export type {default as ConnectPolicyToDigitsParams} from './ConnectPolicyToDigitsParams';
export type {default as ConnectPolicyToZohoBooksParams} from './ConnectPolicyToZohoBooksParams';
export type {default as ConnectPolicyToBusinessCentralParams} from './ConnectPolicyToBusinessCentralParams';
export type {default as OpenPolicyProfilePageParams} from './OpenPolicyProfilePageParams';
@@ -104,6 +105,24 @@ export type {default as UpdateCampfireSettlementsAccountParams} from './UpdateCa
export type {default as UpdateCampfireSyncTravelInvoicingSettlementsParams} from './UpdateCampfireSyncTravelInvoicingSettlementsParams';
export type {default as UpdateCampfireTravelInvoicingSettlementsAccountParams} from './UpdateCampfireTravelInvoicingSettlementsAccountParams';
export type {default as UpdateCampfireTravelInvoicingPayableAccountParams} from './UpdateCampfireTravelInvoicingPayableAccountParams';
+export type {default as SyncPolicyToDigitsParams} from './SyncPolicyToDigitsParams';
+export type {default as UpdateDigitsFieldMappingParams} from './UpdateDigitsFieldMappingParams';
+export type {default as UpdateDigitsEnableNewCategoriesParams} from './UpdateDigitsEnableNewCategoriesParams';
+export type {default as UpdateDigitsExporterParams} from './UpdateDigitsExporterParams';
+export type {default as UpdateDigitsExportDateParams} from './UpdateDigitsExportDateParams';
+export type {default as UpdateDigitsDefaultVendorParams} from './UpdateDigitsDefaultVendorParams';
+export type {default as UpdateDigitsCreditCardAccountParams} from './UpdateDigitsCreditCardAccountParams';
+export type {default as UpdateDigitsExportToMultipleAccountsParams} from './UpdateDigitsExportToMultipleAccountsParams';
+export type {default as UpdateDigitsCardProgramAccountParams} from './UpdateDigitsCardProgramAccountParams';
+export type {default as UpdateDigitsAutoSyncParams} from './UpdateDigitsAutoSyncParams';
+export type {default as UpdateDigitsAccountingMethodParams} from './UpdateDigitsAccountingMethodParams';
+export type {default as UpdateDigitsSyncReimbursedReportsParams} from './UpdateDigitsSyncReimbursedReportsParams';
+export type {default as UpdateDigitsBillPaymentAccountParams} from './UpdateDigitsBillPaymentAccountParams';
+export type {default as UpdateDigitsSyncExpensifyCardSettlementsParams} from './UpdateDigitsSyncExpensifyCardSettlementsParams';
+export type {default as UpdateDigitsSettlementsAccountParams} from './UpdateDigitsSettlementsAccountParams';
+export type {default as UpdateDigitsSyncTravelInvoicingSettlementsParams} from './UpdateDigitsSyncTravelInvoicingSettlementsParams';
+export type {default as UpdateDigitsTravelInvoicingSettlementsAccountParams} from './UpdateDigitsTravelInvoicingSettlementsAccountParams';
+export type {default as UpdateDigitsTravelInvoicingPayableAccountParams} from './UpdateDigitsTravelInvoicingPayableAccountParams';
export type {default as SyncPolicyToZohoBooksParams} from './SyncPolicyToZohoBooksParams';
export type {default as UpdateZohoBooksSubsidiaryParams} from './UpdateZohoBooksSubsidiaryParams';
export type {default as UpdateZohoBooksFieldMappingParams} from './UpdateZohoBooksFieldMappingParams';
diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts
index a934ec144f10..3af61651bbc1 100644
--- a/src/libs/API/types.ts
+++ b/src/libs/API/types.ts
@@ -639,6 +639,23 @@ const WRITE_COMMANDS = {
UPDATE_CAMPFIRE_SYNC_TRAVEL_INVOICING_SETTLEMENTS: 'UpdateCampfireSyncTravelInvoicingSettlements',
UPDATE_CAMPFIRE_TRAVEL_INVOICING_SETTLEMENTS_ACCOUNT: 'UpdateCampfireTravelInvoicingSettlementsAccount',
UPDATE_CAMPFIRE_TRAVEL_INVOICING_PAYABLE_ACCOUNT: 'UpdateCampfireTravelInvoicingPayableAccount',
+ UPDATE_DIGITS_FIELD_MAPPING: 'UpdateDigitsFieldMapping',
+ UPDATE_DIGITS_ENABLE_NEW_CATEGORIES: 'UpdateDigitsEnableNewCategories',
+ UPDATE_DIGITS_EXPORTER: 'UpdateDigitsExporter',
+ UPDATE_DIGITS_EXPORT_DATE: 'UpdateDigitsExportDate',
+ UPDATE_DIGITS_DEFAULT_VENDOR: 'UpdateDigitsDefaultVendor',
+ UPDATE_DIGITS_CREDIT_CARD_ACCOUNT: 'UpdateDigitsCreditCardAccount',
+ UPDATE_DIGITS_EXPORT_TO_MULTIPLE_ACCOUNTS: 'UpdateDigitsExportToMultipleAccounts',
+ UPDATE_DIGITS_CARD_PROGRAM_ACCOUNT: 'UpdateDigitsCardProgramAccount',
+ UPDATE_DIGITS_AUTO_SYNC: 'UpdateDigitsAutoSync',
+ UPDATE_DIGITS_ACCOUNTING_METHOD: 'UpdateDigitsAccountingMethod',
+ UPDATE_DIGITS_SYNC_REIMBURSED_REPORTS: 'UpdateDigitsSyncReimbursedReports',
+ UPDATE_DIGITS_BILL_PAYMENT_ACCOUNT: 'UpdateDigitsBillPaymentAccount',
+ UPDATE_DIGITS_SYNC_EXPENSIFY_CARD_SETTLEMENTS: 'UpdateDigitsSyncExpensifyCardSettlements',
+ UPDATE_DIGITS_SETTLEMENTS_ACCOUNT: 'UpdateDigitsSettlementsAccount',
+ UPDATE_DIGITS_SYNC_TRAVEL_INVOICING_SETTLEMENTS: 'UpdateDigitsSyncTravelInvoicingSettlements',
+ UPDATE_DIGITS_TRAVEL_INVOICING_SETTLEMENTS_ACCOUNT: 'UpdateDigitsTravelInvoicingSettlementsAccount',
+ UPDATE_DIGITS_TRAVEL_INVOICING_PAYABLE_ACCOUNT: 'UpdateDigitsTravelInvoicingPayableAccount',
UPDATE_ZOHO_BOOKS_SUBSIDIARY: 'UpdateZohoBooksSubsidiary',
UPDATE_ZOHO_BOOKS_FIELD_MAPPING: 'UpdateZohoBooksFieldMapping',
UPDATE_ZOHO_BOOKS_ENABLE_NEW_CATEGORIES: 'UpdateZohoBooksEnableNewCategories',
@@ -1416,6 +1433,23 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.UPDATE_CAMPFIRE_SYNC_TRAVEL_INVOICING_SETTLEMENTS]: Parameters.UpdateCampfireSyncTravelInvoicingSettlementsParams;
[WRITE_COMMANDS.UPDATE_CAMPFIRE_TRAVEL_INVOICING_SETTLEMENTS_ACCOUNT]: Parameters.UpdateCampfireTravelInvoicingSettlementsAccountParams;
[WRITE_COMMANDS.UPDATE_CAMPFIRE_TRAVEL_INVOICING_PAYABLE_ACCOUNT]: Parameters.UpdateCampfireTravelInvoicingPayableAccountParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_FIELD_MAPPING]: Parameters.UpdateDigitsFieldMappingParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_ENABLE_NEW_CATEGORIES]: Parameters.UpdateDigitsEnableNewCategoriesParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_EXPORTER]: Parameters.UpdateDigitsExporterParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_EXPORT_DATE]: Parameters.UpdateDigitsExportDateParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_DEFAULT_VENDOR]: Parameters.UpdateDigitsDefaultVendorParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_CREDIT_CARD_ACCOUNT]: Parameters.UpdateDigitsCreditCardAccountParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_EXPORT_TO_MULTIPLE_ACCOUNTS]: Parameters.UpdateDigitsExportToMultipleAccountsParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_CARD_PROGRAM_ACCOUNT]: Parameters.UpdateDigitsCardProgramAccountParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_AUTO_SYNC]: Parameters.UpdateDigitsAutoSyncParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_ACCOUNTING_METHOD]: Parameters.UpdateDigitsAccountingMethodParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateDigitsSyncReimbursedReportsParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_BILL_PAYMENT_ACCOUNT]: Parameters.UpdateDigitsBillPaymentAccountParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_SYNC_EXPENSIFY_CARD_SETTLEMENTS]: Parameters.UpdateDigitsSyncExpensifyCardSettlementsParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_SETTLEMENTS_ACCOUNT]: Parameters.UpdateDigitsSettlementsAccountParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_SYNC_TRAVEL_INVOICING_SETTLEMENTS]: Parameters.UpdateDigitsSyncTravelInvoicingSettlementsParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_TRAVEL_INVOICING_SETTLEMENTS_ACCOUNT]: Parameters.UpdateDigitsTravelInvoicingSettlementsAccountParams;
+ [WRITE_COMMANDS.UPDATE_DIGITS_TRAVEL_INVOICING_PAYABLE_ACCOUNT]: Parameters.UpdateDigitsTravelInvoicingPayableAccountParams;
[WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_SUBSIDIARY]: Parameters.UpdateZohoBooksSubsidiaryParams;
[WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_FIELD_MAPPING]: Parameters.UpdateZohoBooksFieldMappingParams;
[WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_ENABLE_NEW_CATEGORIES]: Parameters.UpdateZohoBooksEnableNewCategoriesParams;
@@ -1658,6 +1692,8 @@ const READ_COMMANDS = {
SYNC_POLICY_TO_RILLET: 'SyncPolicyToRillet',
SYNC_POLICY_TO_DUALENTRY: 'SyncPolicyToDualEntry',
SYNC_POLICY_TO_CAMPFIRE: 'SyncPolicyToCampfire',
+ SYNC_POLICY_TO_DIGITS: 'SyncPolicyToDigits',
+ CONNECT_POLICY_TO_DIGITS: 'ConnectPolicyToDigits',
SYNC_POLICY_TO_ZOHO_BOOKS: 'SyncPolicyToZohoBooks',
CONNECT_POLICY_TO_ZOHO_BOOKS: 'ConnectPolicyToZohoBooks',
SYNC_POLICY_TO_BUSINESS_CENTRAL: 'SyncPolicyToBusinessCentral',
@@ -1785,6 +1821,8 @@ type ReadCommandParameters = {
[READ_COMMANDS.SYNC_POLICY_TO_RILLET]: Parameters.SyncPolicyToRilletParams;
[READ_COMMANDS.SYNC_POLICY_TO_DUALENTRY]: Parameters.SyncPolicyToDualEntryParams;
[READ_COMMANDS.SYNC_POLICY_TO_CAMPFIRE]: Parameters.SyncPolicyToCampfireParams;
+ [READ_COMMANDS.SYNC_POLICY_TO_DIGITS]: Parameters.SyncPolicyToDigitsParams;
+ [READ_COMMANDS.CONNECT_POLICY_TO_DIGITS]: Parameters.ConnectPolicyToDigitsParams;
[READ_COMMANDS.SYNC_POLICY_TO_ZOHO_BOOKS]: Parameters.SyncPolicyToZohoBooksParams;
[READ_COMMANDS.CONNECT_POLICY_TO_ZOHO_BOOKS]: Parameters.ConnectPolicyToZohoBooksParams;
[READ_COMMANDS.SYNC_POLICY_TO_BUSINESS_CENTRAL]: Parameters.SyncPolicyToBusinessCentralParams;
diff --git a/src/libs/AccountingUtils.ts b/src/libs/AccountingUtils.ts
index bbf03d1bd4e5..3d9268d3c249 100644
--- a/src/libs/AccountingUtils.ts
+++ b/src/libs/AccountingUtils.ts
@@ -23,6 +23,7 @@ const ROUTE_NAME_MAPPING = {
[CONST.POLICY.CONNECTIONS.ROUTE.MERGE_ATS]: CONST.POLICY.CONNECTIONS.NAME.MERGE_ATS,
[CONST.POLICY.CONNECTIONS.ROUTE.DUALENTRY]: CONST.POLICY.CONNECTIONS.NAME.DUALENTRY,
[CONST.POLICY.CONNECTIONS.ROUTE.CAMPFIRE]: CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE,
+ [CONST.POLICY.CONNECTIONS.ROUTE.DIGITS]: CONST.POLICY.CONNECTIONS.NAME.DIGITS,
[CONST.POLICY.CONNECTIONS.ROUTE.ZOHO_BOOKS]: CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS,
[CONST.POLICY.CONNECTIONS.ROUTE.BUSINESS_CENTRAL]: CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL,
};
@@ -41,6 +42,7 @@ const NAME_ROUTE_MAPPING = {
[CONST.POLICY.CONNECTIONS.NAME.MERGE_ATS]: CONST.POLICY.CONNECTIONS.ROUTE.MERGE_ATS,
[CONST.POLICY.CONNECTIONS.NAME.DUALENTRY]: CONST.POLICY.CONNECTIONS.ROUTE.DUALENTRY,
[CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE]: CONST.POLICY.CONNECTIONS.ROUTE.CAMPFIRE,
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: CONST.POLICY.CONNECTIONS.ROUTE.DIGITS,
[CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: CONST.POLICY.CONNECTIONS.ROUTE.ZOHO_BOOKS,
[CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL]: CONST.POLICY.CONNECTIONS.ROUTE.BUSINESS_CENTRAL,
};
diff --git a/src/libs/CopyPolicySettingsUtils.ts b/src/libs/CopyPolicySettingsUtils.ts
index 697fd7f8b638..26c6e69b89b6 100644
--- a/src/libs/CopyPolicySettingsUtils.ts
+++ b/src/libs/CopyPolicySettingsUtils.ts
@@ -117,6 +117,12 @@ function getConnectionCompanyID(policy: Policy | undefined, connectionName: Conn
return readCredentialsCompanyID(connections[CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE]?.config);
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS:
return readCredentialsCompanyID(connections[CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]?.config);
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS: {
+ // Digits credentials carry a per-sign-in connection key rather than the company, so two workspaces signed
+ // in to the same Digits company are only recognized as such by the company the sync returned.
+ const companyID = connections[CONST.POLICY.CONNECTIONS.NAME.DIGITS]?.data?.company?.id;
+ return companyID || undefined;
+ }
default:
return undefined;
}
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index b1d299082bb8..887138b8f1b7 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -14147,6 +14147,7 @@ function getIntegrationIcon(
| 'RilletSquare'
| 'DualEntrySquare'
| 'CampfireSquare'
+ | 'DigitsSquare'
| 'ZohoBooksSquare'
| 'BusinessCentralSquare'
| 'GustoSquare'
@@ -14187,6 +14188,9 @@ function getIntegrationIcon(
if (connectionName === CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE) {
return expensifyIcons?.CampfireSquare;
}
+ if (connectionName === CONST.POLICY.CONNECTIONS.NAME.DIGITS) {
+ return expensifyIcons?.DigitsSquare;
+ }
if (connectionName === CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS) {
return expensifyIcons?.ZohoBooksSquare;
}
diff --git a/src/libs/actions/connections/Digits.ts b/src/libs/actions/connections/Digits.ts
new file mode 100644
index 000000000000..48629d33f82d
--- /dev/null
+++ b/src/libs/actions/connections/Digits.ts
@@ -0,0 +1,716 @@
+/**
+ * Onyx actions for the Digits accounting connection. Every setting saves optimistically with a pending field, and
+ * rolls back to its previous value with an error when the server rejects it.
+ */
+import {write} from '@libs/API';
+import type {
+ UpdateDigitsAccountingMethodParams,
+ UpdateDigitsAutoSyncParams,
+ UpdateDigitsBillPaymentAccountParams,
+ UpdateDigitsCardProgramAccountParams,
+ UpdateDigitsCreditCardAccountParams,
+ UpdateDigitsDefaultVendorParams,
+ UpdateDigitsEnableNewCategoriesParams,
+ UpdateDigitsExportDateParams,
+ UpdateDigitsExporterParams,
+ UpdateDigitsExportToMultipleAccountsParams,
+ UpdateDigitsFieldMappingParams,
+ UpdateDigitsSettlementsAccountParams,
+ UpdateDigitsSyncExpensifyCardSettlementsParams,
+ UpdateDigitsSyncReimbursedReportsParams,
+ UpdateDigitsSyncTravelInvoicingSettlementsParams,
+ UpdateDigitsTravelInvoicingPayableAccountParams,
+ UpdateDigitsTravelInvoicingSettlementsAccountParams,
+} from '@libs/API/parameters';
+import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
+import {getCommandURL} from '@libs/ApiUtils';
+import {getMicroSecondOnyxErrorWithTranslationKey} from '@libs/ErrorUtils';
+
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {DigitsAutoSync, DigitsCoding, DigitsConnectionsConfig, DigitsExport, DigitsSync} from '@src/types/onyx/Policy';
+
+import type {OnyxUpdate} from 'react-native-onyx';
+import type {ValueOf} from 'type-fest';
+
+import Onyx from 'react-native-onyx';
+
+function getDigitsSetupLink(policyID: string) {
+ // Digits authenticates with OAuth, so the connector opens this URL in the browser.
+ const params = new URLSearchParams({policyID});
+ const commandURL = getCommandURL({command: READ_COMMANDS.CONNECT_POLICY_TO_DIGITS, shouldSkipWebProxy: true});
+ return commandURL + params.toString();
+}
+
+function clearDigitsErrorField(policyID: string, fieldName: string) {
+ Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {errorFields: {[fieldName]: null}},
+ },
+ },
+ });
+}
+
+function prepareDigitsOnyxData(
+ policyID: string,
+ settingName: TSettingName,
+ settingValue: Partial,
+ oldSettingValue: Partial | null,
+) {
+ const optimisticData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ [settingName]: settingValue ?? null,
+ pendingFields: {
+ [settingName]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+ },
+ errorFields: {
+ [settingName]: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ const successData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ pendingFields: {
+ [settingName]: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ const failureData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ [settingName]: oldSettingValue ?? null,
+ pendingFields: {
+ [settingName]: null,
+ },
+ errorFields: {
+ [settingName]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ return {optimisticData, successData, failureData};
+}
+
+function prepareDigitsFieldMappingOnyxData(
+ policyID: string,
+ fieldID: keyof NonNullable,
+ mapping: ValueOf,
+ oldMapping: ValueOf | null,
+) {
+ const fieldOfflineFeedbackKey = `${CONST.DIGITS_CONFIG.FIELD_MAPPING_PREFIX}${fieldID}`;
+
+ const optimisticData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ coding: {
+ fieldMappings: {
+ [fieldID]: mapping,
+ },
+ },
+ pendingFields: {
+ [fieldOfflineFeedbackKey]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+ },
+ errorFields: {
+ [fieldOfflineFeedbackKey]: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ const successData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ pendingFields: {
+ [fieldOfflineFeedbackKey]: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ const failureData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ coding: {
+ fieldMappings: {
+ [fieldID]: oldMapping ?? null,
+ },
+ },
+ pendingFields: {
+ [fieldOfflineFeedbackKey]: null,
+ },
+ errorFields: {
+ [fieldOfflineFeedbackKey]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ return {optimisticData, successData, failureData};
+}
+
+function prepareDigitsExportOnyxData(
+ policyID: string,
+ settingName: TSettingName,
+ settingValue: Partial,
+ oldSettingValue: Partial | null,
+) {
+ const optimisticData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ export: {
+ [settingName]: settingValue ?? null,
+ },
+ pendingFields: {
+ [settingName]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+ },
+ errorFields: {
+ [settingName]: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ const successData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ pendingFields: {
+ [settingName]: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ const failureData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ export: {
+ [settingName]: oldSettingValue ?? null,
+ },
+ pendingFields: {
+ [settingName]: null,
+ },
+ errorFields: {
+ [settingName]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ return {optimisticData, successData, failureData};
+}
+
+function prepareDigitsAutoSyncOnyxData(policyID: string, enabled: DigitsAutoSync['enabled'], oldEnabled?: DigitsAutoSync['enabled'] | null) {
+ const optimisticData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ autoSync: {
+ enabled,
+ },
+ pendingFields: {
+ [CONST.DIGITS_CONFIG.AUTO_SYNC]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+ },
+ errorFields: {
+ [CONST.DIGITS_CONFIG.AUTO_SYNC]: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ const successData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ pendingFields: {
+ [CONST.DIGITS_CONFIG.AUTO_SYNC]: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ const failureData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ autoSync: {
+ enabled: oldEnabled ?? null,
+ },
+ pendingFields: {
+ [CONST.DIGITS_CONFIG.AUTO_SYNC]: null,
+ },
+ errorFields: {
+ [CONST.DIGITS_CONFIG.AUTO_SYNC]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ return {optimisticData, successData, failureData};
+}
+
+function prepareDigitsSyncOnyxData(
+ policyID: string,
+ settingName: TSettingName,
+ settingValue: Partial,
+ oldSettingValue: Partial | null,
+) {
+ const optimisticData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ sync: {
+ [settingName]: settingValue ?? null,
+ },
+ pendingFields: {
+ [settingName]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+ },
+ errorFields: {
+ [settingName]: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ const successData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ pendingFields: {
+ [settingName]: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ const failureData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ sync: {
+ [settingName]: oldSettingValue ?? null,
+ },
+ pendingFields: {
+ [settingName]: null,
+ },
+ errorFields: {
+ [settingName]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ return {optimisticData, successData, failureData};
+}
+
+function prepareDigitsCardProgramAccountOnyxData(
+ policyID: string,
+ feedKey: keyof DigitsExport['cardProgramAccounts'],
+ accountID: ValueOf,
+ oldAccountID?: ValueOf | null,
+) {
+ const cardProgramAccountOfflineFeedbackKey = `${CONST.DIGITS_CONFIG.CARD_PROGRAM_ACCOUNT_PREFIX}${feedKey}`;
+
+ const optimisticData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ export: {
+ cardProgramAccounts: {
+ // An empty accountID string implies clearing the custom account
+ [feedKey]: accountID || null,
+ },
+ },
+ pendingFields: {
+ [cardProgramAccountOfflineFeedbackKey]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+ },
+ errorFields: {
+ [cardProgramAccountOfflineFeedbackKey]: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ const successData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ pendingFields: {
+ [cardProgramAccountOfflineFeedbackKey]: null,
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ const failureData: Array> = [
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+ value: {
+ connections: {
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: {
+ config: {
+ export: {
+ cardProgramAccounts: {
+ [feedKey]: oldAccountID ?? null,
+ },
+ },
+ pendingFields: {
+ [cardProgramAccountOfflineFeedbackKey]: null,
+ },
+ errorFields: {
+ [cardProgramAccountOfflineFeedbackKey]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+ },
+ },
+ },
+ },
+ },
+ },
+ ];
+
+ return {optimisticData, successData, failureData};
+}
+
+function updateDigitsEnableNewCategories(policyID: string, enabled: DigitsConnectionsConfig['enableNewCategories'], oldEnabled?: DigitsConnectionsConfig['enableNewCategories']) {
+ const onyxData = prepareDigitsOnyxData(policyID, CONST.DIGITS_CONFIG.ENABLE_NEW_CATEGORIES, enabled, oldEnabled ?? null);
+ const parameters: UpdateDigitsEnableNewCategoriesParams = {
+ policyID,
+ enabled,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_ENABLE_NEW_CATEGORIES, parameters, onyxData);
+}
+
+function updateDigitsFieldMapping(
+ policyID: string,
+ fieldID: keyof NonNullable,
+ mapping: ValueOf,
+ oldMapping?: ValueOf,
+) {
+ const onyxData = prepareDigitsFieldMappingOnyxData(policyID, fieldID, mapping, oldMapping ?? null);
+ const parameters: UpdateDigitsFieldMappingParams = {
+ policyID,
+ fieldID,
+ mapping,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_FIELD_MAPPING, parameters, onyxData);
+}
+
+function updateDigitsExporter(policyID: string, email: DigitsExport['exporter'], oldEmail?: DigitsExport['exporter']) {
+ const onyxData = prepareDigitsExportOnyxData(policyID, CONST.DIGITS_CONFIG.EXPORTER, email, oldEmail ?? null);
+ const parameters: UpdateDigitsExporterParams = {
+ policyID,
+ email,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_EXPORTER, parameters, onyxData);
+}
+
+function updateDigitsExportDate(policyID: string, value: DigitsExport['exportDate'], oldValue?: DigitsExport['exportDate']) {
+ const onyxData = prepareDigitsExportOnyxData(policyID, CONST.DIGITS_CONFIG.EXPORT_DATE, value, oldValue ?? null);
+ const parameters: UpdateDigitsExportDateParams = {
+ policyID,
+ value,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_EXPORT_DATE, parameters, onyxData);
+}
+
+function updateDigitsDefaultVendor(policyID: string, vendorID: DigitsExport['defaultVendorID'], oldVendorID?: DigitsExport['defaultVendorID']) {
+ const onyxData = prepareDigitsExportOnyxData(policyID, CONST.DIGITS_CONFIG.DEFAULT_VENDORID, vendorID, oldVendorID ?? null);
+ const parameters: UpdateDigitsDefaultVendorParams = {
+ policyID,
+ vendorID,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_DEFAULT_VENDOR, parameters, onyxData);
+}
+
+function updateDigitsCreditCardAccount(policyID: string, creditCardAccountID: DigitsExport['creditCardAccountID'], oldCreditCardAccountID?: DigitsExport['creditCardAccountID']) {
+ const onyxData = prepareDigitsExportOnyxData(policyID, CONST.DIGITS_CONFIG.CREDIT_CARD_ACCOUNT_ID, creditCardAccountID, oldCreditCardAccountID ?? null);
+ const parameters: UpdateDigitsCreditCardAccountParams = {
+ policyID,
+ creditCardAccountID,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_CREDIT_CARD_ACCOUNT, parameters, onyxData);
+}
+
+function updateDigitsAutoSync(policyID: string, enabled: DigitsAutoSync['enabled'], oldEnabled?: DigitsAutoSync['enabled']) {
+ const onyxData = prepareDigitsAutoSyncOnyxData(policyID, enabled, oldEnabled ?? null);
+ const parameters: UpdateDigitsAutoSyncParams = {
+ policyID,
+ enabled,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_AUTO_SYNC, parameters, onyxData);
+}
+
+function updateDigitsAccountingMethod(policyID: string, accountingMethod: DigitsExport['accountingMethod'], oldAccountingMethod?: DigitsExport['accountingMethod']) {
+ const onyxData = prepareDigitsExportOnyxData(policyID, CONST.DIGITS_CONFIG.ACCOUNTING_METHOD, accountingMethod, oldAccountingMethod ?? null);
+ const parameters: UpdateDigitsAccountingMethodParams = {
+ policyID,
+ accountingMethod,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_ACCOUNTING_METHOD, parameters, onyxData);
+}
+
+function updateDigitsSyncReimbursedReports(policyID: string, enabled: DigitsSync['syncReimbursedReports'], oldEnabled?: DigitsSync['syncReimbursedReports']) {
+ const onyxData = prepareDigitsSyncOnyxData(policyID, CONST.DIGITS_CONFIG.SYNC_REIMBURSED_REPORTS, enabled, oldEnabled ?? null);
+ const parameters: UpdateDigitsSyncReimbursedReportsParams = {
+ policyID,
+ enabled,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_SYNC_REIMBURSED_REPORTS, parameters, onyxData);
+}
+
+function updateDigitsBillPaymentAccount(policyID: string, billPaymentAccountID: DigitsSync['billPaymentAccountID'], oldBillPaymentAccountID?: DigitsSync['billPaymentAccountID']) {
+ const onyxData = prepareDigitsSyncOnyxData(policyID, CONST.DIGITS_CONFIG.BILL_PAYMENT_ACCOUNT_ID, billPaymentAccountID, oldBillPaymentAccountID ?? null);
+ const parameters: UpdateDigitsBillPaymentAccountParams = {
+ policyID,
+ billPaymentAccountID,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_BILL_PAYMENT_ACCOUNT, parameters, onyxData);
+}
+
+function updateDigitsSyncExpensifyCardSettlements(policyID: string, enabled: DigitsSync['syncExpensifyCardSettlements'], oldEnabled?: DigitsSync['syncExpensifyCardSettlements']) {
+ const onyxData = prepareDigitsSyncOnyxData(policyID, CONST.DIGITS_CONFIG.SYNC_EXPENSIFY_CARD_SETTLEMENTS, enabled, oldEnabled ?? null);
+ const parameters: UpdateDigitsSyncExpensifyCardSettlementsParams = {
+ policyID,
+ enabled,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_SYNC_EXPENSIFY_CARD_SETTLEMENTS, parameters, onyxData);
+}
+
+function updateDigitsSettlementsAccount(
+ policyID: string,
+ settlementsBankAccountID: DigitsSync['settlementsBankAccountID'],
+ oldSettlementsBankAccountID?: DigitsSync['settlementsBankAccountID'],
+) {
+ const onyxData = prepareDigitsSyncOnyxData(policyID, CONST.DIGITS_CONFIG.SETTLEMENTS_BANK_ACCOUNT_ID, settlementsBankAccountID, oldSettlementsBankAccountID ?? null);
+ const parameters: UpdateDigitsSettlementsAccountParams = {
+ policyID,
+ settlementsBankAccountID,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_SETTLEMENTS_ACCOUNT, parameters, onyxData);
+}
+
+function updateDigitsSyncTravelInvoicingSettlements(policyID: string, enabled: DigitsSync['syncTravelInvoicingSettlements'], oldEnabled?: DigitsSync['syncTravelInvoicingSettlements']) {
+ const onyxData = prepareDigitsSyncOnyxData(policyID, CONST.DIGITS_CONFIG.SYNC_TRAVEL_BILLING_SETTLEMENTS, enabled, oldEnabled ?? null);
+ const parameters: UpdateDigitsSyncTravelInvoicingSettlementsParams = {
+ policyID,
+ enabled,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_SYNC_TRAVEL_INVOICING_SETTLEMENTS, parameters, onyxData);
+}
+
+function updateDigitsTravelInvoicingSettlementsAccount(
+ policyID: string,
+ travelInvoicingSettlementsBankAccountID: DigitsSync['travelInvoicingSettlementsBankAccountID'],
+ oldTravelInvoicingSettlementsBankAccountID?: DigitsSync['travelInvoicingSettlementsBankAccountID'],
+) {
+ const onyxData = prepareDigitsSyncOnyxData(
+ policyID,
+ CONST.DIGITS_CONFIG.TRAVEL_BILLING_SETTLEMENTS_BANK_ACCOUNT_ID,
+ travelInvoicingSettlementsBankAccountID,
+ oldTravelInvoicingSettlementsBankAccountID ?? null,
+ );
+ const parameters: UpdateDigitsTravelInvoicingSettlementsAccountParams = {
+ policyID,
+ travelInvoicingSettlementsBankAccountID,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_TRAVEL_INVOICING_SETTLEMENTS_ACCOUNT, parameters, onyxData);
+}
+
+function updateDigitsTravelInvoicingPayableAccount(
+ policyID: string,
+ travelInvoicingPayableAccountID: DigitsExport['travelInvoicingPayableAccountID'],
+ oldTravelInvoicingPayableAccountID?: DigitsExport['travelInvoicingPayableAccountID'],
+) {
+ const onyxData = prepareDigitsExportOnyxData(
+ policyID,
+ CONST.DIGITS_CONFIG.TRAVEL_BILLING_PAYABLE_ACCOUNT_ID,
+ travelInvoicingPayableAccountID,
+ oldTravelInvoicingPayableAccountID ?? null,
+ );
+ const parameters: UpdateDigitsTravelInvoicingPayableAccountParams = {
+ policyID,
+ travelInvoicingPayableAccountID,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_TRAVEL_INVOICING_PAYABLE_ACCOUNT, parameters, onyxData);
+}
+
+function updateDigitsExportToMultipleAccounts(policyID: string, enabled: DigitsExport['exportToMultipleAccounts'], oldEnabled?: DigitsExport['exportToMultipleAccounts']) {
+ const onyxData = prepareDigitsExportOnyxData(policyID, CONST.DIGITS_CONFIG.EXPORT_TO_MULTIPLE_ACCOUNTS, enabled, oldEnabled ?? null);
+ const parameters: UpdateDigitsExportToMultipleAccountsParams = {
+ policyID,
+ enabled,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_EXPORT_TO_MULTIPLE_ACCOUNTS, parameters, onyxData);
+}
+
+function updateDigitsCardProgramAccount(
+ policyID: string,
+ feedKey: keyof DigitsExport['cardProgramAccounts'],
+ cardProgramAccountID: ValueOf,
+ oldCardProgramAccountID?: ValueOf,
+) {
+ const onyxData = prepareDigitsCardProgramAccountOnyxData(policyID, feedKey, cardProgramAccountID, oldCardProgramAccountID ?? null);
+ const parameters: UpdateDigitsCardProgramAccountParams = {
+ policyID,
+ feedKey,
+ cardProgramAccountID,
+ };
+ write(WRITE_COMMANDS.UPDATE_DIGITS_CARD_PROGRAM_ACCOUNT, parameters, onyxData);
+}
+
+export {
+ getDigitsSetupLink,
+ clearDigitsErrorField,
+ updateDigitsEnableNewCategories,
+ updateDigitsFieldMapping,
+ updateDigitsExporter,
+ updateDigitsExportDate,
+ updateDigitsDefaultVendor,
+ updateDigitsCreditCardAccount,
+ updateDigitsAutoSync,
+ updateDigitsAccountingMethod,
+ updateDigitsSyncReimbursedReports,
+ updateDigitsBillPaymentAccount,
+ updateDigitsSyncExpensifyCardSettlements,
+ updateDigitsSettlementsAccount,
+ updateDigitsSyncTravelInvoicingSettlements,
+ updateDigitsTravelInvoicingSettlementsAccount,
+ updateDigitsTravelInvoicingPayableAccount,
+ updateDigitsExportToMultipleAccounts,
+ updateDigitsCardProgramAccount,
+};
diff --git a/src/libs/actions/connections/index.ts b/src/libs/actions/connections/index.ts
index 850f9ed50cf7..8afc6927d12c 100644
--- a/src/libs/actions/connections/index.ts
+++ b/src/libs/actions/connections/index.ts
@@ -163,6 +163,9 @@ function getSyncConnectionParameters(connectionName: PolicyConnectionName) {
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE: {
return {readCommand: READ_COMMANDS.SYNC_POLICY_TO_CAMPFIRE, stageInProgress: CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.CAMPFIRE_SYNC_CONNECTION};
}
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS: {
+ return {readCommand: READ_COMMANDS.SYNC_POLICY_TO_DIGITS, stageInProgress: CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.DIGITS_SYNC_CONNECTION};
+ }
case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS: {
return {readCommand: READ_COMMANDS.SYNC_POLICY_TO_ZOHO_BOOKS, stageInProgress: CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.ZOHO_BOOKS_SYNC_CONNECTION};
}
@@ -390,6 +393,9 @@ function copyExistingPolicyConnection(connectedPolicyID: string, targetPolicyID:
case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE:
stageInProgress = CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.CAMPFIRE_SYNC_CONNECTION;
break;
+ case CONST.POLICY.CONNECTIONS.NAME.DIGITS:
+ stageInProgress = CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.DIGITS_SYNC_CONNECTION;
+ break;
default:
stageInProgress = null;
}
diff --git a/src/pages/workspace/accounting/useConnectedAccountingIntegration.tsx b/src/pages/workspace/accounting/useConnectedAccountingIntegration.tsx
index 0e0b442f15b9..e80dfa8525b3 100644
--- a/src/pages/workspace/accounting/useConnectedAccountingIntegration.tsx
+++ b/src/pages/workspace/accounting/useConnectedAccountingIntegration.tsx
@@ -135,6 +135,7 @@ function useConnectedAccountingIntegration(policy: OnyxEntry, {menuItemW
const connectionSyncStage = connectionSyncProgress?.stageInProgress;
const canUseBusinessCentralIntegration = isBetaEnabled(CONST.BETAS.BUSINESS_CENTRAL) || !!policy?.connections?.businessCentral;
const canUseZohoBooksIntegration = isBetaEnabled(CONST.BETAS.ZOHO_BOOKS) || !!policy?.connections?.zohoBooks;
+ const canUseDigitsIntegration = isBetaEnabled(CONST.BETAS.DIGITS) || !!policy?.connections?.digits;
const accountingIntegrations = CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES.filter((name) => {
if (name === CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL) {
return canUseBusinessCentralIntegration;
@@ -142,6 +143,9 @@ function useConnectedAccountingIntegration(policy: OnyxEntry, {menuItemW
if (name === CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS) {
return canUseZohoBooksIntegration;
}
+ if (name === CONST.POLICY.CONNECTIONS.NAME.DIGITS) {
+ return canUseDigitsIntegration;
+ }
return true;
});
const syncingAccountingIntegration = accountingIntegrations.find((integration) => integration === connectionSyncProgress?.connectionName);
diff --git a/src/pages/workspace/connections/useAccountingConnectionListings.ts b/src/pages/workspace/connections/useAccountingConnectionListings.ts
index f3dd0639b920..93eddd3a178b 100644
--- a/src/pages/workspace/connections/useAccountingConnectionListings.ts
+++ b/src/pages/workspace/connections/useAccountingConnectionListings.ts
@@ -63,6 +63,7 @@ function useAccountingConnectionListings(policy: OnyxEntry): ConnectionL
const canUseBusinessCentralIntegration = isBetaEnabled(CONST.BETAS.BUSINESS_CENTRAL) || !!policy?.connections?.businessCentral;
const canUseZohoBooksIntegration = isBetaEnabled(CONST.BETAS.ZOHO_BOOKS) || !!policy?.connections?.zohoBooks;
+ const canUseDigitsIntegration = isBetaEnabled(CONST.BETAS.DIGITS) || !!policy?.connections?.digits;
const accountingIntegrations = CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES.filter((name) => {
if (name === CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL) {
return canUseBusinessCentralIntegration;
@@ -70,6 +71,9 @@ function useAccountingConnectionListings(policy: OnyxEntry): ConnectionL
if (name === CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS) {
return canUseZohoBooksIntegration;
}
+ if (name === CONST.POLICY.CONNECTIONS.NAME.DIGITS) {
+ return canUseDigitsIntegration;
+ }
return true;
});
diff --git a/src/selectors/Policy.ts b/src/selectors/Policy.ts
index 0370a3da0d49..7bb8ea6f93d1 100644
--- a/src/selectors/Policy.ts
+++ b/src/selectors/Policy.ts
@@ -44,7 +44,8 @@ type ReusablePolicyConnectionName =
| typeof CONST.POLICY.CONNECTIONS.NAME.CERTINIA
| typeof CONST.POLICY.CONNECTIONS.NAME.RILLET
| typeof CONST.POLICY.CONNECTIONS.NAME.DUALENTRY
- | typeof CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE;
+ | typeof CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE
+ | typeof CONST.POLICY.CONNECTIONS.NAME.DIGITS;
const ownerPoliciesSelector = (policies: OnyxCollection, currentUserAccountID: number) => getOwnedPaidPolicies(policies, currentUserAccountID);
@@ -477,6 +478,9 @@ const adminPoliciesConnectedToDualEntrySelector = (policies: OnyxCollection) =>
Object.values(policies ?? {}).filter((policy): policy is Policy => isAdminPolicyConnectedTo(policy, CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE));
+const adminPoliciesConnectedToDigitsSelector = (policies: OnyxCollection) =>
+ Object.values(policies ?? {}).filter((policy): policy is Policy => isAdminPolicyConnectedTo(policy, CONST.POLICY.CONNECTIONS.NAME.DIGITS));
+
const reusableConnectionAdminSelectors: Record) => Policy[]> = {
[CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: adminPoliciesConnectedToNetSuiteSelector,
[CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT]: adminPoliciesConnectedToSageIntacctSelector,
@@ -485,6 +489,7 @@ const reusableConnectionAdminSelectors: Record;
+/**
+ * The Digits company the connection is authorized for. A Digits sign-in covers exactly one company.
+ */
+type DigitsCompany = {
+ /** Unique identifier of the company. */
+ id: string;
+
+ /** Name of the company. */
+ name: string;
+
+ /** Currency the company operates in. Digits only supports USD companies. */
+ currency: string;
+};
+
+/**
+ * Chart of accounts entry retrieved from Digits.
+ */
+type DigitsAccount = {
+ /** Unique identifier of the account. */
+ id: string;
+
+ /** Name of the account. */
+ name: string;
+
+ /** Account number shown in Digits, imported as the GL code. */
+ displayNumber?: string;
+
+ /** Unique identifier of the parent account. */
+ parentID?: string;
+
+ /** Type of the account, as the Digits API names it. */
+ type: string;
+
+ /** Subtype of the account. Account pickers filter on the values in `CONST.DIGITS_ACCOUNT_SUBTYPE`. */
+ subtype: string;
+
+ /** Whether the account is active. */
+ isActive: boolean;
+};
+
+/**
+ * Vendor retrieved from Digits.
+ */
+type DigitsVendor = {
+ /** The vendor's Digits external ID, serialized as a JSON string of its issuer and ID. */
+ id: string;
+
+ /** Name of the vendor. */
+ name: string;
+
+ /** Email address associated with the vendor. */
+ email?: string;
+
+ /** Roles Digits derived from the vendor's ledger activity. A vendor without activity has none yet. */
+ roles: string[];
+};
+
+/**
+ * Connection data retrieved from Digits.
+ */
+type DigitsConnectionData = {
+ /** The company the connection is authorized for. */
+ company?: DigitsCompany;
+
+ /** Accounts available in Digits. */
+ accounts?: DigitsAccount[];
+
+ /** Vendors available in Digits. */
+ vendors?: DigitsVendor[];
+};
+
+/**
+ * Digits dimensions that can be mapped to Expensify tags.
+ */
+type DigitsField = ValueOf;
+
+/**
+ * Coding configuration used when importing data from Digits.
+ */
+type DigitsCoding = {
+ /** Mapping of Digits dimensions to their configured mapping behavior. */
+ fieldMappings?: Partial>>;
+};
+
+/** Offline feedback key for field mapping */
+type DigitsCodingFieldMappingsOfflineFeedbackKey = `${typeof CONST.DIGITS_CONFIG.FIELD_MAPPING_PREFIX}${DigitsField}`;
+
+/**
+ * Available dates that can be used as the export date.
+ */
+type DigitsExportDate = ValueOf;
+
+/**
+ * Export strategy for reimbursable expenses.
+ */
+type DigitsExportReimbursable = ValueOf;
+
+/**
+ * Export strategy for company card expenses.
+ */
+type DigitsExportNonReimbursable = ValueOf;
+
+/**
+ * Export configuration for sending accounting data to Digits.
+ */
+type DigitsExport = {
+ /** Identifier of the export implementation to use. */
+ exporter: string;
+
+ /** Date source used when generating exported transactions. */
+ exportDate: DigitsExportDate;
+
+ /** Export behavior for reimbursable expenses. */
+ reimbursable: DigitsExportReimbursable;
+
+ /** Export behavior for company card expenses. */
+ nonReimbursable: DigitsExportNonReimbursable;
+
+ /** Account used when exporting company card expenses. */
+ creditCardAccountID: string;
+
+ /**
+ * Whether card transactions should be exported to multiple
+ * accounts based on card program mappings.
+ */
+ exportToMultipleAccounts: boolean;
+
+ /**
+ * Mapping of card program identifiers to account IDs.
+ */
+ cardProgramAccounts: Record;
+
+ /** Default vendor used when exporting transactions. */
+ defaultVendorID: string;
+
+ /** Payable account used when exporting travel billings. */
+ travelInvoicingPayableAccountID: string;
+
+ /** Accounting method used during export. */
+ accountingMethod: ValueOf;
+};
+
+/** Offline feedback key for card program account */
+type DigitsExportCardProgramAccountsOfflineFeedbackKey = `${typeof CONST.DIGITS_CONFIG.CARD_PROGRAM_ACCOUNT_PREFIX}${string}`;
+
+/**
+ * Offline feedback keys for `DigitsExport`
+ */
+type DigitsExportOfflineFeedbackKeys = keyof Omit | DigitsExportCardProgramAccountsOfflineFeedbackKey;
+
+/**
+ * Automatic synchronization settings for Digits.
+ */
+type DigitsAutoSync = {
+ /** Whether automatic synchronization is enabled. */
+ enabled: boolean;
+};
+
+/**
+ * Synchronization settings for importing and updating data in Digits.
+ */
+type DigitsSync = {
+ /** Whether reimbursed expense reports should be synchronized. */
+ syncReimbursedReports: boolean;
+
+ /** Account used for bill payment transactions. */
+ billPaymentAccountID: string;
+
+ /** Whether Expensify Card settlement transactions should be synchronized. */
+ syncExpensifyCardSettlements: boolean;
+
+ /** Bank account used for Expensify Card settlements. */
+ settlementsBankAccountID: string;
+
+ /** Whether travel billing settlement transactions should be synchronized. */
+ syncTravelInvoicingSettlements: boolean;
+
+ /** Bank account used for travel billing settlements. */
+ travelInvoicingSettlementsBankAccountID: string;
+};
+
+/**
+ * Connection config for Digits. Credentials, the auto-sync job and settlement progress stay on the server.
+ */
+type DigitsConnectionsConfig = OnyxCommon.OnyxValueWithOfflineFeedback<
+ {
+ /** Whether the connection has been configured */
+ isConfigured: boolean;
+
+ /** Whether to enable a new Expense Category into Expensify */
+ enableNewCategories: boolean;
+
+ /** Coding settings */
+ coding?: DigitsCoding;
+
+ /** Export settings */
+ export?: DigitsExport;
+
+ /** Auto-sync settings */
+ autoSync?: DigitsAutoSync;
+
+ /** Sync settings */
+ sync?: DigitsSync;
+
+ /** Collection of errors coming from BE */
+ errors?: OnyxCommon.Errors;
+
+ /** Collection of form field errors */
+ errorFields?: OnyxCommon.ErrorFields;
+ },
+ DigitsCodingFieldMappingsOfflineFeedbackKey | DigitsExportOfflineFeedbackKeys | keyof DigitsAutoSync | keyof DigitsSync
+>;
+
/**
* An organization configured in Zoho Books.
*/
@@ -3400,6 +3613,9 @@ type Connections = {
/** Campfire integration connection */
[CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE]: Connection;
+ /** Digits integration connection */
+ [CONST.POLICY.CONNECTIONS.NAME.DIGITS]: Connection;
+
/** Zoho Books integration connection */
[CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: Connection;
@@ -4299,6 +4515,9 @@ export type {
CampfireExport,
CampfireAutoSync,
CampfireSync,
+ DigitsExportDate,
+ DigitsVendor,
+ DigitsAccount,
ZohoBooksExportDate,
ZohoBooksVendor,
ZohoBooksAccount,
@@ -4318,3 +4537,10 @@ export type {
* @public
*/
export type {ZohoBooksAutoSync, ZohoBooksCoding, ZohoBooksConnectionsConfig, ZohoBooksExport, ZohoBooksSync};
+
+/**
+ * The Digits action module is the only importer of these config types, and Knip ignores that module until workspace screens import it.
+ *
+ * @public
+ */
+export type {DigitsAutoSync, DigitsCoding, DigitsConnectionsConfig, DigitsExport, DigitsSync};
diff --git a/tests/unit/CopyPolicySettingsUtilsTest.ts b/tests/unit/CopyPolicySettingsUtilsTest.ts
index 9f60274cfadc..322651a25ffb 100644
--- a/tests/unit/CopyPolicySettingsUtilsTest.ts
+++ b/tests/unit/CopyPolicySettingsUtilsTest.ts
@@ -73,6 +73,31 @@ describe('CopyPolicySettingsUtils', () => {
expect(getConnectionCompanyID(policy, CONST.POLICY.CONNECTIONS.NAME.QBD)).toBe('QBD-1');
});
+ it('returns the synced company ID for Digits', () => {
+ // Given a Digits connection whose credentials hold a per-sign-in key, while the sync stored the company it reached
+ const policy = makePolicyWithConnection(CONST.POLICY.CONNECTIONS.NAME.DIGITS, {
+ config: {credentials: {companyID: 'sign-in-key'}},
+ data: {company: {id: 'DIGITS-1', name: 'Merlin Technologies Inc.', currency: 'USD'}},
+ });
+
+ // When the company ID is read for the copy and bulk export checks
+ const companyID = getConnectionCompanyID(policy, CONST.POLICY.CONNECTIONS.NAME.DIGITS);
+
+ // Then it is the synced company, so two sign-ins to one Digits company count as the same company
+ expect(companyID).toBe('DIGITS-1');
+ });
+
+ it('returns undefined for Digits before the company has synced', () => {
+ // Given a Digits connection that authorized but has not completed its first sync
+ const policy = makePolicyWithConnection(CONST.POLICY.CONNECTIONS.NAME.DIGITS, {config: {isConfigured: false}});
+
+ // When the company ID is read
+ const companyID = getConnectionCompanyID(policy, CONST.POLICY.CONNECTIONS.NAME.DIGITS);
+
+ // Then there is no company to match on yet
+ expect(companyID).toBeUndefined();
+ });
+
it('returns undefined when the connection field is missing', () => {
const policy = makePolicyWithConnection(CONST.POLICY.CONNECTIONS.NAME.QBO, {config: {}});
expect(getConnectionCompanyID(policy, CONST.POLICY.CONNECTIONS.NAME.QBO)).toBeUndefined();