feat(ProcedureRevision.ineligibilite_rules): add ineligibilite_rules management to procedure revision based on conditional logic
This commit is contained in:
parent
12d23f1498
commit
aca3e38859
22 changed files with 591 additions and 0 deletions
34
app/components/conditions/ineligibilite_rules_component.rb
Normal file
34
app/components/conditions/ineligibilite_rules_component.rb
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
class Conditions::IneligibiliteRulesComponent < Conditions::ConditionsComponent
|
||||||
|
include Logic
|
||||||
|
|
||||||
|
def initialize(draft_revision:)
|
||||||
|
@draft_revision = draft_revision
|
||||||
|
@published_revision = draft_revision.procedure.published_revision
|
||||||
|
@condition = draft_revision.ineligibilite_rules
|
||||||
|
@source_tdcs = draft_revision.types_de_champ_for(scope: :public)
|
||||||
|
end
|
||||||
|
|
||||||
|
def pending_changes?
|
||||||
|
return false if !@published_revision
|
||||||
|
|
||||||
|
!@published_revision.compare_ineligibilite_rules(@draft_revision).empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def input_prefix
|
||||||
|
'procedure_revision[condition_form]'
|
||||||
|
end
|
||||||
|
|
||||||
|
def input_id_for(name, row_index)
|
||||||
|
"#{@draft_revision.id}-#{name}-#{row_index}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_condition_path(row_index)
|
||||||
|
delete_row_admin_procedure_ineligibilite_rules_path(@draft_revision.procedure_id, revision_id: @draft_revision.id, row_index:)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_condition_path
|
||||||
|
add_row_admin_procedure_ineligibilite_rules_path(@draft_revision.procedure_id, revision_id: @draft_revision.id)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
fr:
|
||||||
|
display_if: Bloquer si
|
||||||
|
select: Sélectionner
|
||||||
|
add_condition: Ajouter une règle d’inéligibilité
|
||||||
|
remove_a_row: Supprimer une règle
|
|
@ -0,0 +1,42 @@
|
||||||
|
%div{ id: dom_id(@draft_revision, :ineligibilite_rules) }
|
||||||
|
= render Procedure::PendingRepublishComponent.new(procedure: @draft_revision.procedure, render_if: pending_changes?)
|
||||||
|
= render Conditions::ConditionsErrorsComponent.new(conditions: condition_per_row, source_tdcs: @source_tdcs)
|
||||||
|
%fieldset.fr-fieldset
|
||||||
|
%legend.fr-mx-1w.fr-label.fr-py-0.fr-mb-1w.fr-mt-2w
|
||||||
|
Règles d’inéligibilité
|
||||||
|
%span.fr-hint-text Vous pouvez utiliser 1 ou plusieurs critère pour bloquer le dépot
|
||||||
|
.fr-fieldset__element
|
||||||
|
= form_tag admin_procedure_ineligibilite_rules_path(@draft_revision.procedure_id), method: :patch, data: { turbo: true, controller: 'autosave' }, class: 'form width-100' do
|
||||||
|
.conditionnel.width-100
|
||||||
|
%table.condition-table
|
||||||
|
%thead
|
||||||
|
%tr
|
||||||
|
%th.fr-pt-0.far-left
|
||||||
|
%th.fr-pt-0.target Champ Cible
|
||||||
|
%th.fr-pt-0.operator Opérateur
|
||||||
|
%th.fr-pt-0.value Valeur
|
||||||
|
%th.fr-pt-0.delete-column
|
||||||
|
%tbody
|
||||||
|
- rows.each.with_index do |(targeted_champ, operator_name, value), row_index|
|
||||||
|
%tr
|
||||||
|
%td.far-left= far_left_tag(row_index)
|
||||||
|
%td.target= left_operand_tag(targeted_champ, row_index)
|
||||||
|
%td.operator= operator_tag(operator_name, targeted_champ, row_index)
|
||||||
|
%td.value= right_operand_tag(targeted_champ, value, row_index, operator_name)
|
||||||
|
%td.delete-column= delete_condition_tag(row_index)
|
||||||
|
%tfoot
|
||||||
|
%tr
|
||||||
|
%td.text-right{ colspan: 5 }= add_condition_tag
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
= form_for(@draft_revision, url: change_admin_procedure_ineligibilite_rules_path(@draft_revision.procedure_id)) do |f|
|
||||||
|
.fr-fieldset__element= render Dsfr::InputComponent.new(form: f, attribute: :ineligibilite_message, input_type: :text_area, opts: {rows: 5})
|
||||||
|
.fr-fieldset__element
|
||||||
|
.fr-toggle
|
||||||
|
= f.check_box :ineligibilite_enabled, class: 'fr-toggle__input', data: @opt
|
||||||
|
= f.label :ineligibilite_enabled, "Inéligibilité des dossiers", data: { 'fr-checked-label': "Actif", 'fr-unchecked-label': "Inactif" }, class: 'fr-toggle__label'
|
||||||
|
%p.fr-hint-text Passer l’intérrupteur sur activé pour que les critères d’inéligibilité configurés s'appliquent
|
||||||
|
|
||||||
|
|
||||||
|
= render Procedure::FixedFooterComponent.new(procedure: @draft_revision.procedure, form: f, extra_class_names: 'fr-col-offset-md-2 fr-col-md-8')
|
10
app/components/procedure/pending_republish_component.rb
Normal file
10
app/components/procedure/pending_republish_component.rb
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
class Procedure::PendingRepublishComponent < ApplicationComponent
|
||||||
|
def initialize(procedure:, render_if:)
|
||||||
|
@procedure = procedure
|
||||||
|
@render_if = render_if
|
||||||
|
end
|
||||||
|
|
||||||
|
def render?
|
||||||
|
@render_if
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
fr:
|
||||||
|
pending_republish_html: |
|
||||||
|
Ces modifications ne seront appliquées qu'à la prochaine publication. Vous pouvez vérifier puis publier les modifications sur l'écran de <a href="%{href}">gestion de la démarche</a>
|
|
@ -0,0 +1,3 @@
|
||||||
|
= render Dsfr::AlertComponent.new(state: :warning) do |c|
|
||||||
|
- c.with_body do
|
||||||
|
= t('.pending_republish_html', href: admin_procedure_path(@procedure.id))
|
|
@ -0,0 +1,74 @@
|
||||||
|
module Administrateurs
|
||||||
|
class IneligibiliteRulesController < AdministrateurController
|
||||||
|
before_action :retrieve_procedure
|
||||||
|
|
||||||
|
def edit
|
||||||
|
end
|
||||||
|
|
||||||
|
def change
|
||||||
|
if draft_revision.update(procedure_revision_params)
|
||||||
|
redirect_to edit_admin_procedure_ineligibilite_rules_path(@procedure)
|
||||||
|
else
|
||||||
|
flash[:alert] = draft_revision.errors.full_messages
|
||||||
|
render :edit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_row
|
||||||
|
condition = Logic.add_empty_condition_to(draft_revision.ineligibilite_rules)
|
||||||
|
draft_revision.update!(ineligibilite_rules: condition)
|
||||||
|
@ineligibilite_rules_component = build_ineligibilite_rules_component
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_row
|
||||||
|
condition = condition_form.delete_row(row_index).to_condition
|
||||||
|
draft_revision.update!(ineligibilite_rules: condition)
|
||||||
|
|
||||||
|
@ineligibilite_rules_component = build_ineligibilite_rules_component
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
condition = condition_form.to_condition
|
||||||
|
draft_revision.update!(ineligibilite_rules: condition)
|
||||||
|
|
||||||
|
@ineligibilite_rules_component = build_ineligibilite_rules_component
|
||||||
|
end
|
||||||
|
|
||||||
|
def change_targeted_champ
|
||||||
|
condition = condition_form.change_champ(row_index).to_condition
|
||||||
|
draft_revision.update!(ineligibilite_rules: condition)
|
||||||
|
@ineligibilite_rules_component = build_ineligibilite_rules_component
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def build_ineligibilite_rules_component
|
||||||
|
Conditions::IneligibiliteRulesComponent.new(draft_revision: draft_revision)
|
||||||
|
end
|
||||||
|
|
||||||
|
def draft_revision
|
||||||
|
@procedure.draft_revision
|
||||||
|
end
|
||||||
|
|
||||||
|
def condition_form
|
||||||
|
ConditionForm.new(ineligibilite_rules_params.merge(source_tdcs: draft_revision.types_de_champ_for(scope: :public)))
|
||||||
|
end
|
||||||
|
|
||||||
|
def ineligibilite_rules_params
|
||||||
|
params
|
||||||
|
.require(:procedure_revision)
|
||||||
|
.require(:condition_form)
|
||||||
|
.permit(:top_operator_name, rows: [:targeted_champ, :operator_name, :value])
|
||||||
|
end
|
||||||
|
|
||||||
|
def row_index
|
||||||
|
params[:row_index].to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
def procedure_revision_params
|
||||||
|
params
|
||||||
|
.require(:procedure_revision)
|
||||||
|
.permit(:ineligibilite_message, :ineligibilite_enabled)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,4 +1,5 @@
|
||||||
class ProcedureRevision < ApplicationRecord
|
class ProcedureRevision < ApplicationRecord
|
||||||
|
include Logic
|
||||||
self.implicit_order_column = :created_at
|
self.implicit_order_column = :created_at
|
||||||
belongs_to :procedure, -> { with_discarded }, inverse_of: :revisions, optional: false
|
belongs_to :procedure, -> { with_discarded }, inverse_of: :revisions, optional: false
|
||||||
belongs_to :dossier_submitted_message, inverse_of: :revisions, optional: true, dependent: :destroy
|
belongs_to :dossier_submitted_message, inverse_of: :revisions, optional: true, dependent: :destroy
|
||||||
|
@ -17,8 +18,19 @@ class ProcedureRevision < ApplicationRecord
|
||||||
|
|
||||||
scope :ordered, -> { order(:created_at) }
|
scope :ordered, -> { order(:created_at) }
|
||||||
|
|
||||||
|
validates :ineligibilite_message, presence: true, if: -> { ineligibilite_enabled? }
|
||||||
|
|
||||||
delegate :path, to: :procedure, prefix: true
|
delegate :path, to: :procedure, prefix: true
|
||||||
|
|
||||||
|
validate :ineligibilite_rules_are_valid?,
|
||||||
|
on: [:ineligibilite_rules_editor, :publication]
|
||||||
|
validates :ineligibilite_message,
|
||||||
|
presence: true,
|
||||||
|
if: -> { ineligibilite_enabled? },
|
||||||
|
on: [:ineligibilite_rules_editor, :publication]
|
||||||
|
|
||||||
|
serialize :ineligibilite_rules, LogicSerializer
|
||||||
|
|
||||||
def build_champs_public
|
def build_champs_public
|
||||||
# reload: it can be out of sync in test if some tdcs are added wihtout using add_tdc
|
# reload: it can be out of sync in test if some tdcs are added wihtout using add_tdc
|
||||||
types_de_champ_public.reload.map(&:build_champ)
|
types_de_champ_public.reload.map(&:build_champ)
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
- rendered = render @ineligibilite_rules_component
|
||||||
|
|
||||||
|
- if rendered.present?
|
||||||
|
= turbo_stream.replace dom_id(@procedure.draft_revision, :ineligibilite_rules) do
|
||||||
|
- rendered
|
||||||
|
- else
|
||||||
|
= turbo_stream.remove dom_id(@procedure.draft_revision, :ineligibilite_rules)
|
|
@ -0,0 +1 @@
|
||||||
|
= render partial: 'update'
|
|
@ -0,0 +1 @@
|
||||||
|
= render partial: 'update'
|
|
@ -0,0 +1 @@
|
||||||
|
= render partial: 'update'
|
|
@ -0,0 +1 @@
|
||||||
|
= render partial: 'update'
|
28
app/views/administrateurs/ineligibilite_rules/edit.html.haml
Normal file
28
app/views/administrateurs/ineligibilite_rules/edit.html.haml
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
= render partial: 'administrateurs/breadcrumbs',
|
||||||
|
locals: { steps: [['Démarches', admin_procedures_path],
|
||||||
|
[@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)],
|
||||||
|
['Inéligibilité des dossiers']] }
|
||||||
|
|
||||||
|
|
||||||
|
.fr-container
|
||||||
|
.fr-grid-row
|
||||||
|
.fr-col-12.fr-col-offset-md-2.fr-col-md-8
|
||||||
|
%h1.fr-h1 Inéligibilité des dossiers
|
||||||
|
|
||||||
|
= render Dsfr::AlertComponent.new(title: nil, size: :sm, state: :info, heading_level: 'h2', extra_class_names: 'fr-my-2w') do |c|
|
||||||
|
- c.with_body do
|
||||||
|
%p
|
||||||
|
Les dossiers répondant à vos critères d’inéligibilité ne pourront pas être déposés. Plus d’informations sur l’inéligibilité des dossiers dans la
|
||||||
|
= link_to('doc', ELIGIBILITE_URL, title: "Document sur l’inéligibilité des dossiers", **external_link_attributes)
|
||||||
|
|
||||||
|
- if !@procedure.draft_revision.conditionable_types_de_champ.present?
|
||||||
|
%p.fr-mt-2w.fr-mb-2w
|
||||||
|
Pour configurer l’inéligibilité des dossiers, votre formulaire doit comporter au moins un champ supportant les critères d’inéligibilité. Il vous faut donc ajouter au moins un des champs suivant à votre formulaire :
|
||||||
|
%ul
|
||||||
|
- Logic::ChampValue::MANAGED_TYPE_DE_CHAMP.values.each do
|
||||||
|
%li= "« #{t(_1, scope: [:activerecord, :attributes, :type_de_champ, :type_champs])} »"
|
||||||
|
%p.fr-mt-2w
|
||||||
|
= link_to 'Ajouter un champ supportant les critères d’inéligibilité', champs_admin_procedure_path(@procedure), class: 'fr-link fr-icon-arrow-right-line fr-link--icon-right'
|
||||||
|
= render Procedure::FixedFooterComponent.new(procedure: @procedure)
|
||||||
|
- else
|
||||||
|
= render Conditions::IneligibiliteRulesComponent.new(draft_revision: @procedure.draft_revision)
|
|
@ -0,0 +1 @@
|
||||||
|
= render partial: 'update'
|
|
@ -61,6 +61,9 @@ DS_ENV="staging"
|
||||||
# Instance customization: URL of the Routage documentation
|
# Instance customization: URL of the Routage documentation
|
||||||
# ROUTAGE_URL=""
|
# ROUTAGE_URL=""
|
||||||
#
|
#
|
||||||
|
# Instance customization: URL of the EligibiliteDossier documentation
|
||||||
|
# ELIGIBILITE_URL=""
|
||||||
|
#
|
||||||
# Instance customization: URL of the accessibility statement
|
# Instance customization: URL of the accessibility statement
|
||||||
# ACCESSIBILITE_URL=""
|
# ACCESSIBILITE_URL=""
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ CGU_URL = ENV.fetch("CGU_URL", [DOC_URL, "cgu"].join("/"))
|
||||||
MENTIONS_LEGALES_URL = ENV.fetch("MENTIONS_LEGALES_URL", "/mentions-legales")
|
MENTIONS_LEGALES_URL = ENV.fetch("MENTIONS_LEGALES_URL", "/mentions-legales")
|
||||||
ACCESSIBILITE_URL = ENV.fetch("ACCESSIBILITE_URL", "/declaration-accessibilite")
|
ACCESSIBILITE_URL = ENV.fetch("ACCESSIBILITE_URL", "/declaration-accessibilite")
|
||||||
ROUTAGE_URL = ENV.fetch("ROUTAGE_URL", [DOC_URL, "/pour-aller-plus-loin/routage"].join("/"))
|
ROUTAGE_URL = ENV.fetch("ROUTAGE_URL", [DOC_URL, "/pour-aller-plus-loin/routage"].join("/"))
|
||||||
|
ELIGIBILITE_URL = ENV.fetch("ELIGIBILITE_URL", [DOC_URL, "/pour-aller-plus-loin/eligibilite-des-dossiers"].join("/"))
|
||||||
API_DOC_URL = [DOC_URL, "api-graphql"].join("/")
|
API_DOC_URL = [DOC_URL, "api-graphql"].join("/")
|
||||||
WEBHOOK_DOC_URL = [DOC_URL, "pour-aller-plus-loin", "webhook"].join("/")
|
WEBHOOK_DOC_URL = [DOC_URL, "pour-aller-plus-loin", "webhook"].join("/")
|
||||||
WEBHOOK_ALTERNATIVE_DOC_URL = [DOC_URL, "api-graphql", "cas-dusages-exemple-dimplementation", "synchroniser-les-dossiers-modifies-sur-ma-demarche"].join("/")
|
WEBHOOK_ALTERNATIVE_DOC_URL = [DOC_URL, "api-graphql", "cas-dusages-exemple-dimplementation", "synchroniser-les-dossiers-modifies-sur-ma-demarche"].join("/")
|
||||||
|
|
|
@ -607,6 +607,14 @@ Rails.application.routes.draw do
|
||||||
delete :delete_row, on: :member
|
delete :delete_row, on: :member
|
||||||
end
|
end
|
||||||
|
|
||||||
|
resource :ineligibilite_rules, only: [:edit, :update, :destroy], param: :revision_id do
|
||||||
|
patch :change_targeted_champ, on: :member
|
||||||
|
patch :update_all_rows, on: :member
|
||||||
|
patch :add_row, on: :member
|
||||||
|
delete :delete_row, on: :member
|
||||||
|
patch :change
|
||||||
|
end
|
||||||
|
|
||||||
patch :update_defaut_groupe_instructeur, controller: 'routing_rules', as: :update_defaut_groupe_instructeur
|
patch :update_defaut_groupe_instructeur, controller: 'routing_rules', as: :update_defaut_groupe_instructeur
|
||||||
|
|
||||||
put 'clone'
|
put 'clone'
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
describe Conditions::IneligibiliteRulesComponent, type: :component do
|
||||||
|
include Logic
|
||||||
|
let(:procedure) { create(:procedure) }
|
||||||
|
let(:component) { described_class.new(draft_revision: procedure.draft_revision) }
|
||||||
|
|
||||||
|
describe 'render' do
|
||||||
|
let(:ineligibilite_message) { 'ok' }
|
||||||
|
let(:ineligibilite_enabled) { true }
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.update(ineligibilite_rules:, ineligibilite_message:, ineligibilite_enabled:)
|
||||||
|
end
|
||||||
|
context 'when ineligibilite_rules are valid' do
|
||||||
|
let(:ineligibilite_rules) { ds_eq(constant(true), constant(true)) }
|
||||||
|
it 'does not render error' do
|
||||||
|
render_inline(component)
|
||||||
|
expect(page).not_to have_selector('.errors-summary')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
context 'when ineligibilite_rules are invalid' do
|
||||||
|
let(:ineligibilite_rules) { ds_eq(constant(true), constant(1)) }
|
||||||
|
it 'does not render error' do
|
||||||
|
render_inline(component)
|
||||||
|
expect(page).to have_selector('.errors-summary')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#pending_changes' do
|
||||||
|
context 'when procedure is published' do
|
||||||
|
it 'detect changes when setup changes' do
|
||||||
|
expect(component.pending_changes?).to be_falsey
|
||||||
|
|
||||||
|
procedure.draft_revision.ineligibilite_message = 'changed'
|
||||||
|
expect(component.pending_changes?).to be_falsey
|
||||||
|
|
||||||
|
procedure.reload
|
||||||
|
procedure.draft_revision.ineligibilite_enabled = true
|
||||||
|
expect(component.pending_changes?).to be_falsey
|
||||||
|
|
||||||
|
procedure.reload
|
||||||
|
procedure.draft_revision.ineligibilite_rules = {}
|
||||||
|
expect(component.pending_changes?).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when procedure is published' do
|
||||||
|
let(:procedure) { create(:procedure, :published) }
|
||||||
|
it 'detect changes when setup changes' do
|
||||||
|
expect(component.pending_changes?).to be_falsey
|
||||||
|
|
||||||
|
procedure.draft_revision.ineligibilite_message = 'changed'
|
||||||
|
expect(component.pending_changes?).to be_truthy
|
||||||
|
|
||||||
|
procedure.reload
|
||||||
|
procedure.draft_revision.ineligibilite_enabled = true
|
||||||
|
expect(component.pending_changes?).to be_truthy
|
||||||
|
|
||||||
|
procedure.reload
|
||||||
|
procedure.draft_revision.ineligibilite_rules = {}
|
||||||
|
expect(component.pending_changes?).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,14 @@
|
||||||
|
describe Procedure::PendingRepublishComponent, type: :component do
|
||||||
|
subject { render_inline(described_class.new(render_if:, procedure: build(:procedure, id: 1))) }
|
||||||
|
let(:page) { subject }
|
||||||
|
describe 'render_if' do
|
||||||
|
context 'when false' do
|
||||||
|
let(:render_if) { false }
|
||||||
|
it { expect(page).not_to have_text('Ces modifications ne seront appliquées') }
|
||||||
|
end
|
||||||
|
context 'when true' do
|
||||||
|
let(:render_if) { true }
|
||||||
|
it { expect(page).to have_text('Ces modifications ne seront appliquées') }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,231 @@
|
||||||
|
describe Administrateurs::IneligibiliteRulesController, type: :controller do
|
||||||
|
include Logic
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
let(:admin) { create(:administrateur, user: create(:user)) }
|
||||||
|
let(:procedure) { create(:procedure, administrateurs: [admin], types_de_champ_public:) }
|
||||||
|
let(:types_de_champ_public) { [] }
|
||||||
|
|
||||||
|
describe 'condition management' do
|
||||||
|
before { sign_in(admin.user) }
|
||||||
|
|
||||||
|
let(:default_params) do
|
||||||
|
{
|
||||||
|
procedure_id: procedure.id,
|
||||||
|
revision_id: procedure.draft_revision.id
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#add_row' do
|
||||||
|
subject { post :add_row, params: default_params, format: :turbo_stream }
|
||||||
|
|
||||||
|
context 'without any row' do
|
||||||
|
it 'creates an empty condition' do
|
||||||
|
expect { subject }.to change { procedure.draft_revision.reload.ineligibilite_rules }
|
||||||
|
.from(nil)
|
||||||
|
.to(empty_operator(empty, empty))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with row' do
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.ineligibilite_rules = empty_operator(empty, empty)
|
||||||
|
procedure.draft_revision.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'add one more creates an empty condition' do
|
||||||
|
expect { subject }.to change { procedure.draft_revision.reload.ineligibilite_rules }
|
||||||
|
.from(empty_operator(empty, empty))
|
||||||
|
.to(ds_and([
|
||||||
|
empty_operator(empty, empty),
|
||||||
|
empty_operator(empty, empty)
|
||||||
|
]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'delete_row' do
|
||||||
|
let(:condition_form) do
|
||||||
|
{
|
||||||
|
top_operator_name: Logic::And.name,
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
targeted_champ: empty.to_json,
|
||||||
|
operator_name: Logic::EmptyOperator,
|
||||||
|
value: empty.to_json
|
||||||
|
},
|
||||||
|
{
|
||||||
|
targeted_champ: empty.to_json,
|
||||||
|
operator_name: Logic::EmptyOperator,
|
||||||
|
value: empty.to_json
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
let(:initial_condition) do
|
||||||
|
ds_and([
|
||||||
|
empty_operator(empty, empty),
|
||||||
|
empty_operator(empty, empty)
|
||||||
|
])
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { delete :delete_row, params: default_params.merge(row_index: 0, procedure_revision: { condition_form: }), format: :turbo_stream }
|
||||||
|
it 'remove condition' do
|
||||||
|
procedure.draft_revision.update(ineligibilite_rules: initial_condition)
|
||||||
|
|
||||||
|
expect { subject }
|
||||||
|
.to change { procedure.draft_revision.reload.ineligibilite_rules }
|
||||||
|
.from(initial_condition)
|
||||||
|
.to(empty_operator(empty, empty))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'simple tdc' do
|
||||||
|
let(:types_de_champ_public) { [{ type: :yes_no }] }
|
||||||
|
let(:yes_no_tdc) { procedure.draft_revision.types_de_champ_for(scope: :public).first }
|
||||||
|
let(:targeted_champ) { champ_value(yes_no_tdc.stable_id).to_json }
|
||||||
|
|
||||||
|
describe '#change_targeted_champ' do
|
||||||
|
let(:condition_form) do
|
||||||
|
{
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
targeted_champ: targeted_champ,
|
||||||
|
operator_name: Logic::Eq.name,
|
||||||
|
value: constant(true).to_json
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
subject { patch :change_targeted_champ, params: default_params.merge(procedure_revision: { condition_form: }), format: :turbo_stream }
|
||||||
|
it 'update condition' do
|
||||||
|
expect { subject }.to change { procedure.draft_revision.reload.ineligibilite_rules }
|
||||||
|
.from(nil)
|
||||||
|
.to(ds_eq(champ_value(yes_no_tdc.stable_id), constant(true)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#update' do
|
||||||
|
let(:value) { constant(true).to_json }
|
||||||
|
let(:operator_name) { Logic::Eq.name }
|
||||||
|
let(:condition_form) do
|
||||||
|
{
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
targeted_champ: targeted_champ,
|
||||||
|
operator_name: operator_name,
|
||||||
|
value: value
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
subject { patch :update, params: default_params.merge(procedure_revision: { condition_form: condition_form }), format: :turbo_stream }
|
||||||
|
it 'updates condition' do
|
||||||
|
expect { subject }.to change { procedure.draft_revision.reload.ineligibilite_rules }
|
||||||
|
.from(nil)
|
||||||
|
.to(ds_eq(champ_value(yes_no_tdc.stable_id), constant(true)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'repetition tdc' do
|
||||||
|
let(:types_de_champ_public) { [{ type: :repetition, children: [{ type: :yes_no }] }] }
|
||||||
|
let(:yes_no_tdc) { procedure.draft_revision.types_de_champ_for(scope: :public).find { _1.type_champ == 'yes_no' } }
|
||||||
|
let(:targeted_champ) { champ_value(yes_no_tdc.stable_id).to_json }
|
||||||
|
let(:condition_form) do
|
||||||
|
{
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
targeted_champ: targeted_champ,
|
||||||
|
operator_name: Logic::Eq.name,
|
||||||
|
value: constant(true).to_json
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
subject { patch :change_targeted_champ, params: default_params.merge(procedure_revision: { condition_form: }), format: :turbo_stream }
|
||||||
|
describe "#update" do
|
||||||
|
it 'update condition' do
|
||||||
|
expect { subject }.to change { procedure.draft_revision.reload.ineligibilite_rules }
|
||||||
|
.from(nil)
|
||||||
|
.to(ds_eq(champ_value(yes_no_tdc.stable_id), constant(true)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#change_targeted_champ' do
|
||||||
|
let(:condition_form) do
|
||||||
|
{
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
targeted_champ: targeted_champ,
|
||||||
|
operator_name: Logic::Eq.name,
|
||||||
|
value: constant(true).to_json
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
subject { patch :change_targeted_champ, params: default_params.merge(procedure_revision: { condition_form: }), format: :turbo_stream }
|
||||||
|
it 'update condition' do
|
||||||
|
expect { subject }.to change { procedure.draft_revision.reload.ineligibilite_rules }
|
||||||
|
.from(nil)
|
||||||
|
.to(ds_eq(champ_value(yes_no_tdc.stable_id), constant(true)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#edit' do
|
||||||
|
subject { get :edit, params: { procedure_id: procedure.id } }
|
||||||
|
|
||||||
|
context 'when user is not signed in' do
|
||||||
|
it { is_expected.to redirect_to(new_user_session_path) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user is signed in but not admin of procedure' do
|
||||||
|
before { sign_in(user) }
|
||||||
|
it { is_expected.to redirect_to(new_user_session_path) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user is signed as admin' do
|
||||||
|
before do
|
||||||
|
sign_in(admin.user)
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to have_http_status(200) }
|
||||||
|
|
||||||
|
context 'rendered without tdc' do
|
||||||
|
let(:types_de_champ_public) { [] }
|
||||||
|
render_views
|
||||||
|
|
||||||
|
it { expect(response.body).to have_link("Ajouter un champ supportant les critères d’inéligibilité") }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'rendered with tdc' do
|
||||||
|
let(:types_de_champ_public) { [{ type: :yes_no }] }
|
||||||
|
render_views
|
||||||
|
|
||||||
|
it { expect(response.body).not_to have_link("Ajouter un champ supportant les critères d’inéligibilité") }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'change' do
|
||||||
|
let(:params) do
|
||||||
|
{
|
||||||
|
procedure_id: procedure.id,
|
||||||
|
procedure_revision: {
|
||||||
|
ineligibilite_message: 'panpan',
|
||||||
|
ineligibilite_enabled: '1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
before { sign_in(admin.user) }
|
||||||
|
it 'works' do
|
||||||
|
patch :change, params: params
|
||||||
|
draft_revision = procedure.reload.draft_revision
|
||||||
|
expect(draft_revision.ineligibilite_message).to eq('panpan')
|
||||||
|
expect(draft_revision.ineligibilite_enabled).to eq(true)
|
||||||
|
expect(response).to redirect_to(edit_admin_procedure_ineligibilite_rules_path(procedure))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
45
spec/system/administrateurs/procedure_ineligibilite_spec.rb
Normal file
45
spec/system/administrateurs/procedure_ineligibilite_spec.rb
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
describe 'Administrateurs can edit procedures', js: true do
|
||||||
|
include Logic
|
||||||
|
|
||||||
|
let(:procedure) { create(:procedure, administrateurs: [create(:administrateur)]) }
|
||||||
|
before do
|
||||||
|
login_as procedure.administrateurs.first.user, scope: :user
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'setup eligibilite' do
|
||||||
|
# explain no champ compatible
|
||||||
|
visit admin_procedure_path(procedure)
|
||||||
|
expect(page).to have_content("Champs à configurer")
|
||||||
|
|
||||||
|
# explain which champs are compatible
|
||||||
|
visit edit_admin_procedure_ineligibilite_rules_path(procedure)
|
||||||
|
expect(page).to have_content("Inéligibilité des dossiers")
|
||||||
|
expect(page).to have_content("Pour configurer l’inéligibilité des dossiers, votre formulaire doit comporter au moins un champ supportant les critères d’inéligibilité. Il vous faut donc ajouter au moins un des champs suivant à votre formulaire : ")
|
||||||
|
click_on "Ajouter un champ supportant les critères d’inéligibilité"
|
||||||
|
|
||||||
|
# setup a compatible champ
|
||||||
|
expect(page).to have_content('Champs du formulaire')
|
||||||
|
click_on 'Ajouter un champ'
|
||||||
|
select "Oui/Non"
|
||||||
|
fill_in "Libellé du champ", with: "Un champ oui non"
|
||||||
|
click_on "Revenir à l'écran de gestion"
|
||||||
|
procedure.reload
|
||||||
|
first_tdc = procedure.draft_revision.types_de_champ.first
|
||||||
|
# back to procedure dashboard, explain you can set it up now
|
||||||
|
expect(page).to have_content('À configurer')
|
||||||
|
visit edit_admin_procedure_ineligibilite_rules_path(procedure)
|
||||||
|
|
||||||
|
# setup rules and stuffs
|
||||||
|
expect(page).to have_content("Inéligibilité des dossiers")
|
||||||
|
fill_in "Message d’inéligibilité", with: "vous n'etes pas eligible"
|
||||||
|
find('label', text: 'Inéligibilité des dossiers').click
|
||||||
|
click_on "Ajouter une règle d’inéligibilité"
|
||||||
|
all('select').first.select 'Un champ oui non'
|
||||||
|
click_on 'Enregistrer'
|
||||||
|
|
||||||
|
# rules are setup
|
||||||
|
wait_until { procedure.reload.draft_revision.ineligibilite_enabled == true }
|
||||||
|
expect(procedure.draft_revision.ineligibilite_message).to eq("vous n'etes pas eligible")
|
||||||
|
expect(procedure.draft_revision.ineligibilite_rules).to eq(ds_eq(champ_value(first_tdc.stable_id), constant(true)))
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue