Skip to content

Commit 6c5d968

Browse files
authored
Merge pull request #56931 from callstack-internal/feat/50912-enable-non-usd-flow
feat: Enable non USD flow behind beta flag
2 parents 98127bc + e76fc1a commit 6c5d968

File tree

23 files changed

+199
-158
lines changed

23 files changed

+199
-158
lines changed

src/CONST.ts

+5-30
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ const CONST = {
680680
},
681681
NON_USD_BANK_ACCOUNT: {
682682
ALLOWED_FILE_TYPES: ['pdf', 'jpg', 'jpeg', 'png'],
683-
FILE_LIMIT: 10,
683+
FILE_LIMIT: 1,
684684
TOTAL_FILES_SIZE_LIMIT: 5242880,
685685
PURPOSE_OF_TRANSACTION_ID: 'Intercompany_Payment',
686686
CURRENT_USER_KEY: 'currentUser',
@@ -796,6 +796,7 @@ const CONST = {
796796
RECEIPT_LINE_ITEMS: 'receiptLineItems',
797797
LEFT_HAND_BAR: 'leftHandBar',
798798
WALLET: 'newdotWallet',
799+
GLOBAL_REIMBURSEMENTS_ON_ND: 'globalReimbursementsOnND',
799800
},
800801
BUTTON_STATES: {
801802
DEFAULT: 'default',
@@ -1084,6 +1085,7 @@ const CONST = {
10841085
ENCRYPTION_AND_SECURITY_HELP_URL: 'https://help.expensify.com/articles/new-expensify/settings/Encryption-and-Data-Security',
10851086
PLAN_TYPES_AND_PRICING_HELP_URL: 'https://help.expensify.com/articles/new-expensify/billing-and-subscriptions/Plan-types-and-pricing',
10861087
MERGE_ACCOUNT_HELP_URL: 'https://help.expensify.com/articles/expensify-classic/settings/Merge-accounts',
1088+
CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL: 'https://help.expensify.com/articles/new-expensify/expenses-&-payments/Connect-a-Business-Bank-Account',
10871089
TEST_RECEIPT_URL: `${CLOUDFRONT_URL}/images/fake-receipt__tacotodds.png`,
10881090
// Use Environment.getEnvironmentURL to get the complete URL with port number
10891091
DEV_NEW_EXPENSIFY_URL: 'https://dev.new.expensify.com:',
@@ -3986,61 +3988,34 @@ const CONST = {
39863988
ZW: 'Zimbabwe',
39873989
},
39883990

3989-
ALL_EUROPEAN_COUNTRIES: {
3990-
AL: 'Albania',
3991-
AD: 'Andorra',
3991+
ALL_EUROPEAN_UNION_COUNTRIES: {
39923992
AT: 'Austria',
3993-
BY: 'Belarus',
39943993
BE: 'Belgium',
3995-
BA: 'Bosnia & Herzegovina',
39963994
BG: 'Bulgaria',
39973995
HR: 'Croatia',
39983996
CY: 'Cyprus',
39993997
CZ: 'Czech Republic',
40003998
DK: 'Denmark',
40013999
EE: 'Estonia',
4002-
FO: 'Faroe Islands',
40034000
FI: 'Finland',
40044001
FR: 'France',
4005-
GE: 'Georgia',
40064002
DE: 'Germany',
4007-
GI: 'Gibraltar',
40084003
GR: 'Greece',
4009-
GL: 'Greenland',
40104004
HU: 'Hungary',
4011-
IS: 'Iceland',
40124005
IE: 'Ireland',
4013-
IM: 'Isle of Man',
40144006
IT: 'Italy',
4015-
JE: 'Jersey',
4016-
XK: 'Kosovo',
4017-
LV: 'Latvia',
4018-
LI: 'Liechtenstein',
40194007
LT: 'Lithuania',
40204008
LU: 'Luxembourg',
4009+
LV: 'Latvia',
40214010
MT: 'Malta',
4022-
MD: 'Moldova',
4023-
MC: 'Monaco',
4024-
ME: 'Montenegro',
40254011
NL: 'Netherlands',
4026-
MK: 'North Macedonia',
4027-
NO: 'Norway',
40284012
PL: 'Poland',
40294013
PT: 'Portugal',
40304014
RO: 'Romania',
4031-
RU: 'Russia',
4032-
SM: 'San Marino',
4033-
RS: 'Serbia',
40344015
SK: 'Slovakia',
40354016
SI: 'Slovenia',
40364017
ES: 'Spain',
4037-
SJ: 'Svalbard & Jan Mayen',
40384018
SE: 'Sweden',
4039-
CH: 'Switzerland',
4040-
TR: 'Turkey',
4041-
UA: 'Ukraine',
4042-
GB: 'United Kingdom',
4043-
VA: 'Vatican City',
40444019
},
40454020

40464021
// Sources: https://github.com/Expensify/App/issues/14958#issuecomment-1442138427

src/components/SettlementButton/index.tsx

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, {useEffect, useMemo, useRef} from 'react';
22
import type {GestureResponderEvent} from 'react-native';
33
import {useOnyx} from 'react-native-onyx';
4+
import type {TupleToUnion} from 'type-fest';
45
import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
56
import type {PaymentType} from '@components/ButtonWithDropdownMenu/types';
67
import * as Expensicons from '@components/Icon/Expensicons';
@@ -35,6 +36,8 @@ type KYCFlowEvent = GestureResponderEvent | KeyboardEvent | undefined;
3536

3637
type TriggerKYCFlow = (event: KYCFlowEvent, iouPaymentType: PaymentMethodType) => void;
3738

39+
type CurrencyType = TupleToUnion<typeof CONST.DIRECT_REIMBURSEMENT_CURRENCIES>;
40+
3841
function SettlementButton({
3942
addDebitCardRoute = ROUTES.IOU_SEND_ADD_DEBIT_CARD,
4043
addBankAccountRoute = '',
@@ -75,7 +78,8 @@ function SettlementButton({
7578
const {translate} = useLocalize();
7679
const {isOffline} = useNetwork();
7780
// The app would crash due to subscribing to the entire report collection if chatReportID is an empty string. So we should have a fallback ID here.
78-
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID || CONST.DEFAULT_NUMBER_ID}`);
81+
/* eslint-disable-next-line rulesdir/no-default-id-values */
82+
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID || CONST.DEFAULT_NUMBER_ID}`, {canBeMissing: true});
7983
const isUserValidated = useAccountValidation();
8084
const policyEmployeeAccountIDs = policyID ? getPolicyEmployeeAccountIDs(policyID) : [];
8185
const reportBelongsToWorkspace = policyID ? doesReportBelongToWorkspace(chatReport, policyEmployeeAccountIDs, policyID) : false;
@@ -87,12 +91,13 @@ function SettlementButton({
8791
}
8892
return (paymentMethod?.[policyIDKey] as LastPaymentMethodType)?.lastUsed;
8993
},
94+
canBeMissing: true,
9095
});
9196

9297
const isLoadingLastPaymentMethod = isLoadingOnyxValue(lastPaymentMethodResult);
93-
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`);
94-
const [bankAccountList = {}] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
95-
const [fundList = {}] = useOnyx(ONYXKEYS.FUND_LIST);
98+
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {canBeMissing: true});
99+
const [bankAccountList = {}] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST, {canBeMissing: true});
100+
const [fundList = {}] = useOnyx(ONYXKEYS.FUND_LIST, {canBeMissing: true});
96101
const lastPaymentMethodRef = useRef(lastPaymentMethod);
97102

98103
useEffect(() => {
@@ -156,7 +161,7 @@ function SettlementButton({
156161

157162
if (isInvoiceReport) {
158163
const formattedPaymentMethods = formatPaymentMethods(bankAccountList, fundList, styles);
159-
const isCurrencySupported = isCurrencySupportedForDirectReimbursement(currency);
164+
const isCurrencySupported = isCurrencySupportedForDirectReimbursement(currency as CurrencyType);
160165
const getPaymentSubitems = (payAsBusiness: boolean) =>
161166
formattedPaymentMethods.map((formattedPaymentMethod) => ({
162167
text: formattedPaymentMethod?.title ?? '',

src/components/UploadFile.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import AttachmentPicker from './AttachmentPicker';
1212
import Button from './Button';
1313
import DotIndicatorMessage from './DotIndicatorMessage';
1414
import Icon from './Icon';
15-
import * as Expensicons from './Icon/Expensicons';
15+
import {Close, Paperclip} from './Icon/Expensicons';
1616
import {PressableWithFeedback} from './Pressable';
1717
import Text from './Text';
1818

@@ -129,7 +129,7 @@ function UploadFile({
129129
key={file.name}
130130
>
131131
<Icon
132-
src={Expensicons.Paperclip}
132+
src={Paperclip}
133133
fill={theme.icon}
134134
medium
135135
/>
@@ -145,7 +145,7 @@ function UploadFile({
145145
accessibilityLabel={translate('common.remove')}
146146
>
147147
<Icon
148-
src={Expensicons.Close}
148+
src={Close}
149149
fill={theme.icon}
150150
medium
151151
/>

src/languages/en.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import type {
5151
ConnectionNameParams,
5252
ConnectionParams,
5353
CurrencyCodeParams,
54+
CurrencyInputDisabledTextParams,
5455
CustomersOrJobsLabelParams,
5556
CustomUnitRateParams,
5657
DateParams,
@@ -2687,7 +2688,6 @@ const translations = {
26872688
letsDoubleCheck: 'Let’s double check that everything looks fine.',
26882689
thisBankAccount: 'This bank account will be used for business payments on your workspace',
26892690
accountNumber: 'Account number',
2690-
bankStatement: 'Bank statement',
26912691
chooseFile: 'Choose file',
26922692
uploadYourLatest: 'Upload your latest statement',
26932693
pleaseUpload: ({lastFourDigits}: LastFourDigitsParams) => `Please upload the most recent monthly statement for your business bank account ending in ${lastFourDigits}.`,
@@ -4616,7 +4616,8 @@ const translations = {
46164616
nameIsRequiredError: "You'll need to give your workspace a name",
46174617
currencyInputLabel: 'Default currency',
46184618
currencyInputHelpText: 'All expenses on this workspace will be converted to this currency.',
4619-
currencyInputDisabledText: "The default currency can't be changed because this workspace is linked to a USD bank account.",
4619+
currencyInputDisabledText: ({currency}: CurrencyInputDisabledTextParams) =>
4620+
`The default currency can't be changed because this workspace is linked to a ${currency} bank account.`,
46204621
save: 'Save',
46214622
genericFailureMessage: 'An error occurred while updating the workspace. Please try again.',
46224623
avatarUploadFailureMessage: 'An error occurred uploading the avatar. Please try again.',
@@ -4645,6 +4646,10 @@ const translations = {
46454646
workspaceCurrency: 'Workspace currency',
46464647
updateCurrencyPrompt: 'It looks like your workspace is currently set to a different currency than USD. Please click the button below to update your currency to USD now.',
46474648
updateToUSD: 'Update to USD',
4649+
updateWorkspaceCurrency: 'Update workspace currency',
4650+
workspaceCurrencyNotSupported: 'Workspace currency not supported',
4651+
yourWorkspace: 'Your workspace is set to an unsupported currency. View the',
4652+
listOfSupportedCurrencies: 'list of supported currencies',
46484653
},
46494654
changeOwner: {
46504655
changeOwnerPageTitle: 'Transfer owner',

src/languages/es.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import type {
5050
ConnectionNameParams,
5151
ConnectionParams,
5252
CurrencyCodeParams,
53+
CurrencyInputDisabledTextParams,
5354
CustomersOrJobsLabelParams,
5455
CustomUnitRateParams,
5556
DateParams,
@@ -2712,7 +2713,6 @@ const translations = {
27122713
letsDoubleCheck: 'Verifiquemos que todo esté bien.',
27132714
thisBankAccount: 'Esta cuenta bancaria se utilizará para pagos comerciales en tu espacio de trabajo.',
27142715
accountNumber: 'Número de cuenta',
2715-
bankStatement: 'Extracto bancario',
27162716
chooseFile: 'Elegir archivo',
27172717
uploadYourLatest: '¿Cuáles son los detalles de tu cuenta bancaria comercial?',
27182718
pleaseUpload: ({lastFourDigits}: LastFourDigitsParams) => `Por favor suba el estado de cuenta mensual más reciente de tu cuenta bancaria comercial que termina en ${lastFourDigits}.`,
@@ -4664,7 +4664,8 @@ const translations = {
46644664
nameIsRequiredError: 'Debes definir un nombre para tu espacio de trabajo',
46654665
currencyInputLabel: 'Moneda por defecto',
46664666
currencyInputHelpText: 'Todas los gastos en este espacio de trabajo serán convertidos a esta moneda.',
4667-
currencyInputDisabledText: 'La moneda predeterminada no se puede cambiar porque este espacio de trabajo está vinculado a una cuenta bancaria en USD.',
4667+
currencyInputDisabledText: ({currency}: CurrencyInputDisabledTextParams) =>
4668+
`La moneda predeterminada no se puede cambiar porque este espacio de trabajo está vinculado a una cuenta bancaria en ${currency}.`,
46684669
save: 'Guardar',
46694670
genericFailureMessage: 'Se ha producido un error al guardar el espacio de trabajo. Por favor, inténtalo de nuevo.',
46704671
avatarUploadFailureMessage: 'No se pudo subir el avatar. Por favor, inténtalo de nuevo.',
@@ -4694,6 +4695,10 @@ const translations = {
46944695
updateCurrencyPrompt:
46954696
'Parece que tu espacio de trabajo está configurado actualmente en una moneda diferente a USD. Por favor, haz clic en el botón de abajo para actualizar tu moneda a USD ahora.',
46964697
updateToUSD: 'Actualizar a USD',
4698+
updateWorkspaceCurrency: 'Actualizar la moneda del espacio de trabajo',
4699+
workspaceCurrencyNotSupported: 'Moneda del espacio de trabajo no soportada',
4700+
yourWorkspace: 'Tu espacio de trabajo está configurado en una moneda no soportada. Consulta la',
4701+
listOfSupportedCurrencies: 'lista de monedas soportadas',
46974702
},
46984703
changeOwner: {
46994704
changeOwnerPageTitle: 'Transferir la propiedad',

src/languages/params.ts

+5
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,10 @@ type ReviewParams = {
691691
amount: string;
692692
};
693693

694+
type CurrencyInputDisabledTextParams = {
695+
currency: string;
696+
};
697+
694698
export type {
695699
AuthenticationErrorParams,
696700
ImportMembersSuccessfullDescriptionParams,
@@ -936,4 +940,5 @@ export type {
936940
NeedCategoryForExportToIntegrationParams,
937941
SubscriptionSettingsSummaryParams,
938942
ReviewParams,
943+
CurrencyInputDisabledTextParams,
939944
};

src/libs/Permissions.ts

+5
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ function canUseInAppProvisioning(betas: OnyxEntry<Beta[]>): boolean {
6666
return !!betas?.includes(CONST.BETAS.WALLET) || canUseAllBetas(betas);
6767
}
6868

69+
function canUseGlobalReimbursementsOnND(betas: OnyxEntry<Beta[]>): boolean {
70+
return !!betas?.includes(CONST.BETAS.GLOBAL_REIMBURSEMENTS_ON_ND) || canUseAllBetas(betas);
71+
}
72+
6973
export default {
7074
canUseDefaultRooms,
7175
canUseLinkPreviews,
@@ -81,4 +85,5 @@ export default {
8185
canUseProhibitedExpenses,
8286
canUseLeftHandBar,
8387
canUseInAppProvisioning,
88+
canUseGlobalReimbursementsOnND,
8489
};

src/libs/actions/Policy/Policy.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import escapeRegExp from 'lodash/escapeRegExp';
33
import lodashUnion from 'lodash/union';
44
import type {NullishDeep, OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx';
55
import Onyx from 'react-native-onyx';
6-
import type {ValueOf} from 'type-fest';
6+
import type {TupleToUnion, ValueOf} from 'type-fest';
77
import type {ReportExportType} from '@components/ButtonWithDropdownMenu/types';
88
import * as API from '@libs/API';
99
import type {
@@ -268,6 +268,13 @@ function isCurrencySupportedForDirectReimbursement(currency: string) {
268268
return currency === CONST.CURRENCY.USD;
269269
}
270270

271+
/**
272+
* Checks if the currency is supported for global reimbursement
273+
*/
274+
function isCurrencySupportedForGlobalReimbursement(currency: TupleToUnion<typeof CONST.DIRECT_REIMBURSEMENT_CURRENCIES>, canUseGlobalReimbursementsOnND: boolean) {
275+
return canUseGlobalReimbursementsOnND ? CONST.DIRECT_REIMBURSEMENT_CURRENCIES.includes(currency) : currency === CONST.CURRENCY.USD;
276+
}
277+
271278
/**
272279
* Returns the policy of the report
273280
*/
@@ -5190,6 +5197,7 @@ export {
51905197
setPolicyCustomTaxName,
51915198
clearPolicyErrorField,
51925199
isCurrencySupportedForDirectReimbursement,
5200+
isCurrencySupportedForGlobalReimbursement,
51935201
getInvoicePrimaryWorkspace,
51945202
createDraftWorkspace,
51955203
savePreferredExportMethod,

src/pages/ReimbursementAccount/ConnectedVerifiedBankAccount.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ function ConnectedVerifiedBankAccount({
108108
{shouldShowResetModal && (
109109
<WorkspaceResetBankAccountModal
110110
reimbursementAccount={reimbursementAccount}
111-
setShouldShowConnectedVerifiedBankAccount={setShouldShowConnectedVerifiedBankAccount}
112111
isNonUSDWorkspace={isNonUSDWorkspace}
112+
setShouldShowConnectedVerifiedBankAccount={setShouldShowConnectedVerifiedBankAccount}
113113
setUSDBankAccountStep={setUSDBankAccountStep}
114114
setNonUSDBankAccountStep={setNonUSDBankAccountStep}
115115
/>

src/pages/ReimbursementAccount/NonUSD/BankInfo/BankInfo.tsx

+9-5
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ type BankInfoProps = {
3434
function BankInfo({onBackButtonPress, onSubmit, policyID}: BankInfoProps) {
3535
const {translate} = useLocalize();
3636

37-
const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
38-
const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT);
39-
const [corpayFields] = useOnyx(ONYXKEYS.CORPAY_FIELDS, {initWithStoredValues: false});
40-
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`);
37+
const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {canBeMissing: false});
38+
const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT, {canBeMissing: false});
39+
const [corpayFields] = useOnyx(ONYXKEYS.CORPAY_FIELDS, {initWithStoredValues: false, canBeMissing: true});
40+
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {canBeMissing: false});
4141
const currency = policy?.outputCurrency ?? '';
4242
const country = reimbursementAccount?.achData?.[COUNTRY] ?? reimbursementAccountDraft?.[COUNTRY] ?? '';
4343
const inputKeys = getInputKeysForBankInfoStep(corpayFields);
@@ -65,6 +65,10 @@ function BankInfo({onBackButtonPress, onSubmit, policyID}: BankInfoProps) {
6565
}, [onSubmit, reimbursementAccount?.errors, reimbursementAccount?.isCreateCorpayBankAccount, reimbursementAccount?.isLoading, reimbursementAccount?.isSuccess]);
6666

6767
useEffect(() => {
68+
if (country === '') {
69+
return;
70+
}
71+
6872
getCorpayBankAccountFields(country, currency);
6973
}, [country, currency]);
7074

@@ -93,7 +97,7 @@ function BankInfo({onBackButtonPress, onSubmit, policyID}: BankInfoProps) {
9397
}
9498
};
9599

96-
if (corpayFields !== undefined && corpayFields?.isLoading === false && corpayFields?.isSuccess === false) {
100+
if (corpayFields !== undefined && corpayFields?.isLoading === false && corpayFields?.isSuccess !== undefined && corpayFields?.isSuccess === false) {
97101
return <NotFoundPage />;
98102
}
99103

0 commit comments

Comments
 (0)