feat(admin): config sva/svr
This commit is contained in:
parent
7a8b83cfc9
commit
8c210e6fc7
10 changed files with 300 additions and 0 deletions
37
app/components/procedure/sva_svr_form_component.rb
Normal file
37
app/components/procedure/sva_svr_form_component.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Procedure::SVASVRFormComponent < ApplicationComponent
|
||||
attr_reader :procedure, :configuration
|
||||
|
||||
def initialize(procedure:, configuration:)
|
||||
@procedure = procedure
|
||||
@configuration = configuration
|
||||
end
|
||||
|
||||
def decision_buttons
|
||||
scope = ".decision_buttons"
|
||||
|
||||
[
|
||||
{ label: t("disabled", scope:), value: "disabled" },
|
||||
{ label: t("sva", scope:), value: "sva", hint: t("sva_hint", scope:) },
|
||||
{ label: t("svr", scope:), value: "svr", hint: t("svr_hint", scope:) }
|
||||
]
|
||||
end
|
||||
|
||||
def resume_buttons
|
||||
scope = ".resume_buttons"
|
||||
|
||||
[
|
||||
{
|
||||
value: "continue",
|
||||
label: t("continue_label", scope: scope),
|
||||
hint: t("continue_hint", scope: scope)
|
||||
},
|
||||
{
|
||||
value: "reset",
|
||||
label: t("reset_label", scope: scope),
|
||||
hint: t("reset_hint", scope: scope)
|
||||
}
|
||||
]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
en:
|
||||
rule: Rule to apply
|
||||
delay: Configuration of the delay before decision
|
||||
unit_labels:
|
||||
months: months
|
||||
weeks: weeks
|
||||
days: days
|
||||
resume_method: How to calculate the delay when the applicant resubmits their corrected file?
|
||||
resume_intro: |
|
||||
When an instructor asks for a file to be corrected, the countdown of the delay is interrupted.
|
||||
The delay resumes when the applicant resubmits their file stating that they have made the requested corrections.
|
||||
submit: Apply SVA/SVR configuration
|
||||
cancel: Cancel
|
||||
decision_buttons:
|
||||
disabled: "Disabled"
|
||||
sva: "Silence Equals Acceptation (SVA)"
|
||||
sva_hint: "A file is automatically accepted if no instructor has pronounced before the allotted time"
|
||||
svr: "Silence Equals Rejection (SVR)"
|
||||
svr_hint: "A file is automatically rejected if no instructor has pronounced before the allotted time"
|
||||
resume_buttons:
|
||||
continue_label: "Resume countdown from where it stopped"
|
||||
continue_hint: "Example: if the instructor asks for corrections while there are 10 days left before the automatic decision, and the file is resubmitted on April 15, it will be automatically accepted on April 25, unless the instructor pronounces in the meantime or asks for corrections again"
|
||||
reset_label: "Reset the delay"
|
||||
reset_hint: "Example: if the file is resubmitted on April 15 and the delay is 2 months, the decision will be automatically made on June 15, unless the instructor pronounces in the meantime or asks for corrections again"
|
||||
notice_new_files_only: "Information: if you activate this rule, only the newly submitted files will be subject to it."
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
fr:
|
||||
rule: Règle à appliquer
|
||||
delay: Configuration du délai avant décision
|
||||
unit_labels:
|
||||
months: mois
|
||||
weeks: semaines
|
||||
days: jours
|
||||
resume_method: Comment calculer le délai lorsque le demandeur re-dépose son dossier corrigé ?
|
||||
resume_intro: |
|
||||
Lorsqu’un instructeur demande de corriger un dossier, le décompte du délai est interrompu.
|
||||
Le délai reprend lorsque le demandeur redépose son dossier en déclarant avoir effectué les corrections demandées.
|
||||
submit: Appliquer la configuration SVA/SVR
|
||||
cancel: Annuler
|
||||
decision_buttons:
|
||||
disabled: "Désactivé"
|
||||
sva: "Silence Vaut Accord"
|
||||
sva_hint: "Un dossier est automatiquement accepté si aucun n’instructeur ne s’est prononcé avant le délai imparti"
|
||||
svr: "Silence Vaut Rejet"
|
||||
svr_hint: "Un dossier est automatiquement refusé si aucun n’instructeur ne s’est prononcé avant le délai imparti"
|
||||
resume_buttons:
|
||||
continue_label: "Reprendre le décompte depuis le moment où il s’était arrêté"
|
||||
continue_hint: "Exemple: si l’instructeur demande des corrections alors qu’il reste 10 jours avant la décision automatique, et que le dossier est re-déposé le 15 avril, il sera automatiquement accepté le 25 avril, sauf à ce que l’instructeur se prononce d’ici là ou demande à nouveau des corrections"
|
||||
reset_label: "Réinitialiser le délai"
|
||||
reset_hint: "Exemple: si le dossier est re-déposé le 15 avril et que le délai est de 2 mois, la décision sera automatiquement prise le 15 juin, sauf à ce que l’instructeur se prononce d’ici là ou demande à nouveau des corrections"
|
||||
notice_new_files_only: "Information : si vous activez cette règle, seuls les nouveaux dossiers déposés y seront soumis."
|
|
@ -0,0 +1,37 @@
|
|||
= form_for [procedure, configuration], url: admin_procedure_sva_svr_path(procedure), method: :put do |f|
|
||||
- if procedure.publiee?
|
||||
.fr-alert.fr-alert--info.fr-alert--sm.fr-mb-4w
|
||||
- if procedure.sva_svr_enabled?
|
||||
%p Information : si vous désactivez cette règle, seuls les nouveaux dossiers seront impactés. Ceux déjà déjà déposés la conserveront.
|
||||
- else
|
||||
%p= t('.notice_new_files_only')
|
||||
|
||||
|
||||
%fieldset.fr-fieldset
|
||||
%legend.fr-fieldset__legend= t(".rule")
|
||||
= render Dsfr::RadioButtonListComponent.new(form: f, target: :decision, buttons: decision_buttons, error: configuration.errors[:decision].first)
|
||||
|
||||
%fieldset.fr-fieldset
|
||||
%legend.fr-fieldset__legend= t(".delay")
|
||||
.fr-fieldset__element.fr-fieldset__element--inline
|
||||
.fr-input-group
|
||||
= f.number_field :period, class: 'fr-input', disabled: form_disabled?
|
||||
.fr-fieldset__element.fr-fieldset__element--inline
|
||||
.fr-select-group
|
||||
= f.select :unit, options_for_select(SVASVRConfiguration.unit_options.map { [t(_1, scope: ".unit_labels"), _1] }, selected: configuration.unit), {}, class: 'fr-select', disabled: form_disabled?
|
||||
|
||||
%fieldset.fr-fieldset
|
||||
%legend.fr-fieldset__legend
|
||||
= t(".resume_method")
|
||||
|
||||
%span.fr-hint-text
|
||||
= t(".resume_intro")
|
||||
|
||||
- if procedure.publiee? && procedure.sva_svr_enabled?
|
||||
.fr-alert.fr-alert--warning.fr-alert--sm
|
||||
%p Attention : un changement de ce réglage affectera les éventuels dossiers en cours.
|
||||
|
||||
= render Dsfr::RadioButtonListComponent.new(form: f, target: :resume, buttons: resume_buttons)
|
||||
|
||||
= f.submit t(".submit"), class: "fr-btn"
|
||||
= link_to t(".cancel"), admin_procedure_path(procedure.id), class: "fr-btn fr-btn--secondary fr-ml-2w"
|
34
app/controllers/administrateurs/sva_svr_controller.rb
Normal file
34
app/controllers/administrateurs/sva_svr_controller.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
module Administrateurs
|
||||
class SVASVRController < AdministrateurController
|
||||
before_action :retrieve_procedure
|
||||
|
||||
def show
|
||||
redirect_to edit_admin_procedure_sva_svr_path(@procedure.id)
|
||||
end
|
||||
|
||||
def edit
|
||||
@configuration = @procedure.sva_svr_configuration
|
||||
end
|
||||
|
||||
def update
|
||||
@configuration = @procedure.sva_svr_configuration
|
||||
@configuration.assign_attributes(configuration_params)
|
||||
|
||||
if @configuration.valid?
|
||||
@procedure.update!(sva_svr: @configuration.attributes)
|
||||
|
||||
flash.notice = "La configuration SVA/SVR a été mise à jour et prend immédiatement effet pour les nouveaux dossiers."
|
||||
redirect_to admin_procedure_path(@procedure)
|
||||
else
|
||||
flash.now.alert = "Des erreurs empêchent la validation du SVA/SVR. Corrigez les erreurs"
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def configuration_params
|
||||
params.require(:sva_svr_configuration).permit(:decision, :period, :unit, :resume)
|
||||
end
|
||||
end
|
||||
end
|
27
app/models/concerns/procedure_sva_svr_concern.rb
Normal file
27
app/models/concerns/procedure_sva_svr_concern.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
module ProcedureSVASVRConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
def sva_svr_enabled?
|
||||
sva? || svr?
|
||||
end
|
||||
|
||||
def sva?
|
||||
decision == :sva
|
||||
end
|
||||
|
||||
def svr?
|
||||
decision == :svr
|
||||
end
|
||||
|
||||
def sva_svr_configuration
|
||||
@sva_svr_configuration ||= SVASVRConfiguration.new(sva_svr)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def decision
|
||||
sva_svr.fetch("decision", nil)&.to_sym
|
||||
end
|
||||
end
|
||||
end
|
|
@ -69,6 +69,7 @@ class Procedure < ApplicationRecord
|
|||
include EncryptableConcern
|
||||
include InitiationProcedureConcern
|
||||
include ProcedureGroupeInstructeurAPIHackConcern
|
||||
include ProcedureSVASVRConcern
|
||||
|
||||
include Discard::Model
|
||||
self.discard_column = :hidden_at
|
||||
|
|
28
app/models/sva_svr_configuration.rb
Normal file
28
app/models/sva_svr_configuration.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
class SVASVRConfiguration
|
||||
include ActiveModel::Model
|
||||
include ActiveModel::Attributes
|
||||
|
||||
attribute :decision, default: 'disabled'
|
||||
attribute :period, default: 2
|
||||
attribute :unit, default: 'months'
|
||||
attribute :resume, default: 'continue'
|
||||
|
||||
DECISION_OPTIONS = ['disabled', 'sva', 'svr']
|
||||
UNIT_OPTIONS = ['days', 'weeks', 'months']
|
||||
RESUME_OPTIONS = ['continue', 'reset']
|
||||
|
||||
validates :decision, inclusion: { in: DECISION_OPTIONS }
|
||||
validates :period, presence: true, numericality: { only_integer: true }, if: -> { enabled? }
|
||||
validates :unit, presence: true, inclusion: { in: UNIT_OPTIONS }, if: -> { enabled? }
|
||||
validates :resume, presence: true, inclusion: { in: RESUME_OPTIONS }, if: -> { enabled? }
|
||||
|
||||
def self.unit_options
|
||||
UNIT_OPTIONS
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def enabled?
|
||||
decision != 'disabled'
|
||||
end
|
||||
end
|
9
app/views/administrateurs/sva_svr/edit.html.haml
Normal file
9
app/views/administrateurs/sva_svr/edit.html.haml
Normal file
|
@ -0,0 +1,9 @@
|
|||
= render partial: 'administrateurs/breadcrumbs',
|
||||
locals: { steps: [['Démarches', admin_procedures_path],
|
||||
["#{@procedure.libelle.truncate_words(10)}", admin_procedure_path(@procedure)],
|
||||
["Configuration SVA/SVR"]] }
|
||||
|
||||
.fr-container.fr-my-5w
|
||||
%h1.fr-h1 Règle du Silence Vaut Accord ou Silence Vaut Rejet
|
||||
|
||||
= render Procedure::SVASVRFormComponent.new(procedure: @procedure, configuration: @configuration)
|
75
spec/models/sva_svr_configuration_spec.rb
Normal file
75
spec/models/sva_svr_configuration_spec.rb
Normal file
|
@ -0,0 +1,75 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe SVASVRConfiguration, type: :model do
|
||||
subject(:sva_svr_config) do
|
||||
SVASVRConfiguration.new(
|
||||
decision: decision,
|
||||
period: period,
|
||||
unit: unit,
|
||||
resume: resume
|
||||
)
|
||||
end
|
||||
|
||||
let(:decision) { 'disabled' }
|
||||
let(:period) { 2 }
|
||||
let(:unit) { 'months' }
|
||||
let(:resume) { 'continue' }
|
||||
|
||||
describe 'validations' do
|
||||
context 'when decision is "disabled"' do
|
||||
it 'is valid even if period, unit and resume are nil' do
|
||||
sva_svr_config.period = nil
|
||||
sva_svr_config.unit = nil
|
||||
sva_svr_config.resume = nil
|
||||
|
||||
expect(sva_svr_config).to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
context 'when decision is not in DECISION_OPTIONS' do
|
||||
let(:decision) { 'invalid_decision' }
|
||||
|
||||
it 'is not valid' do
|
||||
expect(sva_svr_config).not_to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
context 'when decision is not "disabled"' do
|
||||
let(:decision) { 'sva' }
|
||||
|
||||
it { expect(sva_svr_config).to be_valid }
|
||||
|
||||
it 'is not valid if period is nil' do
|
||||
sva_svr_config.period = nil
|
||||
|
||||
expect(sva_svr_config).not_to be_valid
|
||||
end
|
||||
|
||||
it 'is not valid if unit is nil or not in UNIT_OPTIONS' do
|
||||
sva_svr_config.unit = nil
|
||||
|
||||
expect(sva_svr_config).not_to be_valid
|
||||
|
||||
sva_svr_config.unit = 'years'
|
||||
|
||||
expect(sva_svr_config).not_to be_valid
|
||||
end
|
||||
|
||||
it 'is not valid if resume is nil or not in RESUME_OPTIONS' do
|
||||
sva_svr_config.resume = nil
|
||||
|
||||
expect(sva_svr_config).not_to be_valid
|
||||
|
||||
sva_svr_config.resume = 'pause'
|
||||
|
||||
expect(sva_svr_config).not_to be_valid
|
||||
end
|
||||
|
||||
it 'is not valid if period is not an integer' do
|
||||
sva_svr_config.period = 3.14
|
||||
|
||||
expect(sva_svr_config).not_to be_valid
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue