Wrapper for BeamLabCountries with billing-specific functions.
Provides a convenient API for working with country data in a billing context: country selection, tax rates, EU membership.
Includes workaround for charlist bug in VAT rates until fixed upstream.
Examples
# Get list of countries for dropdown
countries = CountryData.countries_for_select()
# [{"🇦🇩 Andorra", "AD"}, {"🇦🇪 United Arab Emirates", "AE"}, ...]
# Get standard VAT rate
rate = CountryData.get_standard_vat_rate("EE")
# #Decimal<0.20>
# Check EU membership
CountryData.eu_member?("EE")
# true
# Get country information
country = CountryData.get_country("DE")
# %BeamLabCountries.Country{name: "Germany", ...}
# Format company address from Settings
address = CountryData.format_company_address()
# "123 Business Street\nTallinn 10115\nEstonia"
Summary
Functions
Get list of countries for select dropdown.
Get list of EEA countries (EU + Norway, Iceland, Liechtenstein).
Check if country is an EEA (European Economic Area) member.
Get list of EU countries.
Get list of EU countries for select dropdown.
Check if country is an EU member.
Check if country with given code exists.
Format company address from Settings for document printing.
Get bank details from consolidated Settings.
Get company information from consolidated Settings.
Get country by alpha-2 code.
Get country name.
Get country currency code.
Get country flag (emoji).
Get standard VAT rate as percentage (integer).
Get standard VAT rate for a country as Decimal.
Get the subdivision label for a country.
Get all VAT rates with workaround for charlist bug.
Get all countries sorted by name.
Validate IBAN format (length based on bank country, not company country).
Validate SWIFT/BIC format (8 or 11 characters).
Functions
Get list of countries for select dropdown.
Returns list of tuples {display_name, alpha2_code} for use in Phoenix form selects.
Examples
iex> countries = CountryData.countries_for_select()
iex> {"🇦🇫 Afghanistan", "AF"} in countries
true
Get list of EEA countries (EU + Norway, Iceland, Liechtenstein).
Check if country is an EEA (European Economic Area) member.
EEA includes EU + Norway, Iceland, Liechtenstein.
Examples
iex> CountryData.eea_member?("EE")
true
iex> CountryData.eea_member?("NO")
true
iex> CountryData.eea_member?("CH")
false
Get list of EU countries.
Examples
iex> eu = CountryData.eu_countries()
iex> length(eu)
27
iex> Enum.map(eu, & &1.alpha2) |> Enum.sort() |> Enum.take(5)
["AT", "BE", "BG", "CY", "CZ"]
Get list of EU countries for select dropdown.
Check if country is an EU member.
Examples
iex> CountryData.eu_member?("EE")
true
iex> CountryData.eu_member?("GB")
false
iex> CountryData.eu_member?("US")
false
Check if country with given code exists.
Examples
iex> CountryData.exists?("EE")
true
iex> CountryData.exists?("XX")
false
Format company address from Settings for document printing.
Assembles address from individual fields (address_line1, address_line2, city, state, postal_code, country) into a single string with line breaks.
Returns
Formatted address as string, for example:
123 Business Street
Suite 100
Tallinn 10115
EstoniaExamples
iex> CountryData.format_company_address()
"123 Business Street\nTallinn 10115\nEstonia"
Get bank details from consolidated Settings.
Reads from company_bank_details JSONB with fallback to legacy billing_bank_* keys.
Get company information from consolidated Settings.
Reads from company_info JSONB with fallback to legacy billing_company_* keys.
Get country by alpha-2 code.
Examples
iex> country = CountryData.get_country("EE")
iex> country.name
"Estonia"
iex> CountryData.get_country("XX")
nil
Get country name.
Examples
iex> CountryData.get_country_name("EE")
"Estonia"
iex> CountryData.get_country_name("XX")
nil
Get country currency code.
Examples
iex> CountryData.get_currency_code("EE")
"EUR"
iex> CountryData.get_currency_code("GB")
"GBP"
iex> CountryData.get_currency_code("US")
"USD"
Get country flag (emoji).
Examples
iex> CountryData.get_flag("EE")
"🇪🇪"
Get standard VAT rate as percentage (integer).
Returns rate as percentage (20 = 20%).
Examples
iex> CountryData.get_standard_vat_percent("EE")
20
iex> CountryData.get_standard_vat_percent("DE")
19
iex> CountryData.get_standard_vat_percent("US")
0
Get standard VAT rate for a country as Decimal.
Returns rate in decimal format (0.20 = 20%). If country not found or has no VAT rates, returns 0.
Examples
iex> CountryData.get_standard_vat_rate("EE")
#Decimal<0.20>
iex> CountryData.get_standard_vat_rate("DE")
#Decimal<0.19>
iex> CountryData.get_standard_vat_rate("US")
#Decimal<0>
Get the subdivision label for a country.
Returns appropriate label like "State", "Province", "Region", etc. based on what the country uses for administrative divisions.
Examples
iex> CountryData.get_subdivision_label("US")
"State"
iex> CountryData.get_subdivision_label("CA")
"Province"
iex> CountryData.get_subdivision_label("EE")
"County"
Get all VAT rates with workaround for charlist bug.
Returns map with normalized rates:
- :standard - standard rate (integer)
- :reduced - reduced rates (list of integers)
- :super_reduced - super reduced rate (integer or nil)
- :parking - parking rate (integer or nil)
Examples
iex> CountryData.get_vat_rates("EE")
%{standard: 20, reduced: [9], super_reduced: nil, parking: nil}
iex> CountryData.get_vat_rates("FR")
%{standard: 20, reduced: [5.5, 10], super_reduced: 2.1, parking: nil}
iex> CountryData.get_vat_rates("US")
nil
Get all countries sorted by name.
Examples
iex> countries = CountryData.list_countries()
iex> length(countries)
250
iex> hd(countries).name
"Afghanistan"
Validate IBAN format (length based on bank country, not company country).
Bank can be in a different country than the company - this is legal. Validates format and length based on IBAN's country prefix.
Returns :ok or {:error, reason}.
Examples
iex> CountryData.validate_iban_format("EE382200221020145685", "EE")
:ok
iex> CountryData.validate_iban_format("DE89370400440532013000", "EE")
:ok # German bank for Estonian company is valid
iex> CountryData.validate_iban_format("DE123", "EE")
{:error, "IBAN must be 22 characters for DE"}
Validate SWIFT/BIC format (8 or 11 characters).
SWIFT codes structure:
- 4 letters: bank code
- 2 letters: country code (ISO 3166)
- 2 characters: location code
- 3 characters (optional): branch code
Examples
iex> CountryData.validate_swift_format("HABAEE2X")
:ok
iex> CountryData.validate_swift_format("HABAEE2XXXX")
:ok
iex> CountryData.validate_swift_format("INVALID")
{:error, "SWIFT/BIC must be 8 or 11 characters"}