From 52b0fbf9b74174b6408e0b2ca3178f4b4fdca0c4 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Tue, 23 Nov 2021 07:12:40 +0000 Subject: [PATCH] models: validate repetitions on publishing --- app/models/procedure.rb | 5 +++ .../no_empty_repetitions_validator.rb | 22 +++++++++++ config/locales/fr.yml | 1 + spec/models/procedure_spec.rb | 37 +++++++++++++++++++ 4 files changed, 65 insertions(+) create mode 100644 app/validators/revisions/no_empty_repetitions_validator.rb diff --git a/app/models/procedure.rb b/app/models/procedure.rb index fb3e7b9c0..cd4ac5ad1 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -234,6 +234,7 @@ class Procedure < ApplicationRecord validates :description, presence: true, allow_blank: false, allow_nil: false validates :administrateurs, presence: true validates :lien_site_web, presence: true, if: :publiee? + validates :draft_revision, 'revisions/no_empty_repetitions': true, if: :validate_for_publication? validate :check_juridique validates :path, presence: true, format: { with: /\A[a-z0-9_\-]{3,200}\z/ }, uniqueness: { scope: [:path, :closed_at, :hidden_at, :unpublished_at], case_sensitive: false } validates :duree_conservation_dossiers_dans_ds, allow_nil: false, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: MAX_DUREE_CONSERVATION } @@ -711,6 +712,10 @@ class Procedure < ApplicationRecord private + def validate_for_publication? + validation_context == :publication || publiee? + end + def before_publish assign_attributes(closed_at: nil, unpublished_at: nil) end diff --git a/app/validators/revisions/no_empty_repetitions_validator.rb b/app/validators/revisions/no_empty_repetitions_validator.rb new file mode 100644 index 000000000..b7a44043e --- /dev/null +++ b/app/validators/revisions/no_empty_repetitions_validator.rb @@ -0,0 +1,22 @@ +class Revisions::NoEmptyRepetitionsValidator < ActiveModel::EachValidator + def validate_each(procedure, attribute, revision) + return if revision.nil? + + revision_tdcs = revision.types_de_champ + revision.types_de_champ_private + repetitions = revision_tdcs.filter(&:repetition?) + repetitions.each do |repetition| + validate_repetition_not_empty(procedure, attribute, repetition) + end + end + + private + + def validate_repetition_not_empty(procedure, attribute, repetition) + if repetition.types_de_champ.blank? + procedure.errors.add( + attribute, + procedure.errors.generate_message(attribute, :empty_repetition, { value: repetition.libelle }) + ) + end + end +end diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 4f8510a83..74505b67d 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -308,6 +308,7 @@ fr: connexion: "Erreur lors de la connexion à France Connect." forbidden_html: "Seul-e-s les usagers peuvent se connecter via France Connect. En tant qu’instructeur ou administrateur, nous vous invitons à réininitialiser votre mot de passe." procedure_archived: "Cette démarche en ligne a été close, il n’est plus possible de déposer de dossier." + empty_repetition: 'Le bloc répétable « %{value} » doit comporter au moins un champ' # procedure_not_draft: "Cette démarche n’est maintenant plus en brouillon." cadastres_empty: one: "Aucune parcelle cadastrale sur la zone sélectionnée" diff --git a/spec/models/procedure_spec.rb b/spec/models/procedure_spec.rb index dc659c6e2..96f1e11bc 100644 --- a/spec/models/procedure_spec.rb +++ b/spec/models/procedure_spec.rb @@ -278,6 +278,43 @@ describe Procedure do it_behaves_like 'duree de conservation' end + + describe 'draft_revision' do + let(:repetition) { build(:type_de_champ_repetition, libelle: 'Enfants') } + let(:text_field) { build(:type_de_champ_text) } + let(:procedure) { create(:procedure, types_de_champ: [repetition]) } + let(:invalid_repetition_error_message) { 'Le bloc répétable « Enfants » doit comporter au moins un champ' } + + context 'on a draft procedure' do + it 'doesn’t validate repetitions' do + procedure.validate + expect(procedure.errors[:draft_revision]).not_to include(invalid_repetition_error_message) + end + end + + context 'on a published procedure' do + before { procedure.publish } + + it 'validates that no repetition type de champ is empty' do + procedure.validate + expect(procedure.errors[:draft_revision]).to include(invalid_repetition_error_message) + + text_field.revision = repetition.revision + text_field.order_place = repetition.types_de_champ.size + procedure.draft_revision.types_de_champ.find(&:repetition?).types_de_champ << text_field + + procedure.validate + expect(procedure.errors[:draft_revision]).not_to include(invalid_repetition_error_message) + end + end + + context 'when validating for publication' do + it 'validates that no repetition type de champ is empty' do + procedure.validate(:publication) + expect(procedure.errors[:draft_revision]).to include(invalid_repetition_error_message) + end + end + end end describe 'active' do