diff --git a/assets/images/integrationicons/zoho-books-icon-square.svg b/assets/images/integrationicons/zoho-books-icon-square.svg new file mode 100644 index 000000000000..03699e1bbaf4 --- /dev/null +++ b/assets/images/integrationicons/zoho-books-icon-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/cspell.json b/cspell.json index cd4050470f8c..0919a131be9b 100644 --- a/cspell.json +++ b/cspell.json @@ -469,6 +469,7 @@ "Yema", "Zenefit", "Zenefits", + "Zoho", "Zipaligning", "Zürcher", "aaroon", diff --git a/knip.json b/knip.json index 72c09c1b8500..32c6af6ddd9d 100644 --- a/knip.json +++ b/knip.json @@ -43,6 +43,7 @@ "tests/perf-test/**", "web/snippets/gib.js", "src/libs/actions/connections/FinancialForce.ts", + "src/libs/actions/connections/ZohoBooks.ts", "src/setup/telemetry/noopExpoUpdates.ts" ], "eslint": { diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 41376e1a296a..3752deec46e3 100644 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -4023,6 +4023,63 @@ const CONST = { EMPLOYEE: 'employee', }, + ZOHO_BOOKS_CONFIG: { + ORGANIZATION_ID: 'organizationID', + ENABLE_NEW_CATEGORIES: 'enableNewCategories', + SYNC_TAX_RATES: 'syncTaxRates', + 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_', + }, + + ZOHO_BOOKS_MAPPING_VALUE: { + NONE: 'NONE', + TAG: 'TAG', + }, + + ZOHO_BOOKS_EXPORT_REIMBURSABLE: { + VENDOR_BILL: 'VENDOR_BILL', + }, + + ZOHO_BOOKS_EXPORT_NON_REIMBURSABLE: { + EXPENSE: 'EXPENSE', + }, + + ZOHO_BOOKS_EXPORT_DATE: { + LAST_EXPENSE: 'LAST_EXPENSE', + REPORT_EXPORTED: 'REPORT_EXPORTED', + REPORT_SUBMITTED: 'REPORT_SUBMITTED', + }, + + // Zoho Books accounts have one account_type. These are the lowercase values the API returns. + ZOHO_BOOKS_ACCOUNT_TYPE: { + BANK: 'bank', + CREDIT_CARD: 'credit_card', + EXPENSE: 'expense', + COST_OF_GOODS_SOLD: 'cost_of_goods_sold', + OTHER_EXPENSE: 'other_expense', + }, + + ZOHO_BOOKS_VENDOR_TYPE: { + VENDOR: 'vendor', + CUSTOMER: 'customer', + }, + BUSINESS_CENTRAL_CONFIG: { COMPANY_ID: 'companyID', ENABLE_NEW_CATEGORIES: 'enableNewCategories', @@ -4856,6 +4913,7 @@ const CONST = { RILLET: 'rillet', DUALENTRY: 'dualEntry', CAMPFIRE: 'campfire', + ZOHO_BOOKS: 'zohoBooks', BUSINESS_CENTRAL: 'businessCentral', GUSTO: 'gusto', ZENEFITS: 'zenefits', @@ -4876,6 +4934,7 @@ const CONST = { RILLET: 'rillet', DUALENTRY: 'dualentry', CAMPFIRE: 'campfire', + ZOHO_BOOKS: 'zoho-books', BUSINESS_CENTRAL: 'business-central', GUSTO: 'gusto', ZENEFITS: 'zenefits', @@ -4892,6 +4951,7 @@ const CONST = { rillet: 'Rillet', dualEntry: 'DualEntry', campfire: 'Campfire', + zohoBooks: 'Zoho Books', businessCentral: 'Dynamics 365 Business Central', gusto: 'Gusto', billCom: 'Bill.com', @@ -5055,6 +5115,7 @@ const CONST = { CAMPFIRE_SYNC_PAYMENTS: 'campfireSyncPayments', CAMPFIRE_SYNC_CARD_SETTLEMENTS: 'campfireSyncCardSettlements', CAMPFIRE_SYNC_TRAVEL_SETTLEMENTS: 'campfireSyncTravelSettlements', + ZOHO_BOOKS_SYNC_CONNECTION: 'zohoBooksSyncConnection', BUSINESS_CENTRAL_SYNC_TITLE: 'businessCentralSyncTitle', BUSINESS_CENTRAL_SYNC_CONNECTION: 'businessCentralSyncConnection', BUSINESS_CENTRAL_SYNC_IMPORT_DATA: 'businessCentralSyncImportData', diff --git a/src/components/Icon/chunks/expensify-icons.chunk.ts b/src/components/Icon/chunks/expensify-icons.chunk.ts index dbb862ca5000..7b2c4282e4cd 100644 --- a/src/components/Icon/chunks/expensify-icons.chunk.ts +++ b/src/components/Icon/chunks/expensify-icons.chunk.ts @@ -165,6 +165,7 @@ import Uber from '@assets/images/integrationicons/uber.svg'; import XeroCircle from '@assets/images/integrationicons/xero-icon-circle.svg'; import XeroSquare from '@assets/images/integrationicons/xero-icon-square.svg'; import ZenefitsSquare from '@assets/images/integrationicons/zenefits-icon-square.svg'; +import ZohoBooksSquare from '@assets/images/integrationicons/zoho-books-icon-square.svg'; import InvoiceBookmark from '@assets/images/invoice-bookmark.svg'; import InvoiceGeneric from '@assets/images/invoice-generic.svg'; import Invoice from '@assets/images/invoice.svg'; @@ -609,6 +610,7 @@ const Expensicons = { ApplePayMark, Contactless, CampfireSquare, + ZohoBooksSquare, }; // Create the ExpensifyIcons object from the imported Expensicons diff --git a/src/languages/de.ts b/src/languages/de.ts index 505a983f8e72..c02da9c1c183 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -7318,6 +7318,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.ZOHO_BOOKS: + return 'Zoho Books'; case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL: return 'Dynamics 365 Business Central'; default: { @@ -7545,6 +7547,8 @@ Der Control-Tarif beginnt bei 9 $ pro aktivem Mitglied und Monat.`, return 'Campfire-Daten werden synchronisiert'; case 'campfireSyncConnection': return 'Verbindung zu Campfire wird initialisiert'; + case 'zohoBooksSyncConnection': + return 'Verbindung zu Zoho Books wird initialisiert'; case 'campfireSyncImportData': return 'Daten werden geladen'; case 'campfireSyncPayments': @@ -7602,6 +7606,7 @@ Der Control-Tarif beginnt bei 9 $ pro aktivem Mitglied und Monat.`, syncTravelInvoicingSettlementsNoAccountTooltip: 'Zum Aktivieren legen Sie ein Konto für Ihre Exporte fest.', syncTravelInvoicingSettlementsNoAutoSyncTooltip: 'Zum Entsperren automatische Synchronisierung aktivieren.', campfire: 'Campfire', + zohoBooks: 'Zoho Books', continuousReconciliationFeedSelection: 'Die fortlaufende Abstimmung wird pro Kartenfeed konfiguriert. Wählen Sie einen Feed aus, um zu ändern, welchen Sie konfigurieren.', businessCentral: 'Dynamics 365 Business Central', diff --git a/src/languages/el.ts b/src/languages/el.ts index 064233a100a1..87d967a9c603 100644 --- a/src/languages/el.ts +++ b/src/languages/el.ts @@ -7448,6 +7448,8 @@ _Για πιο αναλυτικές οδηγίες, [επισκεφθείτε τ return 'DualEntry'; case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE: return 'Campfire'; + case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS: + return 'Zoho Books'; case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL: return 'Dynamics 365 Business Central'; default: { @@ -7676,6 +7678,8 @@ _Για πιο αναλυτικές οδηγίες, [επισκεφθείτε τ return 'Γίνεται συγχρονισμός δεδομένων Campfire'; case 'campfireSyncConnection': return 'Γίνεται αρχικοποίηση σύνδεσης με το Campfire'; + case 'zohoBooksSyncConnection': + return 'Γίνεται αρχικοποίηση σύνδεσης με το Zoho Books'; case 'campfireSyncImportData': return 'Φόρτωση δεδομένων'; case 'campfireSyncPayments': @@ -7733,6 +7737,7 @@ _Για πιο αναλυτικές οδηγίες, [επισκεφθείτε τ syncTravelInvoicingSettlementsNoAccountTooltip: 'Για να το ενεργοποιήσετε, ορίστε έναν λογαριασμό για τις εξαγωγές σας.', syncTravelInvoicingSettlementsNoAutoSyncTooltip: 'Για να το ξεκλειδώσετε, ενεργοποιήστε τον αυτόματο συγχρονισμό.', campfire: 'Campfire', + zohoBooks: 'Zoho Books', continuousReconciliationFeedSelection: 'Η συνεχής συμφωνία είναι ρυθμισμένη ανά ροή καρτών. Επιλέξτε μια ροή για να αλλάξετε ποια ρυθμίζετε.', businessCentral: 'Dynamics 365 Business Central', diff --git a/src/languages/en.ts b/src/languages/en.ts index da4c1455f16c..9c2c63980d80 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -7641,6 +7641,7 @@ const translations = { rillet: 'Rillet', dualEntry: 'DualEntry', campfire: 'Campfire', + zohoBooks: 'Zoho Books', businessCentral: 'Dynamics 365 Business Central', sap: 'SAP', oracle: 'Oracle', @@ -7665,6 +7666,8 @@ const translations = { return 'DualEntry'; case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE: return 'Campfire'; + case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS: + return 'Zoho Books'; case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL: return 'Dynamics 365 Business Central'; default: { @@ -7895,6 +7898,8 @@ const translations = { return 'Syncing Campfire data'; case 'campfireSyncConnection': return 'Initializing connection to Campfire'; + case 'zohoBooksSyncConnection': + return 'Initializing connection to Zoho Books'; case 'campfireSyncImportData': return 'Loading data'; case 'campfireSyncPayments': diff --git a/src/languages/es.ts b/src/languages/es.ts index b75baf48477d..533a2b31fa28 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -7123,6 +7123,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.ZOHO_BOOKS: + return 'Zoho Books'; case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL: return 'Dynamics 365 Business Central'; default: { @@ -7351,6 +7353,8 @@ El plan Controlar empieza en 9 $ por miembro activo al mes.`, return 'Sincronizando datos de Campfire'; case 'campfireSyncConnection': return 'Iniciando conexión con Campfire'; + case 'zohoBooksSyncConnection': + return 'Iniciando conexión con Zoho Books'; case 'campfireSyncImportData': return 'Cargando datos'; case 'campfireSyncPayments': @@ -7408,6 +7412,7 @@ El plan Controlar empieza en 9 $ por miembro activo al mes.`, syncTravelInvoicingSettlementsNoAccountTooltip: 'Para desbloquearlo, configura una cuenta para tus exportaciones.', syncTravelInvoicingSettlementsNoAutoSyncTooltip: 'Para desbloquear, habilita la sincronización automática.', campfire: 'Campfire', + 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.', businessCentral: 'Dynamics 365 Business Central', diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 2953e37f929f..cdf0e4777d54 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -7336,6 +7336,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.ZOHO_BOOKS: + return 'Zoho Books'; case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL: return 'Dynamics 365 Business Central'; default: { @@ -7564,6 +7566,8 @@ Le forfait Control commence à 9 $ par Membre actif et par mois.`, return 'Synchronisation des données Campfire'; case 'campfireSyncConnection': return 'Initialisation de la connexion à Campfire'; + case 'zohoBooksSyncConnection': + return 'Initialisation de la connexion à Zoho Books'; case 'campfireSyncImportData': return 'Chargement des données'; case 'campfireSyncPayments': @@ -7621,6 +7625,7 @@ Le forfait Control commence à 9 $ par Membre actif et par mois.`, syncTravelInvoicingSettlementsNoAccountTooltip: 'Pour le déverrouiller, définissez un compte pour vos exports.', syncTravelInvoicingSettlementsNoAutoSyncTooltip: 'Pour le déverrouiller, activez la synchronisation automatique.', campfire: 'Campfire', + zohoBooks: 'Zoho Books', continuousReconciliationFeedSelection: 'Le rapprochement continu est configuré par flux de carte. Sélectionnez un flux pour changer celui que vous configurez.', businessCentral: 'Dynamics 365 Business Central', diff --git a/src/languages/it.ts b/src/languages/it.ts index 4493c684f9c6..6703b0b8abed 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -7276,6 +7276,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.ZOHO_BOOKS: + return 'Zoho Books'; case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL: return 'Dynamics 365 Business Central'; default: { @@ -7503,6 +7505,8 @@ Il piano Control parte da 9 $ al mese per ogni membro attivo.`, return 'Sincronizzazione dei dati Campfire'; case 'campfireSyncConnection': return 'Inizializzazione della connessione a Campfire'; + case 'zohoBooksSyncConnection': + return 'Inizializzazione della connessione a Zoho Books'; case 'campfireSyncImportData': return 'Caricamento dei dati'; case 'campfireSyncPayments': @@ -7560,6 +7564,7 @@ Il piano Control parte da 9 $ al mese per ogni membro attivo.`, syncTravelInvoicingSettlementsNoAccountTooltip: 'Per sbloccare, imposta un conto per le tue esportazioni.', syncTravelInvoicingSettlementsNoAutoSyncTooltip: 'Per sbloccare, abilita la sincronizzazione automatica.', campfire: 'Campfire', + zohoBooks: 'Zoho Books', continuousReconciliationFeedSelection: 'La Riconciliazione continua è configurata per ogni flusso di carte. Seleziona un flusso per cambiare quello che stai configurando.', businessCentral: 'Dynamics 365 Business Central', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index 8c0ae357052b..6efad1e448d2 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -7186,6 +7186,8 @@ Control プランは、アクティブメンバー1人あたり月額 $9 から return 'DualEntry'; case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE: return 'Campfire'; + case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS: + return 'Zoho Books'; case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL: return 'Dynamics 365 Business Central'; default: { @@ -7414,6 +7416,8 @@ Control プランは、アクティブメンバー1人あたり月額 $9 から return 'Campfire データを同期しています'; case 'campfireSyncConnection': return 'Campfire への接続を初期化しています'; + case 'zohoBooksSyncConnection': + return 'Zoho Books への接続を初期化しています'; case 'campfireSyncImportData': return 'データを読み込んでいます'; case 'campfireSyncPayments': @@ -7470,6 +7474,7 @@ Control プランは、アクティブメンバー1人あたり月額 $9 から syncTravelInvoicingSettlementsNoAccountTooltip: 'ロックを解除するには、エクスポート用の口座を設定してください。', syncTravelInvoicingSettlementsNoAutoSyncTooltip: 'ロックを解除するには、自動同期を有効にしてください。', campfire: 'Campfire', + zohoBooks: 'Zoho Books', continuousReconciliationFeedSelection: '継続的な照合はカードフィードごとに設定されます。設定するフィードを変更するには、フィードを選択してください。', businessCentral: 'Dynamics 365 Business Central', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index fadbc004788e..93789f0c3537 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -7260,6 +7260,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.ZOHO_BOOKS: + return 'Zoho Books'; case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL: return 'Dynamics 365 Business Central'; default: { @@ -7487,6 +7489,8 @@ Het Control-abonnement begint bij $9 per actieve deelnemer per maand.`, return 'Campfire-gegevens synchroniseren'; case 'campfireSyncConnection': return 'Verbinding met Campfire initialiseren'; + case 'zohoBooksSyncConnection': + return 'Verbinding met Zoho Books initialiseren'; case 'campfireSyncImportData': return 'Gegevens laden'; case 'campfireSyncPayments': @@ -7544,6 +7548,7 @@ Het Control-abonnement begint bij $9 per actieve deelnemer per maand.`, syncTravelInvoicingSettlementsNoAccountTooltip: 'Om dit te ontgrendelen, stel je een rekening in voor je exporten.', syncTravelInvoicingSettlementsNoAutoSyncTooltip: 'Schakel automatisch synchroniseren in om dit te ontgrendelen.', campfire: 'Campfire', + zohoBooks: 'Zoho Books', continuousReconciliationFeedSelection: 'Doorlopende afstemming wordt per kaartfeed geconfigureerd. Selecteer een feed om te wijzigen welke je configureert.', businessCentral: 'Dynamics 365 Business Central', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 889539ccabe5..c09dd3434716 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -7284,6 +7284,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.ZOHO_BOOKS: + return 'Zoho Books'; case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL: return 'Dynamics 365 Business Central'; default: { @@ -7511,6 +7513,8 @@ Plan Control zaczyna się od 9 USD za aktywnego członka miesięcznie.`, return 'Synchronizowanie danych Campfire'; case 'campfireSyncConnection': return 'Inicjowanie połączenia z Campfire'; + case 'zohoBooksSyncConnection': + return 'Inicjowanie połączenia z Zoho Books'; case 'campfireSyncImportData': return 'Wczytywanie danych'; case 'campfireSyncPayments': @@ -7567,6 +7571,7 @@ Plan Control zaczyna się od 9 USD za aktywnego członka miesięcznie.`, syncTravelInvoicingSettlementsNoAccountTooltip: 'Aby odblokować, ustaw konto dla swoich eksportów.', syncTravelInvoicingSettlementsNoAutoSyncTooltip: 'Aby odblokować, włącz automatyczną synchronizację.', campfire: 'Campfire', + 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.', businessCentral: 'Dynamics 365 Business Central', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 1de49e27f39a..5a76f42a9875 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -7262,6 +7262,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.ZOHO_BOOKS: + return 'Zoho Books'; case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL: return 'Dynamics 365 Business Central'; default: { @@ -7489,6 +7491,8 @@ O plano Control começa em US$ 9 por membro ativo por mês.`, return 'Sincronizando dados do Campfire'; case 'campfireSyncConnection': return 'Inicializando conexão com o Campfire'; + case 'zohoBooksSyncConnection': + return 'Inicializando conexão com o Zoho Books'; case 'campfireSyncImportData': return 'Carregando dados'; case 'campfireSyncPayments': @@ -7546,6 +7550,7 @@ O plano Control começa em US$ 9 por membro ativo por mês.`, syncTravelInvoicingSettlementsNoAccountTooltip: 'Para desbloquear, defina uma conta para suas exportações.', syncTravelInvoicingSettlementsNoAutoSyncTooltip: 'Para desbloquear, ative a sincronização automática.', campfire: 'Campfire', + zohoBooks: 'Zoho Books', continuousReconciliationFeedSelection: 'A Conciliação Contínua é configurada por feed de cartão. Selecione um feed para alterar qual você está configurando.', businessCentral: 'Dynamics 365 Business Central', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 35b7beee7a11..55283d0431ea 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -7008,6 +7008,8 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM return 'DualEntry'; case CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE: return 'Campfire'; + case CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS: + return 'Zoho Books'; case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL: return 'Dynamics 365 Business Central'; default: { @@ -7234,6 +7236,8 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM return '正在同步 Campfire 数据'; case 'campfireSyncConnection': return '正在初始化与 Campfire 的连接'; + case 'zohoBooksSyncConnection': + return '正在初始化与 Zoho Books 的连接'; case 'campfireSyncImportData': return '正在加载数据'; case 'campfireSyncPayments': @@ -7286,6 +7290,7 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM syncTravelInvoicingSettlementsNoAccountTooltip: '要解锁,请为导出设置一个账户。', syncTravelInvoicingSettlementsNoAutoSyncTooltip: '若要解锁,请启用自动同步。', campfire: 'Campfire', + zohoBooks: 'Zoho Books', continuousReconciliationFeedSelection: '按卡片流水单独配置持续对账。选择一个流水以更改您正在配置的流水。', businessCentral: 'Dynamics 365 Business Central', qboConnectionExpiring: ({date}: {date: string}) => `您的 QuickBooks Online 连接将于 ${date} 过期。`, diff --git a/src/libs/API/parameters/ConnectPolicyToZohoBooksParams.ts b/src/libs/API/parameters/ConnectPolicyToZohoBooksParams.ts new file mode 100644 index 000000000000..a1b38c276641 --- /dev/null +++ b/src/libs/API/parameters/ConnectPolicyToZohoBooksParams.ts @@ -0,0 +1,5 @@ +type ConnectPolicyToZohoBooksParams = { + policyID: string; +}; + +export default ConnectPolicyToZohoBooksParams; diff --git a/src/libs/API/parameters/SyncPolicyToZohoBooksParams.ts b/src/libs/API/parameters/SyncPolicyToZohoBooksParams.ts new file mode 100644 index 000000000000..8fb2c5992296 --- /dev/null +++ b/src/libs/API/parameters/SyncPolicyToZohoBooksParams.ts @@ -0,0 +1,6 @@ +type SyncPolicyToZohoBooksParams = { + policyID: string; + idempotencyKey: string; +}; + +export default SyncPolicyToZohoBooksParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksAccountingMethodParams.ts b/src/libs/API/parameters/UpdateZohoBooksAccountingMethodParams.ts new file mode 100644 index 000000000000..004fcc2b6074 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksAccountingMethodParams.ts @@ -0,0 +1,9 @@ +import type {CONST as COMMON_CONST} from 'expensify-common'; +import type {ValueOf} from 'type-fest'; + +type UpdateZohoBooksAccountingMethodParams = { + policyID: string; + accountingMethod: ValueOf; +}; + +export default UpdateZohoBooksAccountingMethodParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksAutoSyncParams.ts b/src/libs/API/parameters/UpdateZohoBooksAutoSyncParams.ts new file mode 100644 index 000000000000..df0764f4d78e --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksAutoSyncParams.ts @@ -0,0 +1,6 @@ +type UpdateZohoBooksAutoSyncParams = { + policyID: string; + enabled: boolean; +}; + +export default UpdateZohoBooksAutoSyncParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksBillPaymentAccountParams.ts b/src/libs/API/parameters/UpdateZohoBooksBillPaymentAccountParams.ts new file mode 100644 index 000000000000..3ac5d96cd718 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksBillPaymentAccountParams.ts @@ -0,0 +1,8 @@ +import type {ZohoBooksAccount} from '@src/types/onyx/Policy'; + +type UpdateZohoBooksBillPaymentAccountParams = { + policyID: string; + billPaymentAccountID: ZohoBooksAccount['id']; +}; + +export default UpdateZohoBooksBillPaymentAccountParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksCardProgramAccountParams.ts b/src/libs/API/parameters/UpdateZohoBooksCardProgramAccountParams.ts new file mode 100644 index 000000000000..aa0fad7563f5 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksCardProgramAccountParams.ts @@ -0,0 +1,10 @@ +import type {CardFeedWithNumber} from '@src/types/onyx/CardFeeds'; +import type {ZohoBooksAccount} from '@src/types/onyx/Policy'; + +type UpdateZohoBooksCardProgramAccountParams = { + policyID: string; + feedKey: CardFeedWithNumber; + cardProgramAccountID: ZohoBooksAccount['id']; +}; + +export default UpdateZohoBooksCardProgramAccountParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksCreditCardAccountParams.ts b/src/libs/API/parameters/UpdateZohoBooksCreditCardAccountParams.ts new file mode 100644 index 000000000000..1c98a59deab0 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksCreditCardAccountParams.ts @@ -0,0 +1,8 @@ +import type {ZohoBooksAccount} from '@src/types/onyx/Policy'; + +type UpdateZohoBooksCreditCardAccountParams = { + policyID: string; + creditCardAccountID: ZohoBooksAccount['id']; +}; + +export default UpdateZohoBooksCreditCardAccountParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksDefaultVendorParams.ts b/src/libs/API/parameters/UpdateZohoBooksDefaultVendorParams.ts new file mode 100644 index 000000000000..a3eb5f7d58c4 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksDefaultVendorParams.ts @@ -0,0 +1,8 @@ +import type {ZohoBooksVendor} from '@src/types/onyx/Policy'; + +type UpdateZohoBooksDefaultVendorParams = { + policyID: string; + vendorID: ZohoBooksVendor['id']; +}; + +export default UpdateZohoBooksDefaultVendorParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksEnableNewCategoriesParams.ts b/src/libs/API/parameters/UpdateZohoBooksEnableNewCategoriesParams.ts new file mode 100644 index 000000000000..c4b458815727 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksEnableNewCategoriesParams.ts @@ -0,0 +1,9 @@ +type UpdateZohoBooksEnableNewCategoriesParams = { + /** The workspace where the setting is updated. */ + policyID: string; + + /** Whether categories newly created in Zoho Books are imported. */ + enabled: boolean; +}; + +export default UpdateZohoBooksEnableNewCategoriesParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksExportDateParams.ts b/src/libs/API/parameters/UpdateZohoBooksExportDateParams.ts new file mode 100644 index 000000000000..777f3089e304 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksExportDateParams.ts @@ -0,0 +1,8 @@ +import type {ZohoBooksExportDate} from '@src/types/onyx/Policy'; + +type UpdateZohoBooksExportDateParams = { + policyID: string; + value: ZohoBooksExportDate; +}; + +export default UpdateZohoBooksExportDateParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksExportToMultipleAccountsParams.ts b/src/libs/API/parameters/UpdateZohoBooksExportToMultipleAccountsParams.ts new file mode 100644 index 000000000000..77def440e222 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksExportToMultipleAccountsParams.ts @@ -0,0 +1,6 @@ +type UpdateZohoBooksExportToMultipleAccountsParams = { + policyID: string; + enabled: boolean; +}; + +export default UpdateZohoBooksExportToMultipleAccountsParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksExporterParams.ts b/src/libs/API/parameters/UpdateZohoBooksExporterParams.ts new file mode 100644 index 000000000000..a1bbbad5f896 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksExporterParams.ts @@ -0,0 +1,6 @@ +type UpdateZohoBooksExporterParams = { + policyID: string; + email: string; +}; + +export default UpdateZohoBooksExporterParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksFieldMappingParams.ts b/src/libs/API/parameters/UpdateZohoBooksFieldMappingParams.ts new file mode 100644 index 000000000000..34c301973558 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksFieldMappingParams.ts @@ -0,0 +1,16 @@ +import type CONST from '@src/CONST'; + +import type {ValueOf} from 'type-fest'; + +type UpdateZohoBooksFieldMappingParams = { + /** The workspace where the field mapping is updated. */ + policyID: string; + + /** The Zoho Books reporting tag to map. */ + fieldID: string; + + /** The Expensify dimension mapped to the Zoho Books reporting tag. */ + mapping: ValueOf; +}; + +export default UpdateZohoBooksFieldMappingParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksOrganizationParams.ts b/src/libs/API/parameters/UpdateZohoBooksOrganizationParams.ts new file mode 100644 index 000000000000..51adb4193bb3 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksOrganizationParams.ts @@ -0,0 +1,6 @@ +type UpdateZohoBooksOrganizationParams = { + policyID: string; + organizationID: string; +}; + +export default UpdateZohoBooksOrganizationParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksSettlementsAccountParams.ts b/src/libs/API/parameters/UpdateZohoBooksSettlementsAccountParams.ts new file mode 100644 index 000000000000..c46c0cb9dd70 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksSettlementsAccountParams.ts @@ -0,0 +1,8 @@ +import type {ZohoBooksAccount} from '@src/types/onyx/Policy'; + +type UpdateZohoBooksSettlementsAccountParams = { + policyID: string; + settlementsBankAccountID: ZohoBooksAccount['id']; +}; + +export default UpdateZohoBooksSettlementsAccountParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksSyncExpensifyCardSettlementsParams.ts b/src/libs/API/parameters/UpdateZohoBooksSyncExpensifyCardSettlementsParams.ts new file mode 100644 index 000000000000..4c4ba509e804 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksSyncExpensifyCardSettlementsParams.ts @@ -0,0 +1,6 @@ +type UpdateZohoBooksSyncExpensifyCardSettlementsParams = { + policyID: string; + enabled: boolean; +}; + +export default UpdateZohoBooksSyncExpensifyCardSettlementsParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksSyncReimbursedReportsParams.ts b/src/libs/API/parameters/UpdateZohoBooksSyncReimbursedReportsParams.ts new file mode 100644 index 000000000000..b07370de5763 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksSyncReimbursedReportsParams.ts @@ -0,0 +1,6 @@ +type UpdateZohoBooksSyncReimbursedReportsParams = { + policyID: string; + enabled: boolean; +}; + +export default UpdateZohoBooksSyncReimbursedReportsParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksSyncTaxRatesParams.ts b/src/libs/API/parameters/UpdateZohoBooksSyncTaxRatesParams.ts new file mode 100644 index 000000000000..614ef888dd8d --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksSyncTaxRatesParams.ts @@ -0,0 +1,9 @@ +type UpdateZohoBooksSyncTaxRatesParams = { + /** The workspace where the setting is updated. */ + policyID: string; + + /** Whether tax rates are imported from Zoho Books. */ + enabled: boolean; +}; + +export default UpdateZohoBooksSyncTaxRatesParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksSyncTravelInvoicingSettlementsParams.ts b/src/libs/API/parameters/UpdateZohoBooksSyncTravelInvoicingSettlementsParams.ts new file mode 100644 index 000000000000..9f563629b877 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksSyncTravelInvoicingSettlementsParams.ts @@ -0,0 +1,6 @@ +type UpdateZohoBooksSyncTravelInvoicingSettlementsParams = { + policyID: string; + enabled: boolean; +}; + +export default UpdateZohoBooksSyncTravelInvoicingSettlementsParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksTravelInvoicingPayableAccountParams.ts b/src/libs/API/parameters/UpdateZohoBooksTravelInvoicingPayableAccountParams.ts new file mode 100644 index 000000000000..f8c5f8c2f769 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksTravelInvoicingPayableAccountParams.ts @@ -0,0 +1,8 @@ +import type {ZohoBooksAccount} from '@src/types/onyx/Policy'; + +type UpdateZohoBooksTravelInvoicingPayableAccountParams = { + policyID: string; + travelInvoicingPayableAccountID: ZohoBooksAccount['id']; +}; + +export default UpdateZohoBooksTravelInvoicingPayableAccountParams; diff --git a/src/libs/API/parameters/UpdateZohoBooksTravelInvoicingSettlementsAccountParams.ts b/src/libs/API/parameters/UpdateZohoBooksTravelInvoicingSettlementsAccountParams.ts new file mode 100644 index 000000000000..3fcb3a50ffc3 --- /dev/null +++ b/src/libs/API/parameters/UpdateZohoBooksTravelInvoicingSettlementsAccountParams.ts @@ -0,0 +1,8 @@ +import type {ZohoBooksAccount} from '@src/types/onyx/Policy'; + +type UpdateZohoBooksTravelInvoicingSettlementsAccountParams = { + policyID: string; + travelInvoicingSettlementsBankAccountID: ZohoBooksAccount['id']; +}; + +export default UpdateZohoBooksTravelInvoicingSettlementsAccountParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 5f66c7ca5c99..c38e680189c0 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -30,6 +30,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 ConnectPolicyToZohoBooksParams} from './ConnectPolicyToZohoBooksParams'; export type {default as ConnectPolicyToBusinessCentralParams} from './ConnectPolicyToBusinessCentralParams'; export type {default as OpenPolicyProfilePageParams} from './OpenPolicyProfilePageParams'; export type {default as OpenPolicyInitialPageParams} from './OpenPolicyInitialPageParams'; @@ -101,6 +102,26 @@ 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 SyncPolicyToZohoBooksParams} from './SyncPolicyToZohoBooksParams'; +export type {default as UpdateZohoBooksOrganizationParams} from './UpdateZohoBooksOrganizationParams'; +export type {default as UpdateZohoBooksFieldMappingParams} from './UpdateZohoBooksFieldMappingParams'; +export type {default as UpdateZohoBooksEnableNewCategoriesParams} from './UpdateZohoBooksEnableNewCategoriesParams'; +export type {default as UpdateZohoBooksSyncTaxRatesParams} from './UpdateZohoBooksSyncTaxRatesParams'; +export type {default as UpdateZohoBooksExporterParams} from './UpdateZohoBooksExporterParams'; +export type {default as UpdateZohoBooksExportDateParams} from './UpdateZohoBooksExportDateParams'; +export type {default as UpdateZohoBooksDefaultVendorParams} from './UpdateZohoBooksDefaultVendorParams'; +export type {default as UpdateZohoBooksCreditCardAccountParams} from './UpdateZohoBooksCreditCardAccountParams'; +export type {default as UpdateZohoBooksExportToMultipleAccountsParams} from './UpdateZohoBooksExportToMultipleAccountsParams'; +export type {default as UpdateZohoBooksCardProgramAccountParams} from './UpdateZohoBooksCardProgramAccountParams'; +export type {default as UpdateZohoBooksAutoSyncParams} from './UpdateZohoBooksAutoSyncParams'; +export type {default as UpdateZohoBooksAccountingMethodParams} from './UpdateZohoBooksAccountingMethodParams'; +export type {default as UpdateZohoBooksSyncReimbursedReportsParams} from './UpdateZohoBooksSyncReimbursedReportsParams'; +export type {default as UpdateZohoBooksBillPaymentAccountParams} from './UpdateZohoBooksBillPaymentAccountParams'; +export type {default as UpdateZohoBooksSyncExpensifyCardSettlementsParams} from './UpdateZohoBooksSyncExpensifyCardSettlementsParams'; +export type {default as UpdateZohoBooksSettlementsAccountParams} from './UpdateZohoBooksSettlementsAccountParams'; +export type {default as UpdateZohoBooksSyncTravelInvoicingSettlementsParams} from './UpdateZohoBooksSyncTravelInvoicingSettlementsParams'; +export type {default as UpdateZohoBooksTravelInvoicingSettlementsAccountParams} from './UpdateZohoBooksTravelInvoicingSettlementsAccountParams'; +export type {default as UpdateZohoBooksTravelInvoicingPayableAccountParams} from './UpdateZohoBooksTravelInvoicingPayableAccountParams'; export type {default as SyncPolicyToBusinessCentralParams} from './SyncPolicyToBusinessCentralParams'; export type {default as UpdateBusinessCentralCompanyParams} from './UpdateBusinessCentralCompanyParams'; export type {default as UpdateBusinessCentralCustomerMappingParams} from './UpdateBusinessCentralCustomerMappingParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 87983049317c..53b395c71dea 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -615,6 +615,25 @@ 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_ZOHO_BOOKS_ORGANIZATION: 'UpdateZohoBooksOrganization', + UPDATE_ZOHO_BOOKS_FIELD_MAPPING: 'UpdateZohoBooksFieldMapping', + UPDATE_ZOHO_BOOKS_ENABLE_NEW_CATEGORIES: 'UpdateZohoBooksEnableNewCategories', + UPDATE_ZOHO_BOOKS_SYNC_TAX_RATES: 'UpdateZohoBooksSyncTaxRates', + UPDATE_ZOHO_BOOKS_EXPORTER: 'UpdateZohoBooksExporter', + UPDATE_ZOHO_BOOKS_EXPORT_DATE: 'UpdateZohoBooksExportDate', + UPDATE_ZOHO_BOOKS_DEFAULT_VENDOR: 'UpdateZohoBooksDefaultVendor', + UPDATE_ZOHO_BOOKS_CREDIT_CARD_ACCOUNT: 'UpdateZohoBooksCreditCardAccount', + UPDATE_ZOHO_BOOKS_EXPORT_TO_MULTIPLE_ACCOUNTS: 'UpdateZohoBooksExportToMultipleAccounts', + UPDATE_ZOHO_BOOKS_CARD_PROGRAM_ACCOUNT: 'UpdateZohoBooksCardProgramAccount', + UPDATE_ZOHO_BOOKS_AUTO_SYNC: 'UpdateZohoBooksAutoSync', + UPDATE_ZOHO_BOOKS_ACCOUNTING_METHOD: 'UpdateZohoBooksAccountingMethod', + UPDATE_ZOHO_BOOKS_SYNC_REIMBURSED_REPORTS: 'UpdateZohoBooksSyncReimbursedReports', + UPDATE_ZOHO_BOOKS_BILL_PAYMENT_ACCOUNT: 'UpdateZohoBooksBillPaymentAccount', + UPDATE_ZOHO_BOOKS_SYNC_EXPENSIFY_CARD_SETTLEMENTS: 'UpdateZohoBooksSyncExpensifyCardSettlements', + UPDATE_ZOHO_BOOKS_SETTLEMENTS_ACCOUNT: 'UpdateZohoBooksSettlementsAccount', + UPDATE_ZOHO_BOOKS_SYNC_TRAVEL_INVOICING_SETTLEMENTS: 'UpdateZohoBooksSyncTravelInvoicingSettlements', + UPDATE_ZOHO_BOOKS_TRAVEL_INVOICING_SETTLEMENTS_ACCOUNT: 'UpdateZohoBooksTravelInvoicingSettlementsAccount', + UPDATE_ZOHO_BOOKS_TRAVEL_INVOICING_PAYABLE_ACCOUNT: 'UpdateZohoBooksTravelInvoicingPayableAccount', SET_PROMO_CODE: 'User_SetPromoCode', REQUEST_TAX_EXEMPTION: 'RequestTaxExemption', @@ -1343,6 +1362,25 @@ 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_ZOHO_BOOKS_ORGANIZATION]: Parameters.UpdateZohoBooksOrganizationParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_FIELD_MAPPING]: Parameters.UpdateZohoBooksFieldMappingParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_ENABLE_NEW_CATEGORIES]: Parameters.UpdateZohoBooksEnableNewCategoriesParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_SYNC_TAX_RATES]: Parameters.UpdateZohoBooksSyncTaxRatesParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_EXPORTER]: Parameters.UpdateZohoBooksExporterParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_EXPORT_DATE]: Parameters.UpdateZohoBooksExportDateParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_DEFAULT_VENDOR]: Parameters.UpdateZohoBooksDefaultVendorParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_CREDIT_CARD_ACCOUNT]: Parameters.UpdateZohoBooksCreditCardAccountParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_EXPORT_TO_MULTIPLE_ACCOUNTS]: Parameters.UpdateZohoBooksExportToMultipleAccountsParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_CARD_PROGRAM_ACCOUNT]: Parameters.UpdateZohoBooksCardProgramAccountParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_AUTO_SYNC]: Parameters.UpdateZohoBooksAutoSyncParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_ACCOUNTING_METHOD]: Parameters.UpdateZohoBooksAccountingMethodParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateZohoBooksSyncReimbursedReportsParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_BILL_PAYMENT_ACCOUNT]: Parameters.UpdateZohoBooksBillPaymentAccountParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_SYNC_EXPENSIFY_CARD_SETTLEMENTS]: Parameters.UpdateZohoBooksSyncExpensifyCardSettlementsParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_SETTLEMENTS_ACCOUNT]: Parameters.UpdateZohoBooksSettlementsAccountParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_SYNC_TRAVEL_INVOICING_SETTLEMENTS]: Parameters.UpdateZohoBooksSyncTravelInvoicingSettlementsParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_TRAVEL_INVOICING_SETTLEMENTS_ACCOUNT]: Parameters.UpdateZohoBooksTravelInvoicingSettlementsAccountParams; + [WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_TRAVEL_INVOICING_PAYABLE_ACCOUNT]: Parameters.UpdateZohoBooksTravelInvoicingPayableAccountParams; [WRITE_COMMANDS.UPGRADE_TO_CORPORATE]: Parameters.UpgradeToCorporateParams; [WRITE_COMMANDS.DOWNGRADE_TO_TEAM]: Parameters.DowngradeToTeamParams; @@ -1562,6 +1600,8 @@ const READ_COMMANDS = { SYNC_POLICY_TO_RILLET: 'SyncPolicyToRillet', SYNC_POLICY_TO_DUALENTRY: 'SyncPolicyToDualEntry', SYNC_POLICY_TO_CAMPFIRE: 'SyncPolicyToCampfire', + SYNC_POLICY_TO_ZOHO_BOOKS: 'SyncPolicyToZohoBooks', + CONNECT_POLICY_TO_ZOHO_BOOKS: 'ConnectPolicyToZohoBooks', SYNC_POLICY_TO_BUSINESS_CENTRAL: 'SyncPolicyToBusinessCentral', CONNECT_POLICY_TO_FINANCIAL_FORCE: 'ConnectPolicyToFinancialForce', OPEN_REIMBURSEMENT_ACCOUNT_PAGE: 'OpenReimbursementAccountPage', @@ -1684,6 +1724,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_ZOHO_BOOKS]: Parameters.SyncPolicyToZohoBooksParams; + [READ_COMMANDS.CONNECT_POLICY_TO_ZOHO_BOOKS]: Parameters.ConnectPolicyToZohoBooksParams; [READ_COMMANDS.SYNC_POLICY_TO_BUSINESS_CENTRAL]: Parameters.SyncPolicyToBusinessCentralParams; [READ_COMMANDS.OPEN_REIMBURSEMENT_ACCOUNT_PAGE]: Parameters.OpenReimbursementAccountPageParams; [READ_COMMANDS.OPEN_WORKSPACE_VIEW]: Parameters.OpenWorkspaceViewParams; diff --git a/src/libs/AccountingUtils.ts b/src/libs/AccountingUtils.ts index af5c8662556e..bbf03d1bd4e5 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.ZOHO_BOOKS]: CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS, [CONST.POLICY.CONNECTIONS.ROUTE.BUSINESS_CENTRAL]: CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL, }; @@ -40,6 +41,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.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/actions/connections/ZohoBooks.ts b/src/libs/actions/connections/ZohoBooks.ts new file mode 100644 index 000000000000..aa99ab7dfa83 --- /dev/null +++ b/src/libs/actions/connections/ZohoBooks.ts @@ -0,0 +1,813 @@ +import {write} from '@libs/API'; +import type { + UpdateZohoBooksAccountingMethodParams, + UpdateZohoBooksAutoSyncParams, + UpdateZohoBooksBillPaymentAccountParams, + UpdateZohoBooksCardProgramAccountParams, + UpdateZohoBooksCreditCardAccountParams, + UpdateZohoBooksDefaultVendorParams, + UpdateZohoBooksEnableNewCategoriesParams, + UpdateZohoBooksExportDateParams, + UpdateZohoBooksExporterParams, + UpdateZohoBooksExportToMultipleAccountsParams, + UpdateZohoBooksFieldMappingParams, + UpdateZohoBooksOrganizationParams, + UpdateZohoBooksSettlementsAccountParams, + UpdateZohoBooksSyncExpensifyCardSettlementsParams, + UpdateZohoBooksSyncReimbursedReportsParams, + UpdateZohoBooksSyncTaxRatesParams, + UpdateZohoBooksSyncTravelInvoicingSettlementsParams, + UpdateZohoBooksTravelInvoicingPayableAccountParams, + UpdateZohoBooksTravelInvoicingSettlementsAccountParams, +} 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 {ZohoBooksAutoSync, ZohoBooksCoding, ZohoBooksConnectionsConfig, ZohoBooksExport, ZohoBooksSync} 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 getZohoBooksSetupLink(policyID: string) { + // Zoho Books 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_ZOHO_BOOKS, shouldSkipWebProxy: true}); + return commandURL + params.toString(); +} + +function clearZohoBooksErrorField(policyID: string, fieldName: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: { + config: {errorFields: {[fieldName]: null}}, + }, + }, + }); +} + +function prepareZohoBooksOnyxData( + 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.ZOHO_BOOKS]: { + 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.ZOHO_BOOKS]: { + config: { + pendingFields: { + [settingName]: null, + }, + }, + }, + }, + }, + }, + ]; + + const failureData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: { + config: { + [settingName]: oldSettingValue ?? null, + pendingFields: { + [settingName]: null, + }, + errorFields: { + [settingName]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + }, + }, + }, + ]; + + return {optimisticData, successData, failureData}; +} + +function prepareZohoBooksCodingOnyxData( + 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.ZOHO_BOOKS]: { + config: { + coding: { + [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.ZOHO_BOOKS]: { + config: { + pendingFields: { + [settingName]: null, + }, + }, + }, + }, + }, + }, + ]; + + const failureData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: { + config: { + coding: { + [settingName]: oldSettingValue ?? null, + }, + pendingFields: { + [settingName]: null, + }, + errorFields: { + [settingName]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + }, + }, + }, + ]; + + return {optimisticData, successData, failureData}; +} + +function prepareZohoBooksFieldMappingOnyxData( + policyID: string, + fieldID: keyof NonNullable, + mapping: ValueOf>, + oldMapping: ValueOf> | null, +) { + const fieldOfflineFeedbackKey = `${CONST.ZOHO_BOOKS_CONFIG.FIELD_MAPPING_PREFIX}${fieldID}`; + + const optimisticData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: { + 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.ZOHO_BOOKS]: { + config: { + pendingFields: { + [fieldOfflineFeedbackKey]: null, + }, + }, + }, + }, + }, + }, + ]; + + const failureData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: { + config: { + coding: { + fieldMappings: { + [fieldID]: oldMapping ?? null, + }, + }, + pendingFields: { + [fieldOfflineFeedbackKey]: null, + }, + errorFields: { + [fieldOfflineFeedbackKey]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + }, + }, + }, + ]; + + return {optimisticData, successData, failureData}; +} + +function prepareZohoBooksExportOnyxData( + 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.ZOHO_BOOKS]: { + 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.ZOHO_BOOKS]: { + config: { + pendingFields: { + [settingName]: null, + }, + }, + }, + }, + }, + }, + ]; + + const failureData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: { + config: { + export: { + [settingName]: oldSettingValue ?? null, + }, + pendingFields: { + [settingName]: null, + }, + errorFields: { + [settingName]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + }, + }, + }, + ]; + + return {optimisticData, successData, failureData}; +} + +function prepareZohoBooksAutoSyncOnyxData(policyID: string, enabled: ZohoBooksAutoSync['enabled'], oldEnabled?: ZohoBooksAutoSync['enabled'] | null) { + const optimisticData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: { + config: { + autoSync: { + enabled, + }, + pendingFields: { + [CONST.ZOHO_BOOKS_CONFIG.AUTO_SYNC]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + }, + errorFields: { + [CONST.ZOHO_BOOKS_CONFIG.AUTO_SYNC]: null, + }, + }, + }, + }, + }, + }, + ]; + + const successData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: { + config: { + pendingFields: { + [CONST.ZOHO_BOOKS_CONFIG.AUTO_SYNC]: null, + }, + }, + }, + }, + }, + }, + ]; + + const failureData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: { + config: { + autoSync: { + enabled: oldEnabled ?? null, + }, + pendingFields: { + [CONST.ZOHO_BOOKS_CONFIG.AUTO_SYNC]: null, + }, + errorFields: { + [CONST.ZOHO_BOOKS_CONFIG.AUTO_SYNC]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + }, + }, + }, + ]; + + return {optimisticData, successData, failureData}; +} + +function prepareZohoBooksSyncOnyxData( + 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.ZOHO_BOOKS]: { + 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.ZOHO_BOOKS]: { + config: { + pendingFields: { + [settingName]: null, + }, + }, + }, + }, + }, + }, + ]; + + const failureData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: { + config: { + sync: { + [settingName]: oldSettingValue ?? null, + }, + pendingFields: { + [settingName]: null, + }, + errorFields: { + [settingName]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + }, + }, + }, + ]; + + return {optimisticData, successData, failureData}; +} + +function prepareZohoBooksCardProgramAccountOnyxData( + policyID: string, + feedKey: keyof ZohoBooksExport['cardProgramAccounts'], + accountID: ValueOf, + oldAccountID?: ValueOf | null, +) { + const cardProgramAccountOfflineFeedbackKey = `${CONST.ZOHO_BOOKS_CONFIG.CARD_PROGRAM_ACCOUNT_PREFIX}${feedKey}`; + + const optimisticData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: { + 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.ZOHO_BOOKS]: { + config: { + pendingFields: { + [cardProgramAccountOfflineFeedbackKey]: null, + }, + }, + }, + }, + }, + }, + ]; + + const failureData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + connections: { + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: { + config: { + export: { + cardProgramAccounts: { + [feedKey]: oldAccountID ?? null, + }, + }, + pendingFields: { + [cardProgramAccountOfflineFeedbackKey]: null, + }, + errorFields: { + [cardProgramAccountOfflineFeedbackKey]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }, + }, + }, + }, + }, + }, + ]; + + return {optimisticData, successData, failureData}; +} + +function updateZohoBooksOrganization(policyID: string, organizationID: ZohoBooksConnectionsConfig['organizationID'], oldSubsidiaryID?: ZohoBooksConnectionsConfig['organizationID']) { + const onyxData = prepareZohoBooksOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.ORGANIZATION_ID, organizationID, oldSubsidiaryID ?? null); + const params: UpdateZohoBooksOrganizationParams = { + policyID, + organizationID, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_ORGANIZATION, params, onyxData); +} + +function updateZohoBooksEnableNewCategories(policyID: string, enabled: ZohoBooksConnectionsConfig['enableNewCategories'], oldEnabled?: ZohoBooksConnectionsConfig['enableNewCategories']) { + const onyxData = prepareZohoBooksOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.ENABLE_NEW_CATEGORIES, enabled, oldEnabled ?? null); + const parameters: UpdateZohoBooksEnableNewCategoriesParams = { + policyID, + enabled, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_ENABLE_NEW_CATEGORIES, parameters, onyxData); +} + +function updateZohoBooksSyncTaxRates(policyID: string, enabled: ZohoBooksCoding['syncTaxRates'], oldEnabled?: ZohoBooksCoding['syncTaxRates']) { + const onyxData = prepareZohoBooksCodingOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.SYNC_TAX_RATES, enabled, oldEnabled ?? null); + const parameters: UpdateZohoBooksSyncTaxRatesParams = { + policyID, + enabled, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_SYNC_TAX_RATES, parameters, onyxData); +} + +function updateZohoBooksFieldMapping( + policyID: string, + fieldID: keyof NonNullable, + mapping: ValueOf>, + oldMapping?: ValueOf>, +) { + const onyxData = prepareZohoBooksFieldMappingOnyxData(policyID, fieldID, mapping, oldMapping ?? null); + const parameters: UpdateZohoBooksFieldMappingParams = { + policyID, + fieldID, + mapping, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_FIELD_MAPPING, parameters, onyxData); +} + +function updateZohoBooksExporter(policyID: string, email: ZohoBooksExport['exporter'], oldEmail?: ZohoBooksExport['exporter']) { + const onyxData = prepareZohoBooksExportOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.EXPORTER, email, oldEmail ?? null); + const parameters: UpdateZohoBooksExporterParams = { + policyID, + email, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_EXPORTER, parameters, onyxData); +} + +function updateZohoBooksExportDate(policyID: string, value: ZohoBooksExport['exportDate'], oldValue?: ZohoBooksExport['exportDate']) { + const onyxData = prepareZohoBooksExportOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.EXPORT_DATE, value, oldValue ?? null); + const parameters: UpdateZohoBooksExportDateParams = { + policyID, + value, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_EXPORT_DATE, parameters, onyxData); +} + +function updateZohoBooksDefaultVendor(policyID: string, vendorID: ZohoBooksExport['defaultVendorID'], oldVendorID?: ZohoBooksExport['defaultVendorID']) { + const onyxData = prepareZohoBooksExportOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.DEFAULT_VENDORID, vendorID, oldVendorID ?? null); + const parameters: UpdateZohoBooksDefaultVendorParams = { + policyID, + vendorID, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_DEFAULT_VENDOR, parameters, onyxData); +} + +function updateZohoBooksCreditCardAccount(policyID: string, creditCardAccountID: ZohoBooksExport['creditCardAccountID'], oldCreditCardAccountID?: ZohoBooksExport['creditCardAccountID']) { + const onyxData = prepareZohoBooksExportOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.CREDIT_CARD_ACCOUNT_ID, creditCardAccountID, oldCreditCardAccountID ?? null); + const parameters: UpdateZohoBooksCreditCardAccountParams = { + policyID, + creditCardAccountID, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_CREDIT_CARD_ACCOUNT, parameters, onyxData); +} + +function updateZohoBooksAutoSync(policyID: string, enabled: ZohoBooksAutoSync['enabled'], oldEnabled?: ZohoBooksAutoSync['enabled']) { + const onyxData = prepareZohoBooksAutoSyncOnyxData(policyID, enabled, oldEnabled ?? null); + const parameters: UpdateZohoBooksAutoSyncParams = { + policyID, + enabled, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_AUTO_SYNC, parameters, onyxData); +} + +function updateZohoBooksAccountingMethod(policyID: string, accountingMethod: ZohoBooksExport['accountingMethod'], oldAccountingMethod?: ZohoBooksExport['accountingMethod']) { + const onyxData = prepareZohoBooksExportOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.ACCOUNTING_METHOD, accountingMethod, oldAccountingMethod ?? null); + const parameters: UpdateZohoBooksAccountingMethodParams = { + policyID, + accountingMethod, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_ACCOUNTING_METHOD, parameters, onyxData); +} + +function updateZohoBooksSyncReimbursedReports(policyID: string, enabled: ZohoBooksSync['syncReimbursedReports'], oldEnabled?: ZohoBooksSync['syncReimbursedReports']) { + const onyxData = prepareZohoBooksSyncOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.SYNC_REIMBURSED_REPORTS, enabled, oldEnabled ?? null); + const parameters: UpdateZohoBooksSyncReimbursedReportsParams = { + policyID, + enabled, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_SYNC_REIMBURSED_REPORTS, parameters, onyxData); +} + +function updateZohoBooksBillPaymentAccount(policyID: string, billPaymentAccountID: ZohoBooksSync['billPaymentAccountID'], oldBillPaymentAccountID?: ZohoBooksSync['billPaymentAccountID']) { + const onyxData = prepareZohoBooksSyncOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.BILL_PAYMENT_ACCOUNT_ID, billPaymentAccountID, oldBillPaymentAccountID ?? null); + const parameters: UpdateZohoBooksBillPaymentAccountParams = { + policyID, + billPaymentAccountID, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_BILL_PAYMENT_ACCOUNT, parameters, onyxData); +} + +function updateZohoBooksSyncExpensifyCardSettlements(policyID: string, enabled: ZohoBooksSync['syncExpensifyCardSettlements'], oldEnabled?: ZohoBooksSync['syncExpensifyCardSettlements']) { + const onyxData = prepareZohoBooksSyncOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.SYNC_EXPENSIFY_CARD_SETTLEMENTS, enabled, oldEnabled ?? null); + const parameters: UpdateZohoBooksSyncExpensifyCardSettlementsParams = { + policyID, + enabled, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_SYNC_EXPENSIFY_CARD_SETTLEMENTS, parameters, onyxData); +} + +function updateZohoBooksSettlementsAccount( + policyID: string, + settlementsBankAccountID: ZohoBooksSync['settlementsBankAccountID'], + oldSettlementsBankAccountID?: ZohoBooksSync['settlementsBankAccountID'], +) { + const onyxData = prepareZohoBooksSyncOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.SETTLEMENTS_BANK_ACCOUNT_ID, settlementsBankAccountID, oldSettlementsBankAccountID ?? null); + const parameters: UpdateZohoBooksSettlementsAccountParams = { + policyID, + settlementsBankAccountID, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_SETTLEMENTS_ACCOUNT, parameters, onyxData); +} + +function updateZohoBooksSyncTravelInvoicingSettlements( + policyID: string, + enabled: ZohoBooksSync['syncTravelInvoicingSettlements'], + oldEnabled?: ZohoBooksSync['syncTravelInvoicingSettlements'], +) { + const onyxData = prepareZohoBooksSyncOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.SYNC_TRAVEL_BILLING_SETTLEMENTS, enabled, oldEnabled ?? null); + const parameters: UpdateZohoBooksSyncTravelInvoicingSettlementsParams = { + policyID, + enabled, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_SYNC_TRAVEL_INVOICING_SETTLEMENTS, parameters, onyxData); +} + +function updateZohoBooksTravelInvoicingSettlementsAccount( + policyID: string, + travelInvoicingSettlementsBankAccountID: ZohoBooksSync['travelInvoicingSettlementsBankAccountID'], + oldTravelInvoicingSettlementsBankAccountID?: ZohoBooksSync['travelInvoicingSettlementsBankAccountID'], +) { + const onyxData = prepareZohoBooksSyncOnyxData( + policyID, + CONST.ZOHO_BOOKS_CONFIG.TRAVEL_BILLING_SETTLEMENTS_BANK_ACCOUNT_ID, + travelInvoicingSettlementsBankAccountID, + oldTravelInvoicingSettlementsBankAccountID ?? null, + ); + const parameters: UpdateZohoBooksTravelInvoicingSettlementsAccountParams = { + policyID, + travelInvoicingSettlementsBankAccountID, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_TRAVEL_INVOICING_SETTLEMENTS_ACCOUNT, parameters, onyxData); +} + +function updateZohoBooksTravelInvoicingPayableAccount( + policyID: string, + travelInvoicingPayableAccountID: ZohoBooksExport['travelInvoicingPayableAccountID'], + oldTravelInvoicingPayableAccountID?: ZohoBooksExport['travelInvoicingPayableAccountID'], +) { + const onyxData = prepareZohoBooksExportOnyxData( + policyID, + CONST.ZOHO_BOOKS_CONFIG.TRAVEL_BILLING_PAYABLE_ACCOUNT_ID, + travelInvoicingPayableAccountID, + oldTravelInvoicingPayableAccountID ?? null, + ); + const parameters: UpdateZohoBooksTravelInvoicingPayableAccountParams = { + policyID, + travelInvoicingPayableAccountID, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_TRAVEL_INVOICING_PAYABLE_ACCOUNT, parameters, onyxData); +} + +function updateZohoBooksExportToMultipleAccounts(policyID: string, enabled: ZohoBooksExport['exportToMultipleAccounts'], oldEnabled?: ZohoBooksExport['exportToMultipleAccounts']) { + const onyxData = prepareZohoBooksExportOnyxData(policyID, CONST.ZOHO_BOOKS_CONFIG.EXPORT_TO_MULTIPLE_ACCOUNTS, enabled, oldEnabled ?? null); + const parameters: UpdateZohoBooksExportToMultipleAccountsParams = { + policyID, + enabled, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_EXPORT_TO_MULTIPLE_ACCOUNTS, parameters, onyxData); +} + +function updateZohoBooksCardProgramAccount( + policyID: string, + feedKey: keyof ZohoBooksExport['cardProgramAccounts'], + cardProgramAccountID: ValueOf, + oldCardProgramAccountID?: ValueOf, +) { + const onyxData = prepareZohoBooksCardProgramAccountOnyxData(policyID, feedKey, cardProgramAccountID, oldCardProgramAccountID ?? null); + const parameters: UpdateZohoBooksCardProgramAccountParams = { + policyID, + feedKey, + cardProgramAccountID, + }; + write(WRITE_COMMANDS.UPDATE_ZOHO_BOOKS_CARD_PROGRAM_ACCOUNT, parameters, onyxData); +} + +export { + getZohoBooksSetupLink, + clearZohoBooksErrorField, + updateZohoBooksOrganization, + updateZohoBooksEnableNewCategories, + updateZohoBooksSyncTaxRates, + updateZohoBooksFieldMapping, + updateZohoBooksExporter, + updateZohoBooksExportDate, + updateZohoBooksDefaultVendor, + updateZohoBooksCreditCardAccount, + updateZohoBooksAutoSync, + updateZohoBooksAccountingMethod, + updateZohoBooksSyncReimbursedReports, + updateZohoBooksBillPaymentAccount, + updateZohoBooksSyncExpensifyCardSettlements, + updateZohoBooksSettlementsAccount, + updateZohoBooksSyncTravelInvoicingSettlements, + updateZohoBooksTravelInvoicingSettlementsAccount, + updateZohoBooksTravelInvoicingPayableAccount, + updateZohoBooksExportToMultipleAccounts, + updateZohoBooksCardProgramAccount, +}; diff --git a/src/libs/actions/connections/index.ts b/src/libs/actions/connections/index.ts index 97901dda98e5..244550066811 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.ZOHO_BOOKS: { + return {readCommand: READ_COMMANDS.SYNC_POLICY_TO_ZOHO_BOOKS, stageInProgress: CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.ZOHO_BOOKS_SYNC_CONNECTION}; + } case CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL: { return { readCommand: READ_COMMANDS.SYNC_POLICY_TO_BUSINESS_CENTRAL, diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 9ae952b123ec..325652c9a510 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1,3 +1,4 @@ +/* eslint-disable max-lines -- Accounting connection types stay together in the policy type. */ import type MergeSyncResult from '@libs/API/MergeSyncResult'; import type CONST from '@src/CONST'; @@ -2511,6 +2512,309 @@ type CampfireConnectionsConfig = OnyxCommon.OnyxValueWithOfflineFeedback< CampfireCodingOfflineFeedbackKeys | CampfireExportOfflineFeedbackKeys | keyof CampfireAutoSync | keyof CampfireSync >; +/** + * An organization configured in Zoho Books. + */ +type ZohoBooksOrganization = { + /** Unique identifier of the organization. */ + id: string; + + /** Name of the organization. */ + name: string; + + /** Currency associated with the organization. */ + currency: string; + + /** Multi-location organizations are not supported. The organization selector uses this to show an error. */ + isMultiLocation?: boolean; +}; + +/** + * Available account types. + */ +type ZohoBooksAccountType = ValueOf; + +/** + * Account retrieved from Zoho Books. + */ +type ZohoBooksAccount = { + /** Unique identifier of the account. */ + id: string; + + /** Account number. */ + number?: string; + + /** Name of the account. */ + name: string; + + /** Zoho Books account_type. */ + accountType: ZohoBooksAccountType; + + /** Currency associated with the account. */ + currency?: string; + + /** Whether the account is active. */ + isActive: boolean; +}; + +/** + * Reporting tag retrieved from Zoho Books. + */ +type ZohoBooksReportingTag = { + /** Unique identifier of the reporting tag. */ + id: string; + + /** Name of the reporting tag. */ + name: string; +}; + +/** + * Available vendor types. + */ +type ZohoBooksVendorType = ValueOf; + +/** + * Vendor retrieved from Zoho Books. + */ +type ZohoBooksVendor = { + /** Unique identifier of the vendor. */ + id: string; + + /** Name of the vendor. */ + name: string; + + /** Email address associated with the vendor. */ + email?: string; + + /** Type of the vendor. */ + vendorType: ZohoBooksVendorType; + + /** Whether the vendor is active. */ + isActive: boolean; +}; + +/** + * Tax rate line retrieved from Zoho Books. + */ +type ZohoBooksTaxRateLine = { + /** Value of the tax rate. */ + rate: string; + + /** Tax account ID. */ + taxAccountID?: string; + + /** Whether to use expense account itself instead of taxAccountID */ + useExpenseAccount: boolean; +}; + +/** + * Tax rate retrieved from Zoho Books. + */ +type ZohoBooksTaxRate = { + /** Unique identifier of the tax rate. */ + id: string; + + /** Name of the tax rate. */ + name: string; + + /** Value of the tax rate. */ + rate: string; + + /** Code used to identify the tax rate. */ + code?: string; + + /** + * A rate is made of lines, and each line says where its share of the tax goes: + * a named tax account, or the expense account itself when useExpenseAccount is set. + */ + lines: ZohoBooksTaxRateLine[]; +}; + +/** + * Connection data retrieved from Zoho Books. + */ +type ZohoBooksConnectionData = { + /** Collection of eligible organizations in Zoho Books. */ + organizations?: ZohoBooksOrganization[]; + + /** Accounts available in Zoho Books. */ + accounts?: ZohoBooksAccount[]; + + /** Reporting tags available in Zoho Books. */ + reportingTags?: ZohoBooksReportingTag[]; + + /** Vendors available in Zoho Books. */ + vendors?: ZohoBooksVendor[]; + + /** Mapping of settlement identifiers to their corresponding journal entry identifiers. */ + settlementJournalEntryIDs?: Record; + + /** Mapping of travel settlement identifiers to their corresponding journal entry identifiers. */ + travelSettlementJournalEntryIDs?: Record; + + /** Entry identifier from which settlement synchronization should start. */ + settlementSyncStartEntryID?: number; + + /** Entry identifier from which travel settlement synchronization should start. */ + travelSettlementSyncStartEntryID?: number; + + /** Tax rates available in Zoho Books. */ + taxRates?: ZohoBooksTaxRate[]; +}; + +/** + * Coding configuration used when exporting data to Zoho Books. + */ +type ZohoBooksCoding = { + /** + * Mapping of Zoho Books reporting tag IDs to their configured mapping behavior. + */ + fieldMappings?: Record>; + + /** Whether tax rates should be synchronized from Zoho Books. */ + syncTaxRates: boolean; +}; + +/** Offline feedback key for field mapping */ +type ZohoBooksCodingFieldMappingsOfflineFeedbackKey = `${typeof CONST.ZOHO_BOOKS_CONFIG.FIELD_MAPPING_PREFIX}${string}`; + +/** + * Offline feedback keys for `ZohoBooksCoding` + */ +type ZohoBooksCodingOfflineFeedbackKeys = keyof Omit | ZohoBooksCodingFieldMappingsOfflineFeedbackKey; + +/** + * Available dates that can be used as the export date. + */ +type ZohoBooksExportDate = ValueOf; + +/** + * Export strategy for reimbursable expenses. + */ +type ZohoBooksExportReimbursable = ValueOf; + +/** + * Export strategy for company card expenses. + */ +type ZohoBooksExportNonReimbursable = ValueOf; + +/** + * Export configuration for sending accounting data to Zoho Books. + */ +type ZohoBooksExport = { + /** Identifier of the export implementation to use. */ + exporter: string; + + /** Date source used when generating exported transactions. */ + exportDate: ZohoBooksExportDate; + + /** Export behavior for reimbursable expenses. */ + reimbursable: ZohoBooksExportReimbursable; + + /** Export behavior for company card expenses. */ + nonReimbursable: ZohoBooksExportNonReimbursable; + + /** 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 codes. + */ + 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 ZohoBooksExportCardProgramAccountsOfflineFeedbackKey = `${typeof CONST.ZOHO_BOOKS_CONFIG.CARD_PROGRAM_ACCOUNT_PREFIX}${string}`; + +/** + * Offline feedback keys for `ZohoBooksExport` + */ +type ZohoBooksExportOfflineFeedbackKeys = keyof Omit | ZohoBooksExportCardProgramAccountsOfflineFeedbackKey; + +/** + * Automatic synchronization settings for Zoho Books. + */ +type ZohoBooksAutoSync = { + /** Whether automatic synchronization is enabled. */ + enabled: boolean; + + /** Unique identifier of the automatic synchronization job. */ + jobID?: string | null; +}; + +/** + * Synchronization settings for importing and updating data in Zoho Books. + */ +type ZohoBooksSync = { + /** Whether reimbursed expense reports should be synchronized. */ + syncReimbursedReports: boolean; + + /** Account code 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 Zoho Books. + */ +type ZohoBooksConnectionsConfig = OnyxCommon.OnyxValueWithOfflineFeedback< + { + /** The internalID of the selected organization in Zoho Books */ + organizationID: string; + + /** Whether the connection has been configured */ + isConfigured: boolean; + + /** Whether to enable a new Expense Category into Expensify */ + enableNewCategories: boolean; + + /** Coding settings */ + coding?: ZohoBooksCoding; + + /** Export settings */ + export?: ZohoBooksExport; + + /** Auto-sync settings */ + autoSync?: ZohoBooksAutoSync; + + /** Sync settings */ + sync?: ZohoBooksSync; + + /** Collection of errors coming from BE */ + errors?: OnyxCommon.Errors; + + /** Collection of form field errors */ + errorFields?: OnyxCommon.ErrorFields; + }, + ZohoBooksCodingOfflineFeedbackKeys | ZohoBooksExportOfflineFeedbackKeys | keyof ZohoBooksAutoSync | keyof ZohoBooksSync +>; + /** * A company (legal entity) reachable with the Business Central connection's credentials. */ @@ -3041,6 +3345,9 @@ type Connections = { /** Campfire integration connection */ [CONST.POLICY.CONNECTIONS.NAME.CAMPFIRE]: Connection; + /** Zoho Books integration connection */ + [CONST.POLICY.CONNECTIONS.NAME.ZOHO_BOOKS]: Connection; + /** Business Central integration connection */ [CONST.POLICY.CONNECTIONS.NAME.BUSINESS_CENTRAL]: Connection; @@ -3912,9 +4219,19 @@ export type { CampfireExport, CampfireAutoSync, CampfireSync, + ZohoBooksExportDate, + ZohoBooksVendor, + ZohoBooksAccount, BusinessCentralCompany, BusinessCentralCoding, BusinessCentralCustomerMappings, BusinessCentralExport, BusinessCentralCodingOfflineFeedbackKeys, }; + +/** + * The Zoho Books action module is the only importer of these config types, and Knip ignores that module until workspace screens import it. + * + * @public + */ +export type {ZohoBooksAutoSync, ZohoBooksCoding, ZohoBooksConnectionsConfig, ZohoBooksExport, ZohoBooksSync};