From 8b4b4d7cb75ea5d01e6ae2929051d399081cdc14 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Mon, 29 Jan 2024 15:15:18 +0100 Subject: [PATCH 1/2] feat(conditional): can condition and route on address champ --- .../conditions/conditions_component.rb | 4 ++-- app/models/logic.rb | 6 ++--- app/models/logic/champ_value.rb | 10 +++++--- .../champs_conditions_component_spec.rb | 14 ++++++++++- .../conditions_errors_component_spec.rb | 4 ++-- spec/models/routing_engine_spec.rb | 24 +++++++++++++++++++ 6 files changed, 51 insertions(+), 11 deletions(-) diff --git a/app/components/conditions/conditions_component.rb b/app/components/conditions/conditions_component.rb index d4acf340b..658da1b22 100644 --- a/app/components/conditions/conditions_component.rb +++ b/app/components/conditions/conditions_component.rb @@ -99,7 +99,7 @@ class Conditions::ConditionsComponent < ApplicationComponent [t('is', scope: 'logic'), Eq.name], [t('is_not', scope: 'logic'), NotEq.name] ] - when ChampValue::CHAMP_VALUE_TYPE.fetch(:commune_enum), ChampValue::CHAMP_VALUE_TYPE.fetch(:epci_enum) + when ChampValue::CHAMP_VALUE_TYPE.fetch(:commune_enum), ChampValue::CHAMP_VALUE_TYPE.fetch(:epci_enum), ChampValue::CHAMP_VALUE_TYPE.fetch(:address) [ [t(InDepartementOperator.name, scope: 'logic.operators'), InDepartementOperator.name], [t(NotInDepartementOperator.name, scope: 'logic.operators'), NotInDepartementOperator.name], @@ -151,7 +151,7 @@ class Conditions::ConditionsComponent < ApplicationComponent id: input_id_for('value', row_index), class: 'fr-select' ) - when :enum, :enums, :commune_enum, :epci_enum, :departement_enum + when :enum, :enums, :commune_enum, :epci_enum, :departement_enum, :address enums_for_select = left.options(@source_tdcs, operator_name) if right_invalid diff --git a/app/models/logic.rb b/app/models/logic.rb index f8d86b465..7325b29f9 100644 --- a/app/models/logic.rb +++ b/app/models/logic.rb @@ -44,7 +44,7 @@ module Logic operator_class = EmptyOperator in [:enum, _] operator_class = Eq - in [:commune_enum, _] | [:epci_enum, _] + in [:commune_enum, _] | [:epci_enum, _] | [:address, _] operator_class = InDepartementOperator in [:departement_enum, _] operator_class = Eq @@ -61,7 +61,7 @@ module Logic Constant.new(true) when :empty Empty.new - when :enum, :enums, :commune_enum, :epci_enum, :departement_enum + when :enum, :enums, :commune_enum, :epci_enum, :departement_enum, :address Constant.new(left.options(type_de_champs).first.second) when :number Constant.new(0) @@ -75,7 +75,7 @@ module Logic case [left.type(type_de_champs), right.type(type_de_champs)] in [a, ^a] # syntax for same type true - in [:enum, :string] | [:enums, :string] | [:commune_enum, :string] | [:epci_enum, :string] | [:departement_enum, :string] + in [:enum, :string] | [:enums, :string] | [:commune_enum, :string] | [:epci_enum, :string] | [:departement_enum, :string] | [:address, :string] true else false diff --git a/app/models/logic/champ_value.rb b/app/models/logic/champ_value.rb index bb48d7073..cb0ac0e27 100644 --- a/app/models/logic/champ_value.rb +++ b/app/models/logic/champ_value.rb @@ -11,7 +11,8 @@ class Logic::ChampValue < Logic::Term :communes, :epci, :departements, - :regions + :regions, + :address ) CHAMP_VALUE_TYPE = { @@ -21,6 +22,7 @@ class Logic::ChampValue < Logic::Term commune_enum: :commune_enum, epci_enum: :epci_enum, departement_enum: :departement_enum, + address: :address, enums: :enums, # multiple choice from a dropdownlist (multipledropdownlist) empty: :empty, unmanaged: :unmanaged @@ -60,7 +62,7 @@ class Logic::ChampValue < Logic::Term value: targeted_champ.code, code_region: targeted_champ.code_region } - when "Champs::CommuneChamp", "Champs::EpciChamp" + when "Champs::CommuneChamp", "Champs::EpciChamp", "Champs::AddressChamp" { code_departement: targeted_champ.code_departement, code_region: targeted_champ.code_region @@ -86,6 +88,8 @@ class Logic::ChampValue < Logic::Term CHAMP_VALUE_TYPE.fetch(:epci_enum) when MANAGED_TYPE_DE_CHAMP.fetch(:departements) CHAMP_VALUE_TYPE.fetch(:departement_enum) + when MANAGED_TYPE_DE_CHAMP.fetch(:address) + CHAMP_VALUE_TYPE.fetch(:address) when MANAGED_TYPE_DE_CHAMP.fetch(:multiple_drop_down_list) CHAMP_VALUE_TYPE.fetch(:enums) else @@ -121,7 +125,7 @@ class Logic::ChampValue < Logic::Term if operator_name.in?([Logic::InRegionOperator.name, Logic::NotInRegionOperator.name]) || tdc.type_champ == MANAGED_TYPE_DE_CHAMP.fetch(:regions) APIGeoService.regions.map { ["#{_1[:code]} – #{_1[:name]}", _1[:code]] } - elsif operator_name.in?([Logic::InDepartementOperator.name, Logic::NotInDepartementOperator.name]) || tdc.type_champ.in?([MANAGED_TYPE_DE_CHAMP.fetch(:communes), MANAGED_TYPE_DE_CHAMP.fetch(:epci), MANAGED_TYPE_DE_CHAMP.fetch(:departements)]) + elsif operator_name.in?([Logic::InDepartementOperator.name, Logic::NotInDepartementOperator.name]) || tdc.type_champ.in?([MANAGED_TYPE_DE_CHAMP.fetch(:communes), MANAGED_TYPE_DE_CHAMP.fetch(:epci), MANAGED_TYPE_DE_CHAMP.fetch(:departements), MANAGED_TYPE_DE_CHAMP.fetch(:address)]) APIGeoService.departements.map { ["#{_1[:code]} – #{_1[:name]}", _1[:code]] } else tdc.drop_down_list_enabled_non_empty_options(other: true).map { _1.is_a?(Array) ? _1 : [_1, _1] } diff --git a/spec/components/conditions/champs_conditions_component_spec.rb b/spec/components/conditions/champs_conditions_component_spec.rb index 27f549315..b24abd8ae 100644 --- a/spec/components/conditions/champs_conditions_component_spec.rb +++ b/spec/components/conditions/champs_conditions_component_spec.rb @@ -15,7 +15,7 @@ describe Conditions::ChampsConditionsComponent, type: :component do end context 'when there are upper tdcs but not managed' do - let(:upper_tdcs) { [build(:type_de_champ_address)] } + let(:upper_tdcs) { [build(:type_de_champ_email)] } it { expect(page).not_to have_text('Logique conditionnelle') } end @@ -130,6 +130,18 @@ describe Conditions::ChampsConditionsComponent, type: :component do expect(page).to have_select('type_de_champ[condition_form][rows][][value]', options: (['Sélectionner'] + region_options)) end end + + context 'address' do + let(:address) { create(:type_de_champ_address) } + let(:upper_tdcs) { [address] } + let(:condition) { empty_operator(champ_value(address.stable_id), constant(true)) } + let(:departement_options) { APIGeoService.departements.map { "#{_1[:code]} – #{_1[:name]}" } } + + it do + expect(page).to have_select('type_de_champ[condition_form][rows][][operator_name]', with_options: ['Est']) + expect(page).to have_select('type_de_champ[condition_form][rows][][value]', options: (['Sélectionner'] + departement_options)) + end + end end context 'and 2 conditions' do diff --git a/spec/components/types_de_champ_editor/conditions_errors_component_spec.rb b/spec/components/types_de_champ_editor/conditions_errors_component_spec.rb index a6a1a41b3..3b550b3ad 100644 --- a/spec/components/types_de_champ_editor/conditions_errors_component_spec.rb +++ b/spec/components/types_de_champ_editor/conditions_errors_component_spec.rb @@ -24,13 +24,13 @@ describe Conditions::ConditionsErrorsComponent, type: :component do end context 'when the targeted_champ is unmanaged' do - let(:tdc) { create(:type_de_champ_address) } + let(:tdc) { create(:type_de_champ_email) } let(:source_tdcs) { [tdc] } let(:conditions) { [ds_eq(champ_value(tdc.stable_id), constant(1))] } it do expect(page).to have_css('.errors-summary') - expect(page).to have_content("Le champ « #{tdc.libelle} » est de type « adresse » et ne peut pas être utilisé comme champ cible.") + expect(page).to have_content("Le champ « #{tdc.libelle} » est de type « adresse électronique » et ne peut pas être utilisé comme champ cible.") end end diff --git a/spec/models/routing_engine_spec.rb b/spec/models/routing_engine_spec.rb index 57bdfef6e..b929844f5 100644 --- a/spec/models/routing_engine_spec.rb +++ b/spec/models/routing_engine_spec.rb @@ -157,6 +157,30 @@ describe RoutingEngine, type: :model do end end + context 'with an address type de champ' do + let(:procedure) do + create(:procedure, types_de_champ_public: [{ type: :address }]).tap do |p| + p.groupe_instructeurs.create(label: 'a third group') + end + end + + let(:address_tdc) { procedure.draft_revision.types_de_champ.first } + + context 'with a matching rule' do + before do + gi_2.update(routing_rule: ds_in_departement(champ_value(address_tdc.stable_id), constant('42'))) + dossier.champs.first.update_columns( + value: "2 rue de l'Hôtel de Ville 42000 Saint-Étienne", + data: { department_code: '42', region_code: '83' } + ) + end + + it do + is_expected.to eq(gi_2) + end + end + end + context 'routing rules priorities' do let(:procedure) do create(:procedure, From fade633828947a730c83bdfbb755a0d90b413107 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Wed, 21 Feb 2024 11:31:49 +0100 Subject: [PATCH 2/2] feat(routing): can create simple routing with address tdc --- .../groupe_instructeurs_controller.rb | 2 +- app/models/type_de_champ.rb | 3 ++- .../groupe_instructeurs_controller_spec.rb | 20 +++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index c8a6eaff4..61225de77 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -53,7 +53,7 @@ module Administrateurs tdc_options = APIGeoService.departements.map { ["#{_1[:code]} – #{_1[:name]}", _1[:code]] } rule_operator = :ds_eq create_groups_from_territorial_tdc(tdc_options, stable_id, rule_operator) - when TypeDeChamp.type_champs.fetch(:communes), TypeDeChamp.type_champs.fetch(:epci) + when TypeDeChamp.type_champs.fetch(:communes), TypeDeChamp.type_champs.fetch(:epci), TypeDeChamp.type_champs.fetch(:address) tdc_options = APIGeoService.departements.map { ["#{_1[:code]} – #{_1[:name]}", _1[:code]] } rule_operator = :ds_in_departement create_groups_from_territorial_tdc(tdc_options, stable_id, rule_operator) diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index 245e9ed1f..3539bf53e 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -117,7 +117,8 @@ class TypeDeChamp < ApplicationRecord type_champs.fetch(:communes), type_champs.fetch(:departements), type_champs.fetch(:regions), - type_champs.fetch(:epci) + type_champs.fetch(:epci), + type_champs.fetch(:address) ] PRIVATE_ONLY_TYPES = [ diff --git a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb index a80e9ed10..1269856da 100644 --- a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb +++ b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb @@ -933,6 +933,26 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do expect(procedure3.routing_enabled).to be_truthy end end + + context 'with an address type de champ' do + let!(:procedure3) do + create(:procedure, + types_de_champ_public: [{ type: :address }], + administrateurs: [admin]) + end + + let!(:address_tdc) { procedure3.draft_revision.types_de_champ.first } + + before { post :create_simple_routing, params: { procedure_id: procedure3.id, create_simple_routing: { stable_id: address_tdc.stable_id } } } + + it do + expect(response).to redirect_to(admin_procedure_groupe_instructeurs_path(procedure3)) + expect(flash.notice).to eq 'Les groupes instructeurs ont été ajoutés' + expect(procedure3.groupe_instructeurs.pluck(:label)).to include("01 – Ain") + expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_in_departement(champ_value(address_tdc.stable_id), constant('01'))) + expect(procedure3.routing_enabled).to be_truthy + end + end end describe '#wizard' do