updates to recurly -> stripe customer upsert script

GitOrigin-RevId: dfe277807f9282804fed5a9cdf86e654a719de96
This commit is contained in:
Simon Gardner
2026-02-06 09:05:15 +00:00
committed by Copybot
parent 4decfd343d
commit 4d338efe56
3 changed files with 1432 additions and 212 deletions
@@ -2,7 +2,6 @@
import lodash from 'lodash'
/*
* This helper can be used by migrate_recurly_customers_to_stripe.mjs
*
* This file can be deleted once the Recurly to Stripe migration is complete.
*/
@@ -181,6 +180,30 @@ export const EU_VAT_COUNTRIES = [
'SK', // Slovakia
]
const EU_VAT_PREFIX_OVERRIDES = {
GR: 'EL', // Greece uses EL prefix for VAT numbers
}
function normalizeTaxId(value) {
if (!value) return ''
return String(value).trim().toUpperCase()
}
function normalizeTaxIdCompact(value) {
return normalizeTaxId(value).replace(/\s+/g, '')
}
function digitsOnly(value) {
return normalizeTaxId(value).replace(/\D+/g, '')
}
function hasEuVatPrefix(country, taxIdValue) {
const normalized = normalizeTaxIdCompact(taxIdValue)
if (!normalized) return false
const prefix = EU_VAT_PREFIX_OVERRIDES[country] || country
return normalized.startsWith(prefix)
}
function caProvinceFromPostalCode(postalCode) {
if (!postalCode) return null
const m = String(postalCode)
@@ -267,6 +290,445 @@ export function getCanadaTaxIdType(taxIdValue, postalCode) {
return null
}
/**
* Determine the Stripe tax ID type for Australia based on the tax ID value.
*
* Source reference:
* - Stripe docs list supported types + example formats (Australia section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'au_abn'|'au_arn'|null}
*/
export function getAustraliaTaxIdType(taxIdValue) {
const digits = digitsOnly(taxIdValue)
if (!digits) return null
// ABN: 11 digits (example: 12345678912)
if (/^\d{11}$/.test(digits)) return 'au_abn'
// ARN: 12 digits (example: 123456789123)
if (/^\d{12}$/.test(digits)) return 'au_arn'
return null
}
/**
* Determine the Stripe tax ID type for Brazil based on the tax ID value.
*
* Source reference:
* - Stripe docs list supported types + example formats (Brazil section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'br_cnpj'|'br_cpf'|null}
*/
export function getBrazilTaxIdType(taxIdValue) {
const digits = digitsOnly(taxIdValue)
if (!digits) return null
// CNPJ: 14 digits (example: 01.234.456/5432-10)
if (/^\d{14}$/.test(digits)) return 'br_cnpj'
// CPF: 11 digits (example: 123.456.789-87)
if (/^\d{11}$/.test(digits)) return 'br_cpf'
return null
}
/**
* Determine the Stripe tax ID type for Bulgaria (EU VAT vs UIC).
*
* Source reference:
* - Stripe docs list supported types + example formats (Bulgaria section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'eu_vat'|'bg_uic'|null}
*/
export function getBulgariaTaxIdType(taxIdValue) {
if (!taxIdValue) return null
// EU VAT: BG prefix (example: BG0123456789)
if (hasEuVatPrefix('BG', taxIdValue)) return 'eu_vat'
// UIC: 9 digits (example: 123456789)
if (/^\d{9}$/.test(digitsOnly(taxIdValue))) return 'bg_uic'
return null
}
/**
* Determine the Stripe tax ID type for Croatia (EU VAT vs OIB).
*
* Source reference:
* - Stripe docs list supported types + example formats (Croatia section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'eu_vat'|'hr_oib'|null}
*/
export function getCroatiaTaxIdType(taxIdValue) {
if (!taxIdValue) return null
// EU VAT: HR prefix (example: HR12345678912)
if (hasEuVatPrefix('HR', taxIdValue)) return 'eu_vat'
// OIB: 11 digits (example: 12345678901)
if (/^\d{11}$/.test(digitsOnly(taxIdValue))) return 'hr_oib'
return null
}
/**
* Determine the Stripe tax ID type for Germany (EU VAT vs Steuer Nummer).
*
* Source reference:
* - Stripe docs list supported types + example formats (Germany section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'eu_vat'|'de_stn'|null}
*/
export function getGermanyTaxIdType(taxIdValue) {
if (!taxIdValue) return null
// EU VAT: DE prefix (example: DE123456789)
if (hasEuVatPrefix('DE', taxIdValue)) return 'eu_vat'
// Steuer Nummer: 10 digits (example: 1234567890)
if (/^\d{10}$/.test(digitsOnly(taxIdValue))) return 'de_stn'
return null
}
/**
* Determine the Stripe tax ID type for Hungary (EU VAT vs HU tax number).
*
* Source reference:
* - Stripe docs list supported types + example formats (Hungary section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'eu_vat'|'hu_tin'|null}
*/
export function getHungaryTaxIdType(taxIdValue) {
if (!taxIdValue) return null
// EU VAT: HU prefix (example: HU12345678)
if (hasEuVatPrefix('HU', taxIdValue)) return 'eu_vat'
// HU tax number: 8-1-2 digits (example: 12345678-1-23)
const normalized = normalizeTaxIdCompact(taxIdValue)
if (/^\d{8}-\d-\d{2}$/.test(normalized)) return 'hu_tin'
return null
}
/**
* Determine the Stripe tax ID type for Japan.
*
* Source reference:
* - Stripe docs list supported types + example formats (Japan section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'jp_cn'|'jp_rn'|'jp_trn'|null}
*/
export function getJapanTaxIdType(taxIdValue) {
const normalized = normalizeTaxIdCompact(taxIdValue)
if (!normalized) return null
// Tax Registration Number: T + 13 digits (example: T1234567891234)
if (/^T\d{13}$/.test(normalized)) return 'jp_trn'
// Corporate Number: 13 digits (example: 1234567891234)
if (/^\d{13}$/.test(normalized)) return 'jp_cn'
// Registered Foreign Businesses: 5 digits (example: 12345)
if (/^\d{5}$/.test(normalized)) return 'jp_rn'
return null
}
/**
* Determine the Stripe tax ID type for Liechtenstein (UID vs VAT).
*
* Source reference:
* - Stripe docs list supported types + example formats (Liechtenstein section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'li_uid'|'li_vat'|null}
*/
export function getLiechtensteinTaxIdType(taxIdValue) {
const normalized = normalizeTaxIdCompact(taxIdValue)
if (!normalized) return null
// UID: CHE + 9 digits (example: CHE123456789)
if (/^CHE\d{9}$/.test(normalized)) return 'li_uid'
// VAT: 5 digits (example: 12345)
if (/^\d{5}$/.test(digitsOnly(normalized))) return 'li_vat'
return null
}
/**
* Determine the Stripe tax ID type for Malaysia (FRP, ITN, SST).
*
* Source reference:
* - Stripe docs list supported types + example formats (Malaysia section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'my_frp'|'my_itn'|'my_sst'|null}
*/
export function getMalaysiaTaxIdType(taxIdValue) {
const normalized = normalizeTaxIdCompact(taxIdValue)
if (!normalized) return null
// FRP: 8 digits (example: 12345678)
if (/^\d{8}$/.test(digitsOnly(normalized))) return 'my_frp'
// ITN: letter + 10 digits (example: C 1234567890)
if (/^[A-Z]\d{10}$/.test(normalized.replace(/\s+/g, ''))) return 'my_itn'
// SST: A12-3456-78912345
if (/^[A-Z]\d{2}-\d{4}-\d{8}$/.test(normalized)) return 'my_sst'
return null
}
/**
* Determine the Stripe tax ID type for Norway (VAT vs VOEC).
*
* Source reference:
* - Stripe docs list supported types + example formats (Norway section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'no_vat'|'no_voec'|null}
*/
export function getNorwayTaxIdType(taxIdValue) {
const normalized = normalizeTaxIdCompact(taxIdValue)
if (!normalized) return null
// VAT: 9 digits + MVA (example: 123456789MVA)
if (/^\d{9}MVA$/.test(normalized)) return 'no_vat'
// VOEC: 7 digits (example: 1234567)
if (/^\d{7}$/.test(digitsOnly(normalized))) return 'no_voec'
return null
}
/**
* Determine the Stripe tax ID type for Poland (EU VAT vs NIP).
*
* Source reference:
* - Stripe docs list supported types + example formats (Poland section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'eu_vat'|'pl_nip'|null}
*/
export function getPolandTaxIdType(taxIdValue) {
if (!taxIdValue) return null
// EU VAT: PL prefix (example: PL1234567890)
if (hasEuVatPrefix('PL', taxIdValue)) return 'eu_vat'
// NIP: 10 digits (example: 1234567890)
if (/^\d{10}$/.test(digitsOnly(taxIdValue))) return 'pl_nip'
return null
}
/**
* Determine the Stripe tax ID type for Romania (EU VAT vs TIN).
*
* Source reference:
* - Stripe docs list supported types + example formats (Romania section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'eu_vat'|'ro_tin'|null}
*/
export function getRomaniaTaxIdType(taxIdValue) {
if (!taxIdValue) return null
// EU VAT: RO prefix (example: RO1234567891)
if (hasEuVatPrefix('RO', taxIdValue)) return 'eu_vat'
// TIN: 13 digits (example: 1234567890123)
if (/^\d{13}$/.test(digitsOnly(taxIdValue))) return 'ro_tin'
return null
}
/**
* Determine the Stripe tax ID type for Russia (INN vs KPP).
*
* Source reference:
* - Stripe docs list supported types + example formats (Russia section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'ru_inn'|'ru_kpp'|null}
*/
export function getRussiaTaxIdType(taxIdValue) {
const digits = digitsOnly(taxIdValue)
if (!digits) return null
// INN: 10 digits (example: 1234567891)
if (/^\d{10}$/.test(digits)) return 'ru_inn'
// KPP: 9 digits (example: 123456789)
if (/^\d{9}$/.test(digits)) return 'ru_kpp'
return null
}
/**
* Determine the Stripe tax ID type for Singapore (GST vs UEN).
*
* Source reference:
* - Stripe docs list supported types + example formats (Singapore section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'sg_gst'|'sg_uen'|null}
*/
export function getSingaporeTaxIdType(taxIdValue) {
const normalized = normalizeTaxIdCompact(taxIdValue)
if (!normalized) return null
// GST: M + 8 digits + letter (example: M12345678X)
if (/^M\d{8}[A-Z]$/.test(normalized)) return 'sg_gst'
// UEN: 9 digits + letter (example: 123456789F)
if (/^\d{9}[A-Z]$/.test(normalized)) return 'sg_uen'
return null
}
/**
* Determine the Stripe tax ID type for Slovenia (EU VAT vs TIN).
*
* Source reference:
* - Stripe docs list supported types + example formats (Slovenia section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'eu_vat'|'si_tin'|null}
*/
export function getSloveniaTaxIdType(taxIdValue) {
if (!taxIdValue) return null
// EU VAT: SI prefix (example: SI12345678)
if (hasEuVatPrefix('SI', taxIdValue)) return 'eu_vat'
// TIN: 8 digits (example: 12345678)
if (/^\d{8}$/.test(digitsOnly(taxIdValue))) return 'si_tin'
return null
}
/**
* Determine the Stripe tax ID type for Spain (EU VAT vs CIF/NIF).
*
* Source reference:
* - Stripe docs list supported types + example formats (Spain section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'eu_vat'|'es_cif'|null}
*/
export function getSpainTaxIdType(taxIdValue) {
const normalized = normalizeTaxIdCompact(taxIdValue)
if (!normalized) return null
// EU VAT: ES prefix (example: ESA1234567Z)
if (hasEuVatPrefix('ES', normalized)) return 'eu_vat'
// CIF/NIF: A12345678 (letter + 7 digits + alnum)
if (/^[A-Z]\d{7}[A-Z0-9]$/.test(normalized)) return 'es_cif'
return null
}
/**
* Determine the Stripe tax ID type for Switzerland (UID vs VAT).
*
* Source reference:
* - Stripe docs list supported types + example formats (Switzerland section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'ch_uid'|'ch_vat'|null}
*/
export function getSwitzerlandTaxIdType(taxIdValue) {
const normalized = normalizeTaxIdCompact(taxIdValue)
if (!normalized) return null
const alnum = normalized.replace(/[^A-Z0-9]/g, '')
// UID: CHE-123.456.789 HR
if (/^CHE\d{9}HR$/.test(alnum)) return 'ch_uid'
// VAT: CHE-123.456.789 MWST
if (/^CHE\d{9}MWST$/.test(alnum)) return 'ch_vat'
return null
}
/**
* Determine the Stripe tax ID type for the United Kingdom (GB VAT vs EU VAT for NI).
*
* Source reference:
* - Stripe docs list supported types + example formats (UK section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'gb_vat'|'eu_vat'|null}
*/
export function getUkTaxIdType(taxIdValue) {
const normalized = normalizeTaxIdCompact(taxIdValue)
if (!normalized) return null
// Northern Ireland VAT numbers use XI prefix
if (/^XI[A-Z0-9]+$/.test(normalized)) return 'eu_vat'
// GB VAT numbers use GB prefix
if (/^GB[A-Z0-9]+$/.test(normalized)) return 'gb_vat'
return null
}
/**
* Determine the Stripe tax ID type for Uzbekistan (TIN vs VAT).
*
* Source reference:
* - Stripe docs list supported types + example formats (Uzbekistan section)
* https://docs.stripe.com/billing/customer/tax-ids
*
* @param {string|undefined|null} taxIdValue
* @returns {'uz_tin'|'uz_vat'|null}
*/
export function getUzbekistanTaxIdType(taxIdValue) {
const digits = digitsOnly(taxIdValue)
if (!digits) return null
// VAT: 12 digits (example: 123456789012)
if (/^\d{12}$/.test(digits)) return 'uz_vat'
// TIN: 9 digits (example: 123456789)
if (/^\d{9}$/.test(digits)) return 'uz_tin'
return null
}
/**
* Get the Stripe tax ID type for a given country + tax ID value.
*
@@ -285,79 +747,152 @@ export function getTaxIdType(country, taxIdValue, postalCode) {
const upperCountry = String(country).toUpperCase()
if (upperCountry === 'EU') {
// European One Stop Shop VAT number for non-Union scheme
const normalized = normalizeTaxIdCompact(taxIdValue)
return /^EU\d+$/.test(normalized) ? 'eu_oss_vat' : null
}
// EU VAT
if (EU_VAT_COUNTRIES.includes(upperCountry)) {
return 'eu_vat'
// If this country has multiple types, we'll handle it below with a dedicated function.
// Otherwise, EU VAT is the only supported type for that country.
const euVatOnlyCountries = new Set([
'AT',
'BE',
'CY',
'CZ',
'DK',
'EE',
'FI',
'FR',
'GR',
'IE',
'IT',
'LT',
'LU',
'LV',
'MT',
'NL',
'PT',
'SE',
'SK',
])
if (euVatOnlyCountries.has(upperCountry)) return 'eu_vat'
}
// Canada
if (upperCountry === 'CA') {
return getCanadaTaxIdType(taxIdValue, postalCode)
}
// Multi-type countries
if (upperCountry === 'CA') return getCanadaTaxIdType(taxIdValue, postalCode)
if (upperCountry === 'AU') return getAustraliaTaxIdType(taxIdValue)
if (upperCountry === 'BR') return getBrazilTaxIdType(taxIdValue)
if (upperCountry === 'BG') return getBulgariaTaxIdType(taxIdValue)
if (upperCountry === 'HR') return getCroatiaTaxIdType(taxIdValue)
if (upperCountry === 'DE') return getGermanyTaxIdType(taxIdValue)
if (upperCountry === 'HU') return getHungaryTaxIdType(taxIdValue)
if (upperCountry === 'JP') return getJapanTaxIdType(taxIdValue)
if (upperCountry === 'LI') return getLiechtensteinTaxIdType(taxIdValue)
if (upperCountry === 'MY') return getMalaysiaTaxIdType(taxIdValue)
if (upperCountry === 'NO') return getNorwayTaxIdType(taxIdValue)
if (upperCountry === 'PL') return getPolandTaxIdType(taxIdValue)
if (upperCountry === 'RO') return getRomaniaTaxIdType(taxIdValue)
if (upperCountry === 'RU') return getRussiaTaxIdType(taxIdValue)
if (upperCountry === 'SG') return getSingaporeTaxIdType(taxIdValue)
if (upperCountry === 'SI') return getSloveniaTaxIdType(taxIdValue)
if (upperCountry === 'ES') return getSpainTaxIdType(taxIdValue)
if (upperCountry === 'CH') return getSwitzerlandTaxIdType(taxIdValue)
if (upperCountry === 'GB') return getUkTaxIdType(taxIdValue)
if (upperCountry === 'UZ') return getUzbekistanTaxIdType(taxIdValue)
// Country-specific tax IDs (all Stripe-supported types)
// See: https://docs.stripe.com/api/tax_ids/create#create_tax_id-type
// See: https://docs.stripe.com/billing/customer/tax-ids
const countryTaxIdTypes = {
// Europe (non-EU)
GB: 'gb_vat',
// CH: 'ch_vat',
// NO: 'no_vat',
// IS: 'is_vat',
// LI: 'li_uid',
// TR: 'tr_tin',
// Africa
AO: 'ao_tin',
BH: 'bh_vat',
BF: 'bf_ifu',
BJ: 'bj_ifu',
CM: 'cm_niu',
CV: 'cv_nif',
CD: 'cd_nif',
EG: 'eg_tin',
ET: 'et_tin',
GN: 'gn_nif',
KE: 'ke_pin',
MA: 'ma_vat',
MR: 'mr_nif',
NG: 'ng_tin',
SN: 'sn_ninea',
TZ: 'tz_vat',
UG: 'ug_tin',
ZA: 'za_vat',
ZM: 'zm_tin',
ZW: 'zw_tin',
// // Americas
// Americas
AR: 'ar_cuit',
BO: 'bo_tin',
BS: 'bs_tin',
BB: 'bb_tin',
CL: 'cl_tin',
CO: 'co_nit',
CR: 'cr_tin',
DO: 'do_rcn',
EC: 'ec_ruc',
MX: 'mx_rfc',
PE: 'pe_ruc',
SR: 'sr_fin',
SV: 'sv_nit',
US: 'us_ein',
// CA: 'ca_bn', // this is more complex, see getCanadaTaxIdType()
// MX: 'mx_rfc',
// BR: 'br_cnpj',
// CL: 'cl_tin',
// CO: 'co_nit',
// AR: 'ar_cuit',
// BO: 'bo_tin',
// CR: 'cr_tin',
// DO: 'do_rcn',
// EC: 'ec_ruc',
// PE: 'pe_ruc',
// UY: 'uy_ruc',
// VE: 've_rif',
// SV: 'sv_nit',
UY: 'uy_ruc',
VE: 've_rif',
// // Asia-Pacific
// AU: 'au_abn',
// NZ: 'nz_gst',
// JP: 'jp_cn',
// KR: 'kr_brn',
// CN: 'cn_tin',
// HK: 'hk_br',
// TW: 'tw_vat',
// SG: 'sg_gst',
// MY: 'my_sst',
// TH: 'th_vat',
// ID: 'id_npwp',
// PH: 'ph_tin',
// IN: 'in_gst',
// VN: 'vn_tin',
// Asia-Pacific
BD: 'bd_bin',
CN: 'cn_tin',
HK: 'hk_br',
ID: 'id_npwp',
IN: 'in_gst',
KH: 'kh_tin',
KR: 'kr_brn',
KZ: 'kz_bin',
KG: 'kg_tin',
LA: 'la_tin',
NZ: 'nz_gst',
NP: 'np_pan',
PH: 'ph_tin',
TH: 'th_vat',
TW: 'tw_vat',
VN: 'vn_tin',
// // Middle East
// AE: 'ae_trn',
// SA: 'sa_vat',
// BH: 'bh_vat',
// OM: 'om_vat',
// IL: 'il_vat',
// Europe (non-EU)
AD: 'ad_nrt',
AL: 'al_tin',
AM: 'am_tin',
AW: 'aw_tin',
AZ: 'az_tin',
BA: 'ba_tin',
BY: 'by_tin',
CH: 'ch_vat',
GE: 'ge_vat',
IS: 'is_vat',
LI: 'li_uid',
MD: 'md_vat',
ME: 'me_pib',
MK: 'mk_vat',
NO: 'no_vat',
RS: 'rs_pib',
RU: 'ru_inn',
TR: 'tr_tin',
UA: 'ua_vat',
// // Africa
// ZA: 'za_vat',
// EG: 'eg_tin',
// KE: 'ke_pin',
// NG: 'ng_tin',
// Middle East
AE: 'ae_trn',
IL: 'il_vat',
OM: 'om_vat',
SA: 'sa_vat',
// // Other
// GE: 'ge_vat',
// UA: 'ua_vat',
// RS: 'rs_pib',
// MD: 'md_vat',
// AD: 'ad_nrt',
// Other
EU: 'eu_oss_vat',
}
return countryTaxIdTypes[upperCountry] || null
@@ -16,6 +16,26 @@ import {
coalesceOrEqualOrThrowName,
coalesceOrThrowVATNumber,
getCanadaTaxIdType,
getAustraliaTaxIdType,
getBrazilTaxIdType,
getBulgariaTaxIdType,
getCroatiaTaxIdType,
getGermanyTaxIdType,
getHungaryTaxIdType,
getJapanTaxIdType,
getLiechtensteinTaxIdType,
getMalaysiaTaxIdType,
getNorwayTaxIdType,
getPolandTaxIdType,
getRomaniaTaxIdType,
getRussiaTaxIdType,
getSingaporeTaxIdType,
getSloveniaTaxIdType,
getSpainTaxIdType,
getSwitzerlandTaxIdType,
getUkTaxIdType,
getUzbekistanTaxIdType,
getTaxIdType,
coalesceOrThrowPaymentMethod,
} from './migrate_recurly_customers_to_stripe.helpers.mjs'
@@ -232,6 +252,108 @@ test('getCanadaTaxIdType returns null when format is unknown/ambiguous', () => {
assert.equal(getCanadaTaxIdType('PST12345678', null), null)
})
test('getAustraliaTaxIdType distinguishes ABN vs ARN', () => {
assert.equal(getAustraliaTaxIdType('12345678912'), 'au_abn')
assert.equal(getAustraliaTaxIdType('123456789123'), 'au_arn')
})
test('getBrazilTaxIdType distinguishes CNPJ vs CPF', () => {
assert.equal(getBrazilTaxIdType('01.234.456/5432-10'), 'br_cnpj')
assert.equal(getBrazilTaxIdType('123.456.789-87'), 'br_cpf')
})
test('getBulgariaTaxIdType distinguishes EU VAT vs UIC', () => {
assert.equal(getBulgariaTaxIdType('BG0123456789'), 'eu_vat')
assert.equal(getBulgariaTaxIdType('123456789'), 'bg_uic')
})
test('getCroatiaTaxIdType distinguishes EU VAT vs OIB', () => {
assert.equal(getCroatiaTaxIdType('HR12345678912'), 'eu_vat')
assert.equal(getCroatiaTaxIdType('12345678901'), 'hr_oib')
})
test('getGermanyTaxIdType distinguishes EU VAT vs Steuer Nummer', () => {
assert.equal(getGermanyTaxIdType('DE123456789'), 'eu_vat')
assert.equal(getGermanyTaxIdType('1234567890'), 'de_stn')
})
test('getHungaryTaxIdType distinguishes EU VAT vs HU tax number', () => {
assert.equal(getHungaryTaxIdType('HU12345678'), 'eu_vat')
assert.equal(getHungaryTaxIdType('12345678-1-23'), 'hu_tin')
})
test('getJapanTaxIdType distinguishes TRN, CN, RN', () => {
assert.equal(getJapanTaxIdType('T1234567891234'), 'jp_trn')
assert.equal(getJapanTaxIdType('1234567891234'), 'jp_cn')
assert.equal(getJapanTaxIdType('12345'), 'jp_rn')
})
test('getLiechtensteinTaxIdType distinguishes UID vs VAT', () => {
assert.equal(getLiechtensteinTaxIdType('CHE123456789'), 'li_uid')
assert.equal(getLiechtensteinTaxIdType('12345'), 'li_vat')
})
test('getMalaysiaTaxIdType distinguishes FRP, ITN, SST', () => {
assert.equal(getMalaysiaTaxIdType('12345678'), 'my_frp')
assert.equal(getMalaysiaTaxIdType('C 1234567890'), 'my_itn')
assert.equal(getMalaysiaTaxIdType('A12-3456-78912345'), 'my_sst')
})
test('getNorwayTaxIdType distinguishes VAT vs VOEC', () => {
assert.equal(getNorwayTaxIdType('123456789MVA'), 'no_vat')
assert.equal(getNorwayTaxIdType('1234567'), 'no_voec')
})
test('getPolandTaxIdType distinguishes EU VAT vs NIP', () => {
assert.equal(getPolandTaxIdType('PL1234567890'), 'eu_vat')
assert.equal(getPolandTaxIdType('1234567890'), 'pl_nip')
})
test('getRomaniaTaxIdType distinguishes EU VAT vs TIN', () => {
assert.equal(getRomaniaTaxIdType('RO1234567891'), 'eu_vat')
assert.equal(getRomaniaTaxIdType('1234567890123'), 'ro_tin')
})
test('getRussiaTaxIdType distinguishes INN vs KPP', () => {
assert.equal(getRussiaTaxIdType('1234567891'), 'ru_inn')
assert.equal(getRussiaTaxIdType('123456789'), 'ru_kpp')
})
test('getSingaporeTaxIdType distinguishes GST vs UEN', () => {
assert.equal(getSingaporeTaxIdType('M12345678X'), 'sg_gst')
assert.equal(getSingaporeTaxIdType('123456789F'), 'sg_uen')
})
test('getSloveniaTaxIdType distinguishes EU VAT vs TIN', () => {
assert.equal(getSloveniaTaxIdType('SI12345678'), 'eu_vat')
assert.equal(getSloveniaTaxIdType('12345678'), 'si_tin')
})
test('getSpainTaxIdType distinguishes EU VAT vs CIF', () => {
assert.equal(getSpainTaxIdType('ESA1234567Z'), 'eu_vat')
assert.equal(getSpainTaxIdType('A12345678'), 'es_cif')
})
test('getSwitzerlandTaxIdType distinguishes UID vs VAT', () => {
assert.equal(getSwitzerlandTaxIdType('CHE-123.456.789 HR'), 'ch_uid')
assert.equal(getSwitzerlandTaxIdType('CHE-123.456.789 MWST'), 'ch_vat')
})
test('getUkTaxIdType distinguishes GB VAT vs EU VAT (NI)', () => {
assert.equal(getUkTaxIdType('GB123456789'), 'gb_vat')
assert.equal(getUkTaxIdType('XI123456789'), 'eu_vat')
})
test('getUzbekistanTaxIdType distinguishes TIN vs VAT', () => {
assert.equal(getUzbekistanTaxIdType('123456789'), 'uz_tin')
assert.equal(getUzbekistanTaxIdType('123456789012'), 'uz_vat')
})
test('getTaxIdType handles EU OSS VAT and EU VAT defaults', () => {
assert.equal(getTaxIdType('EU', 'EU123456789'), 'eu_oss_vat')
assert.equal(getTaxIdType('AT', 'ATU12345678'), 'eu_vat')
})
test('coalesceOrThrowPaymentMethod throws when payment methods array is empty', () => {
assert.throws(
() => coalesceOrThrowPaymentMethod([], 'cus_123', {}),
File diff suppressed because it is too large Load Diff