[HOLD][No QA] Show deposit-only settlement accounts and send-invoice copy for Consolidated Travel Billing#96146
[HOLD][No QA] Show deposit-only settlement accounts and send-invoice copy for Consolidated Travel Billing#96146blimpich wants to merge 4 commits into
Conversation
🦜 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 diffdiff --git a/src/languages/de.ts b/src/languages/de.ts
index 6b8c6f2eadb..2fdfbbb3e3e 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -6000,6 +6000,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
'Wenn Sie das Limit reduzieren, können Mitglieder, die diesen Betrag bereits überschritten haben, bis zum nächsten Monat keine neuen Reisebuchungen vornehmen.',
provisioningError:
'Wir konnten einige Mitglieder Ihres Arbeitsbereichs nicht für die Konsolidierte Reiseabrechnung einrichten. Bitte versuchen Sie es später erneut oder wenden Sie sich für Unterstützung an Concierge.',
+ sendInvoiceNowCta: 'Rechnung jetzt senden',
},
},
disableModal: {
@@ -6022,6 +6023,11 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
invalidDateRangeError: 'Das Startdatum muss vor dem Enddatum liegen',
enabled: 'Zentrale Reiseabrechnung aktiviert!',
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 Reisekredit wird wieder verfügbar, sobald die Rechnung bezahlt ist.',
+ },
+ depositOnly: 'Nur Einzahlung',
},
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 81733f0ce8b..966dc62a37f 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -5854,7 +5854,7 @@ ${amount} para ${merchant} - ${date}`,
},
sendInvoiceModal: {
title: (amount: string) => `¿Enviar factura por ${amount}?`,
- body: 'Crearemos una factura por tu gasto de viaje actual. Tu límite de viaje se libera una vez pagada la factura.',
+ body: 'Crearemos una factura por tus gastos de viaje actuales. Tu límite de viaje se liberará 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 2f9ae12fa81..be5399f0da7 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -6022,6 +6022,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
'Si vous réduisez la limite, les membres ayant déjà dépensé plus que ce montant ne pourront pas effectuer de nouvelles réservations de voyage avant le mois prochain.',
provisioningError:
'Nous n’avons pas pu configurer certains membres de votre espace de travail pour la facturation de voyage consolidée. Veuillez réessayer plus tard ou contacter Concierge pour obtenir de l’aide.',
+ sendInvoiceNowCta: 'Envoyer la facture maintenant',
},
},
disableModal: {
@@ -6044,6 +6045,11 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
invalidDateRangeError: 'La date de début doit être antérieure à la date de fin',
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 est à nouveau disponible une fois la facture payée.',
+ },
+ depositOnly: 'Dépôt uniquement',
},
personalDetailsDescription: 'Pour pouvoir réserver un voyage, veuillez saisir votre nom légal tel qu’il apparaît sur votre pièce d’identité délivrée par le gouvernement.',
},
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 6e49ff0d79c..22b9b99b678 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -5988,6 +5988,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
'Se riduci il limite, i membri che hanno già speso più di questo importo non potranno effettuare nuove prenotazioni di viaggio fino al mese prossimo.',
provisioningError:
'Non siamo riusciti a effettuare il provisioning di alcuni membri del tuo workspace per la Fatturazione Viaggi Consolidata. Riprova più tardi oppure contatta Concierge per assistenza.',
+ sendInvoiceNowCta: 'Invia fattura ora',
},
},
disableModal: {
@@ -6010,6 +6011,11 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
invalidDateRangeError: 'La data di inizio deve essere precedente alla data di fine',
enabled: 'Fatturazione viaggio consolidata abilitata!',
enabledDescription: 'Tutte le spese di viaggio in questo spazio di lavoro saranno ora accentrate in una fattura mensile.',
+ sendInvoiceModal: {
+ title: (amount: string) => `Inviare la fattura per ${amount}?`,
+ body: 'Creeremo una fattura per le tue spese di viaggio attuali. Il tuo limite di viaggio si libera una volta pagata la fattura.',
+ },
+ depositOnly: 'Solo deposito',
},
personalDetailsDescription: 'Per prenotare il viaggio, inserisci il tuo nome legale così come appare sul tuo documento d’identità rilasciato dal governo.',
},
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 2bde735c0fe..725cef961c4 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -5911,6 +5911,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
reduceLimitWarning: 'この上限を引き下げると、すでにこの金額を超えて支出しているメンバーは、翌月まで新しい出張予約ができなくなります。',
provisioningError:
'ワークスペース内の一部メンバーに対して、Consolidated Travel Billing を有効化できませんでした。時間をおいてもう一度お試しいただくか、サポートが必要な場合は Concierge までお問い合わせください。',
+ sendInvoiceNowCta: '請求書を今すぐ送信',
},
},
disableModal: {
@@ -5929,6 +5930,11 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
invalidDateRangeError: '開始日は終了日より前でなければなりません',
enabled: '一括出張請求が有効になりました!',
enabledDescription: 'このワークスペースでの出張費用は、今後すべて月次の請求書に集約されます。',
+ sendInvoiceModal: {
+ title: (amount: string) => `${amount}の請求書を送信しますか?`,
+ body: '現在の出張費用に対して請求書を作成します。請求書が支払われると、出張限度額が再び利用可能になります。',
+ },
+ depositOnly: '入金専用',
},
personalDetailsDescription: '旅行を予約するために、政府発行の身分証明書に記載されているとおりの正式な氏名を入力してください。',
},
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 3bf61f9c238..116a69eb051 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -5971,6 +5971,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: 'Verstuur factuur nu',
},
},
disableModal: {
@@ -5993,6 +5994,11 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
invalidDateRangeError: 'De begindatum moet vóór de einddatum liggen',
enabled: 'Geconsolideerde reiskostenfacturatie ingeschakeld!',
enabledDescription: 'Alle reiskosten in deze workspace worden nu gebundeld op één maandelijkse factuur.',
+ sendInvoiceModal: {
+ title: (amount: string) => `Factuur voor ${amount} verzenden?`,
+ body: 'We maken een factuur voor je huidige reiskosten. Je reistegoed komt weer vrij zodra de factuur is betaald.',
+ },
+ depositOnly: 'Alleen stortingen',
},
personalDetailsDescription: 'Om een reis te boeken, voer je wettelijke naam in zoals deze op je door de overheid uitgegeven identiteitsbewijs staat.',
},
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index b4c34c53be2..ef56642d2b8 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -5951,6 +5951,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
'Jeśli zmniejszysz limit, członkowie, którzy już wydali więcej niż ta kwota, nie będą mogli dokonywać nowych rezerwacji podróży do następnego miesiąca.',
provisioningError:
'Nie udało nam się skonfigurować części członków twojego miejsca pracy do skonsolidowanego rozliczania podróży. Spróbuj ponownie później albo skontaktuj się z Concierge, żeby uzyskać pomoc.',
+ sendInvoiceNowCta: 'Wyślij fakturę teraz',
},
},
disableModal: {
@@ -5973,6 +5974,11 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
invalidDateRangeError: 'Data początkowa musi być wcześniejsza niż data końcowa',
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: 'Wystawimy fakturę za Twoje obecne wydatki na podróż. Twój limit na podróże zostanie odblokowany, gdy faktura zostanie opłacona.',
+ },
+ depositOnly: 'Tylko wpłata',
},
personalDetailsDescription: 'Aby zarezerwować podróż, wpisz swoje imię i nazwisko dokładnie tak, jak widnieje w Twoim dokumencie tożsamości wydanym przez organ państwowy.',
},
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 429816f1f13..7465c75d944 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -5964,6 +5964,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
reduceLimitWarning: 'Se você reduzir o limite, os membros que já gastaram mais do que esse valor não poderão fazer novas reservas de viagem até o próximo mês.',
provisioningError:
'Não foi possível provisionar alguns membros do seu workspace para o Faturamento Consolidado de Viagens. Tente novamente mais tarde ou entre em contato com o Concierge para obter ajuda.',
+ sendInvoiceNowCta: 'Enviar fatura agora',
},
},
disableModal: {
@@ -5986,6 +5987,11 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
invalidDateRangeError: 'A data de início deve ser anterior à data de término',
enabled: 'Faturamento de viagem consolidado ativado!',
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 os seus gastos atuais de viagem. Seu limite de viagem será liberado assim que a fatura for paga.',
+ },
+ depositOnly: 'Apenas depósito',
},
personalDetailsDescription: 'Para reservar viagens, insira seu nome legal exatamente como consta no documento de identificação emitido pelo governo.',
},
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 286066528d3..13427ad21df 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -5797,6 +5797,7 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
reduceLimitTitle: '降低出差支出限额?',
reduceLimitWarning: '如果您降低限额,已超出该金额的成员将无法进行新的出差预订,直至下个月。',
provisioningError: '我们无法为您的工作区中部分成员开通合并差旅结算功能。请稍后重试,或联系 Concierge 获取帮助。',
+ sendInvoiceNowCta: '立即发送发票',
},
},
disableModal: {title: '关闭合并差旅结算?', body: '即将到来的酒店和汽车租赁预订可能需要使用不同的付款方式重新预订,以避免被取消。', confirm: '关闭'},
@@ -5808,6 +5809,8 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
invalidDateRangeError: '开始日期必须早于结束日期',
enabled: '已启用合并差旅账单!',
enabledDescription: '此工作区的所有差旅支出现在将统一汇总到一份月度账单中。',
+ 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 |
There was a problem hiding this comment.
💡 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); |
There was a problem hiding this comment.
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 Report✅ Changes either increased or maintained existing code coverage, great job!
|
|
@flaviadefaria @deetergp please ignore the ping, this is a WIP PR |
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.
Two UI changes, both inert until the backend enables them:
invoiceTopresent in their travel settings, the same signal that drives change Fix spaces #2). Deposit-only options are labeled "Deposit only" in the account selector so they're distinguishable from withdrawal accounts. The server remains the authority (it accepts the deposit-only account only when theprivate_travelBillingSettlementMethodNVP is set);invoiceTois the client-visible hint, since that private NVP never reaches Onyx.invoiceTopresent in their travel settings), since pressing it creates an invoice for their current travel spend instead of queueing a bank debit.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 and a validated deposit-only (personal) bank account.
invoiceToin the workspace's TRAVEL_US card settings (pay-by-invoice config).invoiceToand verify the deposit-only account no longer appears in the selector and the button reverts to "Pay balance" with the original modal copy.Offline tests
QA Steps
None: this UI is gated behind server-side pay-by-invoice configuration (
invoiceTo), which doesn't exist on staging yet.PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
– written by Claude on Ben's behalf