From 1d3a28787b831b9734920a73f2a205fcf00423c1 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Wed, 6 Aug 2025 17:27:05 +0200 Subject: [PATCH 01/12] update translations --- src/languages/de.ts | 10 ++++++++++ src/languages/en.ts | 10 ++++++++++ src/languages/es.ts | 10 ++++++++++ src/languages/fr.ts | 10 ++++++++++ src/languages/it.ts | 10 ++++++++++ src/languages/ja.ts | 10 ++++++++++ src/languages/nl.ts | 10 ++++++++++ src/languages/pl.ts | 10 ++++++++++ src/languages/pt-BR.ts | 10 ++++++++++ src/languages/zh-hans.ts | 10 ++++++++++ 10 files changed, 100 insertions(+) diff --git a/src/languages/de.ts b/src/languages/de.ts index ed6c1f598675..c5a315a7cd55 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -3391,6 +3391,7 @@ const translations = { travel: 'Reisen', members: 'Mitglieder', accounting: 'Buchhaltung', + receiptPartners: 'Beleg-Partner', rules: 'Regeln', displayedAs: 'Angezeigt als', plan: 'Plan', @@ -4603,12 +4604,21 @@ const translations = { title: 'Buchhaltung', subtitle: 'Synchronisieren Sie Ihren Kontenplan und mehr.', }, + receiptPartners: { + title: 'Beleg-Partner', + subtitle: 'Automatischer Import von Belegen.', + }, connectionsWarningModal: { featureEnabledTitle: 'Nicht so schnell...', featureEnabledText: 'Um diese Funktion zu aktivieren oder zu deaktivieren, müssen Sie Ihre Buchhaltungsimporteinstellungen ändern.', disconnectText: 'Um die Buchhaltung zu deaktivieren, müssen Sie Ihre Buchhaltungsverbindung von Ihrem Arbeitsbereich trennen.', manageSettings: 'Einstellungen verwalten', }, + receiptPartnersWarningModal: { + featureEnabledTitle: 'Uber trennen', + disconnectText: 'Um diese Funktion zu deaktivieren, trennen Sie bitte zuerst die Uber for Business Integration.', + confirmText: 'Verstanden', + }, workflowWarningModal: { featureEnabledTitle: 'Nicht so schnell...', featureEnabledText: diff --git a/src/languages/en.ts b/src/languages/en.ts index ef7b9e4908b5..5f71b343b02f 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3384,6 +3384,7 @@ const translations = { travel: 'Travel', members: 'Members', accounting: 'Accounting', + receiptPartners: 'Receipt partners', rules: 'Rules', displayedAs: 'Displayed as', plan: 'Plan', @@ -4582,12 +4583,21 @@ const translations = { title: 'Accounting', subtitle: 'Sync your chart of accounts and more.', }, + receiptPartners: { + title: 'Receipt partners', + subtitle: 'Automatically import receipts.', + }, connectionsWarningModal: { featureEnabledTitle: 'Not so fast...', featureEnabledText: "To enable or disable this feature, you'll need to change your accounting import settings.", disconnectText: "To disable accounting, you'll need to disconnect your accounting connection from your workspace.", manageSettings: 'Manage settings', }, + receiptPartnersWarningModal: { + featureEnabledTitle: 'Disconnect Uber', + disconnectText: 'To disable this feature, please disconnect the Uber for Business integration first.', + confirmText: 'Got it', + }, workflowWarningModal: { featureEnabledTitle: 'Not so fast...', featureEnabledText: diff --git a/src/languages/es.ts b/src/languages/es.ts index e8f9f1bf89eb..80ace7626c20 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -3375,6 +3375,7 @@ const translations = { travel: 'Viajes', members: 'Miembros', accounting: 'Contabilidad', + receiptPartners: 'Socios de recibos', rules: 'Reglas', plan: 'Plan', profile: 'Resumen', @@ -4596,12 +4597,21 @@ const translations = { title: 'Contabilidad', subtitle: 'Sincroniza tu plan de cuentas y otras opciones.', }, + receiptPartners: { + title: 'Socios de recibos', + subtitle: 'Importación automática de recibos.', + }, connectionsWarningModal: { featureEnabledTitle: 'No tan rápido...', featureEnabledText: 'Para activar o desactivar esta función, cambia la configuración de importación contable.', disconnectText: 'Para desactivar la contabilidad, desconecta tu conexión contable del espacio de trabajo.', manageSettings: 'Gestionar la configuración', }, + receiptPartnersWarningModal: { + featureEnabledTitle: 'Desconectar Uber', + disconnectText: 'Para desactivar esta función, desconecta primero la integración de Uber for Business.', + confirmText: 'Entendido', + }, workflowWarningModal: { featureEnabledTitle: 'No tan rápido...', featureEnabledText: diff --git a/src/languages/fr.ts b/src/languages/fr.ts index a5fc1643ff78..08fad229dd49 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -3399,6 +3399,7 @@ const translations = { travel: 'Voyage', members: 'Membres', accounting: 'Comptabilité', + receiptPartners: 'Partenaires de reçus', rules: 'Règles', displayedAs: 'Affiché comme', plan: 'Planification', @@ -4619,12 +4620,21 @@ const translations = { title: 'Comptabilité', subtitle: 'Synchronisez votre plan comptable et plus encore.', }, + receiptPartners: { + title: 'Partenaires de reçus', + subtitle: 'Importer automatiquement les reçus.', + }, connectionsWarningModal: { featureEnabledTitle: 'Pas si vite...', featureEnabledText: "Pour activer ou désactiver cette fonctionnalité, vous devrez modifier vos paramètres d'importation comptable.", disconnectText: 'Pour désactiver la comptabilité, vous devrez déconnecter votre connexion comptable de votre espace de travail.', manageSettings: 'Gérer les paramètres', }, + receiptPartnersWarningModal: { + featureEnabledTitle: 'Déconnecter Uber', + disconnectText: 'Pour désactiver cette fonctionnalité, veuillez d\'abord déconnecter l\'intégration Uber for Business.', + confirmText: 'Compris', + }, workflowWarningModal: { featureEnabledTitle: 'Pas si vite...', featureEnabledText: diff --git a/src/languages/it.ts b/src/languages/it.ts index 1371ec2a2989..c98e654855b9 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -3404,6 +3404,7 @@ const translations = { travel: 'Viaggio', members: 'Membri', accounting: 'Contabilità', + receiptPartners: 'Partner ricevute', rules: 'Regole', displayedAs: 'Visualizzato come', plan: 'Piano', @@ -4618,12 +4619,21 @@ const translations = { title: 'Contabilità', subtitle: 'Sincronizza il tuo piano dei conti e altro ancora.', }, + receiptPartners: { + title: 'Partner ricevute', + subtitle: 'Importa automaticamente le ricevute.', + }, connectionsWarningModal: { featureEnabledTitle: 'Non così in fretta...', featureEnabledText: 'Per abilitare o disabilitare questa funzione, dovrai modificare le impostazioni di importazione contabile.', disconnectText: 'Per disabilitare la contabilità, dovrai disconnettere la tua connessione contabile dal tuo spazio di lavoro.', manageSettings: 'Gestisci impostazioni', }, + receiptPartnersWarningModal: { + featureEnabledTitle: 'Disconnetti Uber', + disconnectText: 'Per disabilitare questa funzionalità, disconnetti prima l\'integrazione Uber for Business.', + confirmText: 'Capito', + }, workflowWarningModal: { featureEnabledTitle: 'Non così in fretta...', featureEnabledText: diff --git a/src/languages/ja.ts b/src/languages/ja.ts index aebcef05c0a9..1f494fce08e0 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -3404,6 +3404,7 @@ const translations = { travel: '旅行', members: 'メンバー', accounting: '会計', + receiptPartners: 'レシートパートナー', rules: 'ルール', displayedAs: '表示される内容', plan: '計画', @@ -4597,12 +4598,21 @@ const translations = { title: '会計', subtitle: '勘定科目表などを同期します。', }, + receiptPartners: { + title: 'レシートパートナー', + subtitle: 'レシートを自動的にインポート', + }, connectionsWarningModal: { featureEnabledTitle: 'ちょっと待ってください…', featureEnabledText: 'この機能を有効または無効にするには、会計インポート設定を変更する必要があります。', disconnectText: '会計を無効にするには、ワークスペースから会計接続を切断する必要があります。', manageSettings: '設定を管理', }, + receiptPartnersWarningModal: { + featureEnabledTitle: 'Uberを切断', + disconnectText: 'この機能を無効にするには、まずUber for Business統合を切断してください。', + confirmText: '了解', + }, workflowWarningModal: { featureEnabledTitle: 'ちょっと待ってください…', featureEnabledText: diff --git a/src/languages/nl.ts b/src/languages/nl.ts index d43856e80f63..48772e979787 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -3411,6 +3411,7 @@ const translations = { travel: 'Reis', members: 'Leden', accounting: 'Boekhouding', + receiptPartners: 'Bonnetjespartners', rules: 'Regels', displayedAs: 'Weergegeven als', plan: 'Plan', @@ -4620,12 +4621,21 @@ const translations = { title: 'Boekhouding', subtitle: 'Synchroniseer uw rekeningschema en meer.', }, + receiptPartners: { + title: 'Bonnetjespartners', + subtitle: 'Automatisch bonnetjes importeren.', + }, connectionsWarningModal: { featureEnabledTitle: 'Niet zo snel...', featureEnabledText: 'Om deze functie in of uit te schakelen, moet je je boekhoudimportinstellingen wijzigen.', disconnectText: 'Om boekhouding uit te schakelen, moet je de boekhoudkoppeling van je werkruimte loskoppelen.', manageSettings: 'Instellingen beheren', }, + receiptPartnersWarningModal: { + featureEnabledTitle: 'Uber verbreken', + disconnectText: 'Om deze functie uit te schakelen, verbreek eerst de Uber for Business integratie.', + confirmText: 'Begrepen', + }, workflowWarningModal: { featureEnabledTitle: 'Niet zo snel...', featureEnabledText: diff --git a/src/languages/pl.ts b/src/languages/pl.ts index d8977ee43551..a7f939b85f9f 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -3404,6 +3404,7 @@ const translations = { travel: 'Podróżować', members: 'Członkowie', accounting: 'Księgowość', + receiptPartners: 'Partnerzy paragonów', rules: 'Zasady', displayedAs: 'Wyświetlane jako', plan: 'Plan', @@ -4609,12 +4610,21 @@ const translations = { title: 'Księgowość', subtitle: 'Synchronizuj swój plan kont i więcej.', }, + receiptPartners: { + title: 'Partnerzy paragonów', + subtitle: 'Automatycznie importuj paragony.', + }, connectionsWarningModal: { featureEnabledTitle: 'Nie tak szybko...', featureEnabledText: 'Aby włączyć lub wyłączyć tę funkcję, musisz zmienić ustawienia importu księgowego.', disconnectText: 'Aby wyłączyć księgowość, musisz odłączyć swoje połączenie księgowe od przestrzeni roboczej.', manageSettings: 'Zarządzaj ustawieniami', }, + receiptPartnersWarningModal: { + featureEnabledTitle: 'Rozłącz Uber', + disconnectText: 'Aby wyłączyć tę funkcję, najpierw rozłącz integrację Uber for Business.', + confirmText: 'Rozumiem', + }, workflowWarningModal: { featureEnabledTitle: 'Nie tak szybko...', featureEnabledText: diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index c81252be63bb..7a75574544a6 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -3409,6 +3409,7 @@ const translations = { travel: 'Viagem', members: 'Membros', accounting: 'Contabilidade', + receiptPartners: 'Parceiros de recibos', rules: 'Regras', displayedAs: 'Exibido como', plan: 'Plano', @@ -4615,12 +4616,21 @@ const translations = { title: 'Contabilidade', subtitle: 'Sincronize seu plano de contas e mais.', }, + receiptPartners: { + title: 'Parceiros de recibos', + subtitle: 'Importar recibos automaticamente.', + }, connectionsWarningModal: { featureEnabledTitle: 'Não tão rápido...', featureEnabledText: 'Para ativar ou desativar este recurso, você precisará alterar suas configurações de importação de contabilidade.', disconnectText: 'Para desativar a contabilidade, você precisará desconectar sua conexão contábil do seu espaço de trabalho.', manageSettings: 'Gerenciar configurações', }, + receiptPartnersWarningModal: { + featureEnabledTitle: 'Desconectar Uber', + disconnectText: 'Para desativar este recurso, desconecte primeiro a integração do Uber for Business.', + confirmText: 'Entendi', + }, workflowWarningModal: { featureEnabledTitle: 'Não tão rápido...', featureEnabledText: diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 799557f2ca9f..4c0dd814b673 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -3364,6 +3364,7 @@ const translations = { travel: '旅行', members: '成员', accounting: '会计', + receiptPartners: '收据合作伙伴', rules: '规则', displayedAs: '显示为', plan: '计划', @@ -4535,12 +4536,21 @@ const translations = { title: '会计', subtitle: '同步您的会计科目表及更多内容。', }, + receiptPartners: { + title: '收据合作伙伴', + subtitle: '自动导入收据。', + }, connectionsWarningModal: { featureEnabledTitle: '慢着...', featureEnabledText: '要启用或禁用此功能,您需要更改会计导入设置。', disconnectText: '要禁用会计功能,您需要从工作区断开会计连接。', manageSettings: '管理设置', }, + receiptPartnersWarningModal: { + featureEnabledTitle: '断开Uber连接', + disconnectText: '要禁用此功能,请先断开Uber for Business集成。', + confirmText: '明白了', + }, workflowWarningModal: { featureEnabledTitle: '慢着...', featureEnabledText: '此工作区的Expensify卡片依赖审批工作流程来定义其智能限额。\n\n请在禁用工作流程之前更改任何具有智能限额的卡片的限额类型。', From a2f0918478a12fb9799feae917d16059340e5156 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Wed, 6 Aug 2025 17:27:20 +0200 Subject: [PATCH 02/12] add new illustration --- .../simple-illustration__receipt.svg | 16 ++++++++++++++++ src/components/Icon/Illustrations.ts | 2 ++ 2 files changed, 18 insertions(+) create mode 100644 assets/images/simple-illustrations/simple-illustration__receipt.svg diff --git a/assets/images/simple-illustrations/simple-illustration__receipt.svg b/assets/images/simple-illustrations/simple-illustration__receipt.svg new file mode 100644 index 000000000000..9920d0d1c770 --- /dev/null +++ b/assets/images/simple-illustrations/simple-illustration__receipt.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/components/Icon/Illustrations.ts b/src/components/Icon/Illustrations.ts index 81b511cce86f..11c406987d97 100644 --- a/src/components/Icon/Illustrations.ts +++ b/src/components/Icon/Illustrations.ts @@ -135,6 +135,7 @@ import RealtimeReport from '@assets/images/simple-illustrations/simple-illustrat import ReceiptEnvelope from '@assets/images/simple-illustrations/simple-illustration__receipt-envelope.svg'; import ReceiptLocationMarker from '@assets/images/simple-illustrations/simple-illustration__receipt-location-marker.svg'; import ReceiptWrangler from '@assets/images/simple-illustrations/simple-illustration__receipt-wrangler.svg'; +import ReceiptPartners from '@assets/images/simple-illustrations/simple-illustration__receipt.svg'; import ReceiptUpload from '@assets/images/simple-illustrations/simple-illustration__receiptupload.svg'; import ReportReceipt from '@assets/images/simple-illustrations/simple-illustration__report-receipt.svg'; import Rules from '@assets/images/simple-illustrations/simple-illustration__rules.svg'; @@ -313,6 +314,7 @@ export { ChaseCompanyCardDetailLarge, CitibankCompanyCardDetailLarge, MasterCardCompanyCardDetailLarge, + ReceiptPartners, StripeCompanyCardDetailLarge, VisaCompanyCardDetailLarge, WellsFargoCompanyCardDetailLarge, From 61ae774074ead6856e3c11744262aa705dc97f28 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Wed, 6 Aug 2025 17:27:26 +0200 Subject: [PATCH 03/12] add new screen --- src/SCREENS.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 6e05d7a0fcfa..7ad1e49b4fda 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -623,6 +623,7 @@ const SCREENS = { UPGRADE: 'Workspace_Upgrade', DOWNGRADE: 'Workspace_Downgrade', PAY_AND_DOWNGRADE: 'Workspace_Pay_And_Downgrade', + RECEIPT_PARTNERS: 'Workspace_Receipt_Partners', RULES: 'Policy_Rules', RULES_CUSTOM_NAME: 'Rules_Custom_Name', RULES_AUTO_APPROVE_REPORTS_UNDER: 'Rules_Auto_Approve_Reports_Under', From d73b6eb89a7198a149a30e2595eb6a33ecc2f589 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Wed, 6 Aug 2025 17:27:35 +0200 Subject: [PATCH 04/12] add new enabled CONST --- src/CONST/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 332cc0d5ccf1..089d4a34cc6d 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -2911,6 +2911,7 @@ const CONST = { ARE_WORKFLOWS_ENABLED: 'areWorkflowsEnabled', ARE_REPORT_FIELDS_ENABLED: 'areReportFieldsEnabled', ARE_CONNECTIONS_ENABLED: 'areConnectionsEnabled', + ARE_RECEIPT_PARTNERS_ENABLED: 'areReceiptPartnersEnabled', ARE_COMPANY_CARDS_ENABLED: 'areCompanyCardsEnabled', ARE_EXPENSIFY_CARDS_ENABLED: 'areExpensifyCardsEnabled', ARE_INVOICES_ENABLED: 'areInvoicesEnabled', From 4adc03ec1ad4e2ff3afd840155f323baebe91489 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Wed, 6 Aug 2025 17:27:51 +0200 Subject: [PATCH 05/12] add new command --- .../parameters/ToggleReceiptPartnersParams.ts | 6 +++ src/libs/API/parameters/index.ts | 1 + src/libs/API/types.ts | 2 + src/libs/actions/Policy/Policy.ts | 50 +++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 src/libs/API/parameters/ToggleReceiptPartnersParams.ts diff --git a/src/libs/API/parameters/ToggleReceiptPartnersParams.ts b/src/libs/API/parameters/ToggleReceiptPartnersParams.ts new file mode 100644 index 000000000000..2986f6dedd73 --- /dev/null +++ b/src/libs/API/parameters/ToggleReceiptPartnersParams.ts @@ -0,0 +1,6 @@ +type ToggleReceiptPartnersParams = { + policyID: string; + enabled: boolean; +}; + +export default ToggleReceiptPartnersParams; \ No newline at end of file diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 4626c848eec0..43959a4a38da 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -201,6 +201,7 @@ export type {default as SwitchToOldDotParams} from './SwitchToOldDotParams'; export type {default as TrackExpenseParams} from './TrackExpenseParams'; export type {default as EnablePolicyCategoriesParams} from './EnablePolicyCategoriesParams'; export type {default as EnablePolicyConnectionsParams} from './EnablePolicyConnectionsParams'; +export type {default as ToggleReceiptPartnersParams} from './ToggleReceiptPartnersParams'; export type {default as EnablePolicyDistanceRatesParams} from './EnablePolicyDistanceRatesParams'; export type {default as EnablePolicyTagsParams} from './EnablePolicyTagsParams'; export type {default as SetPolicyTagsEnabled} from './SetPolicyTagsEnabled'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 20739d73c738..e4ba60e7ed74 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -228,6 +228,7 @@ const WRITE_COMMANDS = { TRACK_EXPENSE: 'TrackExpense', ENABLE_POLICY_CATEGORIES: 'EnablePolicyCategories', ENABLE_POLICY_CONNECTIONS: 'EnablePolicyConnections', + TOGGLE_RECEIPT_PARTNERS: 'ToggleReceiptPartners', ENABLE_POLICY_DISTANCE_RATES: 'EnablePolicyDistanceRates', ENABLE_POLICY_TAGS: 'EnablePolicyTags', ENABLE_POLICY_TAXES: 'EnablePolicyTaxes', @@ -725,6 +726,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.TRACK_EXPENSE]: Parameters.TrackExpenseParams; [WRITE_COMMANDS.ENABLE_POLICY_CATEGORIES]: Parameters.EnablePolicyCategoriesParams; [WRITE_COMMANDS.ENABLE_POLICY_CONNECTIONS]: Parameters.EnablePolicyConnectionsParams; + [WRITE_COMMANDS.TOGGLE_RECEIPT_PARTNERS]: Parameters.ToggleReceiptPartnersParams; [WRITE_COMMANDS.ENABLE_POLICY_DISTANCE_RATES]: Parameters.EnablePolicyDistanceRatesParams; [WRITE_COMMANDS.ENABLE_POLICY_TAGS]: Parameters.EnablePolicyTagsParams; [WRITE_COMMANDS.ENABLE_POLICY_TAXES]: Parameters.EnablePolicyTaxesParams; diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 668de5db8ea3..386815640f0e 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -19,6 +19,7 @@ import type { EnablePolicyAutoReimbursementLimitParams, EnablePolicyCompanyCardsParams, EnablePolicyConnectionsParams, + ToggleReceiptPartnersParams, EnablePolicyExpensifyCardsParams, EnablePolicyInvoicingParams, EnablePolicyReportFieldsParams, @@ -3216,6 +3217,54 @@ function enablePolicyConnections(policyID: string, enabled: boolean) { } } +function enablePolicyReceiptPartners(policyID: string, enabled: boolean) { + const onyxData: OnyxData = { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + areReceiptPartnersEnabled: enabled, + pendingFields: { + areReceiptPartnersEnabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + }, + }, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + pendingFields: { + areReceiptPartnersEnabled: null, + }, + }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + areReceiptPartnersEnabled: !enabled, + pendingFields: { + areReceiptPartnersEnabled: null, + }, + }, + }, + ], + }; + + const parameters: ToggleReceiptPartnersParams = {policyID, enabled}; + + API.write(WRITE_COMMANDS.TOGGLE_RECEIPT_PARTNERS, parameters, onyxData); + + if (enabled && getIsNarrowLayout()) { + goBackWhenEnableFeature(policyID); + } +} + /** Save the preferred export method for a policy */ function savePreferredExportMethod(policyID: string, exportMethod: ReportExportType) { Onyx.merge(`${ONYXKEYS.LAST_EXPORT_METHOD}`, {[policyID]: exportMethod}); @@ -5716,6 +5765,7 @@ export { openPolicyWorkflowsPage, enableCompanyCards, enablePolicyConnections, + enablePolicyReceiptPartners, enablePolicyReportFields, enablePolicyTaxes, enablePolicyWorkflows, From 0fa4c3549b86cb1e1a55d90632863a3405d94d57 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Wed, 6 Aug 2025 17:28:16 +0200 Subject: [PATCH 06/12] add new disabled modal and more features toggle --- src/pages/workspace/WorkspaceInitialPage.tsx | 16 +++++++ .../workspace/WorkspaceMoreFeaturesPage.tsx | 43 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/pages/workspace/WorkspaceInitialPage.tsx b/src/pages/workspace/WorkspaceInitialPage.tsx index a73787d36455..f7e573943395 100644 --- a/src/pages/workspace/WorkspaceInitialPage.tsx +++ b/src/pages/workspace/WorkspaceInitialPage.tsx @@ -18,6 +18,7 @@ import { Folder, Gear, InvoiceGeneric, + Receipt, Sync, Tag, Users, @@ -200,6 +201,21 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac }); } + if (featureStates?.[CONST.POLICY.MORE_FEATURES.ARE_RECEIPT_PARTNERS_ENABLED]) { + protectedMenuItems.push({ + translationKey: 'workspace.common.receiptPartners', + icon: Receipt, + action: singleExecution( + waitForNavigate(() => { + // TODO: Navigate to Receipt Partners page when it's created + // Navigation.navigate(ROUTES.POLICY_RECEIPT_PARTNERS.getRoute(policyID)) + }), + ), + screenName: SCREENS.WORKSPACE.CATEGORIES, // Update to SCREENS.WORKSPACE.RECEIPT_PARTNERS when created + highlighted: highlightedFeature === CONST.POLICY.MORE_FEATURES.ARE_RECEIPT_PARTNERS_ENABLED, + }); + } + if (featureStates?.[CONST.POLICY.MORE_FEATURES.ARE_CATEGORIES_ENABLED]) { protectedMenuItems.push({ translationKey: 'workspace.common.categories', diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx index e25143581d05..b6804fc629b5 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx @@ -29,6 +29,7 @@ import { enableExpensifyCard, enablePolicyConnections, enablePolicyInvoicing, + enablePolicyReceiptPartners, enablePolicyRules, enablePolicyTaxes, enablePolicyWorkflows, @@ -90,6 +91,7 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro const [cardFeeds] = useCardFeeds(policyID); const [isOrganizeWarningModalOpen, setIsOrganizeWarningModalOpen] = useState(false); const [isIntegrateWarningModalOpen, setIsIntegrateWarningModalOpen] = useState(false); + const [isReceiptPartnersWarningModalOpen, setIsReceiptPartnersWarningModalOpen] = useState(false); const [isDisableExpensifyCardWarningModalOpen, setIsDisableExpensifyCardWarningModalOpen] = useState(false); const [isDisableCompanyCardsWarningModalOpen, setIsDisableCompanyCardsWarningModalOpen] = useState(false); const [isDisableWorkflowWarningModalOpen, setIsDisableWorkflowWarningModalOpen] = useState(false); @@ -314,6 +316,32 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro clearPolicyErrorField(policyID, CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED); }, }, + { + icon: Illustrations.ReceiptPartners, + titleTranslationKey: 'workspace.moreFeatures.receiptPartners.title', + subtitleTranslationKey: 'workspace.moreFeatures.receiptPartners.subtitle', + isActive: policy?.areReceiptPartnersEnabled ?? false, + pendingAction: policy?.pendingFields?.areReceiptPartnersEnabled, + disabledAction: () => { + // TODO: When Uber integration is added, check if any integration exists + // and show the warning modal to disconnect integration first + setIsReceiptPartnersWarningModalOpen(true); + }, + action: (isEnabled: boolean) => { + if (!policyID) { + return; + } + enablePolicyReceiptPartners(policyID, isEnabled); + }, + disabled: false, // TODO: When Uber integration is added, set to hasReceiptPartnersIntegration + errors: getLatestErrorField(policy ?? {}, CONST.POLICY.MORE_FEATURES.ARE_RECEIPT_PARTNERS_ENABLED), + onCloseError: () => { + if (!policyID) { + return; + } + clearPolicyErrorField(policyID, CONST.POLICY.MORE_FEATURES.ARE_RECEIPT_PARTNERS_ENABLED); + }, + }, ]; const sections: SectionObject[] = [ @@ -482,6 +510,21 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro confirmText={translate('workspace.moreFeatures.connectionsWarningModal.manageSettings')} cancelText={translate('common.cancel')} /> + { + if (!policyID) { + return; + } + setIsReceiptPartnersWarningModalOpen(false); + // TODO: Navigate to Receipt Partners settings page when it exists + // Navigation.navigate(ROUTES.POLICY_RECEIPT_PARTNERS.getRoute(policyID)); + }} + isVisible={isReceiptPartnersWarningModalOpen} + prompt={translate('workspace.moreFeatures.receiptPartnersWarningModal.disconnectText')} + confirmText={translate('workspace.moreFeatures.receiptPartnersWarningModal.confirmText')} + shouldShowCancelButton={false} + /> Date: Wed, 6 Aug 2025 17:28:25 +0200 Subject: [PATCH 07/12] updates --- src/libs/actions/RequestConflictUtils.ts | 1 + src/types/onyx/Policy.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/libs/actions/RequestConflictUtils.ts b/src/libs/actions/RequestConflictUtils.ts index 359db4ada266..d93a4120525e 100644 --- a/src/libs/actions/RequestConflictUtils.ts +++ b/src/libs/actions/RequestConflictUtils.ts @@ -26,6 +26,7 @@ const enablePolicyFeatureCommand = [ WRITE_COMMANDS.ENABLE_POLICY_EXPENSIFY_CARDS, WRITE_COMMANDS.ENABLE_POLICY_COMPANY_CARDS, WRITE_COMMANDS.ENABLE_POLICY_CONNECTIONS, + WRITE_COMMANDS.TOGGLE_RECEIPT_PARTNERS, WRITE_COMMANDS.ENABLE_POLICY_CATEGORIES, WRITE_COMMANDS.ENABLE_POLICY_TAGS, WRITE_COMMANDS.ENABLE_POLICY_TAXES, diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index d8cd8fe17135..31c2e2781c51 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1843,6 +1843,9 @@ type Policy = OnyxCommon.OnyxValueWithOfflineFeedback< /** Whether the Connections feature is enabled */ areConnectionsEnabled?: boolean; + /** Whether the Receipt Partners feature is enabled */ + areReceiptPartnersEnabled?: boolean; + /** Whether the Invoices feature is enabled */ areInvoicesEnabled?: boolean; From cc589866bb48d1ea3b2a2eddd181d15dc74622a0 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Wed, 6 Aug 2025 17:36:08 +0200 Subject: [PATCH 08/12] fix prettier --- src/languages/fr.ts | 2 +- src/languages/it.ts | 2 +- src/libs/API/parameters/ToggleReceiptPartnersParams.ts | 2 +- src/libs/actions/Policy/Policy.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 08fad229dd49..b01d66e4bc2b 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -4632,7 +4632,7 @@ const translations = { }, receiptPartnersWarningModal: { featureEnabledTitle: 'Déconnecter Uber', - disconnectText: 'Pour désactiver cette fonctionnalité, veuillez d\'abord déconnecter l\'intégration Uber for Business.', + disconnectText: "Pour désactiver cette fonctionnalité, veuillez d'abord déconnecter l'intégration Uber for Business.", confirmText: 'Compris', }, workflowWarningModal: { diff --git a/src/languages/it.ts b/src/languages/it.ts index c98e654855b9..cfdffbfbe8c4 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -4631,7 +4631,7 @@ const translations = { }, receiptPartnersWarningModal: { featureEnabledTitle: 'Disconnetti Uber', - disconnectText: 'Per disabilitare questa funzionalità, disconnetti prima l\'integrazione Uber for Business.', + disconnectText: "Per disabilitare questa funzionalità, disconnetti prima l'integrazione Uber for Business.", confirmText: 'Capito', }, workflowWarningModal: { diff --git a/src/libs/API/parameters/ToggleReceiptPartnersParams.ts b/src/libs/API/parameters/ToggleReceiptPartnersParams.ts index 2986f6dedd73..aeff6e203252 100644 --- a/src/libs/API/parameters/ToggleReceiptPartnersParams.ts +++ b/src/libs/API/parameters/ToggleReceiptPartnersParams.ts @@ -3,4 +3,4 @@ type ToggleReceiptPartnersParams = { enabled: boolean; }; -export default ToggleReceiptPartnersParams; \ No newline at end of file +export default ToggleReceiptPartnersParams; diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 386815640f0e..bd59d52cccb1 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -19,7 +19,6 @@ import type { EnablePolicyAutoReimbursementLimitParams, EnablePolicyCompanyCardsParams, EnablePolicyConnectionsParams, - ToggleReceiptPartnersParams, EnablePolicyExpensifyCardsParams, EnablePolicyInvoicingParams, EnablePolicyReportFieldsParams, @@ -52,6 +51,7 @@ import type { SetWorkspaceAutoReportingMonthlyOffsetParams, SetWorkspacePayerParams, SetWorkspaceReimbursementParams, + ToggleReceiptPartnersParams, UpdateInvoiceCompanyNameParams, UpdateInvoiceCompanyWebsiteParams, UpdatePolicyAddressParams, From 6e4d6a9bb64b804bb40b48920399bb125d216dfd Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Wed, 6 Aug 2025 18:05:35 +0200 Subject: [PATCH 09/12] add new BETA --- src/CONST/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 089d4a34cc6d..8838e8ceb6c0 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -677,6 +677,7 @@ const CONST = { EUR_BILLING: 'eurBilling', MANUAL_DISTANCE: 'manualDistance', VACATION_DELEGATE: 'vacationDelegate', + UBER_FOR_BUSINESS: 'uberForBusiness', }, BUTTON_STATES: { DEFAULT: 'default', From d015ed6ae678b4e7180ee2342969294b36daaed8 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Wed, 6 Aug 2025 18:13:33 +0200 Subject: [PATCH 10/12] add beta usage --- src/pages/workspace/WorkspaceInitialPage.tsx | 5 ++- .../workspace/WorkspaceMoreFeaturesPage.tsx | 43 +++++++++++-------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/pages/workspace/WorkspaceInitialPage.tsx b/src/pages/workspace/WorkspaceInitialPage.tsx index f7e573943395..14f10da0ea59 100644 --- a/src/pages/workspace/WorkspaceInitialPage.tsx +++ b/src/pages/workspace/WorkspaceInitialPage.tsx @@ -36,6 +36,7 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails' import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; import usePrevious from '@hooks/usePrevious'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useSingleExecution from '@hooks/useSingleExecution'; @@ -123,6 +124,7 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac const activeRoute = useNavigationState((state) => findFocusedRoute(state)?.name); const {shouldUseNarrowLayout} = useResponsiveLayout(); const {translate} = useLocalize(); + const {isBetaEnabled} = usePermissions(); const {isOffline} = useNetwork(); const wasRendered = useRef(false); const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: true}); @@ -146,8 +148,9 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac [CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED]: policy?.areRulesEnabled, [CONST.POLICY.MORE_FEATURES.ARE_INVOICES_ENABLED]: policy?.areInvoicesEnabled, [CONST.POLICY.MORE_FEATURES.ARE_PER_DIEM_RATES_ENABLED]: policy?.arePerDiemRatesEnabled, + [CONST.POLICY.MORE_FEATURES.ARE_RECEIPT_PARTNERS_ENABLED]: isBetaEnabled(CONST.BETAS.UBER_FOR_BUSINESS) && (policy?.areReceiptPartnersEnabled ?? false), }), - [policy], + [policy, isBetaEnabled], ) as PolicyFeatureStates; const fetchPolicyData = useCallback(() => { diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx index b6804fc629b5..dabe976c6ed5 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx @@ -11,6 +11,7 @@ import useCardFeeds from '@hooks/useCardFeeds'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; +import usePermissions from '@hooks/usePermissions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -76,6 +77,7 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro const StyleUtils = useStyleUtils(); const {shouldUseNarrowLayout} = useResponsiveLayout(); const {translate} = useLocalize(); + const {isBetaEnabled} = usePermissions(); const hasAccountingConnection = !isEmptyObject(policy?.connections); const isAccountingEnabled = !!policy?.areConnectionsEnabled || !isEmptyObject(policy?.connections); const isSyncTaxEnabled = @@ -316,7 +318,10 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro clearPolicyErrorField(policyID, CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED); }, }, - { + ]; + + if (isBetaEnabled(CONST.BETAS.UBER_FOR_BUSINESS)) { + integrateItems.push({ icon: Illustrations.ReceiptPartners, titleTranslationKey: 'workspace.moreFeatures.receiptPartners.title', subtitleTranslationKey: 'workspace.moreFeatures.receiptPartners.subtitle', @@ -341,8 +346,8 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro } clearPolicyErrorField(policyID, CONST.POLICY.MORE_FEATURES.ARE_RECEIPT_PARTNERS_ENABLED); }, - }, - ]; + }); + } const sections: SectionObject[] = [ { @@ -510,21 +515,23 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro confirmText={translate('workspace.moreFeatures.connectionsWarningModal.manageSettings')} cancelText={translate('common.cancel')} /> - { - if (!policyID) { - return; - } - setIsReceiptPartnersWarningModalOpen(false); - // TODO: Navigate to Receipt Partners settings page when it exists - // Navigation.navigate(ROUTES.POLICY_RECEIPT_PARTNERS.getRoute(policyID)); - }} - isVisible={isReceiptPartnersWarningModalOpen} - prompt={translate('workspace.moreFeatures.receiptPartnersWarningModal.disconnectText')} - confirmText={translate('workspace.moreFeatures.receiptPartnersWarningModal.confirmText')} - shouldShowCancelButton={false} - /> + {isBetaEnabled(CONST.BETAS.UBER_FOR_BUSINESS) && ( + { + if (!policyID) { + return; + } + setIsReceiptPartnersWarningModalOpen(false); + // TODO: Navigate to Receipt Partners settings page when it exists + // Navigation.navigate(ROUTES.POLICY_RECEIPT_PARTNERS.getRoute(policyID)); + }} + isVisible={isReceiptPartnersWarningModalOpen} + prompt={translate('workspace.moreFeatures.receiptPartnersWarningModal.disconnectText')} + confirmText={translate('workspace.moreFeatures.receiptPartnersWarningModal.confirmText')} + shouldShowCancelButton={false} + /> + )} Date: Wed, 6 Aug 2025 18:16:58 +0200 Subject: [PATCH 11/12] Update assets/images/simple-illustrations/simple-illustration__receipt.svg Co-authored-by: dukenv0307 <129500732+dukenv0307@users.noreply.github.com> --- .../simple-illustrations/simple-illustration__receipt.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/images/simple-illustrations/simple-illustration__receipt.svg b/assets/images/simple-illustrations/simple-illustration__receipt.svg index 9920d0d1c770..b241dd2ea501 100644 --- a/assets/images/simple-illustrations/simple-illustration__receipt.svg +++ b/assets/images/simple-illustrations/simple-illustration__receipt.svg @@ -1,4 +1,4 @@ - + From c0870db96e1c41ff1198ed72c5bae0c5317ae74a Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Thu, 7 Aug 2025 15:21:48 +0200 Subject: [PATCH 12/12] updates --- src/pages/workspace/WorkspaceInitialPage.tsx | 5 +++-- src/pages/workspace/WorkspaceMoreFeaturesPage.tsx | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/workspace/WorkspaceInitialPage.tsx b/src/pages/workspace/WorkspaceInitialPage.tsx index 14f10da0ea59..4794e31053af 100644 --- a/src/pages/workspace/WorkspaceInitialPage.tsx +++ b/src/pages/workspace/WorkspaceInitialPage.tsx @@ -125,6 +125,7 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac const {shouldUseNarrowLayout} = useResponsiveLayout(); const {translate} = useLocalize(); const {isBetaEnabled} = usePermissions(); + const isUberForBusinessEnabled = isBetaEnabled(CONST.BETAS.UBER_FOR_BUSINESS); const {isOffline} = useNetwork(); const wasRendered = useRef(false); const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: true}); @@ -148,9 +149,9 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac [CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED]: policy?.areRulesEnabled, [CONST.POLICY.MORE_FEATURES.ARE_INVOICES_ENABLED]: policy?.areInvoicesEnabled, [CONST.POLICY.MORE_FEATURES.ARE_PER_DIEM_RATES_ENABLED]: policy?.arePerDiemRatesEnabled, - [CONST.POLICY.MORE_FEATURES.ARE_RECEIPT_PARTNERS_ENABLED]: isBetaEnabled(CONST.BETAS.UBER_FOR_BUSINESS) && (policy?.areReceiptPartnersEnabled ?? false), + [CONST.POLICY.MORE_FEATURES.ARE_RECEIPT_PARTNERS_ENABLED]: isUberForBusinessEnabled && (policy?.areReceiptPartnersEnabled ?? false), }), - [policy, isBetaEnabled], + [policy, isUberForBusinessEnabled], ) as PolicyFeatureStates; const fetchPolicyData = useCallback(() => { diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx index dabe976c6ed5..3bbdc1e776f4 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx @@ -328,8 +328,7 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro isActive: policy?.areReceiptPartnersEnabled ?? false, pendingAction: policy?.pendingFields?.areReceiptPartnersEnabled, disabledAction: () => { - // TODO: When Uber integration is added, check if any integration exists - // and show the warning modal to disconnect integration first + // TODO: When Uber integration is added, check if any integration exists if(!hasReceiptPartnersIntegration) return; setIsReceiptPartnersWarningModalOpen(true); }, action: (isEnabled: boolean) => {