Skip to content

[HOLD][No QA] CTB net-30 implementation#96146

Open
blimpich wants to merge 12 commits into
mainfrom
blimpich-ctbDepositOnlyTravelBilling
Open

[HOLD][No QA] CTB net-30 implementation#96146
blimpich wants to merge 12 commits into
mainfrom
blimpich-ctbDepositOnlyTravelBilling

Conversation

@blimpich

@blimpich blimpich commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

Part of the Consolidated Travel Billing pay-by-invoice project (plan in the linked issue). A small set of covenant customers can't be auto-debited for their monthly travel spend: they settle from a deposit-only bank account by paying an invoice by wire.

Split note: making deposit-only settlement accounts selectable was moved to its own PR — App #96997. This PR is now just the pay-by-invoice billing UI.

Two UI changes, both inert until the backend enables them (keyed off invoiceTo in the workspace's travel settings, the client-visible pay-by-invoice hint):

  1. "Pay balance" becomes "Send invoice now" (with matching confirmation copy) for pay-by-invoice customers, since pressing it creates an invoice for their current travel spend instead of queueing a bank debit.
  2. Pending-invoice status: once an invoice has been sent and is awaiting payment, the travel section shows an "awaiting payment" row for the outstanding amount, the pay button is suppressed while an invoice covers the spend, and an unpaid invoice keeps hasOutstandingTravelBalance true so Consolidated Travel Billing can't be disabled with money still owed.

Fixed Issues

https://github.com/Expensify/Expensify/issues/657008 (partial — App portion; intentionally not using $ so the issue doesn't auto-close)
PROPOSAL:

Tests

Requires a dev backend with the Auth/Web pay-by-invoice changes.

  1. Set invoiceTo in the workspace's TRAVEL_US card settings (pay-by-invoice config).
  2. Open the workspace's Travel settings.
  3. With unbilled travel spend, verify the "Pay balance" button reads "Send invoice now" and its confirmation modal uses the send-invoice copy.
  4. Simulate a sent invoice (pendingInvoiceAmount set) and verify the section shows an "awaiting payment" row for that amount and the pay button is hidden.
  5. With an unpaid invoice, verify Consolidated Travel Billing can't be disabled.
  6. Clear invoiceTo and verify the button reverts to "Pay balance" with the original modal copy.
  • Verify that no errors appear in the JS console

Offline tests

  1. Go offline.
  2. Verify the "Send invoice now" button is disabled (same behavior as the existing "Pay balance" button).

QA Steps

None: this UI is gated behind server-side pay-by-invoice configuration (invoiceTo), which doesn't exist on staging yet.

  • 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 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 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

Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari

– written by Claude on Ben's behalf

@blimpich
blimpich requested review from a team as code owners July 14, 2026 23:37
@melvin-bot
melvin-bot Bot requested review from deetergp and flaviadefaria and removed request for a team July 14, 2026 23:37
@melvin-bot

melvin-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown

@deetergp 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]

@OSBotify

This comment has been minimized.

@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: 6acaf3eb1e

ℹ️ 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".

const formattedSpend = convertToDisplayString(travelSpend, CONST.CURRENCY.USD);

// Pay-by-invoice customers settle by wire against an invoice, so the pay CTA and modal use invoice copy
const isPayByInvoice = getIsTravelBillingPayByInvoice(travelSettings);

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 Use invoice copy for pending settlements

When invoiceTo is set, confirming the “Send invoice now” modal still calls payTravelInvoicingSpend, which optimistically sets pendingSettlementAmount; this same component then hides the button and renders the existing currentTravelSpendPaymentQueued subtitle, so invoice customers see “Payment of X is queued and will be processed soon” after sending an invoice. Please apply the pay-by-invoice branch to the pending-settlement subtitle as well so the post-confirmation state does not describe an ACH payment.

Useful? React with 👍 / 👎.

@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

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

Files with missing lines Coverage Δ
src/libs/TravelInvoicingUtils.ts 92.30% <100.00%> (+0.81%) ⬆️
...rkspace/travel/WorkspaceTravelInvoicingSection.tsx 92.00% <100.00%> (+0.38%) ⬆️
... and 195 files with indirect coverage changes

@blimpich

Copy link
Copy Markdown
Contributor Author

@flaviadefaria @deetergp please ignore the ping, this is a WIP PR

@OSBotify

This comment has been minimized.

blimpich added 5 commits July 15, 2026 16:02
…lyTravelBilling

# Conflicts:
#	src/pages/workspace/travel/WorkspaceTravelInvoicingSection.tsx
…ware visibility check

The pay-by-invoice CTA text was silently dropped due to a nonexistent
Button prop, always rendering "Pay balance" instead of "Send invoice
now". The button's visibility check also ignored pendingInvoiceAmount,
showing it even when there was no new spend beyond an invoice already
sent and awaiting payment.
…-by-invoice workspaces

Queuing an early bill via "Send invoice now" reused the same
"Payment is queued" copy as ACH settlement, which is misleading since
no automatic debit happens for pay-by-invoice customers.
Translation bot handles non-English locale files; only en.ts should
be edited by hand.
@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 85f68ad8b9c..30d9ad5b54b 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -6071,8 +6071,8 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                         subsections: {
                             currentTravelSpendLabel: 'Aktuelle Reisekosten',
                             currentTravelSpendPaymentQueued: (amount: string) => `Die Zahlung über ${amount} ist in der Warteschlange und wird in Kürze bearbeitet.`,
-                            currentTravelSpendInvoiceQueued: 'Eine neue Rechnung für Ihre Reisekosten wird erstellt und Ihnen in Kürze zugesendet.',
-                            currentTravelSpendInvoicePending: (amount: string) => `Eine Rechnung über ${amount} wurde gesendet und wartet auf Zahlung.`,
+                            currentTravelSpendInvoiceQueued: 'Eine neue Rechnung für Ihre Reisekosten wird erstellt und Ihnen in Kürze zugesandt.',
+                            currentTravelSpendInvoicePending: (amount: string) => `Eine Rechnung über ${amount} wurde gesendet und wartet auf Bezahlung.`,
                             currentTravelSpendCta: 'Saldo bezahlen',
                             currentTravelLimitLabel: 'Aktuelles Reisekontingent',
                             settlementAccountLabel: 'Verrechnungskonto',
@@ -6110,9 +6110,9 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                     enabledDescription: 'Alle Reisekosten in diesem Workspace werden nun in einer monatlichen Rechnung zentralisiert.',
                     sendInvoiceModal: {
                         title: (amount: string) => `Rechnung über ${amount} senden?`,
-                        body: 'Wir erstellen eine Rechnung für Ihre aktuellen Reisekosten. Ihr Reisebudget wird wieder freigegeben, sobald die Rechnung bezahlt ist.',
+                        body: 'Wir erstellen eine Rechnung für Ihre aktuellen Reisekosten. Ihr Reiselimit wird wieder frei, sobald die Rechnung bezahlt ist.',
                     },
-                    depositOnly: 'Nur Einzahlung',
+                    depositOnly: 'Nur Einzahlungen',
                 },
                 personalDetailsDescription: 'Um eine Reise zu buchen, gib bitte deinen amtlichen Namen genau so ein, wie er auf deinem amtlichen Ausweis steht.',
             },
diff --git a/src/languages/es.ts b/src/languages/es.ts
index c3e4a8892a0..8061810bca0 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -5904,7 +5904,7 @@ ${amount} para ${merchant} - ${date}`,
                         subsections: {
                             currentTravelSpendLabel: 'Gasto actual en viajes',
                             currentTravelSpendPaymentQueued: (amount: string) => `El pago de ${amount} está en cola y se procesará pronto.`,
-                            currentTravelSpendInvoiceQueued: 'Se creará y enviará pronto una nueva factura por tu gasto de viaje.',
+                            currentTravelSpendInvoiceQueued: 'Pronto se creará y enviará una nueva factura por tus gastos de viaje.',
                             currentTravelSpendInvoicePending: (amount: string) => `Se ha enviado una factura por ${amount} y está a la espera de pago.`,
                             currentTravelSpendCta: 'Pagar saldo',
                             sendInvoiceNowCta: 'Enviar factura ahora',
@@ -5937,7 +5937,7 @@ ${amount} para ${merchant} - ${date}`,
                     },
                     sendInvoiceModal: {
                         title: (amount: string) => `¿Enviar factura por ${amount}?`,
-                        body: 'Crearemos una factura por tus gastos de viaje actuales. Tu límite de viaje se liberará una vez que se pague la factura.',
+                        body: 'Crearemos una factura por tus gastos de viaje actuales. Tu límite de viaje se libera una vez que se pague la factura.',
                     },
                     exportToPDF: 'Exportar a PDF',
                     exportToCSV: 'Exportar a CSV',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index c769f19964e..93a509905a7 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -6130,8 +6130,8 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                     enabled: 'Facturation de voyage consolidée activée !',
                     enabledDescription: 'Toutes les dépenses de voyage sur cet espace de travail seront désormais centralisées dans une facture mensuelle.',
                     sendInvoiceModal: {
-                        title: (amount: string) => `Envoyer la facture pour ${amount} ?`,
-                        body: 'Nous créerons une facture pour vos dépenses de voyage actuelles. Votre plafond de voyage sera à nouveau disponible une fois la facture payée.',
+                        title: (amount: string) => `Envoyer la facture de ${amount} ?`,
+                        body: 'Nous créerons une facture pour vos dépenses de voyage actuelles. Votre plafond de voyage est à nouveau disponible une fois la facture payée.',
                     },
                     depositOnly: 'Dépôt uniquement',
                 },
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 9e21cf9c751..11d9e866c6f 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -6053,7 +6053,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                         subsections: {
                             currentTravelSpendLabel: 'Spesa di viaggio attuale',
                             currentTravelSpendPaymentQueued: (amount: string) => `Il pagamento di ${amount} è in coda e verrà elaborato a breve.`,
-                            currentTravelSpendInvoiceQueued: 'Una nuova fattura per la tua spesa di viaggio verrà creata e inviata a breve.',
+                            currentTravelSpendInvoiceQueued: 'Una nuova fattura per le tue spese di viaggio verrà creata e ti sarà inviata a breve.',
                             currentTravelSpendInvoicePending: (amount: string) => `Una fattura di ${amount} è stata inviata ed è in attesa di pagamento.`,
                             currentTravelSpendCta: 'Paga saldo',
                             currentTravelLimitLabel: 'Limite di viaggio attuale',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 92e886807eb..cdf13e0f50a 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -5982,7 +5982,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                         subsections: {
                             currentTravelSpendLabel: '現在の出張費支出',
                             currentTravelSpendPaymentQueued: (amount: string) => `${amount} の支払いはキューに登録されており、まもなく処理されます。`,
-                            currentTravelSpendInvoiceQueued: '出張費用の新しい請求書がまもなく作成され、送付されます。',
+                            currentTravelSpendInvoiceQueued: '出張費用の新しい請求書が作成され、まもなくお客様に送信されます。',
                             currentTravelSpendInvoicePending: (amount: string) => `${amount} の請求書が送信され、支払い待ちです。`,
                             currentTravelSpendCta: '残高を支払う',
                             currentTravelLimitLabel: '現在の出張上限',
@@ -6015,10 +6015,10 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                     enabled: '一括出張請求が有効になりました!',
                     enabledDescription: 'このワークスペースでの出張費用は、今後すべて月次の請求書に集約されます。',
                     sendInvoiceModal: {
-                        title: (amount: string) => `${amount} の請求書を送信しますか?`,
+                        title: (amount: string) => `${amount}の請求書を送信しますか?`,
                         body: '現在の出張費用について請求書を作成します。請求書が支払われると、出張の利用可能枠が再び使えるようになります。',
                     },
-                    depositOnly: '入金のみ',
+                    depositOnly: '入金専用',
                 },
                 personalDetailsDescription: '旅行を予約するために、政府発行の身分証明書に記載されているとおりの正式な氏名を入力してください。',
             },
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 4eec5156fa5..fbc3d335719 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -6042,7 +6042,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                         subsections: {
                             currentTravelSpendLabel: 'Huidige reiskosten',
                             currentTravelSpendPaymentQueued: (amount: string) => `Betaling van ${amount} staat in de wachtrij en wordt binnenkort verwerkt.`,
-                            currentTravelSpendInvoiceQueued: 'Er wordt binnenkort een nieuwe factuur voor uw reisuitgaven aangemaakt en naar u verzonden.',
+                            currentTravelSpendInvoiceQueued: 'Er wordt binnenkort een nieuwe factuur voor je reiskosten aangemaakt en naar je verzonden.',
                             currentTravelSpendInvoicePending: (amount: string) => `Er is een factuur voor ${amount} verzonden en deze wacht op betaling.`,
                             currentTravelSpendCta: 'Saldo betalen',
                             currentTravelLimitLabel: 'Huidige reisl imiet',
@@ -6055,7 +6055,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                             reduceLimitWarning: 'Als u het limiet verlaagt, kunnen leden die dit bedrag al hebben overschreden geen nieuwe reisboekingen maken tot volgende maand.',
                             provisioningError:
                                 'We konden voor sommige leden van je werkruimte geen toegang instellen tot Geconsolideerde Reisfacturering. Probeer het later opnieuw of neem contact op met Concierge voor ondersteuning.',
-                            sendInvoiceNowCta: 'Factuur nu verzenden',
+                            sendInvoiceNowCta: 'Verzend factuur nu',
                         },
                     },
                     disableModal: {
@@ -6080,7 +6080,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                     enabledDescription: 'Alle reiskosten in deze workspace worden nu gebundeld op één maandelijkse factuur.',
                     sendInvoiceModal: {
                         title: (amount: string) => `Factuur voor ${amount} versturen?`,
-                        body: 'We maken een factuur voor je huidige reiskosten. Je reistegoed komt weer vrij zodra de factuur is betaald.',
+                        body: 'We maken een factuur aan voor je huidige reiskosten. Je reistegoed komt weer vrij zodra de factuur is betaald.',
                     },
                     depositOnly: 'Alleen storting',
                 },
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index ed764b99d87..5f85d843b68 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -6021,7 +6021,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                         subsections: {
                             currentTravelSpendLabel: 'Aktualne wydatki na podróże',
                             currentTravelSpendPaymentQueued: (amount: string) => `Płatność w wysokości ${amount} jest w kolejce i wkrótce zostanie przetworzona.`,
-                            currentTravelSpendInvoiceQueued: 'Wkrótce zostanie utworzona i wysłana do Ciebie nowa faktura za wydatki podróżne.',
+                            currentTravelSpendInvoiceQueued: 'Nowa faktura za twoje wydatki związane z podróżą zostanie wkrótce utworzona i wysłana do ciebie.',
                             currentTravelSpendInvoicePending: (amount: string) => `Faktura na kwotę ${amount} została wysłana i oczekuje na płatność.`,
                             currentTravelSpendCta: 'Spłać saldo',
                             currentTravelLimitLabel: 'Aktualny limit podróży',
@@ -6059,8 +6059,8 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                     enabled: 'Włączono zbiorcze rozliczanie podróży!',
                     enabledDescription: 'Wszystkie wydatki podróżne w tym obszarze roboczym będą teraz scentralizowane na miesięcznym rachunku.',
                     sendInvoiceModal: {
-                        title: (amount: string) => `Wysłać fakturę na kwotę ${amount}?`,
-                        body: 'Utworzymy fakturę za twoje bieżące wydatki na podróż. Twój limit podróży zwolni się, gdy faktura zostanie opłacona.',
+                        title: (amount: string) => `Wysłać fakturę na ${amount}?`,
+                        body: 'Utworzymy fakturę za twoje bieżące wydatki na podróż. Twój limit podróży zostanie zwolniony, gdy faktura zostanie opłacona.',
                     },
                     depositOnly: 'Tylko wpłata',
                 },
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 431b5426f13..da8312a146f 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -6034,7 +6034,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                         subsections: {
                             currentTravelSpendLabel: 'Gasto atual com viagens',
                             currentTravelSpendPaymentQueued: (amount: string) => `O pagamento de ${amount} está na fila e será processado em breve.`,
-                            currentTravelSpendInvoiceQueued: 'Uma nova fatura para o seu gasto de viagem será criada e enviada a você em breve.',
+                            currentTravelSpendInvoiceQueued: 'Uma nova fatura dos seus gastos de viagem será criada e enviada para você em breve.',
                             currentTravelSpendInvoicePending: (amount: string) => `Uma fatura de ${amount} foi enviada e está aguardando pagamento.`,
                             currentTravelSpendCta: 'Pagar saldo',
                             currentTravelLimitLabel: 'Limite de viagem atual',
@@ -6073,7 +6073,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                     enabledDescription: 'Todos os gastos de viagem neste workspace agora serão centralizados em uma fatura mensal.',
                     sendInvoiceModal: {
                         title: (amount: string) => `Enviar fatura de ${amount}?`,
-                        body: 'Vamos criar uma fatura para seus gastos atuais de viagem. Seu limite de viagem é liberado assim que a fatura é paga.',
+                        body: 'Vamos criar uma fatura para seus gastos atuais de viagem. Seu limite de viagem será liberado assim que a fatura for paga.',
                     },
                     depositOnly: 'Apenas depósito',
                 },
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 20533d30b57..0fb5b49e812 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -5854,7 +5854,7 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
                         subsections: {
                             currentTravelSpendLabel: '当前差旅支出',
                             currentTravelSpendPaymentQueued: (amount: string) => `金额为 ${amount} 的付款已排队,稍后将被处理。`,
-                            currentTravelSpendInvoiceQueued: '您差旅支出的新发票即将生成并发送给您。',
+                            currentTravelSpendInvoiceQueued: '您的差旅费用新发票将很快创建并发送给您。',
                             currentTravelSpendInvoicePending: (amount: string) => `金额为 ${amount} 的发票已发送,正在等待付款。`,
                             currentTravelSpendCta: '支付余额',
                             currentTravelLimitLabel: '当前出行限额',
@@ -5878,8 +5878,8 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
                     invalidDateRangeError: '开始日期必须早于结束日期',
                     enabled: '已启用合并差旅账单!',
                     enabledDescription: '此工作区的所有差旅支出现在将统一汇总到一份月度账单中。',
-                    sendInvoiceModal: {title: (amount: string) => `发送金额为 ${amount} 的发票?`, body: '我们会根据你当前的差旅支出创建一张发票。发票支付后,你的差旅额度将被释放。'},
-                    depositOnly: '仅限存款',
+                    sendInvoiceModal: {title: (amount: string) => `要发送金额为 ${amount} 的发票吗?`, body: '我们会为您当前的差旅支出创建一张发票。发票付清后,您的差旅额度将被释放。'},
+                    depositOnly: '仅存款',
                 },
                 personalDetailsDescription: '为预订行程,请输入您在政府签发的身份证件上显示的法定姓名。',
             },

Note

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

View workflow run

@blimpich blimpich changed the title [HOLD][No QA] Show deposit-only settlement accounts and send-invoice copy for Consolidated Travel Billing [HOLD on Auth#22925][No QA] Show send-invoice CTA and pending-invoice status for Consolidated Travel Billing Jul 24, 2026
@blimpich blimpich changed the title [HOLD on Auth#22925][No QA] Show send-invoice CTA and pending-invoice status for Consolidated Travel Billing [HOLD][No QA] CTB net-30 implementation Jul 24, 2026
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.

2 participants