131 lines
3.9 KiB
Ruby
131 lines
3.9 KiB
Ruby
class APIGeoService
|
||
class << self
|
||
def countries(locale: I18n.locale)
|
||
I18nData.countries(locale)
|
||
.merge(get_localized_additional_countries(locale))
|
||
.map { |(code, name)| { name:, code: } }
|
||
.sort_by { I18n.transliterate(_1[:name].tr('î', 'Î')) }
|
||
end
|
||
|
||
def country_name(code, locale: I18n.locale)
|
||
countries(locale:).find { _1[:code] == code }&.dig(:name)
|
||
end
|
||
|
||
def country_code(name)
|
||
return if name.nil?
|
||
code = I18nData.country_code(name) || I18nData.country_code(name.humanize) || I18nData.country_code(name.titleize)
|
||
if code.nil?
|
||
countries_index_fr[I18n.transliterate(name).upcase]&.dig(:code)
|
||
else
|
||
code
|
||
end
|
||
end
|
||
|
||
def regions
|
||
get_from_api_geo(:regions).sort_by { I18n.transliterate(_1[:name]) }
|
||
end
|
||
|
||
def region_name(code)
|
||
regions.find { _1[:code] == code }&.dig(:name)
|
||
end
|
||
|
||
def region_code(name)
|
||
return if name.nil?
|
||
regions.find { _1[:name] == name }&.dig(:code)
|
||
end
|
||
|
||
def departements
|
||
[{ code: '99', name: 'Etranger' }] + get_from_api_geo('departements?zone=metro,drom,com').sort_by { _1[:code] }
|
||
end
|
||
|
||
def departement_name(code)
|
||
departements.find { _1[:code] == code }&.dig(:name)
|
||
end
|
||
|
||
def departement_code(name)
|
||
return if name.nil?
|
||
departements.find { _1[:name] == name }&.dig(:code)
|
||
end
|
||
|
||
def epcis(departement_code)
|
||
get_from_api_geo("epcis?codeDepartement=#{departement_code}").sort_by { I18n.transliterate(_1[:name]) }
|
||
end
|
||
|
||
def epci_name(departement_code, code)
|
||
epcis(departement_code).find { _1[:code] == code }&.dig(:name)
|
||
end
|
||
|
||
def epci_code(departement_code, name)
|
||
epcis(departement_code).find { _1[:name] == name }&.dig(:code)
|
||
end
|
||
|
||
def communes(departement_code)
|
||
get_from_api_geo("communes?codeDepartement=#{departement_code}&type=commune-actuelle,arrondissement-municipal").sort_by { I18n.transliterate([_1[:name], _1[:postal_code]].join(' ')) }
|
||
end
|
||
|
||
def communes_by_postal_code(postal_code)
|
||
if postal_code.size > 3
|
||
metro_code = postal_code[0..1]
|
||
drom_com_code = postal_code[0..2]
|
||
if metro_code == '20'
|
||
communes('2A') + communes('2B')
|
||
elsif metro_code == '97' || metro_code == '98'
|
||
departement_name(drom_com_code) ? communes(drom_com_code) : []
|
||
else
|
||
departement_name(metro_code) ? communes(metro_code) : []
|
||
end
|
||
.filter { _1[:postal_code] == postal_code }
|
||
.sort_by { I18n.transliterate([_1[:name], _1[:postal_code]].join(' ')) }
|
||
else
|
||
[]
|
||
end
|
||
end
|
||
|
||
def commune_name(departement_code, code)
|
||
communes(departement_code).find { _1[:code] == code }&.dig(:name)
|
||
end
|
||
|
||
def commune_code(departement_code, name)
|
||
communes(departement_code).find { _1[:name] == name }&.dig(:code)
|
||
end
|
||
|
||
private
|
||
|
||
def get_from_api_geo(scope)
|
||
Rails.cache.fetch("api_geo_#{scope}", expires_in: 1.year) do
|
||
response = Typhoeus.get("#{API_GEO_URL}/#{scope}")
|
||
JSON.parse(response.body).map(&:symbolize_keys).flat_map do |result|
|
||
item = {
|
||
name: result[:nom].tr("'", '’'),
|
||
code: result[:code],
|
||
epci_code: result[:codeEpci],
|
||
departement_code: result[:codeDepartement]
|
||
}.compact
|
||
|
||
if result[:codesPostaux].present?
|
||
result[:codesPostaux].map { item.merge(postal_code: _1) }
|
||
else
|
||
[item]
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
def countries_index_fr
|
||
Rails.cache.fetch('countries_index_fr', expires_in: 1.year) do
|
||
countries(locale: 'FR').index_by { I18n.transliterate(_1[:name]).upcase }
|
||
end
|
||
end
|
||
|
||
def get_localized_additional_countries(locale)
|
||
additional_countries[locale.to_s.upcase] || {}
|
||
end
|
||
|
||
def additional_countries
|
||
{
|
||
'FR' => { 'XK' => 'Kosovo' },
|
||
'EN' => { 'XK' => 'Kosovo' }
|
||
}
|
||
end
|
||
end
|
||
end
|