Skip to content

Allow linking an existing card feed to a non-USD workspace - #98509

Merged
chuckdries merged 18 commits into
mainfrom
claude-allowLinkFeedNonUsdWorkspace
Aug 27, 2026
Merged

Allow linking an existing card feed to a non-USD workspace#98509
chuckdries merged 18 commits into
mainfrom
claude-allowLinkFeedNonUsdWorkspace

Conversation

@MelvinBot

@MelvinBot MelvinBot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

We only allow onboarding for Expensify card in workspaces that use one of our supported currencies: USD, GBP, EUR. But, if you already have an active E-card feed on a different workspace, you're supposed to be able to link that feed to a workspace of any currency. This PR allows that. It all already worked, but you used to have to set it up on OldDot.

This change skips the currency prompt when the workspace has accessible feeds (hasAccessibleFeeds). In that case the CTA calls startFlow() directly, which already routes to the feed selector so the admin can link an existing feed.

  • In this case, the feed selector hides the button that would normally initiate onboarding a new feed.
  • The currency prompt still applies to the brand-new-program path (no accessible feeds).

The currency prompt now opens the currency page

The prompt used to switch the workspace to USD directly. It now sends the user to the workspace currency page, so they can pick any supported currency. If an open or partially set up bank account blocks that page, the modal becomes acknowledge-only.

Access to the new-program path

Enrolling a new card program needs workspace admin access, because the bank account setup page and the workspace currency page are both admin only. A member who can write Expensify Card without that access, such as a Card Admin on a Control workspace, can only link an existing feed. With no feed to link, the CTA is dimmed and opens the read-only modal.

Currency prompt copy

The prompt names only the currencies the user can actually choose. GBP and EUR need the expensifyCardEuUk beta, so a user without the beta sees USD only. The copy branches on the beta rather than on isUkEuCurrencySupported, because that flag is always false while the prompt is open. The prompt only opens when the workspace currency is not already a supported one.

Fixed Issues

$ #98503
PROPOSAL: #98503 (comment)

Tests

Enrolling is disallowed on unsupported currencies

  1. On an account with no workspaces, create a workspace on an unsupported currency (CAD, AUD, etc)
  2. Enable Expensify Card under More features
  3. Go to Expensify Card > Issue new card
  4. Verify that you see the USD modal
disallows.enrolling.fresh.on.unsupported.currency.mp4

Linking a USD feed is allowed from a non-USD workspace

  1. Start with an account that is an admin on a workspace with an existing Expensify card feed
  2. Create a new workspace on an unsupported currency (CAD, AUD, etc)
  3. Enable Expensify Card under More features
  4. Go to Expensify Card > Issue new card
  5. Verify that you see the "Select cards" right hand pane, and it lists the USD workspace
  6. Verify that you do not see the entry with the + icon (which would normally let you set up a new feed)
allows.linking.existing.USD.feed.mp4

USD workspaces are allowed to link an existing feed and set up a new one

  1. Start with an account that is an admin on a workspace with an existing Expensify card feed
  2. Create a new USD workspace
  3. Enable Expensify Card under More features
  4. Go to Expensify Card > Issue new card
  5. Verify that you see the "Select cards" right hand pane, and it lists the existing card USD workspace
  6. Verify that you do see the entry with the + icon, and pressing it takes you to the bank account setup flow
allows.setting.up.new.USD.feed.mp4
  • Verify that no errors appear in the JS console

Offline tests

N/A

QA Steps

Same as tests

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

See tests

Co-authored-by: Chuck Dries <chuckdries@users.noreply.github.com>
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ Changes either increased or maintained existing code coverage, great job!

Files with missing lines Coverage Δ
src/hooks/useCanEnrollNewExpensifyCardProgram.ts 0.00% <0.00%> (ø)
...ifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx 0.00% <0.00%> (ø)
...nsifyCard/WorkspaceExpensifyCardPageEmptyState.tsx 0.00% <0.00%> (ø)
... and 242 files with indirect coverage changes

@MelvinBot

This comment was marked as resolved.

@MelvinBot

This comment was marked as resolved.

…elector

Co-authored-by: Chuck Dries <chuckdries@users.noreply.github.com>
@MelvinBot

This comment was marked as resolved.

@MelvinBot

This comment was marked as resolved.

@chuckdries
chuckdries marked this pull request as ready for review August 13, 2026 16:00
@chuckdries
chuckdries requested a review from a team as a code owner August 13, 2026 16:00
@melvin-bot
melvin-bot Bot requested review from Eskalifer1 and removed request for a team August 13, 2026 16:00
@melvin-bot

melvin-bot Bot commented Aug 13, 2026

Copy link
Copy Markdown

@Eskalifer1 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot
melvin-bot Bot requested review from trjExpensify and removed request for a team August 13, 2026 16:00
@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 No code fix needed — all real checks now pass.

When the request came in, several checks were still running (the Android builds, perf tests) and the PR Author Checklist / checklist and independent-approval checks were red. I waited for everything to resolve. The builds, perf tests, and checklist have all since gone green.

The only remaining failing check is Check independent approval, which fails at its Verify peer review step. This isn't a code failure — it just enforces that the PR has an independent reviewer approval, which it doesn't have yet. It will clear on its own once a reviewer approves.

Nothing to push here. Once you've filled out the Tests/QA sections and a reviewer approves, this PR should be all green.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

🤖 Still nothing to push here — no code failure to fix.

I re-checked all checks: every build, test, perf, and checklist check passes. The only remaining red check is Check independent approval, which fails at its Verify peer review step. That's not a code issue — it just requires an independent reviewer approval, which the PR doesn't have yet. It'll clear on its own once someone reviews and approves.

This PR needs a human reviewer, not a code change.

@Eskalifer1

Copy link
Copy Markdown
Contributor

I will review it today!

trjExpensify
trjExpensify previously approved these changes Aug 13, 2026

@trjExpensify trjExpensify left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

conflict, @chuckdries. Looks great though.. thanks for the quick work. 👍

@Eskalifer1

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4f8f9c3aa6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

if (!(policy?.outputCurrency === CONST.CURRENCY.USD || isUkEuCurrencySupported)) {
// The supported currency restriction only applies to enrolling a brand-new card program.
// If hasAccessibleFeeds is true, allow the flow to start in order to link an existing feed
if (!hasAccessibleFeeds && !(policy?.outputCurrency === CONST.CURRENCY.USD || isUkEuCurrencySupported)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require a linkable feed before bypassing currency prompt

When the only accessible Expensify card feeds are pending deletion, hasAccessibleFeeds is still true even though the selector disables those feeds via isFeedPendingDelete. On an unsupported-currency workspace such as CAD/AUD, this skips the Update-to-USD prompt and opens the selector where no feed can be linked and the new-program CTA is hidden, leaving the admin unable to continue. Please base this bypass on at least one non-deleted/linkable feed, or keep the currency prompt when no usable feed exists.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Frankly this feels like an edge case I'm not particularly worried about. @MelvinBot can you check if the user sees a greyed out entry in the list in this case, or an empty panel, or something else? What happens?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user sees a greyed-out, non-clickable entry in the selector — not an empty panel. It's a dead end, but a visible one.

Walking the code for the exact scenario Codex described (brand-new CAD/AUD workspace, the only accessible feed is pending deletion on another workspace):

  • hasAccessibleFeeds is true, so the currency prompt is skipped and startFlow() opens the "Select cards" pane.
  • The pending-delete feed isn't linked to this new workspace, so it lands in otherFeeds and renders under the "From other workspaces" heading.
  • toListItem sets isDisabled: isFeedPendingDelete, so the row shows the feed name + card icon but is greyed out and can't be tapped.
  • Because primaryFeeds is empty and the currency is unsupported, shouldShowIssueCardButton is false, so the + "set up new feed" button is also hidden.

So the admin lands on a pane with a header, the "From other workspaces" label, and a single disabled row — nothing they can click. No blank/empty panel, no crash, no error toast; just a greyed row with no way forward.

One nuance: if that pending-delete feed happened to already be linked to this workspace (i.e. it's a primaryFeed), it renders greyed-out in the main list instead, and issueCardFundID would resolve to it, so an "Issue card" button would appear — but it points at the feed being deleted. In the fresh-workspace case Codex flagged, though, it's the "other workspaces" greyed-row path above.

Derived from reading the code on this branch (4f8f9c3) rather than a live repro — the pendingAction: DELETE feed state is transient and impractical to stage reliably. Happy to dig further if you want a runtime confirmation.

@chuckdries
chuckdries requested a review from a team as a code owner August 13, 2026 20:08
@melvin-bot
melvin-bot Bot requested review from chuckdries and suneox and removed request for a team August 13, 2026 20:09
@MelvinBot

This comment was marked as duplicate.

@MelvinBot

This comment was marked as duplicate.

@OSBotify

Copy link
Copy Markdown
Contributor

🦜 Polyglot Parrot! 🦜

Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues:

View the translation diff
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 2e473fdd..577eecb6 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -7234,9 +7234,10 @@ Der Control-Tarif beginnt bei 9 $ pro aktivem Mitglied und Monat.`,
             yourWorkspace: `Dein Arbeitsbereich ist auf eine nicht unterstützte Währung eingestellt. Sieh dir die <a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">Liste der unterstützten Währungen</a> an.`,
             chooseAnExisting: 'Wähle ein bestehendes Bankkonto zum Bezahlen von Ausgaben oder füge ein neues hinzu.',
             changeBankAccount: 'Bankkonto ändern',
-            updateCurrencyForExpensifyCard:
-                'Die Expensify Karte kann in USD, GBP und EUR ausgegeben werden. Aktualisiere diesen Arbeitsbereich auf eine unterstützte Währung oder verwende einen anderen Arbeitsbereich.',
-            updateCurrencyForExpensifyCardTitle: 'Holen Sie sich die Expensify Karte',
+            updateCurrencyForExpensifyCard: 'Die Expensify Karte kann in USD ausgegeben werden. Bitte aktualisieren Sie diesen Workspace auf USD oder verwenden Sie einen anderen Workspace.',
+            updateCurrencyForExpensifyCardTitle: 'Expensify Karte bestellen',
+            euUkUpdateCurrencyForExpensifyCard:
+                'Die Expensify Karte kann in USD, GBP und EUR ausgestellt werden. Bitte aktualisieren Sie diesen Workspace auf eine unterstützte Währung oder verwenden Sie einen anderen Workspace.',
         },
         changeOwner: {
             changeOwnerPageTitle: 'Besitz übertragen',
diff --git a/src/languages/el.ts b/src/languages/el.ts
index e47a9def..46715d6c 100644
--- a/src/languages/el.ts
+++ b/src/languages/el.ts
@@ -7493,9 +7493,10 @@ _Για πιο αναλυτικές οδηγίες, [επισκεφθείτε τ
             notAllowedToAddBankAccount:
                 'Ο χώρος εργασίας σας είναι ρυθμισμένος σε μη υποστηριζόμενο νόμισμα. Επικοινωνήστε με έναν διαχειριστή χώρου εργασίας που έχει δικαίωμα να το αλλάξει.',
             changeBankAccount: 'Αλλαγή τραπεζικού λογαριασμού',
-            updateCurrencyForExpensifyCard:
-                'Η κάρτα Expensify μπορεί να εκδοθεί σε USD, GBP και EUR. Ενημερώστε αυτόν τον χώρο εργασίας σε υποστηριζόμενο νόμισμα ή χρησιμοποιήστε έναν διαφορετικό χώρο εργασίας.',
-            updateCurrencyForExpensifyCardTitle: 'Αποκτήστε την κάρτα Expensify',
+            updateCurrencyForExpensifyCard: 'Η Κάρτα Expensify είναι διαθέσιμη για έκδοση σε USD. Ενημερώστε αυτόν τον χώρο εργασίας σε USD ή χρησιμοποιήστε έναν διαφορετικό χώρο εργασίας.',
+            updateCurrencyForExpensifyCardTitle: 'Αποκτήστε την Κάρτα Expensify',
+            euUkUpdateCurrencyForExpensifyCard:
+                'Η Κάρτα Expensify είναι διαθέσιμη για έκδοση σε USD, GBP και EUR. Ενημερώστε αυτόν τον χώρο εργασίας σε ένα υποστηριζόμενο νόμισμα ή χρησιμοποιήστε έναν διαφορετικό χώρο εργασίας.',
         },
         changeOwner: {
             changeOwnerPageTitle: 'Μεταφορά ιδιοκτήτη',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index da43b598..53562e35 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7199,8 +7199,11 @@ El plan Controlar empieza en 9 $ por miembro activo al mes.`,
             yourWorkspace: `Tu espacio de trabajo está configurado en una moneda no soportada. Consulta la <a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">lista de monedas soportadas</a>.`,
             chooseAnExisting: 'Elige una cuenta bancaria existente para pagar gastos o añade una nueva.',
             changeBankAccount: 'Cambiar cuenta bancaria',
-            updateCurrencyForExpensifyCard: 'La Tarjeta Expensify se puede emitir en USD, GBP y EUR. Actualiza este espacio de trabajo a una moneda soportada o usa otro espacio de trabajo.',
+            updateCurrencyForExpensifyCard:
+                'La Tarjeta Expensify está disponible para emitirse en USD. Por favor, actualiza este espacio de trabajo a USD o usa un espacio de trabajo diferente.',
             updateCurrencyForExpensifyCardTitle: 'Consigue la Tarjeta Expensify',
+            euUkUpdateCurrencyForExpensifyCard:
+                'La Tarjeta Expensify está disponible para emitirse en USD, GBP y EUR. Actualiza este espacio de trabajo a una moneda compatible o utiliza un espacio de trabajo diferente.',
         },
         changeOwner: {
             changeOwnerPageTitle: 'Transferir la propiedad',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index c6485db0..23138fb6 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -7258,8 +7258,10 @@ Le forfait Control commence à 9 $ par Membre actif et par mois.`,
             chooseAnExisting: 'Choisissez un compte bancaire existant pour payer les dépenses ou ajoutez-en un nouveau.',
             changeBankAccount: 'Changer de compte bancaire',
             updateCurrencyForExpensifyCard:
-                'La Carte Expensify peut être émise en USD, GBP et EUR. Mettez à jour cet espace de travail vers une devise prise en charge ou utilisez un autre espace de travail.',
-            updateCurrencyForExpensifyCardTitle: 'Obtenez la Carte Expensify',
+                "La Carte Expensify est disponible à l'émission en USD. Veuillez mettre à jour cet espace de travail en USD ou utiliser un autre espace de travail.",
+            updateCurrencyForExpensifyCardTitle: 'Obtenir la Carte Expensify',
+            euUkUpdateCurrencyForExpensifyCard:
+                'La Carte Expensify peut être émise en USD, GBP et EUR. Veuillez mettre à jour cet espace de travail vers une devise prise en charge ou utiliser un autre espace de travail.',
         },
         changeOwner: {
             changeOwnerPageTitle: 'Transférer le responsable',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 80edbb1a..c8884688 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -7202,9 +7202,9 @@ Il piano Control parte da 9 $ al mese per ogni membro attivo.`,
             yourWorkspace: `La tua area di lavoro è impostata su una valuta non supportata. Visualizza l’<a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">elenco delle valute supportate</a>.`,
             chooseAnExisting: 'Scegli un conto bancario esistente per pagare le spese oppure aggiungine uno nuovo.',
             changeBankAccount: 'Cambia conto bancario',
-            updateCurrencyForExpensifyCard:
-                'La Carta Expensify può essere emessa in USD, GBP ed EUR. Aggiorna questo spazio di lavoro a una valuta supportata oppure usa un altro spazio di lavoro.',
+            updateCurrencyForExpensifyCard: 'La Carta Expensify è disponibile per l’emissione in USD. Aggiorna questo workspace in USD oppure usa un altro workspace.',
             updateCurrencyForExpensifyCardTitle: 'Ottieni la Carta Expensify',
+            euUkUpdateCurrencyForExpensifyCard: 'La Carta Expensify è disponibile in USD, GBP ed EUR. Aggiorna questo workspace a una valuta supportata oppure usa un altro workspace.',
         },
         changeOwner: {
             changeOwnerPageTitle: 'Trasferisci proprietario',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 6db396c3..aec7a870 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -7116,8 +7116,9 @@ Control プランは、アクティブメンバー1人あたり月額 $9 から
             yourWorkspace: `ご利用のワークスペースはサポートされていない通貨に設定されています。<a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">サポートされている通貨の一覧</a>を表示します。`,
             chooseAnExisting: '既存の銀行口座を選択して経費を支払うか、新しい口座を追加してください。',
             changeBankAccount: '銀行口座を変更',
-            updateCurrencyForExpensifyCard: 'Expensify カードは USD、GBP、EUR で発行できます。このワークスペースをサポートされている通貨に更新するか、別のワークスペースをご利用ください。',
-            updateCurrencyForExpensifyCardTitle: 'Expensify カードを取得する',
+            updateCurrencyForExpensifyCard: 'Expensify カードは USD でのみ発行できます。このワークスペースを USD に更新するか、別のワークスペースをご利用ください。',
+            updateCurrencyForExpensifyCardTitle: 'Expensify カードを申し込む',
+            euUkUpdateCurrencyForExpensifyCard: 'Expensify カードは USD、GBP、EUR で発行できます。このワークスペースを対応している通貨に更新するか、別のワークスペースを使用してください。',
         },
         changeOwner: {
             changeOwnerPageTitle: '所有者を変更',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 9982844a..f3e6b052 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -7186,9 +7186,10 @@ Het Control-abonnement begint bij $9 per actieve deelnemer per maand.`,
             yourWorkspace: `Je werkruimte is ingesteld op een niet-ondersteunde valuta. Bekijk de <a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">lijst met ondersteunde valuta's</a>.`,
             chooseAnExisting: 'Kies een bestaande bankrekening om onkosten te betalen of voeg een nieuwe toe.',
             changeBankAccount: 'Bankrekening wijzigen',
-            updateCurrencyForExpensifyCard:
+            updateCurrencyForExpensifyCard: 'De Expensify Kaart kan alleen in USD worden uitgegeven. Werk deze workspace bij naar USD of gebruik een andere workspace.',
+            updateCurrencyForExpensifyCardTitle: 'Vraag de Expensify Kaart aan',
+            euUkUpdateCurrencyForExpensifyCard:
                 'De Expensify Kaart kan worden uitgegeven in USD, GBP en EUR. Werk deze werkruimte bij naar een ondersteunde valuta of gebruik een andere werkruimte.',
-            updateCurrencyForExpensifyCardTitle: 'Ontvang de Expensify Kaart',
         },
         changeOwner: {
             changeOwnerPageTitle: 'Eigenaar overdragen',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index e9c5d041..be534d5c 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -7167,8 +7167,9 @@ Plan Control zaczyna się od 9 USD za aktywnego członka miesięcznie.`,
             yourWorkspace: `Twoje miejsce pracy jest ustawione na nieobsługiwaną walutę. Zobacz <a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">listę obsługiwanych walut</a>.`,
             chooseAnExisting: 'Wybierz istniejące konto bankowe do opłacania wydatków lub dodaj nowe.',
             changeBankAccount: 'Zmień konto bankowe',
-            updateCurrencyForExpensifyCard: 'Kartę Expensify można wydać w USD, GBP i EUR. Zmień walutę tej przestrzeni roboczej na obsługiwaną albo użyj innej przestrzeni roboczej.',
+            updateCurrencyForExpensifyCard: 'Karta Expensify jest dostępna do wydania w USD. Zmień tę przestrzeń roboczą na USD lub użyj innej przestrzeni roboczej.',
             updateCurrencyForExpensifyCardTitle: 'Zdobądź Kartę Expensify',
+            euUkUpdateCurrencyForExpensifyCard: 'Karta Expensify jest dostępna do wydania w USD, GBP i EUR. Zmień walutę tego workspace’a na obsługiwaną albo użyj innego workspace’a.',
         },
         changeOwner: {
             changeOwnerPageTitle: 'Przenieś właściciela',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index a58b8163..06b34ee6 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -7188,8 +7188,10 @@ O plano Control começa em US$ 9 por membro ativo por mês.`,
             yourWorkspace: `Seu workspace está configurado para uma moeda não compatível. Veja a <a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">lista de moedas compatíveis</a>.`,
             chooseAnExisting: 'Escolha uma conta bancária existente para pagar despesas ou adicione uma nova.',
             changeBankAccount: 'Alterar conta bancária',
-            updateCurrencyForExpensifyCard: 'O Cartão Expensify pode ser emitido em USD, GBP e EUR. Atualize este workspace para uma moeda compatível ou use outro workspace.',
-            updateCurrencyForExpensifyCardTitle: 'Obtenha o Cartão Expensify',
+            updateCurrencyForExpensifyCard: 'O Cartão Expensify está disponível para emissão em USD. Atualize este workspace para USD ou use um workspace diferente.',
+            updateCurrencyForExpensifyCardTitle: 'Obter o Cartão Expensify',
+            euUkUpdateCurrencyForExpensifyCard:
+                'O Cartão Expensify está disponível para emissão em USD, GBP e EUR. Atualize este espaço de trabalho para uma moeda compatível ou use um espaço de trabalho diferente.',
         },
         changeOwner: {
             changeOwnerPageTitle: 'Transferir proprietário',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 5bd3d9bf..2c6a2a50 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -6944,8 +6944,9 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
             yourWorkspace: `您的工作区当前使用不受支持的货币。请查看<a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">支持的货币列表</a>。`,
             chooseAnExisting: '选择现有银行账户来支付报销,或添加新账户。',
             changeBankAccount: '更改银行账户',
-            updateCurrencyForExpensifyCard: 'Expensify 卡可以以美元、英镑和欧元发行。请将此工作区更新为受支持的货币,或使用其他工作区。',
+            updateCurrencyForExpensifyCard: 'Expensify 卡目前仅支持以美元(USD)发行。请将此工作区的货币更新为美元(USD),或使用其他工作区。',
             updateCurrencyForExpensifyCardTitle: '获取 Expensify 卡',
+            euUkUpdateCurrencyForExpensifyCard: 'Expensify 卡目前可发行的货币包括 USD、GBP 和 EUR。请将此工作区更新为受支持的货币或使用其他工作区。',
         },
         changeOwner: {
             changeOwnerPageTitle: '转移所有者',

Note

You can apply these changes to your branch by copying the patch to your clipboard, then running pbpaste | git apply 😉

View workflow run

@MelvinBot

This comment was marked as duplicate.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

👋 chuckdries — still nothing to push. The only remaining failing check is Check independent approval, which is a process gate, not a code failure — it stays red until the PR gets an independent reviewer approval. (The PR Reviewer Checklist / checklist that was failing earlier has since passed.)

All code/build/test checks are green. This last one clears once a reviewer approves — no author action or code change required.


view run

@Eskalifer1

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 97e3cc9252

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@Eskalifer1 Eskalifer1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any problems for now(except the one we will follow-up), so LGTM!


// Suppress the new-program branch on workspaces with unsupported currencies, and for members who cannot
// reach the bank account setup page. These workspaces may only issue cards on existing feeds
const shouldShowIssueCardButton = hasIssueCardFundID || (canEnrollNewCardProgram && canStartBankAccountSetup);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAB: !hasAccessibleFeeds && !canEditSettings is written out twice: once in shouldDisableCTA and once in onCtaPress. Since the first only controls opacity and the second does the actual blocking, they have to stay in sync by hand, and a future edit to one of them will silently desync the styling from the behavior.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oooh good call. I realized we can collapse the two showReadOnlyModal paths in onCtaPress to just one to simplify as well

@MelvinBot

This comment was marked as duplicate.

@chuckdries
chuckdries requested a review from a team August 24, 2026 16:45
@melvin-bot
melvin-bot Bot requested a review from Eskalifer1 August 24, 2026 16:45
@melvin-bot

melvin-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown

@Eskalifer1 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot
melvin-bot Bot removed the request for review from a team August 24, 2026 16:45
@chuckdries

Copy link
Copy Markdown
Contributor

Hmmm, @Eskalifer1 already posted a checklist here... I'll ask around for an internal engineer to review

@Julesssss Julesssss left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No additional feedback from me here

@chuckdries
chuckdries merged commit 64ad449 into main Aug 27, 2026
46 of 48 checks passed
@chuckdries
chuckdries deleted the claude-allowLinkFeedNonUsdWorkspace branch August 27, 2026 00:26
@github-actions

Copy link
Copy Markdown
Contributor

🚧 chuckdries has triggered a test Expensify/App build. You can view the workflow run here.

@OSBotify

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to staging by https://github.com/chuckdries in version: 9.4.63-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Help site review — changes required ✅

This PR introduces a new customer-facing capability: an admin can now link an existing Expensify Card feed to a workspace on any currency (not just USD). The supported-currency requirement now only applies when enrolling a brand-new card program, and the currency prompt sends the user to the workspace currency page instead of force-switching to USD.

The published guide Set Up and Manage the Expensify Card in the US already covered linking an existing feed across workspaces, but did not clarify that this works on a non-USD workspace — and its framing implies a supported currency is always required. That gap warranted an update.

Draft help site PR: #99706

What it changes:

  • Expands the "Select a Bank Account" step to note that linking an existing feed works even when the workspace uses a non-USD currency.
  • Adds an FAQ entry: Can I link an existing card feed to a workspace that isn't set to USD?
Notes on scope & UI terminology
  • Only docs/articles is touched; no product/code changes.
  • The remaining behavior changes in this PR (currency prompt now routing to the currency page, admin-vs-Card-Admin access gating, beta-dependent copy branching) are in-flow UI states the guide does not document step-by-step, so they don't require separate article edits.
  • Button/feature labels reused (Issue new card, Expensify Card, More features, Settings > Workspaces) are unchanged from the currently published guide, so no new UI labels were introduced and no live-UI relabeling was needed.

@chuckdries, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR Ready for review


view run

@mitarachim

Copy link
Copy Markdown

Deploy Blocker #99723 was identified to be related to this PR.

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/AndrewGable in version: 9.4.63-1 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

Bundle Size Analysis (Sentry):

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants