Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/hooks/useGetExpensifyCardFromReportAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {useCardList, useWorkspaceCardList} from '@components/OnyxListItemProvide

import {isPolicyAdmin} from '@libs/PolicyUtils';
import {getOriginalMessage, isCardIssuedAction} from '@libs/ReportActionsUtils';
import {getTravelInvoicingFeedID} from '@libs/TravelInvoicingUtils';

import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
Expand All @@ -25,7 +26,7 @@ function useGetExpensifyCardFromReportAction({reportAction, policyID}: {reportAc
// Travel Invoicing cards on the `_TRAVEL_US` variant. Check both.
return (
allExpensifyCards?.[`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${CONST.EXPENSIFY_CARD.BANK}`]?.[cardID] ??
allExpensifyCards?.[`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${CONST.EXPENSIFY_CARD.BANK}_${CONST.TRAVEL.PROGRAM_TRAVEL_US}`]?.[cardID] ??
allExpensifyCards?.[`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${getTravelInvoicingFeedID(workspaceAccountID)}`]?.[cardID] ??
allUserCards?.[cardID]
);
}
Expand Down
1 change: 1 addition & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6074,6 +6074,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
currentTravelSpendLabel: 'Aktuelle Reisekosten',
currentTravelSpendPaymentQueued: (amount: string) => `Die Zahlung über ${amount} ist in der Warteschlange und wird in Kürze bearbeitet.`,
currentTravelSpendCta: 'Saldo bezahlen',
viewOnSpend: 'In Ausgaben anzeigen',
currentTravelLimitLabel: 'Aktuelles Reisekontingent',
settlementAccountLabel: 'Verrechnungskonto',
settlementFrequencyLabel: 'Auszahlungsfrequenz',
Expand Down
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6163,6 +6163,7 @@ const translations = {
currentTravelSpendLabel: 'Current travel spend',
currentTravelSpendPaymentQueued: (amount: string) => `Payment of ${amount} is queued and will be processed soon.`,
currentTravelSpendCta: 'Pay balance',
viewOnSpend: 'View on Spend',
currentTravelLimitLabel: 'Current travel limit',
settlementAccountLabel: 'Settlement account',
settlementFrequencyLabel: 'Settlement frequency',
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5918,6 +5918,7 @@ ${amount} para ${merchant} - ${date}`,
currentTravelSpendLabel: 'Gasto actual en viajes',
currentTravelSpendPaymentQueued: (amount: string) => `El pago de ${amount} está en cola y se procesará pronto.`,
currentTravelSpendCta: 'Pagar saldo',
viewOnSpend: 'Ver en Gastos',
currentTravelLimitLabel: 'Límite actual de viajes',
settlementAccountLabel: 'Cuenta de liquidación',
settlementFrequencyLabel: 'Frecuencia de liquidación',
Expand Down
1 change: 1 addition & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6094,6 +6094,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
currentTravelSpendLabel: 'Dépenses de voyage actuelles',
currentTravelSpendPaymentQueued: (amount: string) => `Le paiement de ${amount} est en file d’attente et sera traité bientôt.`,
currentTravelSpendCta: 'Payer le solde',
viewOnSpend: 'Voir dans Dépenses',
currentTravelLimitLabel: 'Plafond de déplacement actuel',
settlementAccountLabel: 'Compte de règlement',
settlementFrequencyLabel: 'Fréquence de règlement',
Expand Down
1 change: 1 addition & 0 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6056,6 +6056,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
currentTravelSpendLabel: 'Spesa di viaggio attuale',
currentTravelSpendPaymentQueued: (amount: string) => `Il pagamento di ${amount} è in coda e verrà elaborato a breve.`,
currentTravelSpendCta: 'Paga saldo',
viewOnSpend: 'Visualizza in Spese',
currentTravelLimitLabel: 'Limite di viaggio attuale',
settlementAccountLabel: 'Conto di regolamento',
settlementFrequencyLabel: 'Frequenza di regolamento',
Expand Down
1 change: 1 addition & 0 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5985,6 +5985,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
currentTravelSpendLabel: '現在の出張費支出',
currentTravelSpendPaymentQueued: (amount: string) => `${amount} の支払いはキューに登録されており、まもなく処理されます。`,
currentTravelSpendCta: '残高を支払う',
viewOnSpend: '支出で表示',
currentTravelLimitLabel: '現在の出張上限',
settlementAccountLabel: '決済口座',
settlementFrequencyLabel: '清算頻度',
Expand Down
1 change: 1 addition & 0 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6045,6 +6045,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
currentTravelSpendLabel: 'Huidige reiskosten',
currentTravelSpendPaymentQueued: (amount: string) => `Betaling van ${amount} staat in de wachtrij en wordt binnenkort verwerkt.`,
currentTravelSpendCta: 'Saldo betalen',
viewOnSpend: 'Bekijken in Uitgaven',
currentTravelLimitLabel: 'Huidige reisl imiet',
settlementAccountLabel: 'Verrekeningsrekening',
settlementFrequencyLabel: 'Uitbetalingsfrequentie',
Expand Down
1 change: 1 addition & 0 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6024,6 +6024,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
currentTravelSpendLabel: 'Aktualne wydatki na podróże',
currentTravelSpendPaymentQueued: (amount: string) => `Płatność w wysokości ${amount} jest w kolejce i wkrótce zostanie przetworzona.`,
currentTravelSpendCta: 'Spłać saldo',
viewOnSpend: 'Zobacz w Wydatkach',
currentTravelLimitLabel: 'Aktualny limit podróży',
settlementAccountLabel: 'Konto rozliczeniowe',
settlementFrequencyLabel: 'Częstotliwość rozliczeń',
Expand Down
1 change: 1 addition & 0 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6037,6 +6037,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
currentTravelSpendLabel: 'Gasto atual com viagens',
currentTravelSpendPaymentQueued: (amount: string) => `O pagamento de ${amount} está na fila e será processado em breve.`,
currentTravelSpendCta: 'Pagar saldo',
viewOnSpend: 'Ver em Gastos',
currentTravelLimitLabel: 'Limite de viagem atual',
settlementAccountLabel: 'Conta de liquidação',
settlementFrequencyLabel: 'Frequência de liquidação',
Expand Down
1 change: 1 addition & 0 deletions src/languages/zh-hans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5857,6 +5857,7 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
currentTravelSpendLabel: '当前差旅支出',
currentTravelSpendPaymentQueued: (amount: string) => `金额为 ${amount} 的付款已排队,稍后将被处理。`,
currentTravelSpendCta: '支付余额',
viewOnSpend: '在支出中查看',
currentTravelLimitLabel: '当前出行限额',
settlementAccountLabel: '结算账户',
settlementFrequencyLabel: '结算频率',
Expand Down
8 changes: 8 additions & 0 deletions src/libs/TravelInvoicingUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ function getTravelInvoicingCardSettingsKey(workspaceAccountID: number): `${typeo
return `${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`;
}

/**
* Builds the card-feed ID for a Travel Invoicing card feed (the `_TRAVEL_US` variant).
*/
function getTravelInvoicingFeedID(fundID: number | string): `${string}_${typeof CONST.EXPENSIFY_CARD.BANK}_${typeof CONST.TRAVEL.PROGRAM_TRAVEL_US}` {
return `${fundID}_${CONST.EXPENSIFY_CARD.BANK}_${CONST.TRAVEL.PROGRAM_TRAVEL_US}`;
}

/**
* Downloads a cached Travel Invoice Statement PDF.
* Constructs a secure URL with encrypted auth token and triggers the download.
Expand Down Expand Up @@ -185,6 +192,7 @@ export {
getTravelSettlementAccount,
getTravelSettlementFrequency,
getTravelInvoicingCardSettingsKey,
getTravelInvoicingFeedID,
downloadTravelInvoiceStatementPDF,
getTravelInvoicingCard,
isTravelCVVEligible,
Expand Down
40 changes: 33 additions & 7 deletions src/pages/workspace/travel/WorkspaceTravelInvoicingSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useOnyx from '@hooks/useOnyx';
import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useThemeStyles from '@hooks/useThemeStyles';
import useWorkspaceAccountID from '@hooks/useWorkspaceAccountID';

Expand All @@ -32,9 +33,11 @@ import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/crea
import Navigation from '@libs/Navigation/Navigation';
import {areTravelPersonalDetailsMissing} from '@libs/PersonalDetailsUtils';
import {hasInProgressUSDVBBA} from '@libs/ReimbursementAccountUtils';
import {buildQueryStringFromFilterFormValues} from '@libs/SearchQueryUtils';
import {
getIsTravelInvoicingEnabled,
getTravelInvoicingCardSettingsKey,
getTravelInvoicingFeedID,
getTravelLimit,
getTravelSettlementAccount,
getTravelSettlementFrequency,
Expand Down Expand Up @@ -70,6 +73,7 @@ type WorkspaceTravelInvoicingSectionProps = {
function WorkspaceTravelInvoicingSection({policyID}: WorkspaceTravelInvoicingSectionProps) {
const styles = useThemeStyles();
const {isOffline} = useNetwork();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const {translate} = useLocalize();
const {convertToDisplayString} = useCurrencyListActions();
const workspaceAccountID = useWorkspaceAccountID(policyID);
Expand Down Expand Up @@ -163,6 +167,19 @@ function WorkspaceTravelInvoicingSection({policyID}: WorkspaceTravelInvoicingSec
setIsPayBalanceModalVisible(true);
};

/**
* Navigates to the Spend page pre-filtered on the Consolidated Travel Billing feed so admins
* can reconcile their travel spend.
*/
Comment thread
ishpaul777 marked this conversation as resolved.
const handleViewOnSpend = () => {
const travelFeedID = getTravelInvoicingFeedID(workspaceAccountID);
const query = buildQueryStringFromFilterFormValues({
type: CONST.SEARCH.DATA_TYPES.EXPENSE,
feed: [travelFeedID],
});
Navigation.navigate(ROUTES.SEARCH_ROOT.getRoute({query}));
};

/**
* Handles the confirmed payment of the outstanding travel balance.
* Closes the modal and triggers the API call with optimistic Onyx update.
Expand Down Expand Up @@ -315,7 +332,7 @@ function WorkspaceTravelInvoicingSection({policyID}: WorkspaceTravelInvoicingSec
/>
</View>
)}
<View style={[styles.dFlex, styles.flexRow, styles.mt6, styles.gap4, styles.alignItemsCenter]}>
<View style={[styles.dFlex, styles.mt6, styles.gap4, shouldUseNarrowLayout ? styles.flexColumn : [styles.flexRow, styles.alignItemsCenter]]}>
<View style={styles.flex1}>
<MenuItemWithTopDescription
description={translate('workspace.moreFeatures.travel.travelInvoicing.travelInvoicingSection.subsections.currentTravelSpendLabel')}
Expand All @@ -331,15 +348,24 @@ function WorkspaceTravelInvoicingSection({policyID}: WorkspaceTravelInvoicingSec
</Text>
)}
</View>
{shouldShowPayButton && canWriteMoreFeatures && (
<View style={[styles.dFlex, styles.flexRow, styles.gap2, styles.alignItemsCenter]}>
<Button
onPress={handlePayBalance}
isDisabled={isOffline}
variant={CONST.BUTTON_VARIANT.SUCCESS}
onPress={handleViewOnSpend}
style={shouldUseNarrowLayout ? styles.flex1 : undefined}
>
<Button.Text>{translate('workspace.moreFeatures.travel.travelInvoicing.travelInvoicingSection.subsections.currentTravelSpendCta')}</Button.Text>
<Button.Text>{translate('workspace.moreFeatures.travel.travelInvoicing.travelInvoicingSection.subsections.viewOnSpend')}</Button.Text>
</Button>
)}
{shouldShowPayButton && canWriteMoreFeatures && (
<Button
onPress={handlePayBalance}
isDisabled={isOffline}
variant={CONST.BUTTON_VARIANT.SUCCESS}
style={shouldUseNarrowLayout ? styles.flex1 : undefined}
>
<Button.Text>{translate('workspace.moreFeatures.travel.travelInvoicing.travelInvoicingSection.subsections.currentTravelSpendCta')}</Button.Text>
</Button>
)}
</View>
</View>
<MenuItemWithTopDescription
description={translate('workspace.moreFeatures.travel.travelInvoicing.travelInvoicingSection.subsections.currentTravelLimitLabel')}
Expand Down
Loading