Merge pull request #9423 from demarches-simplifiees/can-route-with-not-equals-routing-rules
ETQ admin je peux router avec des règles dont l'opérateur est "n'est pas"
This commit is contained in:
commit
0c004fd4e5
6 changed files with 137 additions and 26 deletions
|
@ -17,6 +17,10 @@ class Procedure::OneGroupeManagementComponent < ApplicationComponent
|
||||||
@groupe_instructeur.routing_rule&.right || empty
|
@groupe_instructeur.routing_rule&.right || empty
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def operator_name
|
||||||
|
@groupe_instructeur.routing_rule&.class&.name || empty
|
||||||
|
end
|
||||||
|
|
||||||
def targeted_champ_tag
|
def targeted_champ_tag
|
||||||
select_tag(
|
select_tag(
|
||||||
'targeted_champ',
|
'targeted_champ',
|
||||||
|
@ -39,6 +43,21 @@ class Procedure::OneGroupeManagementComponent < ApplicationComponent
|
||||||
.map { |tdc| [tdc.libelle, champ_value(tdc.stable_id).to_json] }
|
.map { |tdc| [tdc.libelle, champ_value(tdc.stable_id).to_json] }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def operator_tag
|
||||||
|
select_tag('operator_name',
|
||||||
|
options_for_select(
|
||||||
|
options_for_operator_tag,
|
||||||
|
selected: operator_name
|
||||||
|
),
|
||||||
|
class: 'fr-select')
|
||||||
|
end
|
||||||
|
|
||||||
|
def options_for_operator_tag
|
||||||
|
[Eq, NotEq]
|
||||||
|
.map(&:name)
|
||||||
|
.map { |name| [t(name, scope: 'logic.operators'), name] }
|
||||||
|
end
|
||||||
|
|
||||||
def value_tag
|
def value_tag
|
||||||
select_tag(
|
select_tag(
|
||||||
'value',
|
'value',
|
||||||
|
|
|
@ -40,7 +40,8 @@
|
||||||
.fr-mr-2w.no-wrap si le champ
|
.fr-mr-2w.no-wrap si le champ
|
||||||
.target.fr-mr-2w
|
.target.fr-mr-2w
|
||||||
= targeted_champ_tag
|
= targeted_champ_tag
|
||||||
.operator.fr-mr-2w.no-wrap est égal à
|
.operator.fr-mr-2w.no-wrap
|
||||||
|
= operator_tag
|
||||||
.value
|
.value
|
||||||
= value_tag
|
= value_tag
|
||||||
.fr-hint-text
|
.fr-hint-text
|
||||||
|
|
|
@ -9,7 +9,13 @@ module Administrateurs
|
||||||
|
|
||||||
right = targeted_champ_changed? ? empty : value
|
right = targeted_champ_changed? ? empty : value
|
||||||
|
|
||||||
groupe_instructeur.update!(routing_rule: ds_eq(left, right))
|
new_routing_rule = case operator_name
|
||||||
|
when Eq.name
|
||||||
|
ds_eq(left, right)
|
||||||
|
when NotEq.name
|
||||||
|
ds_not_eq(left, right)
|
||||||
|
end
|
||||||
|
groupe_instructeur.update!(routing_rule: new_routing_rule)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_defaut_groupe_instructeur
|
def update_defaut_groupe_instructeur
|
||||||
|
@ -27,6 +33,10 @@ module Administrateurs
|
||||||
Logic.from_json(params[:targeted_champ])
|
Logic.from_json(params[:targeted_champ])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def operator_name
|
||||||
|
params[:operator_name]
|
||||||
|
end
|
||||||
|
|
||||||
def value
|
def value
|
||||||
Logic.from_json(params[:value])
|
Logic.from_json(params[:value])
|
||||||
end
|
end
|
||||||
|
|
|
@ -73,9 +73,12 @@ class GroupeInstructeur < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def invalid_rule?
|
def invalid_rule?
|
||||||
rule = routing_rule
|
!valid_rule?
|
||||||
return true if !(rule.is_a?(Logic::Eq) && rule.left.is_a?(Logic::ChampValue) && rule.right.is_a?(Logic::Constant))
|
end
|
||||||
return true if !routing_rule_matches_tdc?
|
|
||||||
|
def valid_rule?
|
||||||
|
return false if routing_rule.nil?
|
||||||
|
([routing_rule.left, routing_rule, routing_rule.right] in [ChampValue, Eq | NotEq, Constant]) && routing_rule_matches_tdc?
|
||||||
end
|
end
|
||||||
|
|
||||||
def non_unique_rule?
|
def non_unique_rule?
|
||||||
|
|
|
@ -11,40 +11,82 @@ describe Administrateurs::RoutingController, type: :controller do
|
||||||
{
|
{
|
||||||
procedure_id: procedure.id,
|
procedure_id: procedure.id,
|
||||||
targeted_champ: champ_value(drop_down_tdc.stable_id).to_json,
|
targeted_champ: champ_value(drop_down_tdc.stable_id).to_json,
|
||||||
|
operator_name: operator_name,
|
||||||
value: empty.to_json,
|
value: empty.to_json,
|
||||||
groupe_instructeur_id: gi_2.id
|
groupe_instructeur_id: gi_2.id
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
context 'with Eq operator' do
|
||||||
post :update, params: params, format: :turbo_stream
|
let(:operator_name) { Logic::Eq.name }
|
||||||
end
|
|
||||||
|
|
||||||
it do
|
|
||||||
expect(gi_2.reload.routing_rule).to eq(ds_eq(champ_value(drop_down_tdc.stable_id), empty))
|
|
||||||
end
|
|
||||||
|
|
||||||
context '#update value' do
|
|
||||||
let(:value_updated_params) { params.merge(value: constant('Lyon').to_json) }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
post :update, params: value_updated_params, format: :turbo_stream
|
post :update, params: params, format: :turbo_stream
|
||||||
end
|
end
|
||||||
|
|
||||||
it do
|
it do
|
||||||
expect(gi_2.reload.routing_rule).to eq(ds_eq(champ_value(drop_down_tdc.stable_id), constant('Lyon')))
|
expect(gi_2.reload.routing_rule).to eq(ds_eq(champ_value(drop_down_tdc.stable_id), empty))
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'targeted champ changed' do
|
context '#update value' do
|
||||||
let(:last_tdc) { procedure.draft_revision.types_de_champ.last }
|
let(:value_updated_params) { params.merge(value: constant('Lyon').to_json) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
targeted_champ_updated_params = value_updated_params.merge(targeted_champ: champ_value(last_tdc.stable_id).to_json)
|
post :update, params: value_updated_params, format: :turbo_stream
|
||||||
post :update, params: targeted_champ_updated_params, format: :turbo_stream
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it do
|
it do
|
||||||
expect(gi_2.reload.routing_rule).to eq(ds_eq(champ_value(last_tdc.stable_id), empty))
|
expect(gi_2.reload.routing_rule).to eq(ds_eq(champ_value(drop_down_tdc.stable_id), constant('Lyon')))
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'targeted champ changed' do
|
||||||
|
let(:last_tdc) { procedure.draft_revision.types_de_champ.last }
|
||||||
|
|
||||||
|
before do
|
||||||
|
targeted_champ_updated_params = value_updated_params.merge(targeted_champ: champ_value(last_tdc.stable_id).to_json)
|
||||||
|
post :update, params: targeted_champ_updated_params, format: :turbo_stream
|
||||||
|
end
|
||||||
|
|
||||||
|
it do
|
||||||
|
expect(gi_2.reload.routing_rule).to eq(ds_eq(champ_value(last_tdc.stable_id), empty))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with NotEq operator' do
|
||||||
|
let(:operator_name) { Logic::NotEq.name }
|
||||||
|
|
||||||
|
before do
|
||||||
|
post :update, params: params, format: :turbo_stream
|
||||||
|
end
|
||||||
|
|
||||||
|
it do
|
||||||
|
expect(gi_2.reload.routing_rule).to eq(ds_not_eq(champ_value(drop_down_tdc.stable_id), empty))
|
||||||
|
end
|
||||||
|
|
||||||
|
context '#update value' do
|
||||||
|
let(:value_updated_params) { params.merge(value: constant('Lyon').to_json) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
post :update, params: value_updated_params, format: :turbo_stream
|
||||||
|
end
|
||||||
|
|
||||||
|
it do
|
||||||
|
expect(gi_2.reload.routing_rule).to eq(ds_not_eq(champ_value(drop_down_tdc.stable_id), constant('Lyon')))
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'targeted champ changed' do
|
||||||
|
let(:last_tdc) { procedure.draft_revision.types_de_champ.last }
|
||||||
|
|
||||||
|
before do
|
||||||
|
targeted_champ_updated_params = value_updated_params.merge(targeted_champ: champ_value(last_tdc.stable_id).to_json)
|
||||||
|
post :update, params: targeted_champ_updated_params, format: :turbo_stream
|
||||||
|
end
|
||||||
|
|
||||||
|
it do
|
||||||
|
expect(gi_2.reload.routing_rule).to eq(ds_not_eq(champ_value(last_tdc.stable_id), empty))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ describe RoutingEngine, type: :model do
|
||||||
describe '.compute' do
|
describe '.compute' do
|
||||||
let(:dossier) { create(:dossier, procedure:) }
|
let(:dossier) { create(:dossier, procedure:) }
|
||||||
let(:defaut_groupe) { procedure.defaut_groupe_instructeur }
|
let(:defaut_groupe) { procedure.defaut_groupe_instructeur }
|
||||||
let(:gi_2) { procedure.groupe_instructeurs.find_by(label: 'a second group') }
|
let(:gi_2) { procedure.groupe_instructeurs.create(label: 'a second group') }
|
||||||
|
|
||||||
subject do
|
subject do
|
||||||
RoutingEngine.compute(dossier)
|
RoutingEngine.compute(dossier)
|
||||||
|
@ -15,7 +15,6 @@ describe RoutingEngine, type: :model do
|
||||||
let(:procedure) do
|
let(:procedure) do
|
||||||
create(:procedure,
|
create(:procedure,
|
||||||
types_de_champ_public: [{ type: :drop_down_list, libelle: 'Votre ville', options: ['Paris', 'Lyon', 'Marseille'] }]).tap do |p|
|
types_de_champ_public: [{ type: :drop_down_list, libelle: 'Votre ville', options: ['Paris', 'Lyon', 'Marseille'] }]).tap do |p|
|
||||||
p.groupe_instructeurs.create(label: 'a second group')
|
|
||||||
p.groupe_instructeurs.create(label: 'a third group')
|
p.groupe_instructeurs.create(label: 'a third group')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -29,7 +28,7 @@ describe RoutingEngine, type: :model do
|
||||||
context 'without any matching rules' do
|
context 'without any matching rules' do
|
||||||
before do
|
before do
|
||||||
procedure.groupe_instructeurs.each do |gi|
|
procedure.groupe_instructeurs.each do |gi|
|
||||||
gi.update(routing_rule: constant(false))
|
gi.update(routing_rule: ds_eq(constant(false), constant(false)))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -60,12 +59,23 @@ describe RoutingEngine, type: :model do
|
||||||
|
|
||||||
it { is_expected.to eq(defaut_groupe) }
|
it { is_expected.to eq(defaut_groupe) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with a non equals rule' do
|
||||||
|
before do
|
||||||
|
gi_2.update(routing_rule: ds_not_eq(champ_value(drop_down_tdc.stable_id), constant('Lyon')))
|
||||||
|
dossier.champs.first.update(value: 'Paris')
|
||||||
|
end
|
||||||
|
|
||||||
|
it do
|
||||||
|
is_expected.not_to eq(defaut_groupe)
|
||||||
|
is_expected.to eq(gi_2)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with a departements type de champ' do
|
context 'with a departements type de champ' do
|
||||||
let(:procedure) do
|
let(:procedure) do
|
||||||
create(:procedure, types_de_champ_public: [{ type: :departements }]).tap do |p|
|
create(:procedure, types_de_champ_public: [{ type: :departements }]).tap do |p|
|
||||||
p.groupe_instructeurs.create(label: 'a second group')
|
|
||||||
p.groupe_instructeurs.create(label: 'a third group')
|
p.groupe_instructeurs.create(label: 'a third group')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -81,5 +91,31 @@ describe RoutingEngine, type: :model do
|
||||||
it { is_expected.to eq(gi_2) }
|
it { is_expected.to eq(gi_2) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'routing rules priorities' do
|
||||||
|
let(:procedure) do
|
||||||
|
create(:procedure,
|
||||||
|
types_de_champ_public: [{ type: :drop_down_list, libelle: 'Ville', options: ['Paris', 'Lyon', 'Marseille'] }]).tap do |p|
|
||||||
|
p.groupe_instructeurs.create(label: 'c')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:drop_down_tdc) { procedure.draft_revision.types_de_champ.first }
|
||||||
|
|
||||||
|
let!(:gi_3) { procedure.groupe_instructeurs.find_by(label: 'c') }
|
||||||
|
|
||||||
|
context 'not eq rule coming first' do
|
||||||
|
before do
|
||||||
|
defaut_groupe.update(label: 'a')
|
||||||
|
gi_2.update(label: 'b', routing_rule: ds_not_eq(champ_value(drop_down_tdc.stable_id), constant('Lyon')))
|
||||||
|
gi_3.update(routing_rule: ds_eq(champ_value(drop_down_tdc.stable_id), constant('Marseille')))
|
||||||
|
dossier.champs.first.update(value: 'Marseille')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'computes by groups label order' do
|
||||||
|
is_expected.to eq(gi_2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue