Merge pull request #10749 from mfo/US/commune-without-insee
correctif: ETQ administrateur/instructeur, je souhaite que les champs de type commune aient tjr un code insee afin de router de maniere fiable
This commit is contained in:
commit
915779c9b0
10 changed files with 305 additions and 68 deletions
|
@ -3,12 +3,12 @@
|
|||
class DataSources::CommuneController < ApplicationController
|
||||
def search
|
||||
if params[:q].present? && params[:q].length > 1
|
||||
response = fetch_results
|
||||
response = APIGeoService.commune_by_name_or_postal_code(params[:q])
|
||||
|
||||
if response.success?
|
||||
results = JSON.parse(response.body, symbolize_names: true)
|
||||
|
||||
render json: format_results(results)
|
||||
render json: APIGeoService.format_commune_response(results, params[:with_combined_code])
|
||||
else
|
||||
render json: []
|
||||
end
|
||||
|
@ -16,70 +16,4 @@ class DataSources::CommuneController < ApplicationController
|
|||
render json: []
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_results
|
||||
if postal_code?(params[:q])
|
||||
fetch_by_postal_code(params[:q])
|
||||
else
|
||||
fetch_by_name(params[:q])
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_by_name(name)
|
||||
Typhoeus.get("#{API_GEO_URL}/communes", params: {
|
||||
type: 'commune-actuelle,arrondissement-municipal',
|
||||
nom: name,
|
||||
boost: 'population',
|
||||
limit: 100
|
||||
}, timeout: 3)
|
||||
end
|
||||
|
||||
def fetch_by_postal_code(postal_code)
|
||||
Typhoeus.get("#{API_GEO_URL}/communes", params: {
|
||||
type: 'commune-actuelle,arrondissement-municipal',
|
||||
codePostal: postal_code,
|
||||
boost: 'population',
|
||||
limit: 50
|
||||
}, timeout: 3)
|
||||
end
|
||||
|
||||
def postal_code?(string)
|
||||
string.match?(/\A[-+]?\d+\z/) ? true : false
|
||||
end
|
||||
|
||||
def format_results(results)
|
||||
results.reject(&method(:code_metropole?)).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.map do |item|
|
||||
if params[:with_combined_code].present?
|
||||
{
|
||||
label: "#{item[:name]} (#{item[:postal_code]})",
|
||||
value: "#{item[:code]}-#{item[:postal_code]}"
|
||||
}
|
||||
else
|
||||
{
|
||||
label: "#{item[:name]} (#{item[:postal_code]})",
|
||||
value: item[:code],
|
||||
data: item[:postal_code]
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def code_metropole?(result)
|
||||
result[:code].in?(['75056', '13055', '69123'])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,6 +4,9 @@ class Champs::CommuneChamp < Champs::TextChamp
|
|||
store_accessor :value_json, :code_departement, :code_postal, :code_region
|
||||
before_save :on_codes_change, if: :should_refresh_after_code_change?
|
||||
|
||||
validates :external_id, presence: true, if: -> { validate_champ_value_or_prefill? && value.present? }
|
||||
after_validation :instrument_external_id_error, if: -> { errors.include?(:external_id) }
|
||||
|
||||
def departement_name
|
||||
APIGeoService.departement_name(code_departement)
|
||||
end
|
||||
|
@ -101,4 +104,11 @@ class Champs::CommuneChamp < Champs::TextChamp
|
|||
def should_refresh_after_code_change?
|
||||
!departement? || code_postal_changed? || external_id_changed?
|
||||
end
|
||||
|
||||
def instrument_external_id_error
|
||||
Sentry.capture_message(
|
||||
"Commune with value and no external id Edge case reached",
|
||||
extra: { request_id: Current.request_id }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -84,6 +84,14 @@ class APIGeoService
|
|||
communes(departement_code).find { _1[:code] == code }&.dig(:name)
|
||||
end
|
||||
|
||||
def commune_by_name_or_postal_code(query)
|
||||
if postal_code?(query)
|
||||
fetch_by_postal_code(query)
|
||||
else
|
||||
fetch_by_name(query)
|
||||
end
|
||||
end
|
||||
|
||||
def commune_code(departement_code, name)
|
||||
communes(departement_code).find { _1[:name] == name }&.dig(:code)
|
||||
end
|
||||
|
@ -215,8 +223,42 @@ class APIGeoService
|
|||
commune_name(department_code, city_code) || fallback
|
||||
end
|
||||
|
||||
def format_commune_response(results, with_combined_code)
|
||||
results.reject(&method(:code_metropole?)).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.map do |item|
|
||||
if with_combined_code.present?
|
||||
{
|
||||
label: "#{item[:name]} (#{item[:postal_code]})",
|
||||
value: "#{item[:code]}-#{item[:postal_code]}"
|
||||
}
|
||||
else
|
||||
{
|
||||
label: "#{item[:name]} (#{item[:postal_code]})",
|
||||
value: item[:code],
|
||||
data: item[:postal_code]
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def code_metropole?(result)
|
||||
result[:code].in?(['75056', '13055', '69123'])
|
||||
end
|
||||
|
||||
def communes_by_postal_code_map
|
||||
Rails.cache.fetch('api_geo_communes', expires_in: 1.day, version: 3) do
|
||||
departements
|
||||
|
@ -251,6 +293,28 @@ class APIGeoService
|
|||
|
||||
private
|
||||
|
||||
def fetch_by_name(name)
|
||||
Typhoeus.get("#{API_GEO_URL}/communes", params: {
|
||||
type: 'commune-actuelle,arrondissement-municipal',
|
||||
nom: name,
|
||||
boost: 'population',
|
||||
limit: 100
|
||||
}, timeout: 3)
|
||||
end
|
||||
|
||||
def fetch_by_postal_code(postal_code)
|
||||
Typhoeus.get("#{API_GEO_URL}/communes", params: {
|
||||
type: 'commune-actuelle,arrondissement-municipal',
|
||||
codePostal: postal_code,
|
||||
boost: 'population',
|
||||
limit: 50
|
||||
}, timeout: 3)
|
||||
end
|
||||
|
||||
def postal_code?(string)
|
||||
string.match?(/\A[-+]?\d+\z/) ? true : false
|
||||
end
|
||||
|
||||
def ban_address_schema
|
||||
JSONSchemer.schema(Rails.root.join('app/schemas/adresse-ban.json'))
|
||||
end
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Maintenance
|
||||
# some of our Champs::CommuneChamp had been corrupted, ie: missing external_id
|
||||
# this tasks fix this issue
|
||||
class FixChampsCommuneHavingValueButNotExternalIdTask < MaintenanceTasks::Task
|
||||
DEFAULT_INSTRUCTEUR_EMAIL = ENV.fetch('DEFAULT_INSTRUCTEUR_EMAIL') { CONTACT_EMAIL }
|
||||
|
||||
def collection
|
||||
Champs::CommuneChamp.where.not(value: nil)
|
||||
end
|
||||
|
||||
def process(champ)
|
||||
return if !fixable?(champ)
|
||||
|
||||
response = APIGeoService.commune_by_name_or_postal_code(champ.value)
|
||||
if !response.success?
|
||||
notify("Strange case of existing commune not requestable", champ)
|
||||
else
|
||||
results = JSON.parse(response.body, symbolize_names: true)
|
||||
formated_results = APIGeoService.format_commune_response(results, true)
|
||||
case formated_results.size
|
||||
when 1
|
||||
champ.code = formated_results.first[:value]
|
||||
champ.save!
|
||||
else # otherwise, we can't find the expected departement
|
||||
champ.code_departement = nil
|
||||
champ.code_postal = nil
|
||||
champ.external_id = nil
|
||||
champ.value = nil
|
||||
champ.save(validate: false)
|
||||
|
||||
ask_user_correction(champ)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def count
|
||||
# 2.4M champs, count is not an option
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ask_user_correction(champ)
|
||||
dossier = champ.dossier
|
||||
|
||||
commentaire = CommentaireService.build(current_instructeur, dossier, { body: "Suite à un problème technique, Veuillez re-remplir le champs : #{champ.libelle}" })
|
||||
dossier.flag_as_pending_correction!(commentaire, :incomplete)
|
||||
end
|
||||
|
||||
def current_instructeur
|
||||
user = User.find_by(email: DEFAULT_INSTRUCTEUR_EMAIL)
|
||||
user ||= User.create(email: DEFAULT_INSTRUCTEUR_EMAIL,
|
||||
password: Random.srand,
|
||||
confirmed_at: Time.zone.now,
|
||||
email_verified_at: Time.zone.now)
|
||||
instructeur = user.instructeur
|
||||
instructeur ||= user.create_instructeur!
|
||||
|
||||
instructeur
|
||||
end
|
||||
|
||||
def fixable?(champ)
|
||||
champ.value.present? && [champ.dossier.en_instruction? || champ.dossier.en_construction?]
|
||||
end
|
||||
|
||||
def notify(message, champ) = Sentry.capture_message(message, extra: { champ: })
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue