Skip to content

Issue 286#562

Open
SAASVUUV wants to merge 30 commits intodevelopfrom
issue_286
Open

Issue 286#562
SAASVUUV wants to merge 30 commits intodevelopfrom
issue_286

Conversation

@SAASVUUV
Copy link
Copy Markdown
Contributor

@SAASVUUV SAASVUUV commented Jun 6, 2025

No description provided.

Comment thread app/models/enrollment_hold.rb Outdated
class_enrollments.each do |class_enrollment|
course_class = class_enrollment.course_class
unless course_class.end_date < self.start_date || course_class.start_date > self.end_date
class_enrollment.delete
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me parece estranho ter um delete dentro de um validate. Acho que seria melhor num after_update ou after_create

@JoaoFelipe
Copy link
Copy Markdown
Contributor

A validação de class enrollment request incomodando um pouco. Me parece razoável ter essa validação, mas se a matricula vai estar trancada para o período seguinte, não deveria ser possível nem abrir a tela de inscrição de disciplina.

O que está acontecendo com o PR é aparecer o link para inscrição, deixar o aluno selecionar disciplinas, mas na hora de enviar, aparece erro da seguinte forma:
image

Acho que pode manter a validação, mas também editar a tela a seguir para avisar algo como "Sua matrícula está trancada. Entre em contato com a secretaria caso queira destrancar para esta inscrição" ou algo assim.
image

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR (Issue 286) extends the “enrollment hold” concept across the enrollment flow: it blocks class enrollments/requests that overlap a hold period, invalidates existing class enrollment requests when a hold is created for the same semester, and updates the student enrollment UI + translations to reflect the held state.

Changes:

  • Add EnrollmentHold validations/callbacks to (a) prevent creating holds that overlap existing class enrollments and (b) invalidate class enrollment requests for the same semester.
  • Enforce “held enrollment” validation in ClassEnrollment and ClassEnrollmentRequest, and surface held status in the student enrollment UI (styles + message).
  • Add model + feature specs and new pt-BR i18n keys for the new validations/messages.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
spec/models/enrollment_hold_spec.rb Adds coverage for blocking holds when class enrollments exist in the hold period.
spec/models/class_enrollment_spec.rb Adds validation spec ensuring class enrollments can’t be created during a hold.
spec/models/class_enrollment_request_spec.rb Adds validation spec ensuring class enrollment requests can’t be created during a hold.
spec/features/enrollment_holds_spec.rb Feature spec for invalidating requests when a hold is created via UI.
spec/factories/factory_enrollment.rb Adjusts default admission_date used by many tests.
config/locales/student_enrollment.pt-BR.yml Adds student-facing message when enrollment is held.
config/locales/enrollment_hold.pt-BR.yml Adds validation message for “class enrollments exist in hold period”.
config/locales/class_enrollment_request.pt-BR.yml Adds labels and held-validation message for requests.
config/locales/class_enrollment.pt-BR.yml Adds label + held-validation message for enrollments.
app/views/student_enrollment/_show_enroll.html.erb Changes UI to show a held banner/message and disable enrollment links while held.
app/models/enrollment_hold.rb Implements overlap checks, request invalidation, and date-range hold detection.
app/models/course_class.rb Adds start_date/end_date helpers based on year/semester.
app/models/class_enrollment_request.rb Adds hold validation to block requests in held periods.
app/models/class_enrollment.rb Adds hold validation to block enrollments in held periods.
app/controllers/class_enrollment_requests_controller.rb Changes flash handling on set_status failure to show validation errors.
app/assets/stylesheets/custom/student_enrollment.scss Adds held-state styling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/controllers/class_enrollment_requests_controller.rb
Comment thread spec/factories/factory_enrollment.rb Outdated
"M#{number}"
end
admission_date { 5.days.ago.to_date }
admission_date { 10.days.ago.to_date }
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting the default admission_date to 10.days.ago is still date-dependent and can fall after YearSemester.current.semester_begin (e.g., during most of the first semester), which makes creating an EnrollmentHold for the current semester fail the existing before_admission_date validation. Consider using a deterministic default (e.g., relative to YearSemester.current.semester_begin) or a trait so tests opt into a recent admission date explicitly.

Suggested change
admission_date { 10.days.ago.to_date }
admission_date { YearSemester.current.semester_begin - 1.day }

Copilot uses AI. Check for mistakes.
Comment on lines +164 to +165
@destroy_later << cer = FactoryBot.create(:enrollment_request, enrollment: e)
class_enrollment_request.enrollment_request = cer
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this spec, cer is used as a variable name for an EnrollmentRequest, but elsewhere cer commonly reads as ClassEnrollmentRequest. Renaming the local to enrollment_request (or similar) would reduce confusion when reading failures.

Suggested change
@destroy_later << cer = FactoryBot.create(:enrollment_request, enrollment: e)
class_enrollment_request.enrollment_request = cer
@destroy_later << enrollment_request = FactoryBot.create(:enrollment_request, enrollment: e)
class_enrollment_request.enrollment_request = enrollment_request

Copilot uses AI. Check for mistakes.
Comment on lines +68 to +77
def invalidate_enrollment_requests
enrollment_requests = EnrollmentRequest.where(enrollment: self.enrollment)
enrollment_requests.each do |enrollment_request|
if self.year == enrollment_request.year && self.semester == enrollment_request.semester
enrollment_request.class_enrollment_requests.each do |class_enrollment_request|
class_enrollment_request.set_status!(ClassEnrollmentRequest::INVALID)
end
end
end
end
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invalidate_enrollment_requests runs on every create/update and will invalidate requests even when the hold is being deactivated (active toggled to false) or when the updated record should not apply. It should likely be gated on active == true (and/or on relevant changes like year/semester/number_of_semesters) to avoid unintended invalidations.

Copilot uses AI. Check for mistakes.
Comment on lines +79 to +86
def verify_class_enrollments
class_enrollments = ClassEnrollment.where(enrollment: self.enrollment)
class_enrollments.each do |class_enrollment|
course_class = class_enrollment.course_class
unless course_class.end_date < self.start_date || course_class.start_date > self.end_date
errors.add(:base, :class_enrollments_exist)
end
end
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verify_class_enrollments also ignores the active flag. As written, it will prevent saving an inactive hold even though inactive holds are treated elsewhere as not in effect; consider skipping this validation when active is false (or clarify intended behavior).

Copilot uses AI. Check for mistakes.
Comment thread app/views/student_enrollment/_show_enroll.html.erb
Comment thread spec/models/enrollment_hold_spec.rb
Comment thread app/models/enrollment_hold.rb Outdated
Comment on lines +89 to +96
def self.hold_in_date(enrollment, course_start, course_end)
enrollment_holds = EnrollmentHold.where(enrollment: enrollment)
unless enrollment_holds.empty?
enrollment_holds.each do |hold|
return true unless course_end < hold.start_date || course_start > hold.end_date
end
end
false
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hold_in_date currently checks all holds for the enrollment, including active = false. The rest of the codebase treats inactive holds as not applicable (e.g., enrollment hold search filters by active = true), so this will incorrectly block enrollments/requests when a hold is inactive. Filter to active holds (or explicitly decide how inactive holds should behave).

Copilot uses AI. Check for mistakes.
Comment thread app/models/enrollment_hold.rb Outdated
Comment on lines +69 to +74
enrollment_requests = EnrollmentRequest.where(enrollment: self.enrollment)
enrollment_requests.each do |enrollment_request|
if self.year == enrollment_request.year && self.semester == enrollment_request.semester
enrollment_request.class_enrollment_requests.each do |class_enrollment_request|
class_enrollment_request.set_status!(ClassEnrollmentRequest::INVALID)
end
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invalidate_enrollment_requests does an N+1 iteration (EnrollmentRequest.where(...).each then class_enrollment_requests.each). This can be reduced to a single query by scoping to the relevant year/semester in SQL and eager-loading (or updating) the associated class_enrollment_requests, which will matter if an enrollment has many requests.

Suggested change
enrollment_requests = EnrollmentRequest.where(enrollment: self.enrollment)
enrollment_requests.each do |enrollment_request|
if self.year == enrollment_request.year && self.semester == enrollment_request.semester
enrollment_request.class_enrollment_requests.each do |class_enrollment_request|
class_enrollment_request.set_status!(ClassEnrollmentRequest::INVALID)
end
enrollment_requests = EnrollmentRequest.where(
enrollment: enrollment,
year: year,
semester: semester
).includes(:class_enrollment_requests)
enrollment_requests.each do |enrollment_request|
enrollment_request.class_enrollment_requests.each do |class_enrollment_request|
class_enrollment_request.set_status!(ClassEnrollmentRequest::INVALID)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants