From 6c508850825c38836d638a9335c5525f8012e54d Mon Sep 17 00:00:00 2001 From: SAASVUUV Date: Mon, 1 Sep 2025 19:31:41 -0300 Subject: [PATCH 1/2] ISSUE #183: main_advisor's validation: main_advisor professor should has authorization to advise students in their levels --- app/models/advisement.rb | 13 +++++++++++++ config/locales/advisement.pt-BR.yml | 1 + 2 files changed, 14 insertions(+) diff --git a/app/models/advisement.rb b/app/models/advisement.rb index 57d67a02..479c4d53 100644 --- a/app/models/advisement.rb +++ b/app/models/advisement.rb @@ -19,6 +19,8 @@ class Advisement < ApplicationRecord message: :advisement_professor_uniqueness } + validate :main_advisor_authorization + after_create :notify_advisor def to_label @@ -89,4 +91,15 @@ def notify_advisor ] Notifier.send_emails(notifications: emails) end + + def main_advisor_authorization + if professor && main_advisor && enrollment + has_authorization = professor.advisement_authorizations. + where(level: enrollment.level). + exists? + unless has_authorization + errors.add(:base, :main_advisor_should_has_level) + end + end + end end diff --git a/config/locales/advisement.pt-BR.yml b/config/locales/advisement.pt-BR.yml index 43dfa603..c2c529fb 100644 --- a/config/locales/advisement.pt-BR.yml +++ b/config/locales/advisement.pt-BR.yml @@ -23,6 +23,7 @@ pt-BR: models: advisement: advisement_professor_uniqueness: "não pode ser orientador duas vezes da mesma matrícula" + main_advisor_should_has_level: "O orientador principal deve ter credenciamento no nivel da matrícula" models: advisement: From 53b8a3080ef3c73be56c3e083b55e54d3a099d7c Mon Sep 17 00:00:00 2001 From: SAASVUUV Date: Mon, 1 Sep 2025 19:32:33 -0300 Subject: [PATCH 2/2] ISSUE #183: Fix specs --- spec/factories/factory_advisement.rb | 1 - spec/features/advisements_spec.rb | 4 ++ .../class_enrollment_requests_spec.rb | 1 + spec/features/class_enrollments_spec.rb | 1 + spec/features/enrollment_requests_spec.rb | 1 + spec/features/enrollments_spec.rb | 1 + spec/features/pendencies_spec.rb | 1 + spec/features/scholarship_durations_spec.rb | 1 + spec/features/student_enrollment_spec.rb | 2 +- spec/models/advisement_spec.rb | 38 +++++++++++++++---- spec/models/enrollment_request_spec.rb | 1 + spec/models/enrollment_spec.rb | 7 ++++ 12 files changed, 50 insertions(+), 9 deletions(-) diff --git a/spec/factories/factory_advisement.rb b/spec/factories/factory_advisement.rb index a897c5d8..188191f8 100644 --- a/spec/factories/factory_advisement.rb +++ b/spec/factories/factory_advisement.rb @@ -9,6 +9,5 @@ factory :advisement do professor enrollment - main_advisor { true } end end diff --git a/spec/features/advisements_spec.rb b/spec/features/advisements_spec.rb index 8596bea1..463c4097 100644 --- a/spec/features/advisements_spec.rb +++ b/spec/features/advisements_spec.rb @@ -33,6 +33,10 @@ @destroy_all << FactoryBot.create(:dismissal, enrollment: @enrollment1, date: Date.today, dismissal_reason: @dismissal_reason) + @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor1, level: @level2) + @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor2, level: @level2) + @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor1, level: @level1) + @destroy_all << FactoryBot.create(:advisement, enrollment: @enrollment1, professor: @professor1, main_advisor: true) @destroy_all << FactoryBot.create(:advisement, enrollment: @enrollment2, professor: @professor2, main_advisor: true) @destroy_all << @record = FactoryBot.create(:advisement, enrollment: @enrollment3, professor: @professor1, main_advisor: true) diff --git a/spec/features/class_enrollment_requests_spec.rb b/spec/features/class_enrollment_requests_spec.rb index 4ef28b9a..cdc693e4 100644 --- a/spec/features/class_enrollment_requests_spec.rb +++ b/spec/features/class_enrollment_requests_spec.rb @@ -63,6 +63,7 @@ @destroy_all << @course_class7 = FactoryBot.create(:course_class, name: "Pesquisa", course: @course6, professor: @professor3, year: 2022, semester: 2) @destroy_all << @course_class8 = FactoryBot.create(:course_class, name: "Programação", course: @course7, professor: @professor1, year: 2022, semester: 2) + @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor1, level: @level2) @destroy_all << FactoryBot.create(:advisement, enrollment: @enrollment1, professor: @professor1, main_advisor: true) @destroy_all << @sponsor1 = FactoryBot.create(:sponsor, name: "CNPq") @destroy_all << @scholarship_type2 = FactoryBot.create(:scholarship_type, name: "Projeto") diff --git a/spec/features/class_enrollments_spec.rb b/spec/features/class_enrollments_spec.rb index 2899bfe7..ae2ed57b 100644 --- a/spec/features/class_enrollments_spec.rb +++ b/spec/features/class_enrollments_spec.rb @@ -63,6 +63,7 @@ @destroy_all << @course_class7 = FactoryBot.create(:course_class, name: "Pesquisa", course: @course6, professor: @professor3, year: 2022, semester: 2) @destroy_all << @course_class8 = FactoryBot.create(:course_class, name: "Programação", course: @course7, professor: @professor1, year: 2022, semester: 2) + @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor1, level: @level2) @destroy_all << FactoryBot.create(:advisement, enrollment: @enrollment1, professor: @professor1, main_advisor: true) @destroy_all << @sponsor1 = FactoryBot.create(:sponsor, name: "CNPq") @destroy_all << @scholarship_type2 = FactoryBot.create(:scholarship_type, name: "Projeto") diff --git a/spec/features/enrollment_requests_spec.rb b/spec/features/enrollment_requests_spec.rb index 577d6e5b..715e102c 100644 --- a/spec/features/enrollment_requests_spec.rb +++ b/spec/features/enrollment_requests_spec.rb @@ -63,6 +63,7 @@ @destroy_all << @course_class7 = FactoryBot.create(:course_class, name: "Pesquisa", course: @course6, professor: @professor3, year: 2022, semester: 2) @destroy_all << @course_class8 = FactoryBot.create(:course_class, name: "Programação", course: @course7, professor: @professor1, year: 2022, semester: 2) + @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor1, level: @level2) @destroy_all << FactoryBot.create(:advisement, enrollment: @enrollment1, professor: @professor1, main_advisor: true) @destroy_all << @sponsor1 = FactoryBot.create(:sponsor, name: "CNPq") @destroy_all << @scholarship_type2 = FactoryBot.create(:scholarship_type, name: "Projeto") diff --git a/spec/features/enrollments_spec.rb b/spec/features/enrollments_spec.rb index 25a63789..64313e69 100644 --- a/spec/features/enrollments_spec.rb +++ b/spec/features/enrollments_spec.rb @@ -55,6 +55,7 @@ @destroy_all << FactoryBot.create(:dismissal, enrollment: @enrollment2, date: 1.day.ago, dismissal_reason: @dismissal_reason2) @destroy_all << @professor1 = FactoryBot.create(:professor, name: "Erica", cpf: "3") + @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor1, level: @level2) @destroy_all << FactoryBot.create(:advisement, enrollment: @enrollment1, professor: @professor1, main_advisor: true) @destroy_all << @sponsor1 = FactoryBot.create(:sponsor, name: "CNPq") @destroy_all << @scholarship_type2 = FactoryBot.create(:scholarship_type, name: "Projeto") diff --git a/spec/features/pendencies_spec.rb b/spec/features/pendencies_spec.rb index 1d9d9f3c..9743ed54 100644 --- a/spec/features/pendencies_spec.rb +++ b/spec/features/pendencies_spec.rb @@ -67,6 +67,7 @@ @destroy_all << @course_class7 = FactoryBot.create(:course_class, name: "Pesquisa", course: @course6, professor: @professor3, year: 0.years.ago.year, semester: YearSemester.current.semester) @destroy_all << @course_class8 = FactoryBot.create(:course_class, name: "Programação", course: @course7, professor: @professor1, year: 0.years.ago.year, semester: YearSemester.current.semester) + @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor1, level: @level2) @destroy_all << FactoryBot.create(:advisement, enrollment: @enrollment1, professor: @professor1, main_advisor: true) @destroy_all << @sponsor1 = FactoryBot.create(:sponsor, name: "CNPq") @destroy_all << @scholarship_type2 = FactoryBot.create(:scholarship_type, name: "Projeto") diff --git a/spec/features/scholarship_durations_spec.rb b/spec/features/scholarship_durations_spec.rb index 2807f60a..6310d9dc 100644 --- a/spec/features/scholarship_durations_spec.rb +++ b/spec/features/scholarship_durations_spec.rb @@ -46,6 +46,7 @@ @destroy_all << @professor1 = FactoryBot.create(:professor, name: "Erica", cpf: "3") + @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor1, level: @level2) @destroy_all << FactoryBot.create(:advisement, enrollment: @enrollment1, professor: @professor1, main_advisor: true) @destroy_all << @user = create_confirmed_user([@role_adm]) diff --git a/spec/features/student_enrollment_spec.rb b/spec/features/student_enrollment_spec.rb index 2ad846c0..84a03063 100644 --- a/spec/features/student_enrollment_spec.rb +++ b/spec/features/student_enrollment_spec.rb @@ -118,7 +118,7 @@ @destroy_all << FactoryBot.create(:deferral, deferral_type: @deferral_type2, enrollment: @enrollment1, approval_date: 15.months.ago.at_beginning_of_month) # Holds - @destroy_all << @record = FactoryBot.create(:enrollment_hold, enrollment: @enrollment1, year: 3.years.ago.year, semester: 2, number_of_semesters: 1) + @destroy_all << @record = FactoryBot.create(:enrollment_hold, enrollment: @enrollment1, year: 2.years.ago.year, semester: 2, number_of_semesters: 1) # Scholarships @destroy_all << @sponsor1 = FactoryBot.create(:sponsor, name: "CNPq") diff --git a/spec/models/advisement_spec.rb b/spec/models/advisement_spec.rb index a0a9f5d5..7e8e18ed 100644 --- a/spec/models/advisement_spec.rb +++ b/spec/models/advisement_spec.rb @@ -60,9 +60,13 @@ it "should return the expected string" do professor1_name = "Leonardo" professor2_name = "Vanessa" + @destroy_later << professor0 = FactoryBot.create(:professor) @destroy_later << professor1 = FactoryBot.create(:professor, name: professor1_name) @destroy_later << professor2 = FactoryBot.create(:professor, name: professor2_name) - @destroy_later << advisement = FactoryBot.create(:advisement) + @destroy_later << level = FactoryBot.create(:level) + @destroy_later << enrollment = FactoryBot.create(:enrollment, level: level) + @destroy_later << FactoryBot.create(:advisement_authorization, professor: professor0, level: level) + @destroy_later << advisement = FactoryBot.create(:advisement, professor: professor0, enrollment: enrollment) @destroy_later << FactoryBot.create(:advisement, professor: professor1, enrollment: advisement.enrollment, main_advisor: false) @destroy_later << FactoryBot.create(:advisement, professor: professor2, enrollment: advisement.enrollment, main_advisor: false) expect(advisement.co_advisor_list).to eql("#{professor1_name} , #{professor2_name}") @@ -71,14 +75,22 @@ describe "active" do context "should return true when " do it "the enrollment does not have a dismissal" do - @destroy_later << advisement = FactoryBot.create(:advisement) + @destroy_later << level = FactoryBot.create(:level) + @destroy_later << professor1 = FactoryBot.create(:professor) + @destroy_later << enrollment = FactoryBot.create(:enrollment, level: level) + @destroy_later << FactoryBot.create(:advisement_authorization, professor: professor1, level: level) + @destroy_later << advisement = FactoryBot.create(:advisement, enrollment: enrollment, professor: professor1) expect(advisement.active).to be_truthy end end context "should return false when " do it "the enrollment have a dismissal" do - @destroy_later << advisement = FactoryBot.create(:advisement) - @destroy_later << FactoryBot.create(:dismissal, enrollment: advisement.enrollment) + @destroy_later << level = FactoryBot.create(:level) + @destroy_later << professor1 = FactoryBot.create(:professor) + @destroy_later << enrollment = FactoryBot.create(:enrollment, level: level) + @destroy_later << FactoryBot.create(:advisement_authorization, professor: professor1, level: level) + @destroy_later << advisement = FactoryBot.create(:advisement, enrollment: enrollment, professor: professor1) + @destroy_later << FactoryBot.create(:dismissal, enrollment: enrollment) expect(advisement.active).to be_falsey end end @@ -86,14 +98,22 @@ describe "co_advisor" do context "should return true when " do it "the enrollment have another advisement" do - @destroy_later << other_advisement = FactoryBot.create(:advisement) + @destroy_later << level = FactoryBot.create(:level) + @destroy_later << professor1 = FactoryBot.create(:professor) + @destroy_later << enrollment = FactoryBot.create(:enrollment, level: level) + @destroy_later << FactoryBot.create(:advisement_authorization, professor: professor1, level: level) + @destroy_later << other_advisement = FactoryBot.create(:advisement, professor: professor1, enrollment: enrollment) @destroy_later << FactoryBot.create(:advisement, enrollment: other_advisement.enrollment, main_advisor: false) expect(other_advisement.co_advisor).to be_truthy end end context "should return false when " do it "the enrollment does not have another advisement" do - @destroy_later << advisement = FactoryBot.create(:advisement) + @destroy_later << level = FactoryBot.create(:level) + @destroy_later << professor1 = FactoryBot.create(:professor) + @destroy_later << enrollment = FactoryBot.create(:enrollment, level: level) + @destroy_later << FactoryBot.create(:advisement_authorization, professor: professor1, level: level) + @destroy_later << advisement = FactoryBot.create(:advisement, professor: professor1, enrollment: enrollment, main_advisor: true) expect(advisement.co_advisor).to be_falsey end end @@ -101,7 +121,11 @@ describe "enrollment_has_advisors" do context "should return true when " do it "the enrollment have one advisement" do - @destroy_later << advisement = FactoryBot.create(:advisement) + @destroy_later << level = FactoryBot.create(:level) + @destroy_later << professor1 = FactoryBot.create(:professor) + @destroy_later << enrollment = FactoryBot.create(:enrollment, level: level) + @destroy_later << FactoryBot.create(:advisement_authorization, professor: professor1, level: level) + @destroy_later << advisement = FactoryBot.create(:advisement, professor: professor1, enrollment: enrollment, main_advisor: true) expect(advisement.enrollment_has_advisors).to be_truthy end end diff --git a/spec/models/enrollment_request_spec.rb b/spec/models/enrollment_request_spec.rb index 34a3b7a9..e9a48fb7 100644 --- a/spec/models/enrollment_request_spec.rb +++ b/spec/models/enrollment_request_spec.rb @@ -710,6 +710,7 @@ def prepare_course_class(allocations, to_destroy, attributes = {}) @destroy_later << professor_role = FactoryBot.create(:role_professor) @destroy_scenario << @advisor = FactoryBot.create(:professor) @destroy_scenario << @user = FactoryBot.create(:user, roles: [professor_role], professor: @advisor) + @destroy_scenario << FactoryBot.create(:advisement_authorization, professor: @advisor, level: @level) @destroy_scenario << FactoryBot.create(:advisement, professor: @advisor, enrollment: enrollment3) @destroy_scenario << course1 = FactoryBot.create(:course, course_type: @course_type) @destroy_scenario << course2 = FactoryBot.create(:course, course_type: @course_type) diff --git a/spec/models/enrollment_spec.rb b/spec/models/enrollment_spec.rb index 51e361e3..ad7ba1a8 100644 --- a/spec/models/enrollment_spec.rb +++ b/spec/models/enrollment_spec.rb @@ -83,6 +83,13 @@ expect(enrollment).not_to be_valid expect(enrollment).to have_error(:main_advisor_uniqueness).on(:base) end + it "has different level of his main advisor" do + professor = FactoryBot.build(:professor) + level = FactoryBot.build(:level) + professor.advisement_authorizations.build(level: level) + advisement = enrollment.advisements.build(professor: professor, main_advisor: true) + expect(advisement).to have_error(:main_advisor_should_has_level).on :base + end end end describe "thesis_defense_date" do