Skip to content
Merged
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
21 changes: 19 additions & 2 deletions src/hooks/useCurrencyForExpensifyCard.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
import {getCardOrFeedCurrency} from '@libs/CardUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import useExpensifyCardUkEuSupported from './useExpensifyCardUkEuSupported';
import useOnyx from './useOnyx';
import usePolicy from './usePolicy';

export default function useCurrencyForExpensifyCard({policyID}: {policyID?: string}) {
export default function useCurrencyForExpensifyCard({policyID, fundID}: {policyID?: string; fundID?: number}) {
const policy = usePolicy(policyID);
const isUkEuCurrencySupported = useExpensifyCardUkEuSupported(policyID);
return isUkEuCurrencySupported ? (policy?.outputCurrency ?? CONST.CURRENCY.USD) : CONST.CURRENCY.USD;
const [cardSettings] = useOnyx(`${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${fundID}`);

// The selected feed can belong to a different policy/domain than the one being viewed
// (e.g. a US feed linked to a GBP policy), so derive the currency from the feed itself.
if (fundID && cardSettings) {
return getCardOrFeedCurrency(undefined, cardSettings);

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 Preserve policy currency when feed settings lack currency

When a GBP/EUR workspace's selected feed settings have loaded but don't include the optional currency field (for example legacy/nested GB settings), this branch returns getCardOrFeedCurrency(undefined, cardSettings). With no card, that helper has no feedCountry, so after failing to find settings.currency it falls through to USD instead of the previous policy.outputCurrency; the list and issue-card flow will display and store USD for that GBP/EUR feed. Please fall back to the policy currency or infer the program from settings when the feed settings don't carry a currency.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

don't include the optional currency field (for example legacy/nested GB settings)

AFAIK this is not a real thing, there are no "legacy" GB settings, the program hasn't even launched yet

}

// If no fund was provided, then use the policy currency, if available
if (isUkEuCurrencySupported && policy?.outputCurrency) {
return policy.outputCurrency;
}

// Finally, fall back to USD
return CONST.CURRENCY.USD;
}
12 changes: 10 additions & 2 deletions src/libs/CardUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1781,7 +1781,15 @@ function getDisplayableThirdPartyCards(cardList: CardList | undefined, cardFeedE
return lodashSortBy(cards, getAssignedCardSortKey);
}

function getCardCurrency(card?: OnyxEntry<Card>, cardSettings?: OnyxEntry<ExpensifyCardSettings>): string {
/**
* Determines the currency of the card and/or feed. Data sources are prioritized as follows:
* 1. Card currency, if card is passed and has a currency set on it
* 2. Feed settings currency, if settings are passed and have a currency
* 3. Use USD for US program keys
* 4. For UK/EU feeds, determine currency based on card country, defaulting to GBP
* 5. Finally, if all else fails, fallback to USD
*/
function getCardOrFeedCurrency(card?: OnyxEntry<Card>, cardSettings?: OnyxEntry<ExpensifyCardSettings>): string {
// If currency is set on the card itself, use it.
if (card?.nameValuePairs?.currency) {
return card.nameValuePairs.currency;
Expand Down Expand Up @@ -2001,7 +2009,7 @@ export {
getDisplayableExpensifyCards,
getDisplayableThirdPartyCards,
isExpiredCard,
getCardCurrency,
getCardOrFeedCurrency,
getSelectedCardsSharedCurrency,
getCardHintText,
resolveTransactionCardFields,
Expand Down
4 changes: 2 additions & 2 deletions src/pages/settings/Wallet/ExpensifyCardPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ import {resetValidateActionCodeSent} from '@libs/actions/User';
import navigateToCardTransactions from '@libs/CardNavigationUtils';
import {
formatCardExpiration,
getCardCurrency,
getCardHintText,
getCardOrFeedCurrency,
getDomainCards,
getTranslationKeyForLimitType,
isCardFrozen,
Expand Down Expand Up @@ -148,7 +148,7 @@ function ExpensifyCardPage({route}: ExpensifyCardPageProps) {
// Cards that are already activated and working (OPEN) and cards shipped but not activated yet can be reported as missing or damaged
const shouldShowReportLostCardButton = currentPhysicalCard?.state === CONST.EXPENSIFY_CARD.STATE.NOT_ACTIVATED || currentPhysicalCard?.state === CONST.EXPENSIFY_CARD.STATE.OPEN;

const currency = getCardCurrency(currentCard, cardSettings);
const currency = getCardOrFeedCurrency(currentCard, cardSettings);
const shouldShowPIN = currency !== CONST.CURRENCY.USD;
const shouldShowChangePINRow = isUkEuExpensifyCard(currentPhysicalCard) && currentPhysicalCard?.state === CONST.EXPENSIFY_CARD.STATE.OPEN;
const canRevealPIN = shouldShowChangePINRow && revealedPIN === undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function DynamicExpensifyCardLimitPage({route}: DynamicExpensifyCardLimitPagePro
const defaultFundID = useDefaultFundID(policyID);
const backPath = useDynamicBackPath(DYNAMIC_ROUTES.EXPENSIFY_CARD_LIMIT.path);

const currency = useCurrencyForExpensifyCard({policyID});
const currency = useCurrencyForExpensifyCard({policyID, fundID: defaultFundID});

const [cardsList] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${defaultFundID}_${CONST.EXPENSIFY_CARD.BANK}`, {selector: filterInactiveCardsForWorkspace});
const card = cardsList?.[cardID];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function DynamicExpensifyCardLimitTypePage({route}: WorkspaceEditCardLimitTypePa
const [typeSelected, setTypeSelected] = useState(initialLimitType);
const [isConfirmModalVisible, setIsConfirmModalVisible] = useState(false);
const [expirationToggle, setExpirationToggle] = useState(!!card?.nameValuePairs?.validFrom);
const currency = useCurrencyForExpensifyCard({policyID});
const currency = useCurrencyForExpensifyCard({policyID, fundID: defaultFundID});
const personalDetails = usePersonalDetails();
const assigneePersonalDetails = personalDetails?.[card?.accountID ?? CONST.DEFAULT_NUMBER_ID];
const assigneeTimeZone = assigneePersonalDetails?.timezone?.selected;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ function WorkspaceCardsListLabel({type, value, style}: WorkspaceCardsListLabelPr

const defaultFundID = useDefaultFundID(policyID);

const settlementCurrency = useCurrencyForExpensifyCard({policyID});
const settlementCurrency = useCurrencyForExpensifyCard({policyID, fundID: defaultFundID});
const [cardSettings] = useOnyx(`${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${defaultFundID}`);
const settings = getCardSettings(cardSettings);
const [cardManualBilling] = useOnyx(`${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_MANUAL_BILLING}${defaultFundID}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ function WorkspaceExpensifyCardDetailsPage({route}: WorkspaceExpensifyCardDetail

const workspaceCard = workspaceCards?.[cardID];
const card = workspaceCard ?? cardFromCardList;
const currency = useCurrencyForExpensifyCard({policyID});
const currency = useCurrencyForExpensifyCard({policyID, fundID: defaultFundID});
const cardholder = personalDetails?.[card?.accountID ?? CONST.DEFAULT_NUMBER_ID];
const isVirtual = !!card?.nameValuePairs?.isVirtual;
const formattedAvailableSpendAmount = convertToDisplayString(card?.availableSpend, currency);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import useCurrencyForExpensifyCard from '@hooks/useCurrencyForExpensifyCard';
import useDefaultFundID from '@hooks/useDefaultFundID';
import useEmptyViewHeaderHeight from '@hooks/useEmptyViewHeaderHeight';
import useExpensifyCardFeedsForFeedSelector from '@hooks/useExpensifyCardFeedsForFeedSelector';
import useExpensifyCardUkEuSupported from '@hooks/useExpensifyCardUkEuSupported';
import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
Expand All @@ -34,7 +33,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import {clearIssueNewCardFormData, exportExpensifyCardListToCSV, setIssueNewCardStepAndData} from '@libs/actions/Card';
import {clearDeletePaymentMethodError} from '@libs/actions/PaymentMethods';
import {filterCardsByPersonalDetails, getCardsByCardholderName, getCardSettings, sortCardsByCardholderName} from '@libs/CardUtils';
import {filterCardsByPersonalDetails, getCardsByCardholderName, getCardSettings, isCurrencySupportedForECards, sortCardsByCardholderName} from '@libs/CardUtils';
import {getExpensifyCardFeedDescription} from '@libs/ExpensifyCardFeedSelectorUtils';
import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
Expand Down Expand Up @@ -86,7 +85,6 @@ function WorkspaceExpensifyCardListPage({route, cardsList, fundID}: WorkspaceExp
const {showDelegateNoAccessModal} = useDelegateNoAccessActions();
const {isAccountLocked} = useLockedAccountState();
const {showLockedAccountModal} = useLockedAccountActions();
const isUkEuCurrencySupported = useExpensifyCardUkEuSupported(policyID);
const shouldChangeLayout = isMediumScreenWidth || shouldUseNarrowLayout;
const isBankAccountVerified = !cardOnWaitlist;
const {windowHeight} = useWindowDimensions();
Expand All @@ -101,7 +99,8 @@ function WorkspaceExpensifyCardListPage({route, cardsList, fundID}: WorkspaceExp
/>
);

const settlementCurrency = useCurrencyForExpensifyCard({policyID});
const settlementCurrency = useCurrencyForExpensifyCard({policyID, fundID});
const shouldShowEuUkDisclaimer = isCurrencySupportedForECards(settlementCurrency);
const allCards = useMemo(() => {
const policyMembersAccountIDs = Object.values(getMemberAccountIDsForWorkspace(policy?.employeeList));
return getCardsByCardholderName(cardsList, policyMembersAccountIDs);
Expand Down Expand Up @@ -390,7 +389,7 @@ function WorkspaceExpensifyCardListPage({route, cardsList, fundID}: WorkspaceExp
style={[styles.textMicroSupporting, styles.p5, footerHeight === 0 && {opacity: 0}]}
onLayout={(event) => setFooterHeight(event.nativeEvent.layout.height)}
>
{translate(isUkEuCurrencySupported ? 'workspace.expensifyCard.euUkDisclaimer' : 'workspace.expensifyCard.disclaimer')}
{translate(shouldShowEuUkDisclaimer ? 'workspace.expensifyCard.euUkDisclaimer' : 'workspace.expensifyCard.disclaimer')}
</Text>
}
ListFooterComponentStyle={[styles.flexGrow1, styles.justifyContentEnd]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import UserListItem from '@components/SelectionList/ListItem/UserListItem';
import type {ListItem} from '@components/SelectionList/types';
import Text from '@components/Text';
import useCurrencyForExpensifyCard from '@hooks/useCurrencyForExpensifyCard';
import useDefaultFundID from '@hooks/useDefaultFundID';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
Expand Down Expand Up @@ -75,7 +76,8 @@ function AssigneeStep({policy, stepNames, startStepIndex, route}: AssigneeStepPr
shouldInitialize: didScreenTransitionEnd,
});
const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE);
const currency = useCurrencyForExpensifyCard({policyID});
const defaultFundID = useDefaultFundID(policyID);
const currency = useCurrencyForExpensifyCard({policyID, fundID: defaultFundID});
const isEditing = issueNewCard?.isEditing;

const submit = (assignee: ListItem) => {
Expand Down
Loading