From dc605015b38be29ca22b11a131fe288957727090 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 21 Mar 2023 14:44:03 +0100 Subject: [PATCH] feat(commune): chose commune by postal code --- .../editable_champ/communes_component.rb | 17 +++- .../communes_component.html.haml | 25 ++--- .../instructeurs/dossiers_controller.rb | 4 +- app/controllers/users/dossiers_controller.rb | 2 +- app/models/champs/commune_champ.rb | 94 +++++++++++++++++-- app/models/type_de_champ.rb | 2 +- .../shared/champs/communes/_show.html.haml | 2 +- 7 files changed, 121 insertions(+), 25 deletions(-) diff --git a/app/components/editable_champ/communes_component.rb b/app/components/editable_champ/communes_component.rb index a586a994b..bbf7d41a0 100644 --- a/app/components/editable_champ/communes_component.rb +++ b/app/components/editable_champ/communes_component.rb @@ -1,2 +1,17 @@ -class EditableChamp::CommunesComponent < EditableChamp::ComboSearchComponent +class EditableChamp::CommunesComponent < EditableChamp::EditableChampBaseComponent + include ApplicationHelper + + private + + def commune_options + @champ.communes.map { ["#{_1[:name]} (#{_1[:postal_code]})", _1[:code]] } + end + + def code_postal_input_id + "#{@champ.input_id}-code_postal" + end + + def commune_select_options + { selected: @champ.selected }.merge(@champ.mandatory? ? { prompt: '' } : { include_blank: '' }) + end end diff --git a/app/components/editable_champ/communes_component/communes_component.html.haml b/app/components/editable_champ/communes_component/communes_component.html.haml index 8723e541b..f69b76712 100644 --- a/app/components/editable_champ/communes_component/communes_component.html.haml +++ b/app/components/editable_champ/communes_component/communes_component.html.haml @@ -1,12 +1,13 @@ -- render_parent -= @form.hidden_field :value -= @form.hidden_field :external_id -= @form.hidden_field :departement -= @form.hidden_field :code_departement -= react_component("ComboCommunesSearch", - required: @champ.required?, - id: @champ.input_id, - classNameDepartement: "width-33-desktop width-100-mobile", - className: "width-66-desktop width-100-mobile", - describedby: @champ.describedby_id, - **react_combo_props) +%label.notice{ for: code_postal_input_id } Code postal de la commune += @form.text_field :code_postal, required: @champ.required?, id: code_postal_input_id, class: "width-33-desktop width-100-mobile small-margin" +- if @champ.code_postal_with_fallback? + - if commune_options.empty? + .fr-error-text.mb-4= "Aucune commune trouvée pour le code postal #{@champ.code_postal_with_fallback}" + - elsif commune_options.size <= 3 + %fieldset.radios + - commune_options.each.with_index do |(option, value), index| + %label + = @form.radio_button :value, value, checked: @champ.selected == value, id: index == 0 ? @champ.input_id : nil + = option + - else + = @form.select :value, commune_options, commune_select_options, required: @champ.required?, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, class: "width-33-desktop width-100-mobile" diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index 51c09e05b..a5997544a 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -326,8 +326,8 @@ module Instructeurs def champs_private_params champs_params = params.require(:dossier).permit(champs_private_attributes: [ - :id, :primary_value, :secondary_value, :piece_justificative_file, :value_other, :external_id, :numero_allocataire, :code_postal, :departement, :code_departement, :value, value: [], - champs_attributes: [:id, :_destroy, :value, :primary_value, :secondary_value, :piece_justificative_file, :value_other, :external_id, :numero_allocataire, :code_postal, :departement, :code_departement, value: []] + :id, :primary_value, :secondary_value, :piece_justificative_file, :value_other, :external_id, :numero_allocataire, :code_postal, :code_departement, :value, value: [], + champs_attributes: [:id, :_destroy, :value, :primary_value, :secondary_value, :piece_justificative_file, :value_other, :external_id, :numero_allocataire, :code_postal, :code_departement, value: []] ]) champs_params[:champs_private_all_attributes] = champs_params.delete(:champs_private_attributes) || {} champs_params diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index fd45c514f..cdd2e1e74 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -387,7 +387,7 @@ module Users def champs_public_params champs_params = params.require(:dossier).permit(champs_public_attributes: [ - :id, :value, :value_other, :external_id, :primary_value, :secondary_value, :numero_allocataire, :code_postal, :identifiant, :numero_fiscal, :reference_avis, :ine, :piece_justificative_file, :departement, :code_departement, value: [], + :id, :value, :value_other, :external_id, :primary_value, :secondary_value, :numero_allocataire, :code_postal, :identifiant, :numero_fiscal, :reference_avis, :ine, :piece_justificative_file, :code_departement, value: [], champs_attributes: [:id, :_destroy, :value, :value_other, :external_id, :primary_value, :secondary_value, :numero_allocataire, :code_postal, :identifiant, :numero_fiscal, :reference_avis, :ine, :piece_justificative_file, :departement, :code_departement, value: []] ]) champs_params[:champs_public_all_attributes] = champs_params.delete(:champs_public_attributes) || {} diff --git a/app/models/champs/commune_champ.rb b/app/models/champs/commune_champ.rb index 71b04c14f..16ebcd847 100644 --- a/app/models/champs/commune_champ.rb +++ b/app/models/champs/commune_champ.rb @@ -21,30 +21,110 @@ # type_de_champ_id :integer # class Champs::CommuneChamp < Champs::TextChamp - store_accessor :value_json, :departement, :code_departement + store_accessor :value_json, :code_departement, :code_postal + before_validation :on_code_postal_change def for_export - [value, external_id, departement? ? departement_code_and_name : ''] + [name, code, departement? ? departement_code_and_name : ''] end - def name_departement - # FIXME we originaly saved already formatted departement with the code in the name - departement&.gsub(/^(.[0-9])\s-\s/, '') + def departement_name + APIGeoService.departement_name(code_departement) end def departement_code_and_name - "#{code_departement} - #{name_departement}" + "#{code_departement} – #{departement_name}" + end + + def departement + { code: code_departement, name: departement_name } end def departement? - departement.present? + code_departement.present? end def code? code.present? end + def code_postal? + code_postal.present? + end + + def name + if code? + "#{APIGeoService.commune_name(code_departement, code)} (#{code_postal_with_fallback})" + else + value + end + end + + def to_s + name + end + def code external_id end + + def selected + code + end + + def communes + if code_postal_with_fallback? + APIGeoService.communes_by_postal_code(code_postal_with_fallback) + else + [] + end + end + + def value=(code) + if code.blank? || !code_postal_with_fallback? + self.code_departement = nil + self.external_id = nil + super(nil) + else + commune = communes.find { _1[:code] == code } + if commune.present? + self.code_departement = commune[:departement_code] + self.external_id = commune[:code] + super(commune[:name]) + else + self.code_departement = nil + self.external_id = nil + super(nil) + end + end + end + + def code_postal_with_fallback? + code_postal_with_fallback.present? + end + + # We try to extract the postal code from the value, which is the name of the commune and the + # postal code in brackets. This is temporary until we do a full data migration. + def code_postal_with_fallback + if code_postal? + code_postal + elsif value.present? + match = value.match(/[^(]\(([^\)]*)\)$/) + match[1] if match.present? + else + nil + end + end + + private + + def on_code_postal_change + if code_postal_changed? + if communes.one? + self.value = communes.first[:code] + else + self.value = nil + end + end + end end diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index a8ceaa202..c6cbf5df0 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -514,7 +514,7 @@ class TypeDeChamp < ApplicationRecord def self.refresh_after_update?(type_champ) case type_champ - when type_champs.fetch(:epci) + when type_champs.fetch(:epci), type_champs.fetch(:communes) true else false diff --git a/app/views/shared/champs/communes/_show.html.haml b/app/views/shared/champs/communes/_show.html.haml index a162917b4..0aab81b82 100644 --- a/app/views/shared/champs/communes/_show.html.haml +++ b/app/views/shared/champs/communes/_show.html.haml @@ -1,4 +1,4 @@ -= format_text_value(champ.to_s) += champ.name - if champ.code? %p.text-sm Code INSEE :