Merge pull request #10503 from mfo/US/fix-condition-validator-on-private-champ-using-public-tdc

Correctif: ETQ admin, je souhaite pouvoir utiliser des champs public pour conditionner une annotation privée
This commit is contained in:
mfo 2024-06-10 09:33:22 +00:00 committed by GitHub
commit ab522a3e40
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 75 additions and 39 deletions

View file

@ -1,21 +1,24 @@
class TypesDeChamp::ConditionValidator < ActiveModel::EachValidator class TypesDeChamp::ConditionValidator < ActiveModel::EachValidator
def validate_each(procedure, attribute, types_de_champ) def validate_each(procedure, attribute, types_de_champ)
public_tdcs = types_de_champ.to_a return if types_de_champ.empty?
.flat_map { _1.repetition? ? procedure.draft_revision.children_of(_1) : _1 }
public_tdcs tdcs = if attribute == :draft_types_de_champ_private
.map.with_index procedure.draft_revision.types_de_champ_for
.filter_map { |tdc, i| tdc.condition? ? [tdc, i] : nil } else
.map do |tdc, i| procedure.draft_revision.types_de_champ_for(scope: :public)
[tdc, tdc.condition.errors(public_tdcs.take(i))] end
end
.filter { |_tdc, errors| errors.present? } tdcs.each_with_index do |tdc, i|
.each do |tdc, _error_hash| next unless tdc.condition?
procedure.errors.add(
attribute, errors = tdc.condition.errors(tdcs.take(i))
procedure.errors.generate_message(attribute, :invalid_condition, { value: tdc.libelle }), next if errors.blank?
type_de_champ: tdc
) procedure.errors.add(
end attribute,
procedure.errors.generate_message(attribute, :invalid_condition, { value: tdc.libelle }),
type_de_champ: tdc
)
end
end end
end end

View file

@ -211,7 +211,7 @@ describe Procedure do
it { is_expected.to allow_value('text').on(:publication).for(:cadre_juridique) } it { is_expected.to allow_value('text').on(:publication).for(:cadre_juridique) }
context 'with deliberation' do context 'with deliberation' do
let(:procedure) { build(:procedure, cadre_juridique: nil) } let(:procedure) { build(:procedure, cadre_juridique: nil, revisions: [build(:procedure_revision)]) }
it { expect(procedure.valid?(:publication)).to eq(false) } it { expect(procedure.valid?(:publication)).to eq(false) }
@ -352,24 +352,12 @@ describe Procedure do
end end
describe 'draft_types_de_champ validations' do describe 'draft_types_de_champ validations' do
let(:repetition) { repetition = procedure.draft_revision.types_de_champ_public.find(&:repetition?) } let(:procedure) { create(:procedure, types_de_champ_public:, types_de_champ_private:) }
let(:text_field) { build(:type_de_champ_text) }
let(:invalid_repetition_error_message) { 'Le champ « Enfants » doit comporter au moins un champ répétable' }
let(:drop_down) { build(:type_de_champ_drop_down_list, :without_selectable_values, libelle: 'Civilité') }
let(:invalid_drop_down_error_message) { 'Le champ « Civilité » doit comporter au moins un choix sélectionnable' }
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :repetition, children: [{ type: :text }, { type: :integer_number }] }]) }
let(:draft) { procedure.draft_revision }
before do
draft.revision_types_de_champ.create(type_de_champ: drop_down, position: 100)
repetition.update(libelle: 'Enfants')
draft.children_of(repetition).destroy_all
end
context 'on a draft procedure' do context 'on a draft procedure' do
let(:types_de_champ_private) { [] }
let(:types_de_champ_public) { [{ type: :repetition, libelle: 'Enfants', children: [] }] }
it 'doesnt validate the types de champs' do it 'doesnt validate the types de champs' do
procedure.validate procedure.validate
expect(procedure.errors[:draft_types_de_champ_public]).not_to be_present expect(procedure.errors[:draft_types_de_champ_public]).not_to be_present
@ -377,12 +365,22 @@ describe Procedure do
end end
context 'when validating for publication' do context 'when validating for publication' do
let(:types_de_champ_public) do
[
{ type: :repetition, libelle: 'Enfants', children: [] },
{ type: :drop_down_list, libelle: 'Civilité', options: [] }
]
end
let(:types_de_champ_private) { [] }
let(:invalid_repetition_error_message) { 'Le champ « Enfants » doit comporter au moins un champ répétable' }
let(:invalid_drop_down_error_message) { 'Le champ « Civilité » doit comporter au moins un choix sélectionnable' }
it 'validates that no repetition type de champ is empty' do it 'validates that no repetition type de champ is empty' do
procedure.validate(:publication) procedure.validate(:publication)
expect(procedure.errors.full_messages_for(:draft_types_de_champ_public)).to include(invalid_repetition_error_message) expect(procedure.errors.full_messages_for(:draft_types_de_champ_public)).to include(invalid_repetition_error_message)
new_draft = procedure.draft_revision new_draft = procedure.draft_revision
repetition = procedure.draft_revision.types_de_champ_public.find(&:repetition?)
parent_coordinate = new_draft.revision_types_de_champ.find_by(type_de_champ: repetition) parent_coordinate = new_draft.revision_types_de_champ.find_by(type_de_champ: repetition)
new_draft.revision_types_de_champ.create(type_de_champ: create(:type_de_champ), position: 0, parent: parent_coordinate) new_draft.revision_types_de_champ.create(type_de_champ: create(:type_de_champ), position: 0, parent: parent_coordinate)
@ -394,6 +392,7 @@ describe Procedure do
procedure.validate(:publication) procedure.validate(:publication)
expect(procedure.errors.full_messages_for(:draft_types_de_champ_public)).to include(invalid_drop_down_error_message) expect(procedure.errors.full_messages_for(:draft_types_de_champ_public)).to include(invalid_drop_down_error_message)
drop_down = procedure.draft_revision.types_de_champ_public.find(&:drop_down_list?)
drop_down.update!(drop_down_list_value: "--title--\r\nsome value") drop_down.update!(drop_down_list_value: "--title--\r\nsome value")
procedure.reload.validate(:publication) procedure.reload.validate(:publication)
expect(procedure.errors.full_messages_for(:draft_types_de_champ_public)).not_to include(invalid_drop_down_error_message) expect(procedure.errors.full_messages_for(:draft_types_de_champ_public)).not_to include(invalid_drop_down_error_message)
@ -401,10 +400,13 @@ describe Procedure do
end end
context 'when the champ is private' do context 'when the champ is private' do
before do let(:types_de_champ_private) do
repetition.update(private: true) [
drop_down.update(private: true) { type: :repetition, libelle: 'Enfants', children: [] },
{ type: :drop_down_list, libelle: 'Civilité', options: [] }
]
end end
let(:types_de_champ_public) { [] }
let(:invalid_repetition_error_message) { 'Lannotation privée « Enfants » doit comporter au moins un champ répétable' } let(:invalid_repetition_error_message) { 'Lannotation privée « Enfants » doit comporter au moins un champ répétable' }
let(:invalid_drop_down_error_message) { 'Lannotation privée « Civilité » doit comporter au moins un choix sélectionnable' } let(:invalid_drop_down_error_message) { 'Lannotation privée « Civilité » doit comporter au moins un choix sélectionnable' }
@ -419,6 +421,38 @@ describe Procedure do
expect(procedure.errors.full_messages_for(:draft_types_de_champ_private)).to include(invalid_drop_down_error_message) expect(procedure.errors.full_messages_for(:draft_types_de_champ_private)).to include(invalid_drop_down_error_message)
end end
end end
context 'when condition on champ private use public champ' do
include Logic
let(:types_de_champ_public) { [{ type: :decimal_number, stable_id: 1 }] }
let(:types_de_champ_private) { [{ type: :text, condition: ds_eq(champ_value(1), constant(2)), stable_id: 2 }] }
it 'validate without context' do
procedure.validate
expect(procedure.errors.full_messages_for(:draft_types_de_champ_private)).to be_empty
end
it 'validate allows condition' do
procedure.validate(:types_de_champ_private_editor)
expect(procedure.errors.full_messages_for(:draft_types_de_champ_private)).to be_empty
end
end
context 'when condition on champ public use private champ' do
include Logic
let(:types_de_champ_public) { [{ type: :text, libelle: 'condition', condition: ds_eq(champ_value(1), constant(2)), stable_id: 2 }] }
let(:types_de_champ_private) { [{ type: :decimal_number, stable_id: 1 }] }
let(:error_on_condition) { "Le champ « condition » a une logique conditionnelle invalide" }
it 'validate without context' do
procedure.validate
expect(procedure.errors.full_messages_for(:draft_types_de_champ_public)).to be_empty
end
it 'validate prevent condition' do
procedure.validate(:types_de_champ_public_editor)
expect(procedure.errors.full_messages_for(:draft_types_de_champ_public)).to include(error_on_condition)
end
end
end end
context 'with auto archive' do context 'with auto archive' do

View file

@ -39,8 +39,7 @@ describe ProcedureExportService do
ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
subject subject
end end
expect(sql_count <= 62).to be_truthy
expect(sql_count <= 58).to be_truthy
dossier = dossiers.first dossier = dossiers.first