From 4a7cc8ff008adf87f9e3494d51dd94515742d1d6 Mon Sep 17 00:00:00 2001 From: simfeld Date: Sat, 9 Mar 2024 19:52:56 +0100 Subject: [PATCH 1/7] Add validate_course_number column to event kinds --- ...005706_add_validate_course_number_to_event_kinds.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb diff --git a/db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb b/db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb new file mode 100644 index 000000000..0e9448741 --- /dev/null +++ b/db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb @@ -0,0 +1,10 @@ +# Copyright (c) 2024, Pfadibewegung Schweiz. This file is part of +# hitobito_cvp and licensed under the Affero General Public License version 3 +# or later. See the COPYING file at the top-level directory or at +# https://github.com/hitobito/hitobito. + +class AddValidateCourseNumberToEventKinds < ActiveRecord::Migration[6.1] + def change + add_column :event_kinds, :validate_course_number, :boolean, default: false, null: false + end +end From a90453e59c3a08af3efbda3a5591937387ed5aac Mon Sep 17 00:00:00 2001 From: simfeld Date: Sat, 9 Mar 2024 19:53:40 +0100 Subject: [PATCH 2/7] Implement validation --- app/models/pbs/event/course.rb | 10 ++++++++++ app/views/event/kinds/_fields_pbs.html.haml | 2 +- config/locales/models.pbs.de.yml | 5 +++++ lib/hitobito_pbs/wagon.rb | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/models/pbs/event/course.rb b/app/models/pbs/event/course.rb index ccb4cb79e..8b5b8e412 100644 --- a/app/models/pbs/event/course.rb +++ b/app/models/pbs/event/course.rb @@ -13,6 +13,8 @@ module Pbs::Event::Course APPROVALS = %w(requires_approval_abteilung requires_approval_region requires_approval_kantonalverband requires_approval_bund).freeze + COURSE_NUMBER_REGEX = /\APBS CH(?: [A-Z]{2})? [0-9]{3}-[0-9]{2}\z/.freeze + included do include Pbs::Event::RestrictedRole @@ -42,6 +44,14 @@ module Pbs::Event::Course validates :bsv_days, numericality: { greater_than_or_equal_to: 0, allow_blank: true } validate :assert_bsv_days_precision + validates :number, format: { with: COURSE_NUMBER_REGEX, + message: :must_adhere_to_format, + if: :validate_number? } + + def validate_number? + (new_record? || number_changed? || kind_id_changed?) && kind.validate_course_number + end + ### CALLBACKS after_initialize :become_campy before_save :set_requires_approval diff --git a/app/views/event/kinds/_fields_pbs.html.haml b/app/views/event/kinds/_fields_pbs.html.haml index 243649b88..b397b7443 100644 --- a/app/views/event/kinds/_fields_pbs.html.haml +++ b/app/views/event/kinds/_fields_pbs.html.haml @@ -3,4 +3,4 @@ -# or later. See the COPYING file at the top-level directory or at -# https://github.com/hitobito/hitobito_pbs. -= f.labeled_input_fields :documents_text, :campy, :can_have_confirmations, :confirmation_name += f.labeled_input_fields :documents_text, :campy, :can_have_confirmations, :confirmation_name, :validate_course_number diff --git a/config/locales/models.pbs.de.yml b/config/locales/models.pbs.de.yml index d8b46c5aa..1c257be45 100644 --- a/config/locales/models.pbs.de.yml +++ b/config/locales/models.pbs.de.yml @@ -1238,6 +1238,7 @@ de: campy: Kurs als Lager anmelden can_have_confirmations: Export Kursbestätigungen aktivieren confirmation_name: Name der Kursart im Export-Tool + validate_course_number: Kursnummer validieren event/participation: additional_information: Wie möchtest du dich im Anlass ernähren? Was sind deine Essgewohnheiten? @@ -1362,6 +1363,10 @@ de: attributes: base: cannot_remove_parent_id: 'Das übergeordnete Lager kann nicht mehr verlassen werden, da es nicht mehr im Status "Erstellt" ist' + event/course: + attributes: + number: + must_adhere_to_format: muss dem Format "PBS CH KV XXX-JJ" entsprechen person: attributes: prefers_digital_correspondence: diff --git a/lib/hitobito_pbs/wagon.rb b/lib/hitobito_pbs/wagon.rb index c017dcb6b..923d59129 100644 --- a/lib/hitobito_pbs/wagon.rb +++ b/lib/hitobito_pbs/wagon.rb @@ -127,7 +127,7 @@ class Wagon < Rails::Engine :prefers_digital_correspondence] GroupsController.permitted_attrs += [:hostname] Event::KindsController.permitted_attrs += [:documents_text, :campy, :can_have_confirmations, - :confirmation_name] + :confirmation_name, :validate_course_number] QualificationKindsController.permitted_attrs += [:manual] ServiceTokensController.permitted_attrs += [:group_health, :census_evaluations] From 5b3ec9be0e7621e8adf0d5f01ccfcf62b0e3f69d Mon Sep 17 00:00:00 2001 From: simfeld Date: Sat, 9 Mar 2024 19:54:02 +0100 Subject: [PATCH 3/7] Add specs --- spec/models/event/course_spec.rb | 101 +++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/spec/models/event/course_spec.rb b/spec/models/event/course_spec.rb index f5b4dcfc0..a4d855fa9 100644 --- a/spec/models/event/course_spec.rb +++ b/spec/models/event/course_spec.rb @@ -232,4 +232,105 @@ def person(name, role) expect(event).to_not be_attr_used(:globally_visible) end end + + context 'validations' do + let(:kind_with_validation) { Fabricate(:event_kind, validate_course_number: true) } + let(:kind_without_validation) { event_kinds(:lpk) } + + context 'course number' do + VALID_NUMBERS = ['PBS CH 947-00', 'PBS CH XX 007-99', 'PBS CH AB 123-45'].freeze + INVALID_NUMBERS = ['PBS CH 000-FP', 'PBS XY XX 475-31', 'CH AB 123-45', 'PBS CH 123-456', + 'PBS CH AB 12-345', 'PBSCHAB123-45'].freeze + + subject { Fabricate(:course, groups: [groups(:be)], kind: kind_with_validation, number: 'PBS CH BE 123-24') } + + VALID_NUMBERS.each do |number| + it "'#{number}' is valid" do + subject.number = number + expect(subject.valid?).to be_truthy + end + end + + INVALID_NUMBERS.each do |number| + it "'#{number}' is invalid" do + subject.number = number + expect(subject.valid?).to be_falsey + expect(subject.errors[:number]).to be_present + end + end + end + + context 'when updating an existing event' do + subject { event } + + context 'with event kind having validation enabled' do + before do + subject.kind = kind_with_validation + # fixture has an invalid course number, so we need to skip validations + subject.save(validate: false) + end + + it 'is invalid for a number not matching the expected format' do + subject.number = '1234' + expect(subject.valid?).to be_falsey + expect(subject.errors[:number]).to be_present + end + + it 'is valid for a number matching the expected format' do + subject.number = 'PBS CH BE 123-24' + expect(subject.valid?).to be_truthy + end + + it 'is valid when switching to an event kind with validation disabled' do + subject.kind = kind_without_validation + expect(subject.valid?).to be_truthy + end + end + + context 'with event kind having validation disabled' do + before do + subject.kind = kind_without_validation + subject.save + end + + it 'is valid for a number not matching the expected format' do + subject.number = '1234' + expect(subject.valid?).to be_truthy + end + + it 'is invalid when switching to an event kind with validation enabled' do + subject.kind = kind_with_validation + expect(subject.valid?).to be_falsey + expect(subject.errors[:number]).to be_present + end + end + end + + context 'when creating a new event' do + subject { Event::Course.new(groups: [groups(:be)], + name: Faker::Lorem.word, + dates: [Event::Date.new(start_at: Time.zone.now)]) } + + it 'is valid for an event kind with validation enabled and a valid number' do + subject.kind = kind_with_validation + subject.number = 'PBS CH BE 123-24' + subject.validate! + puts subject.errors.full_messages + expect(subject.valid?).to be_truthy + end + + it 'is invalid for an event kind with validation enabled and an invalid number' do + subject.kind = kind_with_validation + subject.number = '1234' + expect(subject.valid?).to be_falsey + expect(subject.errors[:number]).to be_present + end + + it 'is valid for an event kind with validation disabled and an invalid number' do + subject.kind = kind_without_validation + subject.number = '1234' + expect(subject.valid?).to be_truthy + end + end + end end From fa7e971c248ce6dc71457f059473c5e916064200 Mon Sep 17 00:00:00 2001 From: simfeld Date: Sat, 9 Mar 2024 21:23:59 +0100 Subject: [PATCH 4/7] Reuse constants --- spec/models/event/course_spec.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/spec/models/event/course_spec.rb b/spec/models/event/course_spec.rb index a4d855fa9..396677b47 100644 --- a/spec/models/event/course_spec.rb +++ b/spec/models/event/course_spec.rb @@ -236,11 +236,11 @@ def person(name, role) context 'validations' do let(:kind_with_validation) { Fabricate(:event_kind, validate_course_number: true) } let(:kind_without_validation) { event_kinds(:lpk) } + VALID_NUMBERS = ['PBS CH 947-00', 'PBS CH XX 007-99', 'PBS CH AB 123-45'].freeze + INVALID_NUMBERS = ['PBS CH 000-FP', 'PBS XY XX 475-31', 'CH AB 123-45', 'PBS CH 123-456', + 'PBS CH AB 12-345', 'PBSCHAB123-45'].freeze context 'course number' do - VALID_NUMBERS = ['PBS CH 947-00', 'PBS CH XX 007-99', 'PBS CH AB 123-45'].freeze - INVALID_NUMBERS = ['PBS CH 000-FP', 'PBS XY XX 475-31', 'CH AB 123-45', 'PBS CH 123-456', - 'PBS CH AB 12-345', 'PBSCHAB123-45'].freeze subject { Fabricate(:course, groups: [groups(:be)], kind: kind_with_validation, number: 'PBS CH BE 123-24') } @@ -271,13 +271,13 @@ def person(name, role) end it 'is invalid for a number not matching the expected format' do - subject.number = '1234' + subject.number = INVALID_NUMBERS.first expect(subject.valid?).to be_falsey expect(subject.errors[:number]).to be_present end it 'is valid for a number matching the expected format' do - subject.number = 'PBS CH BE 123-24' + subject.number = VALID_NUMBERS.first expect(subject.valid?).to be_truthy end @@ -294,7 +294,7 @@ def person(name, role) end it 'is valid for a number not matching the expected format' do - subject.number = '1234' + subject.number = INVALID_NUMBERS.first expect(subject.valid?).to be_truthy end @@ -313,7 +313,7 @@ def person(name, role) it 'is valid for an event kind with validation enabled and a valid number' do subject.kind = kind_with_validation - subject.number = 'PBS CH BE 123-24' + subject.number = VALID_NUMBERS.first subject.validate! puts subject.errors.full_messages expect(subject.valid?).to be_truthy @@ -321,14 +321,14 @@ def person(name, role) it 'is invalid for an event kind with validation enabled and an invalid number' do subject.kind = kind_with_validation - subject.number = '1234' + subject.number = INVALID_NUMBERS.first expect(subject.valid?).to be_falsey expect(subject.errors[:number]).to be_present end it 'is valid for an event kind with validation disabled and an invalid number' do subject.kind = kind_without_validation - subject.number = '1234' + subject.number = INVALID_NUMBERS.first expect(subject.valid?).to be_truthy end end From 5e2163aa3e85c87a7ab3da08ce130324bec6d231 Mon Sep 17 00:00:00 2001 From: simfeld Date: Sat, 9 Mar 2024 21:30:02 +0100 Subject: [PATCH 5/7] Fix license text --- .../20231215154134_set_block_warning_sent_at_for_people.rb | 2 +- .../20240309005706_add_validate_course_number_to_event_kinds.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db/migrate/20231215154134_set_block_warning_sent_at_for_people.rb b/db/migrate/20231215154134_set_block_warning_sent_at_for_people.rb index 5fdf7601f..496182cc3 100644 --- a/db/migrate/20231215154134_set_block_warning_sent_at_for_people.rb +++ b/db/migrate/20231215154134_set_block_warning_sent_at_for_people.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Copyright (c) 2023, Pfadibewegung Schweiz. This file is part of -# hitobito_cvp and licensed under the Affero General Public License version 3 +# hitobito_pbs and licensed under the Affero General Public License version 3 # or later. See the COPYING file at the top-level directory or at # https://github.com/hitobito/hitobito. diff --git a/db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb b/db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb index 0e9448741..85bb31039 100644 --- a/db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb +++ b/db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb @@ -1,5 +1,5 @@ # Copyright (c) 2024, Pfadibewegung Schweiz. This file is part of -# hitobito_cvp and licensed under the Affero General Public License version 3 +# hitobito_pbs and licensed under the Affero General Public License version 3 # or later. See the COPYING file at the top-level directory or at # https://github.com/hitobito/hitobito. From 7201c7c05e17dbb2ab109b8a4b6c69deedba47a9 Mon Sep 17 00:00:00 2001 From: simfeld Date: Sat, 9 Mar 2024 23:36:44 +0100 Subject: [PATCH 6/7] Attempt to correct fixtures in CI --- spec/fixtures/event/kinds.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/spec/fixtures/event/kinds.yml b/spec/fixtures/event/kinds.yml index 893cceea6..055bdbebe 100644 --- a/spec/fixtures/event/kinds.yml +++ b/spec/fixtures/event/kinds.yml @@ -3,9 +3,12 @@ # or later. See the COPYING file at the top-level directory or at # https://github.com/hitobito/hitobito_jubla. -lpk: {} +lpk: + validate_course_number: false -bkws: {} +bkws: + validate_course_number: false fut: campy: true + validate_course_number: false From 8e9d16ca4c05074785c09cd87f8079cf9988a668 Mon Sep 17 00:00:00 2001 From: Samuel Imfeld Date: Thu, 11 Apr 2024 01:01:20 +0200 Subject: [PATCH 7/7] Update db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb Co-authored-by: Nils Rauch --- .../20240309005706_add_validate_course_number_to_event_kinds.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb b/db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb index 85bb31039..467058e20 100644 --- a/db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb +++ b/db/migrate/20240309005706_add_validate_course_number_to_event_kinds.rb @@ -6,5 +6,7 @@ class AddValidateCourseNumberToEventKinds < ActiveRecord::Migration[6.1] def change add_column :event_kinds, :validate_course_number, :boolean, default: false, null: false + + Event::Kind.reset_column_information end end