Skip to content

Commit 53dfdb1

Browse files
committed
more changes
1 parent f53f105 commit 53dfdb1

7 files changed

Lines changed: 168 additions & 34 deletions

File tree

src/languages/en.ts

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import type {
3232
BillingBannerInsufficientFundsParams,
3333
BillingBannerOwnerAmountOwedOverdueParams,
3434
BillingBannerSubtitleWithDateParams,
35+
BusinessTaxIDParams,
3536
CanceledRequestParams,
3637
CardEndingParams,
3738
CardInfoParams,
@@ -2663,25 +2664,39 @@ const translations = {
26632664
whatsTheBusinessAddress: "What's the business address?",
26642665
whatsTheBusinessContactInformation: "What's the business contact information?",
26652666
whatsTheBusinessRegistrationNumber: "What's the business registration number?",
2666-
whatsTheBusinessTaxIDEIN: {
2667-
US: "What's the business employer identification number (EIN)?",
2668-
CA: "What's the business number (BN)?",
2669-
UK: "What's the business VAT registration number (VRN)?",
2670-
AUD: "What's the business australian business number (ABN)?",
2671-
EU: "What's the business EU VAT number?",
2667+
whatsTheBusinessTaxIDEIN: ({country}: BusinessTaxIDParams) => {
2668+
switch (country) {
2669+
case CONST.COUNTRY.US:
2670+
return 'What’s the Employer Identification Number (EIN)?';
2671+
case CONST.COUNTRY.CA:
2672+
return 'What’s the Business Number (BN)?';
2673+
case CONST.COUNTRY.GB:
2674+
return 'What’s the VAT Registration Number (VRN)?';
2675+
case CONST.COUNTRY.AU:
2676+
return 'What’s the Australian Business Number (ABN)?';
2677+
default:
2678+
return 'What’s the EU VAT number?';
2679+
}
26722680
},
26732681
whatsThisNumber: "What's this number?",
26742682
whereWasTheBusinessIncorporated: 'Where was the business incorporated?',
26752683
whatTypeOfBusinessIsIt: 'What type of business is it?',
26762684
whatsTheBusinessAnnualPayment: "What's the business's annual payment volume?",
26772685
whatsYourExpectedAverageReimbursements: "What's your expected average reimbursement amount?",
26782686
registrationNumber: 'Registration number',
2679-
taxIDEIN: {
2680-
US: 'EIN',
2681-
CA: 'BN',
2682-
UK: 'VRN',
2683-
AUD: 'ABN',
2684-
EU: 'EU VAT',
2687+
taxIDEIN: ({country}: BusinessTaxIDParams) => {
2688+
switch (country) {
2689+
case CONST.COUNTRY.US:
2690+
return 'EIN';
2691+
case CONST.COUNTRY.CA:
2692+
return 'BN';
2693+
case CONST.COUNTRY.GB:
2694+
return 'VRN';
2695+
case CONST.COUNTRY.AU:
2696+
return 'ABN';
2697+
default:
2698+
return 'EU VAT';
2699+
}
26852700
},
26862701
businessAddress: 'Business address',
26872702
businessType: 'Business type',
@@ -2706,6 +2721,20 @@ const translations = {
27062721
findAverageReimbursement: 'Find average reimbursement amount',
27072722
error: {
27082723
registrationNumber: 'Please provide a valid registration number',
2724+
taxIDEIN: ({country}: BusinessTaxIDParams) => {
2725+
switch (country) {
2726+
case CONST.COUNTRY.US:
2727+
return 'Please provide a valid Employer Identification Number (EIN)';
2728+
case CONST.COUNTRY.CA:
2729+
return 'Please provide a valid Business Number (BN)';
2730+
case CONST.COUNTRY.GB:
2731+
return 'Please provide a valid VAT Registration Number (VRN)';
2732+
case CONST.COUNTRY.AU:
2733+
return 'Please provide a valid Australian Business Number (ABN)';
2734+
default:
2735+
return 'Please provide a valid EU VAT number';
2736+
}
2737+
},
27092738
},
27102739
},
27112740
beneficialOwnerInfoStep: {

src/languages/es.ts

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import type {
3131
BillingBannerInsufficientFundsParams,
3232
BillingBannerOwnerAmountOwedOverdueParams,
3333
BillingBannerSubtitleWithDateParams,
34+
BusinessTaxIDParams,
3435
CanceledRequestParams,
3536
CardEndingParams,
3637
CardInfoParams,
@@ -2686,25 +2687,39 @@ const translations = {
26862687
whatsTheBusinessAddress: '¿Cuál es la dirección de la empresa?',
26872688
whatsTheBusinessContactInformation: '¿Cuál es la información de contacto de la empresa?',
26882689
whatsTheBusinessRegistrationNumber: '¿Cuál es el número de registro de la empresa?',
2689-
whatsTheBusinessTaxIDEIN: {
2690-
US: '¿Cuál es el número de identificación del empleador (EIN) de la empresa?',
2691-
CA: '¿Cuál es el número de empresa (BN)?',
2692-
UK: '¿Cuál es el número de registro de IVA (VRN) de la empresa?',
2693-
AUD: '¿Cuál es el número australiano de empresa (ABN)?',
2694-
EU: '¿Cuál es el número de IVA de la UE de la empresa?',
2690+
whatsTheBusinessTaxIDEIN: ({country}: BusinessTaxIDParams) => {
2691+
switch (country) {
2692+
case CONST.COUNTRY.US:
2693+
return '¿Cuál es el Número de Identificación del Empleador (EIN)?';
2694+
case CONST.COUNTRY.CA:
2695+
return '¿Cuál es el Número de Empresa (BN)?';
2696+
case CONST.COUNTRY.GB:
2697+
return '¿Cuál es el Número de Registro de IVA (VRN)?';
2698+
case CONST.COUNTRY.AU:
2699+
return '¿Cuál es el Número de Empresa Australiano (ABN)?';
2700+
default:
2701+
return '¿Cuál es el número de IVA de la UE?';
2702+
}
26952703
},
26962704
whatsThisNumber: '¿Qué es este número?',
26972705
whereWasTheBusinessIncorporated: '¿Dónde se constituyó la empresa?',
26982706
whatTypeOfBusinessIsIt: '¿Qué tipo de empresa es?',
26992707
whatsTheBusinessAnnualPayment: '¿Cuál es el volumen anual de pagos de la empresa?',
27002708
whatsYourExpectedAverageReimbursements: '¿Cuál es el monto promedio esperado de reembolso?',
27012709
registrationNumber: 'Número de registro',
2702-
taxIDEIN: {
2703-
US: 'EIN',
2704-
CA: 'BN',
2705-
UK: 'VRN',
2706-
AUD: 'ABN',
2707-
EU: 'EU VAT',
2710+
taxIDEIN: ({country}: BusinessTaxIDParams) => {
2711+
switch (country) {
2712+
case CONST.COUNTRY.US:
2713+
return 'EIN';
2714+
case CONST.COUNTRY.CA:
2715+
return 'BN';
2716+
case CONST.COUNTRY.GB:
2717+
return 'VRN';
2718+
case CONST.COUNTRY.AU:
2719+
return 'ABN';
2720+
default:
2721+
return 'EU VAT';
2722+
}
27082723
},
27092724
businessAddress: 'Dirección de la empresa',
27102725
businessType: 'Tipo de empresa',
@@ -2729,6 +2744,20 @@ const translations = {
27292744
findAverageReimbursement: 'Encuentra el monto promedio de reembolso',
27302745
error: {
27312746
registrationNumber: 'Por favor, proporciona un número de registro válido',
2747+
taxIDEIN: ({country}: BusinessTaxIDParams) => {
2748+
switch (country) {
2749+
case CONST.COUNTRY.US:
2750+
return 'Por favor, proporcione un Número de Identificación del Empleador (EIN) válido';
2751+
case CONST.COUNTRY.CA:
2752+
return 'Por favor, proporcione un Número de Empresa (BN) válido';
2753+
case CONST.COUNTRY.GB:
2754+
return 'Por favor, proporcione un Número de Registro de IVA (VRN) válido';
2755+
case CONST.COUNTRY.AU:
2756+
return 'Por favor, proporcione un Número de Empresa Australiano (ABN) válido';
2757+
default:
2758+
return 'Por favor, proporcione un número de IVA de la UE válido';
2759+
}
2760+
},
27322761
},
27332762
},
27342763
beneficialOwnerInfoStep: {

src/languages/params.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,10 @@ type TravelTypeParams = {
765765
id?: string;
766766
};
767767

768+
type BusinessTaxIDParams = {
769+
country: string;
770+
};
771+
768772
export type {
769773
SplitExpenseEditTitleParams,
770774
SplitExpenseSubtitleParams,
@@ -1034,4 +1038,5 @@ export type {
10341038
AirlineParams,
10351039
RailTicketParams,
10361040
TravelTypeParams,
1041+
BusinessTaxIDParams,
10371042
};

src/libs/Permissions.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import CONST from '@src/CONST';
33
import type Beta from '@src/types/onyx/Beta';
44

55
function canUseAllBetas(betas: OnyxEntry<Beta[]>): boolean {
6-
return true;
76
return !!betas?.includes(CONST.BETAS.ALL);
87
}
98

src/libs/ValidationUtils.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,65 @@ function isValidRegistrationNumber(registrationNumber: string, country: Country
657657
}
658658
}
659659

660+
/**
661+
* Validates the given value as a U.S. Employer Identification Number (EIN).
662+
* Format: XX-XXXXXXX
663+
* @param ein - The EIN to validate.
664+
*/
665+
function isValidEIN(ein: string): boolean {
666+
return /^\d{2}-\d{7}$/.test(ein);
667+
}
668+
669+
/**
670+
* Validates the given value as a UK VAT Registration Number (VRN).
671+
* Format: Optional "GB" prefix followed by 9 digits.
672+
* @param vrn - The VRN to validate.
673+
*/
674+
function isValidVRN(vrn: string): boolean {
675+
return /^(GB)?\d{9}$/.test(vrn);
676+
}
677+
678+
/**
679+
* Validates the given value as a Canadian Business Number (BN).
680+
* Format: 9 digits, optionally followed by a 2-letter program ID and 4-digit reference number.
681+
* Valid program IDs include: RT, RC, RM, RP, etc.
682+
* @param bn - The Business Number to validate.
683+
*/
684+
function isValidBN(bn: string): boolean {
685+
return /^\d{9}([A-Z]{2}\d{4})?$/.test(bn);
686+
}
687+
688+
/**
689+
* Validates the given value as a European Union VAT Number.
690+
* Format: Two-letter country code followed by 8–12 alphanumeric characters.
691+
* @param vat - The VAT number to validate.
692+
* @returns True if the value is a valid EU VAT number; otherwise, false.
693+
*/
694+
function isValidEUVATNumber(vat: string): boolean {
695+
return /^[A-Z]{2}[A-Z0-9]{8,12}$/.test(vat);
696+
}
697+
698+
/**
699+
* Validates the given value as a country-specific tax identification number.
700+
* Delegates to the appropriate country-specific validation function.
701+
* @param number - The tax ID number to validate.
702+
* @param country - The country code (e.g., 'US', 'GB', 'CA', 'AU').
703+
*/
704+
function isValidTaxIDEINNumber(number: string, country: Country | '') {
705+
switch (country) {
706+
case CONST.COUNTRY.AU:
707+
return isValidABN(number);
708+
case CONST.COUNTRY.GB:
709+
return isValidVRN(number);
710+
case CONST.COUNTRY.CA:
711+
return isValidBN(number);
712+
case CONST.COUNTRY.US:
713+
return isValidEIN(number);
714+
default:
715+
return isValidEUVATNumber(number);
716+
}
717+
}
718+
660719
export {
661720
meetsMinimumAgeRequirement,
662721
meetsMaximumAgeRequirement,
@@ -708,4 +767,5 @@ export {
708767
isValidZipCodeInternational,
709768
isValidOwnershipPercentage,
710769
isValidRegistrationNumber,
770+
isValidTaxIDEINNumber,
711771
};

src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/Confirmation.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ function Confirmation({onNext, onMove, isEditing}: SubStepProps) {
101101
},
102102
{
103103
title: values[TAX_ID_EIN_NUMBER],
104-
description: translate('businessInfoStep.taxIDEIN.EU'),
104+
description: translate('businessInfoStep.taxIDEIN', {country: values[COMPANY_COUNTRY_CODE]}),
105105
shouldShowRightIcon: true,
106106
onPress: () => {
107107
onMove(5);

src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/TaxIDEINNumber.tsx

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,36 @@ import SingleFieldStep from '@components/SubStepForms/SingleFieldStep';
55
import useLocalize from '@hooks/useLocalize';
66
import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit';
77
import type {SubStepProps} from '@hooks/useSubStep/types';
8-
import {getFieldRequiredErrors} from '@libs/ValidationUtils';
8+
import {getFieldRequiredErrors, isValidTaxIDEINNumber} from '@libs/ValidationUtils';
99
import ONYXKEYS from '@src/ONYXKEYS';
1010
import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
1111

1212
type TaxIDEINNumberProps = SubStepProps;
1313

14-
const {TAX_ID_EIN_NUMBER} = INPUT_IDS.ADDITIONAL_DATA.CORPAY;
14+
const {TAX_ID_EIN_NUMBER, COMPANY_COUNTRY_CODE} = INPUT_IDS.ADDITIONAL_DATA.CORPAY;
1515
const STEP_FIELDS = [TAX_ID_EIN_NUMBER];
1616

1717
function TaxIDEINNumber({onNext, onMove, isEditing}: TaxIDEINNumberProps) {
1818
const {translate} = useLocalize();
1919

20-
const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
20+
const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {canBeMissing: false});
21+
const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT, {canBeMissing: false});
22+
2123
const defaultValue = reimbursementAccount?.achData?.corpay?.[TAX_ID_EIN_NUMBER] ?? '';
24+
const businessStepCountryValue = reimbursementAccount?.achData?.corpay?.[COMPANY_COUNTRY_CODE] ?? reimbursementAccountDraft?.[COMPANY_COUNTRY_CODE] ?? '';
25+
26+
const validate = useCallback(
27+
(values: FormOnyxValues<typeof ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM> => {
28+
const errors = getFieldRequiredErrors(values, STEP_FIELDS);
2229

23-
const validate = useCallback((values: FormOnyxValues<typeof ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM> => {
24-
return getFieldRequiredErrors(values, STEP_FIELDS);
25-
}, []);
30+
if (values[TAX_ID_EIN_NUMBER] && !isValidTaxIDEINNumber(values[TAX_ID_EIN_NUMBER], businessStepCountryValue)) {
31+
errors[TAX_ID_EIN_NUMBER] = translate('businessInfoStep.error.taxIDEIN', {country: businessStepCountryValue});
32+
}
33+
34+
return errors;
35+
},
36+
[businessStepCountryValue, translate],
37+
);
2638

2739
const handleSubmit = useReimbursementAccountStepFormSubmit({
2840
fieldIds: STEP_FIELDS,
@@ -36,11 +48,11 @@ function TaxIDEINNumber({onNext, onMove, isEditing}: TaxIDEINNumberProps) {
3648
onNext={onNext}
3749
onMove={onMove}
3850
formID={ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM}
39-
formTitle={translate('businessInfoStep.whatsTheBusinessTaxIDEIN.EU')}
51+
formTitle={translate('businessInfoStep.whatsTheBusinessTaxIDEIN', {country: businessStepCountryValue})}
4052
validate={validate}
4153
onSubmit={handleSubmit}
4254
inputId={TAX_ID_EIN_NUMBER}
43-
inputLabel={translate('businessInfoStep.taxIDEIN.UK')}
55+
inputLabel={translate('businessInfoStep.taxIDEIN', {country: businessStepCountryValue})}
4456
defaultValue={defaultValue}
4557
shouldShowHelpLinks={false}
4658
/>

0 commit comments

Comments
 (0)