diff --git a/app/models/champs/departement_champ.rb b/app/models/champs/departement_champ.rb
index 13edb4bb4..5a99ce8ad 100644
--- a/app/models/champs/departement_champ.rb
+++ b/app/models/champs/departement_champ.rb
@@ -21,6 +21,9 @@
# type_de_champ_id :integer
#
class Champs::DepartementChamp < Champs::TextChamp
+ validate :value_in_departement_names, unless: -> { value.nil? }
+ validate :external_id_in_departement_codes, unless: -> { external_id.nil? }
+
def for_export
[name, code]
end
@@ -65,6 +68,9 @@ class Champs::DepartementChamp < Champs::TextChamp
elsif code.blank?
self.external_id = nil
super(nil)
+ else
+ self.external_id = APIGeoService.departement_code(code)
+ super(code)
end
end
@@ -73,4 +79,16 @@ class Champs::DepartementChamp < Champs::TextChamp
def formatted_value
blank? ? "" : "#{code} – #{name}"
end
+
+ def value_in_departement_names
+ return if value.in?(APIGeoService.departements.pluck(:name))
+
+ errors.add(:value, :not_in_departement_names)
+ end
+
+ def external_id_in_departement_codes
+ return if external_id.in?(APIGeoService.departements.pluck(:code))
+
+ errors.add(:external_id, :not_in_departement_codes)
+ end
end
diff --git a/app/models/prefill_params.rb b/app/models/prefill_params.rb
index e4ded1975..33261a8ac 100644
--- a/app/models/prefill_params.rb
+++ b/app/models/prefill_params.rb
@@ -40,7 +40,8 @@ class PrefillParams
TypeDeChamp.type_champs.fetch(:yes_no),
TypeDeChamp.type_champs.fetch(:checkbox),
TypeDeChamp.type_champs.fetch(:pays),
- TypeDeChamp.type_champs.fetch(:regions)
+ TypeDeChamp.type_champs.fetch(:regions),
+ TypeDeChamp.type_champs.fetch(:departements)
]
attr_reader :champ, :value
diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb
index afa6a821a..05091ec70 100644
--- a/app/models/type_de_champ.rb
+++ b/app/models/type_de_champ.rb
@@ -267,7 +267,8 @@ class TypeDeChamp < ApplicationRecord
TypeDeChamp.type_champs.fetch(:yes_no),
TypeDeChamp.type_champs.fetch(:checkbox),
TypeDeChamp.type_champs.fetch(:drop_down_list),
- TypeDeChamp.type_champs.fetch(:regions)
+ TypeDeChamp.type_champs.fetch(:regions),
+ TypeDeChamp.type_champs.fetch(:departements)
])
end
diff --git a/app/models/types_de_champ/prefill_departement_type_de_champ.rb b/app/models/types_de_champ/prefill_departement_type_de_champ.rb
new file mode 100644
index 000000000..2ec1d1d11
--- /dev/null
+++ b/app/models/types_de_champ/prefill_departement_type_de_champ.rb
@@ -0,0 +1,11 @@
+class TypesDeChamp::PrefillDepartementTypeDeChamp < TypesDeChamp::PrefillTypeDeChamp
+ def possible_values
+ departements.map { |departement| "#{departement[:code]} (#{departement[:name]})" }
+ end
+
+ private
+
+ def departements
+ @departements ||= APIGeoService.departements.sort_by { |departement| departement[:code] }
+ end
+end
diff --git a/app/models/types_de_champ/prefill_pays_type_de_champ.rb b/app/models/types_de_champ/prefill_pays_type_de_champ.rb
index 143f041e7..6e5f9952c 100644
--- a/app/models/types_de_champ/prefill_pays_type_de_champ.rb
+++ b/app/models/types_de_champ/prefill_pays_type_de_champ.rb
@@ -3,10 +3,6 @@ class TypesDeChamp::PrefillPaysTypeDeChamp < TypesDeChamp::PrefillTypeDeChamp
countries.map { |country| "#{country[:code]} (#{country[:name]})" }
end
- def example_value
- countries.pick(:code)
- end
-
private
def countries
diff --git a/app/models/types_de_champ/prefill_type_de_champ.rb b/app/models/types_de_champ/prefill_type_de_champ.rb
index 296c04c48..5e9e55380 100644
--- a/app/models/types_de_champ/prefill_type_de_champ.rb
+++ b/app/models/types_de_champ/prefill_type_de_champ.rb
@@ -9,6 +9,8 @@ class TypesDeChamp::PrefillTypeDeChamp < SimpleDelegator
TypesDeChamp::PrefillPaysTypeDeChamp.new(type_de_champ)
when TypeDeChamp.type_champs.fetch(:regions)
TypesDeChamp::PrefillRegionTypeDeChamp.new(type_de_champ)
+ when TypeDeChamp.type_champs.fetch(:departements)
+ TypesDeChamp::PrefillDepartementTypeDeChamp.new(type_de_champ)
else
new(type_de_champ)
end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index dc8be05ec..c9f4af19e 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -130,6 +130,7 @@ en:
yes_no_html: '"true" for Yes, "false" pour No'
checkbox_html: '"true" to check, "false" to uncheck'
pays_html: An ISO 3166-2 country code
+ departements_html: A department number
regions_html: An INSEE region code
date_html: ISO8601 date
datetime_html: ISO8601 datetime
@@ -145,6 +146,7 @@ en:
iban: FR7611315000011234567890138
yes_no: "true"
pays: "FR"
+ departements: "56"
regions: "53"
date: "2023-02-01"
datetime: "2023-02-01T10:30"
@@ -475,6 +477,12 @@ en:
not_in_region_names: "must be a valid region name"
external_id:
not_in_region_codes: "must be a valid region code"
+ "champs/departement_champ":
+ attributes:
+ value:
+ not_in_departement_names: "must be a valid department name"
+ external_id:
+ not_in_departement_codes: "must be a valid department code"
errors:
format: "Field « %{attribute} » %{message}"
messages:
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index d4b864c28..b530475fc 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -121,6 +121,7 @@ fr:
yes_no_html: '"true" pour Oui, "false" pour Non'
checkbox_html: '"true" pour coché, "false" pour décoché'
pays_html: Un code pays ISO 3166-2
+ departements_html: Un numéro de département
regions_html: Un code INSEE de région
datetime_html: Datetime au format ISO8601
date_html: Date au format ISO8601
@@ -137,6 +138,7 @@ fr:
yes_no: "true"
civilite: "M."
pays: "FR"
+ departements: "56"
regions: "53"
date: "2023-02-01"
datetime: "2023-02-01T10:30"
@@ -470,6 +472,12 @@ fr:
not_in_region_names: "doit être un nom de région valide"
external_id:
not_in_region_codes: "doit être un code de région valide"
+ "champs/departement_champ":
+ attributes:
+ value:
+ not_in_departement_names: "doit être un nom de département valide"
+ external_id:
+ not_in_departement_codes: "doit être un code de département valide"
errors:
format: "Le champ « %{attribute} » %{message}"
messages:
diff --git a/spec/controllers/api/v1/dossiers_controller_spec.rb b/spec/controllers/api/v1/dossiers_controller_spec.rb
index af705addd..9c7ef5fe3 100644
--- a/spec/controllers/api/v1/dossiers_controller_spec.rb
+++ b/spec/controllers/api/v1/dossiers_controller_spec.rb
@@ -4,6 +4,13 @@ describe API::V1::DossiersController do
let(:procedure) { create(:procedure, :with_type_de_champ, :with_type_de_champ_private, administrateur: admin) }
let(:wrong_procedure) { create(:procedure) }
+ let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) }
+
+ before do
+ allow(Rails).to receive(:cache).and_return(memory_store)
+ Rails.cache.clear
+ end
+
it { expect(described_class).to be < APIController }
describe 'GET index (with bearer token)' do
@@ -258,7 +265,7 @@ describe API::V1::DossiersController do
end
end
- describe 'departement' do
+ describe 'departement', vcr: { cassette_name: 'api_geo_departements' } do
let(:procedure) { create(:procedure, :with_departement, administrateur: admin) }
let(:dossier) { create(:dossier, :en_construction, :with_populated_champs, procedure: procedure) }
diff --git a/spec/controllers/api/v2/graphql_controller_spec.rb b/spec/controllers/api/v2/graphql_controller_spec.rb
index acfe61304..6f70743cd 100644
--- a/spec/controllers/api/v2/graphql_controller_spec.rb
+++ b/spec/controllers/api/v2/graphql_controller_spec.rb
@@ -42,7 +42,6 @@ describe API::V2::GraphqlController do
allow(Rails).to receive(:cache).and_return(memory_store)
Rails.cache.clear
- allow(APIGeoService).to receive(:departement_name).with('01').and_return('Ain')
instructeur.assign_to_procedure(procedure)
end
@@ -397,7 +396,7 @@ describe API::V2::GraphqlController do
dossier
end
- context "for individual", vcr: { cassette_name: 'api_geo_regions' } do
+ context "for individual", vcr: { cassette_name: 'api_geo_all' } do
let(:procedure) { create(:procedure, :published, :for_individual, :with_service, :with_all_champs, :with_all_annotations, administrateurs: [admin]) }
let(:query) do
"{
diff --git a/spec/models/champs/departement_champ_spec.rb b/spec/models/champs/departement_champ_spec.rb
index 35353f865..1a70439d5 100644
--- a/spec/models/champs/departement_champ_spec.rb
+++ b/spec/models/champs/departement_champ_spec.rb
@@ -6,9 +6,69 @@ describe Champs::DepartementChamp, type: :model do
Rails.cache.clear
end
- let(:champ) { described_class.new }
+ describe 'validations', vcr: { cassette_name: 'api_geo_departements' } do
+ describe 'external link' do
+ subject { build(:champ_departements, external_id: external_id) }
+
+ context 'when nil' do
+ let(:external_id) { nil }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when blank' do
+ let(:external_id) { '' }
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when included in the departement codes' do
+ let(:external_id) { "01" }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when not included in the departement codes' do
+ let(:external_id) { "totoro" }
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+
+ describe 'value' do
+ subject { create(:champ_departements) }
+
+ before { subject.update_columns(value: value) }
+
+ context 'when nil' do
+ let(:value) { nil }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when blank' do
+ let(:value) { '' }
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when included in the departement names' do
+ let(:value) { "Ain" }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when not included in the departement names' do
+ let(:value) { "totoro" }
+
+ it { is_expected.not_to be_valid }
+ end
+ end
+ end
describe 'value', vcr: { cassette_name: 'api_geo_departements' } do
+ let(:champ) { described_class.new }
+
it 'with code having 2 chars' do
champ.value = '01'
expect(champ.external_id).to eq('01')
diff --git a/spec/models/prefill_params_spec.rb b/spec/models/prefill_params_spec.rb
index 84c99a26b..2c9ff077a 100644
--- a/spec/models/prefill_params_spec.rb
+++ b/spec/models/prefill_params_spec.rb
@@ -1,5 +1,5 @@
RSpec.describe PrefillParams do
- describe "#to_a", vcr: { cassette_name: 'api_geo_regions' } do
+ describe "#to_a", vcr: { cassette_name: 'api_geo_all' } do
let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) }
let(:procedure) { create(:procedure, :published, types_de_champ_public:, types_de_champ_private:) }
@@ -126,6 +126,7 @@ RSpec.describe PrefillParams do
it_behaves_like "a champ public value that is authorized", :checkbox, "false"
it_behaves_like "a champ public value that is authorized", :drop_down_list, "value"
it_behaves_like "a champ public value that is authorized", :regions, "03"
+ it_behaves_like "a champ public value that is authorized", :departements, "03"
it_behaves_like "a champ private value that is authorized", :text, "value"
it_behaves_like "a champ private value that is authorized", :textarea, "value"
@@ -144,6 +145,7 @@ RSpec.describe PrefillParams do
it_behaves_like "a champ private value that is authorized", :checkbox, "false"
it_behaves_like "a champ private value that is authorized", :drop_down_list, "value"
it_behaves_like "a champ private value that is authorized", :regions, "93"
+ it_behaves_like "a champ public value that is authorized", :departements, "03"
it_behaves_like "a champ public value that is unauthorized", :decimal_number, "non decimal string"
it_behaves_like "a champ public value that is unauthorized", :integer_number, "non integer string"
diff --git a/spec/models/type_de_champ_spec.rb b/spec/models/type_de_champ_spec.rb
index e1ca7bac6..9d891f5e1 100644
--- a/spec/models/type_de_champ_spec.rb
+++ b/spec/models/type_de_champ_spec.rb
@@ -250,6 +250,7 @@ describe TypeDeChamp do
it_behaves_like "a prefillable type de champ", :type_de_champ_checkbox
it_behaves_like "a prefillable type de champ", :type_de_champ_drop_down_list
it_behaves_like "a prefillable type de champ", :type_de_champ_regions
+ it_behaves_like "a prefillable type de champ", :type_de_champ_departements
it_behaves_like "a non-prefillable type de champ", :type_de_champ_number
it_behaves_like "a non-prefillable type de champ", :type_de_champ_communes
@@ -267,7 +268,6 @@ describe TypeDeChamp do
it_behaves_like "a non-prefillable type de champ", :type_de_champ_mesri
it_behaves_like "a non-prefillable type de champ", :type_de_champ_carte
it_behaves_like "a non-prefillable type de champ", :type_de_champ_address
- it_behaves_like "a non-prefillable type de champ", :type_de_champ_departements
it_behaves_like "a non-prefillable type de champ", :type_de_champ_siret
it_behaves_like "a non-prefillable type de champ", :type_de_champ_rna
it_behaves_like "a non-prefillable type de champ", :type_de_champ_annuaire_education
diff --git a/spec/models/types_de_champ/prefill_departement_type_de_champ_spec.rb b/spec/models/types_de_champ/prefill_departement_type_de_champ_spec.rb
new file mode 100644
index 000000000..f43a07393
--- /dev/null
+++ b/spec/models/types_de_champ/prefill_departement_type_de_champ_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+RSpec.describe TypesDeChamp::PrefillDepartementTypeDeChamp, type: :model do
+ let(:type_de_champ) { build(:type_de_champ_departements) }
+ let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) }
+
+ before do
+ allow(Rails).to receive(:cache).and_return(memory_store)
+ Rails.cache.clear
+ end
+
+ describe 'ancestors' do
+ subject { described_class.build(type_de_champ) }
+
+ it { is_expected.to be_kind_of(TypesDeChamp::PrefillTypeDeChamp) }
+ end
+
+ describe '#possible_values', vcr: { cassette_name: 'api_geo_departements' } do
+ let(:expected_values) {
+ APIGeoService.departements.sort_by { |departement| departement[:code] }.map { |departement| "#{departement[:code]} (#{departement[:name]})" }
+ }
+ subject(:possible_values) { described_class.new(type_de_champ).possible_values }
+
+ it { expect(possible_values).to match(expected_values) }
+ end
+end
diff --git a/spec/models/types_de_champ/prefill_pays_type_de_champ_spec.rb b/spec/models/types_de_champ/prefill_pays_type_de_champ_spec.rb
index f651d3d60..67789ba9e 100644
--- a/spec/models/types_de_champ/prefill_pays_type_de_champ_spec.rb
+++ b/spec/models/types_de_champ/prefill_pays_type_de_champ_spec.rb
@@ -2,16 +2,16 @@
RSpec.describe TypesDeChamp::PrefillPaysTypeDeChamp, type: :model do
let(:type_de_champ) { build(:type_de_champ_pays) }
+ describe 'ancestors' do
+ subject { described_class.build(type_de_champ) }
+
+ it { is_expected.to be_kind_of(TypesDeChamp::PrefillTypeDeChamp) }
+ end
+
describe '#possible_values' do
let(:expected_values) { APIGeoService.countries.sort_by { |country| country[:code] }.map { |country| "#{country[:code]} (#{country[:name]})" } }
subject(:possible_values) { described_class.new(type_de_champ).possible_values }
it { expect(possible_values).to match(expected_values) }
end
-
- describe '#example_value' do
- subject(:example_value) { described_class.new(type_de_champ).example_value }
-
- it { expect(example_value).to eq(APIGeoService.countries.sort_by { |country| country[:code] }.first[:code]) }
- end
end
diff --git a/spec/models/types_de_champ/prefill_type_de_champ_spec.rb b/spec/models/types_de_champ/prefill_type_de_champ_spec.rb
index af0e3cfc9..52508be91 100644
--- a/spec/models/types_de_champ/prefill_type_de_champ_spec.rb
+++ b/spec/models/types_de_champ/prefill_type_de_champ_spec.rb
@@ -22,6 +22,12 @@ RSpec.describe TypesDeChamp::PrefillTypeDeChamp, type: :model do
it { expect(built).to be_kind_of(TypesDeChamp::PrefillRegionTypeDeChamp) }
end
+ context 'when the type de champ is a departements' do
+ let(:type_de_champ) { build(:type_de_champ_departements) }
+
+ it { expect(built).to be_kind_of(TypesDeChamp::PrefillDepartementTypeDeChamp) }
+ end
+
context 'when any other type de champ' do
let(:type_de_champ) { build(:type_de_champ_date) }